disp: msm: add runtime_pm ops support in drm driver
Add runtime_pm ops support in drm driver instead of direct sde_power_resource_enable/disable call. It allows drm driver to use runtime pm refcount logic to track the resources instead of custom implementation. The change also removes the NRT_CLIENT support from sde_power_handle code to simplify it further. Change-Id: Ib14692dca5876703d0a230da2512d731b69b8ebb Signed-off-by: Dhaval Patel <pdhaval@codeaurora.org>
This commit is contained in:
162
msm/sde_rsc.c
162
msm/sde_rsc.c
@@ -15,6 +15,7 @@
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
|
||||
#include <soc/qcom/rpmh.h>
|
||||
#include <drm/drmP.h>
|
||||
@@ -277,64 +278,6 @@ enum sde_rsc_state get_sde_rsc_current_state(int rsc_index)
|
||||
}
|
||||
EXPORT_SYMBOL(get_sde_rsc_current_state);
|
||||
|
||||
static int sde_rsc_clk_enable(struct sde_power_handle *phandle,
|
||||
struct sde_power_client *pclient, bool enable)
|
||||
{
|
||||
int rc = 0;
|
||||
struct dss_module_power *mp;
|
||||
|
||||
if (!phandle || !pclient) {
|
||||
pr_err("invalid input argument\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
mp = &phandle->mp;
|
||||
|
||||
if (enable)
|
||||
pclient->refcount++;
|
||||
else if (pclient->refcount)
|
||||
pclient->refcount--;
|
||||
|
||||
if (pclient->refcount)
|
||||
pclient->usecase_ndx = VOTE_INDEX_LOW;
|
||||
else
|
||||
pclient->usecase_ndx = VOTE_INDEX_DISABLE;
|
||||
|
||||
if (phandle->current_usecase_ndx == pclient->usecase_ndx)
|
||||
goto end;
|
||||
|
||||
if (enable) {
|
||||
rc = msm_dss_enable_vreg(mp->vreg_config, mp->num_vreg,
|
||||
enable);
|
||||
if (rc) {
|
||||
pr_err("failed to enable vregs rc=%d\n", rc);
|
||||
goto end;
|
||||
}
|
||||
|
||||
rc = msm_dss_enable_clk(mp->clk_config, mp->num_clk, enable);
|
||||
if (rc) {
|
||||
pr_err("clock enable failed rc:%d\n", rc);
|
||||
msm_dss_enable_vreg(mp->vreg_config, mp->num_vreg,
|
||||
!enable);
|
||||
goto end;
|
||||
}
|
||||
} else {
|
||||
msm_dss_enable_clk(mp->clk_config, mp->num_clk, enable);
|
||||
|
||||
rc = msm_dss_enable_vreg(mp->vreg_config, mp->num_vreg,
|
||||
enable);
|
||||
if (rc) {
|
||||
pr_err("failed to disable vregs rc=%d\n", rc);
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
phandle->current_usecase_ndx = pclient->usecase_ndx;
|
||||
|
||||
end:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static u32 sde_rsc_timer_calculate(struct sde_rsc_priv *rsc,
|
||||
struct sde_rsc_cmd_config *cmd_config, enum sde_rsc_state state)
|
||||
{
|
||||
@@ -484,7 +427,7 @@ static int sde_rsc_switch_to_cmd(struct sde_rsc_priv *rsc,
|
||||
*/
|
||||
if (rsc->current_state == SDE_RSC_CMD_STATE) {
|
||||
rc = 0;
|
||||
if (config && rsc->version < SDE_RSC_REV_3)
|
||||
if (config)
|
||||
goto vsync_wait;
|
||||
else
|
||||
goto end;
|
||||
@@ -504,8 +447,7 @@ static int sde_rsc_switch_to_cmd(struct sde_rsc_priv *rsc,
|
||||
|
||||
vsync_wait:
|
||||
/* indicate wait for vsync for vid to cmd state switch & cfg update */
|
||||
if (!rc && (rsc->version < SDE_RSC_REV_3) &&
|
||||
(rsc->current_state == SDE_RSC_VID_STATE ||
|
||||
if (!rc && (rsc->current_state == SDE_RSC_VID_STATE ||
|
||||
rsc->current_state == SDE_RSC_CMD_STATE)) {
|
||||
/* clear VSYNC timestamp for indication when update completes */
|
||||
if (rsc->hw_ops.hw_vsync)
|
||||
@@ -623,7 +565,7 @@ static int sde_rsc_switch_to_vid(struct sde_rsc_priv *rsc,
|
||||
*/
|
||||
if (rsc->current_state == SDE_RSC_VID_STATE) {
|
||||
rc = 0;
|
||||
if (config && rsc->version < SDE_RSC_REV_3)
|
||||
if (config)
|
||||
goto vsync_wait;
|
||||
else
|
||||
goto end;
|
||||
@@ -644,8 +586,7 @@ static int sde_rsc_switch_to_vid(struct sde_rsc_priv *rsc,
|
||||
|
||||
vsync_wait:
|
||||
/* indicate wait for vsync for vid to cmd state switch & cfg update */
|
||||
if (!rc && (rsc->version < SDE_RSC_REV_3) &&
|
||||
(rsc->current_state == SDE_RSC_VID_STATE ||
|
||||
if (!rc && (rsc->current_state == SDE_RSC_VID_STATE ||
|
||||
rsc->current_state == SDE_RSC_CMD_STATE)) {
|
||||
/* clear VSYNC timestamp for indication when update completes */
|
||||
if (rsc->hw_ops.hw_vsync)
|
||||
@@ -879,7 +820,7 @@ int sde_rsc_client_state_update(struct sde_rsc_client *caller_client,
|
||||
caller_client->name, state);
|
||||
|
||||
if (rsc->current_state == SDE_RSC_IDLE_STATE)
|
||||
sde_rsc_clk_enable(&rsc->phandle, rsc->pclient, true);
|
||||
pm_runtime_get_sync(rsc->dev);
|
||||
|
||||
switch (state) {
|
||||
case SDE_RSC_IDLE_STATE:
|
||||
@@ -936,7 +877,7 @@ int sde_rsc_client_state_update(struct sde_rsc_client *caller_client,
|
||||
|
||||
clk_disable:
|
||||
if (rsc->current_state == SDE_RSC_IDLE_STATE)
|
||||
sde_rsc_clk_enable(&rsc->phandle, rsc->pclient, false);
|
||||
pm_runtime_put_sync(rsc->dev);
|
||||
end:
|
||||
mutex_unlock(&rsc->client_lock);
|
||||
return rc;
|
||||
@@ -1013,8 +954,8 @@ int sde_rsc_client_trigger_vote(struct sde_rsc_client *caller_client,
|
||||
rsc->bw_config.ib_vote[i] = rsc->bw_config.new_ib_vote[i];
|
||||
}
|
||||
|
||||
rc = sde_rsc_clk_enable(&rsc->phandle, rsc->pclient, true);
|
||||
if (rc)
|
||||
rc = pm_runtime_get_sync(rsc->dev);
|
||||
if (rc < 0)
|
||||
goto clk_enable_fail;
|
||||
|
||||
if (delta_vote) {
|
||||
@@ -1031,8 +972,6 @@ int sde_rsc_client_trigger_vote(struct sde_rsc_client *caller_client,
|
||||
rpmh_invalidate(rsc->rpmh_dev);
|
||||
for (i = 0; i < SDE_POWER_HANDLE_DBUS_ID_MAX; i++)
|
||||
sde_power_data_bus_set_quota(&rsc->phandle,
|
||||
rsc->pclient,
|
||||
SDE_POWER_HANDLE_DATA_BUS_CLIENT_RT,
|
||||
i, rsc->bw_config.ab_vote[i],
|
||||
rsc->bw_config.ib_vote[i]);
|
||||
rpmh_flush(rsc->rpmh_dev);
|
||||
@@ -1046,7 +985,7 @@ int sde_rsc_client_trigger_vote(struct sde_rsc_client *caller_client,
|
||||
rsc->hw_ops.tcs_use_ok(rsc);
|
||||
|
||||
end:
|
||||
sde_rsc_clk_enable(&rsc->phandle, rsc->pclient, false);
|
||||
pm_runtime_put_sync(rsc->dev);
|
||||
clk_enable_fail:
|
||||
mutex_unlock(&rsc->client_lock);
|
||||
|
||||
@@ -1353,8 +1292,7 @@ static void sde_rsc_deinit(struct platform_device *pdev,
|
||||
if (!rsc)
|
||||
return;
|
||||
|
||||
if (rsc->pclient)
|
||||
sde_rsc_clk_enable(&rsc->phandle, rsc->pclient, false);
|
||||
pm_runtime_put_sync(rsc->dev);
|
||||
if (rsc->sw_fs_enabled)
|
||||
regulator_disable(rsc->fs);
|
||||
if (rsc->fs)
|
||||
@@ -1363,14 +1301,64 @@ static void sde_rsc_deinit(struct platform_device *pdev,
|
||||
msm_dss_iounmap(&rsc->wrapper_io);
|
||||
if (rsc->drv_io.base)
|
||||
msm_dss_iounmap(&rsc->drv_io);
|
||||
if (rsc->pclient)
|
||||
sde_power_client_destroy(&rsc->phandle, rsc->pclient);
|
||||
|
||||
sde_power_resource_deinit(pdev, &rsc->phandle);
|
||||
debugfs_remove_recursive(rsc->debugfs_root);
|
||||
kfree(rsc);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int sde_rsc_runtime_suspend(struct device *dev)
|
||||
{
|
||||
struct sde_rsc_priv *rsc = dev_get_drvdata(dev);
|
||||
struct dss_module_power *mp;
|
||||
|
||||
if (!rsc) {
|
||||
pr_err("invalid drv data\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
mp = &rsc->phandle.mp;
|
||||
msm_dss_enable_clk(mp->clk_config, mp->num_clk, false);
|
||||
msm_dss_enable_vreg(mp->vreg_config, mp->num_vreg, false);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sde_rsc_runtime_resume(struct device *dev)
|
||||
{
|
||||
struct sde_rsc_priv *rsc = dev_get_drvdata(dev);
|
||||
struct dss_module_power *mp;
|
||||
int rc = 0;
|
||||
|
||||
if (!rsc) {
|
||||
pr_err("invalid drv data\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
mp = &rsc->phandle.mp;
|
||||
rc = msm_dss_enable_vreg(mp->vreg_config, mp->num_vreg, true);
|
||||
if (rc) {
|
||||
pr_err("failed to enable vregs rc=%d\n", rc);
|
||||
goto end;
|
||||
}
|
||||
|
||||
rc = msm_dss_enable_clk(mp->clk_config, mp->num_clk, true);
|
||||
if (rc) {
|
||||
pr_err("clock enable failed rc:%d\n", rc);
|
||||
msm_dss_enable_vreg(mp->vreg_config, mp->num_vreg, false);
|
||||
}
|
||||
|
||||
end:
|
||||
return rc;
|
||||
}
|
||||
#endif
|
||||
|
||||
static const struct dev_pm_ops sde_rsc_pm_ops = {
|
||||
SET_RUNTIME_PM_OPS(sde_rsc_runtime_suspend,
|
||||
sde_rsc_runtime_resume, NULL)
|
||||
};
|
||||
|
||||
/**
|
||||
* sde_rsc_bind - bind rsc device with controlling device
|
||||
* @dev: Pointer to base of platform device
|
||||
@@ -1464,6 +1452,7 @@ static int sde_rsc_probe(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, rsc);
|
||||
rsc->dev = &pdev->dev;
|
||||
of_property_read_u32(pdev->dev.of_node, "qcom,sde-rsc-version",
|
||||
&rsc->version);
|
||||
|
||||
@@ -1492,20 +1481,6 @@ static int sde_rsc_probe(struct platform_device *pdev)
|
||||
goto sde_rsc_fail;
|
||||
}
|
||||
|
||||
rsc->pclient = sde_power_client_create(&rsc->phandle, "rsc");
|
||||
if (IS_ERR_OR_NULL(rsc->pclient)) {
|
||||
ret = PTR_ERR(rsc->pclient);
|
||||
rsc->pclient = NULL;
|
||||
pr_err("sde rsc:power client create failed ret:%d\n", ret);
|
||||
goto sde_rsc_fail;
|
||||
}
|
||||
|
||||
/**
|
||||
* sde rsc should always vote through enable path, sleep vote is
|
||||
* set to "0" by default.
|
||||
*/
|
||||
sde_power_data_bus_state_update(&rsc->phandle, true);
|
||||
|
||||
rsc->rpmh_dev = rpmh_dev[SDE_RSC_INDEX + counter];
|
||||
if (IS_ERR_OR_NULL(rsc->rpmh_dev)) {
|
||||
ret = !rsc->rpmh_dev ? -EINVAL : PTR_ERR(rsc->rpmh_dev);
|
||||
@@ -1550,15 +1525,17 @@ static int sde_rsc_probe(struct platform_device *pdev)
|
||||
|
||||
rsc->sw_fs_enabled = true;
|
||||
|
||||
if (sde_rsc_clk_enable(&rsc->phandle, rsc->pclient, true)) {
|
||||
pr_err("failed to enable sde rsc power resources\n");
|
||||
pm_runtime_enable(rsc->dev);
|
||||
ret = pm_runtime_get_sync(rsc->dev);
|
||||
if (ret < 0) {
|
||||
pr_err("failed to enable sde rsc power resources rc:%d\n", ret);
|
||||
goto sde_rsc_fail;
|
||||
}
|
||||
|
||||
if (sde_rsc_timer_calculate(rsc, NULL, SDE_RSC_IDLE_STATE))
|
||||
goto sde_rsc_fail;
|
||||
|
||||
sde_rsc_clk_enable(&rsc->phandle, rsc->pclient, false);
|
||||
pm_runtime_put_sync(rsc->dev);
|
||||
|
||||
INIT_LIST_HEAD(&rsc->client_list);
|
||||
INIT_LIST_HEAD(&rsc->event_list);
|
||||
@@ -1636,6 +1613,7 @@ static struct platform_driver sde_rsc_platform_driver = {
|
||||
.name = "sde_rsc",
|
||||
.of_match_table = dt_match,
|
||||
.suppress_bind_attrs = true,
|
||||
.pm = &sde_rsc_pm_ops,
|
||||
},
|
||||
};
|
||||
|
||||
|
Reference in New Issue
Block a user