[PATCH RFC v3 2/4] DRM: Armada: Add support for hardware cursors

2013-06-11 Thread Russell King
This patch adds hardware cursor support to the DRM driver for the
Marvell Armada SoCs.

Signed-off-by: Russell King 
---
 drivers/gpu/drm/armada/Kconfig   |7 +
 drivers/gpu/drm/armada/armada_crtc.c |  201 ++
 drivers/gpu/drm/armada/armada_crtc.h |8 ++
 3 files changed, 216 insertions(+), 0 deletions(-)

diff --git a/drivers/gpu/drm/armada/Kconfig b/drivers/gpu/drm/armada/Kconfig
index c7a0a94..6f64642 100644
--- a/drivers/gpu/drm/armada/Kconfig
+++ b/drivers/gpu/drm/armada/Kconfig
@@ -13,3 +13,10 @@ config DRM_ARMADA
  This driver provides no built-in acceleration; acceleration is
  performed by other IP found on the SoC.  This driver provides
  kernel mode setting and buffer management to userspace.
+
+config DRM_ARMADA_CURSOR
+   bool "Enable hardware cursor support for Marvell Armada DRM"
+   depends on DRM_ARMADA != n
+   help
+ Add support for hardware cursor support on the Marvell
+ Armada devices.
diff --git a/drivers/gpu/drm/armada/armada_crtc.c 
b/drivers/gpu/drm/armada/armada_crtc.c
index dadaf63..4a71ba0 100644
--- a/drivers/gpu/drm/armada/armada_crtc.c
+++ b/drivers/gpu/drm/armada/armada_crtc.c
@@ -626,11 +626,210 @@ static const struct drm_crtc_helper_funcs 
armada_crtc_helper_funcs = {
.disable= armada_drm_crtc_disable,
 };

