Module Name:    src
Committed By:   jmcneill
Date:           Tue Nov 10 22:14:05 UTC 2015

Modified Files:
        src/sys/arch/arm/nvidia: tegra_dcreg.h tegra_drm.c tegra_drm.h
            tegra_drm_mode.c

Log Message:
Add vblank support


To generate a diff of this commit:
cvs rdiff -u -r1.3 -r1.4 src/sys/arch/arm/nvidia/tegra_dcreg.h \
    src/sys/arch/arm/nvidia/tegra_drm_mode.c
cvs rdiff -u -r1.1 -r1.2 src/sys/arch/arm/nvidia/tegra_drm.c \
    src/sys/arch/arm/nvidia/tegra_drm.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/arch/arm/nvidia/tegra_dcreg.h
diff -u src/sys/arch/arm/nvidia/tegra_dcreg.h:1.3 src/sys/arch/arm/nvidia/tegra_dcreg.h:1.4
--- src/sys/arch/arm/nvidia/tegra_dcreg.h:1.3	Thu Jul 23 15:08:19 2015
+++ src/sys/arch/arm/nvidia/tegra_dcreg.h	Tue Nov 10 22:14:05 2015
@@ -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 <[email protected]>
@@ -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
Index: src/sys/arch/arm/nvidia/tegra_drm_mode.c
diff -u src/sys/arch/arm/nvidia/tegra_drm_mode.c:1.3 src/sys/arch/arm/nvidia/tegra_drm_mode.c:1.4
--- src/sys/arch/arm/nvidia/tegra_drm_mode.c:1.3	Tue Nov 10 00:33:39 2015
+++ src/sys/arch/arm/nvidia/tegra_drm_mode.c	Tue Nov 10 22:14:05 2015
@@ -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 <[email protected]>
@@ -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 const struct drm_framebuffer_func
 
 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 @@ tegra_drm_mode_init(struct drm_device *d
 	if (error)
 		return error;
 
+	error = drm_vblank_init(ddev, 2);
+	if (error)
+		return error;
+
 	return 0;
 }
 
@@ -275,9 +280,16 @@ tegra_crtc_init(struct drm_device *ddev,
 	}
 	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 @@ tegra_crtc_destroy(struct drm_crtc *crtc
 {
 	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 @@ tegra_connector_best_encoder(struct drm_
 
 	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);
+}

Index: src/sys/arch/arm/nvidia/tegra_drm.c
diff -u src/sys/arch/arm/nvidia/tegra_drm.c:1.1 src/sys/arch/arm/nvidia/tegra_drm.c:1.2
--- src/sys/arch/arm/nvidia/tegra_drm.c:1.1	Mon Nov  9 23:05:58 2015
+++ src/sys/arch/arm/nvidia/tegra_drm.c	Tue Nov 10 22:14:05 2015
@@ -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 <[email protected]>
@@ -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 @@ static struct drm_driver tegra_drm_drive
 	.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,
Index: src/sys/arch/arm/nvidia/tegra_drm.h
diff -u src/sys/arch/arm/nvidia/tegra_drm.h:1.1 src/sys/arch/arm/nvidia/tegra_drm.h:1.2
--- src/sys/arch/arm/nvidia/tegra_drm.h:1.1	Mon Nov  9 23:05:58 2015
+++ src/sys/arch/arm/nvidia/tegra_drm.h	Tue Nov 10 22:14:05 2015
@@ -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 <[email protected]>
@@ -61,6 +61,8 @@ struct tegra_drm_softc {
 	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 @@ struct tegra_crtc {
 	bus_size_t		size;
 	int			intr;
 	int			index;
+	void			*ih;
 };
 
 struct tegra_encoder {
@@ -129,5 +132,8 @@ struct tegra_fbdev {
 
 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 */

Reply via email to