Module Name:    src
Committed By:   jmcneill
Date:           Mon Nov 10 17:55:25 UTC 2014

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

Log Message:
HDMI framebuffer support, tested on Cubieboard2 and Hummingbird A31.


To generate a diff of this commit:
cvs rdiff -u -r1.26 -r1.27 src/sys/arch/arm/allwinner/awin_board.c
cvs rdiff -u -r1.2 -r1.3 src/sys/arch/arm/allwinner/awin_debe.c \
    src/sys/arch/arm/allwinner/awin_fb.c \
    src/sys/arch/arm/allwinner/awin_tcon.c
cvs rdiff -u -r1.4 -r1.5 src/sys/arch/arm/allwinner/awin_hdmi.c
cvs rdiff -u -r1.46 -r1.47 src/sys/arch/arm/allwinner/awin_reg.h
cvs rdiff -u -r1.21 -r1.22 src/sys/arch/arm/allwinner/awin_var.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/allwinner/awin_board.c
diff -u src/sys/arch/arm/allwinner/awin_board.c:1.26 src/sys/arch/arm/allwinner/awin_board.c:1.27
--- src/sys/arch/arm/allwinner/awin_board.c:1.26	Sun Nov  9 14:10:54 2014
+++ src/sys/arch/arm/allwinner/awin_board.c	Mon Nov 10 17:55:25 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: awin_board.c,v 1.26 2014/11/09 14:10:54 jmcneill Exp $	*/
+/*	$NetBSD: awin_board.c,v 1.27 2014/11/10 17:55:25 jmcneill Exp $	*/
 /*-
  * Copyright (c) 2012 The NetBSD Foundation, Inc.
  * All rights reserved.
@@ -36,7 +36,7 @@
 
 #include <sys/cdefs.h>
 
-__KERNEL_RCSID(1, "$NetBSD: awin_board.c,v 1.26 2014/11/09 14:10:54 jmcneill Exp $");
+__KERNEL_RCSID(1, "$NetBSD: awin_board.c,v 1.27 2014/11/10 17:55:25 jmcneill Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -411,9 +411,6 @@ awin_pll3_enable(void)
 		ncfg &= ~AWIN_A31_PLL3_CFG_MODE;
 		ncfg &= ~AWIN_A31_PLL3_CFG_MODE_SEL;
 		ncfg |= AWIN_A31_PLL3_CFG_FRAC_CLK_OUT;
-		/* 24MHz*N/M - for 29.7MHz, N=99, M=8 */
-		ncfg |= __SHIFTIN(98, AWIN_A31_PLL3_CFG_FACTOR_N);
-		ncfg |= __SHIFTIN(7, AWIN_A31_PLL3_CFG_PREDIV_M);
 		ncfg |= AWIN_PLL_CFG_ENABLE;
 	} else {
 		ncfg &= ~AWIN_PLL3_MODE_SEL;
@@ -424,6 +421,13 @@ awin_pll3_enable(void)
 	if (ncfg != ocfg) {
 		bus_space_write_4(bst, bsh,
 		    AWIN_CCM_OFFSET + AWIN_PLL3_CFG_REG, ncfg);
+
+		if (awin_chip_id() == AWIN_CHIP_ID_A31) {
+			do {
+				ncfg = bus_space_read_4(bst, bsh,
+				    AWIN_CCM_OFFSET + AWIN_PLL3_CFG_REG);
+			} while ((ncfg & AWIN_A31_PLL3_CFG_LOCK) == 0);
+		}
 	}
 }
 
@@ -445,11 +449,6 @@ awin_pll7_enable(void)
 		ncfg &= ~AWIN_A31_PLL7_CFG_MODE;
 		ncfg &= ~AWIN_A31_PLL7_CFG_MODE_SEL;
 		ncfg |= AWIN_A31_PLL7_CFG_FRAC_CLK_OUT;
-		/* 24MHz*N/M - for 29.7MHz, N=99, M=8 */
-		ncfg &= ~AWIN_A31_PLL7_CFG_FACTOR_N;
-		ncfg &= ~AWIN_A31_PLL7_CFG_PREDIV_M;
-		ncfg |= __SHIFTIN(98, AWIN_A31_PLL7_CFG_FACTOR_N);
-		ncfg |= __SHIFTIN(7, AWIN_A31_PLL7_CFG_PREDIV_M);
 		ncfg |= AWIN_PLL_CFG_ENABLE;
 	} else {
 		ncfg &= ~AWIN_PLL7_MODE_SEL;
@@ -477,18 +476,18 @@ awin_pll3_set_rate(uint32_t rate)
 		ncfg &= ~AWIN_PLL_CFG_ENABLE;
 	} else {
 		if (awin_chip_id() == AWIN_CHIP_ID_A31) {
-			unsigned int m = rate / 3000000;
-			ncfg |= AWIN_PLL3_MODE_SEL;
-			ncfg &= ~AWIN_PLL3_FACTOR_M;
-			ncfg |= __SHIFTIN(m, AWIN_PLL3_FACTOR_M);
-		} else {
 			unsigned int m = 8;
-			unsigned int n = rate / 3000000;
+			unsigned int n = rate / (AWIN_REF_FREQ / m);
 			ncfg |= AWIN_A31_PLL3_CFG_MODE_SEL;
 			ncfg &= ~AWIN_A31_PLL3_CFG_FACTOR_N;
 			ncfg |= __SHIFTIN(n - 1, AWIN_A31_PLL3_CFG_FACTOR_N);
 			ncfg &= ~AWIN_A31_PLL3_CFG_PREDIV_M;
 			ncfg |= __SHIFTIN(m - 1, AWIN_A31_PLL3_CFG_PREDIV_M);
+		} else {
+			unsigned int m = rate / 3000000;
+			ncfg |= AWIN_PLL3_MODE_SEL;
+			ncfg &= ~AWIN_PLL3_FACTOR_M;
+			ncfg |= __SHIFTIN(m, AWIN_PLL3_FACTOR_M);
 		}
 		ncfg |= AWIN_PLL_CFG_ENABLE;
 	}
@@ -496,5 +495,54 @@ awin_pll3_set_rate(uint32_t rate)
 	if (ncfg != ocfg) {
 		bus_space_write_4(bst, bsh,
 		    AWIN_CCM_OFFSET + AWIN_PLL3_CFG_REG, ncfg);
+
+		if (awin_chip_id() == AWIN_CHIP_ID_A31) {
+			do {
+				ncfg = bus_space_read_4(bst, bsh,
+				    AWIN_CCM_OFFSET + AWIN_PLL3_CFG_REG);
+			} while ((ncfg & AWIN_A31_PLL3_CFG_LOCK) == 0);
+		}
 	}
 }
