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