Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/arch/arm/rockchip rkdrm: Implement vblank.



details:   https://anonhg.NetBSD.org/src/rev/dd027911742d
branches:  trunk
changeset: 1029050:dd027911742d
user:      riastradh <riastradh%NetBSD.org@localhost>
date:      Mon Dec 20 00:27:17 2021 +0000

description:
rkdrm: Implement vblank.

diffstat:

 sys/arch/arm/rockchip/rk_drm.c |   58 +-----------
 sys/arch/arm/rockchip/rk_vop.c |  191 +++++++++++++++++++++++++++++++++++++---
 2 files changed, 178 insertions(+), 71 deletions(-)

diffs (truncated from 415 to 300 lines):

diff -r b1ee774833ea -r dd027911742d sys/arch/arm/rockchip/rk_drm.c
--- a/sys/arch/arm/rockchip/rk_drm.c    Mon Dec 20 00:10:07 2021 +0000
+++ b/sys/arch/arm/rockchip/rk_drm.c    Mon Dec 20 00:27:17 2021 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: rk_drm.c,v 1.17 2021/12/19 12:45:04 riastradh Exp $ */
+/* $NetBSD: rk_drm.c,v 1.18 2021/12/20 00:27:17 riastradh Exp $ */
 
 /*-
  * Copyright (c) 2019 Jared D. McNeill <jmcneill%invisible.ca@localhost>
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: rk_drm.c,v 1.17 2021/12/19 12:45:04 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: rk_drm.c,v 1.18 2021/12/20 00:27:17 riastradh Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -77,10 +77,6 @@
 static void    rk_drm_init(device_t);
 static vmem_t  *rk_drm_alloc_cma_pool(struct drm_device *, size_t);
 
-static uint32_t        rk_drm_get_vblank_counter(struct drm_device *, unsigned int);
-static int     rk_drm_enable_vblank(struct drm_device *, unsigned int);
-static void    rk_drm_disable_vblank(struct drm_device *, unsigned int);
-
 static int     rk_drm_load(struct drm_device *, unsigned long);
 static void    rk_drm_unload(struct drm_device *);
 
@@ -99,10 +95,6 @@
        .dumb_create = drm_gem_cma_dumb_create,
        .dumb_destroy = drm_gem_dumb_destroy,
 
-       .get_vblank_counter = rk_drm_get_vblank_counter,
-       .enable_vblank = rk_drm_enable_vblank,
-       .disable_vblank = rk_drm_disable_vblank,
-
        .name = DRIVER_NAME,
        .desc = DRIVER_DESC,
        .date = DRIVER_DATE,
@@ -440,7 +432,7 @@
 
        drm_fb_helper_initial_config(&fbdev->helper, 32);
 
-       /* XXX */
+       /* XXX Delegate this to rk_vop.c?  */
        ddev->irq_enabled = true;
        drm_vblank_init(ddev, num_crtc);
 
@@ -454,50 +446,6 @@
        return error;
 }
 