+
+uint32_t
+awin_pll5x_get_rate(void)
+{
+	bus_space_tag_t bst = &awin_bs_tag;
+	bus_space_handle_t bsh = awin_core_bsh;
+	unsigned int n, k, p;
+
+	KASSERT(awin_chip_id() != AWIN_CHIP_ID_A31);
+
+	const uint32_t cfg = bus_space_read_4(bst, bsh,
+	    AWIN_CCM_OFFSET + AWIN_PLL5_CFG_REG);
+
+	n = __SHIFTOUT(cfg, AWIN_PLL_CFG_FACTOR_N);
+	k = __SHIFTOUT(cfg, AWIN_PLL_CFG_FACTOR_K);
+	p = __SHIFTOUT(cfg, AWIN_PLL5_OUT_EXT_DIV_P);
+
+	return (AWIN_REF_FREQ * n * k) >> p;
+}
+
+uint32_t
+awin_pll6_get_rate(void)
+{
+	bus_space_tag_t bst = &awin_bs_tag;
+	bus_space_handle_t bsh = awin_core_bsh;
+	unsigned int n, k, m;
+
+	const uint32_t cfg = bus_space_read_4(bst, bsh,
+	    AWIN_CCM_OFFSET + AWIN_PLL6_CFG_REG);
+
+	if (awin_chip_id() == AWIN_CHIP_ID_A31) {
+		n = __SHIFTOUT(cfg, AWIN_PLL_CFG_FACTOR_N) + 1;
+		k = __SHIFTOUT(cfg, AWIN_PLL_CFG_FACTOR_K) + 1;
+		m = 2;
+	} else {
+		n = __SHIFTOUT(cfg, AWIN_PLL_CFG_FACTOR_N);
+		k = __SHIFTOUT(cfg, AWIN_PLL_CFG_FACTOR_K) + 1;
+		m = __SHIFTOUT(cfg, AWIN_PLL_CFG_FACTOR_M) + 1;
+	}
+
+	return (AWIN_REF_FREQ * n * k) / m;
+}

