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/global_data.h>
20 #include <fdt_support.h>
24 #include "videomodes.h"
25 #include "hitachi_tx18d42vm_lcd.h"
28 #ifdef CONFIG_VIDEO_LCD_BL_PWM_ACTIVE_LOW
36 DECLARE_GLOBAL_DATA_PTR;
44 sunxi_monitor_composite_pal,
45 sunxi_monitor_composite_ntsc,
46 sunxi_monitor_composite_pal_m,
47 sunxi_monitor_composite_pal_nc,
49 #define SUNXI_MONITOR_LAST sunxi_monitor_composite_pal_nc
51 struct sunxi_display {
52 GraphicDevice graphic_device;
53 enum sunxi_monitor monitor;
59 const struct ctfb_res_modes composite_video_modes[2] = {
60 /* x y hz pixclk ps/kHz le ri up lo hs vs s vmode */
61 { 720, 576, 50, 37037, 27000, 137, 5, 20, 27, 2, 2, 0, FB_VMODE_INTERLACED },
62 { 720, 480, 60, 37037, 27000, 116, 20, 16, 27, 2, 2, 0, FB_VMODE_INTERLACED },
65 #ifdef CONFIG_VIDEO_HDMI
68 * Wait up to 200ms for value to be set in given part of reg.
70 static int await_completion(u32 *reg, u32 mask, u32 val)
72 unsigned long tmo = timer_get_us() + 200000;
74 while ((readl(reg) & mask) != val) {
75 if (timer_get_us() > tmo) {
76 printf("DDC: timeout reading EDID\n");
83 static int sunxi_hdmi_hpd_detect(int hpd_delay)
85 struct sunxi_ccm_reg * const ccm =
86 (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
87 struct sunxi_hdmi_reg * const hdmi =
88 (struct sunxi_hdmi_reg *)SUNXI_HDMI_BASE;
89 unsigned long tmo = timer_get_us() + hpd_delay * 1000;
91 /* Set pll3 to 300MHz */
92 clock_set_pll3(300000000);
94 /* Set hdmi parent to pll3 */
95 clrsetbits_le32(&ccm->hdmi_clk_cfg, CCM_HDMI_CTRL_PLL_MASK,
98 /* Set ahb gating to pass */
99 #ifdef CONFIG_SUNXI_GEN_SUN6I
100 setbits_le32(&ccm->ahb_reset1_cfg, 1 << AHB_RESET_OFFSET_HDMI);
102 setbits_le32(&ccm->ahb_gate1, 1 << AHB_GATE_OFFSET_HDMI);
105 setbits_le32(&ccm->hdmi_clk_cfg, CCM_HDMI_CTRL_GATE);
107 writel(SUNXI_HDMI_CTRL_ENABLE, &hdmi->ctrl);
108 writel(SUNXI_HDMI_PAD_CTRL0_HDP, &hdmi->pad_ctrl0);
110 while (timer_get_us() < tmo) {
111 if (readl(&hdmi->hpd) & SUNXI_HDMI_HPD_DETECT)
118 static void sunxi_hdmi_shutdown(void)
120 struct sunxi_ccm_reg * const ccm =
121 (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
122 struct sunxi_hdmi_reg * const hdmi =
123 (struct sunxi_hdmi_reg *)SUNXI_HDMI_BASE;
125 clrbits_le32(&hdmi->ctrl, SUNXI_HDMI_CTRL_ENABLE);
126 clrbits_le32(&ccm->hdmi_clk_cfg, CCM_HDMI_CTRL_GATE);
127 clrbits_le32(&ccm->ahb_gate1, 1 << AHB_GATE_OFFSET_HDMI);
128 #ifdef CONFIG_SUNXI_GEN_SUN6I
129 clrbits_le32(&ccm->ahb_reset1_cfg, 1 << AHB_RESET_OFFSET_HDMI);
134 static int sunxi_hdmi_ddc_do_command(u32 cmnd, int offset, int n)
136 struct sunxi_hdmi_reg * const hdmi =
137 (struct sunxi_hdmi_reg *)SUNXI_HDMI_BASE;
139 setbits_le32(&hdmi->ddc_fifo_ctrl, SUNXI_HDMI_DDC_FIFO_CTRL_CLEAR);
140 writel(SUNXI_HMDI_DDC_ADDR_EDDC_SEGMENT(offset >> 8) |
141 SUNXI_HMDI_DDC_ADDR_EDDC_ADDR |
142 SUNXI_HMDI_DDC_ADDR_OFFSET(offset) |
143 SUNXI_HMDI_DDC_ADDR_SLAVE_ADDR, &hdmi->ddc_addr);
144 #ifndef CONFIG_MACH_SUN6I
145 writel(n, &hdmi->ddc_byte_count);
146 writel(cmnd, &hdmi->ddc_cmnd);
148 writel(n << 16 | cmnd, &hdmi->ddc_cmnd);
150 setbits_le32(&hdmi->ddc_ctrl, SUNXI_HMDI_DDC_CTRL_START);
152 return await_completion(&hdmi->ddc_ctrl, SUNXI_HMDI_DDC_CTRL_START, 0);
155 static int sunxi_hdmi_ddc_read(int offset, u8 *buf, int count)
157 struct sunxi_hdmi_reg * const hdmi =
158 (struct sunxi_hdmi_reg *)SUNXI_HDMI_BASE;
167 if (sunxi_hdmi_ddc_do_command(
168 SUNXI_HDMI_DDC_CMND_EXPLICIT_EDDC_READ,
172 for (i = 0; i < n; i++)
173 *buf++ = readb(&hdmi->ddc_fifo_data);
182 static int sunxi_hdmi_edid_get_block(int block, u8 *buf)
187 r = sunxi_hdmi_ddc_read(block * 128, buf, 128);
190 r = edid_check_checksum(buf);
192 printf("EDID block %d: checksum error%s\n",
193 block, retries ? ", retrying" : "");
195 } while (r && retries--);
200 static int sunxi_hdmi_edid_get_mode(struct ctfb_res_modes *mode)
202 struct edid1_info edid1;
203 struct edid_cea861_info cea681[4];
204 struct edid_detailed_timing *t =
205 (struct edid_detailed_timing *)edid1.monitor_details.timing;
206 struct sunxi_hdmi_reg * const hdmi =
207 (struct sunxi_hdmi_reg *)SUNXI_HDMI_BASE;
208 struct sunxi_ccm_reg * const ccm =
209 (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
210 int i, r, ext_blocks = 0;
212 /* SUNXI_HDMI_CTRL_ENABLE & PAD_CTRL0 are already set by hpd_detect */
213 writel(SUNXI_HDMI_PAD_CTRL1 | SUNXI_HDMI_PAD_CTRL1_HALVE,
215 writel(SUNXI_HDMI_PLL_CTRL | SUNXI_HDMI_PLL_CTRL_DIV(15),
217 writel(SUNXI_HDMI_PLL_DBG0_PLL3, &hdmi->pll_dbg0);
219 /* Reset i2c controller */
220 setbits_le32(&ccm->hdmi_clk_cfg, CCM_HDMI_CTRL_DDC_GATE);
221 writel(SUNXI_HMDI_DDC_CTRL_ENABLE |
222 SUNXI_HMDI_DDC_CTRL_SDA_ENABLE |
223 SUNXI_HMDI_DDC_CTRL_SCL_ENABLE |
224 SUNXI_HMDI_DDC_CTRL_RESET, &hdmi->ddc_ctrl);
225 if (await_completion(&hdmi->ddc_ctrl, SUNXI_HMDI_DDC_CTRL_RESET, 0))
228 writel(SUNXI_HDMI_DDC_CLOCK, &hdmi->ddc_clock);
229 #ifndef CONFIG_MACH_SUN6I
230 writel(SUNXI_HMDI_DDC_LINE_CTRL_SDA_ENABLE |
231 SUNXI_HMDI_DDC_LINE_CTRL_SCL_ENABLE, &hdmi->ddc_line_ctrl);
234 r = sunxi_hdmi_edid_get_block(0, (u8 *)&edid1);
236 r = edid_check_info(&edid1);
238 printf("EDID: invalid EDID data\n");
243 ext_blocks = edid1.extension_flag;
246 for (i = 0; i < ext_blocks; i++) {
247 if (sunxi_hdmi_edid_get_block(1 + i,
248 (u8 *)&cea681[i]) != 0) {
255 /* Disable DDC engine, no longer needed */
256 clrbits_le32(&hdmi->ddc_ctrl, SUNXI_HMDI_DDC_CTRL_ENABLE);
257 clrbits_le32(&ccm->hdmi_clk_cfg, CCM_HDMI_CTRL_DDC_GATE);
262 /* We want version 1.3 or 1.2 with detailed timing info */
263 if (edid1.version != 1 || (edid1.revision < 3 &&
264 !EDID1_INFO_FEATURE_PREFERRED_TIMING_MODE(edid1))) {
265 printf("EDID: unsupported version %d.%d\n",
266 edid1.version, edid1.revision);
270 /* Take the first usable detailed timing */
271 for (i = 0; i < 4; i++, t++) {
272 r = video_edid_dtd_to_ctfb_res_modes(t, mode);
277 printf("EDID: no usable detailed timing found\n");
281 /* Check for basic audio support, if found enable hdmi output */
282 sunxi_display.monitor = sunxi_monitor_dvi;
283 for (i = 0; i < ext_blocks; i++) {
284 if (cea681[i].extension_tag != EDID_CEA861_EXTENSION_TAG ||
285 cea681[i].revision < 2)
288 if (EDID_CEA861_SUPPORTS_BASIC_AUDIO(cea681[i]))
289 sunxi_display.monitor = sunxi_monitor_hdmi;
295 #endif /* CONFIG_VIDEO_HDMI */
297 #ifdef CONFIG_MACH_SUN4I
299 * Testing has shown that on sun4i the display backend engine does not have
300 * deep enough fifo-s causing flickering / tearing in full-hd mode due to
301 * fifo underruns. So on sun4i we use the display frontend engine to do the
302 * dma from memory, as the frontend does have deep enough fifo-s.
305 static const u32 sun4i_vert_coef[32] = {
306 0x00004000, 0x000140ff, 0x00033ffe, 0x00043ffd,
307 0x00063efc, 0xff083dfc, 0x000a3bfb, 0xff0d39fb,
308 0xff0f37fb, 0xff1136fa, 0xfe1433fb, 0xfe1631fb,
309 0xfd192ffb, 0xfd1c2cfb, 0xfd1f29fb, 0xfc2127fc,
310 0xfc2424fc, 0xfc2721fc, 0xfb291ffd, 0xfb2c1cfd,
311 0xfb2f19fd, 0xfb3116fe, 0xfb3314fe, 0xfa3611ff,
312 0xfb370fff, 0xfb390dff, 0xfb3b0a00, 0xfc3d08ff,
313 0xfc3e0600, 0xfd3f0400, 0xfe3f0300, 0xff400100,
316 static const u32 sun4i_horz_coef[64] = {
317 0x40000000, 0x00000000, 0x40fe0000, 0x0000ff03,
318 0x3ffd0000, 0x0000ff05, 0x3ffc0000, 0x0000ff06,
319 0x3efb0000, 0x0000ff08, 0x3dfb0000, 0x0000ff09,
320 0x3bfa0000, 0x0000fe0d, 0x39fa0000, 0x0000fe0f,
321 0x38fa0000, 0x0000fe10, 0x36fa0000, 0x0000fe12,
322 0x33fa0000, 0x0000fd16, 0x31fa0000, 0x0000fd18,
323 0x2ffa0000, 0x0000fd1a, 0x2cfa0000, 0x0000fc1e,
324 0x29fa0000, 0x0000fc21, 0x27fb0000, 0x0000fb23,
325 0x24fb0000, 0x0000fb26, 0x21fb0000, 0x0000fb29,
326 0x1ffc0000, 0x0000fa2b, 0x1cfc0000, 0x0000fa2e,
327 0x19fd0000, 0x0000fa30, 0x16fd0000, 0x0000fa33,
328 0x14fd0000, 0x0000fa35, 0x11fe0000, 0x0000fa37,
329 0x0ffe0000, 0x0000fa39, 0x0dfe0000, 0x0000fa3b,
330 0x0afe0000, 0x0000fa3e, 0x08ff0000, 0x0000fb3e,
331 0x06ff0000, 0x0000fb40, 0x05ff0000, 0x0000fc40,
332 0x03ff0000, 0x0000fd41, 0x01ff0000, 0x0000fe42,
335 static void sunxi_frontend_init(void)
337 struct sunxi_ccm_reg * const ccm =
338 (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
339 struct sunxi_de_fe_reg * const de_fe =
340 (struct sunxi_de_fe_reg *)SUNXI_DE_FE0_BASE;
344 setbits_le32(&ccm->ahb_gate1, 1 << AHB_GATE_OFFSET_DE_FE0);
345 setbits_le32(&ccm->dram_clk_gate, 1 << CCM_DRAM_GATE_OFFSET_DE_FE0);
346 clock_set_de_mod_clock(&ccm->fe0_clk_cfg, 300000000);
348 setbits_le32(&de_fe->enable, SUNXI_DE_FE_ENABLE_EN);
350 for (i = 0; i < 32; i++) {
351 writel(sun4i_horz_coef[2 * i], &de_fe->ch0_horzcoef0[i]);
352 writel(sun4i_horz_coef[2 * i + 1], &de_fe->ch0_horzcoef1[i]);
353 writel(sun4i_vert_coef[i], &de_fe->ch0_vertcoef[i]);
354 writel(sun4i_horz_coef[2 * i], &de_fe->ch1_horzcoef0[i]);
355 writel(sun4i_horz_coef[2 * i + 1], &de_fe->ch1_horzcoef1[i]);
356 writel(sun4i_vert_coef[i], &de_fe->ch1_vertcoef[i]);
359 setbits_le32(&de_fe->frame_ctrl, SUNXI_DE_FE_FRAME_CTRL_COEF_RDY);
362 static void sunxi_frontend_mode_set(const struct ctfb_res_modes *mode,
363 unsigned int address)
365 struct sunxi_de_fe_reg * const de_fe =
366 (struct sunxi_de_fe_reg *)SUNXI_DE_FE0_BASE;
368 setbits_le32(&de_fe->bypass, SUNXI_DE_FE_BYPASS_CSC_BYPASS);
369 writel(CONFIG_SYS_SDRAM_BASE + address, &de_fe->ch0_addr);
370 writel(mode->xres * 4, &de_fe->ch0_stride);
371 writel(SUNXI_DE_FE_INPUT_FMT_ARGB8888, &de_fe->input_fmt);
372 writel(SUNXI_DE_FE_OUTPUT_FMT_ARGB8888, &de_fe->output_fmt);
374 writel(SUNXI_DE_FE_HEIGHT(mode->yres) | SUNXI_DE_FE_WIDTH(mode->xres),
376 writel(SUNXI_DE_FE_HEIGHT(mode->yres) | SUNXI_DE_FE_WIDTH(mode->xres),
377 &de_fe->ch0_outsize);
378 writel(SUNXI_DE_FE_FACTOR_INT(1), &de_fe->ch0_horzfact);
379 writel(SUNXI_DE_FE_FACTOR_INT(1), &de_fe->ch0_vertfact);
381 writel(SUNXI_DE_FE_HEIGHT(mode->yres) | SUNXI_DE_FE_WIDTH(mode->xres),
383 writel(SUNXI_DE_FE_HEIGHT(mode->yres) | SUNXI_DE_FE_WIDTH(mode->xres),
384 &de_fe->ch1_outsize);
385 writel(SUNXI_DE_FE_FACTOR_INT(1), &de_fe->ch1_horzfact);
386 writel(SUNXI_DE_FE_FACTOR_INT(1), &de_fe->ch1_vertfact);
388 setbits_le32(&de_fe->frame_ctrl, SUNXI_DE_FE_FRAME_CTRL_REG_RDY);
391 static void sunxi_frontend_enable(void)
393 struct sunxi_de_fe_reg * const de_fe =
394 (struct sunxi_de_fe_reg *)SUNXI_DE_FE0_BASE;
396 setbits_le32(&de_fe->frame_ctrl, SUNXI_DE_FE_FRAME_CTRL_FRM_START);
399 static void sunxi_frontend_init(void) {}
400 static void sunxi_frontend_mode_set(const struct ctfb_res_modes *mode,
401 unsigned int address) {}
402 static void sunxi_frontend_enable(void) {}
405 static bool sunxi_is_composite(void)
407 switch (sunxi_display.monitor) {
408 case sunxi_monitor_none:
409 case sunxi_monitor_dvi:
410 case sunxi_monitor_hdmi:
411 case sunxi_monitor_lcd:
412 case sunxi_monitor_vga:
414 case sunxi_monitor_composite_pal:
415 case sunxi_monitor_composite_ntsc:
416 case sunxi_monitor_composite_pal_m:
417 case sunxi_monitor_composite_pal_nc:
421 return false; /* Never reached */
425 * This is the entity that mixes and matches the different layers and inputs.
426 * Allwinner calls it the back-end, but i like composer better.
428 static void sunxi_composer_init(void)
430 struct sunxi_ccm_reg * const ccm =
431 (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
432 struct sunxi_de_be_reg * const de_be =
433 (struct sunxi_de_be_reg *)SUNXI_DE_BE0_BASE;
436 sunxi_frontend_init();
438 #ifdef CONFIG_SUNXI_GEN_SUN6I
440 setbits_le32(&ccm->ahb_reset1_cfg, 1 << AHB_RESET_OFFSET_DE_BE0);
444 setbits_le32(&ccm->ahb_gate1, 1 << AHB_GATE_OFFSET_DE_BE0);
445 #ifndef CONFIG_MACH_SUN4I /* On sun4i the frontend does the dma */
446 setbits_le32(&ccm->dram_clk_gate, 1 << CCM_DRAM_GATE_OFFSET_DE_BE0);
448 clock_set_de_mod_clock(&ccm->be0_clk_cfg, 300000000);
450 /* Engine bug, clear registers after reset */
451 for (i = 0x0800; i < 0x1000; i += 4)
452 writel(0, SUNXI_DE_BE0_BASE + i);
454 setbits_le32(&de_be->mode, SUNXI_DE_BE_MODE_ENABLE);
457 static u32 sunxi_rgb2yuv_coef[12] = {
458 0x00000107, 0x00000204, 0x00000064, 0x00000108,
459 0x00003f69, 0x00003ed6, 0x000001c1, 0x00000808,
460 0x000001c1, 0x00003e88, 0x00003fb8, 0x00000808
463 static void sunxi_composer_mode_set(const struct ctfb_res_modes *mode,
464 unsigned int address)
466 struct sunxi_de_be_reg * const de_be =
467 (struct sunxi_de_be_reg *)SUNXI_DE_BE0_BASE;
470 sunxi_frontend_mode_set(mode, address);
472 writel(SUNXI_DE_BE_HEIGHT(mode->yres) | SUNXI_DE_BE_WIDTH(mode->xres),
474 writel(SUNXI_DE_BE_HEIGHT(mode->yres) | SUNXI_DE_BE_WIDTH(mode->xres),
475 &de_be->layer0_size);
476 #ifndef CONFIG_MACH_SUN4I /* On sun4i the frontend does the dma */
477 writel(SUNXI_DE_BE_LAYER_STRIDE(mode->xres), &de_be->layer0_stride);
478 writel(address << 3, &de_be->layer0_addr_low32b);
479 writel(address >> 29, &de_be->layer0_addr_high4b);
481 writel(SUNXI_DE_BE_LAYER_ATTR0_SRC_FE0, &de_be->layer0_attr0_ctrl);
483 writel(SUNXI_DE_BE_LAYER_ATTR1_FMT_XRGB8888, &de_be->layer0_attr1_ctrl);
485 setbits_le32(&de_be->mode, SUNXI_DE_BE_MODE_LAYER0_ENABLE);
486 if (mode->vmode == FB_VMODE_INTERLACED)
487 setbits_le32(&de_be->mode,
488 #ifndef CONFIG_MACH_SUN5I
489 SUNXI_DE_BE_MODE_DEFLICKER_ENABLE |
491 SUNXI_DE_BE_MODE_INTERLACE_ENABLE);
493 if (sunxi_is_composite()) {
494 writel(SUNXI_DE_BE_OUTPUT_COLOR_CTRL_ENABLE,
495 &de_be->output_color_ctrl);
496 for (i = 0; i < 12; i++)
497 writel(sunxi_rgb2yuv_coef[i],
498 &de_be->output_color_coef[i]);
502 static void sunxi_composer_enable(void)
504 struct sunxi_de_be_reg * const de_be =
505 (struct sunxi_de_be_reg *)SUNXI_DE_BE0_BASE;
507 sunxi_frontend_enable();
509 setbits_le32(&de_be->reg_ctrl, SUNXI_DE_BE_REG_CTRL_LOAD_REGS);
510 setbits_le32(&de_be->mode, SUNXI_DE_BE_MODE_START);
514 * LCDC, what allwinner calls a CRTC, so timing controller and serializer.
516 static void sunxi_lcdc_pll_set(int tcon, int dotclock,
517 int *clk_div, int *clk_double)
519 struct sunxi_ccm_reg * const ccm =
520 (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
521 int value, n, m, min_m, max_m, diff;
522 int best_n = 0, best_m = 0, best_diff = 0x0FFFFFFF;
524 bool use_mipi_pll = false;
527 #ifdef CONFIG_VIDEO_LCD_IF_PARALLEL
531 #ifdef CONFIG_VIDEO_LCD_IF_LVDS
540 * Find the lowest divider resulting in a matching clock, if there
541 * is no match, pick the closest lower clock, as monitors tend to
542 * not sync to higher frequencies.
544 for (m = min_m; m <= max_m; m++) {
545 n = (m * dotclock) / 3000;
547 if ((n >= 9) && (n <= 127)) {
548 value = (3000 * n) / m;
549 diff = dotclock - value;
550 if (diff < best_diff) {
558 /* These are just duplicates */
562 n = (m * dotclock) / 6000;
563 if ((n >= 9) && (n <= 127)) {
564 value = (6000 * n) / m;
565 diff = dotclock - value;
566 if (diff < best_diff) {
575 #ifdef CONFIG_MACH_SUN6I
577 * Use the MIPI pll if we've been unable to find any matching setting
578 * for PLL3, this happens with high dotclocks because of min_m = 6.
580 if (tcon == 0 && best_n == 0) {
582 best_m = 6; /* Minimum m for tcon0 */
586 clock_set_pll3(297000000); /* Fix the video pll at 297 MHz */
587 clock_set_mipi_pll(best_m * dotclock * 1000);
588 debug("dotclock: %dkHz = %dkHz via mipi pll\n",
589 dotclock, clock_get_mipi_pll() / best_m / 1000);
593 clock_set_pll3(best_n * 3000000);
594 debug("dotclock: %dkHz = %dkHz: (%d * 3MHz * %d) / %d\n",
596 (best_double + 1) * clock_get_pll3() / best_m / 1000,
597 best_double + 1, best_n, best_m);
604 pll = CCM_LCD_CH0_CTRL_MIPI_PLL;
605 else if (best_double)
606 pll = CCM_LCD_CH0_CTRL_PLL3_2X;
608 pll = CCM_LCD_CH0_CTRL_PLL3;
610 writel(CCM_LCD_CH0_CTRL_GATE | CCM_LCD_CH0_CTRL_RST | pll,
611 &ccm->lcd0_ch0_clk_cfg);
613 writel(CCM_LCD_CH1_CTRL_GATE |
614 (best_double ? CCM_LCD_CH1_CTRL_PLL3_2X :
615 CCM_LCD_CH1_CTRL_PLL3) |
616 CCM_LCD_CH1_CTRL_M(best_m), &ccm->lcd0_ch1_clk_cfg);
617 if (sunxi_is_composite())
618 setbits_le32(&ccm->lcd0_ch1_clk_cfg,
619 CCM_LCD_CH1_CTRL_HALF_SCLK1);
623 *clk_double = best_double;
626 static void sunxi_lcdc_init(void)
628 struct sunxi_ccm_reg * const ccm =
629 (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
630 struct sunxi_lcdc_reg * const lcdc =
631 (struct sunxi_lcdc_reg *)SUNXI_LCD0_BASE;
634 #ifdef CONFIG_SUNXI_GEN_SUN6I
635 setbits_le32(&ccm->ahb_reset1_cfg, 1 << AHB_RESET_OFFSET_LCD0);
637 setbits_le32(&ccm->lcd0_ch0_clk_cfg, CCM_LCD_CH0_CTRL_RST);
641 setbits_le32(&ccm->ahb_gate1, 1 << AHB_GATE_OFFSET_LCD0);
642 #ifdef CONFIG_VIDEO_LCD_IF_LVDS
643 #ifdef CONFIG_SUNXI_GEN_SUN6I
644 setbits_le32(&ccm->ahb_reset2_cfg, 1 << AHB_RESET_OFFSET_LVDS);
646 setbits_le32(&ccm->lvds_clk_cfg, CCM_LVDS_CTRL_RST);
651 writel(0, &lcdc->ctrl); /* Disable tcon */
652 writel(0, &lcdc->int0); /* Disable all interrupts */
654 /* Disable tcon0 dot clock */
655 clrbits_le32(&lcdc->tcon0_dclk, SUNXI_LCDC_TCON0_DCLK_ENABLE);
657 /* Set all io lines to tristate */
658 writel(0xffffffff, &lcdc->tcon0_io_tristate);
659 writel(0xffffffff, &lcdc->tcon1_io_tristate);
662 static void sunxi_lcdc_enable(void)
664 struct sunxi_lcdc_reg * const lcdc =
665 (struct sunxi_lcdc_reg *)SUNXI_LCD0_BASE;
667 setbits_le32(&lcdc->ctrl, SUNXI_LCDC_CTRL_TCON_ENABLE);
668 #ifdef CONFIG_VIDEO_LCD_IF_LVDS
669 setbits_le32(&lcdc->tcon0_lvds_intf, SUNXI_LCDC_TCON0_LVDS_INTF_ENABLE);
670 setbits_le32(&lcdc->lvds_ana0, SUNXI_LCDC_LVDS_ANA0);
671 #ifdef CONFIG_SUNXI_GEN_SUN6I
672 udelay(2); /* delay at least 1200 ns */
673 setbits_le32(&lcdc->lvds_ana0, SUNXI_LCDC_LVDS_ANA0_EN_MB);
674 udelay(2); /* delay at least 1200 ns */
675 setbits_le32(&lcdc->lvds_ana0, SUNXI_LCDC_LVDS_ANA0_DRVC);
676 if (sunxi_display.depth == 18)
677 setbits_le32(&lcdc->lvds_ana0, SUNXI_LCDC_LVDS_ANA0_DRVD(0x7));
679 setbits_le32(&lcdc->lvds_ana0, SUNXI_LCDC_LVDS_ANA0_DRVD(0xf));
681 setbits_le32(&lcdc->lvds_ana0, SUNXI_LCDC_LVDS_ANA0_UPDATE);
682 udelay(2); /* delay at least 1200 ns */
683 setbits_le32(&lcdc->lvds_ana1, SUNXI_LCDC_LVDS_ANA1_INIT1);
684 udelay(1); /* delay at least 120 ns */
685 setbits_le32(&lcdc->lvds_ana1, SUNXI_LCDC_LVDS_ANA1_INIT2);
686 setbits_le32(&lcdc->lvds_ana0, SUNXI_LCDC_LVDS_ANA0_UPDATE);
691 static void sunxi_lcdc_panel_enable(void)
696 * Start with backlight disabled to avoid the screen flashing to
697 * white while the lcd inits.
699 pin = sunxi_name_to_gpio(CONFIG_VIDEO_LCD_BL_EN);
701 gpio_request(pin, "lcd_backlight_enable");
702 gpio_direction_output(pin, 0);
705 pin = sunxi_name_to_gpio(CONFIG_VIDEO_LCD_BL_PWM);
707 gpio_request(pin, "lcd_backlight_pwm");
708 gpio_direction_output(pin, PWM_OFF);
711 reset_pin = sunxi_name_to_gpio(CONFIG_VIDEO_LCD_RESET);
712 if (reset_pin >= 0) {
713 gpio_request(reset_pin, "lcd_reset");
714 gpio_direction_output(reset_pin, 0); /* Assert reset */
717 /* Give the backlight some time to turn off and power up the panel. */
719 pin = sunxi_name_to_gpio(CONFIG_VIDEO_LCD_POWER);
721 gpio_request(pin, "lcd_power");
722 gpio_direction_output(pin, 1);
726 gpio_direction_output(reset_pin, 1); /* De-assert reset */
729 static void sunxi_lcdc_backlight_enable(void)
734 * We want to have scanned out at least one frame before enabling the
735 * backlight to avoid the screen flashing to white when we enable it.
739 pin = sunxi_name_to_gpio(CONFIG_VIDEO_LCD_BL_EN);
741 gpio_direction_output(pin, 1);
743 pin = sunxi_name_to_gpio(CONFIG_VIDEO_LCD_BL_PWM);
745 gpio_direction_output(pin, PWM_ON);
748 static int sunxi_lcdc_get_clk_delay(const struct ctfb_res_modes *mode, int tcon)
752 delay = mode->lower_margin + mode->vsync_len + mode->upper_margin;
753 if (mode->vmode == FB_VMODE_INTERLACED)
758 return (delay > 30) ? 30 : delay;
761 static void sunxi_lcdc_tcon0_mode_set(const struct ctfb_res_modes *mode,
762 bool for_ext_vga_dac)
764 struct sunxi_lcdc_reg * const lcdc =
765 (struct sunxi_lcdc_reg *)SUNXI_LCD0_BASE;
766 int bp, clk_delay, clk_div, clk_double, pin, total, val;
768 for (pin = SUNXI_GPD(0); pin <= SUNXI_GPD(27); pin++)
769 #ifdef CONFIG_VIDEO_LCD_IF_PARALLEL
770 sunxi_gpio_set_cfgpin(pin, SUNXI_GPD_LCD0);
772 #ifdef CONFIG_VIDEO_LCD_IF_LVDS
773 sunxi_gpio_set_cfgpin(pin, SUNXI_GPD_LVDS0);
776 sunxi_lcdc_pll_set(0, mode->pixclock_khz, &clk_div, &clk_double);
779 clrsetbits_le32(&lcdc->ctrl, SUNXI_LCDC_CTRL_IO_MAP_MASK,
780 SUNXI_LCDC_CTRL_IO_MAP_TCON0);
782 clk_delay = sunxi_lcdc_get_clk_delay(mode, 0);
783 writel(SUNXI_LCDC_TCON0_CTRL_ENABLE |
784 SUNXI_LCDC_TCON0_CTRL_CLK_DELAY(clk_delay), &lcdc->tcon0_ctrl);
786 writel(SUNXI_LCDC_TCON0_DCLK_ENABLE |
787 SUNXI_LCDC_TCON0_DCLK_DIV(clk_div), &lcdc->tcon0_dclk);
789 writel(SUNXI_LCDC_X(mode->xres) | SUNXI_LCDC_Y(mode->yres),
790 &lcdc->tcon0_timing_active);
792 bp = mode->hsync_len + mode->left_margin;
793 total = mode->xres + mode->right_margin + bp;
794 writel(SUNXI_LCDC_TCON0_TIMING_H_TOTAL(total) |
795 SUNXI_LCDC_TCON0_TIMING_H_BP(bp), &lcdc->tcon0_timing_h);
797 bp = mode->vsync_len + mode->upper_margin;
798 total = mode->yres + mode->lower_margin + bp;
799 writel(SUNXI_LCDC_TCON0_TIMING_V_TOTAL(total) |
800 SUNXI_LCDC_TCON0_TIMING_V_BP(bp), &lcdc->tcon0_timing_v);
802 #ifdef CONFIG_VIDEO_LCD_IF_PARALLEL
803 writel(SUNXI_LCDC_X(mode->hsync_len) | SUNXI_LCDC_Y(mode->vsync_len),
804 &lcdc->tcon0_timing_sync);
806 writel(0, &lcdc->tcon0_hv_intf);
807 writel(0, &lcdc->tcon0_cpu_intf);
809 #ifdef CONFIG_VIDEO_LCD_IF_LVDS
810 val = (sunxi_display.depth == 18) ? 1 : 0;
811 writel(SUNXI_LCDC_TCON0_LVDS_INTF_BITWIDTH(val) |
812 SUNXI_LCDC_TCON0_LVDS_CLK_SEL_TCON0, &lcdc->tcon0_lvds_intf);
815 if (sunxi_display.depth == 18 || sunxi_display.depth == 16) {
816 writel(SUNXI_LCDC_TCON0_FRM_SEED, &lcdc->tcon0_frm_seed[0]);
817 writel(SUNXI_LCDC_TCON0_FRM_SEED, &lcdc->tcon0_frm_seed[1]);
818 writel(SUNXI_LCDC_TCON0_FRM_SEED, &lcdc->tcon0_frm_seed[2]);
819 writel(SUNXI_LCDC_TCON0_FRM_SEED, &lcdc->tcon0_frm_seed[3]);
820 writel(SUNXI_LCDC_TCON0_FRM_SEED, &lcdc->tcon0_frm_seed[4]);
821 writel(SUNXI_LCDC_TCON0_FRM_SEED, &lcdc->tcon0_frm_seed[5]);
822 writel(SUNXI_LCDC_TCON0_FRM_TAB0, &lcdc->tcon0_frm_table[0]);
823 writel(SUNXI_LCDC_TCON0_FRM_TAB1, &lcdc->tcon0_frm_table[1]);
824 writel(SUNXI_LCDC_TCON0_FRM_TAB2, &lcdc->tcon0_frm_table[2]);
825 writel(SUNXI_LCDC_TCON0_FRM_TAB3, &lcdc->tcon0_frm_table[3]);
826 writel(((sunxi_display.depth == 18) ?
827 SUNXI_LCDC_TCON0_FRM_CTRL_RGB666 :
828 SUNXI_LCDC_TCON0_FRM_CTRL_RGB565),
829 &lcdc->tcon0_frm_ctrl);
832 val = SUNXI_LCDC_TCON0_IO_POL_DCLK_PHASE(CONFIG_VIDEO_LCD_DCLK_PHASE);
833 if (!(mode->sync & FB_SYNC_HOR_HIGH_ACT))
834 val |= SUNXI_LCDC_TCON_HSYNC_MASK;
835 if (!(mode->sync & FB_SYNC_VERT_HIGH_ACT))
836 val |= SUNXI_LCDC_TCON_VSYNC_MASK;
838 #ifdef CONFIG_VIDEO_VGA_VIA_LCD_FORCE_SYNC_ACTIVE_HIGH
842 writel(val, &lcdc->tcon0_io_polarity);
844 writel(0, &lcdc->tcon0_io_tristate);
847 #if defined CONFIG_VIDEO_HDMI || defined CONFIG_VIDEO_VGA || defined CONFIG_VIDEO_COMPOSITE
848 static void sunxi_lcdc_tcon1_mode_set(const struct ctfb_res_modes *mode,
849 int *clk_div, int *clk_double,
850 bool use_portd_hvsync)
852 struct sunxi_lcdc_reg * const lcdc =
853 (struct sunxi_lcdc_reg *)SUNXI_LCD0_BASE;
854 int bp, clk_delay, total, val, yres;
857 clrsetbits_le32(&lcdc->ctrl, SUNXI_LCDC_CTRL_IO_MAP_MASK,
858 SUNXI_LCDC_CTRL_IO_MAP_TCON1);
860 clk_delay = sunxi_lcdc_get_clk_delay(mode, 1);
861 writel(SUNXI_LCDC_TCON1_CTRL_ENABLE |
862 ((mode->vmode == FB_VMODE_INTERLACED) ?
863 SUNXI_LCDC_TCON1_CTRL_INTERLACE_ENABLE : 0) |
864 SUNXI_LCDC_TCON1_CTRL_CLK_DELAY(clk_delay), &lcdc->tcon1_ctrl);
867 if (mode->vmode == FB_VMODE_INTERLACED)
869 writel(SUNXI_LCDC_X(mode->xres) | SUNXI_LCDC_Y(yres),
870 &lcdc->tcon1_timing_source);
871 writel(SUNXI_LCDC_X(mode->xres) | SUNXI_LCDC_Y(yres),
872 &lcdc->tcon1_timing_scale);
873 writel(SUNXI_LCDC_X(mode->xres) | SUNXI_LCDC_Y(yres),
874 &lcdc->tcon1_timing_out);
876 bp = mode->hsync_len + mode->left_margin;
877 total = mode->xres + mode->right_margin + bp;
878 writel(SUNXI_LCDC_TCON1_TIMING_H_TOTAL(total) |
879 SUNXI_LCDC_TCON1_TIMING_H_BP(bp), &lcdc->tcon1_timing_h);
881 bp = mode->vsync_len + mode->upper_margin;
882 total = mode->yres + mode->lower_margin + bp;
883 if (mode->vmode == FB_VMODE_NONINTERLACED)
885 writel(SUNXI_LCDC_TCON1_TIMING_V_TOTAL(total) |
886 SUNXI_LCDC_TCON1_TIMING_V_BP(bp), &lcdc->tcon1_timing_v);
888 writel(SUNXI_LCDC_X(mode->hsync_len) | SUNXI_LCDC_Y(mode->vsync_len),
889 &lcdc->tcon1_timing_sync);
891 if (use_portd_hvsync) {
892 sunxi_gpio_set_cfgpin(SUNXI_GPD(26), SUNXI_GPD_LCD0);
893 sunxi_gpio_set_cfgpin(SUNXI_GPD(27), SUNXI_GPD_LCD0);
896 if (mode->sync & FB_SYNC_HOR_HIGH_ACT)
897 val |= SUNXI_LCDC_TCON_HSYNC_MASK;
898 if (mode->sync & FB_SYNC_VERT_HIGH_ACT)
899 val |= SUNXI_LCDC_TCON_VSYNC_MASK;
900 writel(val, &lcdc->tcon1_io_polarity);
902 clrbits_le32(&lcdc->tcon1_io_tristate,
903 SUNXI_LCDC_TCON_VSYNC_MASK |
904 SUNXI_LCDC_TCON_HSYNC_MASK);
907 #ifdef CONFIG_MACH_SUN5I
908 if (sunxi_is_composite())
909 clrsetbits_le32(&lcdc->mux_ctrl, SUNXI_LCDC_MUX_CTRL_SRC0_MASK,
910 SUNXI_LCDC_MUX_CTRL_SRC0(1));
913 sunxi_lcdc_pll_set(1, mode->pixclock_khz, clk_div, clk_double);
915 #endif /* CONFIG_VIDEO_HDMI || defined CONFIG_VIDEO_VGA || CONFIG_VIDEO_COMPOSITE */
917 #ifdef CONFIG_VIDEO_HDMI
919 static void sunxi_hdmi_setup_info_frames(const struct ctfb_res_modes *mode)
921 struct sunxi_hdmi_reg * const hdmi =
922 (struct sunxi_hdmi_reg *)SUNXI_HDMI_BASE;
924 u8 avi_info_frame[17] = {
925 0x82, 0x02, 0x0d, 0x00, 0x12, 0x00, 0x88, 0x00,
926 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
929 u8 vendor_info_frame[19] = {
930 0x81, 0x01, 0x06, 0x29, 0x03, 0x0c, 0x00, 0x40,
931 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
936 if (mode->pixclock_khz <= 27000)
937 avi_info_frame[5] = 0x40; /* SD-modes, ITU601 colorspace */
939 avi_info_frame[5] = 0x80; /* HD-modes, ITU709 colorspace */
941 if (mode->xres * 100 / mode->yres < 156)
942 avi_info_frame[5] |= 0x18; /* 4 : 3 */
944 avi_info_frame[5] |= 0x28; /* 16 : 9 */
946 for (i = 0; i < ARRAY_SIZE(avi_info_frame); i++)
947 checksum += avi_info_frame[i];
949 avi_info_frame[3] = 0x100 - checksum;
951 for (i = 0; i < ARRAY_SIZE(avi_info_frame); i++)
952 writeb(avi_info_frame[i], &hdmi->avi_info_frame[i]);
954 writel(SUNXI_HDMI_QCP_PACKET0, &hdmi->qcp_packet0);
955 writel(SUNXI_HDMI_QCP_PACKET1, &hdmi->qcp_packet1);
957 for (i = 0; i < ARRAY_SIZE(vendor_info_frame); i++)
958 writeb(vendor_info_frame[i], &hdmi->vendor_info_frame[i]);
960 writel(SUNXI_HDMI_PKT_CTRL0, &hdmi->pkt_ctrl0);
961 writel(SUNXI_HDMI_PKT_CTRL1, &hdmi->pkt_ctrl1);
963 setbits_le32(&hdmi->video_ctrl, SUNXI_HDMI_VIDEO_CTRL_HDMI);
966 static void sunxi_hdmi_mode_set(const struct ctfb_res_modes *mode,
967 int clk_div, int clk_double)
969 struct sunxi_hdmi_reg * const hdmi =
970 (struct sunxi_hdmi_reg *)SUNXI_HDMI_BASE;
973 /* Write clear interrupt status bits */
974 writel(SUNXI_HDMI_IRQ_STATUS_BITS, &hdmi->irq);
976 if (sunxi_display.monitor == sunxi_monitor_hdmi)
977 sunxi_hdmi_setup_info_frames(mode);
979 /* Set input sync enable */
980 writel(SUNXI_HDMI_UNKNOWN_INPUT_SYNC, &hdmi->unknown);
982 /* Init various registers, select pll3 as clock source */
983 writel(SUNXI_HDMI_VIDEO_POL_TX_CLK, &hdmi->video_polarity);
984 writel(SUNXI_HDMI_PAD_CTRL0_RUN, &hdmi->pad_ctrl0);
985 writel(SUNXI_HDMI_PAD_CTRL1, &hdmi->pad_ctrl1);
986 writel(SUNXI_HDMI_PLL_CTRL, &hdmi->pll_ctrl);
987 writel(SUNXI_HDMI_PLL_DBG0_PLL3, &hdmi->pll_dbg0);
989 /* Setup clk div and doubler */
990 clrsetbits_le32(&hdmi->pll_ctrl, SUNXI_HDMI_PLL_CTRL_DIV_MASK,
991 SUNXI_HDMI_PLL_CTRL_DIV(clk_div));
993 setbits_le32(&hdmi->pad_ctrl1, SUNXI_HDMI_PAD_CTRL1_HALVE);
995 /* Setup timing registers */
996 writel(SUNXI_HDMI_Y(mode->yres) | SUNXI_HDMI_X(mode->xres),
999 x = mode->hsync_len + mode->left_margin;
1000 y = mode->vsync_len + mode->upper_margin;
1001 writel(SUNXI_HDMI_Y(y) | SUNXI_HDMI_X(x), &hdmi->video_bp);
1003 x = mode->right_margin;
1004 y = mode->lower_margin;
1005 writel(SUNXI_HDMI_Y(y) | SUNXI_HDMI_X(x), &hdmi->video_fp);
1007 x = mode->hsync_len;
1008 y = mode->vsync_len;
1009 writel(SUNXI_HDMI_Y(y) | SUNXI_HDMI_X(x), &hdmi->video_spw);
1011 if (mode->sync & FB_SYNC_HOR_HIGH_ACT)
1012 setbits_le32(&hdmi->video_polarity, SUNXI_HDMI_VIDEO_POL_HOR);
1014 if (mode->sync & FB_SYNC_VERT_HIGH_ACT)
1015 setbits_le32(&hdmi->video_polarity, SUNXI_HDMI_VIDEO_POL_VER);
1018 static void sunxi_hdmi_enable(void)
1020 struct sunxi_hdmi_reg * const hdmi =
1021 (struct sunxi_hdmi_reg *)SUNXI_HDMI_BASE;
1024 setbits_le32(&hdmi->video_ctrl, SUNXI_HDMI_VIDEO_CTRL_ENABLE);
1027 #endif /* CONFIG_VIDEO_HDMI */
1029 #if defined CONFIG_VIDEO_VGA || defined CONFIG_VIDEO_COMPOSITE
1031 static void sunxi_tvencoder_mode_set(void)
1033 struct sunxi_ccm_reg * const ccm =
1034 (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
1035 struct sunxi_tve_reg * const tve =
1036 (struct sunxi_tve_reg *)SUNXI_TVE0_BASE;
1039 setbits_le32(&ccm->lcd0_ch0_clk_cfg, CCM_LCD_CH0_CTRL_TVE_RST);
1041 setbits_le32(&ccm->ahb_gate1, 1 << AHB_GATE_OFFSET_TVE0);
1043 switch (sunxi_display.monitor) {
1044 case sunxi_monitor_vga:
1045 writel(SUNXI_TVE_GCTRL_DAC_INPUT(0, 1) |
1046 SUNXI_TVE_GCTRL_DAC_INPUT(1, 2) |
1047 SUNXI_TVE_GCTRL_DAC_INPUT(2, 3), &tve->gctrl);
1048 writel(SUNXI_TVE_CFG0_VGA, &tve->cfg0);
1049 writel(SUNXI_TVE_DAC_CFG0_VGA, &tve->dac_cfg0);
1050 writel(SUNXI_TVE_UNKNOWN1_VGA, &tve->unknown1);
1052 case sunxi_monitor_composite_pal_nc:
1053 writel(SUNXI_TVE_CHROMA_FREQ_PAL_NC, &tve->chroma_freq);
1055 case sunxi_monitor_composite_pal:
1056 writel(SUNXI_TVE_GCTRL_DAC_INPUT(0, 1) |
1057 SUNXI_TVE_GCTRL_DAC_INPUT(1, 2) |
1058 SUNXI_TVE_GCTRL_DAC_INPUT(2, 3) |
1059 SUNXI_TVE_GCTRL_DAC_INPUT(3, 4), &tve->gctrl);
1060 writel(SUNXI_TVE_CFG0_PAL, &tve->cfg0);
1061 writel(SUNXI_TVE_DAC_CFG0_COMPOSITE, &tve->dac_cfg0);
1062 writel(SUNXI_TVE_FILTER_COMPOSITE, &tve->filter);
1063 writel(SUNXI_TVE_PORCH_NUM_PAL, &tve->porch_num);
1064 writel(SUNXI_TVE_LINE_NUM_PAL, &tve->line_num);
1065 writel(SUNXI_TVE_BLANK_BLACK_LEVEL_PAL, &tve->blank_black_level);
1066 writel(SUNXI_TVE_UNKNOWN1_COMPOSITE, &tve->unknown1);
1067 writel(SUNXI_TVE_CBR_LEVEL_PAL, &tve->cbr_level);
1068 writel(SUNXI_TVE_BURST_WIDTH_COMPOSITE, &tve->burst_width);
1069 writel(SUNXI_TVE_UNKNOWN2_PAL, &tve->unknown2);
1070 writel(SUNXI_TVE_ACTIVE_NUM_COMPOSITE, &tve->active_num);
1071 writel(SUNXI_TVE_CHROMA_BW_GAIN_COMP, &tve->chroma_bw_gain);
1072 writel(SUNXI_TVE_NOTCH_WIDTH_COMPOSITE, &tve->notch_width);
1073 writel(SUNXI_TVE_RESYNC_NUM_PAL, &tve->resync_num);
1074 writel(SUNXI_TVE_SLAVE_PARA_COMPOSITE, &tve->slave_para);
1076 case sunxi_monitor_composite_pal_m:
1077 writel(SUNXI_TVE_CHROMA_FREQ_PAL_M, &tve->chroma_freq);
1078 writel(SUNXI_TVE_COLOR_BURST_PAL_M, &tve->color_burst);
1080 case sunxi_monitor_composite_ntsc:
1081 writel(SUNXI_TVE_GCTRL_DAC_INPUT(0, 1) |
1082 SUNXI_TVE_GCTRL_DAC_INPUT(1, 2) |
1083 SUNXI_TVE_GCTRL_DAC_INPUT(2, 3) |
1084 SUNXI_TVE_GCTRL_DAC_INPUT(3, 4), &tve->gctrl);
1085 writel(SUNXI_TVE_CFG0_NTSC, &tve->cfg0);
1086 writel(SUNXI_TVE_DAC_CFG0_COMPOSITE, &tve->dac_cfg0);
1087 writel(SUNXI_TVE_FILTER_COMPOSITE, &tve->filter);
1088 writel(SUNXI_TVE_PORCH_NUM_NTSC, &tve->porch_num);
1089 writel(SUNXI_TVE_LINE_NUM_NTSC, &tve->line_num);
1090 writel(SUNXI_TVE_BLANK_BLACK_LEVEL_NTSC, &tve->blank_black_level);
1091 writel(SUNXI_TVE_UNKNOWN1_COMPOSITE, &tve->unknown1);
1092 writel(SUNXI_TVE_CBR_LEVEL_NTSC, &tve->cbr_level);
1093 writel(SUNXI_TVE_BURST_PHASE_NTSC, &tve->burst_phase);
1094 writel(SUNXI_TVE_BURST_WIDTH_COMPOSITE, &tve->burst_width);
1095 writel(SUNXI_TVE_UNKNOWN2_NTSC, &tve->unknown2);
1096 writel(SUNXI_TVE_SYNC_VBI_LEVEL_NTSC, &tve->sync_vbi_level);
1097 writel(SUNXI_TVE_ACTIVE_NUM_COMPOSITE, &tve->active_num);
1098 writel(SUNXI_TVE_CHROMA_BW_GAIN_COMP, &tve->chroma_bw_gain);
1099 writel(SUNXI_TVE_NOTCH_WIDTH_COMPOSITE, &tve->notch_width);
1100 writel(SUNXI_TVE_RESYNC_NUM_NTSC, &tve->resync_num);
1101 writel(SUNXI_TVE_SLAVE_PARA_COMPOSITE, &tve->slave_para);
1103 case sunxi_monitor_none:
1104 case sunxi_monitor_dvi:
1105 case sunxi_monitor_hdmi:
1106 case sunxi_monitor_lcd:
1111 static void sunxi_tvencoder_enable(void)
1113 struct sunxi_tve_reg * const tve =
1114 (struct sunxi_tve_reg *)SUNXI_TVE0_BASE;
1116 setbits_le32(&tve->gctrl, SUNXI_TVE_GCTRL_ENABLE);
1119 #endif /* CONFIG_VIDEO_VGA || defined CONFIG_VIDEO_COMPOSITE */
1121 static void sunxi_drc_init(void)
1123 #ifdef CONFIG_SUNXI_GEN_SUN6I
1124 struct sunxi_ccm_reg * const ccm =
1125 (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
1127 /* On sun6i the drc must be clocked even when in pass-through mode */
1128 #ifdef CONFIG_MACH_SUN8I_A33
1129 setbits_le32(&ccm->ahb_reset1_cfg, 1 << AHB_RESET_OFFSET_SAT);
1131 setbits_le32(&ccm->ahb_reset1_cfg, 1 << AHB_RESET_OFFSET_DRC0);
1132 clock_set_de_mod_clock(&ccm->iep_drc0_clk_cfg, 300000000);
1136 #ifdef CONFIG_VIDEO_VGA_VIA_LCD
1137 static void sunxi_vga_external_dac_enable(void)
1141 pin = sunxi_name_to_gpio(CONFIG_VIDEO_VGA_EXTERNAL_DAC_EN);
1143 gpio_request(pin, "vga_enable");
1144 gpio_direction_output(pin, 1);
1147 #endif /* CONFIG_VIDEO_VGA_VIA_LCD */
1149 #ifdef CONFIG_VIDEO_LCD_SSD2828
1150 static int sunxi_ssd2828_init(const struct ctfb_res_modes *mode)
1152 struct ssd2828_config cfg = {
1153 .csx_pin = name_to_gpio(CONFIG_VIDEO_LCD_SPI_CS),
1154 .sck_pin = name_to_gpio(CONFIG_VIDEO_LCD_SPI_SCLK),
1155 .sdi_pin = name_to_gpio(CONFIG_VIDEO_LCD_SPI_MOSI),
1156 .sdo_pin = name_to_gpio(CONFIG_VIDEO_LCD_SPI_MISO),
1157 .reset_pin = name_to_gpio(CONFIG_VIDEO_LCD_SSD2828_RESET),
1158 .ssd2828_tx_clk_khz = CONFIG_VIDEO_LCD_SSD2828_TX_CLK * 1000,
1159 .ssd2828_color_depth = 24,
1160 #ifdef CONFIG_VIDEO_LCD_PANEL_MIPI_4_LANE_513_MBPS_VIA_SSD2828
1161 .mipi_dsi_number_of_data_lanes = 4,
1162 .mipi_dsi_bitrate_per_data_lane_mbps = 513,
1163 .mipi_dsi_delay_after_exit_sleep_mode_ms = 100,
1164 .mipi_dsi_delay_after_set_display_on_ms = 200
1166 #error MIPI LCD panel needs configuration parameters
1170 if (cfg.csx_pin == -1 || cfg.sck_pin == -1 || cfg.sdi_pin == -1) {
1171 printf("SSD2828: SPI pins are not properly configured\n");
1174 if (cfg.reset_pin == -1) {
1175 printf("SSD2828: Reset pin is not properly configured\n");
1179 return ssd2828_init(&cfg, mode);
1181 #endif /* CONFIG_VIDEO_LCD_SSD2828 */
1183 static void sunxi_engines_init(void)
1185 sunxi_composer_init();
1190 static void sunxi_mode_set(const struct ctfb_res_modes *mode,
1191 unsigned int address)
1193 int __maybe_unused clk_div, clk_double;
1195 switch (sunxi_display.monitor) {
1196 case sunxi_monitor_none:
1198 case sunxi_monitor_dvi:
1199 case sunxi_monitor_hdmi:
1200 #ifdef CONFIG_VIDEO_HDMI
1201 sunxi_composer_mode_set(mode, address);
1202 sunxi_lcdc_tcon1_mode_set(mode, &clk_div, &clk_double, 0);
1203 sunxi_hdmi_mode_set(mode, clk_div, clk_double);
1204 sunxi_composer_enable();
1205 sunxi_lcdc_enable();
1206 sunxi_hdmi_enable();
1209 case sunxi_monitor_lcd:
1210 sunxi_lcdc_panel_enable();
1211 if (IS_ENABLED(CONFIG_VIDEO_LCD_HITACHI_TX18D42VM)) {
1212 mdelay(50); /* Wait for lcd controller power on */
1213 hitachi_tx18d42vm_init();
1215 if (IS_ENABLED(CONFIG_VIDEO_LCD_TL059WV5C0)) {
1216 unsigned int orig_i2c_bus = i2c_get_bus_num();
1217 i2c_set_bus_num(CONFIG_VIDEO_LCD_I2C_BUS);
1218 i2c_reg_write(0x5c, 0x04, 0x42); /* Turn on the LCD */
1219 i2c_set_bus_num(orig_i2c_bus);
1221 sunxi_composer_mode_set(mode, address);
1222 sunxi_lcdc_tcon0_mode_set(mode, false);
1223 sunxi_composer_enable();
1224 sunxi_lcdc_enable();
1225 #ifdef CONFIG_VIDEO_LCD_SSD2828
1226 sunxi_ssd2828_init(mode);
1228 sunxi_lcdc_backlight_enable();
1230 case sunxi_monitor_vga:
1231 #ifdef CONFIG_VIDEO_VGA
1232 sunxi_composer_mode_set(mode, address);
1233 sunxi_lcdc_tcon1_mode_set(mode, &clk_div, &clk_double, 1);
1234 sunxi_tvencoder_mode_set();
1235 sunxi_composer_enable();
1236 sunxi_lcdc_enable();
1237 sunxi_tvencoder_enable();
1238 #elif defined CONFIG_VIDEO_VGA_VIA_LCD
1239 sunxi_composer_mode_set(mode, address);
1240 sunxi_lcdc_tcon0_mode_set(mode, true);
1241 sunxi_composer_enable();
1242 sunxi_lcdc_enable();
1243 sunxi_vga_external_dac_enable();
1246 case sunxi_monitor_composite_pal:
1247 case sunxi_monitor_composite_ntsc:
1248 case sunxi_monitor_composite_pal_m:
1249 case sunxi_monitor_composite_pal_nc:
1250 #ifdef CONFIG_VIDEO_COMPOSITE
1251 sunxi_composer_mode_set(mode, address);
1252 sunxi_lcdc_tcon1_mode_set(mode, &clk_div, &clk_double, 0);
1253 sunxi_tvencoder_mode_set();
1254 sunxi_composer_enable();
1255 sunxi_lcdc_enable();
1256 sunxi_tvencoder_enable();
1262 static const char *sunxi_get_mon_desc(enum sunxi_monitor monitor)
1265 case sunxi_monitor_none: return "none";
1266 case sunxi_monitor_dvi: return "dvi";
1267 case sunxi_monitor_hdmi: return "hdmi";
1268 case sunxi_monitor_lcd: return "lcd";
1269 case sunxi_monitor_vga: return "vga";
1270 case sunxi_monitor_composite_pal: return "composite-pal";
1271 case sunxi_monitor_composite_ntsc: return "composite-ntsc";
1272 case sunxi_monitor_composite_pal_m: return "composite-pal-m";
1273 case sunxi_monitor_composite_pal_nc: return "composite-pal-nc";
1275 return NULL; /* never reached */
1278 ulong board_get_usable_ram_top(ulong total_size)
1280 return gd->ram_top - CONFIG_SUNXI_MAX_FB_SIZE;
1283 static bool sunxi_has_hdmi(void)
1285 #ifdef CONFIG_VIDEO_HDMI
1292 static bool sunxi_has_lcd(void)
1294 char *lcd_mode = CONFIG_VIDEO_LCD_MODE;
1296 return lcd_mode[0] != 0;
1299 static bool sunxi_has_vga(void)
1301 #if defined CONFIG_VIDEO_VGA || defined CONFIG_VIDEO_VGA_VIA_LCD
1308 static bool sunxi_has_composite(void)
1310 #ifdef CONFIG_VIDEO_COMPOSITE
1317 static enum sunxi_monitor sunxi_get_default_mon(bool allow_hdmi)
1319 if (allow_hdmi && sunxi_has_hdmi())
1320 return sunxi_monitor_dvi;
1321 else if (sunxi_has_lcd())
1322 return sunxi_monitor_lcd;
1323 else if (sunxi_has_vga())
1324 return sunxi_monitor_vga;
1325 else if (sunxi_has_composite())
1326 return sunxi_monitor_composite_pal;
1328 return sunxi_monitor_none;
1331 void *video_hw_init(void)
1333 static GraphicDevice *graphic_device = &sunxi_display.graphic_device;
1334 const struct ctfb_res_modes *mode;
1335 struct ctfb_res_modes custom;
1336 const char *options;
1337 #ifdef CONFIG_VIDEO_HDMI
1338 int ret, hpd, hpd_delay, edid;
1340 int i, overscan_offset, overscan_x, overscan_y;
1341 unsigned int fb_dma_addr;
1343 char *lcd_mode = CONFIG_VIDEO_LCD_MODE;
1345 memset(&sunxi_display, 0, sizeof(struct sunxi_display));
1347 video_get_ctfb_res_modes(RES_MODE_1024x768, 24, &mode,
1348 &sunxi_display.depth, &options);
1349 #ifdef CONFIG_VIDEO_HDMI
1350 hpd = video_get_option_int(options, "hpd", 1);
1351 hpd_delay = video_get_option_int(options, "hpd_delay", 500);
1352 edid = video_get_option_int(options, "edid", 1);
1354 overscan_x = video_get_option_int(options, "overscan_x", -1);
1355 overscan_y = video_get_option_int(options, "overscan_y", -1);
1356 sunxi_display.monitor = sunxi_get_default_mon(true);
1357 video_get_option_string(options, "monitor", mon, sizeof(mon),
1358 sunxi_get_mon_desc(sunxi_display.monitor));
1359 for (i = 0; i <= SUNXI_MONITOR_LAST; i++) {
1360 if (strcmp(mon, sunxi_get_mon_desc(i)) == 0) {
1361 sunxi_display.monitor = i;
1365 if (i > SUNXI_MONITOR_LAST)
1366 printf("Unknown monitor: '%s', falling back to '%s'\n",
1367 mon, sunxi_get_mon_desc(sunxi_display.monitor));
1369 #ifdef CONFIG_VIDEO_HDMI
1370 /* If HDMI/DVI is selected do HPD & EDID, and handle fallback */
1371 if (sunxi_display.monitor == sunxi_monitor_dvi ||
1372 sunxi_display.monitor == sunxi_monitor_hdmi) {
1373 /* Always call hdp_detect, as it also enables clocks, etc. */
1374 ret = sunxi_hdmi_hpd_detect(hpd_delay);
1376 printf("HDMI connected: ");
1377 if (edid && sunxi_hdmi_edid_get_mode(&custom) == 0)
1380 sunxi_hdmi_shutdown();
1381 sunxi_display.monitor = sunxi_get_default_mon(false);
1382 } /* else continue with hdmi/dvi without a cable connected */
1386 switch (sunxi_display.monitor) {
1387 case sunxi_monitor_none:
1389 case sunxi_monitor_dvi:
1390 case sunxi_monitor_hdmi:
1391 if (!sunxi_has_hdmi()) {
1392 printf("HDMI/DVI not supported on this board\n");
1393 sunxi_display.monitor = sunxi_monitor_none;
1397 case sunxi_monitor_lcd:
1398 if (!sunxi_has_lcd()) {
1399 printf("LCD not supported on this board\n");
1400 sunxi_display.monitor = sunxi_monitor_none;
1403 sunxi_display.depth = video_get_params(&custom, lcd_mode);
1406 case sunxi_monitor_vga:
1407 if (!sunxi_has_vga()) {
1408 printf("VGA not supported on this board\n");
1409 sunxi_display.monitor = sunxi_monitor_none;
1412 sunxi_display.depth = 18;
1414 case sunxi_monitor_composite_pal:
1415 case sunxi_monitor_composite_ntsc:
1416 case sunxi_monitor_composite_pal_m:
1417 case sunxi_monitor_composite_pal_nc:
1418 if (!sunxi_has_composite()) {
1419 printf("Composite video not supported on this board\n");
1420 sunxi_display.monitor = sunxi_monitor_none;
1423 if (sunxi_display.monitor == sunxi_monitor_composite_pal ||
1424 sunxi_display.monitor == sunxi_monitor_composite_pal_nc)
1425 mode = &composite_video_modes[0];
1427 mode = &composite_video_modes[1];
1428 sunxi_display.depth = 24;
1432 /* Yes these defaults are quite high, overscan on composite sucks... */
1433 if (overscan_x == -1)
1434 overscan_x = sunxi_is_composite() ? 32 : 0;
1435 if (overscan_y == -1)
1436 overscan_y = sunxi_is_composite() ? 20 : 0;
1438 sunxi_display.fb_size =
1439 (mode->xres * mode->yres * 4 + 0xfff) & ~0xfff;
1440 overscan_offset = (overscan_y * mode->xres + overscan_x) * 4;
1441 /* We want to keep the fb_base for simplefb page aligned, where as
1442 * the sunxi dma engines will happily accept an unaligned address. */
1443 if (overscan_offset)
1444 sunxi_display.fb_size += 0x1000;
1446 if (sunxi_display.fb_size > CONFIG_SUNXI_MAX_FB_SIZE) {
1447 printf("Error need %dkB for fb, but only %dkB is reserved\n",
1448 sunxi_display.fb_size >> 10,
1449 CONFIG_SUNXI_MAX_FB_SIZE >> 10);
1453 printf("Setting up a %dx%d%s %s console (overscan %dx%d)\n",
1454 mode->xres, mode->yres,
1455 (mode->vmode == FB_VMODE_INTERLACED) ? "i" : "",
1456 sunxi_get_mon_desc(sunxi_display.monitor),
1457 overscan_x, overscan_y);
1459 gd->fb_base = gd->bd->bi_dram[0].start +
1460 gd->bd->bi_dram[0].size - sunxi_display.fb_size;
1461 sunxi_engines_init();
1463 fb_dma_addr = gd->fb_base - CONFIG_SYS_SDRAM_BASE;
1464 sunxi_display.fb_addr = gd->fb_base;
1465 if (overscan_offset) {
1466 fb_dma_addr += 0x1000 - (overscan_offset & 0xfff);
1467 sunxi_display.fb_addr += (overscan_offset + 0xfff) & ~0xfff;
1468 memset((void *)gd->fb_base, 0, sunxi_display.fb_size);
1469 flush_cache(gd->fb_base, sunxi_display.fb_size);
1471 sunxi_mode_set(mode, fb_dma_addr);
1474 * These are the only members of this structure that are used. All the
1475 * others are driver specific. The pitch is stored in plnSizeX.
1477 graphic_device->frameAdrs = sunxi_display.fb_addr;
1478 graphic_device->gdfIndex = GDF_32BIT_X888RGB;
1479 graphic_device->gdfBytesPP = 4;
1480 graphic_device->winSizeX = mode->xres - 2 * overscan_x;
1481 graphic_device->winSizeY = mode->yres - 2 * overscan_y;
1482 graphic_device->plnSizeX = mode->xres * graphic_device->gdfBytesPP;
1484 return graphic_device;
1490 #if defined(CONFIG_OF_BOARD_SETUP) && defined(CONFIG_VIDEO_DT_SIMPLEFB)
1491 int sunxi_simplefb_setup(void *blob)
1493 static GraphicDevice *graphic_device = &sunxi_display.graphic_device;
1496 const char *pipeline = NULL;
1498 #ifdef CONFIG_MACH_SUN4I
1499 #define PIPELINE_PREFIX "de_fe0-"
1501 #define PIPELINE_PREFIX
1504 switch (sunxi_display.monitor) {
1505 case sunxi_monitor_none:
1507 case sunxi_monitor_dvi:
1508 case sunxi_monitor_hdmi:
1509 pipeline = PIPELINE_PREFIX "de_be0-lcd0-hdmi";
1511 case sunxi_monitor_lcd:
1512 pipeline = PIPELINE_PREFIX "de_be0-lcd0";
1514 case sunxi_monitor_vga:
1515 #ifdef CONFIG_VIDEO_VGA
1516 pipeline = PIPELINE_PREFIX "de_be0-lcd0-tve0";
1517 #elif defined CONFIG_VIDEO_VGA_VIA_LCD
1518 pipeline = PIPELINE_PREFIX "de_be0-lcd0";
1521 case sunxi_monitor_composite_pal:
1522 case sunxi_monitor_composite_ntsc:
1523 case sunxi_monitor_composite_pal_m:
1524 case sunxi_monitor_composite_pal_nc:
1525 pipeline = PIPELINE_PREFIX "de_be0-lcd0-tve0";
1529 /* Find a prefilled simpefb node, matching out pipeline config */
1530 offset = fdt_node_offset_by_compatible(blob, -1,
1531 "allwinner,simple-framebuffer");
1532 while (offset >= 0) {
1533 ret = fdt_find_string(blob, offset, "allwinner,pipeline",
1537 offset = fdt_node_offset_by_compatible(blob, offset,
1538 "allwinner,simple-framebuffer");
1541 eprintf("Cannot setup simplefb: node not found\n");
1542 return 0; /* Keep older kernels working */
1546 * Do not report the framebuffer as free RAM to the OS, note we cannot
1547 * use fdt_add_mem_rsv() here, because then it is still seen as RAM,
1548 * and e.g. Linux refuses to iomap RAM on ARM, see:
1549 * linux/arch/arm/mm/ioremap.c around line 301.
1551 start = gd->bd->bi_dram[0].start;
1552 size = gd->bd->bi_dram[0].size - sunxi_display.fb_size;
1553 ret = fdt_fixup_memory_banks(blob, &start, &size, 1);
1555 eprintf("Cannot setup simplefb: Error reserving memory\n");
1559 ret = fdt_setup_simplefb_node(blob, offset, sunxi_display.fb_addr,
1560 graphic_device->winSizeX, graphic_device->winSizeY,
1561 graphic_device->plnSizeX, "x8r8g8b8");
1563 eprintf("Cannot setup simplefb: Error setting properties\n");
1567 #endif /* CONFIG_OF_BOARD_SETUP && CONFIG_VIDEO_DT_SIMPLEFB */