drm/armada: move primary plane to separate file
authorRussell King <rmk+kernel@armlinux.org.uk>
Mon, 30 Jul 2018 10:52:34 +0000 (11:52 +0100)
committerRussell King <rmk+kernel@armlinux.org.uk>
Mon, 30 Jul 2018 10:52:34 +0000 (11:52 +0100)
Split out the primary plane support; this is now entirely separate from
the CRTC support.

Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
drivers/gpu/drm/armada/Makefile
drivers/gpu/drm/armada/armada_crtc.c
drivers/gpu/drm/armada/armada_crtc.h
drivers/gpu/drm/armada/armada_overlay.c
drivers/gpu/drm/armada/armada_plane.c [new file with mode: 0644]
drivers/gpu/drm/armada/armada_plane.h [new file with mode: 0644]

index ecf25cf9f9f59a222700ab9cd72ca2776cc66bed..9bc3c321372480c3615e320aff5bc47ff2b3fb78 100644 (file)
@@ -1,6 +1,6 @@
 # SPDX-License-Identifier: GPL-2.0
 armada-y       := armada_crtc.o armada_drv.o armada_fb.o armada_fbdev.o \
-                  armada_gem.o armada_overlay.o armada_trace.o
+                  armada_gem.o armada_overlay.o armada_plane.o armada_trace.o
 armada-y       += armada_510.o
 armada-$(CONFIG_DEBUG_FS) += armada_debugfs.o
 
index 14339d5bed149478485167d3dab66521f06660ba..b9b0a508793d3dc59d8e645268524cd530efd39e 100644 (file)
@@ -20,6 +20,7 @@
 #include "armada_fb.h"
 #include "armada_gem.h"
 #include "armada_hw.h"
+#include "armada_plane.h"
 #include "armada_trace.h"
 
 enum csc_mode {
@@ -30,23 +31,6 @@ enum csc_mode {
        CSC_RGB_STUDIO = 2,
 };
 
-static const uint32_t armada_primary_formats[] = {
-       DRM_FORMAT_UYVY,
-       DRM_FORMAT_YUYV,
-       DRM_FORMAT_VYUY,
-       DRM_FORMAT_YVYU,
-       DRM_FORMAT_ARGB8888,
-       DRM_FORMAT_ABGR8888,
-       DRM_FORMAT_XRGB8888,
-       DRM_FORMAT_XBGR8888,
-       DRM_FORMAT_RGB888,
-       DRM_FORMAT_BGR888,
-       DRM_FORMAT_ARGB1555,
-       DRM_FORMAT_ABGR1555,
-       DRM_FORMAT_RGB565,
-       DRM_FORMAT_BGR565,
-};
-
 /*
  * A note about interlacing.  Let's consider HDMI 1920x1080i.
  * The timing parameters we have from X are:
@@ -160,57 +144,6 @@ static void armada_drm_crtc_update(struct armada_crtc *dcrtc)
        }
 }
 
-void armada_drm_plane_calc_addrs(u32 *addrs, struct drm_framebuffer *fb,
-       int x, int y)
-{
-       const struct drm_format_info *format = fb->format;
-       unsigned int num_planes = format->num_planes;
-       u32 addr = drm_fb_obj(fb)->dev_addr;
-       int i;
-
-       if (num_planes > 3)
-               num_planes = 3;
-
-       addrs[0] = addr + fb->offsets[0] + y * fb->pitches[0] +
-                  x * format->cpp[0];
-
-       y /= format->vsub;
-       x /= format->hsub;
-
-       for (i = 1; i < num_planes; i++)
-               addrs[i] = addr + fb->offsets[i] + y * fb->pitches[i] +
-                            x * format->cpp[i];
-       for (; i < 3; i++)
-               addrs[i] = 0;
-}
-
-static unsigned armada_drm_crtc_calc_fb(struct drm_framebuffer *fb,
-       int x, int y, struct armada_regs *regs, bool interlaced)
-{
-       unsigned pitch = fb->pitches[0];
-       u32 addrs[3], addr_odd, addr_even;
-       unsigned i = 0;
-
-       DRM_DEBUG_DRIVER("pitch %u x %d y %d bpp %d\n",
-               pitch, x, y, fb->format->cpp[0] * 8);
-
-       armada_drm_plane_calc_addrs(addrs, fb, x, y);
-
-       addr_odd = addr_even = addrs[0];
-
-       if (interlaced) {
-               addr_even += pitch;
-               pitch *= 2;
-       }
-
-       /* write offset, base, and pitch */
-       armada_reg_queue_set(regs, i, addr_odd, LCD_CFG_GRA_START_ADDR0);
-       armada_reg_queue_set(regs, i, addr_even, LCD_CFG_GRA_START_ADDR1);
-       armada_reg_queue_mod(regs, i, pitch, 0xffff, LCD_CFG_GRA_PITCH);
-
-       return i;
-}
-
 static void armada_drm_plane_work_call(struct armada_crtc *dcrtc,
        struct armada_plane_work *work,
        void (*fn)(struct armada_crtc *, struct armada_plane_work *))
