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);