+#ifdef CONFIG_DRM_ARMADA_CURSOR
+static int armada_drm_crtc_cursor_update(struct armada_crtc *dcrtc, bool 
reload)
+{
+   uint32_t xoff, xscr, w = dcrtc->cursor_w, s;
+   uint32_t yoff, yscr, h = dcrtc->cursor_h;
+
+   /*
+* Calculate the visible width and height of the cursor,
+* screen position, and the position in the cursor bitmap.
+*/
+   if (dcrtc->cursor_x < 0) {
+   xoff = -dcrtc->cursor_x;
+   xscr = 0;
+   w -= min(xoff, w);
+   } else if (dcrtc->cursor_x + w > dcrtc->crtc.mode.hdisplay) {
+   xoff = 0;
+   xscr = dcrtc->cursor_x;
+   w = max_t(int, dcrtc->crtc.mode.hdisplay - dcrtc->cursor_x, 0);
+   } else {
+   xoff = 0;
+   xscr = dcrtc->cursor_x;
+   }
+
+   if (dcrtc->cursor_y < 0) {
+   yoff = -dcrtc->cursor_y;
+   yscr = 0;
+   h -= min(yoff, h);
+   } else if (dcrtc->cursor_y + h > dcrtc->crtc.mode.vdisplay) {
+   yoff = 0;
+   yscr = dcrtc->cursor_y;
+   h = max_t(int, dcrtc->crtc.mode.vdisplay - dcrtc->cursor_y, 0);
+   } else {
+   yoff = 0;
+   yscr = dcrtc->cursor_y;
+   }
+
+   /* On interlaced modes, the vertical cursor size must be halved */
+   s = dcrtc->cursor_w;
+   if (dcrtc->interlaced) {
+   s *= 2;
+   yscr /= 2;
+   h /= 2;
+   }
+
+   if (!dcrtc->cursor_obj || !h || !w) {
+   spin_lock_irq(>irq_lock);
+   armada_updatel(0, CFG_HWC_ENA, dcrtc->base + LCD_SPU_DMA_CTRL0);
+   spin_unlock_irq(>irq_lock);
+   return 0;
+   }
+
+   armada_updatel(CFG_CSB_256x32, CFG_PDWN256x32,
+dcrtc->base + LCD_SPU_SRAM_PARA1);
+
+   if (dcrtc->cursor_lw != w || dcrtc->cursor_lh != h || reload) {
+   struct armada_gem_object *obj = dcrtc->cursor_obj;
+   uint32_t *pix, *p, col2 = 0, col3 = 0;
+   unsigned x, y, d, n, a;
+
+   dcrtc->cursor_lw = w;
+   dcrtc->cursor_lh = h;
+
+   pix = obj->addr;
+
+   /* Set the top-left corner of the cursor image */
+   pix += yoff * s + xoff;
+
+   a = 2 << 14 | 15 << 8;
+   for (d = n = y = 0; y < h; y++) {
+   for (x = 0, p = [y * s]; x < w; x++, p++) {
+   uint32_t v = *p;
+   unsigned b;
+
+   if ((v & 0xff00) != 0xff00) {
+   b = 0;  /* transparent */
+   } else if (col2 == v) {
+   b = 2;  /* color 2 */
+   } else if (col3 == v) {
+   b = 3;  /* color 3 */
+   } else if (col2 == 0) {
+   col2 = v;
+   b = 2;  /* alloc color 2 */
+   } else if (col3 == 0) {
+   col3 = v;
+   b = 3;  /* alloc color 3 */
+   } else {
+   /* fail */
+   b = 1;  /* inverse (!) */
+   }
+
+   d |= b << n;
+   n += 2;
+
+  

[PATCH RFC v3 2/4] DRM: Armada: Add support for hardware cursors

2013-06-10 Thread Russell King
This patch adds hardware cursor support to the DRM driver for the
Marvell Armada SoCs.

Signed-off-by: Russell King rmk+ker...@arm.linux.org.uk
---
 drivers/gpu/drm/armada/Kconfig   |7 +
 drivers/gpu/drm/armada/armada_crtc.c |  201 ++
 drivers/gpu/drm/armada/armada_crtc.h |8 ++
 3 files changed, 216 insertions(+), 0 deletions(-)

diff --git a/drivers/gpu/drm/armada/Kconfig b/drivers/gpu/drm/armada/Kconfig
index c7a0a94..6f64642 100644
--- a/drivers/gpu/drm/armada/Kconfig
+++ b/drivers/gpu/drm/armada/Kconfig
@@ -13,3 +13,10 @@ config DRM_ARMADA
  This driver provides no built-in acceleration; acceleration is
  performed by other IP found on the SoC.  This driver provides
  kernel mode setting and buffer management to userspace.
+
+config DRM_ARMADA_CURSOR
+   bool Enable hardware cursor support for Marvell Armada DRM
+   depends on DRM_ARMADA != n
+   help
+ Add support for hardware cursor support on the Marvell
+ Armada devices.
diff --git a/drivers/gpu/drm/armada/armada_crtc.c 
b/drivers/gpu/drm/armada/armada_crtc.c
index dadaf63..4a71ba0 100644
--- a/drivers/gpu/drm/armada/armada_crtc.c
+++ b/drivers/gpu/drm/armada/armada_crtc.c
@@ -626,11 +626,210 @@ static const struct drm_crtc_helper_funcs 
armada_crtc_helper_funcs = {
.disable= armada_drm_crtc_disable,
 };
 
+#ifdef CONFIG_DRM_ARMADA_CURSOR
+static int armada_drm_crtc_cursor_update(struct armada_crtc *dcrtc, bool 
reload)
+{
+   uint32_t xoff, xscr, w = dcrtc-cursor_w, s;
+   uint32_t yoff, yscr, h = dcrtc-cursor_h;
+
+   /*
+* Calculate the visible width and height of the cursor,
+* screen position, and the position in the cursor bitmap.
+*/
+   if (dcrtc-cursor_x  0) {
+   xoff = -dcrtc-cursor_x;
+   xscr = 0;
+   w -= min(xoff, w);
+   } else if (dcrtc-cursor_x + w  dcrtc-crtc.mode.hdisplay) {
+   xoff = 0;
+   xscr = dcrtc-cursor_x;
+   w = max_t(int, dcrtc-crtc.mode.hdisplay - dcrtc-cursor_x, 0);
+   } else {
+   xoff = 0;
+   xscr = dcrtc-cursor_x;
+   }
+
+   if (dcrtc-cursor_y  0) {
+   yoff = -dcrtc-cursor_y;
+   yscr = 0;
+   h -= min(yoff, h);
+   } else if (dcrtc-cursor_y + h  dcrtc-crtc.mode.vdisplay) {
+   yoff = 0;
+   yscr = dcrtc-cursor_y;
+   h = max_t(int, dcrtc-crtc.mode.vdisplay - dcrtc-cursor_y, 0);
+   } else {
+   yoff = 0;
+   yscr = dcrtc-cursor_y;
+   }
+
+   /* On interlaced modes, the vertical cursor size must be halved */
+   s = dcrtc-cursor_w;
+   if (dcrtc-interlaced) {
+   s *= 2;
+   yscr /= 2;
+   h /= 2;
+   }
+
+   if (!dcrtc-cursor_obj || !h || !w) {
+   spin_lock_irq(dcrtc-irq_lock);
+   armada_updatel(0, CFG_HWC_ENA, dcrtc-base + LCD_SPU_DMA_CTRL0);
+   spin_unlock_irq(dcrtc-irq_lock);
+   return 0;
+   }
+
+   armada_updatel(CFG_CSB_256x32, CFG_PDWN256x32,
+dcrtc-base + LCD_SPU_SRAM_PARA1);
+
+   if (dcrtc-cursor_lw != w || dcrtc-cursor_lh != h || reload) {
+   struct armada_gem_object *obj = dcrtc-cursor_obj;
+   uint32_t *pix, *p, col2 = 0, col3 = 0;
+   unsigned x, y, d, n, a;
+
+   dcrtc-cursor_lw = w;
+   dcrtc-cursor_lh = h;
+
+   pix = obj-addr;
+
+   /* Set the top-left corner of the cursor image */
+   pix += yoff * s + xoff;
+
+   a = 2  14 | 15  8;
+   for (d = n = y = 0; y  h; y++) {
+   for (x = 0, p = pix[y * s]; x  w; x++, p++) {
+   uint32_t v = *p;
+   unsigned b;
+
+   if ((v  0xff00) != 0xff00) {
+   b = 0;  /* transparent */
+   } else if (col2 == v) {
+   b = 2;  /* color 2 */
+   } else if (col3 == v) {
+   b = 3;  /* color 3 */
+   } else if (col2 == 0) {
+   col2 = v;
+   b = 2;  /* alloc color 2 */
+   } else if (col3 == 0) {
+   col3 = v;
+   b = 3;  /* alloc color 3 */
+   } else {
+   /* fail */
+   b = 1;  /* inverse (!) */
+   }
+
+   d |= b  n;
+   n += 2;
+
+   if (n == 32) {
+