Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/arch/arm/allwinner Add support for interlaced video modes.



details:   https://anonhg.NetBSD.org/src/rev/22e7dce665f1
branches:  trunk
changeset: 333688:22e7dce665f1
user:      jmcneill <jmcneill%NetBSD.org@localhost>
date:      Fri Nov 14 00:31:54 2014 +0000

description:
Add support for interlaced video modes.

diffstat:

 sys/arch/arm/allwinner/awin_debe.c |  26 ++++++++++++++++--------
 sys/arch/arm/allwinner/awin_fb.c   |  11 ++++++---
 sys/arch/arm/allwinner/awin_hdmi.c |  18 ++++------------
 sys/arch/arm/allwinner/awin_reg.h  |   5 ++++
 sys/arch/arm/allwinner/awin_tcon.c |  40 ++++++++++++++++++++++++++++++++++---
 5 files changed, 70 insertions(+), 30 deletions(-)

diffs (270 lines):

diff -r b21998f99ff7 -r 22e7dce665f1 sys/arch/arm/allwinner/awin_debe.c
--- a/sys/arch/arm/allwinner/awin_debe.c        Thu Nov 13 22:32:53 2014 +0000
+++ b/sys/arch/arm/allwinner/awin_debe.c        Fri Nov 14 00:31:54 2014 +0000
@@ -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 <jmcneill%invisible.ca@localhost>
@@ -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 @@
 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 @@
        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_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 @@
 
                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 */
diff -r b21998f99ff7 -r 22e7dce665f1 sys/arch/arm/allwinner/awin_fb.c
--- a/sys/arch/arm/allwinner/awin_fb.c  Thu Nov 13 22:32:53 2014 +0000
+++ b/sys/arch/arm/allwinner/awin_fb.c  Fri Nov 14 00:31:54 2014 +0000
@@ -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 <jmcneill%invisible.ca@localhost>
@@ -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 @@
        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");
        }
diff -r b21998f99ff7 -r 22e7dce665f1 sys/arch/arm/allwinner/awin_hdmi.c
--- a/sys/arch/arm/allwinner/awin_hdmi.c        Thu Nov 13 22:32:53 2014 +0000
+++ b/sys/arch/arm/allwinner/awin_hdmi.c        Fri Nov 14 00:31:54 2014 +0000
@@ -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 <jmcneill%invisible.ca@localhost>
@@ -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 @@
        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,
diff -r b21998f99ff7 -r 22e7dce665f1 sys/arch/arm/allwinner/awin_reg.h
--- a/sys/arch/arm/allwinner/awin_reg.h Thu Nov 13 22:32:53 2014 +0000
+++ b/sys/arch/arm/allwinner/awin_reg.h Fri Nov 14 00:31:54 2014 +0000
@@ -1747,12 +1747,17 @@
 #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)
diff -r b21998f99ff7 -r 22e7dce665f1 sys/arch/arm/allwinner/awin_tcon.c
--- a/sys/arch/arm/allwinner/awin_tcon.c        Thu Nov 13 22:32:53 2014 +0000
+++ b/sys/arch/arm/allwinner/awin_tcon.c        Fri Nov 14 00:31:54 2014 +0000
@@ -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 <jmcneill%invisible.ca@localhost>
@@ -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 @@
 
 #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 @@
        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 @@
 
                /* 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 @@
                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);



Home | Main Index | Thread Index | Old Index