drm/exynos: remove struct *_win_data abstraction on planes
authorGustavo Padovan <gustavo.padovan@collabora.co.uk>
Fri, 3 Apr 2015 12:03:40 +0000 (21:03 +0900)
committerInki Dae <inki.dae@samsung.com>
Mon, 13 Apr 2015 02:39:39 +0000 (11:39 +0900)
struct {fimd,mixer,vidi}_win_data was just keeping the same data
as struct exynos_drm_plane thus get ride of it and use exynos_drm_plane
directly.

It changes how planes are created and remove .win_mode_set() callback
that was only filling all *_win_data structs.

v2: check for return of exynos_plane_init()

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

index 9700461..c5dfd99 100644 (file)
@@ -28,6 +28,7 @@
 #include <video/exynos7_decon.h>
 
 #include "exynos_drm_crtc.h"
+#include "exynos_drm_plane.h"
 #include "exynos_drm_drv.h"
 #include "exynos_drm_fbdev.h"
 #include "exynos_drm_iommu.h"
 
 #define WINDOWS_NR     2
 
-struct decon_win_data {
-       unsigned int            ovl_x;
-       unsigned int            ovl_y;
-       unsigned int            offset_x;
-       unsigned int            offset_y;
-       unsigned int            ovl_width;
-       unsigned int            ovl_height;
-       unsigned int            fb_width;
-       unsigned int            fb_height;
-       unsigned int            bpp;
-       unsigned int            pixel_format;
-       dma_addr_t              dma_addr;
-       bool                    enabled;
-       bool                    resume;
-};
-
 struct decon_context {
        struct device                   *dev;
        struct drm_device               *drm_dev;
        struct exynos_drm_crtc          *crtc;
+       struct exynos_drm_plane         planes[WINDOWS_NR];
        struct clk                      *pclk;
        struct clk                      *aclk;
        struct clk                      *eclk;
        struct clk                      *vclk;
        void __iomem                    *regs;
-       struct decon_win_data           win_data[WINDOWS_NR];
        unsigned int                    default_win;
        unsigned long                   irq_flags;
        bool                            i80_if;
@@ -296,59 +281,16 @@ static void decon_disable_vblank(struct exynos_drm_crtc *crtc)
        }
 }
 
