drm/exynos: introduce exynos_drm_plane_state structure
[deliverable/linux.git] / drivers / gpu / drm / exynos / exynos_drm_fimd.c
index bd75c1531cac8d527d018b86b5857c187725a358..739544871589f53b1c57d3673ef4f7266101453a 100644 (file)
@@ -29,6 +29,7 @@
 #include <drm/exynos_drm.h>
 
 #include "exynos_drm_drv.h"
+#include "exynos_drm_fb.h"
 #include "exynos_drm_fbdev.h"
 #include "exynos_drm_crtc.h"
 #include "exynos_drm_plane.h"
@@ -640,39 +641,41 @@ static void fimd_atomic_flush(struct exynos_drm_crtc *crtc,
 static void fimd_update_plane(struct exynos_drm_crtc *crtc,
                              struct exynos_drm_plane *plane)
 {
+       struct exynos_drm_plane_state *state =
+                               to_exynos_plane_state(plane->base.state);
        struct fimd_context *ctx = crtc->ctx;
-       struct drm_plane_state *state = plane->base.state;
+       struct drm_framebuffer *fb = state->base.fb;
        dma_addr_t dma_addr;
        unsigned long val, size, offset;
        unsigned int last_x, last_y, buf_offsize, line_size;
        unsigned int win = plane->zpos;
-       unsigned int bpp = state->fb->bits_per_pixel >> 3;
-       unsigned int pitch = state->fb->pitches[0];
+       unsigned int bpp = fb->bits_per_pixel >> 3;
+       unsigned int pitch = fb->pitches[0];
 
        if (ctx->suspended)
                return;
 
-       offset = plane->src_x * bpp;
-       offset += plane->src_y * pitch;
+       offset = state->src.x * bpp;
+       offset += state->src.y * pitch;
 
        /* buffer start address */
-       dma_addr = plane->dma_addr[0] + offset;
+       dma_addr = exynos_drm_fb_dma_addr(fb, 0) + offset;
        val = (unsigned long)dma_addr;
        writel(val, ctx->regs + VIDWx_BUF_START(win, 0));
 
        /* buffer end address */
-       size = pitch * plane->crtc_h;
+       size = pitch * state->crtc.h;
        val = (unsigned long)(dma_addr + size);
        writel(val, ctx->regs + VIDWx_BUF_END(win, 0));
 
        DRM_DEBUG_KMS("start addr = 0x%lx, end addr = 0x%lx, size = 0x%lx\n",
                        (unsigned long)dma_addr, val, size);
        DRM_DEBUG_KMS("ovl_width = %d, ovl_height = %d\n",
-                       plane->crtc_w, plane->crtc_h);
+                       state->crtc.w, state->crtc.h);
 
        /* buffer size */
-       buf_offsize = pitch - (plane->crtc_w * bpp);
-       line_size = plane->crtc_w * bpp;
+       buf_offsize = pitch - (state->crtc.w * bpp);
+       line_size = state->crtc.w * bpp;
        val = VIDW_BUF_SIZE_OFFSET(buf_offsize) |
                VIDW_BUF_SIZE_PAGEWIDTH(line_size) |
                VIDW_BUF_SIZE_OFFSET_E(buf_offsize) |
@@ -680,16 +683,16 @@ static void fimd_update_plane(struct exynos_drm_crtc *crtc,
        writel(val, ctx->regs + VIDWx_BUF_SIZE(win, 0));
 
        /* OSD position */
-       val = VIDOSDxA_TOPLEFT_X(plane->crtc_x) |
-               VIDOSDxA_TOPLEFT_Y(plane->crtc_y) |
-               VIDOSDxA_TOPLEFT_X_E(plane->crtc_x) |
-               VIDOSDxA_TOPLEFT_Y_E(plane->crtc_y);
+       val = VIDOSDxA_TOPLEFT_X(state->crtc.x) |
+               VIDOSDxA_TOPLEFT_Y(state->crtc.y) |
+               VIDOSDxA_TOPLEFT_X_E(state->crtc.x) |
+               VIDOSDxA_TOPLEFT_Y_E(state->crtc.y);
        writel(val, ctx->regs + VIDOSD_A(win));
 
-       last_x = plane->crtc_x + plane->crtc_w;
+       last_x = state->crtc.x + state->crtc.w;
        if (last_x)
                last_x--;
-       last_y = plane->crtc_y + plane->crtc_h;
+       last_y = state->crtc.y + state->crtc.h;
        if (last_y)
                last_y--;
 
@@ -699,20 +702,20 @@ static void fimd_update_plane(struct exynos_drm_crtc *crtc,
        writel(val, ctx->regs + VIDOSD_B(win));
 
        DRM_DEBUG_KMS("osd pos: tx = %d, ty = %d, bx = %d, by = %d\n",
-                       plane->crtc_x, plane->crtc_y, last_x, last_y);
+                       state->crtc.x, state->crtc.y, last_x, last_y);
 
        /* OSD size */
        if (win != 3 && win != 4) {
                u32 offset = VIDOSD_D(win);
                if (win == 0)
                        offset = VIDOSD_C(win);
-               val = plane->crtc_w * plane->crtc_h;
+               val = state->crtc.w * state->crtc.h;
                writel(val, ctx->regs + offset);
 
                DRM_DEBUG_KMS("osd size = 0x%x\n", (unsigned int)val);
        }
 
-       fimd_win_set_pixfmt(ctx, win, state->fb);
+       fimd_win_set_pixfmt(ctx, win, fb);
 
        /* hardware window 0 doesn't support color key. */
        if (win != 0)
@@ -745,7 +748,6 @@ static void fimd_disable_plane(struct exynos_drm_crtc *crtc,
 static void fimd_enable(struct exynos_drm_crtc *crtc)
 {
        struct fimd_context *ctx = crtc->ctx;
-       int ret;
 
        if (!ctx->suspended)
                return;
@@ -754,18 +756,6 @@ static void fimd_enable(struct exynos_drm_crtc *crtc)
 
        pm_runtime_get_sync(ctx->dev);
 
-       ret = clk_prepare_enable(ctx->bus_clk);
-       if (ret < 0) {
-               DRM_ERROR("Failed to prepare_enable the bus clk [%d]\n", ret);
-               return;
-       }
-
-       ret = clk_prepare_enable(ctx->lcd_clk);
-       if  (ret < 0) {
-               DRM_ERROR("Failed to prepare_enable the lcd clk [%d]\n", ret);
-               return;
-       }
-
        /* if vblank was enabled status, enable it again. */
        if (test_and_clear_bit(0, &ctx->irq_flags))
                fimd_enable_vblank(ctx->crtc);
@@ -795,11 +785,7 @@ static void fimd_disable(struct exynos_drm_crtc *crtc)
 
        writel(0, ctx->regs + VIDCON0);
 
-       clk_disable_unprepare(ctx->lcd_clk);
-       clk_disable_unprepare(ctx->bus_clk);
-
        pm_runtime_put_sync(ctx->dev);
-
        ctx->suspended = true;
 }
 
@@ -1121,12 +1107,49 @@ static int fimd_remove(struct platform_device *pdev)
        return 0;
 }
 
+#ifdef CONFIG_PM
+static int exynos_fimd_suspend(struct device *dev)
+{
+       struct fimd_context *ctx = dev_get_drvdata(dev);
+
+       clk_disable_unprepare(ctx->lcd_clk);
+       clk_disable_unprepare(ctx->bus_clk);
+
+       return 0;
+}
+
+static int exynos_fimd_resume(struct device *dev)
+{
+       struct fimd_context *ctx = dev_get_drvdata(dev);
+       int ret;
+
+       ret = clk_prepare_enable(ctx->bus_clk);
+       if (ret < 0) {
+               DRM_ERROR("Failed to prepare_enable the bus clk [%d]\n", ret);
+               return ret;
+       }
+
+       ret = clk_prepare_enable(ctx->lcd_clk);
+       if  (ret < 0) {
+               DRM_ERROR("Failed to prepare_enable the lcd clk [%d]\n", ret);
+               return ret;
+       }
+
+       return 0;
+}
+#endif
+
+static const struct dev_pm_ops exynos_fimd_pm_ops = {
+       SET_RUNTIME_PM_OPS(exynos_fimd_suspend, exynos_fimd_resume, NULL)
+};
+
 struct platform_driver fimd_driver = {
        .probe          = fimd_probe,
        .remove         = fimd_remove,
        .driver         = {
                .name   = "exynos4-fb",
                .owner  = THIS_MODULE,
+               .pm     = &exynos_fimd_pm_ops,
                .of_match_table = fimd_driver_dt_match,
        },
 };
This page took 0.045631 seconds and 5 git commands to generate.