Index: src/sys/arch/arm/allwinner/awin_debe.c
diff -u src/sys/arch/arm/allwinner/awin_debe.c:1.2 src/sys/arch/arm/allwinner/awin_debe.c:1.3
--- src/sys/arch/arm/allwinner/awin_debe.c:1.2	Sun Nov  9 14:30:55 2014
+++ src/sys/arch/arm/allwinner/awin_debe.c	Mon Nov 10 17:55:25 2014
@@ -1,4 +1,4 @@
-/* $NetBSD: awin_debe.c,v 1.2 2014/11/09 14:30:55 jmcneill Exp $ */
+/* $NetBSD: awin_debe.c,v 1.3 2014/11/10 17:55:25 jmcneill Exp $ */
 
 /*-
  * Copyright (c) 2014 Jared D. McNeill <[email protected]>
@@ -33,7 +33,7 @@
 #include "genfb.h"
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: awin_debe.c,v 1.2 2014/11/09 14:30:55 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: awin_debe.c,v 1.3 2014/11/10 17:55:25 jmcneill Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -109,33 +109,48 @@ awin_debe_attach(device_t parent, device
 	    &sc->sc_ccm_bsh);
 
 	aprint_naive("\n");
-	aprint_normal(": Display Engine Backend\n");
+	aprint_normal(": Display Engine Backend (BE%d)\n", loc->loc_port);
 
 	if (awin_chip_id() == AWIN_CHIP_ID_A31) {
 		awin_reg_set_clear(aio->aio_core_bst, aio->aio_ccm_bsh,
 		    AWIN_A31_AHB_RESET1_REG,
 		    AWIN_A31_AHB_RESET1_BE0_RST << loc->loc_port,
 		    0);
+	} else {
+		awin_reg_set_clear(aio->aio_core_bst, aio->aio_ccm_bsh,
+		    AWIN_BE0_SCLK_CFG_REG + (loc->loc_port * 4),
+		    AWIN_BEx_CLK_RST,
+		    0);
 	}
 
 	if (awin_chip_id() == AWIN_CHIP_ID_A31) {
+		uint32_t pll6_freq = awin_pll6_get_rate() * 2;
+		unsigned int clk_div = (pll6_freq + 299999999) / 300000000;
+
+#ifdef AWIN_DEBE_DEBUG
+		device_printf(sc->sc_dev, "PLL6 @ %u Hz\n", pll6_freq);
+		device_printf(sc->sc_dev, "div %d\n", clk_div);
+#endif
 		awin_reg_set_clear(aio->aio_core_bst, aio->aio_ccm_bsh,
 		    AWIN_BE0_SCLK_CFG_REG + (loc->loc_port * 4),
 		    __SHIFTIN(AWIN_A31_BEx_CLK_SRC_SEL_PLL6_2X,
-			      AWIN_A31_BEx_CLK_SRC_SEL),
-		    AWIN_A31_BEx_CLK_SRC_SEL);
-		awin_reg_set_clear(aio->aio_core_bst, aio->aio_ccm_bsh,
-		    AWIN_BE0_SCLK_CFG_REG + (loc->loc_port * 4),
-		    4 - 1, AWIN_BEx_CLK_DIV_RATIO_M);
+			      AWIN_A31_BEx_CLK_SRC_SEL) |
+		    __SHIFTIN(clk_div - 1, AWIN_BEx_CLK_DIV_RATIO_M),
+		    AWIN_A31_BEx_CLK_SRC_SEL | AWIN_BEx_CLK_DIV_RATIO_M);
 	} else {
+		uint32_t pll5x_freq = awin_pll5x_get_rate();
+		unsigned int clk_div = (pll5x_freq + 299999999) / 300000000;
+
+#ifdef AWIN_DEBE_DEBUG
+		device_printf(sc->sc_dev, "PLL5x @ %u Hz\n", pll5x_freq);
+		device_printf(sc->sc_dev, "div %d\n", clk_div);
+#endif
+
 		awin_reg_set_clear(aio->aio_core_bst, aio->aio_ccm_bsh,
 		    AWIN_BE0_SCLK_CFG_REG + (loc->loc_port * 4),
-		    AWIN_BEx_CLK_RST |
-		    __SHIFTIN(AWIN_BEx_CLK_SRC_SEL_PLL5, AWIN_BEx_CLK_SRC_SEL),
-		    AWIN_BEx_CLK_SRC_SEL);
-		awin_reg_set_clear(aio->aio_core_bst, aio->aio_ccm_bsh,
-		    AWIN_BE0_SCLK_CFG_REG + (loc->loc_port * 4),
-		    0 /* XXX */, AWIN_BEx_CLK_DIV_RATIO_M);
+		    __SHIFTIN(AWIN_BEx_CLK_SRC_SEL_PLL5, AWIN_BEx_CLK_SRC_SEL) |
+		    __SHIFTIN(clk_div - 1, AWIN_BEx_CLK_DIV_RATIO_M),
+		    AWIN_BEx_CLK_SRC_SEL | AWIN_BEx_CLK_DIV_RATIO_M);
 	}
 
 	awin_reg_set_clear(aio->aio_core_bst, aio->aio_ccm_bsh,
@@ -209,7 +224,6 @@ awin_debe_setup_fbdev(struct awin_debe_s
 			.afb_fb = sc->sc_dmap,
 			.afb_width = mode->hdisplay,
 			.afb_height = mode->vdisplay,
-			.afb_console = false, /* XXX */
 			.afb_dmat = sc->sc_dmat,
 			.afb_dmasegs = sc->sc_dmasegs,
 			.afb_ndmasegs = 1
@@ -225,6 +239,35 @@ awin_debe_setup_fbdev(struct awin_debe_s
 }
 
 void
+awin_debe_enable(bool enable)
+{
+	struct awin_debe_softc *sc;
+	device_t dev;
+	uint32_t val;
+
+	dev = device_find_by_driver_unit("awindebe", 0);
+	if (dev == NULL) {
+		printf("DEBE: no driver found\n");
+		return;
+	}
+	sc = device_private(dev);
+
+	if (enable) {
+		val = DEBE_READ(sc, AWIN_DEBE_REGBUFFCTL_REG);
+		val |= AWIN_DEBE_REGBUFFCTL_REGLOADCTL;
+		DEBE_WRITE(sc, AWIN_DEBE_REGBUFFCTL_REG, val);
+
+		val = DEBE_READ(sc, AWIN_DEBE_MODCTL_REG);
+		val |= AWIN_DEBE_MODCTL_START_CTL;
+		DEBE_WRITE(sc, AWIN_DEBE_MODCTL_REG, val);
+	} else {
+		val = DEBE_READ(sc, AWIN_DEBE_MODCTL_REG);
+		val &= ~AWIN_DEBE_MODCTL_START_CTL;
+		DEBE_WRITE(sc, AWIN_DEBE_MODCTL_REG, val);
+	}
+}
+
+void
 awin_debe_set_videomode(const struct videomode *mode)
 {
 	struct awin_debe_softc *sc;
@@ -249,11 +292,6 @@ awin_debe_set_videomode(const struct vid
 			return;
 		}
 
-		/* disable */
-		val = DEBE_READ(sc, AWIN_DEBE_MODCTL_REG);
-		val &= ~AWIN_DEBE_MODCTL_LAY0_EN;
-		DEBE_WRITE(sc, AWIN_DEBE_MODCTL_REG, val);
-
 		/* notify fb */
 		awin_debe_setup_fbdev(sc, mode);
 
@@ -269,7 +307,8 @@ awin_debe_set_videomode(const struct vid
 
 		val = DEBE_READ(sc, AWIN_DEBE_ATTCTL1_REG);
 		val &= ~AWIN_DEBE_ATTCTL1_LAY_FBFMT;
-		val |= AWIN_DEBE_ATTCTL1_LAY_FBFMT_XRGB8888;
+		val |= __SHIFTIN(AWIN_DEBE_ATTCTL1_LAY_FBFMT_XRGB8888,
+				 AWIN_DEBE_ATTCTL1_LAY_FBFMT);
 		val &= ~AWIN_DEBE_ATTCTL1_LAY_BRSWAPEN;
 		val &= ~AWIN_DEBE_ATTCTL1_LAY_FBPS;
 		DEBE_WRITE(sc, AWIN_DEBE_ATTCTL1_REG, val);
@@ -277,17 +316,6 @@ awin_debe_set_videomode(const struct vid
 		val = DEBE_READ(sc, AWIN_DEBE_MODCTL_REG);
 		val |= AWIN_DEBE_MODCTL_LAY0_EN;
 		DEBE_WRITE(sc, AWIN_DEBE_MODCTL_REG, val);
-
-		val = DEBE_READ(sc, AWIN_DEBE_REGBUFFCTL_REG);
-		val |= AWIN_DEBE_REGBUFFCTL_REGLOADCTL;
-		DEBE_WRITE(sc, AWIN_DEBE_REGBUFFCTL_REG, val);
-
-		delay(50000);
-
-		/* enable */
-		val = DEBE_READ(sc, AWIN_DEBE_MODCTL_REG);
-		val |= AWIN_DEBE_MODCTL_START_CTL;
-		DEBE_WRITE(sc, AWIN_DEBE_MODCTL_REG, val);
 	} else {
 		/* disable */
 		val = DEBE_READ(sc, AWIN_DEBE_MODCTL_REG);
Index: src/sys/arch/arm/allwinner/awin_fb.c
diff -u src/sys/arch/arm/allwinner/awin_fb.c:1.2 src/sys/arch/arm/allwinner/awin_fb.c:1.3
--- src/sys/arch/arm/allwinner/awin_fb.c:1.2	Sun Nov  9 14:30:55 2014
+++ src/sys/arch/arm/allwinner/awin_fb.c	Mon Nov 10 17:55:25 2014
@@ -1,4 +1,4 @@
-/* $NetBSD: awin_fb.c,v 1.2 2014/11/09 14:30:55 jmcneill Exp $ */
+/* $NetBSD: awin_fb.c,v 1.3 2014/11/10 17:55:25 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.2 2014/11/09 14:30:55 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: awin_fb.c,v 1.3 2014/11/10 17:55:25 jmcneill Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -86,7 +86,6 @@ awin_fb_attach(device_t parent, device_t
 	sc->sc_dmasegs = afb->afb_dmasegs;
 	sc->sc_ndmasegs = afb->afb_ndmasegs;
 
-	prop_dictionary_set_bool(cfg, "is_console", afb->afb_console);
 	prop_dictionary_set_uint32(cfg, "width", afb->afb_width);
 	prop_dictionary_set_uint32(cfg, "height", afb->afb_height);
 	prop_dictionary_set_uint8(cfg, "depth", 32);
@@ -110,7 +109,10 @@ awin_fb_attach(device_t parent, device_t
 
 	aprint_naive("\n");
 
-	if (afb->afb_console)
+	bool is_console = false;
+	prop_dictionary_get_bool(cfg, "is_console", &is_console);
+
+	if (is_console)
 		aprint_normal(": switching to framebuffer console\n");
 	else
 		aprint_normal("\n");
Index: src/sys/arch/arm/allwinner/awin_tcon.c
diff -u src/sys/arch/arm/allwinner/awin_tcon.c:1.2 src/sys/arch/arm/allwinner/awin_tcon.c:1.3
--- src/sys/arch/arm/allwinner/awin_tcon.c:1.2	Sun Nov  9 14:30:55 2014
+++ src/sys/arch/arm/allwinner/awin_tcon.c	Mon Nov 10 17:55:25 2014
@@ -1,4 +1,4 @@
-/* $NetBSD: awin_tcon.c,v 1.2 2014/11/09 14:30:55 jmcneill Exp $ */
+/* $NetBSD: awin_tcon.c,v 1.3 2014/11/10 17:55:25 jmcneill Exp $ */
 
 /*-
  * Copyright (c) 2014 Jared D. McNeill <[email protected]>
@@ -26,8 +26,10 @@
  * SUCH DAMAGE.
  */
 
+//#define AWIN_TCON_DEBUG
+
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: awin_tcon.c,v 1.2 2014/11/09 14:30:55 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: awin_tcon.c,v 1.3 2014/11/10 17:55:25 jmcneill Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -47,9 +49,10 @@ struct awin_tcon_softc {
 	device_t sc_dev;
 	bus_space_tag_t sc_bst;
 	bus_space_handle_t sc_bsh;
-	bus_space_handle_t sc_ccm_bsh;
+	bus_space_handle_t sc_ch1clk_bsh;
 	unsigned int sc_port;
 	unsigned int sc_clk_div;
+	bool sc_clk_dbl;
 };
 
 #define TCON_READ(sc, reg) \
@@ -90,11 +93,11 @@ awin_tcon_attach(device_t parent, device
 	sc->sc_port = loc->loc_port;
 	bus_space_subregion(sc->sc_bst, aio->aio_core_bsh,
 	    loc->loc_offset, loc->loc_size, &sc->sc_bsh);
-	bus_space_subregion(sc->sc_bst, aio->aio_ccm_bsh, 0, 0x1000,
-	    &sc->sc_ccm_bsh);
+	bus_space_subregion(sc->sc_bst, aio->aio_ccm_bsh,
+	    AWIN_LCD0_CH1_CLK_REG + (loc->loc_port * 4), 4, &sc->sc_ch1clk_bsh);
 
 	aprint_naive("\n");
-	aprint_normal(": LCD/TV timing controller\n");
+	aprint_normal(": LCD/TV timing controller (TCON%d)\n", loc->loc_port);
 
 	awin_pll3_enable();
 
@@ -103,28 +106,16 @@ awin_tcon_attach(device_t parent, device
 		    AWIN_A31_AHB_RESET1_REG,
 		    AWIN_A31_AHB_RESET1_LCD0_RST << loc->loc_port,
 		    0);
+	} else {
+		awin_reg_set_clear(aio->aio_core_bst, aio->aio_ccm_bsh,
+		    AWIN_LCD0_CH0_CLK_REG + (loc->loc_port * 4),
+		    AWIN_LCDx_CH0_CLK_LCDx_RST, 0);
 	}
 
 	awin_reg_set_clear(aio->aio_core_bst, aio->aio_ccm_bsh,
 	    AWIN_AHB_GATING1_REG, AWIN_AHB_GATING1_LCD0 << loc->loc_port, 0);
 
-	awin_reg_set_clear(aio->aio_core_bst, aio->aio_ccm_bsh,
-	    AWIN_LCD0_CH0_CLK_REG + (loc->loc_port * 4),
-	    __SHIFTIN(AWIN_LCDx_CHx_CLK_SRC_SEL_PLL3,
-		      AWIN_LCDx_CHx_CLK_SRC_SEL) |
-	    AWIN_CLK_OUT_ENABLE,
-	    AWIN_LCDx_CHx_CLK_SRC_SEL);
-	awin_reg_set_clear(aio->aio_core_bst, aio->aio_ccm_bsh,
-	    AWIN_LCD0_CH1_CLK_REG + (loc->loc_port * 4),
-	    __SHIFTIN(AWIN_LCDx_CHx_CLK_SRC_SEL_PLL3,
-		      AWIN_LCDx_CHx_CLK_SRC_SEL) |
-	    AWIN_CLK_OUT_ENABLE,
-	    AWIN_LCDx_CHx_CLK_SRC_SEL | AWIN_LCDx_CH1_SCLK1_SRC_SEL);
-
-	TCON_WRITE(sc, AWIN_TCON_GCTL_REG,
-	    __SHIFTIN(AWIN_TCON_GCTL_IO_MAP_SEL_TCON1,
-		      AWIN_TCON_GCTL_IO_MAP_SEL) |
-	    AWIN_TCON_GCTL_EN);
+	TCON_WRITE(sc, AWIN_TCON_GCTL_REG, 0);
 	TCON_WRITE(sc, AWIN_TCON_GINT0_REG, 0);
 	TCON_WRITE(sc, AWIN_TCON_GINT1_REG,
 	    __SHIFTIN(0x20, AWIN_TCON_GINT1_TCON1_LINENO));
@@ -134,38 +125,98 @@ awin_tcon_attach(device_t parent, device
 }
 
 static void
+awin_tcon_calc_pll(int f_ref, int f_out, int *pm, int *pn)
+{
+	int best = 1000000;
+	for (int m = 1; m <= 15; m++) {
+		for (int n = 9; n <= 127; n++) {
+			int f_cur = (n * f_ref) / m;
+			int diff = f_out - f_cur;
+			if (diff > 0 && diff < best) {
+				best = diff;
+				*pm = m;
+				*pn = n;
+			}
+		}
+	}
+}
+
+static void
 awin_tcon_set_pll(struct awin_tcon_softc *sc, const struct videomode *mode)
 {
-	unsigned int n, m, freq;
-	unsigned int m1 = ~0, n1 = ~0;
+	int n = 0, m = 0, n2 = 0, m2 = 0;
+	bool dbl = false;
 
-	for (m = 1; m <= 15; m++) {
-		n = (m * mode->dot_clock) / 3000;
-		freq = (n * 3000) / m;
-
-		if (freq == mode->dot_clock && m < m1) {
-			m1 = m;
-			n1 = n;
-		}
+	awin_tcon_calc_pll(3000, mode->dot_clock, &m, &n);
+	awin_tcon_calc_pll(6000, mode->dot_clock, &m2, &n2);
+
+	int f_single = m ? (n * 3000) / m : 0;
+	int f_double = m2 ? (n2 * 6000) / m2 : 0;
+
+	if (f_double > f_single) {
+		dbl = true;
+		n = n2;
+		m = m2;
 	}
 
-	if (m1 == ~0) {
-		device_printf(sc->sc_dev, "couldn't set rate %u Hz\n",
+	if (n == 0 || m == 0) {
+		device_printf(sc->sc_dev, "couldn't set pll to %d Hz\n",
 		    mode->dot_clock * 1000);
 		sc->sc_clk_div = 0;
 		return;
 	}
 
-	awin_pll3_set_rate(n1 * 3000000);
+#ifdef AWIN_TCON_DEBUG
+	device_printf(sc->sc_dev, "pll n=%d m=%d dbl=%c freq=%d\n", n, m,
+	    dbl ? 'Y' : 'N', n * 3000000);
+#endif
 
-	awin_reg_set_clear(sc->sc_bst, sc->sc_ccm_bsh,
-	    AWIN_LCD0_CH1_CLK_REG + (sc->sc_port * 4),
+	awin_pll3_set_rate(n * 3000000);
+
+	awin_reg_set_clear(sc->sc_bst, sc->sc_ch1clk_bsh, 0,
 	    AWIN_CLK_OUT_ENABLE |
 	    AWIN_LCDx_CH1_SCLK1_GATING |
-	    __SHIFTIN(m1 - 1, AWIN_LCDx_CH1_CLK_DIV_RATIO_M),
-	    AWIN_LCDx_CH1_CLK_DIV_RATIO_M);
+	    __SHIFTIN(dbl ? AWIN_LCDx_CHx_CLK_SRC_SEL_PLL3_2X :
+			    AWIN_LCDx_CHx_CLK_SRC_SEL_PLL3,
+		      AWIN_LCDx_CHx_CLK_SRC_SEL) |
+	    __SHIFTIN(m - 1, AWIN_LCDx_CH1_CLK_DIV_RATIO_M),
+	    AWIN_LCDx_CH1_CLK_DIV_RATIO_M |
+	    AWIN_LCDx_CHx_CLK_SRC_SEL |
+	    AWIN_LCDx_CH1_SCLK1_SRC_SEL);
+
+	sc->sc_clk_div = m;
+	sc->sc_clk_dbl = dbl;
+}
+
+void
+awin_tcon_enable(bool enable)
+{
+	struct awin_tcon_softc *sc;
+	device_t dev;
+	uint32_t val;
+
+	dev = device_find_by_driver_unit("awintcon", 0);
+	if (dev == NULL) {
+		printf("TCON: no driver found\n");
+		return;
+	}
+	sc = device_private(dev);
 
-	sc->sc_clk_div = m1;
+	val = TCON_READ(sc, AWIN_TCON_GCTL_REG);
+	if (enable) {
+		val |= AWIN_TCON_GCTL_EN;
+	} else {
+		val &= ~AWIN_TCON_GCTL_EN;
+	}
+	TCON_WRITE(sc, AWIN_TCON_GCTL_REG, val);
+
+	val = TCON_READ(sc, AWIN_TCON1_IO_TRI_REG);
+	if (enable) {
+		val &= ~0x03000000;
+	} else {
+		val |= 0x03000000;
+	}
+	TCON_WRITE(sc, AWIN_TCON1_IO_TRI_REG, val);
 }
 
 void
@@ -182,19 +233,26 @@ awin_tcon_set_videomode(const struct vid
 	}
 	sc = device_private(dev);
 
-	val = TCON_READ(sc, AWIN_TCON1_CTL_REG);
 	if (mode) {
-		const u_int hbp = mode->htotal - mode->hsync_start;
 		const u_int hspw = mode->hsync_end - mode->hsync_start;
-		const u_int vbp = mode->vtotal - mode->vsync_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;
+
+		val = TCON_READ(sc, AWIN_TCON_GCTL_REG);
+		val |= AWIN_TCON_GCTL_IO_MAP_SEL;
+		TCON_WRITE(sc, AWIN_TCON_GCTL_REG, val);
 
 		/* enable */
-		val |= AWIN_TCON_CTL_EN;
-		val &= ~AWIN_TCON_CTL_START_DELAY;
+		val = AWIN_TCON_CTL_EN;
 		val |= __SHIFTIN(0x1e, AWIN_TCON_CTL_START_DELAY);
+#ifdef AWIN_TCON_BLUEDATA
+		val |= __SHIFTIN(AWIN_TCON_CTL_SRC_SEL_BLUEDATA,
+				 AWIN_TCON_CTL_SRC_SEL);
+#else
 		val |= __SHIFTIN(AWIN_TCON_CTL_SRC_SEL_DE0,
 				 AWIN_TCON_CTL_SRC_SEL);
+#endif
 		TCON_WRITE(sc, AWIN_TCON1_CTL_REG, val);
 
 		/* Source width/height */
@@ -218,16 +276,9 @@ awin_tcon_set_videomode(const struct vid
 
 		/* Setup LCDx CH1 PLL */
 		awin_tcon_set_pll(sc, mode);
-
-		val = TCON_READ(sc, AWIN_TCON_GCTL_REG);
-		val |= AWIN_TCON_GCTL_EN;
-		TCON_WRITE(sc, AWIN_TCON_GCTL_REG, val);
-
-		val = TCON_READ(sc, AWIN_TCON1_IO_TRI_REG);
-		val &= ~0x03000000;
-		TCON_WRITE(sc, AWIN_TCON1_IO_TRI_REG, val);
 	} else {
 		/* disable */
+		val = TCON_READ(sc, AWIN_TCON1_CTL_REG);
 		val &= ~AWIN_TCON_CTL_EN;
 		TCON_WRITE(sc, AWIN_TCON1_CTL_REG, val);
 	}
@@ -248,3 +299,19 @@ awin_tcon_get_clk_div(void)
 
 	return sc->sc_clk_div;
 }
+
+bool
+awin_tcon_get_clk_dbl(void)
+{
+	struct awin_tcon_softc *sc;
+	device_t dev;
+
+	dev = device_find_by_driver_unit("awintcon", 0);
+	if (dev == NULL) {
+		printf("TCON: no driver found\n");
+		return 0;
+	}
+	sc = device_private(dev);
+
+	return sc->sc_clk_dbl;
+}

Index: src/sys/arch/arm/allwinner/awin_hdmi.c
diff -u src/sys/arch/arm/allwinner/awin_hdmi.c:1.4 src/sys/arch/arm/allwinner/awin_hdmi.c:1.5
--- src/sys/arch/arm/allwinner/awin_hdmi.c:1.4	Sun Nov  9 14:30:55 2014
+++ src/sys/arch/arm/allwinner/awin_hdmi.c	Mon Nov 10 17:55:25 2014
@@ -1,4 +1,4 @@
-/* $NetBSD: awin_hdmi.c,v 1.4 2014/11/09 14:30:55 jmcneill Exp $ */
+/* $NetBSD: awin_hdmi.c,v 1.5 2014/11/10 17:55:25 jmcneill Exp $ */
 
 /*-
  * Copyright (c) 2014 Jared D. McNeill <[email protected]>
@@ -26,14 +26,14 @@
  * SUCH DAMAGE.
  */
 
-#define AWIN_HDMI_DEBUG
+//#define AWIN_HDMI_DEBUG
 
 #include "opt_ddb.h"
 
 #define AWIN_HDMI_PLL	3	/* PLL7 or PLL3 */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: awin_hdmi.c,v 1.4 2014/11/09 14:30:55 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: awin_hdmi.c,v 1.5 2014/11/10 17:55:25 jmcneill Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -75,8 +75,8 @@ struct awin_hdmi_softc {
 #define HDMI_WRITE(sc, reg, val)		\
     bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, (reg), (val));
 
-#define HDMI_1_3_P(sc)	((sc)->sc_ver == 0x0103)
-#define HDMI_1_4_P(sc)	((sc)->sc_ver == 0x0104)
+#define HDMI_1_3_P(sc)	((sc)->sc_ver == 0x00010003)
+#define HDMI_1_4_P(sc)	((sc)->sc_ver == 0x00010004)
 
 static int	awin_hdmi_match(device_t, cfdata_t, void *);
 static void	awin_hdmi_attach(device_t, device_t, void *);
@@ -92,6 +92,7 @@ static int	awin_hdmi_i2c_reset(struct aw
 
 static void	awin_hdmi_enable(struct awin_hdmi_softc *);
 static void	awin_hdmi_read_edid(struct awin_hdmi_softc *);
+static void	awin_hdmi_video_enable(struct awin_hdmi_softc *, bool);
 static void	awin_hdmi_set_videomode(struct awin_hdmi_softc *,
 					const struct videomode *);
 static void	awin_hdmi_set_audiomode(struct awin_hdmi_softc *,
@@ -146,18 +147,17 @@ awin_hdmi_attach(device_t parent, device
 		    AWIN_A31_AHB_RESET1_REG, AWIN_A31_AHB_RESET1_HDMI_RST, 0);
 	}
 
-#if AWIN_HDMI_PLL == 7
-	clk = __SHIFTIN(AWIN_HDMI_CLK_SRC_SEL_PLL7, AWIN_HDMI_CLK_SRC_SEL);
-#else
+#if AWIN_HDMI_PLL == 3
 	clk = __SHIFTIN(AWIN_HDMI_CLK_SRC_SEL_PLL3, AWIN_HDMI_CLK_SRC_SEL);
+#else
+	clk = __SHIFTIN(AWIN_HDMI_CLK_SRC_SEL_PLL7, AWIN_HDMI_CLK_SRC_SEL);
 #endif
-	clk |= __SHIFTIN(0, AWIN_HDMI_CLK_DIV_RATIO_M);
 	clk |= AWIN_CLK_ENABLE;
 	if (awin_chip_id() == AWIN_CHIP_ID_A31) {
 		clk |= AWIN_A31_HDMI_CLK_DDC_GATING;
 	}
-	bus_space_write_4(aio->aio_core_bst, aio->aio_ccm_bsh,
-	    AWIN_HDMI_CLK_REG, clk);
+	awin_reg_set_clear(aio->aio_core_bst, aio->aio_ccm_bsh,
+	    AWIN_HDMI_CLK_REG, clk, AWIN_HDMI_CLK_SRC_SEL);
 	awin_reg_set_clear(aio->aio_core_bst, aio->aio_ccm_bsh,
 	    AWIN_AHB_GATING1_REG, AWIN_AHB_GATING1_HDMI, 0);
 
@@ -170,11 +170,7 @@ awin_hdmi_attach(device_t parent, device
 	aprint_normal(": HDMI %d.%d\n", vmaj, vmin);
 
 	sc->sc_ver = ver;
-	if (HDMI_1_3_P(sc)) {
-		sc->sc_i2c_blklen = 1;
-	} else {
-		sc->sc_i2c_blklen = 16;
-	}
+	sc->sc_i2c_blklen = 16;
 
 #if 0
 	sc->sc_ih = intr_establish(loc->loc_intr, IPL_SCHED, IST_LEVEL,
@@ -275,6 +271,11 @@ awin_hdmi_i2c_exec(void *priv, i2c_op_t 
 			    AWIN_A31_HDMI_DDC_FIFO_ACCESS_REG, pbuf, blklen);
 		}
 
+		printf("off=%d:", (int)off);
+		for (int i = 0; i < blklen; i++)
+			printf(" %02x", pbuf[i]);
+		printf("\n");
+
 		pbuf += blklen;
 		off += blklen;
 		resid -= blklen;
@@ -323,7 +324,7 @@ awin_hdmi_i2c_xfer_1_3(void *priv, i2c_a
 	if (retry == 0)
 		return ETIMEDOUT;
 
-	val = HDMI_READ(sc, AWIN_HDMI_DDC_FIFO_STATUS_REG);
+	val = HDMI_READ(sc, AWIN_HDMI_DDC_INT_STATUS_REG);
 	if ((val & AWIN_HDMI_DDC_INT_STATUS_TRANSFER_COMPLETE) == 0) {
 		device_printf(sc->sc_dev, "xfer failed, status=%08x\n", val);
 		return EIO;
@@ -406,7 +407,7 @@ awin_hdmi_i2c_reset(struct awin_hdmi_sof
 		HDMI_WRITE(sc, AWIN_HDMI_DDC_CTRL_REG,
 		    AWIN_HDMI_DDC_CTRL_EN | AWIN_HDMI_DDC_CTRL_SW_RST); 
 
-		delay(10000);
+		delay(1000);
 
 		ctrl = HDMI_READ(sc, AWIN_HDMI_DDC_CTRL_REG);
 		if (ctrl & AWIN_HDMI_DDC_CTRL_SW_RST) {
@@ -454,6 +455,8 @@ awin_hdmi_enable(struct awin_hdmi_softc 
 #elif AWIN_HDMI_PLL == 3
 	HDMI_WRITE(sc, AWIN_HDMI_PLL_DBG0_REG, (0<<21));
 #endif
+
+	delay(1000);
 }
 
 static void
@@ -464,32 +467,67 @@ awin_hdmi_read_edid(struct awin_hdmi_sof
 	struct edid_info ei;
 	int retry = 4;
 
+	memset(edid, 0, sizeof(edid));
+	memset(&ei, 0, sizeof(ei));
+
 	while (--retry > 0) {
 		if (ddc_read_edid(&sc->sc_ic, edid, sizeof(edid)) == 0)
 			break;
 	}
 	if (retry == 0) {
 		device_printf(sc->sc_dev, "failed to read EDID\n");
-		return;
-	}
-
-	edid_parse(edid, &ei);
+	} else {
+		if (edid_parse(edid, &ei) != 0) {
+			device_printf(sc->sc_dev, "failed to parse EDID\n");
+		}
 #ifdef AWIN_HDMI_DEBUG
-	edid_print(&ei);
+		else {
+			edid_print(&ei);
+		}
 #endif
+	}
 
 	mode = ei.edid_preferred_mode;
 	if (mode == NULL)
 		mode = pick_mode_by_ref(640, 480, 60);
 
-	awin_debe_set_videomode(mode);
-	awin_tcon_set_videomode(mode);
-
 	if (mode != NULL) {
-		delay(10000);
+		awin_debe_set_videomode(mode);
+		awin_tcon_set_videomode(mode);
 		awin_hdmi_set_videomode(sc, mode);
 		awin_hdmi_set_audiomode(sc, mode);
+		awin_debe_enable(true);
+		delay(20000);
+		awin_tcon_enable(true);
+		delay(20000);
+		awin_hdmi_video_enable(sc, true);
+	}
+}
+
+static void
+awin_hdmi_video_enable(struct awin_hdmi_softc *sc, bool enable)
+{
+	uint32_t val;
+
+	val = HDMI_READ(sc, AWIN_HDMI_VID_CTRL_REG);
+	val &= ~AWIN_HDMI_VID_CTRL_SRC_SEL;
+#ifdef AWIN_HDMI_CBGEN
+	val |= __SHIFTIN(AWIN_HDMI_VID_CTRL_SRC_SEL_CBGEN,
+			 AWIN_HDMI_VID_CTRL_SRC_SEL);
+#else
+	val |= __SHIFTIN(AWIN_HDMI_VID_CTRL_SRC_SEL_RGB,
+			 AWIN_HDMI_VID_CTRL_SRC_SEL);
+#endif
+	if (enable) {
+		val |= AWIN_HDMI_VID_CTRL_VIDEO_EN;
+	} else {
+		val &= ~AWIN_HDMI_VID_CTRL_VIDEO_EN;
 	}
+	HDMI_WRITE(sc, AWIN_HDMI_VID_CTRL_REG, val);
+
+#if defined(AWIN_HDMI_DEBUG) && defined(DDB)
+	awin_hdmi_dump_regs();
+#endif
 }
 
 static void
@@ -500,12 +538,12 @@ awin_hdmi_set_videomode(struct awin_hdmi
 	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 hbp = mode->htotal - mode->hsync_start;
 	const u_int hfp = mode->hsync_start - mode->hdisplay;
 	const u_int hspw = mode->hsync_end - mode->hsync_start;
-	const u_int vbp = mode->vtotal - mode->vsync_start;
+	const u_int hbp = mode->htotal - mode->hsync_start;
 	const u_int vfp = mode->vsync_start - mode->vdisplay;
 	const u_int vspw = mode->vsync_end - mode->vsync_start;
+	const u_int vbp = mode->vtotal - mode->vsync_start;
 
 #ifdef AWIN_HDMI_DEBUG
 	device_printf(sc->sc_dev,
@@ -517,17 +555,58 @@ awin_hdmi_set_videomode(struct awin_hdmi
 	    mode->vdisplay, vbp, vfp, vspw);
 #endif
 
-	HDMI_WRITE(sc, AWIN_HDMI_VID_CTRL_REG, 0);
 	HDMI_WRITE(sc, AWIN_HDMI_INT_STATUS_REG, 0xffffffff);
 
-	val = 0;
+	u_int clk_div = awin_tcon_get_clk_div();
+	bool clk_dbl = awin_tcon_get_clk_dbl();
+
+#ifdef AWIN_HDMI_DEBUG
+	device_printf(sc->sc_dev, "dot_clock: %d\n", mode->dot_clock);
+	device_printf(sc->sc_dev, "clkdiv: %d\n", clk_div);
+	device_printf(sc->sc_dev, "clkdbl: %c\n", clk_dbl ? 'Y' : 'N');
+#endif
+
+	if (clk_div == 0) {
+		device_printf(sc->sc_dev, "ERROR: TCON clk not configured\n");
+		return;
+	}
+
+	uint32_t pll_ctrl, pad_ctrl0, pad_ctrl1;
+	if (HDMI_1_4_P(sc)) {
+		pad_ctrl0 = 0x7e8000ff;
+		pad_ctrl1 = 0x01ded030;
+		pll_ctrl = 0xba48a308;
+		pll_ctrl |= __SHIFTIN(clk_div-1, AWIN_HDMI_PLL_CTRL_PREDIV);
+	} else {
+		pad_ctrl0 = 0xfe800000;
+		pad_ctrl1 = 0x00d8c830;
+		pll_ctrl = 0xfa4ef708;
+		pll_ctrl |= __SHIFTIN(clk_div, AWIN_HDMI_PLL_CTRL_PREDIV);
+	}
+	if (clk_dbl == false)
+		pad_ctrl1 |= 0x40;
+
+	HDMI_WRITE(sc, AWIN_HDMI_PAD_CTRL0_REG, pad_ctrl0);
+	HDMI_WRITE(sc, AWIN_HDMI_PAD_CTRL1_REG, pad_ctrl1);
+	HDMI_WRITE(sc, AWIN_HDMI_PLL_CTRL_REG, pll_ctrl);
+#if AWIN_HDMI_PLL == 7
+	HDMI_WRITE(sc, AWIN_HDMI_PLL_DBG0_REG, (1<<21));
+#elif AWIN_HDMI_PLL == 3
+	HDMI_WRITE(sc, AWIN_HDMI_PLL_DBG0_REG, (0<<21));
+#endif
+
+	val = HDMI_READ(sc, AWIN_HDMI_VID_CTRL_REG);
 	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);
 
@@ -570,55 +649,6 @@ awin_hdmi_set_videomode(struct awin_hdmi
 	val |= __SHIFTIN(AWIN_HDMI_VID_TIMING_4_TX_CLOCK_NORMAL,
 			 AWIN_HDMI_VID_TIMING_4_TX_CLOCK);
 	HDMI_WRITE(sc, AWIN_HDMI_VID_TIMING_4_REG, val);
-
-	u_int clk_div = awin_tcon_get_clk_div();
-
-#ifdef AWIN_HDMI_DEBUG
-	device_printf(sc->sc_dev, "dot_clock: %d\n", mode->dot_clock);
-	device_printf(sc->sc_dev, "clkdiv: %d\n", clk_div);
-#endif
-
-	if (clk_div == 0) {
-		device_printf(sc->sc_dev, "ERROR: TCON clk not configured\n");
-		return;
-	}
-
-	uint32_t pll_ctrl, pad_ctrl0, pad_ctrl1;
-	if (HDMI_1_4_P(sc)) {
-		pad_ctrl0 = 0x7e8000ff;
-		pad_ctrl1 = 0x01ded030 | 0x40;
-		pll_ctrl = 0xba48a308;
-		pll_ctrl |= __SHIFTIN(clk_div-1, AWIN_HDMI_PLL_CTRL_PREDIV);
-	} else {
-		pad_ctrl0 = 0xfe800000;
-		pad_ctrl1 = 0x00d8c830 | 0x40;
-		pll_ctrl = 0xfa4ef708;
-		pll_ctrl |= __SHIFTIN(clk_div, AWIN_HDMI_PLL_CTRL_PREDIV);
-	}
-
-	HDMI_WRITE(sc, AWIN_HDMI_PAD_CTRL0_REG, pad_ctrl0);
-	HDMI_WRITE(sc, AWIN_HDMI_PAD_CTRL1_REG, pad_ctrl1);
-	HDMI_WRITE(sc, AWIN_HDMI_PLL_CTRL_REG, pll_ctrl);
-
-#if AWIN_HDMI_PLL == 7
-	HDMI_WRITE(sc, AWIN_HDMI_PLL_DBG0_REG, (1<<21));
-#elif AWIN_HDMI_PLL == 3
-	HDMI_WRITE(sc, AWIN_HDMI_PLL_DBG0_REG, (0<<21));
-#endif
-
-	delay(50000);
-
-	val = HDMI_READ(sc, AWIN_HDMI_VID_CTRL_REG);
-#ifdef AWIN_HDMI_CBGEN
-	val |= __SHIFTIN(AWIN_HDMI_VID_CTRL_SRC_SEL_CBGEN,
-			 AWIN_HDMI_VID_CTRL_SRC_SEL);
-#endif
-	val |= AWIN_HDMI_VID_CTRL_VIDEO_EN;
-	HDMI_WRITE(sc, AWIN_HDMI_VID_CTRL_REG, val);
-
-#if defined(AWIN_HDMI_DEBUG) && defined(DDB)
-	awin_hdmi_dump_regs();
-#endif
 }
 
 static void
@@ -686,6 +716,7 @@ awin_hdmi_dump_regs(void)
 		uint16_t reg;
 	} regs[] = {
 		{ "CTRL", AWIN_HDMI_CTRL_REG },
+		{ "INT_STATUS", AWIN_HDMI_INT_STATUS_REG },
 		{ "VID_CTRL", AWIN_HDMI_VID_CTRL_REG },
 		{ "VID_TIMING_0", AWIN_HDMI_VID_TIMING_0_REG },
 		{ "VID_TIMING_1", AWIN_HDMI_VID_TIMING_1_REG },

Index: src/sys/arch/arm/allwinner/awin_reg.h
diff -u src/sys/arch/arm/allwinner/awin_reg.h:1.46 src/sys/arch/arm/allwinner/awin_reg.h:1.47
--- src/sys/arch/arm/allwinner/awin_reg.h:1.46	Sun Nov  9 14:10:54 2014
+++ src/sys/arch/arm/allwinner/awin_reg.h	Mon Nov 10 17:55:25 2014
@@ -967,6 +967,7 @@ struct awin_mmc_idma_descriptor {
 #define AWIN_PLL3_FACTOR_M		__BITS(6,0)
 
 #define AWIN_PLL5_CFG_DDR_CLK_EN	__BIT(29)
+#define AWIN_PLL5_OUT_EXT_DIV_P		__BITS(17,16)
 #define AWIN_PLL5_CFG_LDO_EN		__BIT(7)
 #define AWIN_PLL5_CFG_FACTOR_M1		__BITS(3,2)
 

Index: src/sys/arch/arm/allwinner/awin_var.h
diff -u src/sys/arch/arm/allwinner/awin_var.h:1.21 src/sys/arch/arm/allwinner/awin_var.h:1.22
--- src/sys/arch/arm/allwinner/awin_var.h:1.21	Sun Nov  9 14:30:55 2014
+++ src/sys/arch/arm/allwinner/awin_var.h	Mon Nov 10 17:55:25 2014
@@ -1,4 +1,4 @@
-/* $NetBSD: awin_var.h,v 1.21 2014/11/09 14:30:55 jmcneill Exp $ */
+/* $NetBSD: awin_var.h,v 1.22 2014/11/10 17:55:25 jmcneill Exp $ */
 /*-
  * Copyright (c) 2013 The NetBSD Foundation, Inc.
  * All rights reserved.
@@ -66,7 +66,6 @@ struct awinfb_attach_args {
 	void *afb_fb;
 	uint32_t afb_width;
 	uint32_t afb_height;
-	bool afb_console;
 	bus_dma_tag_t afb_dmat;
 	bus_dma_segment_t *afb_dmasegs;
 	int afb_ndmasegs;
@@ -100,6 +99,8 @@ void	awin_pll3_enable(void);
 void	awin_pll6_enable(void);
 void	awin_pll7_enable(void);
 void	awin_pll3_set_rate(uint32_t);
+uint32_t awin_pll5x_get_rate(void);
+uint32_t awin_pll6_get_rate(void);
 void	awin_cpu_hatch(struct cpu_info *);
 
 #define AWIN_CHIP_ID_A10	AWIN_SRAM_VER_KEY_A10
@@ -125,8 +126,11 @@ void	awin_dma_halt(void *);
 
 struct videomode;
 unsigned int awin_tcon_get_clk_div(void);
+bool	awin_tcon_get_clk_dbl(void);
 void	awin_tcon_set_videomode(const struct videomode *);
+void	awin_tcon_enable(bool);
 void	awin_debe_set_videomode(const struct videomode *);
+void	awin_debe_enable(bool);
 void	awin_fb_set_videomode(device_t, const struct videomode *);
 void	awin_fb_ddb_trap_callback(int);
 

Reply via email to