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/78dc6057cf8a
branches:  trunk
changeset: 448610:78dc6057cf8a
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 d763b74a36bb -r 78dc6057cf8a 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 d763b74a36bb -r 78dc6057cf8a 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