@@ -1067,194 +1000,6 @@ static const struct drm_crtc_funcs armada_crtc_funcs = {
        .disable_vblank = armada_drm_crtc_disable_vblank,
 };
 
-int armada_drm_plane_prepare_fb(struct drm_plane *plane,
-       struct drm_plane_state *state)
-{
-       DRM_DEBUG_KMS("[PLANE:%d:%s] [FB:%d]\n",
-               plane->base.id, plane->name,
-               state->fb ? state->fb->base.id : 0);
-
-       /*
-        * Take a reference on the new framebuffer - we want to
-        * hold on to it while the hardware is displaying it.
-        */
-       if (state->fb)
-               drm_framebuffer_get(state->fb);
-       return 0;
-}
-
-void armada_drm_plane_cleanup_fb(struct drm_plane *plane,
-       struct drm_plane_state *old_state)
-{
-       DRM_DEBUG_KMS("[PLANE:%d:%s] [FB:%d]\n",
-               plane->base.id, plane->name,
-               old_state->fb ? old_state->fb->base.id : 0);
-
-       if (old_state->fb)
-               drm_framebuffer_put(old_state->fb);
-}
-
-int armada_drm_plane_atomic_check(struct drm_plane *plane,
-       struct drm_plane_state *state)
-{
-       if (state->fb && !WARN_ON(!state->crtc)) {
-               struct drm_crtc *crtc = state->crtc;
-               struct drm_crtc_state *crtc_state;
-
-               if (state->state)
-                       crtc_state = drm_atomic_get_existing_crtc_state(state->state, crtc);
-               else
-                       crtc_state = crtc->state;
-               return drm_atomic_helper_check_plane_state(state, crtc_state,
-                                                          0, INT_MAX,
-                                                          true, false);
-       } else {
-               state->visible = false;
-       }
-       return 0;
-}
-
-static void armada_drm_primary_plane_atomic_update(struct drm_plane *plane,
-       struct drm_plane_state *old_state)
-{
-       struct drm_plane_state *state = plane->state;
-       struct armada_crtc *dcrtc;
-       struct armada_regs *regs;
-       u32 cfg, cfg_mask, val;
-       unsigned int idx;
-
-       DRM_DEBUG_KMS("[PLANE:%d:%s]\n", plane->base.id, plane->name);
-
-       if (!state->fb || WARN_ON(!state->crtc))
-               return;
-
-       DRM_DEBUG_KMS("[PLANE:%d:%s] is on [CRTC:%d:%s] with [FB:%d] visible %u->%u\n",
-               plane->base.id, plane->name,
-               state->crtc->base.id, state->crtc->name,
-               state->fb->base.id,
-               old_state->visible, state->visible);
-
-       dcrtc = drm_to_armada_crtc(state->crtc);
-       regs = dcrtc->regs + dcrtc->regs_idx;
-
-       idx = 0;
-       if (!old_state->visible && state->visible) {
-               val = CFG_PDWN64x66;
-               if (drm_fb_to_armada_fb(state->fb)->fmt > CFG_420)
-                       val |= CFG_PDWN256x24;
-               armada_reg_queue_mod(regs, idx, 0, val, LCD_SPU_SRAM_PARA1);
-       }
-       val = armada_rect_hw_fp(&state->src);
-       if (armada_rect_hw_fp(&old_state->src) != val)
-               armada_reg_queue_set(regs, idx, val, LCD_SPU_GRA_HPXL_VLN);
-       val = armada_rect_yx(&state->dst);
-       if (armada_rect_yx(&old_state->dst) != val)
-               armada_reg_queue_set(regs, idx, val, LCD_SPU_GRA_OVSA_HPXL_VLN);
-       val = armada_rect_hw(&state->dst);
-       if (armada_rect_hw(&old_state->dst) != val)
-               armada_reg_queue_set(regs, idx, val, LCD_SPU_GZM_HPXL_VLN);
-       if (old_state->src.x1 != state->src.x1 ||
-           old_state->src.y1 != state->src.y1 ||
-           old_state->fb != state->fb) {
-               idx += armada_drm_crtc_calc_fb(state->fb,
-                                              state->src.x1 >> 16,
-                                              state->src.y1 >> 16,
-                                              regs + idx,
-                                              dcrtc->interlaced);
-       }
-       if (old_state->fb != state->fb) {
-               cfg = CFG_GRA_FMT(drm_fb_to_armada_fb(state->fb)->fmt) |
-                     CFG_GRA_MOD(drm_fb_to_armada_fb(state->fb)->mod);
-               if (drm_fb_to_armada_fb(state->fb)->fmt > CFG_420)
-                       cfg |= CFG_PALETTE_ENA;
-               if (state->visible)
-                       cfg |= CFG_GRA_ENA;
-               if (dcrtc->interlaced)
-                       cfg |= CFG_GRA_FTOGGLE;
-               cfg_mask = CFG_GRAFORMAT |
-                          CFG_GRA_MOD(CFG_SWAPRB | CFG_SWAPUV |
-                                      CFG_SWAPYU | CFG_YUV2RGB) |
-                          CFG_PALETTE_ENA | CFG_GRA_FTOGGLE |
-                          CFG_GRA_ENA;
-       } else if (old_state->visible != state->visible) {
-               cfg = state->visible ? CFG_GRA_ENA : 0;
-               cfg_mask = CFG_GRA_ENA;
-       } else {
-               cfg = cfg_mask = 0;
-       }
-       if (drm_rect_width(&old_state->src) != drm_rect_width(&state->src) ||
-           drm_rect_width(&old_state->dst) != drm_rect_width(&state->dst)) {
-               cfg_mask |= CFG_GRA_HSMOOTH;
-               if (drm_rect_width(&state->src) >> 16 !=
-                   drm_rect_width(&state->dst))
-                       cfg |= CFG_GRA_HSMOOTH;
-       }
-
-       if (cfg_mask)
-               armada_reg_queue_mod(regs, idx, cfg, cfg_mask,
-                                    LCD_SPU_DMA_CTRL0);
-
-       dcrtc->regs_idx += idx;
-}
-
-static void armada_drm_primary_plane_atomic_disable(struct drm_plane *plane,
-       struct drm_plane_state *old_state)
-{
-       struct armada_crtc *dcrtc;
-       struct armada_regs *regs;
-       unsigned int idx = 0;
-
-       DRM_DEBUG_KMS("[PLANE:%d:%s]\n", plane->base.id, plane->name);
-
-       if (!old_state->crtc)
-               return;
-
-       DRM_DEBUG_KMS("[PLANE:%d:%s] was on [CRTC:%d:%s] with [FB:%d]\n",
-               plane->base.id, plane->name,
-               old_state->crtc->base.id, old_state->crtc->name,
-               old_state->fb->base.id);
-
-       dcrtc = drm_to_armada_crtc(old_state->crtc);
-       regs = dcrtc->regs + dcrtc->regs_idx;
-
-       /* Disable plane and power down most RAMs and FIFOs */
-       armada_reg_queue_mod(regs, idx, 0, CFG_GRA_ENA, LCD_SPU_DMA_CTRL0);
-       armada_reg_queue_mod(regs, idx, CFG_PDWN256x32 | CFG_PDWN256x24 |
-                            CFG_PDWN256x8 | CFG_PDWN32x32 | CFG_PDWN64x66,
-                            0, LCD_SPU_SRAM_PARA1);
-
-       dcrtc->regs_idx += idx;
-}
-
-static const struct drm_plane_helper_funcs armada_primary_plane_helper_funcs = {
-       .prepare_fb     = armada_drm_plane_prepare_fb,
-       .cleanup_fb     = armada_drm_plane_cleanup_fb,
-       .atomic_check   = armada_drm_plane_atomic_check,
-       .atomic_update  = armada_drm_primary_plane_atomic_update,
-       .atomic_disable = armada_drm_primary_plane_atomic_disable,
-};
-
-static const struct drm_plane_funcs armada_primary_plane_funcs = {
-       .update_plane   = drm_plane_helper_update,
-       .disable_plane  = drm_plane_helper_disable,
-       .destroy        = drm_primary_helper_destroy,
-       .reset          = drm_atomic_helper_plane_reset,
-       .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
-       .atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
-};
-
-int armada_drm_plane_init(struct armada_plane *plane)
-{
-       unsigned int i;
-
-       for (i = 0; i < ARRAY_SIZE(plane->works); i++)
-               plane->works[i].plane = &plane->base;
-
-       init_waitqueue_head(&plane->frame_wait);
-
-       return 0;
-}
-
 static const struct drm_prop_enum_list armada_drm_csc_yuv_enum_list[] = {
        { CSC_AUTO,        "Auto" },
        { CSC_YUV_CCIR601, "CCIR601" },
@@ -1363,21 +1108,7 @@ static int armada_drm_crtc_create(struct drm_device *drm, struct device *dev,
                goto err_crtc;
        }
 
-       ret = armada_drm_plane_init(primary);
-       if (ret) {
-               kfree(primary);
-               goto err_crtc;
-       }
-
-       drm_plane_helper_add(&primary->base,
-                            &armada_primary_plane_helper_funcs);
-
-       ret = drm_universal_plane_init(drm, &primary->base, 0,
-                                      &armada_primary_plane_funcs,
-                                      armada_primary_formats,
-                                      ARRAY_SIZE(armada_primary_formats),
-                                      NULL,
-                                      DRM_PLANE_TYPE_PRIMARY, NULL);
+       ret = armada_drm_primary_plane_init(drm, primary);
        if (ret) {
                kfree(primary);
                goto err_crtc;
index 79ac0db047c9e68395656c9225afb7c37b041a7e..2672c5cc0e4552a1d71c5be6b73f7ea2a16a36dd 100644 (file)
@@ -54,21 +54,11 @@ struct armada_plane {
 };
 #define drm_to_armada_plane(p) container_of(p, struct armada_plane, base)
 
-int armada_drm_plane_init(struct armada_plane *plane);
 int armada_drm_plane_work_queue(struct armada_crtc *dcrtc,
        struct armada_plane_work *work);
 int armada_drm_plane_work_wait(struct armada_plane *plane, long timeout);
 void armada_drm_plane_work_cancel(struct armada_crtc *dcrtc,
        struct armada_plane *plane);
-void armada_drm_plane_calc_addrs(u32 *addrs, struct drm_framebuffer *fb,
-       int x, int y);
-
-int armada_drm_plane_prepare_fb(struct drm_plane *plane,
-       struct drm_plane_state *state);
-void armada_drm_plane_cleanup_fb(struct drm_plane *plane,
-       struct drm_plane_state *old_state);
-int armada_drm_plane_atomic_check(struct drm_plane *plane,
-       struct drm_plane_state *state);
 
 struct armada_crtc {
        struct drm_crtc         crtc;
index aa2a12aec3cc58661a4a1e214238bc805a8b0bd7..214b2171a8f45c061f1d7210e27e23f2c9e16816 100644 (file)
 #include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_plane_helper.h>
+#include <drm/armada_drm.h>
 #include "armada_crtc.h"
 #include "armada_drm.h"
 #include "armada_fb.h"
 #include "armada_gem.h"
 #include "armada_hw.h"
-#include <drm/armada_drm.h>
 #include "armada_ioctlP.h"
+#include "armada_plane.h"
 #include "armada_trace.h"
 
 struct armada_ovl_plane_properties {
diff --git a/drivers/gpu/drm/armada/armada_plane.c b/drivers/gpu/drm/armada/armada_plane.c
new file mode 100644 (file)
index 0000000..9d1eec1
--- /dev/null
@@ -0,0 +1,297 @@
+/*
+ * Copyright (C) 2012 Russell King
+ *  Rewritten from the dovefb driver, and Armada510 manuals.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <drm/drmP.h>
+#include <drm/drm_atomic.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_plane_helper.h>
+#include "armada_crtc.h"
+#include "armada_drm.h"
+#include "armada_fb.h"
+#include "armada_gem.h"
+#include "armada_hw.h"
+#include "armada_plane.h"
+#include "armada_trace.h"
+
+static const uint32_t armada_primary_formats[] = {
+       DRM_FORMAT_UYVY,
+       DRM_FORMAT_YUYV,
+       DRM_FORMAT_VYUY,
+       DRM_FORMAT_YVYU,
+       DRM_FORMAT_ARGB8888,
+       DRM_FORMAT_ABGR8888,
+       DRM_FORMAT_XRGB8888,
+       DRM_FORMAT_XBGR8888,
+       DRM_FORMAT_RGB888,
+       DRM_FORMAT_BGR888,
+       DRM_FORMAT_ARGB1555,
+       DRM_FORMAT_ABGR1555,
+       DRM_FORMAT_RGB565,
+       DRM_FORMAT_BGR565,
+};
+
+void armada_drm_plane_calc_addrs(u32 *addrs, struct drm_framebuffer *fb,
+       int x, int y)
+{
+       const struct drm_format_info *format = fb->format;
+       unsigned int num_planes = format->num_planes;
+       u32 addr = drm_fb_obj(fb)->dev_addr;
+       int i;
+
+       if (num_planes > 3)
+               num_planes = 3;
+
+       addrs[0] = addr + fb->offsets[0] + y * fb->pitches[0] +
+                  x * format->cpp[0];
+
+       y /= format->vsub;
+       x /= format->hsub;
+
+       for (i = 1; i < num_planes; i++)
+               addrs[i] = addr + fb->offsets[i] + y * fb->pitches[i] +
+                            x * format->cpp[i];
+       for (; i < 3; i++)
+               addrs[i] = 0;
+}
+
+static unsigned armada_drm_crtc_calc_fb(struct drm_framebuffer *fb,
+       int x, int y, struct armada_regs *regs, bool interlaced)
+{
+       unsigned pitch = fb->pitches[0];
+       u32 addrs[3], addr_odd, addr_even;
+       unsigned i = 0;
+
+       DRM_DEBUG_DRIVER("pitch %u x %d y %d bpp %d\n",
+               pitch, x, y, fb->format->cpp[0] * 8);
+
+       armada_drm_plane_calc_addrs(addrs, fb, x, y);
+
+       addr_odd = addr_even = addrs[0];
+
+       if (interlaced) {
+               addr_even += pitch;
+               pitch *= 2;
+       }
+
+       /* write offset, base, and pitch */
+       armada_reg_queue_set(regs, i, addr_odd, LCD_CFG_GRA_START_ADDR0);
+       armada_reg_queue_set(regs, i, addr_even, LCD_CFG_GRA_START_ADDR1);
+       armada_reg_queue_mod(regs, i, pitch, 0xffff, LCD_CFG_GRA_PITCH);
+
+       return i;
+}
+
+int armada_drm_plane_prepare_fb(struct drm_plane *plane,
+       struct drm_plane_state *state)
+{
+       DRM_DEBUG_KMS("[PLANE:%d:%s] [FB:%d]\n",
+               plane->base.id, plane->name,
+               state->fb ? state->fb->base.id : 0);
+
+       /*
+        * Take a reference on the new framebuffer - we want to
+        * hold on to it while the hardware is displaying it.
+        */
+       if (state->fb)
+               drm_framebuffer_get(state->fb);
+       return 0;
+}
+
+void armada_drm_plane_cleanup_fb(struct drm_plane *plane,
+       struct drm_plane_state *old_state)
+{
+       DRM_DEBUG_KMS("[PLANE:%d:%s] [FB:%d]\n",
+               plane->base.id, plane->name,
+               old_state->fb ? old_state->fb->base.id : 0);
+
+       if (old_state->fb)
+               drm_framebuffer_put(old_state->fb);
+}
+
+int armada_drm_plane_atomic_check(struct drm_plane *plane,
+       struct drm_plane_state *state)
+{
+       if (state->fb && !WARN_ON(!state->crtc)) {
+               struct drm_crtc *crtc = state->crtc;
+               struct drm_crtc_state *crtc_state;
+
+               if (state->state)
+                       crtc_state = drm_atomic_get_existing_crtc_state(state->state, crtc);
+               else
+                       crtc_state = crtc->state;
+               return drm_atomic_helper_check_plane_state(state, crtc_state,
+                                                          0, INT_MAX,
+                                                          true, false);
+       } else {
+               state->visible = false;
+       }
+       return 0;
+}
+
+static void armada_drm_primary_plane_atomic_update(struct drm_plane *plane,
+       struct drm_plane_state *old_state)
+{
+       struct drm_plane_state *state = plane->state;
+       struct armada_crtc *dcrtc;
+       struct armada_regs *regs;
+       u32 cfg, cfg_mask, val;
+       unsigned int idx;
+
+       DRM_DEBUG_KMS("[PLANE:%d:%s]\n", plane->base.id, plane->name);
+
+       if (!state->fb || WARN_ON(!state->crtc))
+               return;
+
+       DRM_DEBUG_KMS("[PLANE:%d:%s] is on [CRTC:%d:%s] with [FB:%d] visible %u->%u\n",
+               plane->base.id, plane->name,
+               state->crtc->base.id, state->crtc->name,
+               state->fb->base.id,
+               old_state->visible, state->visible);
+
+       dcrtc = drm_to_armada_crtc(state->crtc);
+       regs = dcrtc->regs + dcrtc->regs_idx;
+
+       idx = 0;
+       if (!old_state->visible && state->visible) {
+               val = CFG_PDWN64x66;
+               if (drm_fb_to_armada_fb(state->fb)->fmt > CFG_420)
+                       val |= CFG_PDWN256x24;
+               armada_reg_queue_mod(regs, idx, 0, val, LCD_SPU_SRAM_PARA1);
+       }
+       val = armada_rect_hw_fp(&state->src);
+       if (armada_rect_hw_fp(&old_state->src) != val)
+               armada_reg_queue_set(regs, idx, val, LCD_SPU_GRA_HPXL_VLN);
+       val = armada_rect_yx(&state->dst);
+       if (armada_rect_yx(&old_state->dst) != val)
+               armada_reg_queue_set(regs, idx, val, LCD_SPU_GRA_OVSA_HPXL_VLN);
+       val = armada_rect_hw(&state->dst);
+       if (armada_rect_hw(&old_state->dst) != val)
+               armada_reg_queue_set(regs, idx, val, LCD_SPU_GZM_HPXL_VLN);
+       if (old_state->src.x1 != state->src.x1 ||
+           old_state->src.y1 != state->src.y1 ||
+           old_state->fb != state->fb) {
+               idx += armada_drm_crtc_calc_fb(state->fb,
+                                              state->src.x1 >> 16,
+                                              state->src.y1 >> 16,
+                                              regs + idx,
+                                              dcrtc->interlaced);
+       }
+       if (old_state->fb != state->fb) {
+               cfg = CFG_GRA_FMT(drm_fb_to_armada_fb(state->fb)->fmt) |
+                     CFG_GRA_MOD(drm_fb_to_armada_fb(state->fb)->mod);
+               if (drm_fb_to_armada_fb(state->fb)->fmt > CFG_420)
+                       cfg |= CFG_PALETTE_ENA;
+               if (state->visible)
+                       cfg |= CFG_GRA_ENA;
+               if (dcrtc->interlaced)
+                       cfg |= CFG_GRA_FTOGGLE;
+               cfg_mask = CFG_GRAFORMAT |
+                          CFG_GRA_MOD(CFG_SWAPRB | CFG_SWAPUV |
+                                      CFG_SWAPYU | CFG_YUV2RGB) |
+                          CFG_PALETTE_ENA | CFG_GRA_FTOGGLE |
+                          CFG_GRA_ENA;
+       } else if (old_state->visible != state->visible) {
+               cfg = state->visible ? CFG_GRA_ENA : 0;
+               cfg_mask = CFG_GRA_ENA;
+       } else {
+               cfg = cfg_mask = 0;
+       }
+       if (drm_rect_width(&old_state->src) != drm_rect_width(&state->src) ||
+           drm_rect_width(&old_state->dst) != drm_rect_width(&state->dst)) {
+               cfg_mask |= CFG_GRA_HSMOOTH;
+               if (drm_rect_width(&state->src) >> 16 !=
+                   drm_rect_width(&state->dst))
+                       cfg |= CFG_GRA_HSMOOTH;
+       }
+
+       if (cfg_mask)
+               armada_reg_queue_mod(regs, idx, cfg, cfg_mask,
+                                    LCD_SPU_DMA_CTRL0);
+
+       dcrtc->regs_idx += idx;
+}
+
+static void armada_drm_primary_plane_atomic_disable(struct drm_plane *plane,
+       struct drm_plane_state *old_state)
+{
+       struct armada_crtc *dcrtc;
+       struct armada_regs *regs;
+       unsigned int idx = 0;
+
+       DRM_DEBUG_KMS("[PLANE:%d:%s]\n", plane->base.id, plane->name);
+
+       if (!old_state->crtc)
+               return;
+
+       DRM_DEBUG_KMS("[PLANE:%d:%s] was on [CRTC:%d:%s] with [FB:%d]\n",
+               plane->base.id, plane->name,
+               old_state->crtc->base.id, old_state->crtc->name,
+               old_state->fb->base.id);
+
+       dcrtc = drm_to_armada_crtc(old_state->crtc);
+       regs = dcrtc->regs + dcrtc->regs_idx;
+
+       /* Disable plane and power down most RAMs and FIFOs */
+       armada_reg_queue_mod(regs, idx, 0, CFG_GRA_ENA, LCD_SPU_DMA_CTRL0);
+       armada_reg_queue_mod(regs, idx, CFG_PDWN256x32 | CFG_PDWN256x24 |
+                            CFG_PDWN256x8 | CFG_PDWN32x32 | CFG_PDWN64x66,
+                            0, LCD_SPU_SRAM_PARA1);
+
+       dcrtc->regs_idx += idx;
+}
+
+static const struct drm_plane_helper_funcs armada_primary_plane_helper_funcs = {
+       .prepare_fb     = armada_drm_plane_prepare_fb,
+       .cleanup_fb     = armada_drm_plane_cleanup_fb,
+       .atomic_check   = armada_drm_plane_atomic_check,
+       .atomic_update  = armada_drm_primary_plane_atomic_update,
+       .atomic_disable = armada_drm_primary_plane_atomic_disable,
+};
+
+static const struct drm_plane_funcs armada_primary_plane_funcs = {
+       .update_plane   = drm_plane_helper_update,
+       .disable_plane  = drm_plane_helper_disable,
+       .destroy        = drm_primary_helper_destroy,
+       .reset          = drm_atomic_helper_plane_reset,
+       .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
+       .atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
+};
+
+int armada_drm_plane_init(struct armada_plane *plane)
+{
+       unsigned int i;
+
+       for (i = 0; i < ARRAY_SIZE(plane->works); i++)
+               plane->works[i].plane = &plane->base;
+
+       init_waitqueue_head(&plane->frame_wait);
+
+       return 0;
+}
+
+int armada_drm_primary_plane_init(struct drm_device *drm,
+       struct armada_plane *primary)
+{
+       int ret;
+
+       ret = armada_drm_plane_init(primary);
+       if (ret)
+               return ret;
+
+       drm_plane_helper_add(&primary->base,
+                            &armada_primary_plane_helper_funcs);
+
+       ret = drm_universal_plane_init(drm, &primary->base, 0,
+                                      &armada_primary_plane_funcs,
+                                      armada_primary_formats,
+                                      ARRAY_SIZE(armada_primary_formats),
+                                      NULL,
+                                      DRM_PLANE_TYPE_PRIMARY, NULL);
+
+       return ret;
+}
diff --git a/drivers/gpu/drm/armada/armada_plane.h b/drivers/gpu/drm/armada/armada_plane.h
new file mode 100644 (file)
index 0000000..3c83160
--- /dev/null
@@ -0,0 +1,16 @@
+#ifndef ARMADA_PLANE_H
+#define ARMADA_PLANE_H
+
+void armada_drm_plane_calc_addrs(u32 *addrs, struct drm_framebuffer *fb,
+       int x, int y);
+int armada_drm_plane_prepare_fb(struct drm_plane *plane,
+       struct drm_plane_state *state);
+void armada_drm_plane_cleanup_fb(struct drm_plane *plane,
+       struct drm_plane_state *old_state);
+int armada_drm_plane_atomic_check(struct drm_plane *plane,
+       struct drm_plane_state *state);
+int armada_drm_plane_init(struct armada_plane *plane);
+int armada_drm_primary_plane_init(struct drm_device *drm,
+       struct armada_plane *primary);
+
+#endif