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;
526 #ifdef CONFIG_VIDEO_LCD_IF_PARALLEL
530 #ifdef CONFIG_VIDEO_LCD_IF_LVDS
539 * Find the lowest divider resulting in a matching clock, if there
540 * is no match, pick the closest lower clock, as monitors tend to
541 * not sync to higher frequencies.
543 for (m = min_m; m <= max_m; m++) {
544 n = (m * dotclock) / 3000;
546 if ((n >= 9) && (n <= 127)) {
547 value = (3000 * n) / m;
548 diff = dotclock - value;
549 if (diff < best_diff) {
557 /* These are just duplicates */
561 n = (m * dotclock) / 6000;
562 if ((n >= 9) && (n <= 127)) {
563 value = (6000 * n) / m;
564 diff = dotclock - value;
565 if (diff < best_diff) {
574 debug("dotclock: %dkHz = %dkHz: (%d * 3MHz * %d) / %d\n",
575 dotclock, (best_double + 1) * 3000 * best_n / best_m,
576 best_double + 1, best_n, best_m);
578 clock_set_pll3(best_n * 3000000);
581 writel(CCM_LCD_CH0_CTRL_GATE | CCM_LCD_CH0_CTRL_RST |
582 (best_double ? CCM_LCD_CH0_CTRL_PLL3_2X :
583 CCM_LCD_CH0_CTRL_PLL3),
584 &ccm->lcd0_ch0_clk_cfg);
586 writel(CCM_LCD_CH1_CTRL_GATE |
587 (best_double ? CCM_LCD_CH1_CTRL_PLL3_2X :
588 CCM_LCD_CH1_CTRL_PLL3) |
589 CCM_LCD_CH1_CTRL_M(best_m), &ccm->lcd0_ch1_clk_cfg);
590 if (sunxi_is_composite())
591 setbits_le32(&ccm->lcd0_ch1_clk_cfg,
592 CCM_LCD_CH1_CTRL_HALF_SCLK1);
596 *clk_double = best_double;
599 static void sunxi_lcdc_init(void)
601 struct sunxi_ccm_reg * const ccm =
602 (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
603 struct sunxi_lcdc_reg * const lcdc =
604 (struct sunxi_lcdc_reg *)SUNXI_LCD0_BASE;
607 #ifdef CONFIG_SUNXI_GEN_SUN6I
608 setbits_le32(&ccm->ahb_reset1_cfg, 1 << AHB_RESET_OFFSET_LCD0);
610 setbits_le32(&ccm->lcd0_ch0_clk_cfg, CCM_LCD_CH0_CTRL_RST);
614 setbits_le32(&ccm->ahb_gate1, 1 << AHB_GATE_OFFSET_LCD0);
615 #ifdef CONFIG_VIDEO_LCD_IF_LVDS
616 #ifdef CONFIG_SUNXI_GEN_SUN6I
617 setbits_le32(&ccm->ahb_reset2_cfg, 1 << AHB_RESET_OFFSET_LVDS);
619 setbits_le32(&ccm->lvds_clk_cfg, CCM_LVDS_CTRL_RST);
624 writel(0, &lcdc->ctrl); /* Disable tcon */
625 writel(0, &lcdc->int0); /* Disable all interrupts */
627 /* Disable tcon0 dot clock */
628 clrbits_le32(&lcdc->tcon0_dclk, SUNXI_LCDC_TCON0_DCLK_ENABLE);
630 /* Set all io lines to tristate */
631 writel(0xffffffff, &lcdc->tcon0_io_tristate);
632 writel(0xffffffff, &lcdc->tcon1_io_tristate);
635 static void sunxi_lcdc_enable(void)
637 struct sunxi_lcdc_reg * const lcdc =
638 (struct sunxi_lcdc_reg *)SUNXI_LCD0_BASE;
640 setbits_le32(&lcdc->ctrl, SUNXI_LCDC_CTRL_TCON_ENABLE);
641 #ifdef CONFIG_VIDEO_LCD_IF_LVDS
642 setbits_le32(&lcdc->tcon0_lvds_intf, SUNXI_LCDC_TCON0_LVDS_INTF_ENABLE);
643 setbits_le32(&lcdc->lvds_ana0, SUNXI_LCDC_LVDS_ANA0);
644 #ifdef CONFIG_SUNXI_GEN_SUN6I
645 udelay(2); /* delay at least 1200 ns */
646 setbits_le32(&lcdc->lvds_ana0, SUNXI_LCDC_LVDS_ANA0_EN_MB);
647 udelay(2); /* delay at least 1200 ns */
648 setbits_le32(&lcdc->lvds_ana0, SUNXI_LCDC_LVDS_ANA0_DRVC);
649 if (sunxi_display.depth == 18)
650 setbits_le32(&lcdc->lvds_ana0, SUNXI_LCDC_LVDS_ANA0_DRVD(0x7));
652 setbits_le32(&lcdc->lvds_ana0, SUNXI_LCDC_LVDS_ANA0_DRVD(0xf));
654 setbits_le32(&lcdc->lvds_ana0, SUNXI_LCDC_LVDS_ANA0_UPDATE);
655 udelay(2); /* delay at least 1200 ns */
656 setbits_le32(&lcdc->lvds_ana1, SUNXI_LCDC_LVDS_ANA1_INIT1);
657 udelay(1); /* delay at least 120 ns */
658 setbits_le32(&lcdc->lvds_ana1, SUNXI_LCDC_LVDS_ANA1_INIT2);
659 setbits_le32(&lcdc->lvds_ana0, SUNXI_LCDC_LVDS_ANA0_UPDATE);
664 static void sunxi_lcdc_panel_enable(void)
669 * Start with backlight disabled to avoid the screen flashing to
670 * white while the lcd inits.
672 pin = sunxi_name_to_gpio(CONFIG_VIDEO_LCD_BL_EN);
674 gpio_request(pin, "lcd_backlight_enable");
675 gpio_direction_output(pin, 0);
678 pin = sunxi_name_to_gpio(CONFIG_VIDEO_LCD_BL_PWM);
680 gpio_request(pin, "lcd_backlight_pwm");
681 gpio_direction_output(pin, PWM_OFF);
684 reset_pin = sunxi_name_to_gpio(CONFIG_VIDEO_LCD_RESET);
685 if (reset_pin >= 0) {
686 gpio_request(reset_pin, "lcd_reset");
687 gpio_direction_output(reset_pin, 0); /* Assert reset */
690 /* Give the backlight some time to turn off and power up the panel. */
692 pin = sunxi_name_to_gpio(CONFIG_VIDEO_LCD_POWER);
694 gpio_request(pin, "lcd_power");
695 gpio_direction_output(pin, 1);
699 gpio_direction_output(reset_pin, 1); /* De-assert reset */
702 static void sunxi_lcdc_backlight_enable(void)
707 * We want to have scanned out at least one frame before enabling the
708 * backlight to avoid the screen flashing to white when we enable it.
712 pin = sunxi_name_to_gpio(CONFIG_VIDEO_LCD_BL_EN);
714 gpio_direction_output(pin, 1);
716 pin = sunxi_name_to_gpio(CONFIG_VIDEO_LCD_BL_PWM);
718 gpio_direction_output(pin, PWM_ON);
721 static int sunxi_lcdc_get_clk_delay(const struct ctfb_res_modes *mode, int tcon)
725 delay = mode->lower_margin + mode->vsync_len + mode->upper_margin;
726 if (mode->vmode == FB_VMODE_INTERLACED)
731 return (delay > 30) ? 30 : delay;
734 static void sunxi_lcdc_tcon0_mode_set(const struct ctfb_res_modes *mode,
735 bool for_ext_vga_dac)
737 struct sunxi_lcdc_reg * const lcdc =
738 (struct sunxi_lcdc_reg *)SUNXI_LCD0_BASE;
739 int bp, clk_delay, clk_div, clk_double, pin, total, val;
741 for (pin = SUNXI_GPD(0); pin <= SUNXI_GPD(27); pin++)
742 #ifdef CONFIG_VIDEO_LCD_IF_PARALLEL
743 sunxi_gpio_set_cfgpin(pin, SUNXI_GPD_LCD0);
745 #ifdef CONFIG_VIDEO_LCD_IF_LVDS
746 sunxi_gpio_set_cfgpin(pin, SUNXI_GPD_LVDS0);
749 sunxi_lcdc_pll_set(0, mode->pixclock_khz, &clk_div, &clk_double);
752 clrsetbits_le32(&lcdc->ctrl, SUNXI_LCDC_CTRL_IO_MAP_MASK,
753 SUNXI_LCDC_CTRL_IO_MAP_TCON0);
755 clk_delay = sunxi_lcdc_get_clk_delay(mode, 0);
756 writel(SUNXI_LCDC_TCON0_CTRL_ENABLE |
757 SUNXI_LCDC_TCON0_CTRL_CLK_DELAY(clk_delay), &lcdc->tcon0_ctrl);
759 writel(SUNXI_LCDC_TCON0_DCLK_ENABLE |
760 SUNXI_LCDC_TCON0_DCLK_DIV(clk_div), &lcdc->tcon0_dclk);
762 writel(SUNXI_LCDC_X(mode->xres) | SUNXI_LCDC_Y(mode->yres),
763 &lcdc->tcon0_timing_active);
765 bp = mode->hsync_len + mode->left_margin;
766 total = mode->xres + mode->right_margin + bp;
767 writel(SUNXI_LCDC_TCON0_TIMING_H_TOTAL(total) |
768 SUNXI_LCDC_TCON0_TIMING_H_BP(bp), &lcdc->tcon0_timing_h);
770 bp = mode->vsync_len + mode->upper_margin;
771 total = mode->yres + mode->lower_margin + bp;
772 writel(SUNXI_LCDC_TCON0_TIMING_V_TOTAL(total) |
773 SUNXI_LCDC_TCON0_TIMING_V_BP(bp), &lcdc->tcon0_timing_v);
775 #ifdef CONFIG_VIDEO_LCD_IF_PARALLEL
776 writel(SUNXI_LCDC_X(mode->hsync_len) | SUNXI_LCDC_Y(mode->vsync_len),
777 &lcdc->tcon0_timing_sync);
779 writel(0, &lcdc->tcon0_hv_intf);
780 writel(0, &lcdc->tcon0_cpu_intf);
782 #ifdef CONFIG_VIDEO_LCD_IF_LVDS
783 val = (sunxi_display.depth == 18) ? 1 : 0;
784 writel(SUNXI_LCDC_TCON0_LVDS_INTF_BITWIDTH(val) |
785 SUNXI_LCDC_TCON0_LVDS_CLK_SEL_TCON0, &lcdc->tcon0_lvds_intf);
788 if (sunxi_display.depth == 18 || sunxi_display.depth == 16) {
789 writel(SUNXI_LCDC_TCON0_FRM_SEED, &lcdc->tcon0_frm_seed[0]);
790 writel(SUNXI_LCDC_TCON0_FRM_SEED, &lcdc->tcon0_frm_seed[1]);
791 writel(SUNXI_LCDC_TCON0_FRM_SEED, &lcdc->tcon0_frm_seed[2]);
792 writel(SUNXI_LCDC_TCON0_FRM_SEED, &lcdc->tcon0_frm_seed[3]);
793 writel(SUNXI_LCDC_TCON0_FRM_SEED, &lcdc->tcon0_frm_seed[4]);
794 writel(SUNXI_LCDC_TCON0_FRM_SEED, &lcdc->tcon0_frm_seed[5]);
795 writel(SUNXI_LCDC_TCON0_FRM_TAB0, &lcdc->tcon0_frm_table[0]);
796 writel(SUNXI_LCDC_TCON0_FRM_TAB1, &lcdc->tcon0_frm_table[1]);
797 writel(SUNXI_LCDC_TCON0_FRM_TAB2, &lcdc->tcon0_frm_table[2]);
798 writel(SUNXI_LCDC_TCON0_FRM_TAB3, &lcdc->tcon0_frm_table[3]);
799 writel(((sunxi_display.depth == 18) ?
800 SUNXI_LCDC_TCON0_FRM_CTRL_RGB666 :
801 SUNXI_LCDC_TCON0_FRM_CTRL_RGB565),
802 &lcdc->tcon0_frm_ctrl);
805 val = SUNXI_LCDC_TCON0_IO_POL_DCLK_PHASE(CONFIG_VIDEO_LCD_DCLK_PHASE);
806 if (!(mode->sync & FB_SYNC_HOR_HIGH_ACT))
807 val |= SUNXI_LCDC_TCON_HSYNC_MASK;
808 if (!(mode->sync & FB_SYNC_VERT_HIGH_ACT))
809 val |= SUNXI_LCDC_TCON_VSYNC_MASK;
811 #ifdef CONFIG_VIDEO_VGA_VIA_LCD_FORCE_SYNC_ACTIVE_HIGH
815 writel(val, &lcdc->tcon0_io_polarity);
817 writel(0, &lcdc->tcon0_io_tristate);
820 #if defined CONFIG_VIDEO_HDMI || defined CONFIG_VIDEO_VGA || defined CONFIG_VIDEO_COMPOSITE
821 static void sunxi_lcdc_tcon1_mode_set(const struct ctfb_res_modes *mode,
822 int *clk_div, int *clk_double,
823 bool use_portd_hvsync)
825 struct sunxi_lcdc_reg * const lcdc =
826 (struct sunxi_lcdc_reg *)SUNXI_LCD0_BASE;
827 int bp, clk_delay, total, val, yres;
830 clrsetbits_le32(&lcdc->ctrl, SUNXI_LCDC_CTRL_IO_MAP_MASK,
831 SUNXI_LCDC_CTRL_IO_MAP_TCON1);
833 clk_delay = sunxi_lcdc_get_clk_delay(mode, 1);
834 writel(SUNXI_LCDC_TCON1_CTRL_ENABLE |
835 ((mode->vmode == FB_VMODE_INTERLACED) ?
836 SUNXI_LCDC_TCON1_CTRL_INTERLACE_ENABLE : 0) |
837 SUNXI_LCDC_TCON1_CTRL_CLK_DELAY(clk_delay), &lcdc->tcon1_ctrl);
840 if (mode->vmode == FB_VMODE_INTERLACED)
842 writel(SUNXI_LCDC_X(mode->xres) | SUNXI_LCDC_Y(yres),
843 &lcdc->tcon1_timing_source);
844 writel(SUNXI_LCDC_X(mode->xres) | SUNXI_LCDC_Y(yres),
845 &lcdc->tcon1_timing_scale);
846 writel(SUNXI_LCDC_X(mode->xres) | SUNXI_LCDC_Y(yres),
847 &lcdc->tcon1_timing_out);
849 bp = mode->hsync_len + mode->left_margin;
850 total = mode->xres + mode->right_margin + bp;
851 writel(SUNXI_LCDC_TCON1_TIMING_H_TOTAL(total) |
852 SUNXI_LCDC_TCON1_TIMING_H_BP(bp), &lcdc->tcon1_timing_h);
854 bp = mode->vsync_len + mode->upper_margin;
855 total = mode->yres + mode->lower_margin + bp;
856 if (mode->vmode == FB_VMODE_NONINTERLACED)
858 writel(SUNXI_LCDC_TCON1_TIMING_V_TOTAL(total) |
859 SUNXI_LCDC_TCON1_TIMING_V_BP(bp), &lcdc->tcon1_timing_v);
861 writel(SUNXI_LCDC_X(mode->hsync_len) | SUNXI_LCDC_Y(mode->vsync_len),
862 &lcdc->tcon1_timing_sync);
864 if (use_portd_hvsync) {
865 sunxi_gpio_set_cfgpin(SUNXI_GPD(26), SUNXI_GPD_LCD0);
866 sunxi_gpio_set_cfgpin(SUNXI_GPD(27), SUNXI_GPD_LCD0);
869 if (mode->sync & FB_SYNC_HOR_HIGH_ACT)
870 val |= SUNXI_LCDC_TCON_HSYNC_MASK;
871 if (mode->sync & FB_SYNC_VERT_HIGH_ACT)
872 val |= SUNXI_LCDC_TCON_VSYNC_MASK;
873 writel(val, &lcdc->tcon1_io_polarity);
875 clrbits_le32(&lcdc->tcon1_io_tristate,
876 SUNXI_LCDC_TCON_VSYNC_MASK |
877 SUNXI_LCDC_TCON_HSYNC_MASK);
880 #ifdef CONFIG_MACH_SUN5I
881 if (sunxi_is_composite())
882 clrsetbits_le32(&lcdc->mux_ctrl, SUNXI_LCDC_MUX_CTRL_SRC0_MASK,
883 SUNXI_LCDC_MUX_CTRL_SRC0(1));
886 sunxi_lcdc_pll_set(1, mode->pixclock_khz, clk_div, clk_double);
888 #endif /* CONFIG_VIDEO_HDMI || defined CONFIG_VIDEO_VGA || CONFIG_VIDEO_COMPOSITE */
890 #ifdef CONFIG_VIDEO_HDMI
892 static void sunxi_hdmi_setup_info_frames(const struct ctfb_res_modes *mode)
894 struct sunxi_hdmi_reg * const hdmi =
895 (struct sunxi_hdmi_reg *)SUNXI_HDMI_BASE;
897 u8 avi_info_frame[17] = {
898 0x82, 0x02, 0x0d, 0x00, 0x12, 0x00, 0x88, 0x00,
899 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
902 u8 vendor_info_frame[19] = {
903 0x81, 0x01, 0x06, 0x29, 0x03, 0x0c, 0x00, 0x40,
904 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
909 if (mode->pixclock_khz <= 27000)
910 avi_info_frame[5] = 0x40; /* SD-modes, ITU601 colorspace */
912 avi_info_frame[5] = 0x80; /* HD-modes, ITU709 colorspace */
914 if (mode->xres * 100 / mode->yres < 156)
915 avi_info_frame[5] |= 0x18; /* 4 : 3 */
917 avi_info_frame[5] |= 0x28; /* 16 : 9 */
919 for (i = 0; i < ARRAY_SIZE(avi_info_frame); i++)
920 checksum += avi_info_frame[i];
922 avi_info_frame[3] = 0x100 - checksum;
924 for (i = 0; i < ARRAY_SIZE(avi_info_frame); i++)
925 writeb(avi_info_frame[i], &hdmi->avi_info_frame[i]);
927 writel(SUNXI_HDMI_QCP_PACKET0, &hdmi->qcp_packet0);
928 writel(SUNXI_HDMI_QCP_PACKET1, &hdmi->qcp_packet1);
930 for (i = 0; i < ARRAY_SIZE(vendor_info_frame); i++)
931 writeb(vendor_info_frame[i], &hdmi->vendor_info_frame[i]);
933 writel(SUNXI_HDMI_PKT_CTRL0, &hdmi->pkt_ctrl0);
934 writel(SUNXI_HDMI_PKT_CTRL1, &hdmi->pkt_ctrl1);
936 setbits_le32(&hdmi->video_ctrl, SUNXI_HDMI_VIDEO_CTRL_HDMI);
939 static void sunxi_hdmi_mode_set(const struct ctfb_res_modes *mode,
940 int clk_div, int clk_double)
942 struct sunxi_hdmi_reg * const hdmi =
943 (struct sunxi_hdmi_reg *)SUNXI_HDMI_BASE;
946 /* Write clear interrupt status bits */
947 writel(SUNXI_HDMI_IRQ_STATUS_BITS, &hdmi->irq);
949 if (sunxi_display.monitor == sunxi_monitor_hdmi)
950 sunxi_hdmi_setup_info_frames(mode);
952 /* Set input sync enable */
953 writel(SUNXI_HDMI_UNKNOWN_INPUT_SYNC, &hdmi->unknown);
955 /* Init various registers, select pll3 as clock source */
956 writel(SUNXI_HDMI_VIDEO_POL_TX_CLK, &hdmi->video_polarity);
957 writel(SUNXI_HDMI_PAD_CTRL0_RUN, &hdmi->pad_ctrl0);
958 writel(SUNXI_HDMI_PAD_CTRL1, &hdmi->pad_ctrl1);
959 writel(SUNXI_HDMI_PLL_CTRL, &hdmi->pll_ctrl);
960 writel(SUNXI_HDMI_PLL_DBG0_PLL3, &hdmi->pll_dbg0);
962 /* Setup clk div and doubler */
963 clrsetbits_le32(&hdmi->pll_ctrl, SUNXI_HDMI_PLL_CTRL_DIV_MASK,
964 SUNXI_HDMI_PLL_CTRL_DIV(clk_div));
966 setbits_le32(&hdmi->pad_ctrl1, SUNXI_HDMI_PAD_CTRL1_HALVE);
968 /* Setup timing registers */
969 writel(SUNXI_HDMI_Y(mode->yres) | SUNXI_HDMI_X(mode->xres),
972 x = mode->hsync_len + mode->left_margin;
973 y = mode->vsync_len + mode->upper_margin;
974 writel(SUNXI_HDMI_Y(y) | SUNXI_HDMI_X(x), &hdmi->video_bp);
976 x = mode->right_margin;
977 y = mode->lower_margin;
978 writel(SUNXI_HDMI_Y(y) | SUNXI_HDMI_X(x), &hdmi->video_fp);
982 writel(SUNXI_HDMI_Y(y) | SUNXI_HDMI_X(x), &hdmi->video_spw);
984 if (mode->sync & FB_SYNC_HOR_HIGH_ACT)
985 setbits_le32(&hdmi->video_polarity, SUNXI_HDMI_VIDEO_POL_HOR);
987 if (mode->sync & FB_SYNC_VERT_HIGH_ACT)
988 setbits_le32(&hdmi->video_polarity, SUNXI_HDMI_VIDEO_POL_VER);
991 static void sunxi_hdmi_enable(void)
993 struct sunxi_hdmi_reg * const hdmi =
994 (struct sunxi_hdmi_reg *)SUNXI_HDMI_BASE;
997 setbits_le32(&hdmi->video_ctrl, SUNXI_HDMI_VIDEO_CTRL_ENABLE);
1000 #endif /* CONFIG_VIDEO_HDMI */
1002 #if defined CONFIG_VIDEO_VGA || defined CONFIG_VIDEO_COMPOSITE
1004 static void sunxi_tvencoder_mode_set(void)
1006 struct sunxi_ccm_reg * const ccm =
1007 (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
1008 struct sunxi_tve_reg * const tve =
1009 (struct sunxi_tve_reg *)SUNXI_TVE0_BASE;
1012 setbits_le32(&ccm->lcd0_ch0_clk_cfg, CCM_LCD_CH0_CTRL_TVE_RST);
1014 setbits_le32(&ccm->ahb_gate1, 1 << AHB_GATE_OFFSET_TVE0);
1016 switch (sunxi_display.monitor) {
1017 case sunxi_monitor_vga:
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), &tve->gctrl);
1021 writel(SUNXI_TVE_CFG0_VGA, &tve->cfg0);
1022 writel(SUNXI_TVE_DAC_CFG0_VGA, &tve->dac_cfg0);
1023 writel(SUNXI_TVE_UNKNOWN1_VGA, &tve->unknown1);
1025 case sunxi_monitor_composite_pal_nc:
1026 writel(SUNXI_TVE_CHROMA_FREQ_PAL_NC, &tve->chroma_freq);
1028 case sunxi_monitor_composite_pal:
1029 writel(SUNXI_TVE_GCTRL_DAC_INPUT(0, 1) |
1030 SUNXI_TVE_GCTRL_DAC_INPUT(1, 2) |
1031 SUNXI_TVE_GCTRL_DAC_INPUT(2, 3) |
1032 SUNXI_TVE_GCTRL_DAC_INPUT(3, 4), &tve->gctrl);
1033 writel(SUNXI_TVE_CFG0_PAL, &tve->cfg0);
1034 writel(SUNXI_TVE_DAC_CFG0_COMPOSITE, &tve->dac_cfg0);
1035 writel(SUNXI_TVE_FILTER_COMPOSITE, &tve->filter);
1036 writel(SUNXI_TVE_PORCH_NUM_PAL, &tve->porch_num);
1037 writel(SUNXI_TVE_LINE_NUM_PAL, &tve->line_num);
1038 writel(SUNXI_TVE_BLANK_BLACK_LEVEL_PAL, &tve->blank_black_level);
1039 writel(SUNXI_TVE_UNKNOWN1_COMPOSITE, &tve->unknown1);
1040 writel(SUNXI_TVE_CBR_LEVEL_PAL, &tve->cbr_level);
1041 writel(SUNXI_TVE_BURST_WIDTH_COMPOSITE, &tve->burst_width);
1042 writel(SUNXI_TVE_UNKNOWN2_PAL, &tve->unknown2);
1043 writel(SUNXI_TVE_ACTIVE_NUM_COMPOSITE, &tve->active_num);
1044 writel(SUNXI_TVE_CHROMA_BW_GAIN_COMP, &tve->chroma_bw_gain);
1045 writel(SUNXI_TVE_NOTCH_WIDTH_COMPOSITE, &tve->notch_width);
1046 writel(SUNXI_TVE_RESYNC_NUM_PAL, &tve->resync_num);
1047 writel(SUNXI_TVE_SLAVE_PARA_COMPOSITE, &tve->slave_para);
1049 case sunxi_monitor_composite_pal_m:
1050 writel(SUNXI_TVE_CHROMA_FREQ_PAL_M, &tve->chroma_freq);
1051 writel(SUNXI_TVE_COLOR_BURST_PAL_M, &tve->color_burst);
1053 case sunxi_monitor_composite_ntsc:
1054 writel(SUNXI_TVE_GCTRL_DAC_INPUT(0, 1) |
1055 SUNXI_TVE_GCTRL_DAC_INPUT(1, 2) |
1056 SUNXI_TVE_GCTRL_DAC_INPUT(2, 3) |
1057 SUNXI_TVE_GCTRL_DAC_INPUT(3, 4), &tve->gctrl);
1058 writel(SUNXI_TVE_CFG0_NTSC, &tve->cfg0);
1059 writel(SUNXI_TVE_DAC_CFG0_COMPOSITE, &tve->dac_cfg0);
1060 writel(SUNXI_TVE_FILTER_COMPOSITE, &tve->filter);
1061 writel(SUNXI_TVE_PORCH_NUM_NTSC, &tve->porch_num);
1062 writel(SUNXI_TVE_LINE_NUM_NTSC, &tve->line_num);
1063 writel(SUNXI_TVE_BLANK_BLACK_LEVEL_NTSC, &tve->blank_black_level);
1064 writel(SUNXI_TVE_UNKNOWN1_COMPOSITE, &tve->unknown1);
1065 writel(SUNXI_TVE_CBR_LEVEL_NTSC, &tve->cbr_level);
1066 writel(SUNXI_TVE_BURST_PHASE_NTSC, &tve->burst_phase);
1067 writel(SUNXI_TVE_BURST_WIDTH_COMPOSITE, &tve->burst_width);
1068 writel(SUNXI_TVE_UNKNOWN2_NTSC, &tve->unknown2);
1069 writel(SUNXI_TVE_SYNC_VBI_LEVEL_NTSC, &tve->sync_vbi_level);
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_NTSC, &tve->resync_num);
1074 writel(SUNXI_TVE_SLAVE_PARA_COMPOSITE, &tve->slave_para);
1076 case sunxi_monitor_none:
1077 case sunxi_monitor_dvi:
1078 case sunxi_monitor_hdmi:
1079 case sunxi_monitor_lcd:
1084 static void sunxi_tvencoder_enable(void)
1086 struct sunxi_tve_reg * const tve =
1087 (struct sunxi_tve_reg *)SUNXI_TVE0_BASE;
1089 setbits_le32(&tve->gctrl, SUNXI_TVE_GCTRL_ENABLE);
1092 #endif /* CONFIG_VIDEO_VGA || defined CONFIG_VIDEO_COMPOSITE */
1094 static void sunxi_drc_init(void)
1096 #ifdef CONFIG_SUNXI_GEN_SUN6I
1097 struct sunxi_ccm_reg * const ccm =
1098 (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
1100 /* On sun6i the drc must be clocked even when in pass-through mode */
1101 #ifdef CONFIG_MACH_SUN8I_A33
1102 setbits_le32(&ccm->ahb_reset1_cfg, 1 << AHB_RESET_OFFSET_SAT);
1104 setbits_le32(&ccm->ahb_reset1_cfg, 1 << AHB_RESET_OFFSET_DRC0);
1105 clock_set_de_mod_clock(&ccm->iep_drc0_clk_cfg, 300000000);
1109 #ifdef CONFIG_VIDEO_VGA_VIA_LCD
1110 static void sunxi_vga_external_dac_enable(void)
1114 pin = sunxi_name_to_gpio(CONFIG_VIDEO_VGA_EXTERNAL_DAC_EN);
1116 gpio_request(pin, "vga_enable");
1117 gpio_direction_output(pin, 1);
1120 #endif /* CONFIG_VIDEO_VGA_VIA_LCD */
1122 #ifdef CONFIG_VIDEO_LCD_SSD2828
1123 static int sunxi_ssd2828_init(const struct ctfb_res_modes *mode)
1125 struct ssd2828_config cfg = {
1126 .csx_pin = name_to_gpio(CONFIG_VIDEO_LCD_SPI_CS),
1127 .sck_pin = name_to_gpio(CONFIG_VIDEO_LCD_SPI_SCLK),
1128 .sdi_pin = name_to_gpio(CONFIG_VIDEO_LCD_SPI_MOSI),
1129 .sdo_pin = name_to_gpio(CONFIG_VIDEO_LCD_SPI_MISO),
1130 .reset_pin = name_to_gpio(CONFIG_VIDEO_LCD_SSD2828_RESET),
1131 .ssd2828_tx_clk_khz = CONFIG_VIDEO_LCD_SSD2828_TX_CLK * 1000,
1132 .ssd2828_color_depth = 24,
1133 #ifdef CONFIG_VIDEO_LCD_PANEL_MIPI_4_LANE_513_MBPS_VIA_SSD2828
1134 .mipi_dsi_number_of_data_lanes = 4,
1135 .mipi_dsi_bitrate_per_data_lane_mbps = 513,
1136 .mipi_dsi_delay_after_exit_sleep_mode_ms = 100,
1137 .mipi_dsi_delay_after_set_display_on_ms = 200
1139 #error MIPI LCD panel needs configuration parameters
1143 if (cfg.csx_pin == -1 || cfg.sck_pin == -1 || cfg.sdi_pin == -1) {
1144 printf("SSD2828: SPI pins are not properly configured\n");
1147 if (cfg.reset_pin == -1) {
1148 printf("SSD2828: Reset pin is not properly configured\n");
1152 return ssd2828_init(&cfg, mode);
1154 #endif /* CONFIG_VIDEO_LCD_SSD2828 */
1156 static void sunxi_engines_init(void)
1158 sunxi_composer_init();
1163 static void sunxi_mode_set(const struct ctfb_res_modes *mode,
1164 unsigned int address)
1166 int __maybe_unused clk_div, clk_double;
1168 switch (sunxi_display.monitor) {
1169 case sunxi_monitor_none:
1171 case sunxi_monitor_dvi:
1172 case sunxi_monitor_hdmi:
1173 #ifdef CONFIG_VIDEO_HDMI
1174 sunxi_composer_mode_set(mode, address);
1175 sunxi_lcdc_tcon1_mode_set(mode, &clk_div, &clk_double, 0);
1176 sunxi_hdmi_mode_set(mode, clk_div, clk_double);
1177 sunxi_composer_enable();
1178 sunxi_lcdc_enable();
1179 sunxi_hdmi_enable();
1182 case sunxi_monitor_lcd:
1183 sunxi_lcdc_panel_enable();
1184 if (IS_ENABLED(CONFIG_VIDEO_LCD_HITACHI_TX18D42VM)) {
1185 mdelay(50); /* Wait for lcd controller power on */
1186 hitachi_tx18d42vm_init();
1188 if (IS_ENABLED(CONFIG_VIDEO_LCD_TL059WV5C0)) {
1189 unsigned int orig_i2c_bus = i2c_get_bus_num();
1190 i2c_set_bus_num(CONFIG_VIDEO_LCD_I2C_BUS);
1191 i2c_reg_write(0x5c, 0x04, 0x42); /* Turn on the LCD */
1192 i2c_set_bus_num(orig_i2c_bus);
1194 sunxi_composer_mode_set(mode, address);
1195 sunxi_lcdc_tcon0_mode_set(mode, false);
1196 sunxi_composer_enable();
1197 sunxi_lcdc_enable();
1198 #ifdef CONFIG_VIDEO_LCD_SSD2828
1199 sunxi_ssd2828_init(mode);
1201 sunxi_lcdc_backlight_enable();
1203 case sunxi_monitor_vga:
1204 #ifdef CONFIG_VIDEO_VGA
1205 sunxi_composer_mode_set(mode, address);
1206 sunxi_lcdc_tcon1_mode_set(mode, &clk_div, &clk_double, 1);
1207 sunxi_tvencoder_mode_set();
1208 sunxi_composer_enable();
1209 sunxi_lcdc_enable();
1210 sunxi_tvencoder_enable();
1211 #elif defined CONFIG_VIDEO_VGA_VIA_LCD
1212 sunxi_composer_mode_set(mode, address);
1213 sunxi_lcdc_tcon0_mode_set(mode, true);
1214 sunxi_composer_enable();
1215 sunxi_lcdc_enable();
1216 sunxi_vga_external_dac_enable();
1219 case sunxi_monitor_composite_pal:
1220 case sunxi_monitor_composite_ntsc:
1221 case sunxi_monitor_composite_pal_m:
1222 case sunxi_monitor_composite_pal_nc:
1223 #ifdef CONFIG_VIDEO_COMPOSITE
1224 sunxi_composer_mode_set(mode, address);
1225 sunxi_lcdc_tcon1_mode_set(mode, &clk_div, &clk_double, 0);
1226 sunxi_tvencoder_mode_set();
1227 sunxi_composer_enable();
1228 sunxi_lcdc_enable();
1229 sunxi_tvencoder_enable();
1235 static const char *sunxi_get_mon_desc(enum sunxi_monitor monitor)
1238 case sunxi_monitor_none: return "none";
1239 case sunxi_monitor_dvi: return "dvi";
1240 case sunxi_monitor_hdmi: return "hdmi";
1241 case sunxi_monitor_lcd: return "lcd";
1242 case sunxi_monitor_vga: return "vga";
1243 case sunxi_monitor_composite_pal: return "composite-pal";
1244 case sunxi_monitor_composite_ntsc: return "composite-ntsc";
1245 case sunxi_monitor_composite_pal_m: return "composite-pal-m";
1246 case sunxi_monitor_composite_pal_nc: return "composite-pal-nc";
1248 return NULL; /* never reached */
1251 ulong board_get_usable_ram_top(ulong total_size)
1253 return gd->ram_top - CONFIG_SUNXI_MAX_FB_SIZE;
1256 static bool sunxi_has_hdmi(void)
1258 #ifdef CONFIG_VIDEO_HDMI
1265 static bool sunxi_has_lcd(void)
1267 char *lcd_mode = CONFIG_VIDEO_LCD_MODE;
1269 return lcd_mode[0] != 0;
1272 static bool sunxi_has_vga(void)
1274 #if defined CONFIG_VIDEO_VGA || defined CONFIG_VIDEO_VGA_VIA_LCD
1281 static bool sunxi_has_composite(void)
1283 #ifdef CONFIG_VIDEO_COMPOSITE
1290 static enum sunxi_monitor sunxi_get_default_mon(bool allow_hdmi)
1292 if (allow_hdmi && sunxi_has_hdmi())
1293 return sunxi_monitor_dvi;
1294 else if (sunxi_has_lcd())
1295 return sunxi_monitor_lcd;
1296 else if (sunxi_has_vga())
1297 return sunxi_monitor_vga;
1298 else if (sunxi_has_composite())
1299 return sunxi_monitor_composite_pal;
1301 return sunxi_monitor_none;
1304 void *video_hw_init(void)
1306 static GraphicDevice *graphic_device = &sunxi_display.graphic_device;
1307 const struct ctfb_res_modes *mode;
1308 struct ctfb_res_modes custom;
1309 const char *options;
1310 #ifdef CONFIG_VIDEO_HDMI
1311 int ret, hpd, hpd_delay, edid;
1313 int i, overscan_offset, overscan_x, overscan_y;
1314 unsigned int fb_dma_addr;
1316 char *lcd_mode = CONFIG_VIDEO_LCD_MODE;
1318 memset(&sunxi_display, 0, sizeof(struct sunxi_display));
1320 video_get_ctfb_res_modes(RES_MODE_1024x768, 24, &mode,
1321 &sunxi_display.depth, &options);
1322 #ifdef CONFIG_VIDEO_HDMI
1323 hpd = video_get_option_int(options, "hpd", 1);
1324 hpd_delay = video_get_option_int(options, "hpd_delay", 500);
1325 edid = video_get_option_int(options, "edid", 1);
1327 overscan_x = video_get_option_int(options, "overscan_x", -1);
1328 overscan_y = video_get_option_int(options, "overscan_y", -1);
1329 sunxi_display.monitor = sunxi_get_default_mon(true);
1330 video_get_option_string(options, "monitor", mon, sizeof(mon),
1331 sunxi_get_mon_desc(sunxi_display.monitor));
1332 for (i = 0; i <= SUNXI_MONITOR_LAST; i++) {
1333 if (strcmp(mon, sunxi_get_mon_desc(i)) == 0) {
1334 sunxi_display.monitor = i;
1338 if (i > SUNXI_MONITOR_LAST)
1339 printf("Unknown monitor: '%s', falling back to '%s'\n",
1340 mon, sunxi_get_mon_desc(sunxi_display.monitor));
1342 #ifdef CONFIG_VIDEO_HDMI
1343 /* If HDMI/DVI is selected do HPD & EDID, and handle fallback */
1344 if (sunxi_display.monitor == sunxi_monitor_dvi ||
1345 sunxi_display.monitor == sunxi_monitor_hdmi) {
1346 /* Always call hdp_detect, as it also enables clocks, etc. */
1347 ret = sunxi_hdmi_hpd_detect(hpd_delay);
1349 printf("HDMI connected: ");
1350 if (edid && sunxi_hdmi_edid_get_mode(&custom) == 0)
1353 sunxi_hdmi_shutdown();
1354 sunxi_display.monitor = sunxi_get_default_mon(false);
1355 } /* else continue with hdmi/dvi without a cable connected */
1359 switch (sunxi_display.monitor) {
1360 case sunxi_monitor_none:
1362 case sunxi_monitor_dvi:
1363 case sunxi_monitor_hdmi:
1364 if (!sunxi_has_hdmi()) {
1365 printf("HDMI/DVI not supported on this board\n");
1366 sunxi_display.monitor = sunxi_monitor_none;
1370 case sunxi_monitor_lcd:
1371 if (!sunxi_has_lcd()) {
1372 printf("LCD not supported on this board\n");
1373 sunxi_display.monitor = sunxi_monitor_none;
1376 sunxi_display.depth = video_get_params(&custom, lcd_mode);
1379 case sunxi_monitor_vga:
1380 if (!sunxi_has_vga()) {
1381 printf("VGA not supported on this board\n");
1382 sunxi_display.monitor = sunxi_monitor_none;
1385 sunxi_display.depth = 18;
1387 case sunxi_monitor_composite_pal:
1388 case sunxi_monitor_composite_ntsc:
1389 case sunxi_monitor_composite_pal_m:
1390 case sunxi_monitor_composite_pal_nc:
1391 if (!sunxi_has_composite()) {
1392 printf("Composite video not supported on this board\n");
1393 sunxi_display.monitor = sunxi_monitor_none;
1396 if (sunxi_display.monitor == sunxi_monitor_composite_pal ||
1397 sunxi_display.monitor == sunxi_monitor_composite_pal_nc)
1398 mode = &composite_video_modes[0];
1400 mode = &composite_video_modes[1];
1401 sunxi_display.depth = 24;
1405 /* Yes these defaults are quite high, overscan on composite sucks... */
1406 if (overscan_x == -1)
1407 overscan_x = sunxi_is_composite() ? 32 : 0;
1408 if (overscan_y == -1)
1409 overscan_y = sunxi_is_composite() ? 20 : 0;
1411 sunxi_display.fb_size =
1412 (mode->xres * mode->yres * 4 + 0xfff) & ~0xfff;
1413 overscan_offset = (overscan_y * mode->xres + overscan_x) * 4;
1414 /* We want to keep the fb_base for simplefb page aligned, where as
1415 * the sunxi dma engines will happily accept an unaligned address. */
1416 if (overscan_offset)
1417 sunxi_display.fb_size += 0x1000;
1419 if (sunxi_display.fb_size > CONFIG_SUNXI_MAX_FB_SIZE) {
1420 printf("Error need %dkB for fb, but only %dkB is reserved\n",
1421 sunxi_display.fb_size >> 10,
1422 CONFIG_SUNXI_MAX_FB_SIZE >> 10);
1426 printf("Setting up a %dx%d%s %s console (overscan %dx%d)\n",
1427 mode->xres, mode->yres,
1428 (mode->vmode == FB_VMODE_INTERLACED) ? "i" : "",
1429 sunxi_get_mon_desc(sunxi_display.monitor),
1430 overscan_x, overscan_y);
1432 gd->fb_base = gd->bd->bi_dram[0].start +
1433 gd->bd->bi_dram[0].size - sunxi_display.fb_size;
1434 sunxi_engines_init();
1436 fb_dma_addr = gd->fb_base - CONFIG_SYS_SDRAM_BASE;
1437 sunxi_display.fb_addr = gd->fb_base;
1438 if (overscan_offset) {
1439 fb_dma_addr += 0x1000 - (overscan_offset & 0xfff);
1440 sunxi_display.fb_addr += (overscan_offset + 0xfff) & ~0xfff;
1441 memset((void *)gd->fb_base, 0, sunxi_display.fb_size);
1442 flush_cache(gd->fb_base, sunxi_display.fb_size);
1444 sunxi_mode_set(mode, fb_dma_addr);
1447 * These are the only members of this structure that are used. All the
1448 * others are driver specific. The pitch is stored in plnSizeX.
1450 graphic_device->frameAdrs = sunxi_display.fb_addr;
1451 graphic_device->gdfIndex = GDF_32BIT_X888RGB;
1452 graphic_device->gdfBytesPP = 4;
1453 graphic_device->winSizeX = mode->xres - 2 * overscan_x;
1454 graphic_device->winSizeY = mode->yres - 2 * overscan_y;
1455 graphic_device->plnSizeX = mode->xres * graphic_device->gdfBytesPP;
1457 return graphic_device;
1463 #if defined(CONFIG_OF_BOARD_SETUP) && defined(CONFIG_VIDEO_DT_SIMPLEFB)
1464 int sunxi_simplefb_setup(void *blob)
1466 static GraphicDevice *graphic_device = &sunxi_display.graphic_device;
1469 const char *pipeline = NULL;
1471 #ifdef CONFIG_MACH_SUN4I
1472 #define PIPELINE_PREFIX "de_fe0-"
1474 #define PIPELINE_PREFIX
1477 switch (sunxi_display.monitor) {
1478 case sunxi_monitor_none:
1480 case sunxi_monitor_dvi:
1481 case sunxi_monitor_hdmi:
1482 pipeline = PIPELINE_PREFIX "de_be0-lcd0-hdmi";
1484 case sunxi_monitor_lcd:
1485 pipeline = PIPELINE_PREFIX "de_be0-lcd0";
1487 case sunxi_monitor_vga:
1488 #ifdef CONFIG_VIDEO_VGA
1489 pipeline = PIPELINE_PREFIX "de_be0-lcd0-tve0";
1490 #elif defined CONFIG_VIDEO_VGA_VIA_LCD
1491 pipeline = PIPELINE_PREFIX "de_be0-lcd0";
1494 case sunxi_monitor_composite_pal:
1495 case sunxi_monitor_composite_ntsc:
1496 case sunxi_monitor_composite_pal_m:
1497 case sunxi_monitor_composite_pal_nc:
1498 pipeline = PIPELINE_PREFIX "de_be0-lcd0-tve0";
1502 /* Find a prefilled simpefb node, matching out pipeline config */
1503 offset = fdt_node_offset_by_compatible(blob, -1,
1504 "allwinner,simple-framebuffer");
1505 while (offset >= 0) {
1506 ret = fdt_find_string(blob, offset, "allwinner,pipeline",
1510 offset = fdt_node_offset_by_compatible(blob, offset,
1511 "allwinner,simple-framebuffer");
1514 eprintf("Cannot setup simplefb: node not found\n");
1515 return 0; /* Keep older kernels working */
1519 * Do not report the framebuffer as free RAM to the OS, note we cannot
1520 * use fdt_add_mem_rsv() here, because then it is still seen as RAM,
1521 * and e.g. Linux refuses to iomap RAM on ARM, see:
1522 * linux/arch/arm/mm/ioremap.c around line 301.
1524 start = gd->bd->bi_dram[0].start;
1525 size = gd->bd->bi_dram[0].size - sunxi_display.fb_size;
1526 ret = fdt_fixup_memory_banks(blob, &start, &size, 1);
1528 eprintf("Cannot setup simplefb: Error reserving memory\n");
1532 ret = fdt_setup_simplefb_node(blob, offset, sunxi_display.fb_addr,
1533 graphic_device->winSizeX, graphic_device->winSizeY,
1534 graphic_device->plnSizeX, "x8r8g8b8");
1536 eprintf("Cannot setup simplefb: Error setting properties\n");
1540 #endif /* CONFIG_OF_BOARD_SETUP && CONFIG_VIDEO_DT_SIMPLEFB */