mirror of
https://xff.cz/git/u-boot/
synced 2025-09-04 10:12:14 +02:00
video: sunxi: Support LVDS output on A83T
- Enable LVDS pins (PD18-PD27) - De-assert LVDS interface reset line - Enable sunxi_lcd platform device for A83T - Really disable all interrupts - A83T does have only a simple clock gate for TCON0 clock (no need to select source) - Lifted some analog circuitry setup magic from the Linux driver Signed-off-by: Ondrej Jirman <megous@megous.com>
This commit is contained in:
@@ -280,11 +280,17 @@ struct sunxi_ccm_reg {
|
||||
#define CCM_DRAM_GATE_OFFSET_DE_BE0 26
|
||||
#define CCM_DRAM_GATE_OFFSET_DE_BE1 27
|
||||
|
||||
|
||||
#define MBUS_CLK_DEFAULT 0x81000002 /* PLL6 / 2 */
|
||||
|
||||
#define MBUS_CLK_GATE (0x1 << 31)
|
||||
|
||||
#define CCM_LCD_CH0_CTRL_PLL3 (0 << 24)
|
||||
#define CCM_LCD_CH0_CTRL_GATE (0x1 << 31)
|
||||
|
||||
#define CCM_LCD_CH1_CTRL_M(n) ((((n) - 1) & 0xf) << 0)
|
||||
#define CCM_LCD_CH1_CTRL_PLL3 (0 << 24)
|
||||
#define CCM_LCD_CH1_CTRL_GATE (0x1 << 31)
|
||||
|
||||
/* ahb_reset0 offsets */
|
||||
#define AHB_RESET_OFFSET_GMAC 17
|
||||
#define AHB_RESET_OFFSET_MCTL 14
|
||||
|
@@ -79,15 +79,18 @@ struct sunxi_lcdc_reg {
|
||||
#define SUNXI_LCDC_TCON0_CTRL_ENABLE (1 << 31)
|
||||
#define SUNXI_LCDC_TCON0_DCLK_DIV(n) ((n) << 0)
|
||||
#define SUNXI_LCDC_TCON0_DCLK_ENABLE (0xf << 28)
|
||||
#define SUNXI_LCDC_TCON0_DCLK_ENABLE_1 (1 << 31)
|
||||
#define SUNXI_LCDC_TCON0_TIMING_H_BP(n) (((n) - 1) << 0)
|
||||
#define SUNXI_LCDC_TCON0_TIMING_H_TOTAL(n) (((n) - 1) << 16)
|
||||
#define SUNXI_LCDC_TCON0_TIMING_V_BP(n) (((n) - 1) << 0)
|
||||
#define SUNXI_LCDC_TCON0_TIMING_V_TOTAL(n) (((n) * 2) << 16)
|
||||
#ifdef CONFIG_SUNXI_GEN_SUN6I
|
||||
#if defined(CONFIG_SUNXI_GEN_SUN6I) || defined(CONFIG_MACH_SUN8I_A83T)
|
||||
#define SUNXI_LCDC_TCON0_LVDS_CLK_SEL_TCON0 (1 << 20)
|
||||
#else
|
||||
#define SUNXI_LCDC_TCON0_LVDS_CLK_SEL_TCON0 0 /* NA */
|
||||
#endif
|
||||
#define SUNXI_LCDC_TCON0_LVDS_IF_CLK_POL_NORMAL (1 << 4)
|
||||
#define SUNXI_LCDC_TCON0_LVDS_IF_DATA_POL_NORMAL (0xf)
|
||||
#define SUNXI_LCDC_TCON0_LVDS_INTF_BITWIDTH(n) ((n) << 26)
|
||||
#define SUNXI_LCDC_TCON0_LVDS_INTF_ENABLE (1 << 31)
|
||||
#define SUNXI_LCDC_TCON0_IO_POL_DCLK_PHASE(x) ((x) << 28)
|
||||
@@ -103,10 +106,15 @@ struct sunxi_lcdc_reg {
|
||||
#define SUNXI_LCDC_MUX_CTRL_SRC1_MASK (0xf << 4)
|
||||
#define SUNXI_LCDC_MUX_CTRL_SRC1(x) ((x) << 4)
|
||||
#ifdef CONFIG_SUNXI_GEN_SUN6I
|
||||
#define SUNXI_LCDC_LVDS_ANA0 0x40040320
|
||||
#define SUNXI_LCDC_LVDS_ANA0_EN_MB (1 << 31)
|
||||
#define SUNXI_LCDC_LVDS_ANA0_DRVC (1 << 24)
|
||||
#define SUNXI_LCDC_LVDS_ANA0_DRVD(x) ((x) << 20)
|
||||
#define SUNXI_LCDC_LVDS_ANA0_EN_LDO (1 << 30)
|
||||
#define SUNXI_LCDC_LVDS_ANA0_EN_DRVC (1 << 24)
|
||||
#define SUNXI_LCDC_LVDS_ANA0_EN_DRVD(x) (((x) & 0xf) << 20)
|
||||
#define SUNXI_LCDC_LVDS_ANA0_C(x) (((x) & 3) << 17)
|
||||
#define SUNXI_LCDC_LVDS_ANA0_V(x) (((x) & 3) << 8)
|
||||
#define SUNXI_LCDC_LVDS_ANA0_PD(x) (((x) & 3) << 4)
|
||||
#else
|
||||
#define SUNXI_LCDC_LVDS_ANA0 0x3f310000
|
||||
#define SUNXI_LCDC_LVDS_ANA0_UPDATE (1 << 22)
|
||||
|
@@ -32,6 +32,7 @@ void lcdc_init(struct sunxi_lcdc_reg * const lcdc)
|
||||
/* Init lcdc */
|
||||
writel(0, &lcdc->ctrl); /* Disable tcon */
|
||||
writel(0, &lcdc->int0); /* Disable all interrupts */
|
||||
writel(0, &lcdc->int1);
|
||||
|
||||
/* Disable tcon0 dot clock */
|
||||
clrbits_le32(&lcdc->tcon0_dclk, SUNXI_LCDC_TCON0_DCLK_ENABLE);
|
||||
@@ -46,17 +47,26 @@ void lcdc_enable(struct sunxi_lcdc_reg * const lcdc, int depth)
|
||||
setbits_le32(&lcdc->ctrl, SUNXI_LCDC_CTRL_TCON_ENABLE);
|
||||
#ifdef CONFIG_VIDEO_LCD_IF_LVDS
|
||||
setbits_le32(&lcdc->tcon0_lvds_intf, SUNXI_LCDC_TCON0_LVDS_INTF_ENABLE);
|
||||
setbits_le32(&lcdc->lvds_ana0, SUNXI_LCDC_LVDS_ANA0);
|
||||
#ifdef CONFIG_SUNXI_GEN_SUN6I
|
||||
writel(SUNXI_LCDC_LVDS_ANA0_C(2) |
|
||||
SUNXI_LCDC_LVDS_ANA0_V(3) |
|
||||
SUNXI_LCDC_LVDS_ANA0_PD(2) |
|
||||
SUNXI_LCDC_LVDS_ANA0_EN_LDO, &lcdc->lvds_ana0);
|
||||
|
||||
udelay(2); /* delay at least 1200 ns */
|
||||
|
||||
setbits_le32(&lcdc->lvds_ana0, SUNXI_LCDC_LVDS_ANA0_EN_MB);
|
||||
|
||||
udelay(2); /* delay at least 1200 ns */
|
||||
|
||||
setbits_le32(&lcdc->lvds_ana0, SUNXI_LCDC_LVDS_ANA0_DRVC);
|
||||
|
||||
if (depth == 18)
|
||||
setbits_le32(&lcdc->lvds_ana0, SUNXI_LCDC_LVDS_ANA0_DRVD(0x7));
|
||||
else
|
||||
setbits_le32(&lcdc->lvds_ana0, SUNXI_LCDC_LVDS_ANA0_DRVD(0xf));
|
||||
#else
|
||||
setbits_le32(&lcdc->lvds_ana0, SUNXI_LCDC_LVDS_ANA0);
|
||||
setbits_le32(&lcdc->lvds_ana0, SUNXI_LCDC_LVDS_ANA0_UPDATE);
|
||||
udelay(2); /* delay at least 1200 ns */
|
||||
setbits_le32(&lcdc->lvds_ana1, SUNXI_LCDC_LVDS_ANA1_INIT1);
|
||||
@@ -84,7 +94,7 @@ void lcdc_tcon0_mode_set(struct sunxi_lcdc_reg * const lcdc,
|
||||
writel(SUNXI_LCDC_TCON0_CTRL_ENABLE |
|
||||
SUNXI_LCDC_TCON0_CTRL_CLK_DELAY(clk_delay), &lcdc->tcon0_ctrl);
|
||||
|
||||
writel(SUNXI_LCDC_TCON0_DCLK_ENABLE |
|
||||
writel(SUNXI_LCDC_TCON0_DCLK_ENABLE_1 |
|
||||
SUNXI_LCDC_TCON0_DCLK_DIV(clk_div), &lcdc->tcon0_dclk);
|
||||
|
||||
writel(SUNXI_LCDC_X(mode->hactive.typ) |
|
||||
@@ -110,6 +120,8 @@ void lcdc_tcon0_mode_set(struct sunxi_lcdc_reg * const lcdc,
|
||||
#ifdef CONFIG_VIDEO_LCD_IF_LVDS
|
||||
val = (depth == 18) ? 1 : 0;
|
||||
writel(SUNXI_LCDC_TCON0_LVDS_INTF_BITWIDTH(val) |
|
||||
SUNXI_LCDC_TCON0_LVDS_IF_CLK_POL_NORMAL |
|
||||
SUNXI_LCDC_TCON0_LVDS_IF_DATA_POL_NORMAL |
|
||||
SUNXI_LCDC_TCON0_LVDS_CLK_SEL_TCON0, &lcdc->tcon0_lvds_intf);
|
||||
#endif
|
||||
|
||||
@@ -142,7 +154,7 @@ void lcdc_tcon0_mode_set(struct sunxi_lcdc_reg * const lcdc,
|
||||
#endif
|
||||
writel(val, &lcdc->tcon0_io_polarity);
|
||||
|
||||
writel(0, &lcdc->tcon0_io_tristate);
|
||||
writel(0xe0000000, &lcdc->tcon0_io_tristate);
|
||||
}
|
||||
|
||||
void lcdc_tcon1_mode_set(struct sunxi_lcdc_reg * const lcdc,
|
||||
@@ -214,7 +226,9 @@ void lcdc_pll_set(struct sunxi_ccm_reg *ccm, int tcon, int dotclock,
|
||||
int value, n, m, min_m, max_m, diff, step;
|
||||
int best_n = 0, best_m = 0, best_diff = 0x0FFFFFFF;
|
||||
int best_double = 0;
|
||||
#ifdef CONFIG_MACH_SUN6I
|
||||
bool use_mipi_pll = false;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SUNXI_DE2
|
||||
step = 6000;
|
||||
@@ -301,11 +315,17 @@ void lcdc_pll_set(struct sunxi_ccm_reg *ccm, int tcon, int dotclock,
|
||||
}
|
||||
|
||||
if (tcon == 0) {
|
||||
u32 pll;
|
||||
#ifdef CONFIG_MACH_SUN8I_A83T
|
||||
writel(CCM_LCD_CH0_CTRL_GATE, &ccm->lcd0_clk_cfg);
|
||||
#else
|
||||
u32 pll = 0;
|
||||
|
||||
#ifdef CONFIG_MACH_SUN6I
|
||||
if (use_mipi_pll)
|
||||
pll = CCM_LCD_CH0_CTRL_MIPI_PLL;
|
||||
else if (best_double)
|
||||
else
|
||||
#endif
|
||||
if (best_double)
|
||||
pll = CCM_LCD_CH0_CTRL_PLL3_2X;
|
||||
else
|
||||
pll = CCM_LCD_CH0_CTRL_PLL3;
|
||||
@@ -315,6 +335,7 @@ void lcdc_pll_set(struct sunxi_ccm_reg *ccm, int tcon, int dotclock,
|
||||
#else
|
||||
writel(CCM_LCD_CH0_CTRL_GATE | CCM_LCD_CH0_CTRL_RST | pll,
|
||||
&ccm->lcd0_clk_cfg);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
#ifndef CONFIG_SUNXI_DE2
|
||||
|
@@ -24,13 +24,19 @@ struct sunxi_lcd_priv {
|
||||
|
||||
static void sunxi_lcdc_config_pinmux(void)
|
||||
{
|
||||
#ifdef CONFIG_MACH_SUN50I
|
||||
#if defined(CONFIG_MACH_SUN50I)
|
||||
int pin;
|
||||
|
||||
for (pin = SUNXI_GPD(0); pin <= SUNXI_GPD(21); pin++) {
|
||||
sunxi_gpio_set_cfgpin(pin, SUNXI_GPD_LCD0);
|
||||
sunxi_gpio_set_drv(pin, 3);
|
||||
}
|
||||
#elif defined(CONFIG_MACH_SUN8I_A83T) && defined(CONFIG_VIDEO_LCD_IF_LVDS)
|
||||
int pin;
|
||||
|
||||
debug("configuring PD LVDS pins\n");
|
||||
for (pin = SUNXI_GPD(18); pin <= SUNXI_GPD(27); pin++)
|
||||
sunxi_gpio_set_cfgpin(pin, SUNXI_GPD_LVDS0);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -50,6 +56,10 @@ static int sunxi_lcd_enable(struct udevice *dev, int bpp,
|
||||
/* Clock on */
|
||||
setbits_le32(&ccm->ahb_gate1, 1 << AHB_GATE_OFFSET_LCD0);
|
||||
|
||||
#ifdef CONFIG_VIDEO_LCD_IF_LVDS
|
||||
setbits_le32(&ccm->ahb_reset2_cfg, 1 << AHB_RESET_OFFSET_LVDS);
|
||||
#endif
|
||||
|
||||
lcdc_init(lcdc);
|
||||
sunxi_lcdc_config_pinmux();
|
||||
lcdc_pll_set(ccm, 0, edid->pixelclock.typ / 1000,
|
||||
@@ -144,7 +154,7 @@ U_BOOT_DRIVER(sunxi_lcd) = {
|
||||
.priv_auto_alloc_size = sizeof(struct sunxi_lcd_priv),
|
||||
};
|
||||
|
||||
#ifdef CONFIG_MACH_SUN50I
|
||||
#if defined(CONFIG_MACH_SUN50I) || defined(CONFIG_MACH_SUN8I_A83T)
|
||||
U_BOOT_DEVICE(sunxi_lcd) = {
|
||||
.name = "sunxi_lcd"
|
||||
};
|
||||
|
Reference in New Issue
Block a user