Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/arch/arm/sunxi Add support for hardware cursors where we...
details: https://anonhg.NetBSD.org/src/rev/72a9700bb1be
branches: trunk
changeset: 996645:72a9700bb1be
user: jmcneill <jmcneill%NetBSD.org@localhost>
date: Wed Feb 06 03:07:08 2019 +0000
description:
Add support for hardware cursors where we can.
As far as I can tell, alpha blending only works between overlay channels,
and not between layers on a channel. Unfortunately, RT-Mixer1 only has
a single UI channel, so this feature is limited to RT-Mixer0.
diffstat:
sys/arch/arm/sunxi/sunxi_drm.c | 5 +-
sys/arch/arm/sunxi/sunxi_mixer.c | 229 +++++++++++++++++++++++++++++++++-----
2 files changed, 200 insertions(+), 34 deletions(-)
diffs (truncated from 464 to 300 lines):
diff -r e56587d911af -r 72a9700bb1be sys/arch/arm/sunxi/sunxi_drm.c
--- a/sys/arch/arm/sunxi/sunxi_drm.c Wed Feb 06 03:01:48 2019 +0000
+++ b/sys/arch/arm/sunxi/sunxi_drm.c Wed Feb 06 03:07:08 2019 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: sunxi_drm.c,v 1.6 2019/02/04 12:10:13 jmcneill Exp $ */
+/* $NetBSD: sunxi_drm.c,v 1.7 2019/02/06 03:07:08 jmcneill Exp $ */
/*-
* Copyright (c) 2019 Jared D. McNeill <jmcneill%invisible.ca@localhost>
@@ -27,7 +27,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sunxi_drm.c,v 1.6 2019/02/04 12:10:13 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sunxi_drm.c,v 1.7 2019/02/06 03:07:08 jmcneill Exp $");
#include <sys/param.h>
#include <sys/bus.h>
@@ -247,6 +247,7 @@
switch (fb->base.pixel_format) {
case DRM_FORMAT_XRGB8888:
+ case DRM_FORMAT_ARGB8888:
fb->base.depth = 32;
break;
default:
diff -r e56587d911af -r 72a9700bb1be sys/arch/arm/sunxi/sunxi_mixer.c
--- a/sys/arch/arm/sunxi/sunxi_mixer.c Wed Feb 06 03:01:48 2019 +0000
+++ b/sys/arch/arm/sunxi/sunxi_mixer.c Wed Feb 06 03:07:08 2019 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: sunxi_mixer.c,v 1.5 2019/02/05 21:01:38 jmcneill Exp $ */
+/* $NetBSD: sunxi_mixer.c,v 1.6 2019/02/06 03:07:08 jmcneill Exp $ */
/*-
* Copyright (c) 2019 Jared D. McNeill <jmcneill%invisible.ca@localhost>
@@ -27,7 +27,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sunxi_mixer.c,v 1.5 2019/02/05 21:01:38 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sunxi_mixer.c,v 1.6 2019/02/06 03:07:08 jmcneill Exp $");
#include <sys/param.h>
#include <sys/bus.h>
@@ -36,6 +36,7 @@
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/conf.h>
+#include <sys/sysctl.h>
#include <drm/drmP.h>
#include <drm/drm_crtc.h>
@@ -47,13 +48,14 @@
#include <arm/sunxi/sunxi_drm.h>
+#define MIXER_CURSOR_MAXWIDTH 256
+#define MIXER_CURSOR_MAXHEIGHT 256
+
#define SUNXI_MIXER_FREQ 432000000
#define GLB_BASE 0x00000
#define BLD_BASE 0x01000
#define OVL_BASE(n) (0x02000 + (n) * 0x1000)
-#define OVL_V_BASE OVL_BASE(0)
-#define OVL_UI_BASE OVL_BASE(1)
#define VSU_BASE 0x20000
#define CSC_BASE(n) ((n) == 0 ? 0xaa050 : 0xa0000)
@@ -67,11 +69,20 @@
/* BLD registers */
#define BLD_FILL_COLOR_CTL 0x000
+#define BLD_FILL_COLOR_CTL_P3_EN __BIT(11)
+#define BLD_FILL_COLOR_CTL_P2_EN __BIT(10)
#define BLD_FILL_COLOR_CTL_P1_EN __BIT(9)
#define BLD_FILL_COLOR_CTL_P0_EN __BIT(8)
+#define BLD_FILL_COLOR_CTL_P3_FCEN __BIT(3)
+#define BLD_FILL_COLOR_CTL_P2_FCEN __BIT(2)
+#define BLD_FILL_COLOR_CTL_P1_FCEN __BIT(1)
+#define BLD_FILL_COLOR_CTL_P0_FCEN __BIT(0)
+#define BLD_FILL_COLOR(n) (0x004 + (n) * 0x10)
#define BLD_CH_ISIZE(n) (0x008 + (n) * 0x10)
#define BLD_CH_OFFSET(n) (0x00c + (n) * 0x10)
#define BLD_CH_RTCTL 0x080
+#define BLD_CH_RTCTL_P3 __BITS(15,12)
+#define BLD_CH_RTCTL_P2 __BITS(11,8)
#define BLD_CH_RTCTL_P1 __BITS(7,4)
#define BLD_CH_RTCTL_P0 __BITS(3,0)
#define BLD_SIZE 0x08c
@@ -88,6 +99,7 @@
#define OVL_V_ATTCTL_LAY_FBFMT_YUV422 0x06
#define OVL_V_ATTCTL_LAY_FBFMT_YUV420 0x0a
#define OVL_V_ATTCTL_LAY_FBFMT_YUV411 0x0e
+#define OVL_V_ATTCTL_LAY_FBFMT_ARGB_8888 0x00
#define OVL_V_ATTCTL_LAY_FBFMT_XRGB_8888 0x04
#define OVL_V_ATTCTL_LAY0_EN __BIT(0)
#define OVL_V_MBSIZE(n) (0x004 + (n) * 0x30)
@@ -112,13 +124,16 @@
/* OVL_UI registers */
#define OVL_UI_ATTR_CTL(n) (0x000 + (n) * 0x20)
#define OVL_UI_ATTR_CTL_LAY_FBFMT __BITS(12,8)
+#define OVL_UI_ATTR_CTL_LAY_FBFMT_ARGB_8888 0x00
#define OVL_UI_ATTR_CTL_LAY_FBFMT_XRGB_8888 0x04
#define OVL_UI_ATTR_CTL_LAY_EN __BIT(0)
#define OVL_UI_MBSIZE(n) (0x004 + (n) * 0x20)
#define OVL_UI_COOR(n) (0x008 + (n) * 0x20)
#define OVL_UI_PITCH(n) (0x00c + (n) * 0x20)
#define OVL_UI_TOP_LADD(n) (0x010 + (n) * 0x20)
+#define OVL_UI_FILL_COLOR(n) (0x018 + (n) * 0x20)
#define OVL_UI_TOP_HADD 0x080
+#define OVL_UI_TOP_HADD_LAYER1 __BITS(15,8)
#define OVL_UI_TOP_HADD_LAYER0 __BITS(7,0)
#define OVL_UI_SIZE 0x088
@@ -158,11 +173,11 @@
MIXER_PORT_OUTPUT = 1,
};
-static const char * const compatible[] = {
- "allwinner,sun8i-h3-de2-mixer-0",
- "allwinner,sun50i-a64-de2-mixer-0",
- "allwinner,sun50i-a64-de2-mixer-1",
- NULL
+static const struct of_compat_data compat_data[] = {
+ { "allwinner,sun8i-h3-de2-mixer-0", 3 },
+ { "allwinner,sun50i-a64-de2-mixer-0", 3 },
+ { "allwinner,sun50i-a64-de2-mixer-1", 1 },
+ { NULL }
};
struct sunxi_mixer_softc;
@@ -172,7 +187,7 @@
struct sunxi_mixer_softc *sc;
};
-struct sunxi_mixer_overlay {
+struct sunxi_mixer_plane {
struct drm_plane base;
struct sunxi_mixer_softc *sc;
};
@@ -183,8 +198,10 @@
bus_space_handle_t sc_bsh;
int sc_phandle;
+ u_int sc_ovl_ui_count;
+
struct sunxi_mixer_crtc sc_crtc;
- struct sunxi_mixer_overlay sc_overlay;
+ struct sunxi_mixer_plane sc_overlay;
struct fdt_device_ports sc_ports;
};
@@ -200,14 +217,14 @@
bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, BLD_BASE + (reg), (val))
#define OVL_V_READ(sc, reg) \
- bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, OVL_V_BASE + (reg))
+ bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, OVL_BASE(0) + (reg))
#define OVL_V_WRITE(sc, reg, val) \
- bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, OVL_V_BASE + (reg), (val))
+ bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, OVL_BASE(0) + (reg), (val))
-#define OVL_UI_READ(sc, reg) \
- bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, OVL_UI_BASE + (reg))
-#define OVL_UI_WRITE(sc, reg, val) \
- bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, OVL_UI_BASE + (reg), (val))
+#define OVL_UI_READ(sc, n, reg) \
+ bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, OVL_BASE((n) + 1) + (reg))
+#define OVL_UI_WRITE(sc, n, reg, val) \
+ bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, OVL_BASE((n) + 1) + (reg), (val))
#define VSU_READ(sc, reg) \
bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, VSU_BASE + (reg))
@@ -220,7 +237,7 @@
bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, CSC_BASE(n) + (reg), (val))
#define to_sunxi_mixer_crtc(x) container_of(x, struct sunxi_mixer_crtc, base)
-#define to_sunxi_mixer_overlay(x) container_of(x, struct sunxi_mixer_overlay, base)
+#define to_sunxi_mixer_plane(x) container_of(x, struct sunxi_mixer_plane, base)
static int
sunxi_mixer_mode_do_set_base(struct drm_crtc *crtc, struct drm_framebuffer *fb,
@@ -231,6 +248,7 @@
struct sunxi_drm_framebuffer *sfb = atomic?
to_sunxi_drm_framebuffer(fb) :
to_sunxi_drm_framebuffer(crtc->primary->fb);
+ uint32_t val;
uint64_t paddr = (uint64_t)sfb->obj->dmamap->dm_segs[0].ds_addr;
@@ -238,8 +256,11 @@
uint32_t laddr = paddr & 0xffffffff;
/* Framebuffer start address */
- OVL_UI_WRITE(sc, OVL_UI_TOP_HADD, haddr);
- OVL_UI_WRITE(sc, OVL_UI_TOP_LADD(0), laddr);
+ val = OVL_UI_READ(sc, 0, OVL_UI_TOP_HADD);
+ val &= ~OVL_UI_TOP_HADD_LAYER0;
+ val |= __SHIFTIN(haddr, OVL_UI_TOP_HADD_LAYER0);
+ OVL_UI_WRITE(sc, 0, OVL_UI_TOP_HADD, val);
+ OVL_UI_WRITE(sc, 0, OVL_UI_TOP_LADD(0), laddr);
return 0;
}
@@ -274,10 +295,137 @@
return 0;
}
+static int
+sunxi_mixer_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv,
+ uint32_t handle, uint32_t width, uint32_t height)
+{
+ struct sunxi_mixer_crtc *mixer_crtc = to_sunxi_mixer_crtc(crtc);
+ struct sunxi_mixer_softc * const sc = mixer_crtc->sc;
+ struct drm_gem_object *gem_obj = NULL;
+ struct drm_gem_cma_object *obj;
+ uint32_t val;
+ int error;
+
+ /* Only mixers with more than one UI layer can support hardware cursors */
+ if (sc->sc_ovl_ui_count <= 1)
+ return -EINVAL;
+
+ if (handle == 0) {
+ val = BLD_READ(sc, BLD_FILL_COLOR_CTL);
+ val &= ~BLD_FILL_COLOR_CTL_P2_EN;
+ val |= BLD_FILL_COLOR_CTL_P2_FCEN;
+ BLD_WRITE(sc, BLD_FILL_COLOR_CTL, val);
+
+ error = 0;
+ goto done;
+ }
+
+ /* Arbitrary limits, the hardware layer can do 8192x8192 */
+ if (width > MIXER_CURSOR_MAXWIDTH || height > MIXER_CURSOR_MAXHEIGHT) {
+ DRM_ERROR("Cursor dimension %ux%u not supported\n", width, height);
+ error = -EINVAL;
+ goto done;
+ }
+
+ gem_obj = drm_gem_object_lookup(crtc->dev, file_priv, handle);
+ if (gem_obj == NULL) {
+ DRM_ERROR("Cannot find cursor object %#x for crtc %d\n",
+ handle, drm_crtc_index(crtc));
+ error = -ENOENT;
+ goto done;
+ }
+ obj = to_drm_gem_cma_obj(gem_obj);
+
+ if (obj->base.size < width * height * 4) {
+ DRM_ERROR("Cursor buffer is too small\n");
+ error = -ENOMEM;
+ goto done;
+ }
+
+ uint64_t paddr = (uint64_t)obj->dmamap->dm_segs[0].ds_addr;
+ uint32_t haddr = (paddr >> 32) & OVL_UI_TOP_HADD_LAYER0;
+ uint32_t laddr = paddr & 0xffffffff;
+
+ /* Framebuffer start address */
+ val = OVL_UI_READ(sc, 1, OVL_UI_TOP_HADD);
+ val &= ~OVL_UI_TOP_HADD_LAYER0;
+ val |= __SHIFTIN(haddr, OVL_UI_TOP_HADD_LAYER0);
+ OVL_UI_WRITE(sc, 1, OVL_UI_TOP_HADD, val);
+ OVL_UI_WRITE(sc, 1, OVL_UI_TOP_LADD(0), laddr);
+
+ const uint32_t size = ((height - 1) << 16) | (width - 1);
+ const uint32_t offset = (crtc->cursor_y << 16) | crtc->cursor_x;
+ const uint32_t crtc_size = ((crtc->primary->fb->height - 1) << 16) |
+ (crtc->primary->fb->width - 1);
+
+ /* Enable cursor in ARGB8888 mode */
+ val = OVL_UI_ATTR_CTL_LAY_EN |
+ __SHIFTIN(OVL_UI_ATTR_CTL_LAY_FBFMT_ARGB_8888, OVL_UI_ATTR_CTL_LAY_FBFMT);
+ OVL_UI_WRITE(sc, 1, OVL_UI_ATTR_CTL(0), val);
+ /* Set UI overlay layer size */
+ OVL_UI_WRITE(sc, 1, OVL_UI_MBSIZE(0), size);
+ /* Set UI overlay offset */
+ OVL_UI_WRITE(sc, 1, OVL_UI_COOR(0), offset);
+ /* Set UI overlay line size */
+ OVL_UI_WRITE(sc, 1, OVL_UI_PITCH(0), width * 4);
+ /* Set UI overlay window size */
+ OVL_UI_WRITE(sc, 1, OVL_UI_SIZE, crtc_size);
+
+ /* Set blender 2 input size */
+ BLD_WRITE(sc, BLD_CH_ISIZE(2), crtc_size);
+ /* Set blender 2 offset */
+ BLD_WRITE(sc, BLD_CH_OFFSET(2), 0);
+ /* Route channel 2 to pipe 2 */
+ val = BLD_READ(sc, BLD_CH_RTCTL);
+ val &= ~BLD_CH_RTCTL_P2;
+ val |= __SHIFTIN(2, BLD_CH_RTCTL_P2);
+ BLD_WRITE(sc, BLD_CH_RTCTL, val);
+
+ /* Enable pipe 2 */
+ val = BLD_READ(sc, BLD_FILL_COLOR_CTL);
+ val |= BLD_FILL_COLOR_CTL_P2_EN;
+ val &= ~BLD_FILL_COLOR_CTL_P2_FCEN;
+ BLD_WRITE(sc, BLD_FILL_COLOR_CTL, val);
Home |
Main Index |
Thread Index |
Old Index