#include <asm/global_data.h>
#include <asm/gpio.h>
#include <asm/io.h>
+#include <axp_pmic.h>
#include <errno.h>
#include <fdtdec.h>
#include <fdt_support.h>
#include <malloc.h>
#include <video_fb.h>
#include "videomodes.h"
+#include "anx9804.h"
#include "hitachi_tx18d42vm_lcd.h"
#include "ssd2828.h"
setbits_le32(&de_be->mode, SUNXI_DE_BE_MODE_LAYER0_ENABLE);
if (mode->vmode == FB_VMODE_INTERLACED)
setbits_le32(&de_be->mode,
+#ifndef CONFIG_MACH_SUN5I
SUNXI_DE_BE_MODE_DEFLICKER_ENABLE |
+#endif
SUNXI_DE_BE_MODE_INTERLACE_ENABLE);
if (sunxi_is_composite()) {
int value, n, m, min_m, max_m, diff;
int best_n = 0, best_m = 0, best_diff = 0x0FFFFFFF;
int best_double = 0;
+ bool use_mipi_pll = false;
if (tcon == 0) {
#ifdef CONFIG_VIDEO_LCD_IF_PARALLEL
}
}
- debug("dotclock: %dkHz = %dkHz: (%d * 3MHz * %d) / %d\n",
- dotclock, (best_double + 1) * 3000 * best_n / best_m,
- best_double + 1, best_n, best_m);
+#ifdef CONFIG_MACH_SUN6I
+ /*
+ * Use the MIPI pll if we've been unable to find any matching setting
+ * for PLL3, this happens with high dotclocks because of min_m = 6.
+ */
+ if (tcon == 0 && best_n == 0) {
+ use_mipi_pll = true;
+ best_m = 6; /* Minimum m for tcon0 */
+ }
- clock_set_pll3(best_n * 3000000);
+ if (use_mipi_pll) {
+ clock_set_pll3(297000000); /* Fix the video pll at 297 MHz */
+ clock_set_mipi_pll(best_m * dotclock * 1000);
+ debug("dotclock: %dkHz = %dkHz via mipi pll\n",
+ dotclock, clock_get_mipi_pll() / best_m / 1000);
+ } else
+#endif
+ {
+ clock_set_pll3(best_n * 3000000);
+ debug("dotclock: %dkHz = %dkHz: (%d * 3MHz * %d) / %d\n",
+ dotclock,
+ (best_double + 1) * clock_get_pll3() / best_m / 1000,
+ best_double + 1, best_n, best_m);
+ }
if (tcon == 0) {
- writel(CCM_LCD_CH0_CTRL_GATE | CCM_LCD_CH0_CTRL_RST |
- (best_double ? CCM_LCD_CH0_CTRL_PLL3_2X :
- CCM_LCD_CH0_CTRL_PLL3),
+ u32 pll;
+
+ if (use_mipi_pll)
+ pll = CCM_LCD_CH0_CTRL_MIPI_PLL;
+ else if (best_double)
+ pll = CCM_LCD_CH0_CTRL_PLL3_2X;
+ else
+ pll = CCM_LCD_CH0_CTRL_PLL3;
+
+ writel(CCM_LCD_CH0_CTRL_GATE | CCM_LCD_CH0_CTRL_RST | pll,
&ccm->lcd0_ch0_clk_cfg);
} else {
writel(CCM_LCD_CH1_CTRL_GATE |
(struct sunxi_lcdc_reg *)SUNXI_LCD0_BASE;
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_GPD_LCD0);
#endif
#ifdef CONFIG_VIDEO_LCD_IF_LVDS
sunxi_gpio_set_cfgpin(pin, SUNXI_GPD_LVDS0);
#endif
+#ifdef CONFIG_VIDEO_LCD_PANEL_EDP_4_LANE_1620M_VIA_ANX9804
+ sunxi_gpio_set_drv(pin, 3);
+#endif
+ }
sunxi_lcdc_pll_set(0, mode->pixclock_khz, &clk_div, &clk_double);
SUNXI_LCDC_TCON_VSYNC_MASK |
SUNXI_LCDC_TCON_HSYNC_MASK);
}
+
+#ifdef CONFIG_MACH_SUN5I
+ if (sunxi_is_composite())
+ clrsetbits_le32(&lcdc->mux_ctrl, SUNXI_LCDC_MUX_CTRL_SRC0_MASK,
+ SUNXI_LCDC_MUX_CTRL_SRC0(1));
+#endif
+
sunxi_lcdc_pll_set(1, mode->pixclock_khz, clk_div, clk_double);
}
#endif /* CONFIG_VIDEO_HDMI || defined CONFIG_VIDEO_VGA || CONFIG_VIDEO_COMPOSITE */
struct sunxi_tve_reg * const tve =
(struct sunxi_tve_reg *)SUNXI_TVE0_BASE;
+ /* Reset off */
+ setbits_le32(&ccm->lcd0_ch0_clk_cfg, CCM_LCD_CH0_CTRL_TVE_RST);
/* Clock on */
setbits_le32(&ccm->ahb_gate1, 1 << AHB_GATE_OFFSET_TVE0);
break;
case sunxi_monitor_lcd:
sunxi_lcdc_panel_enable();
+ if (IS_ENABLED(CONFIG_VIDEO_LCD_PANEL_EDP_4_LANE_1620M_VIA_ANX9804)) {
+ /*
+ * The anx9804 needs 1.8V from eldo3, we do this here
+ * and not via CONFIG_AXP_ELDO3_VOLT from board_init()
+ * to avoid turning this on when using hdmi output.
+ */
+ axp_set_eldo(3, 1800);
+ anx9804_init(CONFIG_VIDEO_LCD_I2C_BUS, 4,
+ ANX9804_DATA_RATE_1620M,
+ sunxi_display.depth);
+ }
if (IS_ENABLED(CONFIG_VIDEO_LCD_HITACHI_TX18D42VM)) {
mdelay(50); /* Wait for lcd controller power on */
hitachi_tx18d42vm_init();