2 * Display driver for Allwinner SoCs.
4 * (C) Copyright 2013-2014 Luc Verhaegen <libv@skynet.be>
5 * (C) Copyright 2014-2015 Hans de Goede <hdegoede@redhat.com>
7 * SPDX-License-Identifier: GPL-2.0+
12 #include <asm/arch/clock.h>
13 #include <asm/arch/display.h>
14 #include <asm/arch/gpio.h>
15 #include <asm/arch/pwm.h>
16 #include <asm/global_data.h>
22 #include <fdt_support.h>
26 #include "videomodes.h"
28 #include "hitachi_tx18d42vm_lcd.h"
31 #ifdef CONFIG_VIDEO_LCD_BL_PWM_ACTIVE_LOW
39 DECLARE_GLOBAL_DATA_PTR;
47 sunxi_monitor_composite_pal,
48 sunxi_monitor_composite_ntsc,
49 sunxi_monitor_composite_pal_m,
50 sunxi_monitor_composite_pal_nc,
52 #define SUNXI_MONITOR_LAST sunxi_monitor_composite_pal_nc
54 struct sunxi_display {
55 GraphicDevice graphic_device;
56 enum sunxi_monitor monitor;
62 const struct ctfb_res_modes composite_video_modes[2] = {
63 /* x y hz pixclk ps/kHz le ri up lo hs vs s vmode */
64 { 720, 576, 50, 37037, 27000, 137, 5, 20, 27, 2, 2, 0, FB_VMODE_INTERLACED },
65 { 720, 480, 60, 37037, 27000, 116, 20, 16, 27, 2, 2, 0, FB_VMODE_INTERLACED },
68 #ifdef CONFIG_VIDEO_HDMI
71 * Wait up to 200ms for value to be set in given part of reg.
73 static int await_completion(u32 *reg, u32 mask, u32 val)
75 unsigned long tmo = timer_get_us() + 200000;
77 while ((readl(reg) & mask) != val) {
78 if (timer_get_us() > tmo) {
79 printf("DDC: timeout reading EDID\n");
86 static int sunxi_hdmi_hpd_detect(int hpd_delay)
88 struct sunxi_ccm_reg * const ccm =
89 (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
90 struct sunxi_hdmi_reg * const hdmi =
91 (struct sunxi_hdmi_reg *)SUNXI_HDMI_BASE;
92 unsigned long tmo = timer_get_us() + hpd_delay * 1000;
94 /* Set pll3 to 300MHz */
95 clock_set_pll3(300000000);
97 /* Set hdmi parent to pll3 */
98 clrsetbits_le32(&ccm->hdmi_clk_cfg, CCM_HDMI_CTRL_PLL_MASK,
101 /* Set ahb gating to pass */
102 #ifdef CONFIG_SUNXI_GEN_SUN6I
103 setbits_le32(&ccm->ahb_reset1_cfg, 1 << AHB_RESET_OFFSET_HDMI);
105 setbits_le32(&ccm->ahb_gate1, 1 << AHB_GATE_OFFSET_HDMI);
108 setbits_le32(&ccm->hdmi_clk_cfg, CCM_HDMI_CTRL_GATE);
110 writel(SUNXI_HDMI_CTRL_ENABLE, &hdmi->ctrl);
111 writel(SUNXI_HDMI_PAD_CTRL0_HDP, &hdmi->pad_ctrl0);
113 while (timer_get_us() < tmo) {
114 if (readl(&hdmi->hpd) & SUNXI_HDMI_HPD_DETECT)
121 static void sunxi_hdmi_shutdown(void)
123 struct sunxi_ccm_reg * const ccm =
124 (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
125 struct sunxi_hdmi_reg * const hdmi =
126 (struct sunxi_hdmi_reg *)SUNXI_HDMI_BASE;
128 clrbits_le32(&hdmi->ctrl, SUNXI_HDMI_CTRL_ENABLE);
129 clrbits_le32(&ccm->hdmi_clk_cfg, CCM_HDMI_CTRL_GATE);
130 clrbits_le32(&ccm->ahb_gate1, 1 << AHB_GATE_OFFSET_HDMI);
131 #ifdef CONFIG_SUNXI_GEN_SUN6I
132 clrbits_le32(&ccm->ahb_reset1_cfg, 1 << AHB_RESET_OFFSET_HDMI);
137 static int sunxi_hdmi_ddc_do_command(u32 cmnd, int offset, int n)
139 struct sunxi_hdmi_reg * const hdmi =
140 (struct sunxi_hdmi_reg *)SUNXI_HDMI_BASE;
142 setbits_le32(&hdmi->ddc_fifo_ctrl, SUNXI_HDMI_DDC_FIFO_CTRL_CLEAR);
143 writel(SUNXI_HMDI_DDC_ADDR_EDDC_SEGMENT(offset >> 8) |
144 SUNXI_HMDI_DDC_ADDR_EDDC_ADDR |
145 SUNXI_HMDI_DDC_ADDR_OFFSET(offset) |
146 SUNXI_HMDI_DDC_ADDR_SLAVE_ADDR, &hdmi->ddc_addr);
147 #ifndef CONFIG_MACH_SUN6I
148 writel(n, &hdmi->ddc_byte_count);
149 writel(cmnd, &hdmi->ddc_cmnd);
151 writel(n << 16 | cmnd, &hdmi->ddc_cmnd);
153 setbits_le32(&hdmi->ddc_ctrl, SUNXI_HMDI_DDC_CTRL_START);
155 return await_completion(&hdmi->ddc_ctrl, SUNXI_HMDI_DDC_CTRL_START, 0);
158 static int sunxi_hdmi_ddc_read(int offset, u8 *buf, int count)
160 struct sunxi_hdmi_reg * const hdmi =
161 (struct sunxi_hdmi_reg *)SUNXI_HDMI_BASE;
170 if (sunxi_hdmi_ddc_do_command(
171 SUNXI_HDMI_DDC_CMND_EXPLICIT_EDDC_READ,
175 for (i = 0; i < n; i++)
176 *buf++ = readb(&hdmi->ddc_fifo_data);
185 static int sunxi_hdmi_edid_get_block(int block, u8 *buf)
190 r = sunxi_hdmi_ddc_read(block * 128, buf, 128);
193 r = edid_check_checksum(buf);
195 printf("EDID block %d: checksum error%s\n",
196 block, retries ? ", retrying" : "");
198 } while (r && retries--);
203 static int sunxi_hdmi_edid_get_mode(struct ctfb_res_modes *mode)
205 struct edid1_info edid1;
206 struct edid_cea861_info cea681[4];
207 struct edid_detailed_timing *t =
208 (struct edid_detailed_timing *)edid1.monitor_details.timing;
209 struct sunxi_hdmi_reg * const hdmi =
210 (struct sunxi_hdmi_reg *)SUNXI_HDMI_BASE;
211 struct sunxi_ccm_reg * const ccm =
212 (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
213 int i, r, ext_blocks = 0;
215 /* SUNXI_HDMI_CTRL_ENABLE & PAD_CTRL0 are already set by hpd_detect */
216 writel(SUNXI_HDMI_PAD_CTRL1 | SUNXI_HDMI_PAD_CTRL1_HALVE,
218 writel(SUNXI_HDMI_PLL_CTRL | SUNXI_HDMI_PLL_CTRL_DIV(15),
220 writel(SUNXI_HDMI_PLL_DBG0_PLL3, &hdmi->pll_dbg0);
222 /* Reset i2c controller */
223 setbits_le32(&ccm->hdmi_clk_cfg, CCM_HDMI_CTRL_DDC_GATE);
224 writel(SUNXI_HMDI_DDC_CTRL_ENABLE |
225 SUNXI_HMDI_DDC_CTRL_SDA_ENABLE |
226 SUNXI_HMDI_DDC_CTRL_SCL_ENABLE |
227 SUNXI_HMDI_DDC_CTRL_RESET, &hdmi->ddc_ctrl);
228 if (await_completion(&hdmi->ddc_ctrl, SUNXI_HMDI_DDC_CTRL_RESET, 0))
231 writel(SUNXI_HDMI_DDC_CLOCK, &hdmi->ddc_clock);
232 #ifndef CONFIG_MACH_SUN6I
233 writel(SUNXI_HMDI_DDC_LINE_CTRL_SDA_ENABLE |
234 SUNXI_HMDI_DDC_LINE_CTRL_SCL_ENABLE, &hdmi->ddc_line_ctrl);
237 r = sunxi_hdmi_edid_get_block(0, (u8 *)&edid1);
239 r = edid_check_info(&edid1);
241 printf("EDID: invalid EDID data\n");
246 ext_blocks = edid1.extension_flag;
249 for (i = 0; i < ext_blocks; i++) {
250 if (sunxi_hdmi_edid_get_block(1 + i,
251 (u8 *)&cea681[i]) != 0) {
258 /* Disable DDC engine, no longer needed */
259 clrbits_le32(&hdmi->ddc_ctrl, SUNXI_HMDI_DDC_CTRL_ENABLE);
260 clrbits_le32(&ccm->hdmi_clk_cfg, CCM_HDMI_CTRL_DDC_GATE);
265 /* We want version 1.3 or 1.2 with detailed timing info */
266 if (edid1.version != 1 || (edid1.revision < 3 &&
267 !EDID1_INFO_FEATURE_PREFERRED_TIMING_MODE(edid1))) {
268 printf("EDID: unsupported version %d.%d\n",
269 edid1.version, edid1.revision);
273 /* Take the first usable detailed timing */
274 for (i = 0; i < 4; i++, t++) {
275 r = video_edid_dtd_to_ctfb_res_modes(t, mode);
280 printf("EDID: no usable detailed timing found\n");
284 /* Check for basic audio support, if found enable hdmi output */
285 sunxi_display.monitor = sunxi_monitor_dvi;
286 for (i = 0; i < ext_blocks; i++) {
287 if (cea681[i].extension_tag != EDID_CEA861_EXTENSION_TAG ||
288 cea681[i].revision < 2)
291 if (EDID_CEA861_SUPPORTS_BASIC_AUDIO(cea681[i]))
292 sunxi_display.monitor = sunxi_monitor_hdmi;
298 #endif /* CONFIG_VIDEO_HDMI */
300 #ifdef CONFIG_MACH_SUN4I
302 * Testing has shown that on sun4i the display backend engine does not have
303 * deep enough fifo-s causing flickering / tearing in full-hd mode due to
304 * fifo underruns. So on sun4i we use the display frontend engine to do the
305 * dma from memory, as the frontend does have deep enough fifo-s.
308 static const u32 sun4i_vert_coef[32] = {
309 0x00004000, 0x000140ff, 0x00033ffe, 0x00043ffd,
310 0x00063efc, 0xff083dfc, 0x000a3bfb, 0xff0d39fb,
311 0xff0f37fb, 0xff1136fa, 0xfe1433fb, 0xfe1631fb,
312 0xfd192ffb, 0xfd1c2cfb, 0xfd1f29fb, 0xfc2127fc,
313 0xfc2424fc, 0xfc2721fc, 0xfb291ffd, 0xfb2c1cfd,
314 0xfb2f19fd, 0xfb3116fe, 0xfb3314fe, 0xfa3611ff,
315 0xfb370fff, 0xfb390dff, 0xfb3b0a00, 0xfc3d08ff,
316 0xfc3e0600, 0xfd3f0400, 0xfe3f0300, 0xff400100,
319 static const u32 sun4i_horz_coef[64] = {
320 0x40000000, 0x00000000, 0x40fe0000, 0x0000ff03,
321 0x3ffd0000, 0x0000ff05, 0x3ffc0000, 0x0000ff06,
322 0x3efb0000, 0x0000ff08, 0x3dfb0000, 0x0000ff09,
323 0x3bfa0000, 0x0000fe0d, 0x39fa0000, 0x0000fe0f,
324 0x38fa0000, 0x0000fe10, 0x36fa0000, 0x0000fe12,
325 0x33fa0000, 0x0000fd16, 0x31fa0000, 0x0000fd18,
326 0x2ffa0000, 0x0000fd1a, 0x2cfa0000, 0x0000fc1e,
327 0x29fa0000, 0x0000fc21, 0x27fb0000, 0x0000fb23,
328 0x24fb0000, 0x0000fb26, 0x21fb0000, 0x0000fb29,
329 0x1ffc0000, 0x0000fa2b, 0x1cfc0000, 0x0000fa2e,
330 0x19fd0000, 0x0000fa30, 0x16fd0000, 0x0000fa33,
331 0x14fd0000, 0x0000fa35, 0x11fe0000, 0x0000fa37,
332 0x0ffe0000, 0x0000fa39, 0x0dfe0000, 0x0000fa3b,
333 0x0afe0000, 0x0000fa3e, 0x08ff0000, 0x0000fb3e,
334 0x06ff0000, 0x0000fb40, 0x05ff0000, 0x0000fc40,
335 0x03ff0000, 0x0000fd41, 0x01ff0000, 0x0000fe42,
338 static void sunxi_frontend_init(void)
340 struct sunxi_ccm_reg * const ccm =
341 (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
342 struct sunxi_de_fe_reg * const de_fe =
343 (struct sunxi_de_fe_reg *)SUNXI_DE_FE0_BASE;
347 setbits_le32(&ccm->ahb_gate1, 1 << AHB_GATE_OFFSET_DE_FE0);
348 setbits_le32(&ccm->dram_clk_gate, 1 << CCM_DRAM_GATE_OFFSET_DE_FE0);
349 clock_set_de_mod_clock(&ccm->fe0_clk_cfg, 300000000);
351 setbits_le32(&de_fe->enable, SUNXI_DE_FE_ENABLE_EN);
353 for (i = 0; i < 32; i++) {
354 writel(sun4i_horz_coef[2 * i], &de_fe->ch0_horzcoef0[i]);
355 writel(sun4i_horz_coef[2 * i + 1], &de_fe->ch0_horzcoef1[i]);
356 writel(sun4i_vert_coef[i], &de_fe->ch0_vertcoef[i]);
357 writel(sun4i_horz_coef[2 * i], &de_fe->ch1_horzcoef0[i]);
358 writel(sun4i_horz_coef[2 * i + 1], &de_fe->ch1_horzcoef1[i]);
359 writel(sun4i_vert_coef[i], &de_fe->ch1_vertcoef[i]);
362 setbits_le32(&de_fe->frame_ctrl, SUNXI_DE_FE_FRAME_CTRL_COEF_RDY);
365 static void sunxi_frontend_mode_set(const struct ctfb_res_modes *mode,
366 unsigned int address)
368 struct sunxi_de_fe_reg * const de_fe =
369 (struct sunxi_de_fe_reg *)SUNXI_DE_FE0_BASE;
371 setbits_le32(&de_fe->bypass, SUNXI_DE_FE_BYPASS_CSC_BYPASS);
372 writel(CONFIG_SYS_SDRAM_BASE + address, &de_fe->ch0_addr);
373 writel(mode->xres * 4, &de_fe->ch0_stride);
374 writel(SUNXI_DE_FE_INPUT_FMT_ARGB8888, &de_fe->input_fmt);
375 writel(SUNXI_DE_FE_OUTPUT_FMT_ARGB8888, &de_fe->output_fmt);
377 writel(SUNXI_DE_FE_HEIGHT(mode->yres) | SUNXI_DE_FE_WIDTH(mode->xres),
379 writel(SUNXI_DE_FE_HEIGHT(mode->yres) | SUNXI_DE_FE_WIDTH(mode->xres),
380 &de_fe->ch0_outsize);
381 writel(SUNXI_DE_FE_FACTOR_INT(1), &de_fe->ch0_horzfact);
382 writel(SUNXI_DE_FE_FACTOR_INT(1), &de_fe->ch0_vertfact);
384 writel(SUNXI_DE_FE_HEIGHT(mode->yres) | SUNXI_DE_FE_WIDTH(mode->xres),
386 writel(SUNXI_DE_FE_HEIGHT(mode->yres) | SUNXI_DE_FE_WIDTH(mode->xres),
387 &de_fe->ch1_outsize);
388 writel(SUNXI_DE_FE_FACTOR_INT(1), &de_fe->ch1_horzfact);
389 writel(SUNXI_DE_FE_FACTOR_INT(1), &de_fe->ch1_vertfact);
391 setbits_le32(&de_fe->frame_ctrl, SUNXI_DE_FE_FRAME_CTRL_REG_RDY);
394 static void sunxi_frontend_enable(void)
396 struct sunxi_de_fe_reg * const de_fe =
397 (struct sunxi_de_fe_reg *)SUNXI_DE_FE0_BASE;
399 setbits_le32(&de_fe->frame_ctrl, SUNXI_DE_FE_FRAME_CTRL_FRM_START);
402 static void sunxi_frontend_init(void) {}
403 static void sunxi_frontend_mode_set(const struct ctfb_res_modes *mode,
404 unsigned int address) {}
405 static void sunxi_frontend_enable(void) {}
408 static bool sunxi_is_composite(void)
410 switch (sunxi_display.monitor) {
411 case sunxi_monitor_none:
412 case sunxi_monitor_dvi:
413 case sunxi_monitor_hdmi:
414 case sunxi_monitor_lcd:
415 case sunxi_monitor_vga:
417 case sunxi_monitor_composite_pal:
418 case sunxi_monitor_composite_ntsc:
419 case sunxi_monitor_composite_pal_m:
420 case sunxi_monitor_composite_pal_nc:
424 return false; /* Never reached */
428 * This is the entity that mixes and matches the different layers and inputs.
429 * Allwinner calls it the back-end, but i like composer better.
431 static void sunxi_composer_init(void)
433 struct sunxi_ccm_reg * const ccm =
434 (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
435 struct sunxi_de_be_reg * const de_be =
436 (struct sunxi_de_be_reg *)SUNXI_DE_BE0_BASE;
439 sunxi_frontend_init();
441 #ifdef CONFIG_SUNXI_GEN_SUN6I
443 setbits_le32(&ccm->ahb_reset1_cfg, 1 << AHB_RESET_OFFSET_DE_BE0);
447 setbits_le32(&ccm->ahb_gate1, 1 << AHB_GATE_OFFSET_DE_BE0);
448 #ifndef CONFIG_MACH_SUN4I /* On sun4i the frontend does the dma */
449 setbits_le32(&ccm->dram_clk_gate, 1 << CCM_DRAM_GATE_OFFSET_DE_BE0);
451 clock_set_de_mod_clock(&ccm->be0_clk_cfg, 300000000);
453 /* Engine bug, clear registers after reset */
454 for (i = 0x0800; i < 0x1000; i += 4)
455 writel(0, SUNXI_DE_BE0_BASE + i);
457 setbits_le32(&de_be->mode, SUNXI_DE_BE_MODE_ENABLE);
460 static u32 sunxi_rgb2yuv_coef[12] = {
461 0x00000107, 0x00000204, 0x00000064, 0x00000108,
462 0x00003f69, 0x00003ed6, 0x000001c1, 0x00000808,
463 0x000001c1, 0x00003e88, 0x00003fb8, 0x00000808
466 static void sunxi_composer_mode_set(const struct ctfb_res_modes *mode,
467 unsigned int address)
469 struct sunxi_de_be_reg * const de_be =
470 (struct sunxi_de_be_reg *)SUNXI_DE_BE0_BASE;
473 sunxi_frontend_mode_set(mode, address);
475 writel(SUNXI_DE_BE_HEIGHT(mode->yres) | SUNXI_DE_BE_WIDTH(mode->xres),
477 writel(SUNXI_DE_BE_HEIGHT(mode->yres) | SUNXI_DE_BE_WIDTH(mode->xres),
478 &de_be->layer0_size);
479 #ifndef CONFIG_MACH_SUN4I /* On sun4i the frontend does the dma */
480 writel(SUNXI_DE_BE_LAYER_STRIDE(mode->xres), &de_be->layer0_stride);
481 writel(address << 3, &de_be->layer0_addr_low32b);
482 writel(address >> 29, &de_be->layer0_addr_high4b);
484 writel(SUNXI_DE_BE_LAYER_ATTR0_SRC_FE0, &de_be->layer0_attr0_ctrl);
486 writel(SUNXI_DE_BE_LAYER_ATTR1_FMT_XRGB8888, &de_be->layer0_attr1_ctrl);
488 setbits_le32(&de_be->mode, SUNXI_DE_BE_MODE_LAYER0_ENABLE);
489 if (mode->vmode == FB_VMODE_INTERLACED)
490 setbits_le32(&de_be->mode,
491 #ifndef CONFIG_MACH_SUN5I
492 SUNXI_DE_BE_MODE_DEFLICKER_ENABLE |
494 SUNXI_DE_BE_MODE_INTERLACE_ENABLE);
496 if (sunxi_is_composite()) {
497 writel(SUNXI_DE_BE_OUTPUT_COLOR_CTRL_ENABLE,
498 &de_be->output_color_ctrl);
499 for (i = 0; i < 12; i++)
500 writel(sunxi_rgb2yuv_coef[i],
501 &de_be->output_color_coef[i]);
505 static void sunxi_composer_enable(void)
507 struct sunxi_de_be_reg * const de_be =
508 (struct sunxi_de_be_reg *)SUNXI_DE_BE0_BASE;
510 sunxi_frontend_enable();
512 setbits_le32(&de_be->reg_ctrl, SUNXI_DE_BE_REG_CTRL_LOAD_REGS);
513 setbits_le32(&de_be->mode, SUNXI_DE_BE_MODE_START);
517 * LCDC, what allwinner calls a CRTC, so timing controller and serializer.
519 static void sunxi_lcdc_pll_set(int tcon, int dotclock,
520 int *clk_div, int *clk_double)
522 struct sunxi_ccm_reg * const ccm =
523 (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
524 int value, n, m, min_m, max_m, diff;
525 int best_n = 0, best_m = 0, best_diff = 0x0FFFFFFF;
527 bool use_mipi_pll = false;
530 #ifdef CONFIG_VIDEO_LCD_IF_PARALLEL
534 #ifdef CONFIG_VIDEO_LCD_IF_LVDS
543 * Find the lowest divider resulting in a matching clock, if there
544 * is no match, pick the closest lower clock, as monitors tend to
545 * not sync to higher frequencies.
547 for (m = min_m; m <= max_m; m++) {
548 n = (m * dotclock) / 3000;
550 if ((n >= 9) && (n <= 127)) {
551 value = (3000 * n) / m;
552 diff = dotclock - value;
553 if (diff < best_diff) {
561 /* These are just duplicates */
565 n = (m * dotclock) / 6000;
566 if ((n >= 9) && (n <= 127)) {
567 value = (6000 * n) / m;
568 diff = dotclock - value;
569 if (diff < best_diff) {
578 #ifdef CONFIG_MACH_SUN6I
580 * Use the MIPI pll if we've been unable to find any matching setting
581 * for PLL3, this happens with high dotclocks because of min_m = 6.
583 if (tcon == 0 && best_n == 0) {
585 best_m = 6; /* Minimum m for tcon0 */
589 clock_set_pll3(297000000); /* Fix the video pll at 297 MHz */
590 clock_set_mipi_pll(best_m * dotclock * 1000);
591 debug("dotclock: %dkHz = %dkHz via mipi pll\n",
592 dotclock, clock_get_mipi_pll() / best_m / 1000);
596 clock_set_pll3(best_n * 3000000);
597 debug("dotclock: %dkHz = %dkHz: (%d * 3MHz * %d) / %d\n",
599 (best_double + 1) * clock_get_pll3() / best_m / 1000,
600 best_double + 1, best_n, best_m);
607 pll = CCM_LCD_CH0_CTRL_MIPI_PLL;
608 else if (best_double)
609 pll = CCM_LCD_CH0_CTRL_PLL3_2X;
611 pll = CCM_LCD_CH0_CTRL_PLL3;
613 writel(CCM_LCD_CH0_CTRL_GATE | CCM_LCD_CH0_CTRL_RST | pll,
614 &ccm->lcd0_ch0_clk_cfg);
616 writel(CCM_LCD_CH1_CTRL_GATE |
617 (best_double ? CCM_LCD_CH1_CTRL_PLL3_2X :
618 CCM_LCD_CH1_CTRL_PLL3) |
619 CCM_LCD_CH1_CTRL_M(best_m), &ccm->lcd0_ch1_clk_cfg);
620 if (sunxi_is_composite())
621 setbits_le32(&ccm->lcd0_ch1_clk_cfg,
622 CCM_LCD_CH1_CTRL_HALF_SCLK1);
626 *clk_double = best_double;
629 static void sunxi_lcdc_init(void)
631 struct sunxi_ccm_reg * const ccm =
632 (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
633 struct sunxi_lcdc_reg * const lcdc =
634 (struct sunxi_lcdc_reg *)SUNXI_LCD0_BASE;
637 #ifdef CONFIG_SUNXI_GEN_SUN6I
638 setbits_le32(&ccm->ahb_reset1_cfg, 1 << AHB_RESET_OFFSET_LCD0);
640 setbits_le32(&ccm->lcd0_ch0_clk_cfg, CCM_LCD_CH0_CTRL_RST);
644 setbits_le32(&ccm->ahb_gate1, 1 << AHB_GATE_OFFSET_LCD0);
645 #ifdef CONFIG_VIDEO_LCD_IF_LVDS
646 #ifdef CONFIG_SUNXI_GEN_SUN6I
647 setbits_le32(&ccm->ahb_reset2_cfg, 1 << AHB_RESET_OFFSET_LVDS);
649 setbits_le32(&ccm->lvds_clk_cfg, CCM_LVDS_CTRL_RST);
654 writel(0, &lcdc->ctrl); /* Disable tcon */
655 writel(0, &lcdc->int0); /* Disable all interrupts */
657 /* Disable tcon0 dot clock */
658 clrbits_le32(&lcdc->tcon0_dclk, SUNXI_LCDC_TCON0_DCLK_ENABLE);
660 /* Set all io lines to tristate */
661 writel(0xffffffff, &lcdc->tcon0_io_tristate);
662 writel(0xffffffff, &lcdc->tcon1_io_tristate);
665 static void sunxi_lcdc_enable(void)
667 struct sunxi_lcdc_reg * const lcdc =
668 (struct sunxi_lcdc_reg *)SUNXI_LCD0_BASE;
670 setbits_le32(&lcdc->ctrl, SUNXI_LCDC_CTRL_TCON_ENABLE);
671 #ifdef CONFIG_VIDEO_LCD_IF_LVDS
672 setbits_le32(&lcdc->tcon0_lvds_intf, SUNXI_LCDC_TCON0_LVDS_INTF_ENABLE);
673 setbits_le32(&lcdc->lvds_ana0, SUNXI_LCDC_LVDS_ANA0);
674 #ifdef CONFIG_SUNXI_GEN_SUN6I
675 udelay(2); /* delay at least 1200 ns */
676 setbits_le32(&lcdc->lvds_ana0, SUNXI_LCDC_LVDS_ANA0_EN_MB);
677 udelay(2); /* delay at least 1200 ns */
678 setbits_le32(&lcdc->lvds_ana0, SUNXI_LCDC_LVDS_ANA0_DRVC);
679 if (sunxi_display.depth == 18)
680 setbits_le32(&lcdc->lvds_ana0, SUNXI_LCDC_LVDS_ANA0_DRVD(0x7));
682 setbits_le32(&lcdc->lvds_ana0, SUNXI_LCDC_LVDS_ANA0_DRVD(0xf));
684 setbits_le32(&lcdc->lvds_ana0, SUNXI_LCDC_LVDS_ANA0_UPDATE);
685 udelay(2); /* delay at least 1200 ns */
686 setbits_le32(&lcdc->lvds_ana1, SUNXI_LCDC_LVDS_ANA1_INIT1);
687 udelay(1); /* delay at least 120 ns */
688 setbits_le32(&lcdc->lvds_ana1, SUNXI_LCDC_LVDS_ANA1_INIT2);
689 setbits_le32(&lcdc->lvds_ana0, SUNXI_LCDC_LVDS_ANA0_UPDATE);
694 static void sunxi_lcdc_panel_enable(void)
699 * Start with backlight disabled to avoid the screen flashing to
700 * white while the lcd inits.
702 pin = sunxi_name_to_gpio(CONFIG_VIDEO_LCD_BL_EN);
704 gpio_request(pin, "lcd_backlight_enable");
705 gpio_direction_output(pin, 0);
708 pin = sunxi_name_to_gpio(CONFIG_VIDEO_LCD_BL_PWM);
710 gpio_request(pin, "lcd_backlight_pwm");
711 gpio_direction_output(pin, PWM_OFF);
714 reset_pin = sunxi_name_to_gpio(CONFIG_VIDEO_LCD_RESET);
715 if (reset_pin >= 0) {
716 gpio_request(reset_pin, "lcd_reset");
717 gpio_direction_output(reset_pin, 0); /* Assert reset */
720 /* Give the backlight some time to turn off and power up the panel. */
722 pin = sunxi_name_to_gpio(CONFIG_VIDEO_LCD_POWER);
724 gpio_request(pin, "lcd_power");
725 gpio_direction_output(pin, 1);
729 gpio_direction_output(reset_pin, 1); /* De-assert reset */
732 static void sunxi_lcdc_backlight_enable(void)
737 * We want to have scanned out at least one frame before enabling the
738 * backlight to avoid the screen flashing to white when we enable it.
742 pin = sunxi_name_to_gpio(CONFIG_VIDEO_LCD_BL_EN);
744 gpio_direction_output(pin, 1);
746 pin = sunxi_name_to_gpio(CONFIG_VIDEO_LCD_BL_PWM);
747 #ifdef SUNXI_PWM_PIN0
748 if (pin == SUNXI_PWM_PIN0) {
749 writel(SUNXI_PWM_CTRL_POLARITY0(PWM_ON) |
750 SUNXI_PWM_CTRL_ENABLE0 |
751 SUNXI_PWM_CTRL_PRESCALE0(0xf), SUNXI_PWM_CTRL_REG);
752 writel(SUNXI_PWM_PERIOD_80PCT, SUNXI_PWM_CH0_PERIOD);
753 sunxi_gpio_set_cfgpin(pin, SUNXI_PWM_MUX);
758 gpio_direction_output(pin, PWM_ON);
761 static int sunxi_lcdc_get_clk_delay(const struct ctfb_res_modes *mode, int tcon)
765 delay = mode->lower_margin + mode->vsync_len + mode->upper_margin;
766 if (mode->vmode == FB_VMODE_INTERLACED)
771 return (delay > 30) ? 30 : delay;
774 static void sunxi_lcdc_tcon0_mode_set(const struct ctfb_res_modes *mode,
775 bool for_ext_vga_dac)
777 struct sunxi_lcdc_reg * const lcdc =
778 (struct sunxi_lcdc_reg *)SUNXI_LCD0_BASE;
779 int bp, clk_delay, clk_div, clk_double, pin, total, val;
781 #if defined CONFIG_MACH_SUN8I && defined CONFIG_VIDEO_LCD_IF_LVDS
782 for (pin = SUNXI_GPD(18); pin <= SUNXI_GPD(27); pin++) {
784 for (pin = SUNXI_GPD(0); pin <= SUNXI_GPD(27); pin++) {
786 #ifdef CONFIG_VIDEO_LCD_IF_PARALLEL
787 sunxi_gpio_set_cfgpin(pin, SUNXI_GPD_LCD0);
789 #ifdef CONFIG_VIDEO_LCD_IF_LVDS
790 sunxi_gpio_set_cfgpin(pin, SUNXI_GPD_LVDS0);
792 #ifdef CONFIG_VIDEO_LCD_PANEL_EDP_4_LANE_1620M_VIA_ANX9804
793 sunxi_gpio_set_drv(pin, 3);
797 sunxi_lcdc_pll_set(0, mode->pixclock_khz, &clk_div, &clk_double);
800 clrsetbits_le32(&lcdc->ctrl, SUNXI_LCDC_CTRL_IO_MAP_MASK,
801 SUNXI_LCDC_CTRL_IO_MAP_TCON0);
803 clk_delay = sunxi_lcdc_get_clk_delay(mode, 0);
804 writel(SUNXI_LCDC_TCON0_CTRL_ENABLE |
805 SUNXI_LCDC_TCON0_CTRL_CLK_DELAY(clk_delay), &lcdc->tcon0_ctrl);
807 writel(SUNXI_LCDC_TCON0_DCLK_ENABLE |
808 SUNXI_LCDC_TCON0_DCLK_DIV(clk_div), &lcdc->tcon0_dclk);
810 writel(SUNXI_LCDC_X(mode->xres) | SUNXI_LCDC_Y(mode->yres),
811 &lcdc->tcon0_timing_active);
813 bp = mode->hsync_len + mode->left_margin;
814 total = mode->xres + mode->right_margin + bp;
815 writel(SUNXI_LCDC_TCON0_TIMING_H_TOTAL(total) |
816 SUNXI_LCDC_TCON0_TIMING_H_BP(bp), &lcdc->tcon0_timing_h);
818 bp = mode->vsync_len + mode->upper_margin;
819 total = mode->yres + mode->lower_margin + bp;
820 writel(SUNXI_LCDC_TCON0_TIMING_V_TOTAL(total) |
821 SUNXI_LCDC_TCON0_TIMING_V_BP(bp), &lcdc->tcon0_timing_v);
823 #ifdef CONFIG_VIDEO_LCD_IF_PARALLEL
824 writel(SUNXI_LCDC_X(mode->hsync_len) | SUNXI_LCDC_Y(mode->vsync_len),
825 &lcdc->tcon0_timing_sync);
827 writel(0, &lcdc->tcon0_hv_intf);
828 writel(0, &lcdc->tcon0_cpu_intf);
830 #ifdef CONFIG_VIDEO_LCD_IF_LVDS
831 val = (sunxi_display.depth == 18) ? 1 : 0;
832 writel(SUNXI_LCDC_TCON0_LVDS_INTF_BITWIDTH(val) |
833 SUNXI_LCDC_TCON0_LVDS_CLK_SEL_TCON0, &lcdc->tcon0_lvds_intf);
836 if (sunxi_display.depth == 18 || sunxi_display.depth == 16) {
837 writel(SUNXI_LCDC_TCON0_FRM_SEED, &lcdc->tcon0_frm_seed[0]);
838 writel(SUNXI_LCDC_TCON0_FRM_SEED, &lcdc->tcon0_frm_seed[1]);
839 writel(SUNXI_LCDC_TCON0_FRM_SEED, &lcdc->tcon0_frm_seed[2]);
840 writel(SUNXI_LCDC_TCON0_FRM_SEED, &lcdc->tcon0_frm_seed[3]);
841 writel(SUNXI_LCDC_TCON0_FRM_SEED, &lcdc->tcon0_frm_seed[4]);
842 writel(SUNXI_LCDC_TCON0_FRM_SEED, &lcdc->tcon0_frm_seed[5]);
843 writel(SUNXI_LCDC_TCON0_FRM_TAB0, &lcdc->tcon0_frm_table[0]);
844 writel(SUNXI_LCDC_TCON0_FRM_TAB1, &lcdc->tcon0_frm_table[1]);
845 writel(SUNXI_LCDC_TCON0_FRM_TAB2, &lcdc->tcon0_frm_table[2]);
846 writel(SUNXI_LCDC_TCON0_FRM_TAB3, &lcdc->tcon0_frm_table[3]);
847 writel(((sunxi_display.depth == 18) ?
848 SUNXI_LCDC_TCON0_FRM_CTRL_RGB666 :
849 SUNXI_LCDC_TCON0_FRM_CTRL_RGB565),
850 &lcdc->tcon0_frm_ctrl);
853 val = SUNXI_LCDC_TCON0_IO_POL_DCLK_PHASE(CONFIG_VIDEO_LCD_DCLK_PHASE);
854 if (!(mode->sync & FB_SYNC_HOR_HIGH_ACT))
855 val |= SUNXI_LCDC_TCON_HSYNC_MASK;
856 if (!(mode->sync & FB_SYNC_VERT_HIGH_ACT))
857 val |= SUNXI_LCDC_TCON_VSYNC_MASK;
859 #ifdef CONFIG_VIDEO_VGA_VIA_LCD_FORCE_SYNC_ACTIVE_HIGH
863 writel(val, &lcdc->tcon0_io_polarity);
865 writel(0, &lcdc->tcon0_io_tristate);
868 #if defined CONFIG_VIDEO_HDMI || defined CONFIG_VIDEO_VGA || defined CONFIG_VIDEO_COMPOSITE
869 static void sunxi_lcdc_tcon1_mode_set(const struct ctfb_res_modes *mode,
870 int *clk_div, int *clk_double,
871 bool use_portd_hvsync)
873 struct sunxi_lcdc_reg * const lcdc =
874 (struct sunxi_lcdc_reg *)SUNXI_LCD0_BASE;
875 int bp, clk_delay, total, val, yres;
878 clrsetbits_le32(&lcdc->ctrl, SUNXI_LCDC_CTRL_IO_MAP_MASK,
879 SUNXI_LCDC_CTRL_IO_MAP_TCON1);
881 clk_delay = sunxi_lcdc_get_clk_delay(mode, 1);
882 writel(SUNXI_LCDC_TCON1_CTRL_ENABLE |
883 ((mode->vmode == FB_VMODE_INTERLACED) ?
884 SUNXI_LCDC_TCON1_CTRL_INTERLACE_ENABLE : 0) |
885 SUNXI_LCDC_TCON1_CTRL_CLK_DELAY(clk_delay), &lcdc->tcon1_ctrl);
888 if (mode->vmode == FB_VMODE_INTERLACED)
890 writel(SUNXI_LCDC_X(mode->xres) | SUNXI_LCDC_Y(yres),
891 &lcdc->tcon1_timing_source);
892 writel(SUNXI_LCDC_X(mode->xres) | SUNXI_LCDC_Y(yres),
893 &lcdc->tcon1_timing_scale);
894 writel(SUNXI_LCDC_X(mode->xres) | SUNXI_LCDC_Y(yres),
895 &lcdc->tcon1_timing_out);
897 bp = mode->hsync_len + mode->left_margin;
898 total = mode->xres + mode->right_margin + bp;
899 writel(SUNXI_LCDC_TCON1_TIMING_H_TOTAL(total) |
900 SUNXI_LCDC_TCON1_TIMING_H_BP(bp), &lcdc->tcon1_timing_h);
902 bp = mode->vsync_len + mode->upper_margin;
903 total = mode->yres + mode->lower_margin + bp;
904 if (mode->vmode == FB_VMODE_NONINTERLACED)
906 writel(SUNXI_LCDC_TCON1_TIMING_V_TOTAL(total) |
907 SUNXI_LCDC_TCON1_TIMING_V_BP(bp), &lcdc->tcon1_timing_v);
909 writel(SUNXI_LCDC_X(mode->hsync_len) | SUNXI_LCDC_Y(mode->vsync_len),
910 &lcdc->tcon1_timing_sync);
912 if (use_portd_hvsync) {
913 sunxi_gpio_set_cfgpin(SUNXI_GPD(26), SUNXI_GPD_LCD0);
914 sunxi_gpio_set_cfgpin(SUNXI_GPD(27), SUNXI_GPD_LCD0);
917 if (mode->sync & FB_SYNC_HOR_HIGH_ACT)
918 val |= SUNXI_LCDC_TCON_HSYNC_MASK;
919 if (mode->sync & FB_SYNC_VERT_HIGH_ACT)
920 val |= SUNXI_LCDC_TCON_VSYNC_MASK;
921 writel(val, &lcdc->tcon1_io_polarity);
923 clrbits_le32(&lcdc->tcon1_io_tristate,
924 SUNXI_LCDC_TCON_VSYNC_MASK |
925 SUNXI_LCDC_TCON_HSYNC_MASK);
928 #ifdef CONFIG_MACH_SUN5I
929 if (sunxi_is_composite())
930 clrsetbits_le32(&lcdc->mux_ctrl, SUNXI_LCDC_MUX_CTRL_SRC0_MASK,
931 SUNXI_LCDC_MUX_CTRL_SRC0(1));
934 sunxi_lcdc_pll_set(1, mode->pixclock_khz, clk_div, clk_double);
936 #endif /* CONFIG_VIDEO_HDMI || defined CONFIG_VIDEO_VGA || CONFIG_VIDEO_COMPOSITE */
938 #ifdef CONFIG_VIDEO_HDMI
940 static void sunxi_hdmi_setup_info_frames(const struct ctfb_res_modes *mode)
942 struct sunxi_hdmi_reg * const hdmi =
943 (struct sunxi_hdmi_reg *)SUNXI_HDMI_BASE;
945 u8 avi_info_frame[17] = {
946 0x82, 0x02, 0x0d, 0x00, 0x12, 0x00, 0x88, 0x00,
947 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
950 u8 vendor_info_frame[19] = {
951 0x81, 0x01, 0x06, 0x29, 0x03, 0x0c, 0x00, 0x40,
952 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
957 if (mode->pixclock_khz <= 27000)
958 avi_info_frame[5] = 0x40; /* SD-modes, ITU601 colorspace */
960 avi_info_frame[5] = 0x80; /* HD-modes, ITU709 colorspace */
962 if (mode->xres * 100 / mode->yres < 156)
963 avi_info_frame[5] |= 0x18; /* 4 : 3 */
965 avi_info_frame[5] |= 0x28; /* 16 : 9 */
967 for (i = 0; i < ARRAY_SIZE(avi_info_frame); i++)
968 checksum += avi_info_frame[i];
970 avi_info_frame[3] = 0x100 - checksum;
972 for (i = 0; i < ARRAY_SIZE(avi_info_frame); i++)
973 writeb(avi_info_frame[i], &hdmi->avi_info_frame[i]);
975 writel(SUNXI_HDMI_QCP_PACKET0, &hdmi->qcp_packet0);
976 writel(SUNXI_HDMI_QCP_PACKET1, &hdmi->qcp_packet1);
978 for (i = 0; i < ARRAY_SIZE(vendor_info_frame); i++)
979 writeb(vendor_info_frame[i], &hdmi->vendor_info_frame[i]);
981 writel(SUNXI_HDMI_PKT_CTRL0, &hdmi->pkt_ctrl0);
982 writel(SUNXI_HDMI_PKT_CTRL1, &hdmi->pkt_ctrl1);
984 setbits_le32(&hdmi->video_ctrl, SUNXI_HDMI_VIDEO_CTRL_HDMI);
987 static void sunxi_hdmi_mode_set(const struct ctfb_res_modes *mode,
988 int clk_div, int clk_double)
990 struct sunxi_hdmi_reg * const hdmi =
991 (struct sunxi_hdmi_reg *)SUNXI_HDMI_BASE;
994 /* Write clear interrupt status bits */
995 writel(SUNXI_HDMI_IRQ_STATUS_BITS, &hdmi->irq);
997 if (sunxi_display.monitor == sunxi_monitor_hdmi)
998 sunxi_hdmi_setup_info_frames(mode);
1000 /* Set input sync enable */
1001 writel(SUNXI_HDMI_UNKNOWN_INPUT_SYNC, &hdmi->unknown);
1003 /* Init various registers, select pll3 as clock source */
1004 writel(SUNXI_HDMI_VIDEO_POL_TX_CLK, &hdmi->video_polarity);
1005 writel(SUNXI_HDMI_PAD_CTRL0_RUN, &hdmi->pad_ctrl0);
1006 writel(SUNXI_HDMI_PAD_CTRL1, &hdmi->pad_ctrl1);
1007 writel(SUNXI_HDMI_PLL_CTRL, &hdmi->pll_ctrl);
1008 writel(SUNXI_HDMI_PLL_DBG0_PLL3, &hdmi->pll_dbg0);
1010 /* Setup clk div and doubler */
1011 clrsetbits_le32(&hdmi->pll_ctrl, SUNXI_HDMI_PLL_CTRL_DIV_MASK,
1012 SUNXI_HDMI_PLL_CTRL_DIV(clk_div));
1014 setbits_le32(&hdmi->pad_ctrl1, SUNXI_HDMI_PAD_CTRL1_HALVE);
1016 /* Setup timing registers */
1017 writel(SUNXI_HDMI_Y(mode->yres) | SUNXI_HDMI_X(mode->xres),
1020 x = mode->hsync_len + mode->left_margin;
1021 y = mode->vsync_len + mode->upper_margin;
1022 writel(SUNXI_HDMI_Y(y) | SUNXI_HDMI_X(x), &hdmi->video_bp);
1024 x = mode->right_margin;
1025 y = mode->lower_margin;
1026 writel(SUNXI_HDMI_Y(y) | SUNXI_HDMI_X(x), &hdmi->video_fp);
1028 x = mode->hsync_len;
1029 y = mode->vsync_len;
1030 writel(SUNXI_HDMI_Y(y) | SUNXI_HDMI_X(x), &hdmi->video_spw);
1032 if (mode->sync & FB_SYNC_HOR_HIGH_ACT)
1033 setbits_le32(&hdmi->video_polarity, SUNXI_HDMI_VIDEO_POL_HOR);
1035 if (mode->sync & FB_SYNC_VERT_HIGH_ACT)
1036 setbits_le32(&hdmi->video_polarity, SUNXI_HDMI_VIDEO_POL_VER);
1039 static void sunxi_hdmi_enable(void)
1041 struct sunxi_hdmi_reg * const hdmi =
1042 (struct sunxi_hdmi_reg *)SUNXI_HDMI_BASE;
1045 setbits_le32(&hdmi->video_ctrl, SUNXI_HDMI_VIDEO_CTRL_ENABLE);
1048 #endif /* CONFIG_VIDEO_HDMI */
1050 #if defined CONFIG_VIDEO_VGA || defined CONFIG_VIDEO_COMPOSITE
1052 static void sunxi_tvencoder_mode_set(void)
1054 struct sunxi_ccm_reg * const ccm =
1055 (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
1056 struct sunxi_tve_reg * const tve =
1057 (struct sunxi_tve_reg *)SUNXI_TVE0_BASE;
1060 setbits_le32(&ccm->lcd0_ch0_clk_cfg, CCM_LCD_CH0_CTRL_TVE_RST);
1062 setbits_le32(&ccm->ahb_gate1, 1 << AHB_GATE_OFFSET_TVE0);
1064 switch (sunxi_display.monitor) {
1065 case sunxi_monitor_vga:
1066 writel(SUNXI_TVE_GCTRL_DAC_INPUT(0, 1) |
1067 SUNXI_TVE_GCTRL_DAC_INPUT(1, 2) |
1068 SUNXI_TVE_GCTRL_DAC_INPUT(2, 3), &tve->gctrl);
1069 writel(SUNXI_TVE_CFG0_VGA, &tve->cfg0);
1070 writel(SUNXI_TVE_DAC_CFG0_VGA, &tve->dac_cfg0);
1071 writel(SUNXI_TVE_UNKNOWN1_VGA, &tve->unknown1);
1073 case sunxi_monitor_composite_pal_nc:
1074 writel(SUNXI_TVE_CHROMA_FREQ_PAL_NC, &tve->chroma_freq);
1076 case sunxi_monitor_composite_pal:
1077 writel(SUNXI_TVE_GCTRL_DAC_INPUT(0, 1) |
1078 SUNXI_TVE_GCTRL_DAC_INPUT(1, 2) |
1079 SUNXI_TVE_GCTRL_DAC_INPUT(2, 3) |
1080 SUNXI_TVE_GCTRL_DAC_INPUT(3, 4), &tve->gctrl);
1081 writel(SUNXI_TVE_CFG0_PAL, &tve->cfg0);
1082 writel(SUNXI_TVE_DAC_CFG0_COMPOSITE, &tve->dac_cfg0);
1083 writel(SUNXI_TVE_FILTER_COMPOSITE, &tve->filter);
1084 writel(SUNXI_TVE_PORCH_NUM_PAL, &tve->porch_num);
1085 writel(SUNXI_TVE_LINE_NUM_PAL, &tve->line_num);
1086 writel(SUNXI_TVE_BLANK_BLACK_LEVEL_PAL, &tve->blank_black_level);
1087 writel(SUNXI_TVE_UNKNOWN1_COMPOSITE, &tve->unknown1);
1088 writel(SUNXI_TVE_CBR_LEVEL_PAL, &tve->cbr_level);
1089 writel(SUNXI_TVE_BURST_WIDTH_COMPOSITE, &tve->burst_width);
1090 writel(SUNXI_TVE_UNKNOWN2_PAL, &tve->unknown2);
1091 writel(SUNXI_TVE_ACTIVE_NUM_COMPOSITE, &tve->active_num);
1092 writel(SUNXI_TVE_CHROMA_BW_GAIN_COMP, &tve->chroma_bw_gain);
1093 writel(SUNXI_TVE_NOTCH_WIDTH_COMPOSITE, &tve->notch_width);
1094 writel(SUNXI_TVE_RESYNC_NUM_PAL, &tve->resync_num);
1095 writel(SUNXI_TVE_SLAVE_PARA_COMPOSITE, &tve->slave_para);
1097 case sunxi_monitor_composite_pal_m:
1098 writel(SUNXI_TVE_CHROMA_FREQ_PAL_M, &tve->chroma_freq);
1099 writel(SUNXI_TVE_COLOR_BURST_PAL_M, &tve->color_burst);
1101 case sunxi_monitor_composite_ntsc:
1102 writel(SUNXI_TVE_GCTRL_DAC_INPUT(0, 1) |
1103 SUNXI_TVE_GCTRL_DAC_INPUT(1, 2) |
1104 SUNXI_TVE_GCTRL_DAC_INPUT(2, 3) |
1105 SUNXI_TVE_GCTRL_DAC_INPUT(3, 4), &tve->gctrl);
1106 writel(SUNXI_TVE_CFG0_NTSC, &tve->cfg0);
1107 writel(SUNXI_TVE_DAC_CFG0_COMPOSITE, &tve->dac_cfg0);
1108 writel(SUNXI_TVE_FILTER_COMPOSITE, &tve->filter);
1109 writel(SUNXI_TVE_PORCH_NUM_NTSC, &tve->porch_num);
1110 writel(SUNXI_TVE_LINE_NUM_NTSC, &tve->line_num);
1111 writel(SUNXI_TVE_BLANK_BLACK_LEVEL_NTSC, &tve->blank_black_level);
1112 writel(SUNXI_TVE_UNKNOWN1_COMPOSITE, &tve->unknown1);
1113 writel(SUNXI_TVE_CBR_LEVEL_NTSC, &tve->cbr_level);
1114 writel(SUNXI_TVE_BURST_PHASE_NTSC, &tve->burst_phase);
1115 writel(SUNXI_TVE_BURST_WIDTH_COMPOSITE, &tve->burst_width);
1116 writel(SUNXI_TVE_UNKNOWN2_NTSC, &tve->unknown2);
1117 writel(SUNXI_TVE_SYNC_VBI_LEVEL_NTSC, &tve->sync_vbi_level);
1118 writel(SUNXI_TVE_ACTIVE_NUM_COMPOSITE, &tve->active_num);
1119 writel(SUNXI_TVE_CHROMA_BW_GAIN_COMP, &tve->chroma_bw_gain);
1120 writel(SUNXI_TVE_NOTCH_WIDTH_COMPOSITE, &tve->notch_width);
1121 writel(SUNXI_TVE_RESYNC_NUM_NTSC, &tve->resync_num);
1122 writel(SUNXI_TVE_SLAVE_PARA_COMPOSITE, &tve->slave_para);
1124 case sunxi_monitor_none:
1125 case sunxi_monitor_dvi:
1126 case sunxi_monitor_hdmi:
1127 case sunxi_monitor_lcd:
1132 static void sunxi_tvencoder_enable(void)
1134 struct sunxi_tve_reg * const tve =
1135 (struct sunxi_tve_reg *)SUNXI_TVE0_BASE;
1137 setbits_le32(&tve->gctrl, SUNXI_TVE_GCTRL_ENABLE);
1140 #endif /* CONFIG_VIDEO_VGA || defined CONFIG_VIDEO_COMPOSITE */
1142 static void sunxi_drc_init(void)
1144 #ifdef CONFIG_SUNXI_GEN_SUN6I
1145 struct sunxi_ccm_reg * const ccm =
1146 (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
1148 /* On sun6i the drc must be clocked even when in pass-through mode */
1149 #ifdef CONFIG_MACH_SUN8I_A33
1150 setbits_le32(&ccm->ahb_reset1_cfg, 1 << AHB_RESET_OFFSET_SAT);
1152 setbits_le32(&ccm->ahb_reset1_cfg, 1 << AHB_RESET_OFFSET_DRC0);
1153 clock_set_de_mod_clock(&ccm->iep_drc0_clk_cfg, 300000000);
1157 #ifdef CONFIG_VIDEO_VGA_VIA_LCD
1158 static void sunxi_vga_external_dac_enable(void)
1162 pin = sunxi_name_to_gpio(CONFIG_VIDEO_VGA_EXTERNAL_DAC_EN);
1164 gpio_request(pin, "vga_enable");
1165 gpio_direction_output(pin, 1);
1168 #endif /* CONFIG_VIDEO_VGA_VIA_LCD */
1170 #ifdef CONFIG_VIDEO_LCD_SSD2828
1171 static int sunxi_ssd2828_init(const struct ctfb_res_modes *mode)
1173 struct ssd2828_config cfg = {
1174 .csx_pin = name_to_gpio(CONFIG_VIDEO_LCD_SPI_CS),
1175 .sck_pin = name_to_gpio(CONFIG_VIDEO_LCD_SPI_SCLK),
1176 .sdi_pin = name_to_gpio(CONFIG_VIDEO_LCD_SPI_MOSI),
1177 .sdo_pin = name_to_gpio(CONFIG_VIDEO_LCD_SPI_MISO),
1178 .reset_pin = name_to_gpio(CONFIG_VIDEO_LCD_SSD2828_RESET),
1179 .ssd2828_tx_clk_khz = CONFIG_VIDEO_LCD_SSD2828_TX_CLK * 1000,
1180 .ssd2828_color_depth = 24,
1181 #ifdef CONFIG_VIDEO_LCD_PANEL_MIPI_4_LANE_513_MBPS_VIA_SSD2828
1182 .mipi_dsi_number_of_data_lanes = 4,
1183 .mipi_dsi_bitrate_per_data_lane_mbps = 513,
1184 .mipi_dsi_delay_after_exit_sleep_mode_ms = 100,
1185 .mipi_dsi_delay_after_set_display_on_ms = 200
1187 #error MIPI LCD panel needs configuration parameters
1191 if (cfg.csx_pin == -1 || cfg.sck_pin == -1 || cfg.sdi_pin == -1) {
1192 printf("SSD2828: SPI pins are not properly configured\n");
1195 if (cfg.reset_pin == -1) {
1196 printf("SSD2828: Reset pin is not properly configured\n");
1200 return ssd2828_init(&cfg, mode);
1202 #endif /* CONFIG_VIDEO_LCD_SSD2828 */
1204 static void sunxi_engines_init(void)
1206 sunxi_composer_init();
1211 static void sunxi_mode_set(const struct ctfb_res_modes *mode,
1212 unsigned int address)
1214 int __maybe_unused clk_div, clk_double;
1216 switch (sunxi_display.monitor) {
1217 case sunxi_monitor_none:
1219 case sunxi_monitor_dvi:
1220 case sunxi_monitor_hdmi:
1221 #ifdef CONFIG_VIDEO_HDMI
1222 sunxi_composer_mode_set(mode, address);
1223 sunxi_lcdc_tcon1_mode_set(mode, &clk_div, &clk_double, 0);
1224 sunxi_hdmi_mode_set(mode, clk_div, clk_double);
1225 sunxi_composer_enable();
1226 sunxi_lcdc_enable();
1227 sunxi_hdmi_enable();
1230 case sunxi_monitor_lcd:
1231 sunxi_lcdc_panel_enable();
1232 if (IS_ENABLED(CONFIG_VIDEO_LCD_PANEL_EDP_4_LANE_1620M_VIA_ANX9804)) {
1234 * The anx9804 needs 1.8V from eldo3, we do this here
1235 * and not via CONFIG_AXP_ELDO3_VOLT from board_init()
1236 * to avoid turning this on when using hdmi output.
1238 axp_set_eldo(3, 1800);
1239 anx9804_init(CONFIG_VIDEO_LCD_I2C_BUS, 4,
1240 ANX9804_DATA_RATE_1620M,
1241 sunxi_display.depth);
1243 if (IS_ENABLED(CONFIG_VIDEO_LCD_HITACHI_TX18D42VM)) {
1244 mdelay(50); /* Wait for lcd controller power on */
1245 hitachi_tx18d42vm_init();
1247 if (IS_ENABLED(CONFIG_VIDEO_LCD_TL059WV5C0)) {
1248 unsigned int orig_i2c_bus = i2c_get_bus_num();
1249 i2c_set_bus_num(CONFIG_VIDEO_LCD_I2C_BUS);
1250 i2c_reg_write(0x5c, 0x04, 0x42); /* Turn on the LCD */
1251 i2c_set_bus_num(orig_i2c_bus);
1253 sunxi_composer_mode_set(mode, address);
1254 sunxi_lcdc_tcon0_mode_set(mode, false);
1255 sunxi_composer_enable();
1256 sunxi_lcdc_enable();
1257 #ifdef CONFIG_VIDEO_LCD_SSD2828
1258 sunxi_ssd2828_init(mode);
1260 sunxi_lcdc_backlight_enable();
1262 case sunxi_monitor_vga:
1263 #ifdef CONFIG_VIDEO_VGA
1264 sunxi_composer_mode_set(mode, address);
1265 sunxi_lcdc_tcon1_mode_set(mode, &clk_div, &clk_double, 1);
1266 sunxi_tvencoder_mode_set();
1267 sunxi_composer_enable();
1268 sunxi_lcdc_enable();
1269 sunxi_tvencoder_enable();
1270 #elif defined CONFIG_VIDEO_VGA_VIA_LCD
1271 sunxi_composer_mode_set(mode, address);
1272 sunxi_lcdc_tcon0_mode_set(mode, true);
1273 sunxi_composer_enable();
1274 sunxi_lcdc_enable();
1275 sunxi_vga_external_dac_enable();
1278 case sunxi_monitor_composite_pal:
1279 case sunxi_monitor_composite_ntsc:
1280 case sunxi_monitor_composite_pal_m:
1281 case sunxi_monitor_composite_pal_nc:
1282 #ifdef CONFIG_VIDEO_COMPOSITE
1283 sunxi_composer_mode_set(mode, address);
1284 sunxi_lcdc_tcon1_mode_set(mode, &clk_div, &clk_double, 0);
1285 sunxi_tvencoder_mode_set();
1286 sunxi_composer_enable();
1287 sunxi_lcdc_enable();
1288 sunxi_tvencoder_enable();
1294 static const char *sunxi_get_mon_desc(enum sunxi_monitor monitor)
1297 case sunxi_monitor_none: return "none";
1298 case sunxi_monitor_dvi: return "dvi";
1299 case sunxi_monitor_hdmi: return "hdmi";
1300 case sunxi_monitor_lcd: return "lcd";
1301 case sunxi_monitor_vga: return "vga";
1302 case sunxi_monitor_composite_pal: return "composite-pal";
1303 case sunxi_monitor_composite_ntsc: return "composite-ntsc";
1304 case sunxi_monitor_composite_pal_m: return "composite-pal-m";
1305 case sunxi_monitor_composite_pal_nc: return "composite-pal-nc";
1307 return NULL; /* never reached */
1310 ulong board_get_usable_ram_top(ulong total_size)
1312 return gd->ram_top - CONFIG_SUNXI_MAX_FB_SIZE;
1315 static bool sunxi_has_hdmi(void)
1317 #ifdef CONFIG_VIDEO_HDMI
1324 static bool sunxi_has_lcd(void)
1326 char *lcd_mode = CONFIG_VIDEO_LCD_MODE;
1328 return lcd_mode[0] != 0;
1331 static bool sunxi_has_vga(void)
1333 #if defined CONFIG_VIDEO_VGA || defined CONFIG_VIDEO_VGA_VIA_LCD
1340 static bool sunxi_has_composite(void)
1342 #ifdef CONFIG_VIDEO_COMPOSITE
1349 static enum sunxi_monitor sunxi_get_default_mon(bool allow_hdmi)
1351 if (allow_hdmi && sunxi_has_hdmi())
1352 return sunxi_monitor_dvi;
1353 else if (sunxi_has_lcd())
1354 return sunxi_monitor_lcd;
1355 else if (sunxi_has_vga())
1356 return sunxi_monitor_vga;
1357 else if (sunxi_has_composite())
1358 return sunxi_monitor_composite_pal;
1360 return sunxi_monitor_none;
1363 void *video_hw_init(void)
1365 static GraphicDevice *graphic_device = &sunxi_display.graphic_device;
1366 const struct ctfb_res_modes *mode;
1367 struct ctfb_res_modes custom;
1368 const char *options;
1369 #ifdef CONFIG_VIDEO_HDMI
1370 int ret, hpd, hpd_delay, edid;
1372 int i, overscan_offset, overscan_x, overscan_y;
1373 unsigned int fb_dma_addr;
1375 char *lcd_mode = CONFIG_VIDEO_LCD_MODE;
1377 memset(&sunxi_display, 0, sizeof(struct sunxi_display));
1379 video_get_ctfb_res_modes(RES_MODE_1024x768, 24, &mode,
1380 &sunxi_display.depth, &options);
1381 #ifdef CONFIG_VIDEO_HDMI
1382 hpd = video_get_option_int(options, "hpd", 1);
1383 hpd_delay = video_get_option_int(options, "hpd_delay", 500);
1384 edid = video_get_option_int(options, "edid", 1);
1386 overscan_x = video_get_option_int(options, "overscan_x", -1);
1387 overscan_y = video_get_option_int(options, "overscan_y", -1);
1388 sunxi_display.monitor = sunxi_get_default_mon(true);
1389 video_get_option_string(options, "monitor", mon, sizeof(mon),
1390 sunxi_get_mon_desc(sunxi_display.monitor));
1391 for (i = 0; i <= SUNXI_MONITOR_LAST; i++) {
1392 if (strcmp(mon, sunxi_get_mon_desc(i)) == 0) {
1393 sunxi_display.monitor = i;
1397 if (i > SUNXI_MONITOR_LAST)
1398 printf("Unknown monitor: '%s', falling back to '%s'\n",
1399 mon, sunxi_get_mon_desc(sunxi_display.monitor));
1401 #ifdef CONFIG_VIDEO_HDMI
1402 /* If HDMI/DVI is selected do HPD & EDID, and handle fallback */
1403 if (sunxi_display.monitor == sunxi_monitor_dvi ||
1404 sunxi_display.monitor == sunxi_monitor_hdmi) {
1405 /* Always call hdp_detect, as it also enables clocks, etc. */
1406 ret = sunxi_hdmi_hpd_detect(hpd_delay);
1408 printf("HDMI connected: ");
1409 if (edid && sunxi_hdmi_edid_get_mode(&custom) == 0)
1412 sunxi_hdmi_shutdown();
1413 sunxi_display.monitor = sunxi_get_default_mon(false);
1414 } /* else continue with hdmi/dvi without a cable connected */
1418 switch (sunxi_display.monitor) {
1419 case sunxi_monitor_none:
1421 case sunxi_monitor_dvi:
1422 case sunxi_monitor_hdmi:
1423 if (!sunxi_has_hdmi()) {
1424 printf("HDMI/DVI not supported on this board\n");
1425 sunxi_display.monitor = sunxi_monitor_none;
1429 case sunxi_monitor_lcd:
1430 if (!sunxi_has_lcd()) {
1431 printf("LCD not supported on this board\n");
1432 sunxi_display.monitor = sunxi_monitor_none;
1435 sunxi_display.depth = video_get_params(&custom, lcd_mode);
1438 case sunxi_monitor_vga:
1439 if (!sunxi_has_vga()) {
1440 printf("VGA not supported on this board\n");
1441 sunxi_display.monitor = sunxi_monitor_none;
1444 sunxi_display.depth = 18;
1446 case sunxi_monitor_composite_pal:
1447 case sunxi_monitor_composite_ntsc:
1448 case sunxi_monitor_composite_pal_m:
1449 case sunxi_monitor_composite_pal_nc:
1450 if (!sunxi_has_composite()) {
1451 printf("Composite video not supported on this board\n");
1452 sunxi_display.monitor = sunxi_monitor_none;
1455 if (sunxi_display.monitor == sunxi_monitor_composite_pal ||
1456 sunxi_display.monitor == sunxi_monitor_composite_pal_nc)
1457 mode = &composite_video_modes[0];
1459 mode = &composite_video_modes[1];
1460 sunxi_display.depth = 24;
1464 /* Yes these defaults are quite high, overscan on composite sucks... */
1465 if (overscan_x == -1)
1466 overscan_x = sunxi_is_composite() ? 32 : 0;
1467 if (overscan_y == -1)
1468 overscan_y = sunxi_is_composite() ? 20 : 0;
1470 sunxi_display.fb_size =
1471 (mode->xres * mode->yres * 4 + 0xfff) & ~0xfff;
1472 overscan_offset = (overscan_y * mode->xres + overscan_x) * 4;
1473 /* We want to keep the fb_base for simplefb page aligned, where as
1474 * the sunxi dma engines will happily accept an unaligned address. */
1475 if (overscan_offset)
1476 sunxi_display.fb_size += 0x1000;
1478 if (sunxi_display.fb_size > CONFIG_SUNXI_MAX_FB_SIZE) {
1479 printf("Error need %dkB for fb, but only %dkB is reserved\n",
1480 sunxi_display.fb_size >> 10,
1481 CONFIG_SUNXI_MAX_FB_SIZE >> 10);
1485 printf("Setting up a %dx%d%s %s console (overscan %dx%d)\n",
1486 mode->xres, mode->yres,
1487 (mode->vmode == FB_VMODE_INTERLACED) ? "i" : "",
1488 sunxi_get_mon_desc(sunxi_display.monitor),
1489 overscan_x, overscan_y);
1491 gd->fb_base = gd->bd->bi_dram[0].start +
1492 gd->bd->bi_dram[0].size - sunxi_display.fb_size;
1493 sunxi_engines_init();
1495 fb_dma_addr = gd->fb_base - CONFIG_SYS_SDRAM_BASE;
1496 sunxi_display.fb_addr = gd->fb_base;
1497 if (overscan_offset) {
1498 fb_dma_addr += 0x1000 - (overscan_offset & 0xfff);
1499 sunxi_display.fb_addr += (overscan_offset + 0xfff) & ~0xfff;
1500 memset((void *)gd->fb_base, 0, sunxi_display.fb_size);
1501 flush_cache(gd->fb_base, sunxi_display.fb_size);
1503 sunxi_mode_set(mode, fb_dma_addr);
1506 * These are the only members of this structure that are used. All the
1507 * others are driver specific. The pitch is stored in plnSizeX.
1509 graphic_device->frameAdrs = sunxi_display.fb_addr;
1510 graphic_device->gdfIndex = GDF_32BIT_X888RGB;
1511 graphic_device->gdfBytesPP = 4;
1512 graphic_device->winSizeX = mode->xres - 2 * overscan_x;
1513 graphic_device->winSizeY = mode->yres - 2 * overscan_y;
1514 graphic_device->plnSizeX = mode->xres * graphic_device->gdfBytesPP;
1516 return graphic_device;
1522 #if defined(CONFIG_OF_BOARD_SETUP) && defined(CONFIG_VIDEO_DT_SIMPLEFB)
1523 int sunxi_simplefb_setup(void *blob)
1525 static GraphicDevice *graphic_device = &sunxi_display.graphic_device;
1528 const char *pipeline = NULL;
1530 #ifdef CONFIG_MACH_SUN4I
1531 #define PIPELINE_PREFIX "de_fe0-"
1533 #define PIPELINE_PREFIX
1536 switch (sunxi_display.monitor) {
1537 case sunxi_monitor_none:
1539 case sunxi_monitor_dvi:
1540 case sunxi_monitor_hdmi:
1541 pipeline = PIPELINE_PREFIX "de_be0-lcd0-hdmi";
1543 case sunxi_monitor_lcd:
1544 pipeline = PIPELINE_PREFIX "de_be0-lcd0";
1546 case sunxi_monitor_vga:
1547 #ifdef CONFIG_VIDEO_VGA
1548 pipeline = PIPELINE_PREFIX "de_be0-lcd0-tve0";
1549 #elif defined CONFIG_VIDEO_VGA_VIA_LCD
1550 pipeline = PIPELINE_PREFIX "de_be0-lcd0";
1553 case sunxi_monitor_composite_pal:
1554 case sunxi_monitor_composite_ntsc:
1555 case sunxi_monitor_composite_pal_m:
1556 case sunxi_monitor_composite_pal_nc:
1557 pipeline = PIPELINE_PREFIX "de_be0-lcd0-tve0";
1561 /* Find a prefilled simpefb node, matching out pipeline config */
1562 offset = fdt_node_offset_by_compatible(blob, -1,
1563 "allwinner,simple-framebuffer");
1564 while (offset >= 0) {
1565 ret = fdt_stringlist_search(blob, offset, "allwinner,pipeline",
1569 offset = fdt_node_offset_by_compatible(blob, offset,
1570 "allwinner,simple-framebuffer");
1573 eprintf("Cannot setup simplefb: node not found\n");
1574 return 0; /* Keep older kernels working */
1578 * Do not report the framebuffer as free RAM to the OS, note we cannot
1579 * use fdt_add_mem_rsv() here, because then it is still seen as RAM,
1580 * and e.g. Linux refuses to iomap RAM on ARM, see:
1581 * linux/arch/arm/mm/ioremap.c around line 301.
1583 start = gd->bd->bi_dram[0].start;
1584 size = gd->bd->bi_dram[0].size - sunxi_display.fb_size;
1585 ret = fdt_fixup_memory_banks(blob, &start, &size, 1);
1587 eprintf("Cannot setup simplefb: Error reserving memory\n");
1591 ret = fdt_setup_simplefb_node(blob, offset, sunxi_display.fb_addr,
1592 graphic_device->winSizeX, graphic_device->winSizeY,
1593 graphic_device->plnSizeX, "x8r8g8b8");
1595 eprintf("Cannot setup simplefb: Error setting properties\n");
1599 #endif /* CONFIG_OF_BOARD_SETUP && CONFIG_VIDEO_DT_SIMPLEFB */