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 HDMI framebuffer support, tested on C...



details:   https://anonhg.NetBSD.org/src/rev/6529e650f025
branches:  trunk
changeset: 333596:6529e650f025
user:      jmcneill <jmcneill%NetBSD.org@localhost>
date:      Mon Nov 10 17:55:25 2014 +0000

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

diffstat:

 sys/arch/arm/allwinner/awin_board.c |   80 +++++++++++--
 sys/arch/arm/allwinner/awin_debe.c  |   94 +++++++++++------
 sys/arch/arm/allwinner/awin_fb.c    |   10 +-
 sys/arch/arm/allwinner/awin_hdmi.c  |  193 ++++++++++++++++++++---------------
 sys/arch/arm/allwinner/awin_reg.h   |    1 +
 sys/arch/arm/allwinner/awin_tcon.c  |  173 ++++++++++++++++++++++---------
 sys/arch/arm/allwinner/awin_var.h   |    8 +-
 7 files changed, 370 insertions(+), 189 deletions(-)

diffs (truncated from 995 to 300 lines):

diff -r 8541f15e82f7 -r 6529e650f025 sys/arch/arm/allwinner/awin_board.c
--- a/sys/arch/arm/allwinner/awin_board.c       Mon Nov 10 16:32:21 2014 +0000
+++ b/sys/arch/arm/allwinner/awin_board.c       Mon Nov 10 17:55:25 2014 +0000
@@ -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 @@
                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 @@
        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 @@
                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 @@
                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 @@
        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;
+}
diff -r 8541f15e82f7 -r 6529e650f025 sys/arch/arm/allwinner/awin_debe.c
--- a/sys/arch/arm/allwinner/awin_debe.c        Mon Nov 10 16:32:21 2014 +0000
+++ b/sys/arch/arm/allwinner/awin_debe.c        Mon Nov 10 17:55:25 2014 +0000
@@ -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 <jmcneill%invisible.ca@localhost>
@@ -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 @@
            &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_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),
-                   4 - 1, AWIN_BEx_CLK_DIV_RATIO_M);
-       } 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 |
-                   __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 @@
                        .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 @@
 }
 
 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 @@
                        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 @@
 
                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 @@
                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);
diff -r 8541f15e82f7 -r 6529e650f025 sys/arch/arm/allwinner/awin_fb.c
--- a/sys/arch/arm/allwinner/awin_fb.c  Mon Nov 10 16:32:21 2014 +0000



Home | Main Index | Thread Index | Old Index