drm/exynos: add pm_runtime to Mixer
authorGustavo Padovan <gustavo.padovan@collabora.co.uk>
Fri, 4 Sep 2015 20:15:46 +0000 (17:15 -0300)
committerInki Dae <daeinki@gmail.com>
Sun, 13 Dec 2015 13:22:45 +0000 (22:22 +0900)
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 v2:
- revive MXR_BIT_POWERED flag to keep current dpms mode.

Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
Signed-off-by: Inki Dae <inki.dae@samsung.com>
drivers/gpu/drm/exynos/exynos_mixer.c

index d09f8f9a893952e826233286043c59ceaa3ad66b..47777be1a754c15c484fc4f17395a8b1c455f68e 100644 (file)
@@ -1020,43 +1020,12 @@ static void mixer_enable(struct exynos_drm_crtc *crtc)
 {
        struct mixer_context *ctx = crtc->ctx;
        struct mixer_resources *res = &ctx->mixer_res;
-       int ret;
 
        if (test_bit(MXR_BIT_POWERED, &ctx->flags))
                return;
 
        pm_runtime_get_sync(ctx->dev);
 
-       ret = clk_prepare_enable(res->mixer);
-       if (ret < 0) {
-               DRM_ERROR("Failed to prepare_enable the mixer clk [%d]\n", ret);
-               return;
-       }
-       ret = clk_prepare_enable(res->hdmi);
-       if (ret < 0) {
-               DRM_ERROR("Failed to prepare_enable the hdmi clk [%d]\n", ret);
-               return;
-       }
-       if (ctx->vp_enabled) {
-               ret = clk_prepare_enable(res->vp);
-               if (ret < 0) {
-                       DRM_ERROR("Failed to prepare_enable the vp clk [%d]\n",
-                                 ret);
-                       return;
-               }
-               if (ctx->has_sclk) {
-                       ret = clk_prepare_enable(res->sclk_mixer);
-                       if (ret < 0) {
-                               DRM_ERROR("Failed to prepare_enable the " \
-                                          "sclk_mixer clk [%d]\n",
-                                         ret);
-                               return;
-                       }
-               }
-       }
-
-       set_bit(MXR_BIT_POWERED, &ctx->flags);
-
        mixer_reg_writemask(res, MXR_STATUS, ~0, MXR_STATUS_SOFT_RESET);
 
        if (test_bit(MXR_BIT_VSYNC, &ctx->flags)) {
@@ -1064,12 +1033,13 @@ static void mixer_enable(struct exynos_drm_crtc *crtc)
                mixer_reg_writemask(res, MXR_INT_EN, ~0, MXR_INT_EN_VSYNC);
        }
        mixer_win_reset(ctx);
+
+       set_bit(MXR_BIT_POWERED, &ctx->flags);
 }
 
 static void mixer_disable(struct exynos_drm_crtc *crtc)
 {
        struct mixer_context *ctx = crtc->ctx;
-       struct mixer_resources *res = &ctx->mixer_res;
        int i;
 
        if (!test_bit(MXR_BIT_POWERED, &ctx->flags))
@@ -1081,17 +1051,9 @@ static void mixer_disable(struct exynos_drm_crtc *crtc)
        for (i = 0; i < MIXER_WIN_NR; i++)
                mixer_disable_plane(crtc, &ctx->planes[i]);
 
-       clear_bit(MXR_BIT_POWERED, &ctx->flags);
+       pm_runtime_put(ctx->dev);
 
-       clk_disable_unprepare(res->hdmi);
-       clk_disable_unprepare(res->mixer);
-       if (ctx->vp_enabled) {
-               clk_disable_unprepare(res->vp);
-               if (ctx->has_sclk)
-                       clk_disable_unprepare(res->sclk_mixer);
-       }
-
-       pm_runtime_put_sync(ctx->dev);
+       clear_bit(MXR_BIT_POWERED, &ctx->flags);
 }
 
 /* Only valid for Mixer version 16.0.33.0 */
@@ -1293,10 +1255,70 @@ static int mixer_remove(struct platform_device *pdev)
        return 0;
 }
 
+#ifdef CONFIG_PM_SLEEP
+static int exynos_mixer_suspend(struct device *dev)
+{
+       struct mixer_context *ctx = dev_get_drvdata(dev);
+       struct mixer_resources *res = &ctx->mixer_res;
+
+       clk_disable_unprepare(res->hdmi);
+       clk_disable_unprepare(res->mixer);
+       if (ctx->vp_enabled) {
+               clk_disable_unprepare(res->vp);
+               if (ctx->has_sclk)
+                       clk_disable_unprepare(res->sclk_mixer);
+       }
+
+       return 0;
+}
+
+static int exynos_mixer_resume(struct device *dev)
+{
+       struct mixer_context *ctx = dev_get_drvdata(dev);
+       struct mixer_resources *res = &ctx->mixer_res;
+       int ret;
+
+       ret = clk_prepare_enable(res->mixer);
+       if (ret < 0) {
+               DRM_ERROR("Failed to prepare_enable the mixer clk [%d]\n", ret);
+               return ret;
+       }
+       ret = clk_prepare_enable(res->hdmi);
+       if (ret < 0) {
+               DRM_ERROR("Failed to prepare_enable the hdmi clk [%d]\n", ret);
+               return ret;
+       }
+       if (ctx->vp_enabled) {
+               ret = clk_prepare_enable(res->vp);
+               if (ret < 0) {
+                       DRM_ERROR("Failed to prepare_enable the vp clk [%d]\n",
+                                 ret);
+                       return ret;
+               }
+               if (ctx->has_sclk) {
+                       ret = clk_prepare_enable(res->sclk_mixer);
+                       if (ret < 0) {
+                               DRM_ERROR("Failed to prepare_enable the " \
+                                          "sclk_mixer clk [%d]\n",
+                                         ret);
+                               return ret;
+                       }
+               }
+       }
+
+       return 0;
+}
+#endif
+
+static const struct dev_pm_ops exynos_mixer_pm_ops = {
+       SET_RUNTIME_PM_OPS(exynos_mixer_suspend, exynos_mixer_resume, NULL)
+};
+
 struct platform_driver mixer_driver = {
        .driver = {
                .name = "exynos-mixer",
                .owner = THIS_MODULE,
+               .pm = &exynos_mixer_pm_ops,
                .of_match_table = mixer_match_types,
        },
        .probe = mixer_probe,