-static uint32_t
-rk_drm_get_vblank_counter(struct drm_device *ddev, unsigned int crtc)
-{
-       struct rk_drm_softc * const sc = rk_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
-rk_drm_enable_vblank(struct drm_device *ddev, unsigned int crtc)
-{
-       struct rk_drm_softc * const sc = rk_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
-rk_drm_disable_vblank(struct drm_device *ddev, unsigned int crtc)
-{
-       struct rk_drm_softc * const sc = rk_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 void
 rk_drm_unload(struct drm_device *ddev)
 {
diff -r b1ee774833ea -r dd027911742d sys/arch/arm/rockchip/rk_vop.c
--- a/sys/arch/arm/rockchip/rk_vop.c    Mon Dec 20 00:10:07 2021 +0000
+++ b/sys/arch/arm/rockchip/rk_vop.c    Mon Dec 20 00:27:17 2021 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: rk_vop.c,v 1.15 2021/12/19 12:45:27 riastradh Exp $ */
+/* $NetBSD: rk_vop.c,v 1.16 2021/12/20 00:27:17 riastradh Exp $ */
 
 /*-
  * Copyright (c) 2019 Jared D. McNeill <jmcneill%invisible.ca@localhost>
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: rk_vop.c,v 1.15 2021/12/19 12:45:27 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: rk_vop.c,v 1.16 2021/12/20 00:27:17 riastradh Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -50,6 +50,7 @@
 #include <drm/drm_drv.h>
 #include <drm/drm_fourcc.h>
 #include <drm/drm_plane_helper.h>
+#include <drm/drm_vblank.h>
 
 #define        VOP_REG_CFG_DONE                0x0000
 #define         REG_LOAD_EN                    __BIT(0)
@@ -104,6 +105,26 @@
 #define        VOP_DSP_VACT_ST_END             0x0194
 #define         DSP_VACT_ST                    __BITS(28,16)
 #define         DSP_VACT_END                   __BITS(12,0)
+#define        VOP_INTR_EN0                    0x0280
+#define        VOP_INTR_CLEAR0                 0x0284
+#define        VOP_INTR_STATUS0                0x0288
+#define        VOP_INTR_RAW_STATUS0            0x028c
+#define         VOP_INTR0_DMA_FINISH           __BIT(15)
+#define         VOP_INTR0_MMU                  __BIT(14)
+#define         VOP_INTR0_DSP_HOLD_VALID       __BIT(13)
+#define         VOP_INTR0_FS_FIELD             __BIT(12)
+#define         VOP_INTR0_POST_BUF_EMPTY       __BIT(11)
+#define         VOP_INTR0_HWC_EMPTY            __BIT(10)
+#define         VOP_INTR0_WIN3_EMPTY           __BIT(9)
+#define         VOP_INTR0_WIN2_EMPTY           __BIT(8)
+#define         VOP_INTR0_WIN1_EMPTY           __BIT(7)
+#define         VOP_INTR0_WIN0_EMPTY           __BIT(6)
+#define         VOP_INTR0_BUS_ERROR            __BIT(5)
+#define         VOP_INTR0_LINE_FLAG1           __BIT(4)
+#define         VOP_INTR0_LINE_FLAG0           __BIT(3)
+#define         VOP_INTR0_ADDR_SAME            __BIT(2)
+#define         VOP_INTR0_FS_NEW               __BIT(1)
+#define         VOP_INTR0_FS                   __BIT(0)
 
 /*
  * Polarity fields are in different locations depending on SoC and output type,
@@ -150,6 +171,11 @@
        struct fdt_device_ports sc_ports;
 
        const struct rk_vop_config *sc_conf;
+
+       /* vblank */
+       void                    *sc_ih;
+       kmutex_t                sc_intr_lock;
+       struct drm_pending_vblank_event *sc_event;
 };
 
 #define        to_rk_vop_crtc(x)       container_of(x, struct rk_vop_crtc, base)
@@ -160,6 +186,14 @@
 #define        WR4(sc, reg, val)                       \
        bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, (reg), (val))
 
+static void
+WR4_MASK(struct rk_vop_softc *sc, bus_size_t reg, uint16_t mask, uint16_t val)
+{
+
+       KASSERT(val == (mask & val));
+       WR4(sc, reg, ((uint32_t)mask << 16) | val);
+}
+
 struct rk_vop_config {
        const char              *descr;
        u_int                   out_mode;
@@ -364,7 +398,7 @@
 };
 
 static bool
-rk_vop_format_mod_supported(struct drm_plane *plane, uint32_t format,
+rk_vop_plane_format_mod_supported(struct drm_plane *plane, uint32_t format,
     uint64_t modifier)
 {
        return modifier == DRM_FORMAT_MOD_LINEAR;
@@ -377,11 +411,11 @@
        .reset = drm_atomic_helper_plane_reset,
        .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
        .atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
-       .format_mod_supported = rk_vop_format_mod_supported,
+       .format_mod_supported = rk_vop_plane_format_mod_supported,
 };
 
 static void
-rk_vop_dpms(struct drm_crtc *crtc, int mode)
+rk_vop_crtc_dpms(struct drm_crtc *crtc, int mode)
 {
        struct rk_vop_crtc *mixer_crtc = to_rk_vop_crtc(crtc);
        struct rk_vop_softc * const sc = mixer_crtc->sc;
@@ -407,7 +441,7 @@
 }
 
 static int
-rk_vop_atomic_check(struct drm_crtc *crtc, struct drm_crtc_state *state)
+rk_vop_crtc_atomic_check(struct drm_crtc *crtc, struct drm_crtc_state *state)
 {
        bool enabled = state->plane_mask & drm_plane_mask(crtc->primary);
 
@@ -418,7 +452,7 @@
 }
 
 static void
-rk_vop_atomic_enable(struct drm_crtc *crtc, struct drm_crtc_state *state)
+rk_vop_crtc_atomic_enable(struct drm_crtc *crtc, struct drm_crtc_state *state)
 {
        struct rk_vop_crtc *mixer_crtc = to_rk_vop_crtc(crtc);
        struct rk_vop_softc * const sc = mixer_crtc->sc;
@@ -512,24 +546,91 @@
        val = __SHIFTIN(vsync_len, DSP_VTOTAL) |
              __SHIFTIN(vsync_len + vback_porch + vactive + vfront_porch, DSP_VS_END);
        WR4(sc, VOP_DSP_VTOTAL_VS_END, val);
+
+       drm_crtc_vblank_on(crtc);
+}
+
+static void
+rk_vop_crtc_atomic_disable(struct drm_crtc *crtc, struct drm_crtc_state *state)
+{
+       struct rk_vop_crtc *mixer_crtc = to_rk_vop_crtc(crtc);
+       struct rk_vop_softc * const sc = mixer_crtc->sc;
+       uint32_t val;
+
+       drm_crtc_vblank_off(crtc);
+
+       val = RD4(sc, VOP_SYS_CTRL);
+       val |= VOP_STANDBY_EN;
+       WR4(sc, VOP_SYS_CTRL, val);
+
+       if (crtc->state->event && !crtc->state->active) {
+               spin_lock(&crtc->dev->event_lock);
+               drm_crtc_send_vblank_event(crtc, crtc->state->event);
+               spin_unlock(&crtc->dev->event_lock);
+
+               crtc->state->event = NULL;
+       }
 }
 
 static void
-rk_vop_atomic_flush(struct drm_crtc *crtc, struct drm_crtc_state *state)
+rk_vop_crtc_atomic_flush(struct drm_crtc *crtc, struct drm_crtc_state *state)
+{
+       struct rk_vop_crtc *mixer_crtc = to_rk_vop_crtc(crtc);
+       struct rk_vop_softc * const sc = mixer_crtc->sc;
+       int ret;
+
+       /* Commit settings */
+       WR4(sc, VOP_REG_CFG_DONE, REG_LOAD_EN);
+
+       /*
+        * If caller wants a vblank event, tell the vblank interrupt
+        * handler to send it on the next interrupt.
+        */
+       spin_lock(&crtc->dev->event_lock);
+       if (crtc->state->event) {
+               if ((ret = drm_crtc_vblank_get_locked(crtc)) != 0)
+                       aprint_error_dev(sc->sc_dev,
+                           "drm_crtc_vblank_get: %d\n", ret);
+               if (sc->sc_event) /* XXX leaky; KASSERT? */
+                       aprint_error_dev(sc->sc_dev, "unfinished vblank\n");
+               sc->sc_event = crtc->state->event;
+               crtc->state->event = NULL;
+       }
+       spin_unlock(&crtc->dev->event_lock);
+}
+
+static const struct drm_crtc_helper_funcs rk_vop_crtc_helper_funcs = {
+       .dpms = rk_vop_crtc_dpms,
+       .atomic_check = rk_vop_crtc_atomic_check,
+       .atomic_enable = rk_vop_crtc_atomic_enable,
+       .atomic_disable = rk_vop_crtc_atomic_disable,
+       .atomic_flush = rk_vop_crtc_atomic_flush,
+};
+
+static int
+rk_vop_crtc_enable_vblank(struct drm_crtc *crtc)
 {
        struct rk_vop_crtc *mixer_crtc = to_rk_vop_crtc(crtc);
        struct rk_vop_softc * const sc = mixer_crtc->sc;
 
-       /* Commit settings */
-       WR4(sc, VOP_REG_CFG_DONE, REG_LOAD_EN);
+       mutex_spin_enter(&sc->sc_intr_lock);
+       WR4_MASK(sc, VOP_INTR_CLEAR0, VOP_INTR0_FS_NEW, VOP_INTR0_FS_NEW);
+       WR4_MASK(sc, VOP_INTR_EN0, VOP_INTR0_FS_NEW, VOP_INTR0_FS_NEW);
+       mutex_spin_exit(&sc->sc_intr_lock);
+



Home | Main Index | Thread Index | Old Index