-static void decon_win_mode_set(struct exynos_drm_crtc *crtc,
-                       struct exynos_drm_plane *plane)
-{
-       struct decon_context *ctx = crtc->ctx;
-       struct decon_win_data *win_data;
-       int win, padding;
-
-       if (!plane) {
-               DRM_ERROR("plane is NULL\n");
-               return;
-       }
-
-       win = plane->zpos;
-       if (win == DEFAULT_ZPOS)
-               win = ctx->default_win;
-
-       if (win < 0 || win >= WINDOWS_NR)
-               return;
-
-
-       win_data = &ctx->win_data[win];
-
-       padding = (plane->pitch / (plane->bpp >> 3)) - plane->fb_width;
-       win_data->offset_x = plane->fb_x;
-       win_data->offset_y = plane->fb_y;
-       win_data->fb_width = plane->fb_width + padding;
-       win_data->fb_height = plane->fb_height;
-       win_data->ovl_x = plane->crtc_x;
-       win_data->ovl_y = plane->crtc_y;
-       win_data->ovl_width = plane->crtc_width;
-       win_data->ovl_height = plane->crtc_height;
-       win_data->dma_addr = plane->dma_addr[0];
-       win_data->bpp = plane->bpp;
-       win_data->pixel_format = plane->pixel_format;
-
-       DRM_DEBUG_KMS("offset_x = %d, offset_y = %d\n",
-                       win_data->offset_x, win_data->offset_y);
-       DRM_DEBUG_KMS("ovl_width = %d, ovl_height = %d\n",
-                       win_data->ovl_width, win_data->ovl_height);
-       DRM_DEBUG_KMS("paddr = 0x%lx\n", (unsigned long)win_data->dma_addr);
-       DRM_DEBUG_KMS("fb_width = %d, crtc_width = %d\n",
-                       plane->fb_width, plane->crtc_width);
-}
-
 static void decon_win_set_pixfmt(struct decon_context *ctx, unsigned int win)
 {
-       struct decon_win_data *win_data = &ctx->win_data[win];
+       struct exynos_drm_plane *plane = &ctx->planes[win];
        unsigned long val;
+       int padding;
 
        val = readl(ctx->regs + WINCON(win));
        val &= ~WINCONx_BPPMODE_MASK;
 
-       switch (win_data->pixel_format) {
+       switch (plane->pixel_format) {
        case DRM_FORMAT_RGB565:
                val |= WINCONx_BPPMODE_16BPP_565;
                val |= WINCONx_BURSTLEN_16WORD;
@@ -397,7 +339,7 @@ static void decon_win_set_pixfmt(struct decon_context *ctx, unsigned int win)
                break;
        }
 
-       DRM_DEBUG_KMS("bpp = %d\n", win_data->bpp);
+       DRM_DEBUG_KMS("bpp = %d\n", plane->bpp);
 
        /*
         * In case of exynos, setting dma-burst to 16Word causes permanent
@@ -407,7 +349,8 @@ static void decon_win_set_pixfmt(struct decon_context *ctx, unsigned int win)
         * movement causes unstable DMA which results into iommu crash/tear.
         */
 
-       if (win_data->fb_width < MIN_FB_WIDTH_FOR_16WORD_BURST) {
+       padding = (plane->pitch / (plane->bpp >> 3)) - plane->fb_width;
+       if (plane->fb_width + padding < MIN_FB_WIDTH_FOR_16WORD_BURST) {
                val &= ~WINCONx_BURSTLEN_MASK;
                val |= WINCONx_BURSTLEN_8WORD;
        }
@@ -453,8 +396,8 @@ static void decon_win_commit(struct exynos_drm_crtc *crtc, int zpos)
 {
        struct decon_context *ctx = crtc->ctx;
        struct drm_display_mode *mode = &crtc->base.mode;
-       struct decon_win_data *win_data;
-       int win = zpos;
+       struct exynos_drm_plane *plane;
+       int padding, win = zpos;
        unsigned long val, alpha;
        unsigned int last_x;
        unsigned int last_y;
@@ -468,11 +411,11 @@ static void decon_win_commit(struct exynos_drm_crtc *crtc, int zpos)
        if (win < 0 || win >= WINDOWS_NR)
                return;
 
-       win_data = &ctx->win_data[win];
+       plane = &ctx->planes[win];
 
        /* If suspended, enable this on resume */
        if (ctx->suspended) {
-               win_data->resume = true;
+               plane->resume = true;
                return;
        }
 
@@ -490,39 +433,41 @@ static void decon_win_commit(struct exynos_drm_crtc *crtc, int zpos)
        decon_shadow_protect_win(ctx, win, true);
 
        /* buffer start address */
-       val = (unsigned long)win_data->dma_addr;
+       val = (unsigned long)plane->dma_addr[0];
        writel(val, ctx->regs + VIDW_BUF_START(win));
 
+       padding = (plane->pitch / (plane->bpp >> 3)) - plane->fb_width;
+
        /* buffer size */
-       writel(win_data->fb_width, ctx->regs + VIDW_WHOLE_X(win));
-       writel(win_data->fb_height, ctx->regs + VIDW_WHOLE_Y(win));
+       writel(plane->fb_width + padding, ctx->regs + VIDW_WHOLE_X(win));
+       writel(plane->fb_height, ctx->regs + VIDW_WHOLE_Y(win));
 
        /* offset from the start of the buffer to read */
-       writel(win_data->offset_x, ctx->regs + VIDW_OFFSET_X(win));
-       writel(win_data->offset_y, ctx->regs + VIDW_OFFSET_Y(win));
+       writel(plane->fb_x, ctx->regs + VIDW_OFFSET_X(win));
+       writel(plane->fb_y, ctx->regs + VIDW_OFFSET_Y(win));
 
        DRM_DEBUG_KMS("start addr = 0x%lx\n",
-                       (unsigned long)win_data->dma_addr);
+                       (unsigned long)val);
        DRM_DEBUG_KMS("ovl_width = %d, ovl_height = %d\n",
-                       win_data->ovl_width, win_data->ovl_height);
+                       plane->crtc_width, plane->crtc_height);
 
        /*
         * OSD position.
         * In case the window layout goes of LCD layout, DECON fails.
         */
-       if ((win_data->ovl_x + win_data->ovl_width) > mode->hdisplay)
-               win_data->ovl_x = mode->hdisplay - win_data->ovl_width;
-       if ((win_data->ovl_y + win_data->ovl_height) > mode->vdisplay)
-               win_data->ovl_y = mode->vdisplay - win_data->ovl_height;
+       if ((plane->crtc_x + plane->crtc_width) > mode->hdisplay)
+               plane->crtc_x = mode->hdisplay - plane->crtc_width;
+       if ((plane->crtc_y + plane->crtc_height) > mode->vdisplay)
+               plane->crtc_y = mode->vdisplay - plane->crtc_height;
 
-       val = VIDOSDxA_TOPLEFT_X(win_data->ovl_x) |
-               VIDOSDxA_TOPLEFT_Y(win_data->ovl_y);
+       val = VIDOSDxA_TOPLEFT_X(plane->crtc_x) |
+               VIDOSDxA_TOPLEFT_Y(plane->crtc_y);
        writel(val, ctx->regs + VIDOSD_A(win));
 
-       last_x = win_data->ovl_x + win_data->ovl_width;
+       last_x = plane->crtc_x + plane->crtc_width;
        if (last_x)
                last_x--;
-       last_y = win_data->ovl_y + win_data->ovl_height;
+       last_y = plane->crtc_y + plane->crtc_height;
        if (last_y)
                last_y--;
 
@@ -531,7 +476,7 @@ static void decon_win_commit(struct exynos_drm_crtc *crtc, int zpos)
        writel(val, ctx->regs + VIDOSD_B(win));
 
        DRM_DEBUG_KMS("osd pos: tx = %d, ty = %d, bx = %d, by = %d\n",
-                       win_data->ovl_x, win_data->ovl_y, last_x, last_y);
+                       plane->crtc_x, plane->crtc_y, last_x, last_y);
 
        /* OSD alpha */
        alpha = VIDOSDxC_ALPHA0_R_F(0x0) |
@@ -565,13 +510,13 @@ static void decon_win_commit(struct exynos_drm_crtc *crtc, int zpos)
        val |= DECON_UPDATE_STANDALONE_F;
        writel(val, ctx->regs + DECON_UPDATE);
 
-       win_data->enabled = true;
+       plane->enabled = true;
 }
 
 static void decon_win_disable(struct exynos_drm_crtc *crtc, int zpos)
 {
        struct decon_context *ctx = crtc->ctx;
-       struct decon_win_data *win_data;
+       struct exynos_drm_plane *plane;
        int win = zpos;
        u32 val;
 
@@ -581,11 +526,11 @@ static void decon_win_disable(struct exynos_drm_crtc *crtc, int zpos)
        if (win < 0 || win >= WINDOWS_NR)
                return;
 
-       win_data = &ctx->win_data[win];
+       plane = &ctx->planes[win];
 
        if (ctx->suspended) {
                /* do not resume this window*/
-               win_data->resume = false;
+               plane->resume = false;
                return;
        }
 
@@ -604,42 +549,42 @@ static void decon_win_disable(struct exynos_drm_crtc *crtc, int zpos)
        val |= DECON_UPDATE_STANDALONE_F;
        writel(val, ctx->regs + DECON_UPDATE);
 
-       win_data->enabled = false;
+       plane->enabled = false;
 }
 
 static void decon_window_suspend(struct decon_context *ctx)
 {
-       struct decon_win_data *win_data;
+       struct exynos_drm_plane *plane;
        int i;
 
        for (i = 0; i < WINDOWS_NR; i++) {
-               win_data = &ctx->win_data[i];
-               win_data->resume = win_data->enabled;
-               if (win_data->enabled)
+               plane = &ctx->planes[i];
+               plane->resume = plane->enabled;
+               if (plane->enabled)
                        decon_win_disable(ctx->crtc, i);
        }
 }
 
 static void decon_window_resume(struct decon_context *ctx)
 {
-       struct decon_win_data *win_data;
+       struct exynos_drm_plane *plane;
        int i;
 
        for (i = 0; i < WINDOWS_NR; i++) {
-               win_data = &ctx->win_data[i];
-               win_data->enabled = win_data->resume;
-               win_data->resume = false;
+               plane = &ctx->planes[i];
+               plane->enabled = plane->resume;
+               plane->resume = false;
        }
 }
 
 static void decon_apply(struct decon_context *ctx)
 {
-       struct decon_win_data *win_data;
+       struct exynos_drm_plane *plane;
        int i;
 
        for (i = 0; i < WINDOWS_NR; i++) {
-               win_data = &ctx->win_data[i];
-               if (win_data->enabled)
+               plane = &ctx->planes[i];
+               if (plane->enabled)
                        decon_win_commit(ctx->crtc, i);
                else
                        decon_win_disable(ctx->crtc, i);
@@ -779,7 +724,6 @@ static struct exynos_drm_crtc_ops decon_crtc_ops = {
        .enable_vblank = decon_enable_vblank,
        .disable_vblank = decon_disable_vblank,
        .wait_for_vblank = decon_wait_for_vblank,
-       .win_mode_set = decon_win_mode_set,
        .win_commit = decon_win_commit,
        .win_disable = decon_win_disable,
 };
@@ -818,7 +762,9 @@ static int decon_bind(struct device *dev, struct device *master, void *data)
 {
        struct decon_context *ctx = dev_get_drvdata(dev);
        struct drm_device *drm_dev = data;
-       int ret;
+       struct exynos_drm_plane *exynos_plane;
+       enum drm_plane_type type;
+       int zpos, ret;
 
        ret = decon_ctx_initialize(ctx, drm_dev);
        if (ret) {
@@ -826,8 +772,18 @@ static int decon_bind(struct device *dev, struct device *master, void *data)
                return ret;
        }
 
-       ctx->crtc = exynos_drm_crtc_create(drm_dev, ctx->pipe,
-                                          EXYNOS_DISPLAY_TYPE_LCD,
+       for (zpos = 0; zpos < WINDOWS_NR; zpos++) {
+               type = (zpos == ctx->default_win) ? DRM_PLANE_TYPE_PRIMARY :
+                                               DRM_PLANE_TYPE_OVERLAY;
+               ret = exynos_plane_init(drm_dev, &ctx->planes[zpos],
+                                       1 << ctx->pipe, type);
+               if (ret)
+                       return ret;
+       }
+
+       exynos_plane = &ctx->planes[ctx->default_win];
+       ctx->crtc = exynos_drm_crtc_create(drm_dev, &exynos_plane->base,
+                                          ctx->pipe, EXYNOS_DISPLAY_TYPE_LCD,
                                           &decon_crtc_ops, ctx);
        if (IS_ERR(ctx->crtc)) {
                decon_ctx_remove(ctx);
index 48ccab7..47dd2b0 100644 (file)
@@ -239,13 +239,13 @@ static struct drm_crtc_funcs exynos_crtc_funcs = {
 };
 
 struct exynos_drm_crtc *exynos_drm_crtc_create(struct drm_device *drm_dev,
+                                              struct drm_plane *plane,
                                               int pipe,
                                               enum exynos_drm_output_type type,
                                               struct exynos_drm_crtc_ops *ops,
                                               void *ctx)
 {
        struct exynos_drm_crtc *exynos_crtc;
-       struct drm_plane *plane;
        struct exynos_drm_private *private = drm_dev->dev_private;
        struct drm_crtc *crtc;
        int ret;
@@ -262,12 +262,6 @@ struct exynos_drm_crtc *exynos_drm_crtc_create(struct drm_device *drm_dev,
        exynos_crtc->type = type;
        exynos_crtc->ops = ops;
        exynos_crtc->ctx = ctx;
-       plane = exynos_plane_init(drm_dev, 1 << pipe,
-                                 DRM_PLANE_TYPE_PRIMARY);
-       if (IS_ERR(plane)) {
-               ret = PTR_ERR(plane);
-               goto err_plane;
-       }
 
        crtc = &exynos_crtc->base;
 
@@ -284,7 +278,6 @@ struct exynos_drm_crtc *exynos_drm_crtc_create(struct drm_device *drm_dev,
 
 err_crtc:
        plane->funcs->destroy(plane);
-err_plane:
        kfree(exynos_crtc);
        return ERR_PTR(ret);
 }
index 6258b80..e1fd2ef 100644 (file)
@@ -18,6 +18,7 @@
 #include "exynos_drm_drv.h"
 
 struct exynos_drm_crtc *exynos_drm_crtc_create(struct drm_device *drm_dev,
+                                              struct drm_plane *plane,
                                               int pipe,
                                               enum exynos_drm_output_type type,
                                               struct exynos_drm_crtc_ops *ops,
index 90168d7..bb6e7f7 100644 (file)
@@ -55,7 +55,6 @@ static int exynos_drm_load(struct drm_device *dev, unsigned long flags)
 {
        struct exynos_drm_private *private;
        int ret;
-       int nr;
 
        private = kzalloc(sizeof(struct exynos_drm_private), GFP_KERNEL);
        if (!private)
@@ -81,19 +80,6 @@ static int exynos_drm_load(struct drm_device *dev, unsigned long flags)
 
        exynos_drm_mode_config_init(dev);
 
-       for (nr = 0; nr < MAX_PLANE; nr++) {
-               struct drm_plane *plane;
-               unsigned long possible_crtcs = (1 << MAX_CRTC) - 1;
-
-               plane = exynos_plane_init(dev, possible_crtcs,
-                                         DRM_PLANE_TYPE_OVERLAY);
-               if (!IS_ERR(plane))
-                       continue;
-
-               ret = PTR_ERR(plane);
-               goto err_mode_config_cleanup;
-       }
-
        /* setup possible_clones. */
        exynos_drm_encoder_setup(dev);
 
index 4e8f0b0..8a2f943 100644 (file)
@@ -78,6 +78,7 @@ enum exynos_drm_output_type {
  * @transparency: transparency on or off.
  * @activated: activated or not.
  * @enabled: enabled or not.
+ * @resume: to resume or not.
  *
  * this structure is common to exynos SoC and its contents would be copied
  * to hardware specific overlay info.
@@ -112,6 +113,7 @@ struct exynos_drm_plane {
        bool transparency:1;
        bool activated:1;
        bool enabled:1;
+       bool resume:1;
 };
 
 /*
@@ -172,7 +174,6 @@ struct exynos_drm_display {
  * @disable_vblank: specific driver callback for disabling vblank interrupt.
  * @wait_for_vblank: wait for vblank interrupt to make sure that
  *     hardware overlay is updated.
- * @win_mode_set: copy drm overlay info to hw specific overlay info.
  * @win_commit: apply hardware specific overlay data to registers.
  * @win_disable: disable hardware specific overlay.
  * @te_handler: trigger to transfer video image at the tearing effect
@@ -188,8 +189,6 @@ struct exynos_drm_crtc_ops {
        int (*enable_vblank)(struct exynos_drm_crtc *crtc);
        void (*disable_vblank)(struct exynos_drm_crtc *crtc);
        void (*wait_for_vblank)(struct exynos_drm_crtc *crtc);
-       void (*win_mode_set)(struct exynos_drm_crtc *crtc,
-                               struct exynos_drm_plane *plane);
        void (*win_commit)(struct exynos_drm_crtc *crtc, int zpos);
        void (*win_disable)(struct exynos_drm_crtc *crtc, int zpos);
        void (*te_handler)(struct exynos_drm_crtc *crtc);
index 6f51d3d..ab97162 100644 (file)
@@ -31,6 +31,7 @@
 #include "exynos_drm_drv.h"
 #include "exynos_drm_fbdev.h"
 #include "exynos_drm_crtc.h"
+#include "exynos_drm_plane.h"
 #include "exynos_drm_iommu.h"
 
 /*
@@ -143,32 +144,15 @@ static struct fimd_driver_data exynos5_fimd_driver_data = {
        .has_vtsel = 1,
 };
 
-struct fimd_win_data {
-       unsigned int            offset_x;
-       unsigned int            offset_y;
-       unsigned int            ovl_width;
-       unsigned int            ovl_height;
-       unsigned int            fb_width;
-       unsigned int            fb_height;
-       unsigned int            fb_pitch;
-       unsigned int            bpp;
-       unsigned int            pixel_format;
-       dma_addr_t              dma_addr;
-       unsigned int            buf_offsize;
-       unsigned int            line_size;      /* bytes */
-       bool                    enabled;
-       bool                    resume;
-};
-
 struct fimd_context {
        struct device                   *dev;
        struct drm_device               *drm_dev;
        struct exynos_drm_crtc          *crtc;
+       struct exynos_drm_plane         planes[WINDOWS_NR];
        struct clk                      *bus_clk;
        struct clk                      *lcd_clk;
        void __iomem                    *regs;
        struct regmap                   *sysreg;
-       struct fimd_win_data            win_data[WINDOWS_NR];
        unsigned int                    default_win;
        unsigned long                   irq_flags;
        u32                             vidcon0;
@@ -505,59 +489,9 @@ static void fimd_disable_vblank(struct exynos_drm_crtc *crtc)
        }
 }
 
-static void fimd_win_mode_set(struct exynos_drm_crtc *crtc,
-                       struct exynos_drm_plane *plane)
-{
-       struct fimd_context *ctx = crtc->ctx;
-       struct fimd_win_data *win_data;
-       int win;
-       unsigned long offset;
-
-       if (!plane) {
-               DRM_ERROR("plane is NULL\n");
-               return;
-       }
-
-       win = plane->zpos;
-       if (win == DEFAULT_ZPOS)
-               win = ctx->default_win;
-
-       if (win < 0 || win >= WINDOWS_NR)
-               return;
-
-       offset = plane->fb_x * (plane->bpp >> 3);
-       offset += plane->fb_y * plane->pitch;
-
-       DRM_DEBUG_KMS("offset = 0x%lx, pitch = %x\n", offset, plane->pitch);
-
-       win_data = &ctx->win_data[win];
-
-       win_data->offset_x = plane->crtc_x;
-       win_data->offset_y = plane->crtc_y;
-       win_data->ovl_width = plane->crtc_width;
-       win_data->ovl_height = plane->crtc_height;
-       win_data->fb_pitch = plane->pitch;
-       win_data->fb_width = plane->fb_width;
-       win_data->fb_height = plane->fb_height;
-       win_data->dma_addr = plane->dma_addr[0] + offset;
-       win_data->bpp = plane->bpp;
-       win_data->pixel_format = plane->pixel_format;
-       win_data->buf_offsize =
-               plane->pitch - (plane->crtc_width * (plane->bpp >> 3));
-       win_data->line_size = plane->crtc_width * (plane->bpp >> 3);
-
-       DRM_DEBUG_KMS("offset_x = %d, offset_y = %d\n",
-                       win_data->offset_x, win_data->offset_y);
-       DRM_DEBUG_KMS("ovl_width = %d, ovl_height = %d\n",
-                       win_data->ovl_width, win_data->ovl_height);
-       DRM_DEBUG_KMS("paddr = 0x%lx\n", (unsigned long)win_data->dma_addr);
-       DRM_DEBUG_KMS("fb_width = %d, crtc_width = %d\n",
-                       plane->fb_width, plane->crtc_width);
-}
-
 static void fimd_win_set_pixfmt(struct fimd_context *ctx, unsigned int win)
 {
-       struct fimd_win_data *win_data = &ctx->win_data[win];
+       struct exynos_drm_plane *plane = &ctx->planes[win];
        unsigned long val;
 
        val = WINCONx_ENWIN;
@@ -567,11 +501,11 @@ static void fimd_win_set_pixfmt(struct fimd_context *ctx, unsigned int win)
         * So the request format is ARGB8888 then change it to XRGB8888.
         */
        if (ctx->driver_data->has_limited_fmt && !win) {
-               if (win_data->pixel_format == DRM_FORMAT_ARGB8888)
-                       win_data->pixel_format = DRM_FORMAT_XRGB8888;
+               if (plane->pixel_format == DRM_FORMAT_ARGB8888)
+                       plane->pixel_format = DRM_FORMAT_XRGB8888;
        }
 
-       switch (win_data->pixel_format) {
+       switch (plane->pixel_format) {
        case DRM_FORMAT_C8:
                val |= WINCON0_BPPMODE_8BPP_PALETTE;
                val |= WINCONx_BURSTLEN_8WORD;
@@ -607,7 +541,7 @@ static void fimd_win_set_pixfmt(struct fimd_context *ctx, unsigned int win)
                break;
        }
 
-       DRM_DEBUG_KMS("bpp = %d\n", win_data->bpp);
+       DRM_DEBUG_KMS("bpp = %d\n", plane->bpp);
 
        /*
         * In case of exynos, setting dma-burst to 16Word causes permanent
@@ -617,7 +551,7 @@ static void fimd_win_set_pixfmt(struct fimd_context *ctx, unsigned int win)
         * movement causes unstable DMA which results into iommu crash/tear.
         */
 
-       if (win_data->fb_width < MIN_FB_WIDTH_FOR_16WORD_BURST) {
+       if (plane->fb_width < MIN_FB_WIDTH_FOR_16WORD_BURST) {
                val &= ~WINCONx_BURSTLEN_MASK;
                val |= WINCONx_BURSTLEN_4WORD;
        }
@@ -686,11 +620,11 @@ static void fimd_shadow_protect_win(struct fimd_context *ctx,
 static void fimd_win_commit(struct exynos_drm_crtc *crtc, int zpos)
 {
        struct fimd_context *ctx = crtc->ctx;
-       struct fimd_win_data *win_data;
+       struct exynos_drm_plane *plane;
        int win = zpos;
-       unsigned long val, size;
-       unsigned int last_x;
-       unsigned int last_y;
+       dma_addr_t dma_addr;
+       unsigned long val, size, offset;
+       unsigned int last_x, last_y, buf_offsize, line_size;
 
        if (ctx->suspended)
                return;
@@ -701,11 +635,11 @@ static void fimd_win_commit(struct exynos_drm_crtc *crtc, int zpos)
        if (win < 0 || win >= WINDOWS_NR)
                return;
 
-       win_data = &ctx->win_data[win];
+       plane = &ctx->planes[win];
 
        /* If suspended, enable this on resume */
        if (ctx->suspended) {
-               win_data->resume = true;
+               plane->resume = true;
                return;
        }
 
@@ -722,38 +656,45 @@ static void fimd_win_commit(struct exynos_drm_crtc *crtc, int zpos)
        /* protect windows */
        fimd_shadow_protect_win(ctx, win, true);
 
+
+       offset = plane->fb_x * (plane->bpp >> 3);
+       offset += plane->fb_y * plane->pitch;
+
        /* buffer start address */
-       val = (unsigned long)win_data->dma_addr;
+       dma_addr = plane->dma_addr[0] + offset;
+       val = (unsigned long)dma_addr;
        writel(val, ctx->regs + VIDWx_BUF_START(win, 0));
 
        /* buffer end address */
-       size = win_data->fb_pitch * win_data->ovl_height * (win_data->bpp >> 3);
-       val = (unsigned long)(win_data->dma_addr + size);
+       size = plane->pitch * plane->crtc_height * (plane->bpp >> 3);
+       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)win_data->dma_addr, val, size);
+                       (unsigned long)dma_addr, val, size);
        DRM_DEBUG_KMS("ovl_width = %d, ovl_height = %d\n",
-                       win_data->ovl_width, win_data->ovl_height);
+                       plane->crtc_width, plane->crtc_height);
 
        /* buffer size */
-       val = VIDW_BUF_SIZE_OFFSET(win_data->buf_offsize) |
-               VIDW_BUF_SIZE_PAGEWIDTH(win_data->line_size) |
-               VIDW_BUF_SIZE_OFFSET_E(win_data->buf_offsize) |
-               VIDW_BUF_SIZE_PAGEWIDTH_E(win_data->line_size);
+       buf_offsize = (plane->fb_width - plane->crtc_width) * (plane->bpp >> 3);
+       line_size = plane->crtc_width * (plane->bpp >> 3);
+       val = VIDW_BUF_SIZE_OFFSET(buf_offsize) |
+               VIDW_BUF_SIZE_PAGEWIDTH(line_size) |
+               VIDW_BUF_SIZE_OFFSET_E(buf_offsize) |
+               VIDW_BUF_SIZE_PAGEWIDTH_E(line_size);
        writel(val, ctx->regs + VIDWx_BUF_SIZE(win, 0));
 
        /* OSD position */
-       val = VIDOSDxA_TOPLEFT_X(win_data->offset_x) |
-               VIDOSDxA_TOPLEFT_Y(win_data->offset_y) |
-               VIDOSDxA_TOPLEFT_X_E(win_data->offset_x) |
-               VIDOSDxA_TOPLEFT_Y_E(win_data->offset_y);
+       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);
        writel(val, ctx->regs + VIDOSD_A(win));
 
-       last_x = win_data->offset_x + win_data->ovl_width;
+       last_x = plane->crtc_x + plane->crtc_width;
        if (last_x)
                last_x--;
-       last_y = win_data->offset_y + win_data->ovl_height;
+       last_y = plane->crtc_y + plane->crtc_height;
        if (last_y)
                last_y--;
 
@@ -763,14 +704,14 @@ static void fimd_win_commit(struct exynos_drm_crtc *crtc, int zpos)
        writel(val, ctx->regs + VIDOSD_B(win));
 
        DRM_DEBUG_KMS("osd pos: tx = %d, ty = %d, bx = %d, by = %d\n",
-                       win_data->offset_x, win_data->offset_y, last_x, last_y);
+                       plane->crtc_x, plane->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 = win_data->ovl_width * win_data->ovl_height;
+               val = plane->crtc_width * plane->crtc_height;
                writel(val, ctx->regs + offset);
 
                DRM_DEBUG_KMS("osd size = 0x%x\n", (unsigned int)val);
@@ -790,7 +731,7 @@ static void fimd_win_commit(struct exynos_drm_crtc *crtc, int zpos)
        /* Enable DMA channel and unprotect windows */
        fimd_shadow_protect_win(ctx, win, false);
 
-       win_data->enabled = true;
+       plane->enabled = true;
 
        if (ctx->i80_if)
                atomic_set(&ctx->win_updated, 1);
@@ -799,7 +740,7 @@ static void fimd_win_commit(struct exynos_drm_crtc *crtc, int zpos)
 static void fimd_win_disable(struct exynos_drm_crtc *crtc, int zpos)
 {
        struct fimd_context *ctx = crtc->ctx;
-       struct fimd_win_data *win_data;
+       struct exynos_drm_plane *plane;
        int win = zpos;
 
        if (win == DEFAULT_ZPOS)
@@ -808,11 +749,11 @@ static void fimd_win_disable(struct exynos_drm_crtc *crtc, int zpos)
        if (win < 0 || win >= WINDOWS_NR)
                return;
 
-       win_data = &ctx->win_data[win];
+       plane = &ctx->planes[win];
 
        if (ctx->suspended) {
                /* do not resume this window*/
-               win_data->resume = false;
+               plane->resume = false;
                return;
        }
 
@@ -827,42 +768,42 @@ static void fimd_win_disable(struct exynos_drm_crtc *crtc, int zpos)
        /* unprotect windows */
        fimd_shadow_protect_win(ctx, win, false);
 
-       win_data->enabled = false;
+       plane->enabled = false;
 }
 
 static void fimd_window_suspend(struct fimd_context *ctx)
 {
-       struct fimd_win_data *win_data;
+       struct exynos_drm_plane *plane;
        int i;
 
        for (i = 0; i < WINDOWS_NR; i++) {
-               win_data = &ctx->win_data[i];
-               win_data->resume = win_data->enabled;
-               if (win_data->enabled)
+               plane = &ctx->planes[i];
+               plane->resume = plane->enabled;
+               if (plane->enabled)
                        fimd_win_disable(ctx->crtc, i);
        }
 }
 
 static void fimd_window_resume(struct fimd_context *ctx)
 {
-       struct fimd_win_data *win_data;
+       struct exynos_drm_plane *plane;
        int i;
 
        for (i = 0; i < WINDOWS_NR; i++) {
-               win_data = &ctx->win_data[i];
-               win_data->enabled = win_data->resume;
-               win_data->resume = false;
+               plane = &ctx->planes[i];
+               plane->enabled = plane->resume;
+               plane->resume = false;
        }
 }
 
 static void fimd_apply(struct fimd_context *ctx)
 {
-       struct fimd_win_data *win_data;
+       struct exynos_drm_plane *plane;
        int i;
 
        for (i = 0; i < WINDOWS_NR; i++) {
-               win_data = &ctx->win_data[i];
-               if (win_data->enabled)
+               plane = &ctx->planes[i];
+               if (plane->enabled)
                        fimd_win_commit(ctx->crtc, i);
                else
                        fimd_win_disable(ctx->crtc, i);
@@ -1019,7 +960,6 @@ static struct exynos_drm_crtc_ops fimd_crtc_ops = {
        .enable_vblank = fimd_enable_vblank,
        .disable_vblank = fimd_disable_vblank,
        .wait_for_vblank = fimd_wait_for_vblank,
-       .win_mode_set = fimd_win_mode_set,
        .win_commit = fimd_win_commit,
        .win_disable = fimd_win_disable,
        .te_handler = fimd_te_handler,
@@ -1065,13 +1005,25 @@ static int fimd_bind(struct device *dev, struct device *master, void *data)
        struct fimd_context *ctx = dev_get_drvdata(dev);
        struct drm_device *drm_dev = data;
        struct exynos_drm_private *priv = drm_dev->dev_private;
-       int ret;
+       struct exynos_drm_plane *exynos_plane;
+       enum drm_plane_type type;
+       int zpos, ret;
 
        ctx->drm_dev = drm_dev;
        ctx->pipe = priv->pipe++;
 
-       ctx->crtc = exynos_drm_crtc_create(drm_dev, ctx->pipe,
-                                          EXYNOS_DISPLAY_TYPE_LCD,
+       for (zpos = 0; zpos < WINDOWS_NR; zpos++) {
+               type = (zpos == ctx->default_win) ? DRM_PLANE_TYPE_PRIMARY :
+                                               DRM_PLANE_TYPE_OVERLAY;
+               ret = exynos_plane_init(drm_dev, &ctx->planes[zpos],
+                                       1 << ctx->pipe, type);
+               if (ret)
+                       return ret;
+       }
+
+       exynos_plane = &ctx->planes[ctx->default_win];
+       ctx->crtc = exynos_drm_crtc_create(drm_dev, &exynos_plane->base,
+                                          ctx->pipe, EXYNOS_DISPLAY_TYPE_LCD,
                                           &fimd_crtc_ops, ctx);
 
        if (ctx->display)
index 8ad5b72..4014c74 100644 (file)
@@ -92,7 +92,6 @@ void exynos_plane_mode_set(struct drm_plane *plane, struct drm_crtc *crtc,
                          uint32_t src_w, uint32_t src_h)
 {
        struct exynos_drm_plane *exynos_plane = to_exynos_plane(plane);
-       struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
        unsigned int actual_w;
        unsigned int actual_h;
 
@@ -139,9 +138,6 @@ void exynos_plane_mode_set(struct drm_plane *plane, struct drm_crtc *crtc,
                        exynos_plane->crtc_width, exynos_plane->crtc_height);
 
        plane->crtc = crtc;
-
-       if (exynos_crtc->ops->win_mode_set)
-               exynos_crtc->ops->win_mode_set(exynos_crtc, exynos_plane);
 }
 
 int
@@ -184,11 +180,8 @@ static int exynos_disable_plane(struct drm_plane *plane)
 
 static void exynos_plane_destroy(struct drm_plane *plane)
 {
-       struct exynos_drm_plane *exynos_plane = to_exynos_plane(plane);
-
        exynos_disable_plane(plane);
        drm_plane_cleanup(plane);
-       kfree(exynos_plane);
 }
 
 static int exynos_plane_set_property(struct drm_plane *plane,
@@ -233,24 +226,18 @@ static void exynos_plane_attach_zpos_property(struct drm_plane *plane)
        drm_object_attach_property(&plane->base, prop, 0);
 }
 
-struct drm_plane *exynos_plane_init(struct drm_device *dev,
-                                   unsigned long possible_crtcs,
-                                   enum drm_plane_type type)
+int exynos_plane_init(struct drm_device *dev,
+                     struct exynos_drm_plane *exynos_plane,
+                     unsigned long possible_crtcs, enum drm_plane_type type)
 {
-       struct exynos_drm_plane *exynos_plane;
        int err;
 
-       exynos_plane = kzalloc(sizeof(struct exynos_drm_plane), GFP_KERNEL);
-       if (!exynos_plane)
-               return ERR_PTR(-ENOMEM);
-
        err = drm_universal_plane_init(dev, &exynos_plane->base, possible_crtcs,
                                       &exynos_plane_funcs, formats,
                                       ARRAY_SIZE(formats), type);
        if (err) {
                DRM_ERROR("failed to initialize plane\n");
-               kfree(exynos_plane);
-               return ERR_PTR(err);
+               return err;
        }
 
        if (type == DRM_PLANE_TYPE_PRIMARY)
@@ -258,5 +245,5 @@ struct drm_plane *exynos_plane_init(struct drm_device *dev,
        else
                exynos_plane_attach_zpos_property(&exynos_plane->base);
 
-       return &exynos_plane->base;
+       return 0;
 }
index 9d3c374..d8a3494 100644 (file)
@@ -20,6 +20,6 @@ int exynos_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
                        unsigned int crtc_w, unsigned int crtc_h,
                        uint32_t src_x, uint32_t src_y,
                        uint32_t src_w, uint32_t src_h);
-struct drm_plane *exynos_plane_init(struct drm_device *dev,
-                                   unsigned long possible_crtcs,
-                                   enum drm_plane_type type);
+int exynos_plane_init(struct drm_device *dev,
+                     struct exynos_drm_plane *exynos_plane,
+                     unsigned long possible_crtcs, enum drm_plane_type type);
index b886972..da5ee15 100644 (file)
@@ -23,6 +23,7 @@
 
 #include "exynos_drm_drv.h"
 #include "exynos_drm_crtc.h"
+#include "exynos_drm_plane.h"
 #include "exynos_drm_encoder.h"
 #include "exynos_drm_vidi.h"
 
 #define ctx_from_connector(c)  container_of(c, struct vidi_context, \
                                        connector)
 
-struct vidi_win_data {
-       unsigned int            offset_x;
-       unsigned int            offset_y;
-       unsigned int            ovl_width;
-       unsigned int            ovl_height;
-       unsigned int            fb_width;
-       unsigned int            fb_height;
-       unsigned int            bpp;
-       dma_addr_t              dma_addr;
-       unsigned int            buf_offsize;
-       unsigned int            line_size;      /* bytes */
-       bool                    enabled;
-};
-
 struct vidi_context {
        struct exynos_drm_display       display;
        struct platform_device          *pdev;
@@ -53,7 +40,7 @@ struct vidi_context {
        struct exynos_drm_crtc          *crtc;
        struct drm_encoder              *encoder;
        struct drm_connector            connector;
-       struct vidi_win_data            win_data[WINDOWS_NR];
+       struct exynos_drm_plane         planes[WINDOWS_NR];
        struct edid                     *raw_edid;
        unsigned int                    clkdiv;
        unsigned int                    default_win;
@@ -97,19 +84,6 @@ static const char fake_edid_info[] = {
        0x00, 0x00, 0x00, 0x06
 };
 
-static void vidi_apply(struct vidi_context *ctx)
-{
-       struct exynos_drm_crtc_ops *crtc_ops = ctx->crtc->ops;
-       struct vidi_win_data *win_data;
-       int i;
-
-       for (i = 0; i < WINDOWS_NR; i++) {
-               win_data = &ctx->win_data[i];
-               if (win_data->enabled && (crtc_ops && crtc_ops->win_commit))
-                       crtc_ops->win_commit(ctx->crtc, i);
-       }
-}
-
 static int vidi_enable_vblank(struct exynos_drm_crtc *crtc)
 {
        struct vidi_context *ctx = crtc->ctx;
@@ -143,63 +117,10 @@ static void vidi_disable_vblank(struct exynos_drm_crtc *crtc)
                ctx->vblank_on = false;
 }
 
-static void vidi_win_mode_set(struct exynos_drm_crtc *crtc,
-                       struct exynos_drm_plane *plane)
-{
-       struct vidi_context *ctx = crtc->ctx;
-       struct vidi_win_data *win_data;
-       int win;
-       unsigned long offset;
-
-       if (!plane) {
-               DRM_ERROR("plane is NULL\n");
-               return;
-       }
-
-       win = plane->zpos;
-       if (win == DEFAULT_ZPOS)
-               win = ctx->default_win;
-
-       if (win < 0 || win >= WINDOWS_NR)
-               return;
-
-       offset = plane->fb_x * (plane->bpp >> 3);
-       offset += plane->fb_y * plane->pitch;
-
-       DRM_DEBUG_KMS("offset = 0x%lx, pitch = %x\n", offset, plane->pitch);
-
-       win_data = &ctx->win_data[win];
-
-       win_data->offset_x = plane->crtc_x;
-       win_data->offset_y = plane->crtc_y;
-       win_data->ovl_width = plane->crtc_width;
-       win_data->ovl_height = plane->crtc_height;
-       win_data->fb_width = plane->fb_width;
-       win_data->fb_height = plane->fb_height;
-       win_data->dma_addr = plane->dma_addr[0] + offset;
-       win_data->bpp = plane->bpp;
-       win_data->buf_offsize = (plane->fb_width - plane->crtc_width) *
-                               (plane->bpp >> 3);
-       win_data->line_size = plane->crtc_width * (plane->bpp >> 3);
-
-       /*
-        * some parts of win_data should be transferred to user side
-        * through specific ioctl.
-        */
-
-       DRM_DEBUG_KMS("offset_x = %d, offset_y = %d\n",
-                       win_data->offset_x, win_data->offset_y);
-       DRM_DEBUG_KMS("ovl_width = %d, ovl_height = %d\n",
-                       win_data->ovl_width, win_data->ovl_height);
-       DRM_DEBUG_KMS("paddr = 0x%lx\n", (unsigned long)win_data->dma_addr);
-       DRM_DEBUG_KMS("fb_width = %d, crtc_width = %d\n",
-                       plane->fb_width, plane->crtc_width);
-}
-
 static void vidi_win_commit(struct exynos_drm_crtc *crtc, int zpos)
 {
        struct vidi_context *ctx = crtc->ctx;
-       struct vidi_win_data *win_data;
+       struct exynos_drm_plane *plane;
        int win = zpos;
 
        if (ctx->suspended)
@@ -211,11 +132,11 @@ static void vidi_win_commit(struct exynos_drm_crtc *crtc, int zpos)
        if (win < 0 || win >= WINDOWS_NR)
                return;
 
-       win_data = &ctx->win_data[win];
+       plane = &ctx->planes[win];
 
-       win_data->enabled = true;
+       plane->enabled = true;
 
-       DRM_DEBUG_KMS("dma_addr = %pad\n", &win_data->dma_addr);
+       DRM_DEBUG_KMS("dma_addr = %pad\n", plane->dma_addr);
 
        if (ctx->vblank_on)
                schedule_work(&ctx->work);
@@ -224,7 +145,7 @@ static void vidi_win_commit(struct exynos_drm_crtc *crtc, int zpos)
 static void vidi_win_disable(struct exynos_drm_crtc *crtc, int zpos)
 {
        struct vidi_context *ctx = crtc->ctx;
-       struct vidi_win_data *win_data;
+       struct exynos_drm_plane *plane;
        int win = zpos;
 
        if (win == DEFAULT_ZPOS)
@@ -233,14 +154,17 @@ static void vidi_win_disable(struct exynos_drm_crtc *crtc, int zpos)
        if (win < 0 || win >= WINDOWS_NR)
                return;
 
-       win_data = &ctx->win_data[win];
-       win_data->enabled = false;
+       plane = &ctx->planes[win];
+       plane->enabled = false;
 
        /* TODO. */
 }
 
 static int vidi_power_on(struct vidi_context *ctx, bool enable)
 {
+       struct exynos_drm_plane *plane;
+       int i;
+
        DRM_DEBUG_KMS("%s\n", __FILE__);
 
        if (enable != false && enable != true)
@@ -253,7 +177,11 @@ static int vidi_power_on(struct vidi_context *ctx, bool enable)
                if (test_and_clear_bit(0, &ctx->irq_flags))
                        vidi_enable_vblank(ctx->crtc);
 
-               vidi_apply(ctx);
+               for (i = 0; i < WINDOWS_NR; i++) {
+                       plane = &ctx->planes[i];
+                       if (plane->enabled)
+                               vidi_win_commit(ctx->crtc, i);
+               }
        } else {
                ctx->suspended = true;
        }
@@ -301,7 +229,6 @@ static struct exynos_drm_crtc_ops vidi_crtc_ops = {
        .dpms = vidi_dpms,
        .enable_vblank = vidi_enable_vblank,
        .disable_vblank = vidi_disable_vblank,
-       .win_mode_set = vidi_win_mode_set,
        .win_commit = vidi_win_commit,
        .win_disable = vidi_win_disable,
 };
@@ -543,12 +470,24 @@ static int vidi_bind(struct device *dev, struct device *master, void *data)
 {
        struct vidi_context *ctx = dev_get_drvdata(dev);
        struct drm_device *drm_dev = data;
-       int ret;
+       struct exynos_drm_plane *exynos_plane;
+       enum drm_plane_type type;
+       int zpos, ret;
 
        vidi_ctx_initialize(ctx, drm_dev);
 
-       ctx->crtc = exynos_drm_crtc_create(drm_dev, ctx->pipe,
-                                          EXYNOS_DISPLAY_TYPE_VIDI,
+       for (zpos = 0; zpos < WINDOWS_NR; zpos++) {
+               type = (zpos == ctx->default_win) ? DRM_PLANE_TYPE_PRIMARY :
+                                               DRM_PLANE_TYPE_OVERLAY;
+               ret = exynos_plane_init(drm_dev, &ctx->planes[zpos],
+                                       1 << ctx->pipe, type);
+               if (ret)
+                       return ret;
+       }
+
+       exynos_plane = &ctx->planes[ctx->default_win];
+       ctx->crtc = exynos_drm_crtc_create(drm_dev, &exynos_plane->base,
+                                          ctx->pipe, EXYNOS_DISPLAY_TYPE_VIDI,
                                           &vidi_crtc_ops, ctx);
        if (IS_ERR(ctx->crtc)) {
                DRM_ERROR("failed to create crtc.\n");
index 2e3bc57..d181cb1 100644 (file)
 
 #include "exynos_drm_drv.h"
 #include "exynos_drm_crtc.h"
+#include "exynos_drm_plane.h"
 #include "exynos_drm_iommu.h"
 #include "exynos_mixer.h"
 
 #define MIXER_WIN_NR           3
 #define MIXER_DEFAULT_WIN      0
 
-struct hdmi_win_data {
-       dma_addr_t              dma_addr;
-       dma_addr_t              chroma_dma_addr;
-       uint32_t                pixel_format;
-       unsigned int            bpp;
-       unsigned int            crtc_x;
-       unsigned int            crtc_y;
-       unsigned int            crtc_width;
-       unsigned int            crtc_height;
-       unsigned int            fb_x;
-       unsigned int            fb_y;
-       unsigned int            fb_width;
-       unsigned int            fb_pitch;
-       unsigned int            fb_height;
-       unsigned int            src_width;
-       unsigned int            src_height;
-       unsigned int            mode_width;
-       unsigned int            mode_height;
-       unsigned int            scan_flags;
-       bool                    enabled;
-       bool                    resume;
-};
-
 struct mixer_resources {
        int                     irq;
        void __iomem            *mixer_regs;
@@ -90,6 +68,7 @@ struct mixer_context {
        struct device           *dev;
        struct drm_device       *drm_dev;
        struct exynos_drm_crtc  *crtc;
+       struct exynos_drm_plane planes[MIXER_WIN_NR];
        int                     pipe;
        bool                    interlace;
        bool                    powered;
@@ -99,7 +78,6 @@ struct mixer_context {
 
        struct mutex            mixer_mutex;
        struct mixer_resources  mixer_res;
-       struct hdmi_win_data    win_data[MIXER_WIN_NR];
        enum mixer_version_id   mxr_ver;
        wait_queue_head_t       wait_vsync_queue;
        atomic_t                wait_vsync_event;
@@ -403,7 +381,7 @@ static void vp_video_buffer(struct mixer_context *ctx, int win)
 {
        struct mixer_resources *res = &ctx->mixer_res;
        unsigned long flags;
-       struct hdmi_win_data *win_data;
+       struct exynos_drm_plane *plane;
        unsigned int x_ratio, y_ratio;
        unsigned int buf_num = 1;
        dma_addr_t luma_addr[2], chroma_addr[2];
@@ -411,9 +389,9 @@ static void vp_video_buffer(struct mixer_context *ctx, int win)
        bool crcb_mode = false;
        u32 val;
 
-       win_data = &ctx->win_data[win];
+       plane = &ctx->planes[win];
 
-       switch (win_data->pixel_format) {
+       switch (plane->pixel_format) {
        case DRM_FORMAT_NV12:
                crcb_mode = false;
                buf_num = 2;
@@ -421,35 +399,35 @@ static void vp_video_buffer(struct mixer_context *ctx, int win)
        /* TODO: single buffer format NV12, NV21 */
        default:
                /* ignore pixel format at disable time */
-               if (!win_data->dma_addr)
+               if (!plane->dma_addr[0])
                        break;
 
                DRM_ERROR("pixel format for vp is wrong [%d].\n",
-                               win_data->pixel_format);
+                               plane->pixel_format);
                return;
        }
 
        /* scaling feature: (src << 16) / dst */
-       x_ratio = (win_data->src_width << 16) / win_data->crtc_width;
-       y_ratio = (win_data->src_height << 16) / win_data->crtc_height;
+       x_ratio = (plane->src_width << 16) / plane->crtc_width;
+       y_ratio = (plane->src_height << 16) / plane->crtc_height;
 
        if (buf_num == 2) {
-               luma_addr[0] = win_data->dma_addr;
-               chroma_addr[0] = win_data->chroma_dma_addr;
+               luma_addr[0] = plane->dma_addr[0];
+               chroma_addr[0] = plane->dma_addr[1];
        } else {
-               luma_addr[0] = win_data->dma_addr;
-               chroma_addr[0] = win_data->dma_addr
-                       + (win_data->fb_pitch * win_data->fb_height);
+               luma_addr[0] = plane->dma_addr[0];
+               chroma_addr[0] = plane->dma_addr[0]
+                       + (plane->pitch * plane->fb_height);
        }
 
-       if (win_data->scan_flags & DRM_MODE_FLAG_INTERLACE) {
+       if (plane->scan_flag & DRM_MODE_FLAG_INTERLACE) {
                ctx->interlace = true;
                if (tiled_mode) {
                        luma_addr[1] = luma_addr[0] + 0x40;
                        chroma_addr[1] = chroma_addr[0] + 0x40;
                } else {
-                       luma_addr[1] = luma_addr[0] + win_data->fb_pitch;
-                       chroma_addr[1] = chroma_addr[0] + win_data->fb_pitch;
+                       luma_addr[1] = luma_addr[0] + plane->pitch;
+                       chroma_addr[1] = chroma_addr[0] + plane->pitch;
                }
        } else {
                ctx->interlace = false;
@@ -470,26 +448,26 @@ static void vp_video_buffer(struct mixer_context *ctx, int win)
        vp_reg_writemask(res, VP_MODE, val, VP_MODE_FMT_MASK);
 
        /* setting size of input image */
-       vp_reg_write(res, VP_IMG_SIZE_Y, VP_IMG_HSIZE(win_data->fb_pitch) |
-               VP_IMG_VSIZE(win_data->fb_height));
+       vp_reg_write(res, VP_IMG_SIZE_Y, VP_IMG_HSIZE(plane->pitch) |
+               VP_IMG_VSIZE(plane->fb_height));
        /* chroma height has to reduced by 2 to avoid chroma distorions */
-       vp_reg_write(res, VP_IMG_SIZE_C, VP_IMG_HSIZE(win_data->fb_pitch) |
-               VP_IMG_VSIZE(win_data->fb_height / 2));
+       vp_reg_write(res, VP_IMG_SIZE_C, VP_IMG_HSIZE(plane->pitch) |
+               VP_IMG_VSIZE(plane->fb_height / 2));
 
-       vp_reg_write(res, VP_SRC_WIDTH, win_data->src_width);
-       vp_reg_write(res, VP_SRC_HEIGHT, win_data->src_height);
+       vp_reg_write(res, VP_SRC_WIDTH, plane->src_width);
+       vp_reg_write(res, VP_SRC_HEIGHT, plane->src_height);
        vp_reg_write(res, VP_SRC_H_POSITION,
-                       VP_SRC_H_POSITION_VAL(win_data->fb_x));
-       vp_reg_write(res, VP_SRC_V_POSITION, win_data->fb_y);
+                       VP_SRC_H_POSITION_VAL(plane->fb_x));
+       vp_reg_write(res, VP_SRC_V_POSITION, plane->fb_y);
 
-       vp_reg_write(res, VP_DST_WIDTH, win_data->crtc_width);
-       vp_reg_write(res, VP_DST_H_POSITION, win_data->crtc_x);
+       vp_reg_write(res, VP_DST_WIDTH, plane->crtc_width);
+       vp_reg_write(res, VP_DST_H_POSITION, plane->crtc_x);
        if (ctx->interlace) {
-               vp_reg_write(res, VP_DST_HEIGHT, win_data->crtc_height / 2);
-               vp_reg_write(res, VP_DST_V_POSITION, win_data->crtc_y / 2);
+               vp_reg_write(res, VP_DST_HEIGHT, plane->crtc_height / 2);
+               vp_reg_write(res, VP_DST_V_POSITION, plane->crtc_y / 2);
        } else {
-               vp_reg_write(res, VP_DST_HEIGHT, win_data->crtc_height);
-               vp_reg_write(res, VP_DST_V_POSITION, win_data->crtc_y);
+               vp_reg_write(res, VP_DST_HEIGHT, plane->crtc_height);
+               vp_reg_write(res, VP_DST_V_POSITION, plane->crtc_y);
        }
 
        vp_reg_write(res, VP_H_RATIO, x_ratio);
@@ -503,8 +481,8 @@ static void vp_video_buffer(struct mixer_context *ctx, int win)
        vp_reg_write(res, VP_TOP_C_PTR, chroma_addr[0]);
        vp_reg_write(res, VP_BOT_C_PTR, chroma_addr[1]);
 
-       mixer_cfg_scan(ctx, win_data->mode_height);
-       mixer_cfg_rgb_fmt(ctx, win_data->mode_height);
+       mixer_cfg_scan(ctx, plane->mode_height);
+       mixer_cfg_rgb_fmt(ctx, plane->mode_height);
        mixer_cfg_layer(ctx, win, true);
        mixer_run(ctx);
 
@@ -525,21 +503,21 @@ static void mixer_graph_buffer(struct mixer_context *ctx, int win)
 {
        struct mixer_resources *res = &ctx->mixer_res;
        unsigned long flags;
-       struct hdmi_win_data *win_data;
+       struct exynos_drm_plane *plane;
        unsigned int x_ratio, y_ratio;
        unsigned int src_x_offset, src_y_offset, dst_x_offset, dst_y_offset;
        dma_addr_t dma_addr;
        unsigned int fmt;
        u32 val;
 
-       win_data = &ctx->win_data[win];
+       plane = &ctx->planes[win];
 
        #define RGB565 4
        #define ARGB1555 5
        #define ARGB4444 6
        #define ARGB8888 7
 
-       switch (win_data->bpp) {
+       switch (plane->bpp) {
        case 16:
                fmt = ARGB4444;
                break;
@@ -554,17 +532,17 @@ static void mixer_graph_buffer(struct mixer_context *ctx, int win)
        x_ratio = 0;
        y_ratio = 0;
 
-       dst_x_offset = win_data->crtc_x;
-       dst_y_offset = win_data->crtc_y;
+       dst_x_offset = plane->crtc_x;
+       dst_y_offset = plane->crtc_y;
 
        /* converting dma address base and source offset */
-       dma_addr = win_data->dma_addr
-               + (win_data->fb_x * win_data->bpp >> 3)
-               + (win_data->fb_y * win_data->fb_pitch);
+       dma_addr = plane->dma_addr[0]
+               + (plane->fb_x * plane->bpp >> 3)
+               + (plane->fb_y * plane->pitch);
        src_x_offset = 0;
        src_y_offset = 0;
 
-       if (win_data->scan_flags & DRM_MODE_FLAG_INTERLACE)
+       if (plane->scan_flag & DRM_MODE_FLAG_INTERLACE)
                ctx->interlace = true;
        else
                ctx->interlace = false;
@@ -578,18 +556,18 @@ static void mixer_graph_buffer(struct mixer_context *ctx, int win)
 
        /* setup geometry */
        mixer_reg_write(res, MXR_GRAPHIC_SPAN(win),
-                       win_data->fb_pitch / (win_data->bpp >> 3));
+                       plane->pitch / (plane->bpp >> 3));
 
        /* setup display size */
        if (ctx->mxr_ver == MXR_VER_128_0_0_184 &&
                win == MIXER_DEFAULT_WIN) {
-               val  = MXR_MXR_RES_HEIGHT(win_data->mode_height);
-               val |= MXR_MXR_RES_WIDTH(win_data->mode_width);
+               val  = MXR_MXR_RES_HEIGHT(plane->mode_height);
+               val |= MXR_MXR_RES_WIDTH(plane->mode_width);
                mixer_reg_write(res, MXR_RESOLUTION, val);
        }
 
-       val  = MXR_GRP_WH_WIDTH(win_data->crtc_width);
-       val |= MXR_GRP_WH_HEIGHT(win_data->crtc_height);
+       val  = MXR_GRP_WH_WIDTH(plane->crtc_width);
+       val |= MXR_GRP_WH_HEIGHT(plane->crtc_height);
        val |= MXR_GRP_WH_H_SCALE(x_ratio);
        val |= MXR_GRP_WH_V_SCALE(y_ratio);
        mixer_reg_write(res, MXR_GRAPHIC_WH(win), val);
@@ -607,8 +585,8 @@ static void mixer_graph_buffer(struct mixer_context *ctx, int win)
        /* set buffer address to mixer */
        mixer_reg_write(res, MXR_GRAPHIC_BASE(win), dma_addr);
 
-       mixer_cfg_scan(ctx, win_data->mode_height);
-       mixer_cfg_rgb_fmt(ctx, win_data->mode_height);
+       mixer_cfg_scan(ctx, plane->mode_height);
+       mixer_cfg_rgb_fmt(ctx, plane->mode_height);
        mixer_cfg_layer(ctx, win, true);
 
        /* layer update mandatory for mixer 16.0.33.0 */
@@ -920,59 +898,6 @@ static void mixer_disable_vblank(struct exynos_drm_crtc *crtc)
        mixer_reg_writemask(res, MXR_INT_EN, 0, MXR_INT_EN_VSYNC);
 }
 
-static void mixer_win_mode_set(struct exynos_drm_crtc *crtc,
-                       struct exynos_drm_plane *plane)
-{
-       struct mixer_context *mixer_ctx = crtc->ctx;
-       struct hdmi_win_data *win_data;
-       int win;
-
-       if (!plane) {
-               DRM_ERROR("plane is NULL\n");
-               return;
-       }
-
-       DRM_DEBUG_KMS("set [%d]x[%d] at (%d,%d) to [%d]x[%d] at (%d,%d)\n",
-                                plane->fb_width, plane->fb_height,
-                                plane->fb_x, plane->fb_y,
-                                plane->crtc_width, plane->crtc_height,
-                                plane->crtc_x, plane->crtc_y);
-
-       win = plane->zpos;
-       if (win == DEFAULT_ZPOS)
-               win = MIXER_DEFAULT_WIN;
-
-       if (win < 0 || win >= MIXER_WIN_NR) {
-               DRM_ERROR("mixer window[%d] is wrong\n", win);
-               return;
-       }
-
-       win_data = &mixer_ctx->win_data[win];
-
-       win_data->dma_addr = plane->dma_addr[0];
-       win_data->chroma_dma_addr = plane->dma_addr[1];
-       win_data->pixel_format = plane->pixel_format;
-       win_data->bpp = plane->bpp;
-
-       win_data->crtc_x = plane->crtc_x;
-       win_data->crtc_y = plane->crtc_y;
-       win_data->crtc_width = plane->crtc_width;
-       win_data->crtc_height = plane->crtc_height;
-
-       win_data->fb_x = plane->fb_x;
-       win_data->fb_y = plane->fb_y;
-       win_data->fb_width = plane->fb_width;
-       win_data->fb_height = plane->fb_height;
-       win_data->fb_pitch = plane->pitch;
-       win_data->src_width = plane->src_width;
-       win_data->src_height = plane->src_height;
-
-       win_data->mode_width = plane->mode_width;
-       win_data->mode_height = plane->mode_height;
-
-       win_data->scan_flags = plane->scan_flag;
-}
-
 static void mixer_win_commit(struct exynos_drm_crtc *crtc, int zpos)
 {
        struct mixer_context *mixer_ctx = crtc->ctx;
@@ -992,7 +917,7 @@ static void mixer_win_commit(struct exynos_drm_crtc *crtc, int zpos)
        else
                mixer_graph_buffer(mixer_ctx, win);
 
-       mixer_ctx->win_data[win].enabled = true;
+       mixer_ctx->planes[win].enabled = true;
 }
 
 static void mixer_win_disable(struct exynos_drm_crtc *crtc, int zpos)
@@ -1007,7 +932,7 @@ static void mixer_win_disable(struct exynos_drm_crtc *crtc, int zpos)
        mutex_lock(&mixer_ctx->mixer_mutex);
        if (!mixer_ctx->powered) {
                mutex_unlock(&mixer_ctx->mixer_mutex);
-               mixer_ctx->win_data[win].resume = false;
+               mixer_ctx->planes[win].resume = false;
                return;
        }
        mutex_unlock(&mixer_ctx->mixer_mutex);
@@ -1020,7 +945,7 @@ static void mixer_win_disable(struct exynos_drm_crtc *crtc, int zpos)
        mixer_vsync_set_update(mixer_ctx, true);
        spin_unlock_irqrestore(&res->reg_slock, flags);
 
-       mixer_ctx->win_data[win].enabled = false;
+       mixer_ctx->planes[win].enabled = false;
 }
 
 static void mixer_wait_for_vblank(struct exynos_drm_crtc *crtc)
@@ -1057,12 +982,12 @@ static void mixer_wait_for_vblank(struct exynos_drm_crtc *crtc)
 
 static void mixer_window_suspend(struct mixer_context *ctx)
 {
-       struct hdmi_win_data *win_data;
+       struct exynos_drm_plane *plane;
        int i;
 
        for (i = 0; i < MIXER_WIN_NR; i++) {
-               win_data = &ctx->win_data[i];
-               win_data->resume = win_data->enabled;
+               plane = &ctx->planes[i];
+               plane->resume = plane->enabled;
                mixer_win_disable(ctx->crtc, i);
        }
        mixer_wait_for_vblank(ctx->crtc);
@@ -1070,14 +995,14 @@ static void mixer_window_suspend(struct mixer_context *ctx)
 
 static void mixer_window_resume(struct mixer_context *ctx)
 {
-       struct hdmi_win_data *win_data;
+       struct exynos_drm_plane *plane;
        int i;
 
        for (i = 0; i < MIXER_WIN_NR; i++) {
-               win_data = &ctx->win_data[i];
-               win_data->enabled = win_data->resume;
-               win_data->resume = false;
-               if (win_data->enabled)
+               plane = &ctx->planes[i];
+               plane->enabled = plane->resume;
+               plane->resume = false;
+               if (plane->enabled)
                        mixer_win_commit(ctx->crtc, i);
        }
 }
@@ -1189,7 +1114,6 @@ static struct exynos_drm_crtc_ops mixer_crtc_ops = {
        .enable_vblank          = mixer_enable_vblank,
        .disable_vblank         = mixer_disable_vblank,
        .wait_for_vblank        = mixer_wait_for_vblank,
-       .win_mode_set           = mixer_win_mode_set,
        .win_commit             = mixer_win_commit,
        .win_disable            = mixer_win_disable,
 };
@@ -1253,15 +1177,27 @@ static int mixer_bind(struct device *dev, struct device *manager, void *data)
 {
        struct mixer_context *ctx = dev_get_drvdata(dev);
        struct drm_device *drm_dev = data;
-       int ret;
+       struct exynos_drm_plane *exynos_plane;
+       enum drm_plane_type type;
+       int zpos, ret;
 
        ret = mixer_initialize(ctx, drm_dev);
        if (ret)
                return ret;
 
-       ctx->crtc = exynos_drm_crtc_create(drm_dev, ctx->pipe,
-                                    EXYNOS_DISPLAY_TYPE_HDMI,
-                                    &mixer_crtc_ops, ctx);
+       for (zpos = 0; zpos < MIXER_WIN_NR; zpos++) {
+               type = (zpos == MIXER_DEFAULT_WIN) ? DRM_PLANE_TYPE_PRIMARY :
+                                               DRM_PLANE_TYPE_OVERLAY;
+               ret = exynos_plane_init(drm_dev, &ctx->planes[zpos],
+                                       1 << ctx->pipe, type);
+               if (ret)
+                       return ret;
+       }
+
+       exynos_plane = &ctx->planes[MIXER_DEFAULT_WIN];
+       ctx->crtc = exynos_drm_crtc_create(drm_dev, &exynos_plane->base,
+                                          ctx->pipe, EXYNOS_DISPLAY_TYPE_HDMI,
+                                          &mixer_crtc_ops, ctx);
        if (IS_ERR(ctx->crtc)) {
                mixer_ctx_remove(ctx);
                ret = PTR_ERR(ctx->crtc);