drm/exynos: stop mixer before gating clocks during poweroff
[deliverable/linux.git] / drivers / gpu / drm / exynos / exynos_mixer.c
index 483d7c08384a15d9ff280e314b432c1057d29ff4..d35950121fc42b2fd10b7b70d991ce6d61a9130d 100644 (file)
@@ -377,6 +377,20 @@ static void mixer_run(struct mixer_context *ctx)
        mixer_regs_dump(ctx);
 }
 
+static void mixer_stop(struct mixer_context *ctx)
+{
+       struct mixer_resources *res = &ctx->mixer_res;
+       int timeout = 20;
+
+       mixer_reg_writemask(res, MXR_STATUS, 0, MXR_STATUS_REG_RUN);
+
+       while (!(mixer_reg_read(res, MXR_STATUS) & MXR_STATUS_REG_IDLE) &&
+                       --timeout)
+               usleep_range(10000, 12000);
+
+       mixer_regs_dump(ctx);
+}
+
 static void vp_video_buffer(struct mixer_context *ctx, int win)
 {
        struct mixer_resources *res = &ctx->mixer_res;
@@ -1061,7 +1075,7 @@ static void mixer_poweron(struct exynos_drm_manager *mgr)
                mutex_unlock(&ctx->mixer_mutex);
                return;
        }
-       ctx->powered = true;
+
        mutex_unlock(&ctx->mixer_mutex);
 
        pm_runtime_get_sync(ctx->dev);
@@ -1072,6 +1086,10 @@ static void mixer_poweron(struct exynos_drm_manager *mgr)
                clk_prepare_enable(res->sclk_mixer);
        }
 
+       mutex_lock(&ctx->mixer_mutex);
+       ctx->powered = true;
+       mutex_unlock(&ctx->mixer_mutex);
+
        mixer_reg_write(res, MXR_INT_EN, ctx->int_en);
        mixer_win_reset(ctx);
 
@@ -1084,14 +1102,21 @@ static void mixer_poweroff(struct exynos_drm_manager *mgr)
        struct mixer_resources *res = &ctx->mixer_res;
 
        mutex_lock(&ctx->mixer_mutex);
-       if (!ctx->powered)
-               goto out;
+       if (!ctx->powered) {
+               mutex_unlock(&ctx->mixer_mutex);
+               return;
+       }
        mutex_unlock(&ctx->mixer_mutex);
 
+       mixer_stop(ctx);
        mixer_window_suspend(mgr);
 
        ctx->int_en = mixer_reg_read(res, MXR_INT_EN);
 
+       mutex_lock(&ctx->mixer_mutex);
+       ctx->powered = false;
+       mutex_unlock(&ctx->mixer_mutex);
+
        clk_disable_unprepare(res->mixer);
        if (ctx->vp_enabled) {
                clk_disable_unprepare(res->vp);
@@ -1099,12 +1124,6 @@ static void mixer_poweroff(struct exynos_drm_manager *mgr)
        }
 
        pm_runtime_put_sync(ctx->dev);
-
-       mutex_lock(&ctx->mixer_mutex);
-       ctx->powered = false;
-
-out:
-       mutex_unlock(&ctx->mixer_mutex);
 }
 
 static void mixer_dpms(struct exynos_drm_manager *mgr, int mode)
@@ -1273,12 +1292,25 @@ static const struct component_ops mixer_component_ops = {
 
 static int mixer_probe(struct platform_device *pdev)
 {
-       return exynos_drm_component_add(&pdev->dev, &mixer_component_ops);
+       int ret;
+
+       ret = exynos_drm_component_add(&pdev->dev, EXYNOS_DEVICE_TYPE_CRTC,
+                                       mixer_manager.type);
+       if (ret)
+               return ret;
+
+       ret = component_add(&pdev->dev, &mixer_component_ops);
+       if (ret)
+               exynos_drm_component_del(&pdev->dev, EXYNOS_DEVICE_TYPE_CRTC);
+
+       return ret;
 }
 
 static int mixer_remove(struct platform_device *pdev)
 {
-       exynos_drm_component_del(&pdev->dev, &mixer_component_ops);
+       component_del(&pdev->dev, &mixer_component_ops);
+       exynos_drm_component_del(&pdev->dev, EXYNOS_DEVICE_TYPE_CRTC);
+
        return 0;
 }
 
This page took 0.029152 seconds and 5 git commands to generate.