Module Name:    src
Committed By:   jmcneill
Date:           Fri Nov 14 00:31:54 UTC 2014

Modified Files:
        src/sys/arch/arm/allwinner: awin_debe.c awin_fb.c awin_hdmi.c
            awin_reg.h awin_tcon.c

Log Message:
Add support for interlaced video modes.


To generate a diff of this commit:
cvs rdiff -u -r1.5 -r1.6 src/sys/arch/arm/allwinner/awin_debe.c
cvs rdiff -u -r1.3 -r1.4 src/sys/arch/arm/allwinner/awin_fb.c
cvs rdiff -u -r1.10 -r1.11 src/sys/arch/arm/allwinner/awin_hdmi.c
cvs rdiff -u -r1.48 -r1.49 src/sys/arch/arm/allwinner/awin_reg.h
cvs rdiff -u -r1.4 -r1.5 src/sys/arch/arm/allwinner/awin_tcon.c

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/allwinner/awin_debe.c
diff -u src/sys/arch/arm/allwinner/awin_debe.c:1.5 src/sys/arch/arm/allwinner/awin_debe.c:1.6
--- src/sys/arch/arm/allwinner/awin_debe.c:1.5	Wed Nov 12 23:12:27 2014
+++ src/sys/arch/arm/allwinner/awin_debe.c	Fri Nov 14 00:31:54 2014
@@ -1,4 +1,4 @@
-/* $NetBSD: awin_debe.c,v 1.5 2014/11/12 23:12:27 jmcneill Exp $ */
+/* $NetBSD: awin_debe.c,v 1.6 2014/11/14 00:31:54 jmcneill Exp $ */
 
 /*-
  * Copyright (c) 2014 Jared D. McNeill <[email protected]>
@@ -34,7 +34,7 @@
 #endif
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: awin_debe.c,v 1.5 2014/11/12 23:12:27 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: awin_debe.c,v 1.6 2014/11/14 00:31:54 jmcneill Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -221,10 +221,11 @@ static void
 awin_debe_setup_fbdev(struct awin_debe_softc *sc, const struct videomode *mode)
 {
 	if (mode && sc->sc_fbdev == NULL) {
+		const u_int interlace_p = !!(mode->flags & VID_INTERLACE);
 		struct awinfb_attach_args afb = {
 			.afb_fb = sc->sc_dmap,
 			.afb_width = mode->hdisplay,
-			.afb_height = mode->vdisplay,
+			.afb_height = (mode->vdisplay << interlace_p),
 			.afb_dmat = sc->sc_dmat,
 			.afb_dmasegs = sc->sc_dmasegs,
 			.afb_ndmasegs = 1
@@ -283,13 +284,15 @@ awin_debe_set_videomode(const struct vid
 	sc = device_private(dev);
 
 	if (mode) {
-		uint32_t vmem = mode->vdisplay * mode->hdisplay * 4;
+		const u_int interlace_p = !!(mode->flags & VID_INTERLACE);
+		const u_int width = mode->hdisplay;
+		const u_int height = (mode->vdisplay << interlace_p);
+		uint32_t vmem = width * height * 4;
 
 		if (vmem > sc->sc_dmasize) {
 			device_printf(sc->sc_dev,
 			    "not enough memory for %ux%u fb (req %u have %u)\n",
-			    mode->hdisplay, mode->vdisplay,
-			    vmem, (unsigned int)sc->sc_dmasize);
+			    width, height, vmem, (unsigned int)sc->sc_dmasize);
 			return;
 		}
 
@@ -305,10 +308,10 @@ awin_debe_set_videomode(const struct vid
 		awin_debe_setup_fbdev(sc, mode);
 
 		DEBE_WRITE(sc, AWIN_DEBE_DISSIZE_REG,
-		    ((mode->vdisplay - 1) << 16) | (mode->hdisplay - 1));
+		    ((height - 1) << 16) | (width - 1));
 		DEBE_WRITE(sc, AWIN_DEBE_LAYSIZE_REG,
-		    ((mode->vdisplay - 1) << 16) | (mode->hdisplay - 1));
-		DEBE_WRITE(sc, AWIN_DEBE_LAYLINEWIDTH_REG, mode->hdisplay << 5);
+		    ((height - 1) << 16) | (width - 1));
+		DEBE_WRITE(sc, AWIN_DEBE_LAYLINEWIDTH_REG, (width << 5));
 		DEBE_WRITE(sc, AWIN_DEBE_LAYFB_L32ADD_REG, pa << 3);
 		DEBE_WRITE(sc, AWIN_DEBE_LAYFB_H4ADD_REG, pa >> 29);
 
@@ -322,6 +325,11 @@ awin_debe_set_videomode(const struct vid
 
 		val = DEBE_READ(sc, AWIN_DEBE_MODCTL_REG);
 		val |= AWIN_DEBE_MODCTL_LAY0_EN;
+		if (interlace_p) {
+			val |= AWIN_DEBE_MODCTL_ITLMOD_EN;
+		} else {
+			val &= ~AWIN_DEBE_MODCTL_ITLMOD_EN;
+		}
 		DEBE_WRITE(sc, AWIN_DEBE_MODCTL_REG, val);
 	} else {
 		/* disable */

