[PATCH RFC v3 2/4] DRM: Armada: Add support for hardware cursors
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
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) { +