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