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/lcdc.h>
16 #include <asm/arch/pwm.h>
17 #include <asm/global_data.h>
23 #include <fdt_support.h>
27 #include "../videomodes.h"
28 #include "../anx9804.h"
29 #include "../hitachi_tx18d42vm_lcd.h"
30 #include "../ssd2828.h"
32 #ifdef CONFIG_VIDEO_LCD_BL_PWM_ACTIVE_LOW
40 DECLARE_GLOBAL_DATA_PTR;
48 sunxi_monitor_composite_pal,
49 sunxi_monitor_composite_ntsc,
50 sunxi_monitor_composite_pal_m,
51 sunxi_monitor_composite_pal_nc,
53 #define SUNXI_MONITOR_LAST sunxi_monitor_composite_pal_nc
55 struct sunxi_display {
56 GraphicDevice graphic_device;
57 enum sunxi_monitor monitor;
63 const struct ctfb_res_modes composite_video_modes[2] = {
64 /* x y hz pixclk ps/kHz le ri up lo hs vs s vmode */
65 { 720, 576, 50, 37037, 27000, 137, 5, 20, 27, 2, 2, 0, FB_VMODE_INTERLACED },
66 { 720, 480, 60, 37037, 27000, 116, 20, 16, 27, 2, 2, 0, FB_VMODE_INTERLACED },
69 #ifdef CONFIG_VIDEO_HDMI
72 * Wait up to 200ms for value to be set in given part of reg.
74 static int await_completion(u32 *reg, u32 mask, u32 val)
76 unsigned long tmo = timer_get_us() + 200000;
78 while ((readl(reg) & mask) != val) {
79 if (timer_get_us() > tmo) {
80 printf("DDC: timeout reading EDID\n");
87 static int sunxi_hdmi_hpd_detect(int hpd_delay)
89 struct sunxi_ccm_reg * const ccm =
90 (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
91 struct sunxi_hdmi_reg * const hdmi =
92 (struct sunxi_hdmi_reg *)SUNXI_HDMI_BASE;
93 unsigned long tmo = timer_get_us() + hpd_delay * 1000;
95 /* Set pll3 to 300MHz */
96 clock_set_pll3(300000000);
98 /* Set hdmi parent to pll3 */
99 clrsetbits_le32(&ccm->hdmi_clk_cfg, CCM_HDMI_CTRL_PLL_MASK,
102 /* Set ahb gating to pass */
103 #ifdef CONFIG_SUNXI_GEN_SUN6I
104 setbits_le32(&ccm->ahb_reset1_cfg, 1 << AHB_RESET_OFFSET_HDMI);
106 setbits_le32(&ccm->ahb_gate1, 1 << AHB_GATE_OFFSET_HDMI);
109 setbits_le32(&ccm->hdmi_clk_cfg, CCM_HDMI_CTRL_GATE);
111 writel(SUNXI_HDMI_CTRL_ENABLE, &hdmi->ctrl);
112 writel(SUNXI_HDMI_PAD_CTRL0_HDP, &hdmi->pad_ctrl0);
114 while (timer_get_us() < tmo) {
115 if (readl(&hdmi->hpd) & SUNXI_HDMI_HPD_DETECT)
122 static void sunxi_hdmi_shutdown(void)
124 struct sunxi_ccm_reg * const ccm =
125 (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
126 struct sunxi_hdmi_reg * const hdmi =
127 (struct sunxi_hdmi_reg *)SUNXI_HDMI_BASE;
129 clrbits_le32(&hdmi->ctrl, SUNXI_HDMI_CTRL_ENABLE);
130 clrbits_le32(&ccm->hdmi_clk_cfg, CCM_HDMI_CTRL_GATE);
131 clrbits_le32(&ccm->ahb_gate1, 1 << AHB_GATE_OFFSET_HDMI);
132 #ifdef CONFIG_SUNXI_GEN_SUN6I
133 clrbits_le32(&ccm->ahb_reset1_cfg, 1 << AHB_RESET_OFFSET_HDMI);
138 static int sunxi_hdmi_ddc_do_command(u32 cmnd, int offset, int n)
140 struct sunxi_hdmi_reg * const hdmi =
141 (struct sunxi_hdmi_reg *)SUNXI_HDMI_BASE;
143 setbits_le32(&hdmi->ddc_fifo_ctrl, SUNXI_HDMI_DDC_FIFO_CTRL_CLEAR);
144 writel(SUNXI_HMDI_DDC_ADDR_EDDC_SEGMENT(offset >> 8) |
145 SUNXI_HMDI_DDC_ADDR_EDDC_ADDR |
146 SUNXI_HMDI_DDC_ADDR_OFFSET(offset) |
147 SUNXI_HMDI_DDC_ADDR_SLAVE_ADDR, &hdmi->ddc_addr);
148 #ifndef CONFIG_MACH_SUN6I
149 writel(n, &hdmi->ddc_byte_count);
150 writel(cmnd, &hdmi->ddc_cmnd);
152 writel(n << 16 | cmnd, &hdmi->ddc_cmnd);
154 setbits_le32(&hdmi->ddc_ctrl, SUNXI_HMDI_DDC_CTRL_START);
156 return await_completion(&hdmi->ddc_ctrl, SUNXI_HMDI_DDC_CTRL_START, 0);
159 static int sunxi_hdmi_ddc_read(int offset, u8 *buf, int count)
161 struct sunxi_hdmi_reg * const hdmi =
162 (struct sunxi_hdmi_reg *)SUNXI_HDMI_BASE;
171 if (sunxi_hdmi_ddc_do_command(
172 SUNXI_HDMI_DDC_CMND_EXPLICIT_EDDC_READ,
176 for (i = 0; i < n; i++)
177 *buf++ = readb(&hdmi->ddc_fifo_data);
186 static int sunxi_hdmi_edid_get_block(int block, u8 *buf)
191 r = sunxi_hdmi_ddc_read(block * 128, buf, 128);
194 r = edid_check_checksum(buf);
196 printf("EDID block %d: checksum error%s\n",
197 block, retries ? ", retrying" : "");
199 } while (r && retries--);
204 static int sunxi_hdmi_edid_get_mode(struct ctfb_res_modes *mode)
206 struct edid1_info edid1;
207 struct edid_cea861_info cea681[4];
208 struct edid_detailed_timing *t =
209 (struct edid_detailed_timing *)edid1.monitor_details.timing;
210 struct sunxi_hdmi_reg * const hdmi =
211 (struct sunxi_hdmi_reg *)SUNXI_HDMI_BASE;
212 struct sunxi_ccm_reg * const ccm =
213 (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
214 int i, r, ext_blocks = 0;
216 /* SUNXI_HDMI_CTRL_ENABLE & PAD_CTRL0 are already set by hpd_detect */
217 writel(SUNXI_HDMI_PAD_CTRL1 | SUNXI_HDMI_PAD_CTRL1_HALVE,
219 writel(SUNXI_HDMI_PLL_CTRL | SUNXI_HDMI_PLL_CTRL_DIV(15),
221 writel(SUNXI_HDMI_PLL_DBG0_PLL3, &hdmi->pll_dbg0);
223 /* Reset i2c controller */
224 setbits_le32(&ccm->hdmi_clk_cfg, CCM_HDMI_CTRL_DDC_GATE);
225 writel(SUNXI_HMDI_DDC_CTRL_ENABLE |
226 SUNXI_HMDI_DDC_CTRL_SDA_ENABLE |
227 SUNXI_HMDI_DDC_CTRL_SCL_ENABLE |
228 SUNXI_HMDI_DDC_CTRL_RESET, &hdmi->ddc_ctrl);
229 if (await_completion(&hdmi->ddc_ctrl, SUNXI_HMDI_DDC_CTRL_RESET, 0))
232 writel(SUNXI_HDMI_DDC_CLOCK, &hdmi->ddc_clock);
233 #ifndef CONFIG_MACH_SUN6I
234 writel(SUNXI_HMDI_DDC_LINE_CTRL_SDA_ENABLE |
235 SUNXI_HMDI_DDC_LINE_CTRL_SCL_ENABLE, &hdmi->ddc_line_ctrl);
238 r = sunxi_hdmi_edid_get_block(0, (u8 *)&edid1);
240 r = edid_check_info(&edid1);
242 printf("EDID: invalid EDID data\n");
247 ext_blocks = edid1.extension_flag;
250 for (i = 0; i < ext_blocks; i++) {
251 if (sunxi_hdmi_edid_get_block(1 + i,
252 (u8 *)&cea681[i]) != 0) {
259 /* Disable DDC engine, no longer needed */
260 clrbits_le32(&hdmi->ddc_ctrl, SUNXI_HMDI_DDC_CTRL_ENABLE);
261 clrbits_le32(&ccm->hdmi_clk_cfg, CCM_HDMI_CTRL_DDC_GATE);
266 /* We want version 1.3 or 1.2 with detailed timing info */
267 if (edid1.version != 1 || (edid1.revision < 3 &&
268 !EDID1_INFO_FEATURE_PREFERRED_TIMING_MODE(edid1))) {
269 printf("EDID: unsupported version %d.%d\n",
270 edid1.version, edid1.revision);
274 /* Take the first usable detailed timing */
275 for (i = 0; i < 4; i++, t++) {
276 r = video_edid_dtd_to_ctfb_res_modes(t, mode);
281 printf("EDID: no usable detailed timing found\n");
285 /* Check for basic audio support, if found enable hdmi output */
286 sunxi_display.monitor = sunxi_monitor_dvi;
287 for (i = 0; i < ext_blocks; i++) {
288 if (cea681[i].extension_tag != EDID_CEA861_EXTENSION_TAG ||
289 cea681[i].revision < 2)
292 if (EDID_CEA861_SUPPORTS_BASIC_AUDIO(cea681[i]))
293 sunxi_display.monitor = sunxi_monitor_hdmi;
299 #endif /* CONFIG_VIDEO_HDMI */
301 #ifdef CONFIG_MACH_SUN4I
303 * Testing has shown that on sun4i the display backend engine does not have
304 * deep enough fifo-s causing flickering / tearing in full-hd mode due to
305 * fifo underruns. So on sun4i we use the display frontend engine to do the
306 * dma from memory, as the frontend does have deep enough fifo-s.
309 static const u32 sun4i_vert_coef[32] = {
310 0x00004000, 0x000140ff, 0x00033ffe, 0x00043ffd,
311 0x00063efc, 0xff083dfc, 0x000a3bfb, 0xff0d39fb,
312 0xff0f37fb, 0xff1136fa, 0xfe1433fb, 0xfe1631fb,
313 0xfd192ffb, 0xfd1c2cfb, 0xfd1f29fb, 0xfc2127fc,
314 0xfc2424fc, 0xfc2721fc, 0xfb291ffd, 0xfb2c1cfd,
315 0xfb2f19fd, 0xfb3116fe, 0xfb3314fe, 0xfa3611ff,
316 0xfb370fff, 0xfb390dff, 0xfb3b0a00, 0xfc3d08ff,
317 0xfc3e0600, 0xfd3f0400, 0xfe3f0300, 0xff400100,
320 static const u32 sun4i_horz_coef[64] = {
321 0x40000000, 0x00000000, 0x40fe0000, 0x0000ff03,
322 0x3ffd0000, 0x0000ff05, 0x3ffc0000, 0x0000ff06,
323 0x3efb0000, 0x0000ff08, 0x3dfb0000, 0x0000ff09,
324 0x3bfa0000, 0x0000fe0d, 0x39fa0000, 0x0000fe0f,
325 0x38fa0000, 0x0000fe10, 0x36fa0000, 0x0000fe12,
326 0x33fa0000, 0x0000fd16, 0x31fa0000, 0x0000fd18,
327 0x2ffa0000, 0x0000fd1a, 0x2cfa0000, 0x0000fc1e,
328 0x29fa0000, 0x0000fc21, 0x27fb0000, 0x0000fb23,
329 0x24fb0000, 0x0000fb26, 0x21fb0000, 0x0000fb29,
330 0x1ffc0000, 0x0000fa2b, 0x1cfc0000, 0x0000fa2e,
331 0x19fd0000, 0x0000fa30, 0x16fd0000, 0x0000fa33,
332 0x14fd0000, 0x0000fa35, 0x11fe0000, 0x0000fa37,
333 0x0ffe0000, 0x0000fa39, 0x0dfe0000, 0x0000fa3b,
334 0x0afe0000, 0x0000fa3e, 0x08ff0000, 0x0000fb3e,
335 0x06ff0000, 0x0000fb40, 0x05ff0000, 0x0000fc40,
336 0x03ff0000, 0x0000fd41, 0x01ff0000, 0x0000fe42,
339 static void sunxi_frontend_init(void)
341 struct sunxi_ccm_reg * const ccm =
342 (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
343 struct sunxi_de_fe_reg * const de_fe =
344 (struct sunxi_de_fe_reg *)SUNXI_DE_FE0_BASE;
348 setbits_le32(&ccm->ahb_gate1, 1 << AHB_GATE_OFFSET_DE_FE0);
349 setbits_le32(&ccm->dram_clk_gate, 1 << CCM_DRAM_GATE_OFFSET_DE_FE0);
350 clock_set_de_mod_clock(&ccm->fe0_clk_cfg, 300000000);
352 setbits_le32(&de_fe->enable, SUNXI_DE_FE_ENABLE_EN);
354 for (i = 0; i < 32; i++) {
355 writel(sun4i_horz_coef[2 * i], &de_fe->ch0_horzcoef0[i]);
356 writel(sun4i_horz_coef[2 * i + 1], &de_fe->ch0_horzcoef1[i]);
357 writel(sun4i_vert_coef[i], &de_fe->ch0_vertcoef[i]);
358 writel(sun4i_horz_coef[2 * i], &de_fe->ch1_horzcoef0[i]);
359 writel(sun4i_horz_coef[2 * i + 1], &de_fe->ch1_horzcoef1[i]);
360 writel(sun4i_vert_coef[i], &de_fe->ch1_vertcoef[i]);
363 setbits_le32(&de_fe->frame_ctrl, SUNXI_DE_FE_FRAME_CTRL_COEF_RDY);
366 static void sunxi_frontend_mode_set(const struct ctfb_res_modes *mode,
367 unsigned int address)
369 struct sunxi_de_fe_reg * const de_fe =
370 (struct sunxi_de_fe_reg *)SUNXI_DE_FE0_BASE;
372 setbits_le32(&de_fe->bypass, SUNXI_DE_FE_BYPASS_CSC_BYPASS);
373 writel(CONFIG_SYS_SDRAM_BASE + address, &de_fe->ch0_addr);
374 writel(mode->xres * 4, &de_fe->ch0_stride);
375 writel(SUNXI_DE_FE_INPUT_FMT_ARGB8888, &de_fe->input_fmt);
376 writel(SUNXI_DE_FE_OUTPUT_FMT_ARGB8888, &de_fe->output_fmt);
378 writel(SUNXI_DE_FE_HEIGHT(mode->yres) | SUNXI_DE_FE_WIDTH(mode->xres),
380 writel(SUNXI_DE_FE_HEIGHT(mode->yres) | SUNXI_DE_FE_WIDTH(mode->xres),
381 &de_fe->ch0_outsize);
382 writel(SUNXI_DE_FE_FACTOR_INT(1), &de_fe->ch0_horzfact);
383 writel(SUNXI_DE_FE_FACTOR_INT(1), &de_fe->ch0_vertfact);
385 writel(SUNXI_DE_FE_HEIGHT(mode->yres) | SUNXI_DE_FE_WIDTH(mode->xres),
387 writel(SUNXI_DE_FE_HEIGHT(mode->yres) | SUNXI_DE_FE_WIDTH(mode->xres),
388 &de_fe->ch1_outsize);
389 writel(SUNXI_DE_FE_FACTOR_INT(1), &de_fe->ch1_horzfact);
390 writel(SUNXI_DE_FE_FACTOR_INT(1), &de_fe->ch1_vertfact);
392 setbits_le32(&de_fe->frame_ctrl, SUNXI_DE_FE_FRAME_CTRL_REG_RDY);
395 static void sunxi_frontend_enable(void)
397 struct sunxi_de_fe_reg * const de_fe =
398 (struct sunxi_de_fe_reg *)SUNXI_DE_FE0_BASE;
400 setbits_le32(&de_fe->frame_ctrl, SUNXI_DE_FE_FRAME_CTRL_FRM_START);
403 static void sunxi_frontend_init(void) {}
404 static void sunxi_frontend_mode_set(const struct ctfb_res_modes *mode,
405 unsigned int address) {}
406 static void sunxi_frontend_enable(void) {}
409 static bool sunxi_is_composite(void)
411 switch (sunxi_display.monitor) {
412 case sunxi_monitor_none:
413 case sunxi_monitor_dvi:
414 case sunxi_monitor_hdmi:
415 case sunxi_monitor_lcd:
416 case sunxi_monitor_vga:
418 case sunxi_monitor_composite_pal:
419 case sunxi_monitor_composite_ntsc:
420 case sunxi_monitor_composite_pal_m:
421 case sunxi_monitor_composite_pal_nc:
425 return false; /* Never reached */
429 * This is the entity that mixes and matches the different layers and inputs.
430 * Allwinner calls it the back-end, but i like composer better.
432 static void sunxi_composer_init(void)
434 struct sunxi_ccm_reg * const ccm =
435 (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
436 struct sunxi_de_be_reg * const de_be =
437 (struct sunxi_de_be_reg *)SUNXI_DE_BE0_BASE;
440 sunxi_frontend_init();
442 #ifdef CONFIG_SUNXI_GEN_SUN6I
444 setbits_le32(&ccm->ahb_reset1_cfg, 1 << AHB_RESET_OFFSET_DE_BE0);
448 setbits_le32(&ccm->ahb_gate1, 1 << AHB_GATE_OFFSET_DE_BE0);
449 #ifndef CONFIG_MACH_SUN4I /* On sun4i the frontend does the dma */
450 setbits_le32(&ccm->dram_clk_gate, 1 << CCM_DRAM_GATE_OFFSET_DE_BE0);
452 clock_set_de_mod_clock(&ccm->be0_clk_cfg, 300000000);
454 /* Engine bug, clear registers after reset */
455 for (i = 0x0800; i < 0x1000; i += 4)
456 writel(0, SUNXI_DE_BE0_BASE + i);
458 setbits_le32(&de_be->mode, SUNXI_DE_BE_MODE_ENABLE);
461 static u32 sunxi_rgb2yuv_coef[12] = {
462 0x00000107, 0x00000204, 0x00000064, 0x00000108,
463 0x00003f69, 0x00003ed6, 0x000001c1, 0x00000808,
464 0x000001c1, 0x00003e88, 0x00003fb8, 0x00000808
467 static void sunxi_composer_mode_set(const struct ctfb_res_modes *mode,
468 unsigned int address)
470 struct sunxi_de_be_reg * const de_be =
471 (struct sunxi_de_be_reg *)SUNXI_DE_BE0_BASE;
474 sunxi_frontend_mode_set(mode, address);
476 writel(SUNXI_DE_BE_HEIGHT(mode->yres) | SUNXI_DE_BE_WIDTH(mode->xres),
478 writel(SUNXI_DE_BE_HEIGHT(mode->yres) | SUNXI_DE_BE_WIDTH(mode->xres),
479 &de_be->layer0_size);
480 #ifndef CONFIG_MACH_SUN4I /* On sun4i the frontend does the dma */
481 writel(SUNXI_DE_BE_LAYER_STRIDE(mode->xres), &de_be->layer0_stride);
482 writel(address << 3, &de_be->layer0_addr_low32b);
483 writel(address >> 29, &de_be->layer0_addr_high4b);
485 writel(SUNXI_DE_BE_LAYER_ATTR0_SRC_FE0, &de_be->layer0_attr0_ctrl);
487 writel(SUNXI_DE_BE_LAYER_ATTR1_FMT_XRGB8888, &de_be->layer0_attr1_ctrl);
489 setbits_le32(&de_be->mode, SUNXI_DE_BE_MODE_LAYER0_ENABLE);
490 if (mode->vmode == FB_VMODE_INTERLACED)
491 setbits_le32(&de_be->mode,
492 #ifndef CONFIG_MACH_SUN5I
493 SUNXI_DE_BE_MODE_DEFLICKER_ENABLE |
495 SUNXI_DE_BE_MODE_INTERLACE_ENABLE);
497 if (sunxi_is_composite()) {
498 writel(SUNXI_DE_BE_OUTPUT_COLOR_CTRL_ENABLE,
499 &de_be->output_color_ctrl);
500 for (i = 0; i < 12; i++)
501 writel(sunxi_rgb2yuv_coef[i],
502 &de_be->output_color_coef[i]);
506 static void sunxi_composer_enable(void)
508 struct sunxi_de_be_reg * const de_be =
509 (struct sunxi_de_be_reg *)SUNXI_DE_BE0_BASE;
511 sunxi_frontend_enable();
513 setbits_le32(&de_be->reg_ctrl, SUNXI_DE_BE_REG_CTRL_LOAD_REGS);
514 setbits_le32(&de_be->mode, SUNXI_DE_BE_MODE_START);
518 * LCDC, what allwinner calls a CRTC, so timing controller and serializer.
520 static void sunxi_lcdc_pll_set(int tcon, int dotclock,
521 int *clk_div, int *clk_double)
523 struct sunxi_ccm_reg * const ccm =
524 (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
525 int value, n, m, min_m, max_m, diff;
526 int best_n = 0, best_m = 0, best_diff = 0x0FFFFFFF;
528 bool use_mipi_pll = false;
531 #ifdef CONFIG_VIDEO_LCD_IF_PARALLEL
535 #ifdef CONFIG_VIDEO_LCD_IF_LVDS
544 * Find the lowest divider resulting in a matching clock, if there
545 * is no match, pick the closest lower clock, as monitors tend to
546 * not sync to higher frequencies.
548 for (m = min_m; m <= max_m; m++) {
549 n = (m * dotclock) / 3000;
551 if ((n >= 9) && (n <= 127)) {
552 value = (3000 * n) / m;
553 diff = dotclock - value;
554 if (diff < best_diff) {
562 /* These are just duplicates */
566 n = (m * dotclock) / 6000;
567 if ((n >= 9) && (n <= 127)) {
568 value = (6000 * n) / m;
569 diff = dotclock - value;
570 if (diff < best_diff) {
579 #ifdef CONFIG_MACH_SUN6I
581 * Use the MIPI pll if we've been unable to find any matching setting
582 * for PLL3, this happens with high dotclocks because of min_m = 6.
584 if (tcon == 0 && best_n == 0) {
586 best_m = 6; /* Minimum m for tcon0 */
590 clock_set_pll3(297000000); /* Fix the video pll at 297 MHz */
591 clock_set_mipi_pll(best_m * dotclock * 1000);
592 debug("dotclock: %dkHz = %dkHz via mipi pll\n",
593 dotclock, clock_get_mipi_pll() / best_m / 1000);
597 clock_set_pll3(best_n * 3000000);
598 debug("dotclock: %dkHz = %dkHz: (%d * 3MHz * %d) / %d\n",
600 (best_double + 1) * clock_get_pll3() / best_m / 1000,
601 best_double + 1, best_n, best_m);
608 pll = CCM_LCD_CH0_CTRL_MIPI_PLL;
609 else if (best_double)
610 pll = CCM_LCD_CH0_CTRL_PLL3_2X;
612 pll = CCM_LCD_CH0_CTRL_PLL3;
614 writel(CCM_LCD_CH0_CTRL_GATE | CCM_LCD_CH0_CTRL_RST | pll,
615 &ccm->lcd0_ch0_clk_cfg);
617 writel(CCM_LCD_CH1_CTRL_GATE |
618 (best_double ? CCM_LCD_CH1_CTRL_PLL3_2X :
619 CCM_LCD_CH1_CTRL_PLL3) |
620 CCM_LCD_CH1_CTRL_M(best_m), &ccm->lcd0_ch1_clk_cfg);
621 if (sunxi_is_composite())
622 setbits_le32(&ccm->lcd0_ch1_clk_cfg,
623 CCM_LCD_CH1_CTRL_HALF_SCLK1);
627 *clk_double = best_double;
630 static void sunxi_lcdc_init(void)
632 struct sunxi_ccm_reg * const ccm =
633 (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
634 struct sunxi_lcdc_reg * const lcdc =
635 (struct sunxi_lcdc_reg *)SUNXI_LCD0_BASE;
638 #ifdef CONFIG_SUNXI_GEN_SUN6I
639 setbits_le32(&ccm->ahb_reset1_cfg, 1 << AHB_RESET_OFFSET_LCD0);
641 setbits_le32(&ccm->lcd0_ch0_clk_cfg, CCM_LCD_CH0_CTRL_RST);
645 setbits_le32(&ccm->ahb_gate1, 1 << AHB_GATE_OFFSET_LCD0);
646 #ifdef CONFIG_VIDEO_LCD_IF_LVDS
647 #ifdef CONFIG_SUNXI_GEN_SUN6I
648 setbits_le32(&ccm->ahb_reset2_cfg, 1 << AHB_RESET_OFFSET_LVDS);
650 setbits_le32(&ccm->lvds_clk_cfg, CCM_LVDS_CTRL_RST);
657 static void sunxi_lcdc_panel_enable(void)
662 * Start with backlight disabled to avoid the screen flashing to
663 * white while the lcd inits.
665 pin = sunxi_name_to_gpio(CONFIG_VIDEO_LCD_BL_EN);
667 gpio_request(pin, "lcd_backlight_enable");
668 gpio_direction_output(pin, 0);
671 pin = sunxi_name_to_gpio(CONFIG_VIDEO_LCD_BL_PWM);
673 gpio_request(pin, "lcd_backlight_pwm");
674 gpio_direction_output(pin, PWM_OFF);
677 reset_pin = sunxi_name_to_gpio(CONFIG_VIDEO_LCD_RESET);
678 if (reset_pin >= 0) {
679 gpio_request(reset_pin, "lcd_reset");
680 gpio_direction_output(reset_pin, 0); /* Assert reset */
683 /* Give the backlight some time to turn off and power up the panel. */
685 pin = sunxi_name_to_gpio(CONFIG_VIDEO_LCD_POWER);
687 gpio_request(pin, "lcd_power");
688 gpio_direction_output(pin, 1);
692 gpio_direction_output(reset_pin, 1); /* De-assert reset */
695 static void sunxi_lcdc_backlight_enable(void)
700 * We want to have scanned out at least one frame before enabling the
701 * backlight to avoid the screen flashing to white when we enable it.
705 pin = sunxi_name_to_gpio(CONFIG_VIDEO_LCD_BL_EN);
707 gpio_direction_output(pin, 1);
709 pin = sunxi_name_to_gpio(CONFIG_VIDEO_LCD_BL_PWM);
710 #ifdef SUNXI_PWM_PIN0
711 if (pin == SUNXI_PWM_PIN0) {
712 writel(SUNXI_PWM_CTRL_POLARITY0(PWM_ON) |
713 SUNXI_PWM_CTRL_ENABLE0 |
714 SUNXI_PWM_CTRL_PRESCALE0(0xf), SUNXI_PWM_CTRL_REG);
715 writel(SUNXI_PWM_PERIOD_80PCT, SUNXI_PWM_CH0_PERIOD);
716 sunxi_gpio_set_cfgpin(pin, SUNXI_PWM_MUX);
721 gpio_direction_output(pin, PWM_ON);
724 static void sunxi_ctfb_mode_to_display_timing(const struct ctfb_res_modes *mode,
725 struct display_timing *timing)
727 timing->pixelclock.typ = mode->pixclock_khz * 1000;
729 timing->hactive.typ = mode->xres;
730 timing->hfront_porch.typ = mode->right_margin;
731 timing->hback_porch.typ = mode->left_margin;
732 timing->hsync_len.typ = mode->hsync_len;
734 timing->vactive.typ = mode->yres;
735 timing->vfront_porch.typ = mode->lower_margin;
736 timing->vback_porch.typ = mode->upper_margin;
737 timing->vsync_len.typ = mode->vsync_len;
739 if (mode->sync & FB_SYNC_HOR_HIGH_ACT)
740 timing->flags |= DISPLAY_FLAGS_HSYNC_HIGH;
742 timing->flags |= DISPLAY_FLAGS_HSYNC_LOW;
743 if (mode->sync & FB_SYNC_VERT_HIGH_ACT)
744 timing->flags |= DISPLAY_FLAGS_VSYNC_HIGH;
746 timing->flags |= DISPLAY_FLAGS_VSYNC_LOW;
747 if (mode->vmode == FB_VMODE_INTERLACED)
748 timing->flags |= DISPLAY_FLAGS_INTERLACED;
751 static void sunxi_lcdc_tcon0_mode_set(const struct ctfb_res_modes *mode,
752 bool for_ext_vga_dac)
754 struct sunxi_lcdc_reg * const lcdc =
755 (struct sunxi_lcdc_reg *)SUNXI_LCD0_BASE;
756 int clk_div, clk_double, pin;
757 struct display_timing timing;
759 #if defined CONFIG_MACH_SUN8I && defined CONFIG_VIDEO_LCD_IF_LVDS
760 for (pin = SUNXI_GPD(18); pin <= SUNXI_GPD(27); pin++) {
762 for (pin = SUNXI_GPD(0); pin <= SUNXI_GPD(27); pin++) {
764 #ifdef CONFIG_VIDEO_LCD_IF_PARALLEL
765 sunxi_gpio_set_cfgpin(pin, SUNXI_GPD_LCD0);
767 #ifdef CONFIG_VIDEO_LCD_IF_LVDS
768 sunxi_gpio_set_cfgpin(pin, SUNXI_GPD_LVDS0);
770 #ifdef CONFIG_VIDEO_LCD_PANEL_EDP_4_LANE_1620M_VIA_ANX9804
771 sunxi_gpio_set_drv(pin, 3);
775 sunxi_lcdc_pll_set(0, mode->pixclock_khz, &clk_div, &clk_double);
777 sunxi_ctfb_mode_to_display_timing(mode, &timing);
778 lcdc_tcon0_mode_set(lcdc, &timing, clk_div, for_ext_vga_dac,
779 sunxi_display.depth, CONFIG_VIDEO_LCD_DCLK_PHASE);
782 #if defined CONFIG_VIDEO_HDMI || defined CONFIG_VIDEO_VGA || defined CONFIG_VIDEO_COMPOSITE
783 static void sunxi_lcdc_tcon1_mode_set(const struct ctfb_res_modes *mode,
784 int *clk_div, int *clk_double,
785 bool use_portd_hvsync)
787 struct sunxi_lcdc_reg * const lcdc =
788 (struct sunxi_lcdc_reg *)SUNXI_LCD0_BASE;
789 struct display_timing timing;
791 sunxi_ctfb_mode_to_display_timing(mode, &timing);
792 lcdc_tcon1_mode_set(lcdc, &timing, use_portd_hvsync,
793 sunxi_is_composite());
795 if (use_portd_hvsync) {
796 sunxi_gpio_set_cfgpin(SUNXI_GPD(26), SUNXI_GPD_LCD0);
797 sunxi_gpio_set_cfgpin(SUNXI_GPD(27), SUNXI_GPD_LCD0);
800 sunxi_lcdc_pll_set(1, mode->pixclock_khz, clk_div, clk_double);
802 #endif /* CONFIG_VIDEO_HDMI || defined CONFIG_VIDEO_VGA || CONFIG_VIDEO_COMPOSITE */
804 #ifdef CONFIG_VIDEO_HDMI
806 static void sunxi_hdmi_setup_info_frames(const struct ctfb_res_modes *mode)
808 struct sunxi_hdmi_reg * const hdmi =
809 (struct sunxi_hdmi_reg *)SUNXI_HDMI_BASE;
811 u8 avi_info_frame[17] = {
812 0x82, 0x02, 0x0d, 0x00, 0x12, 0x00, 0x88, 0x00,
813 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
816 u8 vendor_info_frame[19] = {
817 0x81, 0x01, 0x06, 0x29, 0x03, 0x0c, 0x00, 0x40,
818 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
823 if (mode->pixclock_khz <= 27000)
824 avi_info_frame[5] = 0x40; /* SD-modes, ITU601 colorspace */
826 avi_info_frame[5] = 0x80; /* HD-modes, ITU709 colorspace */
828 if (mode->xres * 100 / mode->yres < 156)
829 avi_info_frame[5] |= 0x18; /* 4 : 3 */
831 avi_info_frame[5] |= 0x28; /* 16 : 9 */
833 for (i = 0; i < ARRAY_SIZE(avi_info_frame); i++)
834 checksum += avi_info_frame[i];
836 avi_info_frame[3] = 0x100 - checksum;
838 for (i = 0; i < ARRAY_SIZE(avi_info_frame); i++)
839 writeb(avi_info_frame[i], &hdmi->avi_info_frame[i]);
841 writel(SUNXI_HDMI_QCP_PACKET0, &hdmi->qcp_packet0);
842 writel(SUNXI_HDMI_QCP_PACKET1, &hdmi->qcp_packet1);
844 for (i = 0; i < ARRAY_SIZE(vendor_info_frame); i++)
845 writeb(vendor_info_frame[i], &hdmi->vendor_info_frame[i]);
847 writel(SUNXI_HDMI_PKT_CTRL0, &hdmi->pkt_ctrl0);
848 writel(SUNXI_HDMI_PKT_CTRL1, &hdmi->pkt_ctrl1);
850 setbits_le32(&hdmi->video_ctrl, SUNXI_HDMI_VIDEO_CTRL_HDMI);
853 static void sunxi_hdmi_mode_set(const struct ctfb_res_modes *mode,
854 int clk_div, int clk_double)
856 struct sunxi_hdmi_reg * const hdmi =
857 (struct sunxi_hdmi_reg *)SUNXI_HDMI_BASE;
860 /* Write clear interrupt status bits */
861 writel(SUNXI_HDMI_IRQ_STATUS_BITS, &hdmi->irq);
863 if (sunxi_display.monitor == sunxi_monitor_hdmi)
864 sunxi_hdmi_setup_info_frames(mode);
866 /* Set input sync enable */
867 writel(SUNXI_HDMI_UNKNOWN_INPUT_SYNC, &hdmi->unknown);
869 /* Init various registers, select pll3 as clock source */
870 writel(SUNXI_HDMI_VIDEO_POL_TX_CLK, &hdmi->video_polarity);
871 writel(SUNXI_HDMI_PAD_CTRL0_RUN, &hdmi->pad_ctrl0);
872 writel(SUNXI_HDMI_PAD_CTRL1, &hdmi->pad_ctrl1);
873 writel(SUNXI_HDMI_PLL_CTRL, &hdmi->pll_ctrl);
874 writel(SUNXI_HDMI_PLL_DBG0_PLL3, &hdmi->pll_dbg0);
876 /* Setup clk div and doubler */
877 clrsetbits_le32(&hdmi->pll_ctrl, SUNXI_HDMI_PLL_CTRL_DIV_MASK,
878 SUNXI_HDMI_PLL_CTRL_DIV(clk_div));
880 setbits_le32(&hdmi->pad_ctrl1, SUNXI_HDMI_PAD_CTRL1_HALVE);
882 /* Setup timing registers */
883 writel(SUNXI_HDMI_Y(mode->yres) | SUNXI_HDMI_X(mode->xres),
886 x = mode->hsync_len + mode->left_margin;
887 y = mode->vsync_len + mode->upper_margin;
888 writel(SUNXI_HDMI_Y(y) | SUNXI_HDMI_X(x), &hdmi->video_bp);
890 x = mode->right_margin;
891 y = mode->lower_margin;
892 writel(SUNXI_HDMI_Y(y) | SUNXI_HDMI_X(x), &hdmi->video_fp);
896 writel(SUNXI_HDMI_Y(y) | SUNXI_HDMI_X(x), &hdmi->video_spw);
898 if (mode->sync & FB_SYNC_HOR_HIGH_ACT)
899 setbits_le32(&hdmi->video_polarity, SUNXI_HDMI_VIDEO_POL_HOR);
901 if (mode->sync & FB_SYNC_VERT_HIGH_ACT)
902 setbits_le32(&hdmi->video_polarity, SUNXI_HDMI_VIDEO_POL_VER);
905 static void sunxi_hdmi_enable(void)
907 struct sunxi_hdmi_reg * const hdmi =
908 (struct sunxi_hdmi_reg *)SUNXI_HDMI_BASE;
911 setbits_le32(&hdmi->video_ctrl, SUNXI_HDMI_VIDEO_CTRL_ENABLE);
914 #endif /* CONFIG_VIDEO_HDMI */
916 #if defined CONFIG_VIDEO_VGA || defined CONFIG_VIDEO_COMPOSITE
918 static void sunxi_tvencoder_mode_set(void)
920 struct sunxi_ccm_reg * const ccm =
921 (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
922 struct sunxi_tve_reg * const tve =
923 (struct sunxi_tve_reg *)SUNXI_TVE0_BASE;
926 setbits_le32(&ccm->lcd0_ch0_clk_cfg, CCM_LCD_CH0_CTRL_TVE_RST);
928 setbits_le32(&ccm->ahb_gate1, 1 << AHB_GATE_OFFSET_TVE0);
930 switch (sunxi_display.monitor) {
931 case sunxi_monitor_vga:
932 writel(SUNXI_TVE_GCTRL_DAC_INPUT(0, 1) |
933 SUNXI_TVE_GCTRL_DAC_INPUT(1, 2) |
934 SUNXI_TVE_GCTRL_DAC_INPUT(2, 3), &tve->gctrl);
935 writel(SUNXI_TVE_CFG0_VGA, &tve->cfg0);
936 writel(SUNXI_TVE_DAC_CFG0_VGA, &tve->dac_cfg0);
937 writel(SUNXI_TVE_UNKNOWN1_VGA, &tve->unknown1);
939 case sunxi_monitor_composite_pal_nc:
940 writel(SUNXI_TVE_CHROMA_FREQ_PAL_NC, &tve->chroma_freq);
942 case sunxi_monitor_composite_pal:
943 writel(SUNXI_TVE_GCTRL_DAC_INPUT(0, 1) |
944 SUNXI_TVE_GCTRL_DAC_INPUT(1, 2) |
945 SUNXI_TVE_GCTRL_DAC_INPUT(2, 3) |
946 SUNXI_TVE_GCTRL_DAC_INPUT(3, 4), &tve->gctrl);
947 writel(SUNXI_TVE_CFG0_PAL, &tve->cfg0);
948 writel(SUNXI_TVE_DAC_CFG0_COMPOSITE, &tve->dac_cfg0);
949 writel(SUNXI_TVE_FILTER_COMPOSITE, &tve->filter);
950 writel(SUNXI_TVE_PORCH_NUM_PAL, &tve->porch_num);
951 writel(SUNXI_TVE_LINE_NUM_PAL, &tve->line_num);
952 writel(SUNXI_TVE_BLANK_BLACK_LEVEL_PAL, &tve->blank_black_level);
953 writel(SUNXI_TVE_UNKNOWN1_COMPOSITE, &tve->unknown1);
954 writel(SUNXI_TVE_CBR_LEVEL_PAL, &tve->cbr_level);
955 writel(SUNXI_TVE_BURST_WIDTH_COMPOSITE, &tve->burst_width);
956 writel(SUNXI_TVE_UNKNOWN2_PAL, &tve->unknown2);
957 writel(SUNXI_TVE_ACTIVE_NUM_COMPOSITE, &tve->active_num);
958 writel(SUNXI_TVE_CHROMA_BW_GAIN_COMP, &tve->chroma_bw_gain);
959 writel(SUNXI_TVE_NOTCH_WIDTH_COMPOSITE, &tve->notch_width);
960 writel(SUNXI_TVE_RESYNC_NUM_PAL, &tve->resync_num);
961 writel(SUNXI_TVE_SLAVE_PARA_COMPOSITE, &tve->slave_para);
963 case sunxi_monitor_composite_pal_m:
964 writel(SUNXI_TVE_CHROMA_FREQ_PAL_M, &tve->chroma_freq);
965 writel(SUNXI_TVE_COLOR_BURST_PAL_M, &tve->color_burst);
967 case sunxi_monitor_composite_ntsc:
968 writel(SUNXI_TVE_GCTRL_DAC_INPUT(0, 1) |
969 SUNXI_TVE_GCTRL_DAC_INPUT(1, 2) |
970 SUNXI_TVE_GCTRL_DAC_INPUT(2, 3) |
971 SUNXI_TVE_GCTRL_DAC_INPUT(3, 4), &tve->gctrl);
972 writel(SUNXI_TVE_CFG0_NTSC, &tve->cfg0);
973 writel(SUNXI_TVE_DAC_CFG0_COMPOSITE, &tve->dac_cfg0);
974 writel(SUNXI_TVE_FILTER_COMPOSITE, &tve->filter);
975 writel(SUNXI_TVE_PORCH_NUM_NTSC, &tve->porch_num);
976 writel(SUNXI_TVE_LINE_NUM_NTSC, &tve->line_num);
977 writel(SUNXI_TVE_BLANK_BLACK_LEVEL_NTSC, &tve->blank_black_level);
978 writel(SUNXI_TVE_UNKNOWN1_COMPOSITE, &tve->unknown1);
979 writel(SUNXI_TVE_CBR_LEVEL_NTSC, &tve->cbr_level);
980 writel(SUNXI_TVE_BURST_PHASE_NTSC, &tve->burst_phase);
981 writel(SUNXI_TVE_BURST_WIDTH_COMPOSITE, &tve->burst_width);
982 writel(SUNXI_TVE_UNKNOWN2_NTSC, &tve->unknown2);
983 writel(SUNXI_TVE_SYNC_VBI_LEVEL_NTSC, &tve->sync_vbi_level);
984 writel(SUNXI_TVE_ACTIVE_NUM_COMPOSITE, &tve->active_num);
985 writel(SUNXI_TVE_CHROMA_BW_GAIN_COMP, &tve->chroma_bw_gain);
986 writel(SUNXI_TVE_NOTCH_WIDTH_COMPOSITE, &tve->notch_width);
987 writel(SUNXI_TVE_RESYNC_NUM_NTSC, &tve->resync_num);
988 writel(SUNXI_TVE_SLAVE_PARA_COMPOSITE, &tve->slave_para);
990 case sunxi_monitor_none:
991 case sunxi_monitor_dvi:
992 case sunxi_monitor_hdmi:
993 case sunxi_monitor_lcd:
998 static void sunxi_tvencoder_enable(void)
1000 struct sunxi_tve_reg * const tve =
1001 (struct sunxi_tve_reg *)SUNXI_TVE0_BASE;
1003 setbits_le32(&tve->gctrl, SUNXI_TVE_GCTRL_ENABLE);
1006 #endif /* CONFIG_VIDEO_VGA || defined CONFIG_VIDEO_COMPOSITE */
1008 static void sunxi_drc_init(void)
1010 #ifdef CONFIG_SUNXI_GEN_SUN6I
1011 struct sunxi_ccm_reg * const ccm =
1012 (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
1014 /* On sun6i the drc must be clocked even when in pass-through mode */
1015 #ifdef CONFIG_MACH_SUN8I_A33
1016 setbits_le32(&ccm->ahb_reset1_cfg, 1 << AHB_RESET_OFFSET_SAT);
1018 setbits_le32(&ccm->ahb_reset1_cfg, 1 << AHB_RESET_OFFSET_DRC0);
1019 clock_set_de_mod_clock(&ccm->iep_drc0_clk_cfg, 300000000);
1023 #ifdef CONFIG_VIDEO_VGA_VIA_LCD
1024 static void sunxi_vga_external_dac_enable(void)
1028 pin = sunxi_name_to_gpio(CONFIG_VIDEO_VGA_EXTERNAL_DAC_EN);
1030 gpio_request(pin, "vga_enable");
1031 gpio_direction_output(pin, 1);
1034 #endif /* CONFIG_VIDEO_VGA_VIA_LCD */
1036 #ifdef CONFIG_VIDEO_LCD_SSD2828
1037 static int sunxi_ssd2828_init(const struct ctfb_res_modes *mode)
1039 struct ssd2828_config cfg = {
1040 .csx_pin = name_to_gpio(CONFIG_VIDEO_LCD_SPI_CS),
1041 .sck_pin = name_to_gpio(CONFIG_VIDEO_LCD_SPI_SCLK),
1042 .sdi_pin = name_to_gpio(CONFIG_VIDEO_LCD_SPI_MOSI),
1043 .sdo_pin = name_to_gpio(CONFIG_VIDEO_LCD_SPI_MISO),
1044 .reset_pin = name_to_gpio(CONFIG_VIDEO_LCD_SSD2828_RESET),
1045 .ssd2828_tx_clk_khz = CONFIG_VIDEO_LCD_SSD2828_TX_CLK * 1000,
1046 .ssd2828_color_depth = 24,
1047 #ifdef CONFIG_VIDEO_LCD_PANEL_MIPI_4_LANE_513_MBPS_VIA_SSD2828
1048 .mipi_dsi_number_of_data_lanes = 4,
1049 .mipi_dsi_bitrate_per_data_lane_mbps = 513,
1050 .mipi_dsi_delay_after_exit_sleep_mode_ms = 100,
1051 .mipi_dsi_delay_after_set_display_on_ms = 200
1053 #error MIPI LCD panel needs configuration parameters
1057 if (cfg.csx_pin == -1 || cfg.sck_pin == -1 || cfg.sdi_pin == -1) {
1058 printf("SSD2828: SPI pins are not properly configured\n");
1061 if (cfg.reset_pin == -1) {
1062 printf("SSD2828: Reset pin is not properly configured\n");
1066 return ssd2828_init(&cfg, mode);
1068 #endif /* CONFIG_VIDEO_LCD_SSD2828 */
1070 static void sunxi_engines_init(void)
1072 sunxi_composer_init();
1077 static void sunxi_mode_set(const struct ctfb_res_modes *mode,
1078 unsigned int address)
1080 int __maybe_unused clk_div, clk_double;
1081 struct sunxi_lcdc_reg * const lcdc =
1082 (struct sunxi_lcdc_reg *)SUNXI_LCD0_BASE;
1084 switch (sunxi_display.monitor) {
1085 case sunxi_monitor_none:
1087 case sunxi_monitor_dvi:
1088 case sunxi_monitor_hdmi:
1089 #ifdef CONFIG_VIDEO_HDMI
1090 sunxi_composer_mode_set(mode, address);
1091 sunxi_lcdc_tcon1_mode_set(mode, &clk_div, &clk_double, 0);
1092 sunxi_hdmi_mode_set(mode, clk_div, clk_double);
1093 sunxi_composer_enable();
1094 lcdc_enable(lcdc, sunxi_display.depth);
1095 sunxi_hdmi_enable();
1098 case sunxi_monitor_lcd:
1099 sunxi_lcdc_panel_enable();
1100 if (IS_ENABLED(CONFIG_VIDEO_LCD_PANEL_EDP_4_LANE_1620M_VIA_ANX9804)) {
1102 * The anx9804 needs 1.8V from eldo3, we do this here
1103 * and not via CONFIG_AXP_ELDO3_VOLT from board_init()
1104 * to avoid turning this on when using hdmi output.
1106 axp_set_eldo(3, 1800);
1107 anx9804_init(CONFIG_VIDEO_LCD_I2C_BUS, 4,
1108 ANX9804_DATA_RATE_1620M,
1109 sunxi_display.depth);
1111 if (IS_ENABLED(CONFIG_VIDEO_LCD_HITACHI_TX18D42VM)) {
1112 mdelay(50); /* Wait for lcd controller power on */
1113 hitachi_tx18d42vm_init();
1115 if (IS_ENABLED(CONFIG_VIDEO_LCD_TL059WV5C0)) {
1116 unsigned int orig_i2c_bus = i2c_get_bus_num();
1117 i2c_set_bus_num(CONFIG_VIDEO_LCD_I2C_BUS);
1118 i2c_reg_write(0x5c, 0x04, 0x42); /* Turn on the LCD */
1119 i2c_set_bus_num(orig_i2c_bus);
1121 sunxi_composer_mode_set(mode, address);
1122 sunxi_lcdc_tcon0_mode_set(mode, false);
1123 sunxi_composer_enable();
1124 lcdc_enable(lcdc, sunxi_display.depth);
1125 #ifdef CONFIG_VIDEO_LCD_SSD2828
1126 sunxi_ssd2828_init(mode);
1128 sunxi_lcdc_backlight_enable();
1130 case sunxi_monitor_vga:
1131 #ifdef CONFIG_VIDEO_VGA
1132 sunxi_composer_mode_set(mode, address);
1133 sunxi_lcdc_tcon1_mode_set(mode, &clk_div, &clk_double, 1);
1134 sunxi_tvencoder_mode_set();
1135 sunxi_composer_enable();
1136 lcdc_enable(lcdc, sunxi_display.depth);
1137 sunxi_tvencoder_enable();
1138 #elif defined CONFIG_VIDEO_VGA_VIA_LCD
1139 sunxi_composer_mode_set(mode, address);
1140 sunxi_lcdc_tcon0_mode_set(mode, true);
1141 sunxi_composer_enable();
1142 lcdc_enable(lcdc, sunxi_display.depth);
1143 sunxi_vga_external_dac_enable();
1146 case sunxi_monitor_composite_pal:
1147 case sunxi_monitor_composite_ntsc:
1148 case sunxi_monitor_composite_pal_m:
1149 case sunxi_monitor_composite_pal_nc:
1150 #ifdef CONFIG_VIDEO_COMPOSITE
1151 sunxi_composer_mode_set(mode, address);
1152 sunxi_lcdc_tcon1_mode_set(mode, &clk_div, &clk_double, 0);
1153 sunxi_tvencoder_mode_set();
1154 sunxi_composer_enable();
1155 lcdc_enable(lcdc, sunxi_display.depth);
1156 sunxi_tvencoder_enable();
1162 static const char *sunxi_get_mon_desc(enum sunxi_monitor monitor)
1165 case sunxi_monitor_none: return "none";
1166 case sunxi_monitor_dvi: return "dvi";
1167 case sunxi_monitor_hdmi: return "hdmi";
1168 case sunxi_monitor_lcd: return "lcd";
1169 case sunxi_monitor_vga: return "vga";
1170 case sunxi_monitor_composite_pal: return "composite-pal";
1171 case sunxi_monitor_composite_ntsc: return "composite-ntsc";
1172 case sunxi_monitor_composite_pal_m: return "composite-pal-m";
1173 case sunxi_monitor_composite_pal_nc: return "composite-pal-nc";
1175 return NULL; /* never reached */
1178 ulong board_get_usable_ram_top(ulong total_size)
1180 return gd->ram_top - CONFIG_SUNXI_MAX_FB_SIZE;
1183 static bool sunxi_has_hdmi(void)
1185 #ifdef CONFIG_VIDEO_HDMI
1192 static bool sunxi_has_lcd(void)
1194 char *lcd_mode = CONFIG_VIDEO_LCD_MODE;
1196 return lcd_mode[0] != 0;
1199 static bool sunxi_has_vga(void)
1201 #if defined CONFIG_VIDEO_VGA || defined CONFIG_VIDEO_VGA_VIA_LCD
1208 static bool sunxi_has_composite(void)
1210 #ifdef CONFIG_VIDEO_COMPOSITE
1217 static enum sunxi_monitor sunxi_get_default_mon(bool allow_hdmi)
1219 if (allow_hdmi && sunxi_has_hdmi())
1220 return sunxi_monitor_dvi;
1221 else if (sunxi_has_lcd())
1222 return sunxi_monitor_lcd;
1223 else if (sunxi_has_vga())
1224 return sunxi_monitor_vga;
1225 else if (sunxi_has_composite())
1226 return sunxi_monitor_composite_pal;
1228 return sunxi_monitor_none;
1231 void *video_hw_init(void)
1233 static GraphicDevice *graphic_device = &sunxi_display.graphic_device;
1234 const struct ctfb_res_modes *mode;
1235 struct ctfb_res_modes custom;
1236 const char *options;
1237 #ifdef CONFIG_VIDEO_HDMI
1238 int ret, hpd, hpd_delay, edid;
1240 int i, overscan_offset, overscan_x, overscan_y;
1241 unsigned int fb_dma_addr;
1243 char *lcd_mode = CONFIG_VIDEO_LCD_MODE;
1245 memset(&sunxi_display, 0, sizeof(struct sunxi_display));
1247 video_get_ctfb_res_modes(RES_MODE_1024x768, 24, &mode,
1248 &sunxi_display.depth, &options);
1249 #ifdef CONFIG_VIDEO_HDMI
1250 hpd = video_get_option_int(options, "hpd", 1);
1251 hpd_delay = video_get_option_int(options, "hpd_delay", 500);
1252 edid = video_get_option_int(options, "edid", 1);
1254 overscan_x = video_get_option_int(options, "overscan_x", -1);
1255 overscan_y = video_get_option_int(options, "overscan_y", -1);
1256 sunxi_display.monitor = sunxi_get_default_mon(true);
1257 video_get_option_string(options, "monitor", mon, sizeof(mon),
1258 sunxi_get_mon_desc(sunxi_display.monitor));
1259 for (i = 0; i <= SUNXI_MONITOR_LAST; i++) {
1260 if (strcmp(mon, sunxi_get_mon_desc(i)) == 0) {
1261 sunxi_display.monitor = i;
1265 if (i > SUNXI_MONITOR_LAST)
1266 printf("Unknown monitor: '%s', falling back to '%s'\n",
1267 mon, sunxi_get_mon_desc(sunxi_display.monitor));
1269 #ifdef CONFIG_VIDEO_HDMI
1270 /* If HDMI/DVI is selected do HPD & EDID, and handle fallback */
1271 if (sunxi_display.monitor == sunxi_monitor_dvi ||
1272 sunxi_display.monitor == sunxi_monitor_hdmi) {
1273 /* Always call hdp_detect, as it also enables clocks, etc. */
1274 ret = sunxi_hdmi_hpd_detect(hpd_delay);
1276 printf("HDMI connected: ");
1277 if (edid && sunxi_hdmi_edid_get_mode(&custom) == 0)
1280 sunxi_hdmi_shutdown();
1281 sunxi_display.monitor = sunxi_get_default_mon(false);
1282 } /* else continue with hdmi/dvi without a cable connected */
1286 switch (sunxi_display.monitor) {
1287 case sunxi_monitor_none:
1289 case sunxi_monitor_dvi:
1290 case sunxi_monitor_hdmi:
1291 if (!sunxi_has_hdmi()) {
1292 printf("HDMI/DVI not supported on this board\n");
1293 sunxi_display.monitor = sunxi_monitor_none;
1297 case sunxi_monitor_lcd:
1298 if (!sunxi_has_lcd()) {
1299 printf("LCD not supported on this board\n");
1300 sunxi_display.monitor = sunxi_monitor_none;
1303 sunxi_display.depth = video_get_params(&custom, lcd_mode);
1306 case sunxi_monitor_vga:
1307 if (!sunxi_has_vga()) {
1308 printf("VGA not supported on this board\n");
1309 sunxi_display.monitor = sunxi_monitor_none;
1312 sunxi_display.depth = 18;
1314 case sunxi_monitor_composite_pal:
1315 case sunxi_monitor_composite_ntsc:
1316 case sunxi_monitor_composite_pal_m:
1317 case sunxi_monitor_composite_pal_nc:
1318 if (!sunxi_has_composite()) {
1319 printf("Composite video not supported on this board\n");
1320 sunxi_display.monitor = sunxi_monitor_none;
1323 if (sunxi_display.monitor == sunxi_monitor_composite_pal ||
1324 sunxi_display.monitor == sunxi_monitor_composite_pal_nc)
1325 mode = &composite_video_modes[0];
1327 mode = &composite_video_modes[1];
1328 sunxi_display.depth = 24;
1332 /* Yes these defaults are quite high, overscan on composite sucks... */
1333 if (overscan_x == -1)
1334 overscan_x = sunxi_is_composite() ? 32 : 0;
1335 if (overscan_y == -1)
1336 overscan_y = sunxi_is_composite() ? 20 : 0;
1338 sunxi_display.fb_size =
1339 (mode->xres * mode->yres * 4 + 0xfff) & ~0xfff;
1340 overscan_offset = (overscan_y * mode->xres + overscan_x) * 4;
1341 /* We want to keep the fb_base for simplefb page aligned, where as
1342 * the sunxi dma engines will happily accept an unaligned address. */
1343 if (overscan_offset)
1344 sunxi_display.fb_size += 0x1000;
1346 if (sunxi_display.fb_size > CONFIG_SUNXI_MAX_FB_SIZE) {
1347 printf("Error need %dkB for fb, but only %dkB is reserved\n",
1348 sunxi_display.fb_size >> 10,
1349 CONFIG_SUNXI_MAX_FB_SIZE >> 10);
1353 printf("Setting up a %dx%d%s %s console (overscan %dx%d)\n",
1354 mode->xres, mode->yres,
1355 (mode->vmode == FB_VMODE_INTERLACED) ? "i" : "",
1356 sunxi_get_mon_desc(sunxi_display.monitor),
1357 overscan_x, overscan_y);
1359 gd->fb_base = gd->bd->bi_dram[0].start +
1360 gd->bd->bi_dram[0].size - sunxi_display.fb_size;
1361 sunxi_engines_init();
1363 fb_dma_addr = gd->fb_base - CONFIG_SYS_SDRAM_BASE;
1364 sunxi_display.fb_addr = gd->fb_base;
1365 if (overscan_offset) {
1366 fb_dma_addr += 0x1000 - (overscan_offset & 0xfff);
1367 sunxi_display.fb_addr += (overscan_offset + 0xfff) & ~0xfff;
1368 memset((void *)gd->fb_base, 0, sunxi_display.fb_size);
1369 flush_cache(gd->fb_base, sunxi_display.fb_size);
1371 sunxi_mode_set(mode, fb_dma_addr);
1374 * These are the only members of this structure that are used. All the
1375 * others are driver specific. The pitch is stored in plnSizeX.
1377 graphic_device->frameAdrs = sunxi_display.fb_addr;
1378 graphic_device->gdfIndex = GDF_32BIT_X888RGB;
1379 graphic_device->gdfBytesPP = 4;
1380 graphic_device->winSizeX = mode->xres - 2 * overscan_x;
1381 graphic_device->winSizeY = mode->yres - 2 * overscan_y;
1382 graphic_device->plnSizeX = mode->xres * graphic_device->gdfBytesPP;
1384 return graphic_device;
1390 #if defined(CONFIG_OF_BOARD_SETUP) && defined(CONFIG_VIDEO_DT_SIMPLEFB)
1391 int sunxi_simplefb_setup(void *blob)
1393 static GraphicDevice *graphic_device = &sunxi_display.graphic_device;
1396 const char *pipeline = NULL;
1398 #ifdef CONFIG_MACH_SUN4I
1399 #define PIPELINE_PREFIX "de_fe0-"
1401 #define PIPELINE_PREFIX
1404 switch (sunxi_display.monitor) {
1405 case sunxi_monitor_none:
1407 case sunxi_monitor_dvi:
1408 case sunxi_monitor_hdmi:
1409 pipeline = PIPELINE_PREFIX "de_be0-lcd0-hdmi";
1411 case sunxi_monitor_lcd:
1412 pipeline = PIPELINE_PREFIX "de_be0-lcd0";
1414 case sunxi_monitor_vga:
1415 #ifdef CONFIG_VIDEO_VGA
1416 pipeline = PIPELINE_PREFIX "de_be0-lcd0-tve0";
1417 #elif defined CONFIG_VIDEO_VGA_VIA_LCD
1418 pipeline = PIPELINE_PREFIX "de_be0-lcd0";
1421 case sunxi_monitor_composite_pal:
1422 case sunxi_monitor_composite_ntsc:
1423 case sunxi_monitor_composite_pal_m:
1424 case sunxi_monitor_composite_pal_nc:
1425 pipeline = PIPELINE_PREFIX "de_be0-lcd0-tve0";
1429 /* Find a prefilled simpefb node, matching out pipeline config */
1430 offset = fdt_node_offset_by_compatible(blob, -1,
1431 "allwinner,simple-framebuffer");
1432 while (offset >= 0) {
1433 ret = fdt_stringlist_search(blob, offset, "allwinner,pipeline",
1437 offset = fdt_node_offset_by_compatible(blob, offset,
1438 "allwinner,simple-framebuffer");
1441 eprintf("Cannot setup simplefb: node not found\n");
1442 return 0; /* Keep older kernels working */
1446 * Do not report the framebuffer as free RAM to the OS, note we cannot
1447 * use fdt_add_mem_rsv() here, because then it is still seen as RAM,
1448 * and e.g. Linux refuses to iomap RAM on ARM, see:
1449 * linux/arch/arm/mm/ioremap.c around line 301.
1451 start = gd->bd->bi_dram[0].start;
1452 size = gd->bd->bi_dram[0].size - sunxi_display.fb_size;
1453 ret = fdt_fixup_memory_banks(blob, &start, &size, 1);
1455 eprintf("Cannot setup simplefb: Error reserving memory\n");
1459 ret = fdt_setup_simplefb_node(blob, offset, sunxi_display.fb_addr,
1460 graphic_device->winSizeX, graphic_device->winSizeY,
1461 graphic_device->plnSizeX, "x8r8g8b8");
1463 eprintf("Cannot setup simplefb: Error setting properties\n");
1467 #endif /* CONFIG_OF_BOARD_SETUP && CONFIG_VIDEO_DT_SIMPLEFB */