mirror of
https://xff.cz/git/u-boot/
synced 2025-09-30 06:51:28 +02:00
sunxi: video: Add lvds support
Add support for lvds lcd panels Signed-off-by: Hans de Goede <hdegoede@redhat.com> Acked-by: Anatolij Gustschin <agust@denx.de>
This commit is contained in:
@@ -284,6 +284,8 @@ struct sunxi_ccm_reg {
|
|||||||
/* Enable / disable both ch1 sclk1 and sclk2 at the same time */
|
/* Enable / disable both ch1 sclk1 and sclk2 at the same time */
|
||||||
#define CCM_LCD_CH1_CTRL_GATE (0x1 << 31 | 0x1 << 15)
|
#define CCM_LCD_CH1_CTRL_GATE (0x1 << 31 | 0x1 << 15)
|
||||||
|
|
||||||
|
#define CCM_LVDS_CTRL_RST (1 << 0)
|
||||||
|
|
||||||
#define CCM_HDMI_CTRL_M(n) ((((n) - 1) & 0xf) << 0)
|
#define CCM_HDMI_CTRL_M(n) ((((n) - 1) & 0xf) << 0)
|
||||||
#define CCM_HDMI_CTRL_PLL_MASK (3 << 24)
|
#define CCM_HDMI_CTRL_PLL_MASK (3 << 24)
|
||||||
#define CCM_HDMI_CTRL_PLL3 (0 << 24)
|
#define CCM_HDMI_CTRL_PLL3 (0 << 24)
|
||||||
|
@@ -91,6 +91,9 @@ struct sunxi_lcdc_reg {
|
|||||||
u8 res3[0x44]; /* 0xac */
|
u8 res3[0x44]; /* 0xac */
|
||||||
u32 tcon1_io_polarity; /* 0xf0 */
|
u32 tcon1_io_polarity; /* 0xf0 */
|
||||||
u32 tcon1_io_tristate; /* 0xf4 */
|
u32 tcon1_io_tristate; /* 0xf4 */
|
||||||
|
u8 res4[0x128]; /* 0xf8 */
|
||||||
|
u32 lvds_ana0; /* 0x220 */
|
||||||
|
u32 lvds_ana1; /* 0x224 */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct sunxi_hdmi_reg {
|
struct sunxi_hdmi_reg {
|
||||||
@@ -244,12 +247,21 @@ struct sunxi_tve_reg {
|
|||||||
#define SUNXI_LCDC_TCON0_TIMING_H_TOTAL(n) (((n) - 1) << 16)
|
#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_BP(n) (((n) - 1) << 0)
|
||||||
#define SUNXI_LCDC_TCON0_TIMING_V_TOTAL(n) (((n) * 2) << 16)
|
#define SUNXI_LCDC_TCON0_TIMING_V_TOTAL(n) (((n) * 2) << 16)
|
||||||
|
#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_PHASE0 (0 << 28)
|
||||||
|
#define SUNXI_LCDC_TCON0_IO_POL_DCLK_PHASE60 (1 << 28)
|
||||||
|
#define SUNXI_LCDC_TCON0_IO_POL_DCLK_PHASE120 (2 << 28)
|
||||||
#define SUNXI_LCDC_TCON1_CTRL_CLK_DELAY(n) (((n) & 0x1f) << 4)
|
#define SUNXI_LCDC_TCON1_CTRL_CLK_DELAY(n) (((n) & 0x1f) << 4)
|
||||||
#define SUNXI_LCDC_TCON1_CTRL_ENABLE (1 << 31)
|
#define SUNXI_LCDC_TCON1_CTRL_ENABLE (1 << 31)
|
||||||
#define SUNXI_LCDC_TCON1_TIMING_H_BP(n) (((n) - 1) << 0)
|
#define SUNXI_LCDC_TCON1_TIMING_H_BP(n) (((n) - 1) << 0)
|
||||||
#define SUNXI_LCDC_TCON1_TIMING_H_TOTAL(n) (((n) - 1) << 16)
|
#define SUNXI_LCDC_TCON1_TIMING_H_TOTAL(n) (((n) - 1) << 16)
|
||||||
#define SUNXI_LCDC_TCON1_TIMING_V_BP(n) (((n) - 1) << 0)
|
#define SUNXI_LCDC_TCON1_TIMING_V_BP(n) (((n) - 1) << 0)
|
||||||
#define SUNXI_LCDC_TCON1_TIMING_V_TOTAL(n) (((n) * 2) << 16)
|
#define SUNXI_LCDC_TCON1_TIMING_V_TOTAL(n) (((n) * 2) << 16)
|
||||||
|
#define SUNXI_LCDC_LVDS_ANA0 0x3f310000
|
||||||
|
#define SUNXI_LCDC_LVDS_ANA0_UPDATE (1 << 22)
|
||||||
|
#define SUNXI_LCDC_LVDS_ANA1_INIT1 (0x1f << 26 | 0x1f << 10)
|
||||||
|
#define SUNXI_LCDC_LVDS_ANA1_INIT2 (0x1f << 16 | 0x1f << 00)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* HDMI register constants.
|
* HDMI register constants.
|
||||||
|
@@ -151,6 +151,7 @@ enum sunxi_gpio_number {
|
|||||||
#define SUNXI_GPC6_SDC2 3
|
#define SUNXI_GPC6_SDC2 3
|
||||||
|
|
||||||
#define SUNXI_GPD0_LCD0 2
|
#define SUNXI_GPD0_LCD0 2
|
||||||
|
#define SUNXI_GPD0_LVDS0 3
|
||||||
|
|
||||||
#define SUNXI_GPF0_SDC0 2
|
#define SUNXI_GPF0_SDC0 2
|
||||||
|
|
||||||
|
@@ -348,6 +348,33 @@ config VIDEO_LCD_BL_PWM
|
|||||||
Set the backlight pwm pin for the LCD panel. This takes a string in the
|
Set the backlight pwm pin for the LCD panel. This takes a string in the
|
||||||
format understood by sunxi_name_to_gpio, e.g. PH1 for pin 1 of port H.
|
format understood by sunxi_name_to_gpio, e.g. PH1 for pin 1 of port H.
|
||||||
|
|
||||||
|
|
||||||
|
# Note only one of these may be selected at a time! But hidden choices are
|
||||||
|
# not supported by Kconfig
|
||||||
|
config VIDEO_LCD_IF_PARALLEL
|
||||||
|
bool
|
||||||
|
|
||||||
|
config VIDEO_LCD_IF_LVDS
|
||||||
|
bool
|
||||||
|
|
||||||
|
|
||||||
|
choice
|
||||||
|
prompt "LCD panel support"
|
||||||
|
depends on VIDEO
|
||||||
|
---help---
|
||||||
|
Select which type of LCD panel to support.
|
||||||
|
|
||||||
|
config VIDEO_LCD_PANEL_PARALLEL
|
||||||
|
bool "Generic parallel interface LCD panel"
|
||||||
|
select VIDEO_LCD_IF_PARALLEL
|
||||||
|
|
||||||
|
config VIDEO_LCD_PANEL_LVDS
|
||||||
|
bool "Generic lvds interface LCD panel"
|
||||||
|
select VIDEO_LCD_IF_LVDS
|
||||||
|
|
||||||
|
endchoice
|
||||||
|
|
||||||
|
|
||||||
config USB_KEYBOARD
|
config USB_KEYBOARD
|
||||||
boolean "Enable USB keyboard support"
|
boolean "Enable USB keyboard support"
|
||||||
default y
|
default y
|
||||||
|
@@ -339,8 +339,13 @@ static void sunxi_lcdc_pll_set(int tcon, int dotclock,
|
|||||||
int best_double = 0;
|
int best_double = 0;
|
||||||
|
|
||||||
if (tcon == 0) {
|
if (tcon == 0) {
|
||||||
|
#ifdef CONFIG_VIDEO_LCD_IF_PARALLEL
|
||||||
min_m = 6;
|
min_m = 6;
|
||||||
max_m = 127;
|
max_m = 127;
|
||||||
|
#endif
|
||||||
|
#ifdef CONFIG_VIDEO_LCD_IF_LVDS
|
||||||
|
min_m = max_m = 7;
|
||||||
|
#endif
|
||||||
} else {
|
} else {
|
||||||
min_m = 1;
|
min_m = 1;
|
||||||
max_m = 15;
|
max_m = 15;
|
||||||
@@ -420,6 +425,9 @@ static void sunxi_lcdc_init(void)
|
|||||||
|
|
||||||
/* Clock on */
|
/* Clock on */
|
||||||
setbits_le32(&ccm->ahb_gate1, 1 << AHB_GATE_OFFSET_LCD0);
|
setbits_le32(&ccm->ahb_gate1, 1 << AHB_GATE_OFFSET_LCD0);
|
||||||
|
#ifdef CONFIG_VIDEO_LCD_IF_LVDS
|
||||||
|
setbits_le32(&ccm->lvds_clk_cfg, CCM_LVDS_CTRL_RST);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Init lcdc */
|
/* Init lcdc */
|
||||||
writel(0, &lcdc->ctrl); /* Disable tcon */
|
writel(0, &lcdc->ctrl); /* Disable tcon */
|
||||||
@@ -439,6 +447,16 @@ static void sunxi_lcdc_enable(void)
|
|||||||
(struct sunxi_lcdc_reg *)SUNXI_LCD0_BASE;
|
(struct sunxi_lcdc_reg *)SUNXI_LCD0_BASE;
|
||||||
|
|
||||||
setbits_le32(&lcdc->ctrl, SUNXI_LCDC_CTRL_TCON_ENABLE);
|
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);
|
||||||
|
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);
|
||||||
|
udelay(1); /* delay at least 120 ns */
|
||||||
|
setbits_le32(&lcdc->lvds_ana1, SUNXI_LCDC_LVDS_ANA1_INIT2);
|
||||||
|
setbits_le32(&lcdc->lvds_ana0, SUNXI_LCDC_LVDS_ANA0_UPDATE);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sunxi_lcdc_panel_enable(void)
|
static void sunxi_lcdc_panel_enable(void)
|
||||||
@@ -507,7 +525,12 @@ static void sunxi_lcdc_tcon0_mode_set(const struct ctfb_res_modes *mode)
|
|||||||
int bp, clk_delay, clk_div, clk_double, pin, total, val;
|
int bp, clk_delay, clk_div, clk_double, pin, total, val;
|
||||||
|
|
||||||
for (pin = SUNXI_GPD(0); pin <= SUNXI_GPD(27); pin++)
|
for (pin = SUNXI_GPD(0); pin <= SUNXI_GPD(27); pin++)
|
||||||
|
#ifdef CONFIG_VIDEO_LCD_IF_PARALLEL
|
||||||
sunxi_gpio_set_cfgpin(pin, SUNXI_GPD0_LCD0);
|
sunxi_gpio_set_cfgpin(pin, SUNXI_GPD0_LCD0);
|
||||||
|
#endif
|
||||||
|
#ifdef CONFIG_VIDEO_LCD_IF_LVDS
|
||||||
|
sunxi_gpio_set_cfgpin(pin, SUNXI_GPD0_LVDS0);
|
||||||
|
#endif
|
||||||
|
|
||||||
sunxi_lcdc_pll_set(0, mode->pixclock_khz, &clk_div, &clk_double);
|
sunxi_lcdc_pll_set(0, mode->pixclock_khz, &clk_div, &clk_double);
|
||||||
|
|
||||||
@@ -535,12 +558,17 @@ static void sunxi_lcdc_tcon0_mode_set(const struct ctfb_res_modes *mode)
|
|||||||
writel(SUNXI_LCDC_TCON0_TIMING_V_TOTAL(total) |
|
writel(SUNXI_LCDC_TCON0_TIMING_V_TOTAL(total) |
|
||||||
SUNXI_LCDC_TCON0_TIMING_V_BP(bp), &lcdc->tcon0_timing_v);
|
SUNXI_LCDC_TCON0_TIMING_V_BP(bp), &lcdc->tcon0_timing_v);
|
||||||
|
|
||||||
|
#ifdef CONFIG_VIDEO_LCD_IF_PARALLEL
|
||||||
writel(SUNXI_LCDC_X(mode->hsync_len) | SUNXI_LCDC_Y(mode->vsync_len),
|
writel(SUNXI_LCDC_X(mode->hsync_len) | SUNXI_LCDC_Y(mode->vsync_len),
|
||||||
&lcdc->tcon0_timing_sync);
|
&lcdc->tcon0_timing_sync);
|
||||||
|
|
||||||
/* We only support hv-sync parallel lcd-s for now */
|
|
||||||
writel(0, &lcdc->tcon0_hv_intf);
|
writel(0, &lcdc->tcon0_hv_intf);
|
||||||
writel(0, &lcdc->tcon0_cpu_intf);
|
writel(0, &lcdc->tcon0_cpu_intf);
|
||||||
|
#endif
|
||||||
|
#ifdef CONFIG_VIDEO_LCD_IF_LVDS
|
||||||
|
val = (sunxi_display.depth == 18) ? 1 : 0;
|
||||||
|
writel(SUNXI_LCDC_TCON0_LVDS_INTF_BITWIDTH(val), &lcdc->tcon0_lvds_intf);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (sunxi_display.depth == 18 || sunxi_display.depth == 16) {
|
if (sunxi_display.depth == 18 || sunxi_display.depth == 16) {
|
||||||
writel(SUNXI_LCDC_TCON0_FRM_SEED, &lcdc->tcon0_frm_seed[0]);
|
writel(SUNXI_LCDC_TCON0_FRM_SEED, &lcdc->tcon0_frm_seed[0]);
|
||||||
@@ -559,7 +587,12 @@ static void sunxi_lcdc_tcon0_mode_set(const struct ctfb_res_modes *mode)
|
|||||||
&lcdc->tcon0_frm_ctrl);
|
&lcdc->tcon0_frm_ctrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
val = 0;
|
#ifdef CONFIG_VIDEO_LCD_IF_PARALLEL
|
||||||
|
val = SUNXI_LCDC_TCON0_IO_POL_DCLK_PHASE0;
|
||||||
|
#endif
|
||||||
|
#ifdef CONFIG_VIDEO_LCD_IF_LVDS
|
||||||
|
val = SUNXI_LCDC_TCON0_IO_POL_DCLK_PHASE60;
|
||||||
|
#endif
|
||||||
if (!(mode->sync & FB_SYNC_HOR_HIGH_ACT))
|
if (!(mode->sync & FB_SYNC_HOR_HIGH_ACT))
|
||||||
val |= SUNXI_LCDC_TCON_HSYNC_MASK;
|
val |= SUNXI_LCDC_TCON_HSYNC_MASK;
|
||||||
if (!(mode->sync & FB_SYNC_VERT_HIGH_ACT))
|
if (!(mode->sync & FB_SYNC_VERT_HIGH_ACT))
|
||||||
|
Reference in New Issue
Block a user