diff options
Diffstat (limited to 'drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c')
-rw-r--r-- | drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c | 54 |
1 files changed, 43 insertions, 11 deletions
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c index 1c603aef3c59..f7c0698fec40 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c @@ -30,11 +30,10 @@ static const char *iommu_ports[] = { static int mdp5_hw_init(struct msm_kms *kms) { struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(kms)); - struct platform_device *pdev = mdp5_kms->pdev; + struct device *dev = &mdp5_kms->pdev->dev; unsigned long flags; - pm_runtime_get_sync(&pdev->dev); - mdp5_enable(mdp5_kms); + pm_runtime_get_sync(dev); /* Magic unknown register writes: * @@ -66,8 +65,7 @@ static int mdp5_hw_init(struct msm_kms *kms) mdp5_ctlm_hw_reset(mdp5_kms->ctlm); - mdp5_disable(mdp5_kms); - pm_runtime_put_sync(&pdev->dev); + pm_runtime_put_sync(dev); return 0; } @@ -111,8 +109,9 @@ static void mdp5_swap_state(struct msm_kms *kms, struct drm_atomic_state *state) static void mdp5_prepare_commit(struct msm_kms *kms, struct drm_atomic_state *state) { struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(kms)); + struct device *dev = &mdp5_kms->pdev->dev; - mdp5_enable(mdp5_kms); + pm_runtime_get_sync(dev); if (mdp5_kms->smp) mdp5_smp_prepare_commit(mdp5_kms->smp, &mdp5_kms->state->smp); @@ -121,11 +120,12 @@ static void mdp5_prepare_commit(struct msm_kms *kms, struct drm_atomic_state *st static void mdp5_complete_commit(struct msm_kms *kms, struct drm_atomic_state *state) { struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(kms)); + struct device *dev = &mdp5_kms->pdev->dev; if (mdp5_kms->smp) mdp5_smp_complete_commit(mdp5_kms->smp, &mdp5_kms->state->smp); - mdp5_disable(mdp5_kms); + pm_runtime_put_autosuspend(dev); } static void mdp5_wait_for_crtc_commit_done(struct msm_kms *kms, @@ -249,6 +249,9 @@ int mdp5_disable(struct mdp5_kms *mdp5_kms) { DBG(""); + mdp5_kms->enable_count--; + WARN_ON(mdp5_kms->enable_count < 0); + clk_disable_unprepare(mdp5_kms->ahb_clk); clk_disable_unprepare(mdp5_kms->axi_clk); clk_disable_unprepare(mdp5_kms->core_clk); @@ -262,6 +265,8 @@ int mdp5_enable(struct mdp5_kms *mdp5_kms) { DBG(""); + mdp5_kms->enable_count++; + clk_prepare_enable(mdp5_kms->ahb_clk); clk_prepare_enable(mdp5_kms->axi_clk); clk_prepare_enable(mdp5_kms->core_clk); @@ -486,11 +491,12 @@ fail: static void read_mdp_hw_revision(struct mdp5_kms *mdp5_kms, u32 *major, u32 *minor) { + struct device *dev = &mdp5_kms->pdev->dev; u32 version; - mdp5_enable(mdp5_kms); + pm_runtime_get_sync(dev); version = mdp5_read(mdp5_kms, REG_MDP5_HW_VERSION); - mdp5_disable(mdp5_kms); + pm_runtime_put_autosuspend(dev); *major = FIELD(version, MDP5_HW_VERSION_MAJOR); *minor = FIELD(version, MDP5_HW_VERSION_MINOR); @@ -643,7 +649,7 @@ struct msm_kms *mdp5_kms_init(struct drm_device *dev) * have left things on, in which case we'll start getting faults if * we don't disable): */ - mdp5_enable(mdp5_kms); + pm_runtime_get_sync(&pdev->dev); for (i = 0; i < MDP5_INTF_NUM_MAX; i++) { if (mdp5_cfg_intf_is_virtual(config->hw->intf.connect[i]) || !config->hw->intf.base[i]) @@ -652,7 +658,6 @@ struct msm_kms *mdp5_kms_init(struct drm_device *dev) mdp5_write(mdp5_kms, REG_MDP5_INTF_FRAME_LINE_COUNT_EN(i), 0x3); } - mdp5_disable(mdp5_kms); mdelay(16); if (config->platform.iommu) { @@ -678,6 +683,8 @@ struct msm_kms *mdp5_kms_init(struct drm_device *dev) aspace = NULL;; } + pm_runtime_put_autosuspend(&pdev->dev); + ret = modeset_init(mdp5_kms); if (ret) { dev_err(&pdev->dev, "modeset_init failed: %d\n", ret); @@ -1005,6 +1012,30 @@ static int mdp5_dev_remove(struct platform_device *pdev) return 0; } +static __maybe_unused int mdp5_runtime_suspend(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct mdp5_kms *mdp5_kms = platform_get_drvdata(pdev); + + DBG(""); + + return mdp5_disable(mdp5_kms); +} + +static __maybe_unused int mdp5_runtime_resume(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct mdp5_kms *mdp5_kms = platform_get_drvdata(pdev); + + DBG(""); + + return mdp5_enable(mdp5_kms); +} + +static const struct dev_pm_ops mdp5_pm_ops = { + SET_RUNTIME_PM_OPS(mdp5_runtime_suspend, mdp5_runtime_resume, NULL) +}; + static const struct of_device_id mdp5_dt_match[] = { { .compatible = "qcom,mdp5", }, /* to support downstream DT files */ @@ -1019,6 +1050,7 @@ static struct platform_driver mdp5_driver = { .driver = { .name = "msm_mdp", .of_match_table = mdp5_dt_match, + .pm = &mdp5_pm_ops, }, }; |