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:
Dhaval Patel
2018-05-04 10:08:05 -07:00
parent a702cd897f
commit a74d2cf7fa
26 changed files with 324 additions and 958 deletions

View File

@@ -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,
},
};