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 vblank irq and RGB overla...



details:   https://anonhg.NetBSD.org/src/rev/aaabf8d42b2b
branches:  trunk
changeset: 448523:aaabf8d42b2b
user:      jmcneill <jmcneill%NetBSD.org@localhost>
date:      Mon Feb 04 12:10:13 2019 +0000

description:
Add support for vblank irq and RGB overlay planes.

diffstat:

 sys/arch/arm/sunxi/sunxi_drm.c   |   73 ++++++++++++-
 sys/arch/arm/sunxi/sunxi_drm.h   |   13 ++-
 sys/arch/arm/sunxi/sunxi_lcdc.c  |   98 ++++++++++++++++++-
 sys/arch/arm/sunxi/sunxi_mixer.c |  206 ++++++++++++++++++++++++++++++++++++++-
 4 files changed, 376 insertions(+), 14 deletions(-)

diffs (truncated from 644 to 300 lines):

diff -r 0e84b1c51b98 -r aaabf8d42b2b sys/arch/arm/sunxi/sunxi_drm.c
--- a/sys/arch/arm/sunxi/sunxi_drm.c    Mon Feb 04 12:08:03 2019 +0000
+++ b/sys/arch/arm/sunxi/sunxi_drm.c    Mon Feb 04 12:10:13 2019 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: sunxi_drm.c,v 1.5 2019/02/03 15:43:57 jmcneill Exp $ */
+/* $NetBSD: sunxi_drm.c,v 1.6 2019/02/04 12:10:13 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.5 2019/02/03 15:43:57 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sunxi_drm.c,v 1.6 2019/02/04 12:10:13 jmcneill Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -71,6 +71,10 @@
 
 static int     sunxi_drm_set_busid(struct drm_device *, struct drm_master *);
 
+static uint32_t        sunxi_drm_get_vblank_counter(struct drm_device *, unsigned int);
+static int     sunxi_drm_enable_vblank(struct drm_device *, unsigned int);
+static void    sunxi_drm_disable_vblank(struct drm_device *, unsigned int);
+
 static int     sunxi_drm_load(struct drm_device *, unsigned long);
 static int     sunxi_drm_unload(struct drm_device *);
 
@@ -88,11 +92,9 @@
        .dumb_map_offset = drm_gem_cma_dumb_map_offset,
        .dumb_destroy = drm_gem_dumb_destroy,
 
-#if notyet
        .get_vblank_counter = sunxi_drm_get_vblank_counter,
        .enable_vblank = sunxi_drm_enable_vblank,
        .disable_vblank = sunxi_drm_disable_vblank,
-#endif
 
        .name = DRIVER_NAME,
        .desc = DRIVER_DESC,
@@ -233,12 +235,23 @@
        fb = kmem_zalloc(sizeof(*fb), KM_SLEEP);
        fb->obj = to_drm_gem_cma_obj(gem_obj);
        fb->base.pitches[0] = cmd->pitches[0];
+       fb->base.pitches[1] = cmd->pitches[1];
+       fb->base.pitches[2] = cmd->pitches[2];
        fb->base.offsets[0] = cmd->offsets[0];
+       fb->base.offsets[1] = cmd->offsets[2];
+       fb->base.offsets[2] = cmd->offsets[1];
        fb->base.width = cmd->width;
        fb->base.height = cmd->height;
        fb->base.pixel_format = cmd->pixel_format;
-       drm_fb_get_bpp_depth(cmd->pixel_format, &fb->base.depth,
-           &fb->base.bits_per_pixel);
+       fb->base.bits_per_pixel = drm_format_plane_cpp(fb->base.pixel_format, 0) * 8;
+
+       switch (fb->base.pixel_format) {
+       case DRM_FORMAT_XRGB8888:
+               fb->base.depth = 32;
+               break;
+       default:
+               break;
+       }
 
        error = drm_framebuffer_init(ddev, &fb->base, &sunxi_drm_framebuffer_funcs);
        if (error != 0)
@@ -372,6 +385,10 @@
 
        drm_fb_helper_initial_config(&fbdev->helper, 32);
 
+       /* XXX */
+       ddev->irq_enabled = true;
+       drm_vblank_init(ddev, num_crtc);
+
        return 0;
 
 drmerr:
@@ -381,6 +398,50 @@
        return error;
 }
 
