]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - drivers/gpu/drm/exynos/exynos_drm_fimd.c
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux...
[karo-tx-linux.git] / drivers / gpu / drm / exynos / exynos_drm_fimd.c
index 5d09e33fef8716084a169bee2afb63e429187b48..085b066a99934116963b0aa3a1fe6d4a136387c2 100644 (file)
@@ -104,6 +104,14 @@ static struct fimd_driver_data s3c64xx_fimd_driver_data = {
        .has_limited_fmt = 1,
 };
 
+static struct fimd_driver_data exynos3_fimd_driver_data = {
+       .timing_base = 0x20000,
+       .lcdblk_offset = 0x210,
+       .lcdblk_bypass_shift = 1,
+       .has_shadowcon = 1,
+       .has_vidoutcon = 1,
+};
+
 static struct fimd_driver_data exynos4_fimd_driver_data = {
        .timing_base = 0x0,
        .lcdblk_offset = 0x210,
@@ -168,6 +176,8 @@ struct fimd_context {
 static const struct of_device_id fimd_driver_dt_match[] = {
        { .compatible = "samsung,s3c6400-fimd",
          .data = &s3c64xx_fimd_driver_data },
+       { .compatible = "samsung,exynos3250-fimd",
+         .data = &exynos3_fimd_driver_data },
        { .compatible = "samsung,exynos4210-fimd",
          .data = &exynos4_fimd_driver_data },
        { .compatible = "samsung,exynos5250-fimd",
@@ -204,7 +214,6 @@ static void fimd_wait_for_vblank(struct exynos_drm_manager *mgr)
                DRM_DEBUG_KMS("vblank wait timed out.\n");
 }
 
-
 static void fimd_clear_channel(struct exynos_drm_manager *mgr)
 {
        struct fimd_context *ctx = mgr->ctx;
@@ -214,17 +223,31 @@ static void fimd_clear_channel(struct exynos_drm_manager *mgr)
 
        /* Check if any channel is enabled. */
        for (win = 0; win < WINDOWS_NR; win++) {
-               u32 val = readl(ctx->regs + SHADOWCON);
-               if (val & SHADOWCON_CHx_ENABLE(win)) {
-                       val &= ~SHADOWCON_CHx_ENABLE(win);
-                       writel(val, ctx->regs + SHADOWCON);
+               u32 val = readl(ctx->regs + WINCON(win));
+
+               if (val & WINCONx_ENWIN) {
+                       /* wincon */
+                       val &= ~WINCONx_ENWIN;
+                       writel(val, ctx->regs + WINCON(win));
+
+                       /* unprotect windows */
+                       if (ctx->driver_data->has_shadowcon) {
+                               val = readl(ctx->regs + SHADOWCON);
+                               val &= ~SHADOWCON_CHx_ENABLE(win);
+                               writel(val, ctx->regs + SHADOWCON);
+                       }
                        ch_enabled = 1;
                }
        }
 
        /* Wait for vsync, as disable channel takes effect at next vsync */
-       if (ch_enabled)
+       if (ch_enabled) {
+               unsigned int state = ctx->suspended;
+
+               ctx->suspended = 0;
                fimd_wait_for_vblank(mgr);
+               ctx->suspended = state;
+       }
 }
 
 static int fimd_mgr_initialize(struct exynos_drm_manager *mgr,
@@ -237,23 +260,6 @@ static int fimd_mgr_initialize(struct exynos_drm_manager *mgr,
        mgr->drm_dev = ctx->drm_dev = drm_dev;
        mgr->pipe = ctx->pipe = priv->pipe++;
 
-       /*
-        * enable drm irq mode.
-        * - with irq_enabled = true, we can use the vblank feature.
-        *
-        * P.S. note that we wouldn't use drm irq handler but
-        *      just specific driver own one instead because
-        *      drm framework supports only one irq handler.
-        */
-       drm_dev->irq_enabled = true;
-
-       /*
-        * with vblank_disable_allowed = true, vblank interrupt will be disabled
-        * by drm timer once a current process gives up ownership of
-        * vblank event.(after drm_vblank_put function is called)
-        */
-       drm_dev->vblank_disable_allowed = true;
-
        /* attach this sub driver to iommu mapping if supported. */
        if (is_drm_iommu_supported(ctx->drm_dev)) {
                /*
@@ -1051,7 +1057,6 @@ static void fimd_unbind(struct device *dev, struct device *master,
 {
        struct exynos_drm_manager *mgr = dev_get_drvdata(dev);
        struct fimd_context *ctx = fimd_manager.ctx;
-       struct drm_crtc *crtc = mgr->crtc;
 
        fimd_dpms(mgr, DRM_MODE_DPMS_OFF);
 
@@ -1059,8 +1064,6 @@ static void fimd_unbind(struct device *dev, struct device *master,
                exynos_dpi_remove(dev);
 
        fimd_mgr_remove(mgr);
-
-       crtc->funcs->destroy(crtc);
 }
 
 static const struct component_ops fimd_component_ops = {