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 SUNXI_DE_BE_MODE_DEFLICKER_ENABLE |
489 SUNXI_DE_BE_MODE_INTERLACE_ENABLE);
491 if (sunxi_is_composite()) {
492 writel(SUNXI_DE_BE_OUTPUT_COLOR_CTRL_ENABLE,
493 &de_be->output_color_ctrl);
494 for (i = 0; i < 12; i++)
495 writel(sunxi_rgb2yuv_coef[i],
496 &de_be->output_color_coef[i]);
500 static void sunxi_composer_enable(void)
502 struct sunxi_de_be_reg * const de_be =
503 (struct sunxi_de_be_reg *)SUNXI_DE_BE0_BASE;
505 sunxi_frontend_enable();
507 setbits_le32(&de_be->reg_ctrl, SUNXI_DE_BE_REG_CTRL_LOAD_REGS);
508 setbits_le32(&de_be->mode, SUNXI_DE_BE_MODE_START);
512 * LCDC, what allwinner calls a CRTC, so timing controller and serializer.
514 static void sunxi_lcdc_pll_set(int tcon, int dotclock,
515 int *clk_div, int *clk_double)
517 struct sunxi_ccm_reg * const ccm =
518 (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
519 int value, n, m, min_m, max_m, diff;
520 int best_n = 0, best_m = 0, best_diff = 0x0FFFFFFF;
524 #ifdef CONFIG_VIDEO_LCD_IF_PARALLEL
528 #ifdef CONFIG_VIDEO_LCD_IF_LVDS
537 * Find the lowest divider resulting in a matching clock, if there
538 * is no match, pick the closest lower clock, as monitors tend to
539 * not sync to higher frequencies.
541 for (m = min_m; m <= max_m; m++) {
542 n = (m * dotclock) / 3000;
544 if ((n >= 9) && (n <= 127)) {
545 value = (3000 * n) / m;
546 diff = dotclock - value;
547 if (diff < best_diff) {
555 /* These are just duplicates */
559 n = (m * dotclock) / 6000;
560 if ((n >= 9) && (n <= 127)) {
561 value = (6000 * n) / m;
562 diff = dotclock - value;
563 if (diff < best_diff) {
572 debug("dotclock: %dkHz = %dkHz: (%d * 3MHz * %d) / %d\n",
573 dotclock, (best_double + 1) * 3000 * best_n / best_m,
574 best_double + 1, best_n, best_m);
576 clock_set_pll3(best_n * 3000000);
579 writel(CCM_LCD_CH0_CTRL_GATE | CCM_LCD_CH0_CTRL_RST |
580 (best_double ? CCM_LCD_CH0_CTRL_PLL3_2X :
581 CCM_LCD_CH0_CTRL_PLL3),
582 &ccm->lcd0_ch0_clk_cfg);
584 writel(CCM_LCD_CH1_CTRL_GATE |
585 (best_double ? CCM_LCD_CH1_CTRL_PLL3_2X :
586 CCM_LCD_CH1_CTRL_PLL3) |
587 CCM_LCD_CH1_CTRL_M(best_m), &ccm->lcd0_ch1_clk_cfg);
588 if (sunxi_is_composite())
589 setbits_le32(&ccm->lcd0_ch1_clk_cfg,
590 CCM_LCD_CH1_CTRL_HALF_SCLK1);
594 *clk_double = best_double;
597 static void sunxi_lcdc_init(void)
599 struct sunxi_ccm_reg * const ccm =
600 (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
601 struct sunxi_lcdc_reg * const lcdc =
602 (struct sunxi_lcdc_reg *)SUNXI_LCD0_BASE;
605 #ifdef CONFIG_SUNXI_GEN_SUN6I
606 setbits_le32(&ccm->ahb_reset1_cfg, 1 << AHB_RESET_OFFSET_LCD0);
608 setbits_le32(&ccm->lcd0_ch0_clk_cfg, CCM_LCD_CH0_CTRL_RST);
612 setbits_le32(&ccm->ahb_gate1, 1 << AHB_GATE_OFFSET_LCD0);
613 #ifdef CONFIG_VIDEO_LCD_IF_LVDS
614 #ifdef CONFIG_SUNXI_GEN_SUN6I
615 setbits_le32(&ccm->ahb_reset2_cfg, 1 << AHB_RESET_OFFSET_LVDS);
617 setbits_le32(&ccm->lvds_clk_cfg, CCM_LVDS_CTRL_RST);
622 writel(0, &lcdc->ctrl); /* Disable tcon */
623 writel(0, &lcdc->int0); /* Disable all interrupts */
625 /* Disable tcon0 dot clock */
626 clrbits_le32(&lcdc->tcon0_dclk, SUNXI_LCDC_TCON0_DCLK_ENABLE);
628 /* Set all io lines to tristate */
629 writel(0xffffffff, &lcdc->tcon0_io_tristate);
630 writel(0xffffffff, &lcdc->tcon1_io_tristate);
633 static void sunxi_lcdc_enable(void)
635 struct sunxi_lcdc_reg * const lcdc =
636 (struct sunxi_lcdc_reg *)SUNXI_LCD0_BASE;
638 setbits_le32(&lcdc->ctrl, SUNXI_LCDC_CTRL_TCON_ENABLE);
639 #ifdef CONFIG_VIDEO_LCD_IF_LVDS
640 setbits_le32(&lcdc->tcon0_lvds_intf, SUNXI_LCDC_TCON0_LVDS_INTF_ENABLE);
641 setbits_le32(&lcdc->lvds_ana0, SUNXI_LCDC_LVDS_ANA0);
642 #ifdef CONFIG_SUNXI_GEN_SUN6I
643 udelay(2); /* delay at least 1200 ns */
644 setbits_le32(&lcdc->lvds_ana0, SUNXI_LCDC_LVDS_ANA0_EN_MB);
645 udelay(2); /* delay at least 1200 ns */
646 setbits_le32(&lcdc->lvds_ana0, SUNXI_LCDC_LVDS_ANA0_DRVC);
647 if (sunxi_display.depth == 18)
648 setbits_le32(&lcdc->lvds_ana0, SUNXI_LCDC_LVDS_ANA0_DRVD(0x7));
650 setbits_le32(&lcdc->lvds_ana0, SUNXI_LCDC_LVDS_ANA0_DRVD(0xf));
652 setbits_le32(&lcdc->lvds_ana0, SUNXI_LCDC_LVDS_ANA0_UPDATE);
653 udelay(2); /* delay at least 1200 ns */
654 setbits_le32(&lcdc->lvds_ana1, SUNXI_LCDC_LVDS_ANA1_INIT1);
655 udelay(1); /* delay at least 120 ns */
656 setbits_le32(&lcdc->lvds_ana1, SUNXI_LCDC_LVDS_ANA1_INIT2);
657 setbits_le32(&lcdc->lvds_ana0, SUNXI_LCDC_LVDS_ANA0_UPDATE);
662 static void sunxi_lcdc_panel_enable(void)
667 * Start with backlight disabled to avoid the screen flashing to
668 * white while the lcd inits.
670 pin = sunxi_name_to_gpio(CONFIG_VIDEO_LCD_BL_EN);
672 gpio_request(pin, "lcd_backlight_enable");
673 gpio_direction_output(pin, 0);
676 pin = sunxi_name_to_gpio(CONFIG_VIDEO_LCD_BL_PWM);
678 gpio_request(pin, "lcd_backlight_pwm");
679 gpio_direction_output(pin, PWM_OFF);
682 reset_pin = sunxi_name_to_gpio(CONFIG_VIDEO_LCD_RESET);
683 if (reset_pin >= 0) {
684 gpio_request(reset_pin, "lcd_reset");
685 gpio_direction_output(reset_pin, 0); /* Assert reset */
688 /* Give the backlight some time to turn off and power up the panel. */
690 pin = sunxi_name_to_gpio(CONFIG_VIDEO_LCD_POWER);
692 gpio_request(pin, "lcd_power");
693 gpio_direction_output(pin, 1);
697 gpio_direction_output(reset_pin, 1); /* De-assert reset */
700 static void sunxi_lcdc_backlight_enable(void)
705 * We want to have scanned out at least one frame before enabling the
706 * backlight to avoid the screen flashing to white when we enable it.
710 pin = sunxi_name_to_gpio(CONFIG_VIDEO_LCD_BL_EN);
712 gpio_direction_output(pin, 1);
714 pin = sunxi_name_to_gpio(CONFIG_VIDEO_LCD_BL_PWM);
716 gpio_direction_output(pin, PWM_ON);
719 static int sunxi_lcdc_get_clk_delay(const struct ctfb_res_modes *mode, int tcon)
723 delay = mode->lower_margin + mode->vsync_len + mode->upper_margin;
724 if (mode->vmode == FB_VMODE_INTERLACED)
729 return (delay > 30) ? 30 : delay;
732 static void sunxi_lcdc_tcon0_mode_set(const struct ctfb_res_modes *mode,
733 bool for_ext_vga_dac)
735 struct sunxi_lcdc_reg * const lcdc =
736 (struct sunxi_lcdc_reg *)SUNXI_LCD0_BASE;
737 int bp, clk_delay, clk_div, clk_double, pin, total, val;
739 for (pin = SUNXI_GPD(0); pin <= SUNXI_GPD(27); pin++)
740 #ifdef CONFIG_VIDEO_LCD_IF_PARALLEL
741 sunxi_gpio_set_cfgpin(pin, SUNXI_GPD_LCD0);
743 #ifdef CONFIG_VIDEO_LCD_IF_LVDS
744 sunxi_gpio_set_cfgpin(pin, SUNXI_GPD_LVDS0);
747 sunxi_lcdc_pll_set(0, mode->pixclock_khz, &clk_div, &clk_double);
750 clrsetbits_le32(&lcdc->ctrl, SUNXI_LCDC_CTRL_IO_MAP_MASK,
751 SUNXI_LCDC_CTRL_IO_MAP_TCON0);
753 clk_delay = sunxi_lcdc_get_clk_delay(mode, 0);
754 writel(SUNXI_LCDC_TCON0_CTRL_ENABLE |
755 SUNXI_LCDC_TCON0_CTRL_CLK_DELAY(clk_delay), &lcdc->tcon0_ctrl);
757 writel(SUNXI_LCDC_TCON0_DCLK_ENABLE |
758 SUNXI_LCDC_TCON0_DCLK_DIV(clk_div), &lcdc->tcon0_dclk);
760 writel(SUNXI_LCDC_X(mode->xres) | SUNXI_LCDC_Y(mode->yres),
761 &lcdc->tcon0_timing_active);
763 bp = mode->hsync_len + mode->left_margin;
764 total = mode->xres + mode->right_margin + bp;
765 writel(SUNXI_LCDC_TCON0_TIMING_H_TOTAL(total) |
766 SUNXI_LCDC_TCON0_TIMING_H_BP(bp), &lcdc->tcon0_timing_h);
768 bp = mode->vsync_len + mode->upper_margin;
769 total = mode->yres + mode->lower_margin + bp;
770 writel(SUNXI_LCDC_TCON0_TIMING_V_TOTAL(total) |
771 SUNXI_LCDC_TCON0_TIMING_V_BP(bp), &lcdc->tcon0_timing_v);
773 #ifdef CONFIG_VIDEO_LCD_IF_PARALLEL
774 writel(SUNXI_LCDC_X(mode->hsync_len) | SUNXI_LCDC_Y(mode->vsync_len),
775 &lcdc->tcon0_timing_sync);
777 writel(0, &lcdc->tcon0_hv_intf);
778 writel(0, &lcdc->tcon0_cpu_intf);
780 #ifdef CONFIG_VIDEO_LCD_IF_LVDS
781 val = (sunxi_display.depth == 18) ? 1 : 0;
782 writel(SUNXI_LCDC_TCON0_LVDS_INTF_BITWIDTH(val) |
783 SUNXI_LCDC_TCON0_LVDS_CLK_SEL_TCON0, &lcdc->tcon0_lvds_intf);
786 if (sunxi_display.depth == 18 || sunxi_display.depth == 16) {
787 writel(SUNXI_LCDC_TCON0_FRM_SEED, &lcdc->tcon0_frm_seed[0]);
788 writel(SUNXI_LCDC_TCON0_FRM_SEED, &lcdc->tcon0_frm_seed[1]);
789 writel(SUNXI_LCDC_TCON0_FRM_SEED, &lcdc->tcon0_frm_seed[2]);
790 writel(SUNXI_LCDC_TCON0_FRM_SEED, &lcdc->tcon0_frm_seed[3]);
791 writel(SUNXI_LCDC_TCON0_FRM_SEED, &lcdc->tcon0_frm_seed[4]);
792 writel(SUNXI_LCDC_TCON0_FRM_SEED, &lcdc->tcon0_frm_seed[5]);
793 writel(SUNXI_LCDC_TCON0_FRM_TAB0, &lcdc->tcon0_frm_table[0]);
794 writel(SUNXI_LCDC_TCON0_FRM_TAB1, &lcdc->tcon0_frm_table[1]);
795 writel(SUNXI_LCDC_TCON0_FRM_TAB2, &lcdc->tcon0_frm_table[2]);
796 writel(SUNXI_LCDC_TCON0_FRM_TAB3, &lcdc->tcon0_frm_table[3]);
797 writel(((sunxi_display.depth == 18) ?
798 SUNXI_LCDC_TCON0_FRM_CTRL_RGB666 :
799 SUNXI_LCDC_TCON0_FRM_CTRL_RGB565),
800 &lcdc->tcon0_frm_ctrl);
803 val = SUNXI_LCDC_TCON0_IO_POL_DCLK_PHASE(CONFIG_VIDEO_LCD_DCLK_PHASE);
804 if (!(mode->sync & FB_SYNC_HOR_HIGH_ACT))
805 val |= SUNXI_LCDC_TCON_HSYNC_MASK;
806 if (!(mode->sync & FB_SYNC_VERT_HIGH_ACT))
807 val |= SUNXI_LCDC_TCON_VSYNC_MASK;
809 #ifdef CONFIG_VIDEO_VGA_VIA_LCD_FORCE_SYNC_ACTIVE_HIGH
813 writel(val, &lcdc->tcon0_io_polarity);
815 writel(0, &lcdc->tcon0_io_tristate);
818 #if defined CONFIG_VIDEO_HDMI || defined CONFIG_VIDEO_VGA || defined CONFIG_VIDEO_COMPOSITE
819 static void sunxi_lcdc_tcon1_mode_set(const struct ctfb_res_modes *mode,
820 int *clk_div, int *clk_double,
821 bool use_portd_hvsync)
823 struct sunxi_lcdc_reg * const lcdc =
824 (struct sunxi_lcdc_reg *)SUNXI_LCD0_BASE;
825 int bp, clk_delay, total, val, yres;
828 clrsetbits_le32(&lcdc->ctrl, SUNXI_LCDC_CTRL_IO_MAP_MASK,
829 SUNXI_LCDC_CTRL_IO_MAP_TCON1);
831 clk_delay = sunxi_lcdc_get_clk_delay(mode, 1);
832 writel(SUNXI_LCDC_TCON1_CTRL_ENABLE |
833 ((mode->vmode == FB_VMODE_INTERLACED) ?
834 SUNXI_LCDC_TCON1_CTRL_INTERLACE_ENABLE : 0) |
835 SUNXI_LCDC_TCON1_CTRL_CLK_DELAY(clk_delay), &lcdc->tcon1_ctrl);
838 if (mode->vmode == FB_VMODE_INTERLACED)
840 writel(SUNXI_LCDC_X(mode->xres) | SUNXI_LCDC_Y(yres),
841 &lcdc->tcon1_timing_source);
842 writel(SUNXI_LCDC_X(mode->xres) | SUNXI_LCDC_Y(yres),
843 &lcdc->tcon1_timing_scale);
844 writel(SUNXI_LCDC_X(mode->xres) | SUNXI_LCDC_Y(yres),
845 &lcdc->tcon1_timing_out);
847 bp = mode->hsync_len + mode->left_margin;
848 total = mode->xres + mode->right_margin + bp;
849 writel(SUNXI_LCDC_TCON1_TIMING_H_TOTAL(total) |
850 SUNXI_LCDC_TCON1_TIMING_H_BP(bp), &lcdc->tcon1_timing_h);
852 bp = mode->vsync_len + mode->upper_margin;
853 total = mode->yres + mode->lower_margin + bp;
854 if (mode->vmode == FB_VMODE_NONINTERLACED)
856 writel(SUNXI_LCDC_TCON1_TIMING_V_TOTAL(total) |
857 SUNXI_LCDC_TCON1_TIMING_V_BP(bp), &lcdc->tcon1_timing_v);
859 writel(SUNXI_LCDC_X(mode->hsync_len) | SUNXI_LCDC_Y(mode->vsync_len),
860 &lcdc->tcon1_timing_sync);
862 if (use_portd_hvsync) {
863 sunxi_gpio_set_cfgpin(SUNXI_GPD(26), SUNXI_GPD_LCD0);
864 sunxi_gpio_set_cfgpin(SUNXI_GPD(27), SUNXI_GPD_LCD0);
867 if (mode->sync & FB_SYNC_HOR_HIGH_ACT)
868 val |= SUNXI_LCDC_TCON_HSYNC_MASK;
869 if (mode->sync & FB_SYNC_VERT_HIGH_ACT)
870 val |= SUNXI_LCDC_TCON_VSYNC_MASK;
871 writel(val, &lcdc->tcon1_io_polarity);
873 clrbits_le32(&lcdc->tcon1_io_tristate,
874 SUNXI_LCDC_TCON_VSYNC_MASK |
875 SUNXI_LCDC_TCON_HSYNC_MASK);
877 sunxi_lcdc_pll_set(1, mode->pixclock_khz, clk_div, clk_double);
879 #endif /* CONFIG_VIDEO_HDMI || defined CONFIG_VIDEO_VGA || CONFIG_VIDEO_COMPOSITE */
881 #ifdef CONFIG_VIDEO_HDMI
883 static void sunxi_hdmi_setup_info_frames(const struct ctfb_res_modes *mode)
885 struct sunxi_hdmi_reg * const hdmi =
886 (struct sunxi_hdmi_reg *)SUNXI_HDMI_BASE;
888 u8 avi_info_frame[17] = {
889 0x82, 0x02, 0x0d, 0x00, 0x12, 0x00, 0x88, 0x00,
890 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
893 u8 vendor_info_frame[19] = {
894 0x81, 0x01, 0x06, 0x29, 0x03, 0x0c, 0x00, 0x40,
895 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
900 if (mode->pixclock_khz <= 27000)
901 avi_info_frame[5] = 0x40; /* SD-modes, ITU601 colorspace */
903 avi_info_frame[5] = 0x80; /* HD-modes, ITU709 colorspace */
905 if (mode->xres * 100 / mode->yres < 156)
906 avi_info_frame[5] |= 0x18; /* 4 : 3 */
908 avi_info_frame[5] |= 0x28; /* 16 : 9 */
910 for (i = 0; i < ARRAY_SIZE(avi_info_frame); i++)
911 checksum += avi_info_frame[i];
913 avi_info_frame[3] = 0x100 - checksum;
915 for (i = 0; i < ARRAY_SIZE(avi_info_frame); i++)
916 writeb(avi_info_frame[i], &hdmi->avi_info_frame[i]);
918 writel(SUNXI_HDMI_QCP_PACKET0, &hdmi->qcp_packet0);
919 writel(SUNXI_HDMI_QCP_PACKET1, &hdmi->qcp_packet1);
921 for (i = 0; i < ARRAY_SIZE(vendor_info_frame); i++)
922 writeb(vendor_info_frame[i], &hdmi->vendor_info_frame[i]);
924 writel(SUNXI_HDMI_PKT_CTRL0, &hdmi->pkt_ctrl0);
925 writel(SUNXI_HDMI_PKT_CTRL1, &hdmi->pkt_ctrl1);
927 setbits_le32(&hdmi->video_ctrl, SUNXI_HDMI_VIDEO_CTRL_HDMI);
930 static void sunxi_hdmi_mode_set(const struct ctfb_res_modes *mode,
931 int clk_div, int clk_double)
933 struct sunxi_hdmi_reg * const hdmi =
934 (struct sunxi_hdmi_reg *)SUNXI_HDMI_BASE;
937 /* Write clear interrupt status bits */
938 writel(SUNXI_HDMI_IRQ_STATUS_BITS, &hdmi->irq);
940 if (sunxi_display.monitor == sunxi_monitor_hdmi)
941 sunxi_hdmi_setup_info_frames(mode);
943 /* Set input sync enable */
944 writel(SUNXI_HDMI_UNKNOWN_INPUT_SYNC, &hdmi->unknown);
946 /* Init various registers, select pll3 as clock source */
947 writel(SUNXI_HDMI_VIDEO_POL_TX_CLK, &hdmi->video_polarity);
948 writel(SUNXI_HDMI_PAD_CTRL0_RUN, &hdmi->pad_ctrl0);
949 writel(SUNXI_HDMI_PAD_CTRL1, &hdmi->pad_ctrl1);
950 writel(SUNXI_HDMI_PLL_CTRL, &hdmi->pll_ctrl);
951 writel(SUNXI_HDMI_PLL_DBG0_PLL3, &hdmi->pll_dbg0);
953 /* Setup clk div and doubler */
954 clrsetbits_le32(&hdmi->pll_ctrl, SUNXI_HDMI_PLL_CTRL_DIV_MASK,
955 SUNXI_HDMI_PLL_CTRL_DIV(clk_div));
957 setbits_le32(&hdmi->pad_ctrl1, SUNXI_HDMI_PAD_CTRL1_HALVE);
959 /* Setup timing registers */
960 writel(SUNXI_HDMI_Y(mode->yres) | SUNXI_HDMI_X(mode->xres),
963 x = mode->hsync_len + mode->left_margin;
964 y = mode->vsync_len + mode->upper_margin;
965 writel(SUNXI_HDMI_Y(y) | SUNXI_HDMI_X(x), &hdmi->video_bp);
967 x = mode->right_margin;
968 y = mode->lower_margin;
969 writel(SUNXI_HDMI_Y(y) | SUNXI_HDMI_X(x), &hdmi->video_fp);
973 writel(SUNXI_HDMI_Y(y) | SUNXI_HDMI_X(x), &hdmi->video_spw);
975 if (mode->sync & FB_SYNC_HOR_HIGH_ACT)
976 setbits_le32(&hdmi->video_polarity, SUNXI_HDMI_VIDEO_POL_HOR);
978 if (mode->sync & FB_SYNC_VERT_HIGH_ACT)
979 setbits_le32(&hdmi->video_polarity, SUNXI_HDMI_VIDEO_POL_VER);
982 static void sunxi_hdmi_enable(void)
984 struct sunxi_hdmi_reg * const hdmi =
985 (struct sunxi_hdmi_reg *)SUNXI_HDMI_BASE;
988 setbits_le32(&hdmi->video_ctrl, SUNXI_HDMI_VIDEO_CTRL_ENABLE);
991 #endif /* CONFIG_VIDEO_HDMI */
993 #if defined CONFIG_VIDEO_VGA || defined CONFIG_VIDEO_COMPOSITE
995 static void sunxi_tvencoder_mode_set(void)
997 struct sunxi_ccm_reg * const ccm =
998 (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
999 struct sunxi_tve_reg * const tve =
1000 (struct sunxi_tve_reg *)SUNXI_TVE0_BASE;
1003 setbits_le32(&ccm->ahb_gate1, 1 << AHB_GATE_OFFSET_TVE0);
1005 switch (sunxi_display.monitor) {
1006 case sunxi_monitor_vga:
1007 writel(SUNXI_TVE_GCTRL_DAC_INPUT(0, 1) |
1008 SUNXI_TVE_GCTRL_DAC_INPUT(1, 2) |
1009 SUNXI_TVE_GCTRL_DAC_INPUT(2, 3), &tve->gctrl);
1010 writel(SUNXI_TVE_CFG0_VGA, &tve->cfg0);
1011 writel(SUNXI_TVE_DAC_CFG0_VGA, &tve->dac_cfg0);
1012 writel(SUNXI_TVE_UNKNOWN1_VGA, &tve->unknown1);
1014 case sunxi_monitor_composite_pal_nc:
1015 writel(SUNXI_TVE_CHROMA_FREQ_PAL_NC, &tve->chroma_freq);
1017 case sunxi_monitor_composite_pal:
1018 writel(SUNXI_TVE_GCTRL_DAC_INPUT(0, 1) |
1019 SUNXI_TVE_GCTRL_DAC_INPUT(1, 2) |
1020 SUNXI_TVE_GCTRL_DAC_INPUT(2, 3) |
1021 SUNXI_TVE_GCTRL_DAC_INPUT(3, 4), &tve->gctrl);
1022 writel(SUNXI_TVE_CFG0_PAL, &tve->cfg0);
1023 writel(SUNXI_TVE_DAC_CFG0_COMPOSITE, &tve->dac_cfg0);
1024 writel(SUNXI_TVE_FILTER_COMPOSITE, &tve->filter);
1025 writel(SUNXI_TVE_PORCH_NUM_PAL, &tve->porch_num);
1026 writel(SUNXI_TVE_LINE_NUM_PAL, &tve->line_num);
1027 writel(SUNXI_TVE_BLANK_BLACK_LEVEL_PAL, &tve->blank_black_level);
1028 writel(SUNXI_TVE_UNKNOWN1_COMPOSITE, &tve->unknown1);
1029 writel(SUNXI_TVE_CBR_LEVEL_PAL, &tve->cbr_level);
1030 writel(SUNXI_TVE_BURST_WIDTH_COMPOSITE, &tve->burst_width);
1031 writel(SUNXI_TVE_UNKNOWN2_PAL, &tve->unknown2);
1032 writel(SUNXI_TVE_ACTIVE_NUM_COMPOSITE, &tve->active_num);
1033 writel(SUNXI_TVE_CHROMA_BW_GAIN_COMP, &tve->chroma_bw_gain);
1034 writel(SUNXI_TVE_NOTCH_WIDTH_COMPOSITE, &tve->notch_width);
1035 writel(SUNXI_TVE_RESYNC_NUM_PAL, &tve->resync_num);
1036 writel(SUNXI_TVE_SLAVE_PARA_COMPOSITE, &tve->slave_para);
1038 case sunxi_monitor_composite_pal_m:
1039 writel(SUNXI_TVE_CHROMA_FREQ_PAL_M, &tve->chroma_freq);
1040 writel(SUNXI_TVE_COLOR_BURST_PAL_M, &tve->color_burst);
1042 case sunxi_monitor_composite_ntsc:
1043 writel(SUNXI_TVE_GCTRL_DAC_INPUT(0, 1) |
1044 SUNXI_TVE_GCTRL_DAC_INPUT(1, 2) |
1045 SUNXI_TVE_GCTRL_DAC_INPUT(2, 3) |
1046 SUNXI_TVE_GCTRL_DAC_INPUT(3, 4), &tve->gctrl);
1047 writel(SUNXI_TVE_CFG0_NTSC, &tve->cfg0);
1048 writel(SUNXI_TVE_DAC_CFG0_COMPOSITE, &tve->dac_cfg0);
1049 writel(SUNXI_TVE_FILTER_COMPOSITE, &tve->filter);
1050 writel(SUNXI_TVE_PORCH_NUM_NTSC, &tve->porch_num);
1051 writel(SUNXI_TVE_LINE_NUM_NTSC, &tve->line_num);
1052 writel(SUNXI_TVE_BLANK_BLACK_LEVEL_NTSC, &tve->blank_black_level);
1053 writel(SUNXI_TVE_UNKNOWN1_COMPOSITE, &tve->unknown1);
1054 writel(SUNXI_TVE_CBR_LEVEL_NTSC, &tve->cbr_level);
1055 writel(SUNXI_TVE_BURST_PHASE_NTSC, &tve->burst_phase);
1056 writel(SUNXI_TVE_BURST_WIDTH_COMPOSITE, &tve->burst_width);
1057 writel(SUNXI_TVE_UNKNOWN2_NTSC, &tve->unknown2);
1058 writel(SUNXI_TVE_SYNC_VBI_LEVEL_NTSC, &tve->sync_vbi_level);
1059 writel(SUNXI_TVE_ACTIVE_NUM_COMPOSITE, &tve->active_num);
1060 writel(SUNXI_TVE_CHROMA_BW_GAIN_COMP, &tve->chroma_bw_gain);
1061 writel(SUNXI_TVE_NOTCH_WIDTH_COMPOSITE, &tve->notch_width);
1062 writel(SUNXI_TVE_RESYNC_NUM_NTSC, &tve->resync_num);
1063 writel(SUNXI_TVE_SLAVE_PARA_COMPOSITE, &tve->slave_para);
1065 case sunxi_monitor_none:
1066 case sunxi_monitor_dvi:
1067 case sunxi_monitor_hdmi:
1068 case sunxi_monitor_lcd:
1073 static void sunxi_tvencoder_enable(void)
1075 struct sunxi_tve_reg * const tve =
1076 (struct sunxi_tve_reg *)SUNXI_TVE0_BASE;
1078 setbits_le32(&tve->gctrl, SUNXI_TVE_GCTRL_ENABLE);
1081 #endif /* CONFIG_VIDEO_VGA || defined CONFIG_VIDEO_COMPOSITE */
1083 static void sunxi_drc_init(void)
1085 #ifdef CONFIG_SUNXI_GEN_SUN6I
1086 struct sunxi_ccm_reg * const ccm =
1087 (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
1089 /* On sun6i the drc must be clocked even when in pass-through mode */
1090 #ifdef CONFIG_MACH_SUN8I_A33
1091 setbits_le32(&ccm->ahb_reset1_cfg, 1 << AHB_RESET_OFFSET_SAT);
1093 setbits_le32(&ccm->ahb_reset1_cfg, 1 << AHB_RESET_OFFSET_DRC0);
1094 clock_set_de_mod_clock(&ccm->iep_drc0_clk_cfg, 300000000);
1098 #ifdef CONFIG_VIDEO_VGA_VIA_LCD
1099 static void sunxi_vga_external_dac_enable(void)
1103 pin = sunxi_name_to_gpio(CONFIG_VIDEO_VGA_EXTERNAL_DAC_EN);
1105 gpio_request(pin, "vga_enable");
1106 gpio_direction_output(pin, 1);
1109 #endif /* CONFIG_VIDEO_VGA_VIA_LCD */
1111 #ifdef CONFIG_VIDEO_LCD_SSD2828
1112 static int sunxi_ssd2828_init(const struct ctfb_res_modes *mode)
1114 struct ssd2828_config cfg = {
1115 .csx_pin = name_to_gpio(CONFIG_VIDEO_LCD_SPI_CS),
1116 .sck_pin = name_to_gpio(CONFIG_VIDEO_LCD_SPI_SCLK),
1117 .sdi_pin = name_to_gpio(CONFIG_VIDEO_LCD_SPI_MOSI),
1118 .sdo_pin = name_to_gpio(CONFIG_VIDEO_LCD_SPI_MISO),
1119 .reset_pin = name_to_gpio(CONFIG_VIDEO_LCD_SSD2828_RESET),
1120 .ssd2828_tx_clk_khz = CONFIG_VIDEO_LCD_SSD2828_TX_CLK * 1000,
1121 .ssd2828_color_depth = 24,
1122 #ifdef CONFIG_VIDEO_LCD_PANEL_MIPI_4_LANE_513_MBPS_VIA_SSD2828
1123 .mipi_dsi_number_of_data_lanes = 4,
1124 .mipi_dsi_bitrate_per_data_lane_mbps = 513,
1125 .mipi_dsi_delay_after_exit_sleep_mode_ms = 100,
1126 .mipi_dsi_delay_after_set_display_on_ms = 200
1128 #error MIPI LCD panel needs configuration parameters
1132 if (cfg.csx_pin == -1 || cfg.sck_pin == -1 || cfg.sdi_pin == -1) {
1133 printf("SSD2828: SPI pins are not properly configured\n");
1136 if (cfg.reset_pin == -1) {
1137 printf("SSD2828: Reset pin is not properly configured\n");
1141 return ssd2828_init(&cfg, mode);
1143 #endif /* CONFIG_VIDEO_LCD_SSD2828 */
1145 static void sunxi_engines_init(void)
1147 sunxi_composer_init();
1152 static void sunxi_mode_set(const struct ctfb_res_modes *mode,
1153 unsigned int address)
1155 int __maybe_unused clk_div, clk_double;
1157 switch (sunxi_display.monitor) {
1158 case sunxi_monitor_none:
1160 case sunxi_monitor_dvi:
1161 case sunxi_monitor_hdmi:
1162 #ifdef CONFIG_VIDEO_HDMI
1163 sunxi_composer_mode_set(mode, address);
1164 sunxi_lcdc_tcon1_mode_set(mode, &clk_div, &clk_double, 0);
1165 sunxi_hdmi_mode_set(mode, clk_div, clk_double);
1166 sunxi_composer_enable();
1167 sunxi_lcdc_enable();
1168 sunxi_hdmi_enable();
1171 case sunxi_monitor_lcd:
1172 sunxi_lcdc_panel_enable();
1173 if (IS_ENABLED(CONFIG_VIDEO_LCD_HITACHI_TX18D42VM)) {
1174 mdelay(50); /* Wait for lcd controller power on */
1175 hitachi_tx18d42vm_init();
1177 if (IS_ENABLED(CONFIG_VIDEO_LCD_TL059WV5C0)) {
1178 unsigned int orig_i2c_bus = i2c_get_bus_num();
1179 i2c_set_bus_num(CONFIG_VIDEO_LCD_I2C_BUS);
1180 i2c_reg_write(0x5c, 0x04, 0x42); /* Turn on the LCD */
1181 i2c_set_bus_num(orig_i2c_bus);
1183 sunxi_composer_mode_set(mode, address);
1184 sunxi_lcdc_tcon0_mode_set(mode, false);
1185 sunxi_composer_enable();
1186 sunxi_lcdc_enable();
1187 #ifdef CONFIG_VIDEO_LCD_SSD2828
1188 sunxi_ssd2828_init(mode);
1190 sunxi_lcdc_backlight_enable();
1192 case sunxi_monitor_vga:
1193 #ifdef CONFIG_VIDEO_VGA
1194 sunxi_composer_mode_set(mode, address);
1195 sunxi_lcdc_tcon1_mode_set(mode, &clk_div, &clk_double, 1);
1196 sunxi_tvencoder_mode_set();
1197 sunxi_composer_enable();
1198 sunxi_lcdc_enable();
1199 sunxi_tvencoder_enable();
1200 #elif defined CONFIG_VIDEO_VGA_VIA_LCD
1201 sunxi_composer_mode_set(mode, address);
1202 sunxi_lcdc_tcon0_mode_set(mode, true);
1203 sunxi_composer_enable();
1204 sunxi_lcdc_enable();
1205 sunxi_vga_external_dac_enable();
1208 case sunxi_monitor_composite_pal:
1209 case sunxi_monitor_composite_ntsc:
1210 case sunxi_monitor_composite_pal_m:
1211 case sunxi_monitor_composite_pal_nc:
1212 #ifdef CONFIG_VIDEO_COMPOSITE
1213 sunxi_composer_mode_set(mode, address);
1214 sunxi_lcdc_tcon1_mode_set(mode, &clk_div, &clk_double, 0);
1215 sunxi_tvencoder_mode_set();
1216 sunxi_composer_enable();
1217 sunxi_lcdc_enable();
1218 sunxi_tvencoder_enable();
1224 static const char *sunxi_get_mon_desc(enum sunxi_monitor monitor)
1227 case sunxi_monitor_none: return "none";
1228 case sunxi_monitor_dvi: return "dvi";
1229 case sunxi_monitor_hdmi: return "hdmi";
1230 case sunxi_monitor_lcd: return "lcd";
1231 case sunxi_monitor_vga: return "vga";
1232 case sunxi_monitor_composite_pal: return "composite-pal";
1233 case sunxi_monitor_composite_ntsc: return "composite-ntsc";
1234 case sunxi_monitor_composite_pal_m: return "composite-pal-m";
1235 case sunxi_monitor_composite_pal_nc: return "composite-pal-nc";
1237 return NULL; /* never reached */
1240 ulong board_get_usable_ram_top(ulong total_size)
1242 return gd->ram_top - CONFIG_SUNXI_MAX_FB_SIZE;
1245 static bool sunxi_has_hdmi(void)
1247 #ifdef CONFIG_VIDEO_HDMI
1254 static bool sunxi_has_lcd(void)
1256 char *lcd_mode = CONFIG_VIDEO_LCD_MODE;
1258 return lcd_mode[0] != 0;
1261 static bool sunxi_has_vga(void)
1263 #if defined CONFIG_VIDEO_VGA || defined CONFIG_VIDEO_VGA_VIA_LCD
1270 static bool sunxi_has_composite(void)
1272 #ifdef CONFIG_VIDEO_COMPOSITE
1279 static enum sunxi_monitor sunxi_get_default_mon(bool allow_hdmi)
1281 if (allow_hdmi && sunxi_has_hdmi())
1282 return sunxi_monitor_dvi;
1283 else if (sunxi_has_lcd())
1284 return sunxi_monitor_lcd;
1285 else if (sunxi_has_vga())
1286 return sunxi_monitor_vga;
1287 else if (sunxi_has_composite())
1288 return sunxi_monitor_composite_pal;
1290 return sunxi_monitor_none;
1293 void *video_hw_init(void)
1295 static GraphicDevice *graphic_device = &sunxi_display.graphic_device;
1296 const struct ctfb_res_modes *mode;
1297 struct ctfb_res_modes custom;
1298 const char *options;
1299 #ifdef CONFIG_VIDEO_HDMI
1300 int ret, hpd, hpd_delay, edid;
1302 int i, overscan_offset, overscan_x, overscan_y;
1303 unsigned int fb_dma_addr;
1305 char *lcd_mode = CONFIG_VIDEO_LCD_MODE;
1307 memset(&sunxi_display, 0, sizeof(struct sunxi_display));
1309 video_get_ctfb_res_modes(RES_MODE_1024x768, 24, &mode,
1310 &sunxi_display.depth, &options);
1311 #ifdef CONFIG_VIDEO_HDMI
1312 hpd = video_get_option_int(options, "hpd", 1);
1313 hpd_delay = video_get_option_int(options, "hpd_delay", 500);
1314 edid = video_get_option_int(options, "edid", 1);
1316 overscan_x = video_get_option_int(options, "overscan_x", -1);
1317 overscan_y = video_get_option_int(options, "overscan_y", -1);
1318 sunxi_display.monitor = sunxi_get_default_mon(true);
1319 video_get_option_string(options, "monitor", mon, sizeof(mon),
1320 sunxi_get_mon_desc(sunxi_display.monitor));
1321 for (i = 0; i <= SUNXI_MONITOR_LAST; i++) {
1322 if (strcmp(mon, sunxi_get_mon_desc(i)) == 0) {
1323 sunxi_display.monitor = i;
1327 if (i > SUNXI_MONITOR_LAST)
1328 printf("Unknown monitor: '%s', falling back to '%s'\n",
1329 mon, sunxi_get_mon_desc(sunxi_display.monitor));
1331 #ifdef CONFIG_VIDEO_HDMI
1332 /* If HDMI/DVI is selected do HPD & EDID, and handle fallback */
1333 if (sunxi_display.monitor == sunxi_monitor_dvi ||
1334 sunxi_display.monitor == sunxi_monitor_hdmi) {
1335 /* Always call hdp_detect, as it also enables clocks, etc. */
1336 ret = sunxi_hdmi_hpd_detect(hpd_delay);
1338 printf("HDMI connected: ");
1339 if (edid && sunxi_hdmi_edid_get_mode(&custom) == 0)
1342 sunxi_hdmi_shutdown();
1343 sunxi_display.monitor = sunxi_get_default_mon(false);
1344 } /* else continue with hdmi/dvi without a cable connected */
1348 switch (sunxi_display.monitor) {
1349 case sunxi_monitor_none:
1351 case sunxi_monitor_dvi:
1352 case sunxi_monitor_hdmi:
1353 if (!sunxi_has_hdmi()) {
1354 printf("HDMI/DVI not supported on this board\n");
1355 sunxi_display.monitor = sunxi_monitor_none;
1359 case sunxi_monitor_lcd:
1360 if (!sunxi_has_lcd()) {
1361 printf("LCD not supported on this board\n");
1362 sunxi_display.monitor = sunxi_monitor_none;
1365 sunxi_display.depth = video_get_params(&custom, lcd_mode);
1368 case sunxi_monitor_vga:
1369 if (!sunxi_has_vga()) {
1370 printf("VGA not supported on this board\n");
1371 sunxi_display.monitor = sunxi_monitor_none;
1374 sunxi_display.depth = 18;
1376 case sunxi_monitor_composite_pal:
1377 case sunxi_monitor_composite_ntsc:
1378 case sunxi_monitor_composite_pal_m:
1379 case sunxi_monitor_composite_pal_nc:
1380 if (!sunxi_has_composite()) {
1381 printf("Composite video not supported on this board\n");
1382 sunxi_display.monitor = sunxi_monitor_none;
1385 if (sunxi_display.monitor == sunxi_monitor_composite_pal ||
1386 sunxi_display.monitor == sunxi_monitor_composite_pal_nc)
1387 mode = &composite_video_modes[0];
1389 mode = &composite_video_modes[1];
1390 sunxi_display.depth = 24;
1394 /* Yes these defaults are quite high, overscan on composite sucks... */
1395 if (overscan_x == -1)
1396 overscan_x = sunxi_is_composite() ? 32 : 0;
1397 if (overscan_y == -1)
1398 overscan_y = sunxi_is_composite() ? 20 : 0;
1400 sunxi_display.fb_size =
1401 (mode->xres * mode->yres * 4 + 0xfff) & ~0xfff;
1402 overscan_offset = (overscan_y * mode->xres + overscan_x) * 4;
1403 /* We want to keep the fb_base for simplefb page aligned, where as
1404 * the sunxi dma engines will happily accept an unaligned address. */
1405 if (overscan_offset)
1406 sunxi_display.fb_size += 0x1000;
1408 if (sunxi_display.fb_size > CONFIG_SUNXI_MAX_FB_SIZE) {
1409 printf("Error need %dkB for fb, but only %dkB is reserved\n",
1410 sunxi_display.fb_size >> 10,
1411 CONFIG_SUNXI_MAX_FB_SIZE >> 10);
1415 printf("Setting up a %dx%d%s %s console (overscan %dx%d)\n",
1416 mode->xres, mode->yres,
1417 (mode->vmode == FB_VMODE_INTERLACED) ? "i" : "",
1418 sunxi_get_mon_desc(sunxi_display.monitor),
1419 overscan_x, overscan_y);
1421 gd->fb_base = gd->bd->bi_dram[0].start +
1422 gd->bd->bi_dram[0].size - sunxi_display.fb_size;
1423 sunxi_engines_init();
1425 fb_dma_addr = gd->fb_base - CONFIG_SYS_SDRAM_BASE;
1426 sunxi_display.fb_addr = gd->fb_base;
1427 if (overscan_offset) {
1428 fb_dma_addr += 0x1000 - (overscan_offset & 0xfff);
1429 sunxi_display.fb_addr += (overscan_offset + 0xfff) & ~0xfff;
1430 memset((void *)gd->fb_base, 0, sunxi_display.fb_size);
1431 flush_cache(gd->fb_base, sunxi_display.fb_size);
1433 sunxi_mode_set(mode, fb_dma_addr);
1436 * These are the only members of this structure that are used. All the
1437 * others are driver specific. The pitch is stored in plnSizeX.
1439 graphic_device->frameAdrs = sunxi_display.fb_addr;
1440 graphic_device->gdfIndex = GDF_32BIT_X888RGB;
1441 graphic_device->gdfBytesPP = 4;
1442 graphic_device->winSizeX = mode->xres - 2 * overscan_x;
1443 graphic_device->winSizeY = mode->yres - 2 * overscan_y;
1444 graphic_device->plnSizeX = mode->xres * graphic_device->gdfBytesPP;
1446 return graphic_device;
1452 #if defined(CONFIG_OF_BOARD_SETUP) && defined(CONFIG_VIDEO_DT_SIMPLEFB)
1453 int sunxi_simplefb_setup(void *blob)
1455 static GraphicDevice *graphic_device = &sunxi_display.graphic_device;
1458 const char *pipeline = NULL;
1460 #ifdef CONFIG_MACH_SUN4I
1461 #define PIPELINE_PREFIX "de_fe0-"
1463 #define PIPELINE_PREFIX
1466 switch (sunxi_display.monitor) {
1467 case sunxi_monitor_none:
1469 case sunxi_monitor_dvi:
1470 case sunxi_monitor_hdmi:
1471 pipeline = PIPELINE_PREFIX "de_be0-lcd0-hdmi";
1473 case sunxi_monitor_lcd:
1474 pipeline = PIPELINE_PREFIX "de_be0-lcd0";
1476 case sunxi_monitor_vga:
1477 #ifdef CONFIG_VIDEO_VGA
1478 pipeline = PIPELINE_PREFIX "de_be0-lcd0-tve0";
1479 #elif defined CONFIG_VIDEO_VGA_VIA_LCD
1480 pipeline = PIPELINE_PREFIX "de_be0-lcd0";
1483 case sunxi_monitor_composite_pal:
1484 case sunxi_monitor_composite_ntsc:
1485 case sunxi_monitor_composite_pal_m:
1486 case sunxi_monitor_composite_pal_nc:
1487 pipeline = PIPELINE_PREFIX "de_be0-lcd0-tve0";
1491 /* Find a prefilled simpefb node, matching out pipeline config */
1492 offset = fdt_node_offset_by_compatible(blob, -1,
1493 "allwinner,simple-framebuffer");
1494 while (offset >= 0) {
1495 ret = fdt_find_string(blob, offset, "allwinner,pipeline",
1499 offset = fdt_node_offset_by_compatible(blob, offset,
1500 "allwinner,simple-framebuffer");
1503 eprintf("Cannot setup simplefb: node not found\n");
1504 return 0; /* Keep older kernels working */
1508 * Do not report the framebuffer as free RAM to the OS, note we cannot
1509 * use fdt_add_mem_rsv() here, because then it is still seen as RAM,
1510 * and e.g. Linux refuses to iomap RAM on ARM, see:
1511 * linux/arch/arm/mm/ioremap.c around line 301.
1513 start = gd->bd->bi_dram[0].start;
1514 size = gd->bd->bi_dram[0].size - sunxi_display.fb_size;
1515 ret = fdt_fixup_memory_banks(blob, &start, &size, 1);
1517 eprintf("Cannot setup simplefb: Error reserving memory\n");
1521 ret = fdt_setup_simplefb_node(blob, offset, sunxi_display.fb_addr,
1522 graphic_device->winSizeX, graphic_device->winSizeY,
1523 graphic_device->plnSizeX, "x8r8g8b8");
1525 eprintf("Cannot setup simplefb: Error setting properties\n");
1529 #endif /* CONFIG_OF_BOARD_SETUP && CONFIG_VIDEO_DT_SIMPLEFB */