/* Clock on */
setbits_le32(&ccm->ahb_gate1, 1 << AHB_GATE_OFFSET_LCD0);
#ifdef CONFIG_VIDEO_LCD_IF_LVDS
+#ifdef CONFIG_SUNXI_GEN_SUN6I
+ setbits_le32(&ccm->ahb_reset2_cfg, 1 << AHB_RESET_OFFSET_LVDS);
+#else
setbits_le32(&ccm->lvds_clk_cfg, CCM_LVDS_CTRL_RST);
+#endif
#endif
/* Init lcdc */
#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
+ 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 (sunxi_display.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_UPDATE);
udelay(2); /* delay at least 1200 ns */
setbits_le32(&lcdc->lvds_ana1, SUNXI_LCDC_LVDS_ANA1_INIT1);
setbits_le32(&lcdc->lvds_ana1, SUNXI_LCDC_LVDS_ANA1_INIT2);
setbits_le32(&lcdc->lvds_ana0, SUNXI_LCDC_LVDS_ANA0_UPDATE);
#endif
+#endif
}
static void sunxi_lcdc_panel_enable(void)
gpio_direction_output(pin, PWM_ON);
}
-static int sunxi_lcdc_get_clk_delay(const struct ctfb_res_modes *mode)
+static int sunxi_lcdc_get_clk_delay(const struct ctfb_res_modes *mode, int tcon)
{
int delay;
- delay = mode->lower_margin + mode->vsync_len + mode->upper_margin - 2;
+ delay = mode->lower_margin + mode->vsync_len + mode->upper_margin;
+ if (tcon == 1)
+ delay -= 2;
+
return (delay > 30) ? 30 : delay;
}
clrsetbits_le32(&lcdc->ctrl, SUNXI_LCDC_CTRL_IO_MAP_MASK,
SUNXI_LCDC_CTRL_IO_MAP_TCON0);
- clk_delay = sunxi_lcdc_get_clk_delay(mode);
+ clk_delay = sunxi_lcdc_get_clk_delay(mode, 0);
writel(SUNXI_LCDC_TCON0_CTRL_ENABLE |
SUNXI_LCDC_TCON0_CTRL_CLK_DELAY(clk_delay), &lcdc->tcon0_ctrl);
#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);
+ writel(SUNXI_LCDC_TCON0_LVDS_INTF_BITWIDTH(val) |
+ SUNXI_LCDC_TCON0_LVDS_CLK_SEL_TCON0, &lcdc->tcon0_lvds_intf);
#endif
if (sunxi_display.depth == 18 || sunxi_display.depth == 16) {
clrsetbits_le32(&lcdc->ctrl, SUNXI_LCDC_CTRL_IO_MAP_MASK,
SUNXI_LCDC_CTRL_IO_MAP_TCON1);
- clk_delay = sunxi_lcdc_get_clk_delay(mode);
+ clk_delay = sunxi_lcdc_get_clk_delay(mode, 1);
writel(SUNXI_LCDC_TCON1_CTRL_ENABLE |
SUNXI_LCDC_TCON1_CTRL_CLK_DELAY(clk_delay), &lcdc->tcon1_ctrl);
return gd->ram_top - CONFIG_SUNXI_MAX_FB_SIZE;
}
+static bool sunxi_has_hdmi(void)
+{
+#ifdef CONFIG_VIDEO_HDMI
+ return true;
+#else
+ return false;
+#endif
+}
+
+static bool sunxi_has_lcd(void)
+{
+ char *lcd_mode = CONFIG_VIDEO_LCD_MODE;
+
+ return lcd_mode[0] != 0;
+}
+
+static bool sunxi_has_vga(void)
+{
+#if defined CONFIG_VIDEO_VGA || defined CONFIG_VIDEO_VGA_VIA_LCD
+ return true;
+#else
+ return false;
+#endif
+}
+
+static enum sunxi_monitor sunxi_get_default_mon(bool allow_hdmi)
+{
+ if (allow_hdmi && sunxi_has_hdmi())
+ return sunxi_monitor_dvi;
+ else if (sunxi_has_lcd())
+ return sunxi_monitor_lcd;
+ else if (sunxi_has_vga())
+ return sunxi_monitor_vga;
+ else
+ return sunxi_monitor_none;
+}
+
void *video_hw_init(void)
{
static GraphicDevice *graphic_device = &sunxi_display.graphic_device;
hpd = video_get_option_int(options, "hpd", 1);
hpd_delay = video_get_option_int(options, "hpd_delay", 500);
edid = video_get_option_int(options, "edid", 1);
- sunxi_display.monitor = sunxi_monitor_dvi;
-#elif defined CONFIG_VIDEO_VGA_VIA_LCD
- sunxi_display.monitor = sunxi_monitor_vga;
-#else
- sunxi_display.monitor = sunxi_monitor_lcd;
#endif
+ sunxi_display.monitor = sunxi_get_default_mon(true);
video_get_option_string(options, "monitor", mon, sizeof(mon),
sunxi_get_mon_desc(sunxi_display.monitor));
for (i = 0; i <= SUNXI_MONITOR_LAST; i++) {
mode = &custom;
} else if (hpd) {
sunxi_hdmi_shutdown();
- /* Fallback to lcd / vga / none */
- if (lcd_mode[0]) {
- sunxi_display.monitor = sunxi_monitor_lcd;
- } else {
-#if defined CONFIG_VIDEO_VGA_VIA_LCD || defined CONFIG_VIDEO_VGA
- sunxi_display.monitor = sunxi_monitor_vga;
-#else
- sunxi_display.monitor = sunxi_monitor_none;
-#endif
- }
+ sunxi_display.monitor = sunxi_get_default_mon(false);
} /* else continue with hdmi/dvi without a cable connected */
}
#endif
return NULL;
case sunxi_monitor_dvi:
case sunxi_monitor_hdmi:
-#ifdef CONFIG_VIDEO_HDMI
+ if (!sunxi_has_hdmi()) {
+ printf("HDMI/DVI not supported on this board\n");
+ sunxi_display.monitor = sunxi_monitor_none;
+ return NULL;
+ }
break;
-#else
- printf("HDMI/DVI not supported on this board\n");
- sunxi_display.monitor = sunxi_monitor_none;
- return NULL;
-#endif
case sunxi_monitor_lcd:
- if (lcd_mode[0]) {
- sunxi_display.depth = video_get_params(&custom, lcd_mode);
- mode = &custom;
- break;
+ if (!sunxi_has_lcd()) {
+ printf("LCD not supported on this board\n");
+ sunxi_display.monitor = sunxi_monitor_none;
+ return NULL;
}
- printf("LCD not supported on this board\n");
- sunxi_display.monitor = sunxi_monitor_none;
- return NULL;
+ sunxi_display.depth = video_get_params(&custom, lcd_mode);
+ mode = &custom;
+ break;
case sunxi_monitor_vga:
-#if defined CONFIG_VIDEO_VGA_VIA_LCD || defined CONFIG_VIDEO_VGA
+ if (!sunxi_has_vga()) {
+ printf("VGA not supported on this board\n");
+ sunxi_display.monitor = sunxi_monitor_none;
+ return NULL;
+ }
sunxi_display.depth = 18;
break;
-#else
- printf("VGA not supported on this board\n");
- sunxi_display.monitor = sunxi_monitor_none;
- return NULL;
-#endif
}
if (mode->vmode != FB_VMODE_NONINTERLACED) {