Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/arch/arm/nvidia Add vblank support
details: https://anonhg.NetBSD.org/src/rev/f86103e9b18b
branches: trunk
changeset: 341536:f86103e9b18b
user: jmcneill <jmcneill%NetBSD.org@localhost>
date: Tue Nov 10 22:14:05 2015 +0000
description:
Add vblank support
diffstat:
sys/arch/arm/nvidia/tegra_dcreg.h | 4 +-
sys/arch/arm/nvidia/tegra_drm.c | 8 ++-
sys/arch/arm/nvidia/tegra_drm.h | 8 ++-
sys/arch/arm/nvidia/tegra_drm_mode.c | 89 +++++++++++++++++++++++++++++++++++-
4 files changed, 103 insertions(+), 6 deletions(-)
diffs (220 lines):
diff -r fc40c414bcbc -r f86103e9b18b sys/arch/arm/nvidia/tegra_dcreg.h
--- a/sys/arch/arm/nvidia/tegra_dcreg.h Tue Nov 10 20:56:20 2015 +0000
+++ b/sys/arch/arm/nvidia/tegra_dcreg.h Tue Nov 10 22:14:05 2015 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: tegra_dcreg.h,v 1.3 2015/07/23 15:08:19 skrll Exp $ */
+/* $NetBSD: tegra_dcreg.h,v 1.4 2015/11/10 22:14:05 jmcneill Exp $ */
/*-
* Copyright (c) 2015 Jared D. McNeill <jmcneill%invisible.ca@localhost>
@@ -73,6 +73,8 @@
#define DC_CMD_INT_STATUS_REG 0x0dc
#define DC_CMD_INT_MASK_REG 0x0e0
#define DC_CMD_INT_ENABLE_REG 0x0e4
+#define DC_CMD_INT_V_BLANK __BIT(2)
+
#define DC_CMD_INT_TYPE_REG 0x0e8
#define DC_CMD_INT_POLARITY_REG 0x0ec
#define DC_CMD_SIGNAL_RAISE1_REG 0x0f0
diff -r fc40c414bcbc -r f86103e9b18b sys/arch/arm/nvidia/tegra_drm.c
--- a/sys/arch/arm/nvidia/tegra_drm.c Tue Nov 10 20:56:20 2015 +0000
+++ b/sys/arch/arm/nvidia/tegra_drm.c Tue Nov 10 22:14:05 2015 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: tegra_drm.c,v 1.1 2015/11/09 23:05:58 jmcneill Exp $ */
+/* $NetBSD: tegra_drm.c,v 1.2 2015/11/10 22:14:05 jmcneill Exp $ */
/*-
* Copyright (c) 2015 Jared D. McNeill <jmcneill%invisible.ca@localhost>
@@ -29,7 +29,7 @@
#include "locators.h"
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: tegra_drm.c,v 1.1 2015/11/09 23:05:58 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: tegra_drm.c,v 1.2 2015/11/10 22:14:05 jmcneill Exp $");
#include <sys/param.h>
#include <sys/bus.h>
@@ -79,6 +79,10 @@
.dumb_map_offset = tegra_drm_dumb_map_offset,
.dumb_destroy = tegra_drm_dumb_destroy,
+ .get_vblank_counter = tegra_drm_get_vblank_counter,
+ .enable_vblank = tegra_drm_enable_vblank,
+ .disable_vblank = tegra_drm_disable_vblank,
+
.name = DRIVER_NAME,
.desc = DRIVER_DESC,
.date = DRIVER_DATE,
diff -r fc40c414bcbc -r f86103e9b18b sys/arch/arm/nvidia/tegra_drm.h
--- a/sys/arch/arm/nvidia/tegra_drm.h Tue Nov 10 20:56:20 2015 +0000
+++ b/sys/arch/arm/nvidia/tegra_drm.h Tue Nov 10 22:14:05 2015 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: tegra_drm.h,v 1.1 2015/11/09 23:05:58 jmcneill Exp $ */
+/* $NetBSD: tegra_drm.h,v 1.2 2015/11/10 22:14:05 jmcneill Exp $ */
/*-
* Copyright (c) 2015 Jared D. McNeill <jmcneill%invisible.ca@localhost>
@@ -61,6 +61,8 @@
bus_size_t sc_dmasize;
bus_dmamap_t sc_dmamap;
void *sc_dmap;
+
+ uint32_t sc_vbl_received[2];
};
struct tegra_drmfb_attach_args {
@@ -78,6 +80,7 @@
bus_size_t size;
int intr;
int index;
+ void *ih;
};
struct tegra_encoder {
@@ -129,5 +132,8 @@
int tegra_drm_mode_init(struct drm_device *);
int tegra_drm_fb_init(struct drm_device *);
+u32 tegra_drm_get_vblank_counter(struct drm_device *, int);
+int tegra_drm_enable_vblank(struct drm_device *, int);
+void tegra_drm_disable_vblank(struct drm_device *, int);
#endif /* _ARM_TEGRA_DRM_H */
diff -r fc40c414bcbc -r f86103e9b18b sys/arch/arm/nvidia/tegra_drm_mode.c
--- a/sys/arch/arm/nvidia/tegra_drm_mode.c Tue Nov 10 20:56:20 2015 +0000
+++ b/sys/arch/arm/nvidia/tegra_drm_mode.c Tue Nov 10 22:14:05 2015 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: tegra_drm_mode.c,v 1.3 2015/11/10 00:33:39 jmcneill Exp $ */
+/* $NetBSD: tegra_drm_mode.c,v 1.4 2015/11/10 22:14:05 jmcneill Exp $ */
/*-
* Copyright (c) 2015 Jared D. McNeill <jmcneill%invisible.ca@localhost>
@@ -27,7 +27,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: tegra_drm_mode.c,v 1.3 2015/11/10 00:33:39 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: tegra_drm_mode.c,v 1.4 2015/11/10 22:14:05 jmcneill Exp $");
#include <drm/drmP.h>
#include <drm/drm_crtc.h>
@@ -58,6 +58,7 @@
static int tegra_crtc_init(struct drm_device *, int);
static void tegra_crtc_destroy(struct drm_crtc *);
+static int tegra_crtc_intr(void *);
static const struct drm_crtc_funcs tegra_crtc_funcs = {
.set_config = drm_crtc_helper_set_config,
@@ -187,6 +188,10 @@
if (error)
return error;
+ error = drm_vblank_init(ddev, 2);
+ if (error)
+ return error;
+
return 0;
}
@@ -275,9 +280,16 @@
}
crtc->size = size;
crtc->intr = intr;
+ crtc->ih = intr_establish(intr, IPL_VM, IST_LEVEL | IST_MPSAFE,
+ tegra_crtc_intr, crtc);
+ if (crtc->ih == NULL) {
+ DRM_ERROR("failed to establish interrupt for crtc %d\n", index);
+ }
tegra_car_dc_enable(crtc->index);
+ DC_WRITE(crtc, DC_CMD_INT_ENABLE_REG, DC_CMD_INT_V_BLANK);
+
drm_crtc_init(ddev, &crtc->base, &tegra_crtc_funcs);
drm_crtc_helper_add(&crtc->base, &tegra_crtc_helper_funcs);
@@ -289,6 +301,9 @@
{
struct tegra_crtc *tegra_crtc = to_tegra_crtc(crtc);
drm_crtc_cleanup(crtc);
+ if (tegra_crtc->ih) {
+ intr_disestablish(tegra_crtc->ih);
+ }
bus_space_unmap(tegra_crtc->bst, tegra_crtc->bsh, tegra_crtc->size);
kmem_free(tegra_crtc, sizeof(*tegra_crtc));
}
@@ -969,3 +984,73 @@
return encoder;
}
+
+static int
+tegra_crtc_intr(void *priv)
+{
+ struct tegra_crtc *tegra_crtc = priv;
+ struct drm_device *ddev = tegra_crtc->base.dev;
+ struct tegra_drm_softc * const sc = tegra_drm_private(ddev);
+ int rv = 0;
+
+ const uint32_t status = DC_READ(tegra_crtc, DC_CMD_INT_STATUS_REG);
+
+ if (status & DC_CMD_INT_V_BLANK) {
+ DC_WRITE(tegra_crtc, DC_CMD_INT_STATUS_REG, DC_CMD_INT_V_BLANK);
+ atomic_inc_32(&sc->sc_vbl_received[tegra_crtc->index]);
+ drm_handle_vblank(ddev, tegra_crtc->index);
+ rv = 1;
+ }
+
+ return rv;
+}
+
+u32
+tegra_drm_get_vblank_counter(struct drm_device *ddev, int crtc)
+{
+ struct tegra_drm_softc * const sc = tegra_drm_private(ddev);
+
+ if (crtc > 1)
+ return 0;
+
+ return sc->sc_vbl_received[crtc];
+}
+
+int
+tegra_drm_enable_vblank(struct drm_device *ddev, int crtc)
+{
+ struct tegra_crtc *tegra_crtc = NULL;
+ struct drm_crtc *iter;
+
+ list_for_each_entry(iter, &ddev->mode_config.crtc_list, head) {
+ if (to_tegra_crtc(iter)->index == crtc) {
+ tegra_crtc = to_tegra_crtc(iter);
+ break;
+ }
+ }
+ if (tegra_crtc == NULL)
+ return -EINVAL;
+
+ DC_SET_CLEAR(tegra_crtc, DC_CMD_INT_MASK_REG, DC_CMD_INT_V_BLANK, 0);
+
+ return 0;
+}
+
+void
+tegra_drm_disable_vblank(struct drm_device *ddev, int crtc)
+{
+ struct tegra_crtc *tegra_crtc = NULL;
+ struct drm_crtc *iter;
+
+ list_for_each_entry(iter, &ddev->mode_config.crtc_list, head) {
+ if (to_tegra_crtc(iter)->index == crtc) {
+ tegra_crtc = to_tegra_crtc(iter);
+ break;
+ }
+ }
+ if (tegra_crtc == NULL)
+ return;
+
+ DC_SET_CLEAR(tegra_crtc, DC_CMD_INT_MASK_REG, 0, DC_CMD_INT_V_BLANK);
+ DC_WRITE(tegra_crtc, DC_CMD_INT_STATUS_REG, DC_CMD_INT_V_BLANK);
+}
Home |
Main Index |
Thread Index |
Old Index