+static uint32_t
+sunxi_drm_get_vblank_counter(struct drm_device *ddev, unsigned int crtc)
+{
+       struct sunxi_drm_softc * const sc = sunxi_drm_private(ddev);
+
+       if (crtc >= __arraycount(sc->sc_vbl))
+               return 0;
+
+       if (sc->sc_vbl[crtc].get_vblank_counter == NULL)
+               return 0;
+
+       return sc->sc_vbl[crtc].get_vblank_counter(sc->sc_vbl[crtc].priv);
+}
+
+static int
+sunxi_drm_enable_vblank(struct drm_device *ddev, unsigned int crtc)
+{
+       struct sunxi_drm_softc * const sc = sunxi_drm_private(ddev);
+
+       if (crtc >= __arraycount(sc->sc_vbl))
+               return 0;
+
+       if (sc->sc_vbl[crtc].enable_vblank == NULL)
+               return 0;
+
+       sc->sc_vbl[crtc].enable_vblank(sc->sc_vbl[crtc].priv);
+
+       return 0;
+}
+
+static void
+sunxi_drm_disable_vblank(struct drm_device *ddev, unsigned int crtc)
+{
+       struct sunxi_drm_softc * const sc = sunxi_drm_private(ddev);
+
+       if (crtc >= __arraycount(sc->sc_vbl))
+               return;
+
+       if (sc->sc_vbl[crtc].disable_vblank == NULL)
+               return;
+
+       sc->sc_vbl[crtc].disable_vblank(sc->sc_vbl[crtc].priv);
+}
+
 static int
 sunxi_drm_unload(struct drm_device *ddev)
 {
diff -r 0e84b1c51b98 -r aaabf8d42b2b sys/arch/arm/sunxi/sunxi_drm.h
--- a/sys/arch/arm/sunxi/sunxi_drm.h    Mon Feb 04 12:08:03 2019 +0000
+++ b/sys/arch/arm/sunxi/sunxi_drm.h    Mon Feb 04 12:10:13 2019 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: sunxi_drm.h,v 1.1 2019/01/30 01:24:00 jmcneill Exp $ */
+/* $NetBSD: sunxi_drm.h,v 1.2 2019/02/04 12:10:13 jmcneill Exp $ */
 
 /*-
  * Copyright (c) 2019 Jared D. McNeill <jmcneill%invisible.ca@localhost>
@@ -44,6 +44,15 @@
 
 struct sunxi_framebuffer;
 
+#define        SUNXI_DRM_MAX_CRTC      2
+
+struct sunxi_drm_vblank {
+       void                    *priv;
+       void                    (*enable_vblank)(void *);
+       void                    (*disable_vblank)(void *);
+       uint32_t                (*get_vblank_counter)(void *);
+};
+
 struct sunxi_drm_softc {
        device_t                sc_dev;
        struct drm_device       *sc_ddev;
@@ -52,6 +61,8 @@
        bus_dma_tag_t           sc_dmat;
 
        int                     sc_phandle;
+
+       struct sunxi_drm_vblank sc_vbl[SUNXI_DRM_MAX_CRTC];
 };
 
 struct sunxi_drm_framebuffer {
diff -r 0e84b1c51b98 -r aaabf8d42b2b sys/arch/arm/sunxi/sunxi_lcdc.c
--- a/sys/arch/arm/sunxi/sunxi_lcdc.c   Mon Feb 04 12:08:03 2019 +0000
+++ b/sys/arch/arm/sunxi/sunxi_lcdc.c   Mon Feb 04 12:10:13 2019 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: sunxi_lcdc.c,v 1.3 2019/02/03 13:15:19 jmcneill Exp $ */
+/* $NetBSD: sunxi_lcdc.c,v 1.4 2019/02/04 12:10:13 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_lcdc.c,v 1.3 2019/02/03 13:15:19 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sunxi_lcdc.c,v 1.4 2019/02/04 12:10:13 jmcneill Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -43,11 +43,17 @@
 #include <dev/fdt/fdtvar.h>
 #include <dev/fdt/fdt_port.h>
 
+#include <arm/sunxi/sunxi_drm.h>
+
 #define        TCON_GCTL_REG           0x000
 #define         TCON_GCTL_TCON_EN                      __BIT(31)
 #define         TCON_GCTL_GAMMA_EN                     __BIT(30)
 #define         TCON_GCTL_IO_MAP_SEL                   __BIT(0)
 #define        TCON_GINT0_REG          0x004
+#define         TCON_GINT0_TCON0_VB_INT_EN             __BIT(31)
+#define         TCON_GINT0_TCON1_VB_INT_EN             __BIT(30)
+#define         TCON_GINT0_TCON0_VB_INT_FLAG           __BIT(15)
+#define         TCON_GINT0_TCON1_VB_INT_FLAG           __BIT(14)
 #define        TCON_GINT1_REG          0x008
 #define         TCON_GINT1_TCON1_LINE_INT_NUM          __BITS(11,0)
 
@@ -129,6 +135,8 @@
        struct drm_connector    sc_connector;
 
        struct fdt_device_ports sc_ports;
+
+       uint32_t                sc_vbl_counter;
 };
 
 #define        to_sunxi_lcdc_encoder(x)        container_of(x, struct sunxi_lcdc_encoder, base)
@@ -336,6 +344,50 @@
        }
 }
 
+static uint32_t
+sunxi_lcdc_get_vblank_counter(void *priv)
+{
+       struct sunxi_lcdc_softc * const sc = priv;
+
+       return sc->sc_vbl_counter;
+}
+
+static void
+sunxi_lcdc_enable_vblank(void *priv)
+{
+       struct sunxi_lcdc_softc * const sc = priv;
+        const int crtc_index = ffs32(sc->sc_encoder.base.possible_crtcs) - 1;
+
+       if (crtc_index == 0)
+               TCON_WRITE(sc, TCON_GINT0_REG, TCON_GINT0_TCON0_VB_INT_EN);
+       else
+               TCON_WRITE(sc, TCON_GINT0_REG, TCON_GINT0_TCON1_VB_INT_EN);
+}
+
+static void
+sunxi_lcdc_disable_vblank(void *priv)
+{
+       struct sunxi_lcdc_softc * const sc = priv;
+
+       TCON_WRITE(sc, TCON_GINT0_REG, 0);
+}
+
+static void
+sunxi_lcdc_setup_vblank(struct sunxi_lcdc_softc *sc)
+{
+        const int crtc_index = ffs32(sc->sc_encoder.base.possible_crtcs) - 1;
+       struct drm_device *ddev = sc->sc_encoder.base.dev;
+       struct sunxi_drm_softc *drm_sc;
+
+       KASSERT(ddev != NULL);
+
+       drm_sc = device_private(ddev->dev);
+       drm_sc->sc_vbl[crtc_index].priv = sc;
+       drm_sc->sc_vbl[crtc_index].get_vblank_counter = sunxi_lcdc_get_vblank_counter;
+       drm_sc->sc_vbl[crtc_index].enable_vblank = sunxi_lcdc_enable_vblank;
+       drm_sc->sc_vbl[crtc_index].disable_vblank = sunxi_lcdc_disable_vblank;
+}
+
 static int
 sunxi_lcdc_ep_activate(device_t dev, struct fdt_endpoint *ep, bool activate)
 {
@@ -364,6 +416,8 @@
                    sunxi_lcdc_encoder_mode(out_ep));
                drm_encoder_helper_add(&sc->sc_encoder.base, &sunxi_lcdc_tcon0_helper_funcs);
 
+               sunxi_lcdc_setup_vblank(sc);
+
                return fdt_endpoint_activate(out_ep, activate);
        }
 
@@ -373,6 +427,8 @@
                    sunxi_lcdc_encoder_mode(out_ep));
                drm_encoder_helper_add(&sc->sc_encoder.base, &sunxi_lcdc_tcon1_helper_funcs);
 
+               sunxi_lcdc_setup_vblank(sc);
+
                return fdt_endpoint_activate(out_ep, activate);
        }
 
@@ -388,6 +444,28 @@
 }
 
 static int
+sunxi_lcdc_intr(void *priv)
+{
+       struct sunxi_lcdc_softc * const sc = priv;
+       uint32_t val;
+       int rv = 0;
+
+       const int crtc_index = ffs32(sc->sc_encoder.base.possible_crtcs) - 1;
+       const uint32_t status_mask = crtc_index == 0 ?
+           TCON_GINT0_TCON0_VB_INT_FLAG : TCON_GINT0_TCON1_VB_INT_FLAG;
+
+       val = TCON_READ(sc, TCON_GINT0_REG);
+       if ((val & status_mask) != 0) {
+               TCON_WRITE(sc, TCON_GINT0_REG, val & ~status_mask);
+               atomic_inc_32(&sc->sc_vbl_counter);
+               drm_handle_vblank(sc->sc_encoder.base.dev, crtc_index);
+               rv = 1;
+       }
+
+       return rv;



Home | Main Index | Thread Index | Old Index