Add support for LVDS output on tcon0. Tested with a full HD LVDS display.
Other LCD interfaces not supported yet, mostly by lack of hardware. The LVDS output and timings are set from the FEX script.
This commit is contained in:
parent
c6240a4b43
commit
dd1e9ee14e
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: awin_hdmi.c,v 1.17 2015/10/25 20:54:19 bouyer Exp $ */
|
||||
/* $NetBSD: awin_hdmi.c,v 1.18 2015/11/15 21:28:54 bouyer Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2014 Jared D. McNeill <jmcneill@invisible.ca>
|
||||
@ -30,7 +30,7 @@
|
||||
#include "opt_ddb.h"
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: awin_hdmi.c,v 1.17 2015/10/25 20:54:19 bouyer Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: awin_hdmi.c,v 1.18 2015/11/15 21:28:54 bouyer Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/bus.h>
|
||||
@ -580,13 +580,13 @@ awin_hdmi_read_edid(struct awin_hdmi_softc *sc)
|
||||
|
||||
if (mode != NULL) {
|
||||
awin_hdmi_video_enable(sc, false);
|
||||
awin_tcon_enable(sc->sc_tcon_unit, false);
|
||||
awin_tcon1_enable(sc->sc_tcon_unit, false);
|
||||
delay(20000);
|
||||
|
||||
awin_tcon_set_videomode(sc->sc_tcon_unit, mode);
|
||||
awin_tcon1_set_videomode(sc->sc_tcon_unit, mode);
|
||||
awin_hdmi_set_videomode(sc, mode, display_mode);
|
||||
awin_hdmi_set_audiomode(sc, mode, display_mode);
|
||||
awin_tcon_enable(sc->sc_tcon_unit, true);
|
||||
awin_tcon1_enable(sc->sc_tcon_unit, true);
|
||||
delay(20000);
|
||||
awin_hdmi_video_enable(sc, true);
|
||||
}
|
||||
@ -928,7 +928,7 @@ awin_hdmi_hpd(struct awin_hdmi_softc *sc)
|
||||
awin_hdmi_read_edid(sc);
|
||||
} else {
|
||||
device_printf(sc->sc_dev, "display disconnected\n");
|
||||
awin_tcon_set_videomode(sc->sc_tcon_unit, NULL);
|
||||
awin_tcon1_set_videomode(sc->sc_tcon_unit, NULL);
|
||||
}
|
||||
|
||||
sc->sc_connected = con;
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: awin_reg.h,v 1.83 2015/11/09 10:10:39 bouyer Exp $ */
|
||||
/* $NetBSD: awin_reg.h,v 1.84 2015/11/15 21:28:54 bouyer Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2013 The NetBSD Foundation, Inc.
|
||||
@ -1111,6 +1111,8 @@ struct awin_mmc_idma_descriptor {
|
||||
#define AWIN_CLK_DIV_RATIO_N __BITS(17,16)
|
||||
#define AWIN_CLK_DIV_RATIO_M __BITS(3,0)
|
||||
|
||||
#define AWIN_LVDS_CLK_ENABLE __BIT(0)
|
||||
|
||||
#define AWIN_ISS_CLK_SRC_SEL __BITS(17,16)
|
||||
|
||||
#define AWIN_USB_CLK_USBPHY_ENABLE __BIT(8)
|
||||
@ -1161,7 +1163,7 @@ struct awin_mmc_idma_descriptor {
|
||||
#define AWIN_LCDx_CHx_CLK_SRC_SEL_PLL3 0
|
||||
#define AWIN_LCDx_CHx_CLK_SRC_SEL_PLL7 1
|
||||
#define AWIN_LCDx_CHx_CLK_SRC_SEL_PLL3_2X 2
|
||||
#define AWIN_LCDx_CHx_CLK_SRC_SEL_PLL7_2X 3
|
||||
#define AWIN_LCDx_CHx_CLK_SRC_SEL_PLL7_2X 3 /* for lcd0ch0 this is pll6x2 */
|
||||
#define AWIN_LCDx_CH1_SCLK1_GATING __BIT(15)
|
||||
#define AWIN_LCDx_CH1_SCLK1_SRC_SEL __BIT(11)
|
||||
#define AWIN_LCDx_CH1_CLK_DIV_RATIO_M __BITS(3,0)
|
||||
@ -1772,6 +1774,8 @@ struct awin_mmc_idma_descriptor {
|
||||
#define AWIN_TCON_GINT0_REG 0x0004
|
||||
#define AWIN_TCON_GINT1_REG 0x0008
|
||||
#define AWIN_TCON0_FRM_CTL_REG 0x0010
|
||||
#define AWIN_TCON0_FRM1_CTL_REG 0x0014
|
||||
#define AWIN_TCON0_FRM2_CTL_REG 0x002c
|
||||
#define AWIN_TCON0_CTL_REG 0x0040
|
||||
#define AWIN_TCON0_DCLK_REG 0x0044
|
||||
#define AWIN_TCON0_BASIC0_REG 0x0048
|
||||
@ -1806,6 +1810,8 @@ struct awin_mmc_idma_descriptor {
|
||||
#define AWIN_TCON_CMAP_EVEN0_REG 0x0198
|
||||
#define AWIN_TCON_CMAP_EVEN1_REG 0x019C
|
||||
#define AWIN_TCON_MUX_CTL_REG 0x0200 /* only in TCON0 */
|
||||
#define AWIN_TCON_LVDS_ANA0 0x220
|
||||
#define AWIN_TCON_LVDS_ANA1 0x224
|
||||
|
||||
#define AWIN_TCON_GCTL_EN __BIT(31)
|
||||
#define AWIN_TCON_GCTL_GAMMA_EN __BIT(30)
|
||||
@ -1816,13 +1822,33 @@ struct awin_mmc_idma_descriptor {
|
||||
#define AWIN_TCON_GINT1_TCON0_LINENO __BITS(27,16)
|
||||
#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_TCON0_FRM_ENABLE __BIT(31)
|
||||
#define AWIN_TCON0_FRM_R5BITS __BIT(6)
|
||||
#define AWIN_TCON0_FRM_G5BITS __BIT(5)
|
||||
#define AWIN_TCON0_FRM_B5BITS __BIT(4)
|
||||
|
||||
#define AWIN_TCONx_CTL_EN __BIT(31)
|
||||
#define AWIN_TCON0_CTL0_IF __BITS(25,24)
|
||||
#define AWIN_TCON0_CTL0_IF_HV 0
|
||||
#define AWIN_TCON0_CTL0_IF_8080 1
|
||||
#define AWIN_TCON0_CTL0_IF_TTL 2
|
||||
#define AWIN_TCON0_CTL_RG_SWAP __BIT(23)
|
||||
#define AWIN_TCON0_CTL_TSTV __BIT(22)
|
||||
#define AWIN_TCONx_CTL_INTERLACE_EN __BIT(20)
|
||||
#define AWIN_TCONx_CTL_START_DELAY __BITS(8,4)
|
||||
#define AWIN_TCONx_CTL_SRC_SEL __BITS(1,0)
|
||||
#define AWIN_TCONx_CTL_SRC_SEL_DE0 0
|
||||
#define AWIN_TCONx_CTL_SRC_SEL_DE1 1
|
||||
#define AWIN_TCONx_CTL_SRC_SEL_BLUEDATA 2
|
||||
|
||||
#define AWIN_TCON0_DCLK_DIV __BITS(6,0)
|
||||
|
||||
#define AWIN_TCON0_LVDS_IF_EN __BIT(31)
|
||||
#define AWIN_TCON0_LVDS_IF_DUALCHAN __BIT(30)
|
||||
#define AWIN_TCON0_LVDS_IF_DIR_REV __BIT(28)
|
||||
#define AWIN_TCON0_LVDS_IF_MODE_JEIDA __BIT(27)
|
||||
#define AWIN_TCON0_LVDS_IF_18BITS __BIT(26)
|
||||
#define AWIN_TCON0_LVDS_IF_CORR_MODE1 __BIT(23)
|
||||
|
||||
#define AWIN_TCON_IO_POL_IO2_INV __BIT(26)
|
||||
#define AWIN_TCON_IO_POL_PVSYNC __BIT(25)
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: awin_tcon.c,v 1.8 2015/11/03 19:28:28 bouyer Exp $ */
|
||||
/* $NetBSD: awin_tcon.c,v 1.9 2015/11/15 21:28:54 bouyer Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2014 Jared D. McNeill <jmcneill@invisible.ca>
|
||||
@ -29,7 +29,7 @@
|
||||
#include "opt_allwinner.h"
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: awin_tcon.c,v 1.8 2015/11/03 19:28:28 bouyer Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: awin_tcon.c,v 1.9 2015/11/15 21:28:54 bouyer Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/bus.h>
|
||||
@ -47,17 +47,37 @@ __KERNEL_RCSID(0, "$NetBSD: awin_tcon.c,v 1.8 2015/11/03 19:28:28 bouyer Exp $")
|
||||
|
||||
#define DIVIDE(x,y) (((x) + ((y) / 2)) / (y))
|
||||
|
||||
struct awin_tcon_gpio {
|
||||
const char *value;
|
||||
const char *name;
|
||||
};
|
||||
|
||||
|
||||
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_ch0clk_bsh;
|
||||
bus_space_handle_t sc_ch1clk_bsh;
|
||||
unsigned int sc_port;
|
||||
unsigned int sc_clk_pll;
|
||||
unsigned int sc_clk_div;
|
||||
bool sc_clk_dbl;
|
||||
unsigned int sc_debe_unit;
|
||||
unsigned int sc_output_type;
|
||||
#define OUTPUT_HDMI 0
|
||||
#define OUTPUT_LVDS 1
|
||||
const char *sc_lcdpwr_pin_name;
|
||||
struct awin_gpio_pindata sc_lcdpwr_pin;
|
||||
const char *sc_lcdblk_pin_name;
|
||||
struct awin_gpio_pindata sc_lcdblk_pin;
|
||||
};
|
||||
|
||||
static const struct awin_gpio_pinset awin_lvds0_pinset =
|
||||
{ 'D', AWIN_PIO_PD_LVDS0_FUNC, AWIN_PIO_PD_LVDS0_PINS};
|
||||
static const struct awin_gpio_pinset awin_lvds1_pinset =
|
||||
{ 'D', AWIN_PIO_PD_LVDS1_FUNC, AWIN_PIO_PD_LVDS1_PINS};
|
||||
|
||||
static bus_space_handle_t tcon_mux_bsh;
|
||||
static bool tcon_mux_inited = false;
|
||||
|
||||
@ -69,8 +89,8 @@ static bool tcon_mux_inited = false;
|
||||
static int awin_tcon_match(device_t, cfdata_t, void *);
|
||||
static void awin_tcon_attach(device_t, device_t, void *);
|
||||
|
||||
static void awin_tcon_set_pll(struct awin_tcon_softc *,
|
||||
const struct videomode *);
|
||||
static void awin_tcon_set_pll(struct awin_tcon_softc *, int, int);
|
||||
static void awin_tcon0_set_video(struct awin_tcon_softc *);
|
||||
|
||||
static void
|
||||
awin_tcon_clear_reset(struct awinio_attach_args * const aio, int unit)
|
||||
@ -112,12 +132,16 @@ awin_tcon_attach(device_t parent, device_t self, void *aux)
|
||||
struct awin_tcon_softc *sc = device_private(self);
|
||||
struct awinio_attach_args * const aio = aux;
|
||||
const struct awin_locators * const loc = &aio->aio_loc;
|
||||
prop_dictionary_t cfg = device_properties(self);
|
||||
const char *output;
|
||||
|
||||
sc->sc_dev = self;
|
||||
sc->sc_bst = aio->aio_core_bst;
|
||||
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,
|
||||
AWIN_LCD0_CH0_CLK_REG + (loc->loc_port * 4), 4, &sc->sc_ch0clk_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);
|
||||
if (!tcon_mux_inited) {
|
||||
@ -129,6 +153,18 @@ awin_tcon_attach(device_t parent, device_t self, void *aux)
|
||||
awin_tcon_clear_reset(aio, 0);
|
||||
}
|
||||
|
||||
if (prop_dictionary_get_cstring_nocopy(cfg, "output", &output)) {
|
||||
if (strcmp(output, "hdmi") == 0) {
|
||||
sc->sc_output_type = OUTPUT_HDMI;
|
||||
} else if (strcmp(output, "lvds") == 0) {
|
||||
sc->sc_output_type = OUTPUT_LVDS;
|
||||
} else {
|
||||
panic("tcon: wrong mode %s", output);
|
||||
}
|
||||
} else {
|
||||
sc->sc_output_type = OUTPUT_HDMI; /* default */
|
||||
}
|
||||
|
||||
aprint_naive("\n");
|
||||
aprint_normal(": LCD/TV timing controller (TCON%d)\n", loc->loc_port);
|
||||
switch (sc->sc_port) {
|
||||
@ -152,17 +188,25 @@ awin_tcon_attach(device_t parent, device_t self, void *aux)
|
||||
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));
|
||||
__SHIFTIN(0x20, AWIN_TCON_GINT1_TCON0_LINENO));
|
||||
TCON_WRITE(sc, AWIN_TCON0_DCLK_REG, 0xf0000000);
|
||||
TCON_WRITE(sc, AWIN_TCON0_CTL_REG, 0);
|
||||
TCON_WRITE(sc, AWIN_TCON0_IO_TRI_REG, 0xffffffff);
|
||||
TCON_WRITE(sc, AWIN_TCON1_CTL_REG, 0);
|
||||
TCON_WRITE(sc, AWIN_TCON1_IO_TRI_REG, 0xffffffff);
|
||||
if (sc->sc_output_type == OUTPUT_LVDS) {
|
||||
awin_reg_set_clear(aio->aio_core_bst, aio->aio_ccm_bsh,
|
||||
AWIN_LVDS_CLK_REG, AWIN_LVDS_CLK_ENABLE, 0);
|
||||
awin_tcon0_set_video(sc);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
awin_tcon_calc_pll(int f_ref, int f_out, int *pm, int *pn)
|
||||
awin_tcon_calc_pll(int f_ref, int f_out, int min_m, int *pm, int *pn)
|
||||
{
|
||||
int best = 1000000;
|
||||
for (int m = 1; m <= 15; m++) {
|
||||
KASSERT(min_m > 0);
|
||||
for (int m = min_m; m <= 15; m++) {
|
||||
for (int n = 9; n <= 127; n++) {
|
||||
int f_cur = (n * f_ref) / m;
|
||||
int diff = f_out - f_cur;
|
||||
@ -176,13 +220,13 @@ awin_tcon_calc_pll(int f_ref, int f_out, int *pm, int *pn)
|
||||
}
|
||||
|
||||
static void
|
||||
awin_tcon_set_pll(struct awin_tcon_softc *sc, const struct videomode *mode)
|
||||
awin_tcon_set_pll(struct awin_tcon_softc *sc, int dclk, int min_div)
|
||||
{
|
||||
int n = 0, m = 0, n2 = 0, m2 = 0;
|
||||
bool dbl = false;
|
||||
|
||||
awin_tcon_calc_pll(3000, mode->dot_clock, &m, &n);
|
||||
awin_tcon_calc_pll(6000, mode->dot_clock, &m2, &n2);
|
||||
awin_tcon_calc_pll(3000, dclk, min_div, &m, &n);
|
||||
awin_tcon_calc_pll(6000, dclk, min_div, &m2, &n2);
|
||||
|
||||
int f_single = m ? (n * 3000) / m : 0;
|
||||
int f_double = m2 ? (n2 * 6000) / m2 : 0;
|
||||
@ -195,42 +239,83 @@ awin_tcon_set_pll(struct awin_tcon_softc *sc, const struct videomode *mode)
|
||||
|
||||
if (n == 0 || m == 0) {
|
||||
device_printf(sc->sc_dev, "couldn't set pll to %d Hz\n",
|
||||
mode->dot_clock * 1000);
|
||||
dclk * 1000);
|
||||
sc->sc_clk_div = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
#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);
|
||||
device_printf(sc->sc_dev, "ch%d pll%d n=%d m=%d dbl=%c freq=%d\n",
|
||||
(sc->sc_output_type == OUTPUT_HDMI) ? 1 : 0,
|
||||
sc->sc_clk_pll, n, m, dbl ? 'Y' : 'N', n * 3000000);
|
||||
#endif
|
||||
|
||||
switch(sc->sc_clk_pll) {
|
||||
case 3:
|
||||
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(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);
|
||||
if (sc->sc_output_type == OUTPUT_HDMI) {
|
||||
awin_reg_set_clear(sc->sc_bst, sc->sc_ch1clk_bsh, 0,
|
||||
AWIN_CLK_OUT_ENABLE |
|
||||
AWIN_LCDx_CH1_SCLK1_GATING |
|
||||
__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);
|
||||
} else {
|
||||
awin_reg_set_clear(sc->sc_bst, sc->sc_ch0clk_bsh, 0,
|
||||
AWIN_CLK_OUT_ENABLE | AWIN_LCDx_CH0_CLK_LCDx_RST |
|
||||
__SHIFTIN(dbl ? AWIN_LCDx_CHx_CLK_SRC_SEL_PLL3_2X :
|
||||
AWIN_LCDx_CHx_CLK_SRC_SEL_PLL3,
|
||||
AWIN_LCDx_CHx_CLK_SRC_SEL),
|
||||
AWIN_LCDx_CHx_CLK_SRC_SEL);
|
||||
awin_reg_set_clear(sc->sc_bst, sc->sc_ch1clk_bsh, 0,
|
||||
AWIN_CLK_OUT_ENABLE |
|
||||
AWIN_LCDx_CH1_SCLK1_GATING |
|
||||
__SHIFTIN(dbl ? AWIN_LCDx_CHx_CLK_SRC_SEL_PLL3_2X :
|
||||
AWIN_LCDx_CHx_CLK_SRC_SEL_PLL3,
|
||||
AWIN_LCDx_CHx_CLK_SRC_SEL) |
|
||||
__SHIFTIN(10, 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);
|
||||
}
|
||||
break;
|
||||
case 7:
|
||||
awin_pll7_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(dbl ? AWIN_LCDx_CHx_CLK_SRC_SEL_PLL7_2X :
|
||||
AWIN_LCDx_CHx_CLK_SRC_SEL_PLL7,
|
||||
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);
|
||||
if (sc->sc_output_type == OUTPUT_HDMI) {
|
||||
awin_reg_set_clear(sc->sc_bst, sc->sc_ch1clk_bsh, 0,
|
||||
AWIN_CLK_OUT_ENABLE |
|
||||
AWIN_LCDx_CH1_SCLK1_GATING |
|
||||
__SHIFTIN(dbl ? AWIN_LCDx_CHx_CLK_SRC_SEL_PLL7_2X :
|
||||
AWIN_LCDx_CHx_CLK_SRC_SEL_PLL7,
|
||||
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);
|
||||
} else {
|
||||
/* pll7x2 not available for lcd0ch0 */
|
||||
KASSERT(dbl == false || sc->sc_port != 0);
|
||||
awin_reg_set_clear(sc->sc_bst, sc->sc_ch0clk_bsh, 0,
|
||||
AWIN_CLK_OUT_ENABLE | AWIN_LCDx_CH0_CLK_LCDx_RST |
|
||||
__SHIFTIN(dbl ? AWIN_LCDx_CHx_CLK_SRC_SEL_PLL7_2X :
|
||||
AWIN_LCDx_CHx_CLK_SRC_SEL_PLL7,
|
||||
AWIN_LCDx_CHx_CLK_SRC_SEL),
|
||||
AWIN_LCDx_CHx_CLK_SRC_SEL);
|
||||
awin_reg_set_clear(sc->sc_bst, sc->sc_ch1clk_bsh, 0,
|
||||
AWIN_CLK_OUT_ENABLE |
|
||||
AWIN_LCDx_CH1_SCLK1_GATING |
|
||||
__SHIFTIN(dbl ? AWIN_LCDx_CHx_CLK_SRC_SEL_PLL7_2X :
|
||||
AWIN_LCDx_CHx_CLK_SRC_SEL_PLL7,
|
||||
AWIN_LCDx_CHx_CLK_SRC_SEL) |
|
||||
__SHIFTIN(10, 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);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
panic("awin_tcon pll");
|
||||
@ -240,8 +325,220 @@ awin_tcon_set_pll(struct awin_tcon_softc *sc, const struct videomode *mode)
|
||||
sc->sc_clk_dbl = dbl;
|
||||
}
|
||||
|
||||
static void
|
||||
awin_tcon0_set_video(struct awin_tcon_softc *sc)
|
||||
{
|
||||
int32_t lcd_x, lcd_y, lcd_dclk_freq;
|
||||
int32_t lcd_hbp, lcd_ht, lcd_vbp, lcd_vt;
|
||||
int32_t lcd_hspw, lcd_vspw, lcd_io_cfg0;
|
||||
uint32_t vblk, start_delay;
|
||||
prop_dictionary_t cfg = device_properties(sc->sc_dev);
|
||||
uint32_t val;
|
||||
bool propb;
|
||||
bool dualchan = false;
|
||||
static struct videomode mode;
|
||||
|
||||
if (!prop_dictionary_get_int32(cfg, "lcd_x", &lcd_x)) {
|
||||
aprint_error_dev(sc->sc_dev, ": can't read lcd_x\n");
|
||||
return;
|
||||
}
|
||||
if (!prop_dictionary_get_int32(cfg, "lcd_y", &lcd_y)) {
|
||||
aprint_error_dev(sc->sc_dev, ": can't read lcd_y\n");
|
||||
return;
|
||||
}
|
||||
if (!prop_dictionary_get_int32(cfg, "lcd_dclk_freq", &lcd_dclk_freq)) {
|
||||
aprint_error_dev(sc->sc_dev, ": can't read lcd_dclk_freq\n");
|
||||
return;
|
||||
}
|
||||
if (!prop_dictionary_get_int32(cfg, "lcd_hbp", &lcd_hbp)) {
|
||||
aprint_error_dev(sc->sc_dev, ": can't read lcd_hbp\n");
|
||||
return;
|
||||
}
|
||||
if (!prop_dictionary_get_int32(cfg, "lcd_ht", &lcd_ht)) {
|
||||
aprint_error_dev(sc->sc_dev, ": can't read lcd_ht\n");
|
||||
return;
|
||||
}
|
||||
if (!prop_dictionary_get_int32(cfg, "lcd_vbp", &lcd_vbp)) {
|
||||
aprint_error_dev(sc->sc_dev, ": can't read lcd_vbp\n");
|
||||
return;
|
||||
}
|
||||
if (!prop_dictionary_get_int32(cfg, "lcd_vt", &lcd_vt)) {
|
||||
aprint_error_dev(sc->sc_dev, ": can't read lcd_vt\n");
|
||||
return;
|
||||
}
|
||||
if (!prop_dictionary_get_int32(cfg, "lcd_hspw", &lcd_hspw)) {
|
||||
aprint_error_dev(sc->sc_dev, ": can't read lcd_hspw\n");
|
||||
return;
|
||||
}
|
||||
if (!prop_dictionary_get_int32(cfg, "lcd_vspw", &lcd_vspw)) {
|
||||
aprint_error_dev(sc->sc_dev, ": can't read lcd_vspw\n");
|
||||
return;
|
||||
}
|
||||
if (!prop_dictionary_get_int32(cfg, "lcd_io_cfg0", &lcd_io_cfg0)) {
|
||||
aprint_error_dev(sc->sc_dev, ": can't read lcd_io_cfg0\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (prop_dictionary_get_bool(cfg, "lvds_dual", &propb) && propb)
|
||||
dualchan = true;
|
||||
if (!awin_gpio_pinset_available(&awin_lvds0_pinset)) {
|
||||
aprint_error_dev(sc->sc_dev, "lvds0 pins not available\n");
|
||||
return;
|
||||
}
|
||||
if (dualchan && !awin_gpio_pinset_available(&awin_lvds1_pinset)) {
|
||||
aprint_error_dev(sc->sc_dev, "lvds1 pins not available\n");
|
||||
return;
|
||||
}
|
||||
awin_gpio_pinset_acquire(&awin_lvds0_pinset);
|
||||
if (dualchan) {
|
||||
awin_gpio_pinset_acquire(&awin_lvds1_pinset);
|
||||
}
|
||||
prop_dictionary_get_cstring_nocopy(cfg, "lcd_power_en",
|
||||
&sc->sc_lcdpwr_pin_name);
|
||||
if (sc->sc_lcdpwr_pin_name != NULL) {
|
||||
if (!awin_gpio_pin_reserve(
|
||||
sc->sc_lcdpwr_pin_name, &sc->sc_lcdpwr_pin)) {
|
||||
aprint_error_dev(sc->sc_dev,
|
||||
"failed to reserve GPIO \"%s\" for LCD power\n",
|
||||
sc->sc_lcdpwr_pin_name);
|
||||
sc->sc_lcdpwr_pin_name = NULL;
|
||||
} else {
|
||||
aprint_verbose_dev(sc->sc_dev,
|
||||
": using GPIO \"%s\" for LCD power\n",
|
||||
sc->sc_lcdpwr_pin_name);
|
||||
}
|
||||
}
|
||||
prop_dictionary_get_cstring_nocopy(cfg, "lcd_bl_en",
|
||||
&sc->sc_lcdblk_pin_name);
|
||||
if (sc->sc_lcdblk_pin_name != NULL) {
|
||||
if (!awin_gpio_pin_reserve(
|
||||
sc->sc_lcdblk_pin_name, &sc->sc_lcdblk_pin)) {
|
||||
aprint_error_dev(sc->sc_dev,
|
||||
"failed to reserve GPIO \"%s\" for backlight\n",
|
||||
sc->sc_lcdblk_pin_name);
|
||||
sc->sc_lcdblk_pin_name = NULL;
|
||||
} else {
|
||||
if (sc->sc_lcdpwr_pin_name == NULL) {
|
||||
aprint_verbose_dev(sc->sc_dev,
|
||||
": using GPIO \"%s\" for backlight\n",
|
||||
sc->sc_lcdblk_pin_name);
|
||||
} else {
|
||||
aprint_verbose(
|
||||
", GPIO \"%s\" for backlight\n",
|
||||
sc->sc_lcdblk_pin_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (sc->sc_lcdpwr_pin_name != NULL) {
|
||||
awin_gpio_pindata_write(&sc->sc_lcdpwr_pin, 1);
|
||||
}
|
||||
|
||||
vblk = (lcd_vt / 2) - lcd_y;
|
||||
start_delay = (vblk >= 32) ? 30 : (vblk - 2);
|
||||
|
||||
if (lcd_dclk_freq > 150) /* hardware limit ? */
|
||||
lcd_dclk_freq = 150;
|
||||
awin_tcon_set_pll(sc, lcd_dclk_freq * 1000, 7);
|
||||
|
||||
val = AWIN_TCONx_CTL_EN;
|
||||
val |= __SHIFTIN(start_delay, AWIN_TCONx_CTL_START_DELAY);
|
||||
/*
|
||||
* the DE selector selects the primary DEBE for this tcon:
|
||||
* 0 selects debe0 for tcon0 and debe1 for tcon1
|
||||
*/
|
||||
val |= __SHIFTIN(AWIN_TCONx_CTL_SRC_SEL_DE0,
|
||||
AWIN_TCONx_CTL_SRC_SEL);
|
||||
TCON_WRITE(sc, AWIN_TCON0_CTL_REG, val);
|
||||
|
||||
val = (lcd_x - 1) << 16 | (lcd_y - 1);
|
||||
TCON_WRITE(sc, AWIN_TCON0_BASIC0_REG, val);
|
||||
val = (lcd_ht - 1) << 16 | (lcd_hbp - 1);
|
||||
TCON_WRITE(sc, AWIN_TCON0_BASIC1_REG, val);
|
||||
val = (lcd_vt) << 16 | (lcd_vbp - 1);
|
||||
TCON_WRITE(sc, AWIN_TCON0_BASIC2_REG, val);
|
||||
val = ((lcd_hspw > 0) ? (lcd_hspw - 1) : 0) << 16;
|
||||
val |= ((lcd_vspw > 0) ? (lcd_vspw - 1) : 0);
|
||||
TCON_WRITE(sc, AWIN_TCON0_BASIC3_REG, val);
|
||||
|
||||
val = 0;
|
||||
if (dualchan)
|
||||
val |= AWIN_TCON0_LVDS_IF_DUALCHAN;
|
||||
if (prop_dictionary_get_bool(cfg, "lvds_mode_jeida", &propb) && propb)
|
||||
val |= AWIN_TCON0_LVDS_IF_MODE_JEIDA;
|
||||
if (prop_dictionary_get_bool(cfg, "lvds_18bits", &propb) && propb)
|
||||
val |= AWIN_TCON0_LVDS_IF_18BITS;
|
||||
TCON_WRITE(sc, AWIN_TCON0_LVDS_IF_REG, val);
|
||||
|
||||
|
||||
TCON_WRITE(sc, AWIN_TCON0_IO_POL_REG, lcd_io_cfg0);
|
||||
TCON_WRITE(sc, AWIN_TCON0_IO_TRI_REG, 0);
|
||||
TCON_WRITE(sc, AWIN_TCON_GINT1_REG,
|
||||
__SHIFTIN(start_delay + 2, AWIN_TCON_GINT1_TCON0_LINENO));
|
||||
|
||||
val = 0xf0000000;
|
||||
val &= ~AWIN_TCON0_DCLK_DIV;
|
||||
val |= __SHIFTIN(sc->sc_clk_div, AWIN_TCON0_DCLK_DIV);
|
||||
TCON_WRITE(sc, AWIN_TCON0_DCLK_REG, val);
|
||||
|
||||
mode.dot_clock = lcd_dclk_freq;
|
||||
mode.hdisplay = lcd_x;
|
||||
mode.hsync_start = lcd_ht - lcd_hbp;
|
||||
mode.hsync_end = lcd_hspw + mode.hsync_start;
|
||||
mode.htotal = lcd_ht;
|
||||
mode.vdisplay = lcd_y;
|
||||
mode.vsync_start = lcd_vt - lcd_vbp;
|
||||
mode.vsync_end = lcd_vspw + mode.vsync_start;
|
||||
mode.vtotal = lcd_vt;
|
||||
mode.flags = 0;
|
||||
mode.name = NULL;
|
||||
|
||||
awin_debe_set_videomode(sc->sc_debe_unit, &mode);
|
||||
|
||||
/* and finally, enable it */
|
||||
awin_debe_enable(sc->sc_debe_unit, true);
|
||||
delay(20000);
|
||||
|
||||
val = TCON_READ(sc, AWIN_TCON_GCTL_REG);
|
||||
val |= AWIN_TCON_GCTL_EN;
|
||||
TCON_WRITE(sc, AWIN_TCON_GCTL_REG, val);
|
||||
delay(20000);
|
||||
|
||||
|
||||
val = TCON_READ(sc, AWIN_TCON0_LVDS_IF_REG);
|
||||
val |= AWIN_TCON0_LVDS_IF_EN;
|
||||
TCON_WRITE(sc, AWIN_TCON0_LVDS_IF_REG, val);
|
||||
|
||||
/* XXX
|
||||
* magic values here from linux. these are not documented
|
||||
* in the A20 user manual, and other Allwiner LVDS-capable SoC
|
||||
* documentation don't make sense with these values
|
||||
*/
|
||||
val = TCON_READ(sc, AWIN_TCON_LVDS_ANA0);
|
||||
val |= 0x3F310000;
|
||||
TCON_WRITE(sc, AWIN_TCON_LVDS_ANA0, val);
|
||||
val = TCON_READ(sc, AWIN_TCON_LVDS_ANA0);
|
||||
val |= 1 << 22;
|
||||
TCON_WRITE(sc, AWIN_TCON_LVDS_ANA0, val);
|
||||
delay(2);
|
||||
val = TCON_READ(sc, AWIN_TCON_LVDS_ANA1);
|
||||
val |= (0x1f << 26 | 0x1f << 10);
|
||||
TCON_WRITE(sc, AWIN_TCON_LVDS_ANA1, val);
|
||||
delay(2);
|
||||
val = TCON_READ(sc, AWIN_TCON_LVDS_ANA1);
|
||||
val |= (0x1f << 16 | 0x1f << 0);
|
||||
TCON_WRITE(sc, AWIN_TCON_LVDS_ANA1, val);
|
||||
val = TCON_READ(sc, AWIN_TCON_LVDS_ANA0);
|
||||
val |= 1 << 22;
|
||||
TCON_WRITE(sc, AWIN_TCON_LVDS_ANA0, val);
|
||||
|
||||
if (sc->sc_lcdblk_pin_name != NULL) {
|
||||
awin_gpio_pindata_write(&sc->sc_lcdblk_pin, 1);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
awin_tcon_enable(int unit, bool enable)
|
||||
awin_tcon1_enable(int unit, bool enable)
|
||||
{
|
||||
struct awin_tcon_softc *sc;
|
||||
device_t dev;
|
||||
@ -253,6 +550,7 @@ awin_tcon_enable(int unit, bool enable)
|
||||
return;
|
||||
}
|
||||
sc = device_private(dev);
|
||||
KASSERT(sc->sc_output_type == OUTPUT_HDMI);
|
||||
|
||||
awin_debe_enable(device_unit(sc->sc_dev), enable);
|
||||
delay(20000);
|
||||
@ -264,18 +562,12 @@ awin_tcon_enable(int unit, bool enable)
|
||||
}
|
||||
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);
|
||||
TCON_WRITE(sc, AWIN_TCON1_IO_TRI_REG, 0);
|
||||
|
||||
KASSERT(tcon_mux_inited);
|
||||
val = bus_space_read_4(sc->sc_bst, tcon_mux_bsh, 0);
|
||||
#ifdef AWIN_TCON_DEBUG
|
||||
printf("awin_tcon_enable(%d) val 0x%x", unit, val);
|
||||
printf("awin_tcon1_enable(%d) val 0x%x", unit, val);
|
||||
#endif
|
||||
val &= ~ AWIN_TCON_MUX_CTL_HDMI_OUTPUT_SRC;
|
||||
if (unit == 0) {
|
||||
@ -297,7 +589,7 @@ awin_tcon_enable(int unit, bool enable)
|
||||
}
|
||||
|
||||
void
|
||||
awin_tcon_set_videomode(int unit, const struct videomode *mode)
|
||||
awin_tcon1_set_videomode(int unit, const struct videomode *mode)
|
||||
{
|
||||
struct awin_tcon_softc *sc;
|
||||
device_t dev;
|
||||
@ -309,6 +601,7 @@ awin_tcon_set_videomode(int unit, const struct videomode *mode)
|
||||
return;
|
||||
}
|
||||
sc = device_private(dev);
|
||||
KASSERT(sc->sc_output_type == OUTPUT_HDMI);
|
||||
|
||||
awin_debe_set_videomode(device_unit(sc->sc_dev), mode);
|
||||
if (mode) {
|
||||
@ -329,20 +622,20 @@ awin_tcon_set_videomode(int unit, const struct videomode *mode)
|
||||
TCON_WRITE(sc, AWIN_TCON_GCTL_REG, val);
|
||||
|
||||
/* enable */
|
||||
val = AWIN_TCON_CTL_EN;
|
||||
val = AWIN_TCONx_CTL_EN;
|
||||
if (interlace_p)
|
||||
val |= AWIN_TCON_CTL_INTERLACE_EN;
|
||||
val |= __SHIFTIN(start_delay, AWIN_TCON_CTL_START_DELAY);
|
||||
val |= AWIN_TCONx_CTL_INTERLACE_EN;
|
||||
val |= __SHIFTIN(start_delay, AWIN_TCONx_CTL_START_DELAY);
|
||||
#ifdef AWIN_TCON1_BLUEDATA
|
||||
val |= __SHIFTIN(AWIN_TCON_CTL_SRC_SEL_BLUEDATA,
|
||||
AWIN_TCON_CTL_SRC_SEL);
|
||||
val |= __SHIFTIN(AWIN_TCONx_CTL_SRC_SEL_BLUEDATA,
|
||||
AWIN_TCONx_CTL_SRC_SEL);
|
||||
#else
|
||||
/*
|
||||
* the DE selector selects the primary DEBE for this tcon:
|
||||
* 0 selects debe0 for tcon0 and debe1 for tcon1
|
||||
*/
|
||||
val |= __SHIFTIN(AWIN_TCON_CTL_SRC_SEL_DE0,
|
||||
AWIN_TCON_CTL_SRC_SEL);
|
||||
val |= __SHIFTIN(AWIN_TCONx_CTL_SRC_SEL_DE0,
|
||||
AWIN_TCONx_CTL_SRC_SEL);
|
||||
#endif
|
||||
TCON_WRITE(sc, AWIN_TCON1_CTL_REG, val);
|
||||
|
||||
@ -387,19 +680,11 @@ awin_tcon_set_videomode(int unit, const struct videomode *mode)
|
||||
__SHIFTIN(start_delay + 2, AWIN_TCON_GINT1_TCON1_LINENO));
|
||||
|
||||
/* Setup LCDx CH1 PLL */
|
||||
awin_tcon_set_pll(sc, mode);
|
||||
#if 0
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < 0x800; i += 4) {
|
||||
printf("TCON 0x%04x: 0x%08x\n", i, TCON_READ(sc, i));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
awin_tcon_set_pll(sc, mode->dot_clock, 1);
|
||||
} else {
|
||||
/* disable */
|
||||
val = TCON_READ(sc, AWIN_TCON1_CTL_REG);
|
||||
val &= ~AWIN_TCON_CTL_EN;
|
||||
val &= ~AWIN_TCONx_CTL_EN;
|
||||
TCON_WRITE(sc, AWIN_TCON1_CTL_REG, val);
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: awin_var.h,v 1.37 2015/10/25 20:54:19 bouyer Exp $ */
|
||||
/* $NetBSD: awin_var.h,v 1.38 2015/11/15 21:28:54 bouyer Exp $ */
|
||||
/*-
|
||||
* Copyright (c) 2013 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
@ -140,8 +140,8 @@ struct videomode;
|
||||
unsigned int awin_tcon_get_clk_pll(int);
|
||||
unsigned int awin_tcon_get_clk_div(int);
|
||||
bool awin_tcon_get_clk_dbl(int);
|
||||
void awin_tcon_set_videomode(int, const struct videomode *);
|
||||
void awin_tcon_enable(int, bool);
|
||||
void awin_tcon1_set_videomode(int, const struct videomode *);
|
||||
void awin_tcon1_enable(int, bool);
|
||||
void awin_debe_set_videomode(int, const struct videomode *);
|
||||
void awin_debe_enable(int, bool);
|
||||
int awin_debe_ioctl(device_t, u_long, void *);
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: awin_machdep.c,v 1.46 2015/11/03 18:38:03 bouyer Exp $ */
|
||||
/* $NetBSD: awin_machdep.c,v 1.47 2015/11/15 21:28:54 bouyer Exp $ */
|
||||
|
||||
/*
|
||||
* Machine dependent functions for kernel setup for TI OSK5912 board.
|
||||
@ -125,7 +125,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: awin_machdep.c,v 1.46 2015/11/03 18:38:03 bouyer Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: awin_machdep.c,v 1.47 2015/11/15 21:28:54 bouyer Exp $");
|
||||
|
||||
#include "opt_machdep.h"
|
||||
#include "opt_ddb.h"
|
||||
@ -941,6 +941,10 @@ awin_gpio_sysconfig(prop_dictionary_t dict)
|
||||
{ "mmc0detect", "mmc0_para", "sdc_det" },
|
||||
{ "audiopactrl", "audio_para", "audio_pa_ctrl" },
|
||||
{ "gmacpwren", "gmac_phy_power", "gmac_phy_power_en" },
|
||||
{ "lcd0_power_en", "lcd0_para", "lcd_power" },
|
||||
{ "lcd0_bl_en", "lcd0_para", "lcd_bl_en" },
|
||||
{ "lcd1_power_en", "lcd1_para", "lcd_power" },
|
||||
{ "lcd1_bl_en", "lcd1_para", "lcd_bl_en" },
|
||||
};
|
||||
unsigned int n;
|
||||
|
||||
@ -1057,6 +1061,16 @@ awin_tcon_sysconfig(device_t self, prop_dictionary_t dict)
|
||||
if (type == 1) {
|
||||
/* LCD/LVDS output */
|
||||
awin_tcon_lcd_sysconfig("lcd0_para", dict);
|
||||
if (awin_sysconfig_get_int("lcd0_para",
|
||||
"lcd_bl_en_used") == 1) {
|
||||
prop_dictionary_set_cstring(dict,
|
||||
"lcd_bl_en", "lcd0_bl_en");
|
||||
}
|
||||
if (awin_sysconfig_get_int("lcd0_para",
|
||||
"lcd_power_used") == 1) {
|
||||
prop_dictionary_set_cstring(dict,
|
||||
"lcd_power_en", "lcd0_power_en");
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (type == 3) {
|
||||
@ -1071,6 +1085,16 @@ awin_tcon_sysconfig(device_t self, prop_dictionary_t dict)
|
||||
if (type == 1) {
|
||||
/* LCD/LVDS output */
|
||||
awin_tcon_lcd_sysconfig("lcd1_para", dict);
|
||||
if (awin_sysconfig_get_int("lcd1_para",
|
||||
"lcd_bl_en_used") == 1) {
|
||||
prop_dictionary_set_cstring(dict,
|
||||
"lcd_bl_en", "lcd1_bl_en");
|
||||
}
|
||||
if (awin_sysconfig_get_int("lcd1_para",
|
||||
"lcd_power_used") == 1) {
|
||||
prop_dictionary_set_cstring(dict,
|
||||
"lcd_power_en", "lcd1_power_en");
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (type == 3) {
|
||||
@ -1091,9 +1115,10 @@ awin_tcon_lcd_sysconfig(const char *key, prop_dictionary_t dict)
|
||||
"lcd_dclk_freq",
|
||||
"lcd_hbp",
|
||||
"lcd_ht",
|
||||
"lcd_hspw",
|
||||
"lcd_vbp",
|
||||
"lcd_vt",
|
||||
"lcd_hv_hspw",
|
||||
"lcd_vspw",
|
||||
"lcd_io_cfg0",
|
||||
};
|
||||
static const char *lcdgpio[] = {
|
||||
@ -1129,24 +1154,39 @@ awin_tcon_lcd_sysconfig(const char *key, prop_dictionary_t dict)
|
||||
unsigned int n;
|
||||
const char *cfg;
|
||||
|
||||
switch(awin_sysconfig_get_int(key, "lcd_if")) {
|
||||
case -1:
|
||||
/* error */
|
||||
return;
|
||||
case 3:
|
||||
prop_dictionary_set_cstring(dict, "output", "lvds");
|
||||
|
||||
if (awin_sysconfig_get_int(key, "lcd_lvds_ch") == 1)
|
||||
prop_dictionary_set_bool(dict, "lvds_dual", true);
|
||||
else
|
||||
prop_dictionary_set_bool(dict, "lvds_dual", false);
|
||||
|
||||
if (awin_sysconfig_get_int(key, "lcd_lvds_mode") == 1)
|
||||
prop_dictionary_set_bool(dict, "lvds_mode_jeida", true);
|
||||
else
|
||||
prop_dictionary_set_bool(dict, "lvds_mode_jeida", false);
|
||||
|
||||
if (awin_sysconfig_get_int(key, "lcd_lvds_bitwidth") == 1)
|
||||
prop_dictionary_set_bool(dict, "lvds_18bits", true);
|
||||
else
|
||||
prop_dictionary_set_bool(dict, "lvds_18bits", false);
|
||||
break;
|
||||
default:
|
||||
/* unsupported */
|
||||
return;
|
||||
}
|
||||
|
||||
for (n = 0; n < __arraycount(lcdtimings); n++) {
|
||||
int value = awin_sysconfig_get_int( key, lcdtimings[n]);
|
||||
if (value >= 0) {
|
||||
prop_dictionary_set_int32(dict, lcdtimings[n], value);
|
||||
}
|
||||
}
|
||||
if (awin_sysconfig_get_int(key, "lcd_bl_en_used") == 1) {
|
||||
cfg = awin_sysconfig_get_gpio(key, "lcd_bl_en");
|
||||
if (cfg != NULL) {
|
||||
prop_dictionary_set_cstring(dict, "lcd_bl_en", cfg);
|
||||
}
|
||||
}
|
||||
if (awin_sysconfig_get_int(key, "lcd_power_used") == 1) {
|
||||
cfg = awin_sysconfig_get_gpio(key, "lcd_power");
|
||||
if (cfg != NULL) {
|
||||
prop_dictionary_set_cstring(dict, "lcd_bl_en", cfg);
|
||||
}
|
||||
}
|
||||
for (n = 0; n < __arraycount(lcdgpio); n++) {
|
||||
cfg = awin_sysconfig_get_string(key, lcdgpio[n]);
|
||||
if (cfg != NULL) {
|
||||
|
Loading…
Reference in New Issue
Block a user