diff options
author | Gustavo Padovan <gustavo.padovan@collabora.co.uk> | 2015-11-02 14:58:02 +0300 |
---|---|---|
committer | Inki Dae <daeinki@gmail.com> | 2015-12-13 16:22:47 +0300 |
commit | 681c801eb9f322873c67996720a138d534cb8ff9 (patch) | |
tree | 8c7ef0aa0042af1120686d9e06ca72bf5340cda1 /drivers/gpu/drm | |
parent | ebf3fd403b79ba6561bd1a4bb5a7cacc99da08e5 (diff) | |
download | linux-681c801eb9f322873c67996720a138d534cb8ff9.tar.xz |
drm/exynos: add pm_runtime to DECON 7
Let pm_runtime handle the enabling/disabling of the device with
proper refcnt instead of rely on specific flags to track the enabled
state.
Changelog v3:
- revive suspended to keep current dpms mode
Changelog v2:
- Modify CONFIG_PM_SLEEP -> CONFIG_PM
Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
Signed-off-by: Inki Dae <inki.dae@samsung.com>
Diffstat (limited to 'drivers/gpu/drm')
-rw-r--r-- | drivers/gpu/drm/exynos/exynos7_drm_decon.c | 93 |
1 files changed, 55 insertions, 38 deletions
diff --git a/drivers/gpu/drm/exynos/exynos7_drm_decon.c b/drivers/gpu/drm/exynos/exynos7_drm_decon.c index ead2b16e237d..38d7762ebdcb 100644 --- a/drivers/gpu/drm/exynos/exynos7_drm_decon.c +++ b/drivers/gpu/drm/exynos/exynos7_drm_decon.c @@ -119,13 +119,8 @@ static void decon_clear_channels(struct exynos_drm_crtc *crtc) } /* Wait for vsync, as disable channel takes effect at next vsync */ - if (ch_enabled) { - unsigned int state = ctx->suspended; - - ctx->suspended = 0; + if (ch_enabled) decon_wait_for_vblank(ctx->crtc); - ctx->suspended = state; - } } static int decon_ctx_initialize(struct decon_context *ctx, @@ -555,39 +550,12 @@ static void decon_init(struct decon_context *ctx) static void decon_enable(struct exynos_drm_crtc *crtc) { struct decon_context *ctx = crtc->ctx; - int ret; if (!ctx->suspended) return; - ctx->suspended = false; - pm_runtime_get_sync(ctx->dev); - ret = clk_prepare_enable(ctx->pclk); - if (ret < 0) { - DRM_ERROR("Failed to prepare_enable the pclk [%d]\n", ret); - return; - } - - ret = clk_prepare_enable(ctx->aclk); - if (ret < 0) { - DRM_ERROR("Failed to prepare_enable the aclk [%d]\n", ret); - return; - } - - ret = clk_prepare_enable(ctx->eclk); - if (ret < 0) { - DRM_ERROR("Failed to prepare_enable the eclk [%d]\n", ret); - return; - } - - ret = clk_prepare_enable(ctx->vclk); - if (ret < 0) { - DRM_ERROR("Failed to prepare_enable the vclk [%d]\n", ret); - return; - } - decon_init(ctx); /* if vblank was enabled status, enable it again. */ @@ -595,6 +563,8 @@ static void decon_enable(struct exynos_drm_crtc *crtc) decon_enable_vblank(ctx->crtc); decon_commit(ctx->crtc); + + ctx->suspended = false; } static void decon_disable(struct exynos_drm_crtc *crtc) @@ -613,11 +583,6 @@ static void decon_disable(struct exynos_drm_crtc *crtc) for (i = 0; i < WINDOWS_NR; i++) decon_disable_plane(crtc, &ctx->planes[i]); - clk_disable_unprepare(ctx->vclk); - clk_disable_unprepare(ctx->eclk); - clk_disable_unprepare(ctx->aclk); - clk_disable_unprepare(ctx->pclk); - pm_runtime_put_sync(ctx->dev); ctx->suspended = true; @@ -843,11 +808,63 @@ static int decon_remove(struct platform_device *pdev) return 0; } +#ifdef CONFIG_PM +static int exynos7_decon_suspend(struct device *dev) +{ + struct decon_context *ctx = dev_get_drvdata(dev); + + clk_disable_unprepare(ctx->vclk); + clk_disable_unprepare(ctx->eclk); + clk_disable_unprepare(ctx->aclk); + clk_disable_unprepare(ctx->pclk); + + return 0; +} + +static int exynos7_decon_resume(struct device *dev) +{ + struct decon_context *ctx = dev_get_drvdata(dev); + int ret; + + ret = clk_prepare_enable(ctx->pclk); + if (ret < 0) { + DRM_ERROR("Failed to prepare_enable the pclk [%d]\n", ret); + return ret; + } + + ret = clk_prepare_enable(ctx->aclk); + if (ret < 0) { + DRM_ERROR("Failed to prepare_enable the aclk [%d]\n", ret); + return ret; + } + + ret = clk_prepare_enable(ctx->eclk); + if (ret < 0) { + DRM_ERROR("Failed to prepare_enable the eclk [%d]\n", ret); + return ret; + } + + ret = clk_prepare_enable(ctx->vclk); + if (ret < 0) { + DRM_ERROR("Failed to prepare_enable the vclk [%d]\n", ret); + return ret; + } + + return 0; +} +#endif + +static const struct dev_pm_ops exynos7_decon_pm_ops = { + SET_RUNTIME_PM_OPS(exynos7_decon_suspend, exynos7_decon_resume, + NULL) +}; + struct platform_driver decon_driver = { .probe = decon_probe, .remove = decon_remove, .driver = { .name = "exynos-decon", + .pm = &exynos7_decon_pm_ops, .of_match_table = decon_driver_dt_match, }, }; |