Index: src/sys/arch/arm/allwinner/awin_fb.c
diff -u src/sys/arch/arm/allwinner/awin_fb.c:1.3 src/sys/arch/arm/allwinner/awin_fb.c:1.4
--- src/sys/arch/arm/allwinner/awin_fb.c:1.3	Mon Nov 10 17:55:25 2014
+++ src/sys/arch/arm/allwinner/awin_fb.c	Fri Nov 14 00:31:54 2014
@@ -1,4 +1,4 @@
-/* $NetBSD: awin_fb.c,v 1.3 2014/11/10 17:55:25 jmcneill Exp $ */
+/* $NetBSD: awin_fb.c,v 1.4 2014/11/14 00:31:54 jmcneill Exp $ */
 
 /*-
  * Copyright (c) 2014 Jared D. McNeill <[email protected]>
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: awin_fb.c,v 1.3 2014/11/10 17:55:25 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: awin_fb.c,v 1.4 2014/11/14 00:31:54 jmcneill Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -189,8 +189,11 @@ awin_fb_set_videomode(device_t dev, cons
 	if (mode == NULL)
 		return;
 
-	if (sc->sc_gen.sc_width != mode->hdisplay ||
-	    sc->sc_gen.sc_height != mode->vdisplay) {
+	const u_int interlace_p = !!(mode->flags & VID_INTERLACE);
+	const u_int width = mode->hdisplay;
+	const u_int height = (mode->vdisplay << interlace_p);
+
+	if (sc->sc_gen.sc_width != width || sc->sc_gen.sc_height != height) {
 		device_printf(sc->sc_gen.sc_dev,
 		    "mode switching not yet supported\n");
 	}

Index: src/sys/arch/arm/allwinner/awin_hdmi.c
diff -u src/sys/arch/arm/allwinner/awin_hdmi.c:1.10 src/sys/arch/arm/allwinner/awin_hdmi.c:1.11
--- src/sys/arch/arm/allwinner/awin_hdmi.c:1.10	Wed Nov 12 17:38:14 2014
+++ src/sys/arch/arm/allwinner/awin_hdmi.c	Fri Nov 14 00:31:54 2014
@@ -1,4 +1,4 @@
-/* $NetBSD: awin_hdmi.c,v 1.10 2014/11/12 17:38:14 jmcneill Exp $ */
+/* $NetBSD: awin_hdmi.c,v 1.11 2014/11/14 00:31:54 jmcneill Exp $ */
 
 /*-
  * Copyright (c) 2014 Jared D. McNeill <[email protected]>
@@ -32,7 +32,7 @@
 #define AWIN_HDMI_PLL	3	/* PLL7 or PLL3 */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: awin_hdmi.c,v 1.10 2014/11/12 17:38:14 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: awin_hdmi.c,v 1.11 2014/11/14 00:31:54 jmcneill Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -601,29 +601,21 @@ awin_hdmi_set_videomode(struct awin_hdmi
 	val = HDMI_READ(sc, AWIN_HDMI_VID_CTRL_REG);
 	val |= __SHIFTIN(AWIN_HDMI_VID_CTRL_HDMI_MODE_HDMI,
 			 AWIN_HDMI_VID_CTRL_HDMI_MODE);
+	val &= ~AWIN_HDMI_VID_CTRL_OUTPUT_FMT;
 	if (dblscan_p) {
 		val |= __SHIFTIN(AWIN_HDMI_VID_CTRL_REPEATER_SEL_2X,
 				 AWIN_HDMI_VID_CTRL_REPEATER_SEL);
-	} else {
-		val &= ~AWIN_HDMI_VID_CTRL_REPEATER_SEL;
 	}
 	if (interlace_p) {
 		val |= __SHIFTIN(AWIN_HDMI_VID_CTRL_OUTPUT_FMT_INTERLACE,
 				 AWIN_HDMI_VID_CTRL_OUTPUT_FMT);
-	} else {
-		val &= ~AWIN_HDMI_VID_CTRL_OUTPUT_FMT;
 	}
 	HDMI_WRITE(sc, AWIN_HDMI_VID_CTRL_REG, val);
 
 	val = __SHIFTIN((mode->hdisplay << dblscan_p) - 1,
 			AWIN_HDMI_VID_TIMING_0_ACT_H);
-	if (interlace_p) {
-		val |= __SHIFTIN((mode->vdisplay / 2) - 1,
-				 AWIN_HDMI_VID_TIMING_0_ACT_V);
-	} else {
-		val |= __SHIFTIN(mode->vdisplay - 1,
-				 AWIN_HDMI_VID_TIMING_0_ACT_V);
-	}
+	val |= __SHIFTIN(mode->vdisplay - 1,
+			 AWIN_HDMI_VID_TIMING_0_ACT_V);
 	HDMI_WRITE(sc, AWIN_HDMI_VID_TIMING_0_REG, val);
 
 	val = __SHIFTIN((hbp << dblscan_p) - 1,

Index: src/sys/arch/arm/allwinner/awin_reg.h
diff -u src/sys/arch/arm/allwinner/awin_reg.h:1.48 src/sys/arch/arm/allwinner/awin_reg.h:1.49
--- src/sys/arch/arm/allwinner/awin_reg.h:1.48	Tue Nov 11 17:00:59 2014
+++ src/sys/arch/arm/allwinner/awin_reg.h	Fri Nov 14 00:31:54 2014
@@ -1747,12 +1747,17 @@ struct awin_mmc_idma_descriptor {
 #define AWIN_TCON_GINT1_TCON1_LINENO	__BITS(11,0)
 
 #define AWIN_TCON_CTL_EN		__BIT(31)
+#define AWIN_TCON_CTL_INTERLACE_EN	__BIT(20)
 #define AWIN_TCON_CTL_START_DELAY	__BITS(8,4)
 #define AWIN_TCON_CTL_SRC_SEL		__BITS(1,0)
 #define AWIN_TCON_CTL_SRC_SEL_DE0	0
 #define AWIN_TCON_CTL_SRC_SEL_DE1	1
 #define AWIN_TCON_CTL_SRC_SEL_BLUEDATA	2
 
+#define AWIN_TCON_IO_POL_IO2_INV	__BIT(26)
+#define AWIN_TCON_IO_POL_PVSYNC		__BIT(25)
+#define AWIN_TCON_IO_POL_PHSYNC		__BIT(24)
+
 #define AWIN_TCON_IO_TRI_IO3		__BIT(27)
 #define AWIN_TCON_IO_TRI_IO2		__BIT(26)
 #define AWIN_TCON_IO_TRI_IO1		__BIT(25)

Index: src/sys/arch/arm/allwinner/awin_tcon.c
diff -u src/sys/arch/arm/allwinner/awin_tcon.c:1.4 src/sys/arch/arm/allwinner/awin_tcon.c:1.5
--- src/sys/arch/arm/allwinner/awin_tcon.c:1.4	Tue Nov 11 19:22:32 2014
+++ src/sys/arch/arm/allwinner/awin_tcon.c	Fri Nov 14 00:31:54 2014
@@ -1,4 +1,4 @@
-/* $NetBSD: awin_tcon.c,v 1.4 2014/11/11 19:22:32 jmcneill Exp $ */
+/* $NetBSD: awin_tcon.c,v 1.5 2014/11/14 00:31:54 jmcneill Exp $ */
 
 /*-
  * Copyright (c) 2014 Jared D. McNeill <[email protected]>
@@ -29,7 +29,7 @@
 #include "opt_allwinner.h"
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: awin_tcon.c,v 1.4 2014/11/11 19:22:32 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: awin_tcon.c,v 1.5 2014/11/14 00:31:54 jmcneill Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -45,6 +45,8 @@ __KERNEL_RCSID(0, "$NetBSD: awin_tcon.c,
 
 #include <dev/videomode/videomode.h>
 
+#define DIVIDE(x,y)     (((x) + ((y) / 2)) / (y))
+
 struct awin_tcon_softc {
 	device_t sc_dev;
 	bus_space_tag_t sc_bst;
@@ -234,10 +236,17 @@ awin_tcon_set_videomode(const struct vid
 	sc = device_private(dev);
 
 	if (mode) {
+		const u_int interlace_p = !!(mode->flags & VID_INTERLACE);
+		const u_int phsync_p = !!(mode->flags & VID_PHSYNC);
+		const u_int pvsync_p = !!(mode->flags & VID_PVSYNC);
 		const u_int hspw = mode->hsync_end - mode->hsync_start;
 		const u_int hbp = mode->htotal - mode->hsync_start;
 		const u_int vspw = mode->vsync_end - mode->vsync_start;
 		const u_int vbp = mode->vtotal - mode->vsync_start;
+		const u_int vblank_len =
+		    ((mode->vtotal << interlace_p) >> 1) - mode->vdisplay - 2;
+		const u_int start_delay =
+		    vblank_len >= 32 ? 30 : vblank_len - 2;
 
 		val = TCON_READ(sc, AWIN_TCON_GCTL_REG);
 		val |= AWIN_TCON_GCTL_IO_MAP_SEL;
@@ -245,7 +254,9 @@ awin_tcon_set_videomode(const struct vid
 
 		/* enable */
 		val = AWIN_TCON_CTL_EN;
-		val |= __SHIFTIN(0x1e, AWIN_TCON_CTL_START_DELAY);
+		if (interlace_p)
+			val |= AWIN_TCON_CTL_INTERLACE_EN;
+		val |= __SHIFTIN(start_delay, AWIN_TCON_CTL_START_DELAY);
 #ifdef AWIN_TCON_BLUEDATA
 		val |= __SHIFTIN(AWIN_TCON_CTL_SRC_SEL_BLUEDATA,
 				 AWIN_TCON_CTL_SRC_SEL);
@@ -268,11 +279,32 @@ awin_tcon_set_videomode(const struct vid
 		TCON_WRITE(sc, AWIN_TCON1_BASIC3_REG,
 		    ((mode->htotal - 1) << 16) | (hbp - 1));
 		/* Vertical total + back porch */
+		u_int vtotal = mode->vtotal * 2;
+		if (interlace_p) {
+			u_int framerate =
+			    DIVIDE(DIVIDE(mode->dot_clock * 1000, mode->htotal),
+			    mode->vtotal);
+			u_int clk = mode->htotal * (mode->vtotal * 2 + 1) *
+			    framerate;
+			if ((clk / 2) == mode->dot_clock * 1000)
+				vtotal += 1;
+		}
 		TCON_WRITE(sc, AWIN_TCON1_BASIC4_REG,
-		    ((mode->vtotal * 2) << 16) | (vbp - 1));
+		    (vtotal << 16) | (vbp - 1));
+
 		/* Sync */
 		TCON_WRITE(sc, AWIN_TCON1_BASIC5_REG,
 		    ((hspw - 1) << 16) | (vspw - 1));
+		/* Polarity */
+		val = AWIN_TCON_IO_POL_IO2_INV;
+		if (phsync_p)
+			val |= AWIN_TCON_IO_POL_PHSYNC;
+		if (pvsync_p)
+			val |= AWIN_TCON_IO_POL_PVSYNC;
+		TCON_WRITE(sc, AWIN_TCON1_IO_POL_REG, val);
+
+		TCON_WRITE(sc, AWIN_TCON_GINT1_REG,
+		    __SHIFTIN(start_delay + 2, AWIN_TCON_GINT1_TCON1_LINENO));
 
 		/* Setup LCDx CH1 PLL */
 		awin_tcon_set_pll(sc, mode);

Reply via email to