Merge tag 'u-boot-imx-20211020' of https://source.denx.de/u-boot/custodians/u-boot-imx
[platform/kernel/u-boot.git] / drivers / video / sunxi / sunxi_display.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Display driver for Allwinner SoCs.
4  *
5  * (C) Copyright 2013-2014 Luc Verhaegen <libv@skynet.be>
6  * (C) Copyright 2014-2015 Hans de Goede <hdegoede@redhat.com>
7  */
8
9 #include <common.h>
10 #include <display.h>
11 #include <dm.h>
12 #include <cpu_func.h>
13 #include <efi_loader.h>
14 #include <init.h>
15 #include <time.h>
16 #include <linux/delay.h>
17
18 #include <asm/arch/clock.h>
19 #include <asm/arch/display.h>
20 #include <asm/arch/lcdc.h>
21 #include <asm/arch/pwm.h>
22 #include <asm/arch/tve.h>
23 #include <asm/global_data.h>
24 #include <asm/gpio.h>
25 #include <asm/io.h>
26 #include <axp_pmic.h>
27 #include <errno.h>
28 #include <fdtdec.h>
29 #include <fdt_support.h>
30 #include <i2c.h>
31 #include <malloc.h>
32 #include <video.h>
33 #include <video_fb.h>
34 #include <dm/uclass-internal.h>
35 #include "../videomodes.h"
36 #include "../anx9804.h"
37 #include "../hitachi_tx18d42vm_lcd.h"
38 #include "../ssd2828.h"
39 #include "simplefb_common.h"
40
41 #ifdef CONFIG_VIDEO_LCD_BL_PWM_ACTIVE_LOW
42 #define PWM_ON 0
43 #define PWM_OFF 1
44 #else
45 #define PWM_ON 1
46 #define PWM_OFF 0
47 #endif
48
49 DECLARE_GLOBAL_DATA_PTR;
50
51 /* Maximum LCD size we support */
52 #define LCD_MAX_WIDTH           3840
53 #define LCD_MAX_HEIGHT          2160
54 #define LCD_MAX_LOG2_BPP        VIDEO_BPP32
55
56 enum sunxi_monitor {
57         sunxi_monitor_none,
58         sunxi_monitor_dvi,
59         sunxi_monitor_hdmi,
60         sunxi_monitor_lcd,
61         sunxi_monitor_vga,
62         sunxi_monitor_composite_pal,
63         sunxi_monitor_composite_ntsc,
64         sunxi_monitor_composite_pal_m,
65         sunxi_monitor_composite_pal_nc,
66 };
67 #define SUNXI_MONITOR_LAST sunxi_monitor_composite_pal_nc
68
69 struct sunxi_display_priv {
70         enum sunxi_monitor monitor;
71         unsigned int depth;
72         unsigned int fb_addr;
73         unsigned int fb_size;
74 };
75
76 const struct ctfb_res_modes composite_video_modes[2] = {
77         /*  x     y  hz  pixclk ps/kHz   le   ri  up  lo   hs vs  s  vmode */
78         { 720,  576, 50, 37037,  27000, 137,   5, 20, 27,   2, 2, 0, FB_VMODE_INTERLACED },
79         { 720,  480, 60, 37037,  27000, 116,  20, 16, 27,   2, 2, 0, FB_VMODE_INTERLACED },
80 };
81
82 #ifdef CONFIG_VIDEO_HDMI
83
84 /*
85  * Wait up to 200ms for value to be set in given part of reg.
86  */
87 static int await_completion(u32 *reg, u32 mask, u32 val)
88 {
89         unsigned long tmo = timer_get_us() + 200000;
90
91         while ((readl(reg) & mask) != val) {
92                 if (timer_get_us() > tmo) {
93                         printf("DDC: timeout reading EDID\n");
94                         return -ETIME;
95                 }
96         }
97         return 0;
98 }
99
100 static int sunxi_hdmi_hpd_detect(int hpd_delay)
101 {
102         struct sunxi_ccm_reg * const ccm =
103                 (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
104         struct sunxi_hdmi_reg * const hdmi =
105                 (struct sunxi_hdmi_reg *)SUNXI_HDMI_BASE;
106         unsigned long tmo = timer_get_us() + hpd_delay * 1000;
107
108         /* Set pll3 to 300MHz */
109         clock_set_pll3(300000000);
110
111         /* Set hdmi parent to pll3 */
112         clrsetbits_le32(&ccm->hdmi_clk_cfg, CCM_HDMI_CTRL_PLL_MASK,
113                         CCM_HDMI_CTRL_PLL3);
114
115         /* Set ahb gating to pass */
116 #ifdef CONFIG_SUNXI_GEN_SUN6I
117         setbits_le32(&ccm->ahb_reset1_cfg, 1 << AHB_RESET_OFFSET_HDMI);
118 #endif
119         setbits_le32(&ccm->ahb_gate1, 1 << AHB_GATE_OFFSET_HDMI);
120
121         /* Clock on */
122         setbits_le32(&ccm->hdmi_clk_cfg, CCM_HDMI_CTRL_GATE);
123
124         writel(SUNXI_HDMI_CTRL_ENABLE, &hdmi->ctrl);
125         writel(SUNXI_HDMI_PAD_CTRL0_HDP, &hdmi->pad_ctrl0);
126
127         /* Enable PLLs for eventual DDC */
128         writel(SUNXI_HDMI_PAD_CTRL1 | SUNXI_HDMI_PAD_CTRL1_HALVE,
129                &hdmi->pad_ctrl1);
130         writel(SUNXI_HDMI_PLL_CTRL | SUNXI_HDMI_PLL_CTRL_DIV(15),
131                &hdmi->pll_ctrl);
132         writel(SUNXI_HDMI_PLL_DBG0_PLL3, &hdmi->pll_dbg0);
133
134         while (timer_get_us() < tmo) {
135                 if (readl(&hdmi->hpd) & SUNXI_HDMI_HPD_DETECT)
136                         return 1;
137         }
138
139         return 0;
140 }
141
142 static void sunxi_hdmi_shutdown(void)
143 {
144         struct sunxi_ccm_reg * const ccm =
145                 (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
146         struct sunxi_hdmi_reg * const hdmi =
147                 (struct sunxi_hdmi_reg *)SUNXI_HDMI_BASE;
148
149         clrbits_le32(&hdmi->ctrl, SUNXI_HDMI_CTRL_ENABLE);
150         clrbits_le32(&ccm->hdmi_clk_cfg, CCM_HDMI_CTRL_GATE);
151         clrbits_le32(&ccm->ahb_gate1, 1 << AHB_GATE_OFFSET_HDMI);
152 #ifdef CONFIG_SUNXI_GEN_SUN6I
153         clrbits_le32(&ccm->ahb_reset1_cfg, 1 << AHB_RESET_OFFSET_HDMI);
154 #endif
155         clock_set_pll3(0);
156 }
157
158 static int sunxi_hdmi_ddc_do_command(u32 cmnd, int offset, int n)
159 {
160         struct sunxi_hdmi_reg * const hdmi =
161                 (struct sunxi_hdmi_reg *)SUNXI_HDMI_BASE;
162
163         setbits_le32(&hdmi->ddc_fifo_ctrl, SUNXI_HDMI_DDC_FIFO_CTRL_CLEAR);
164         writel(SUNXI_HMDI_DDC_ADDR_EDDC_SEGMENT(offset >> 8) |
165                SUNXI_HMDI_DDC_ADDR_EDDC_ADDR |
166                SUNXI_HMDI_DDC_ADDR_OFFSET(offset) |
167                SUNXI_HMDI_DDC_ADDR_SLAVE_ADDR, &hdmi->ddc_addr);
168 #ifndef CONFIG_MACH_SUN6I
169         writel(n, &hdmi->ddc_byte_count);
170         writel(cmnd, &hdmi->ddc_cmnd);
171 #else
172         writel(n << 16 | cmnd, &hdmi->ddc_cmnd);
173 #endif
174         setbits_le32(&hdmi->ddc_ctrl, SUNXI_HMDI_DDC_CTRL_START);
175
176         return await_completion(&hdmi->ddc_ctrl, SUNXI_HMDI_DDC_CTRL_START, 0);
177 }
178
179 static int sunxi_hdmi_ddc_read(int offset, u8 *buf, int count)
180 {
181         struct sunxi_hdmi_reg * const hdmi =
182                 (struct sunxi_hdmi_reg *)SUNXI_HDMI_BASE;
183         int i, n;
184
185         while (count > 0) {
186                 if (count > 16)
187                         n = 16;
188                 else
189                         n = count;
190
191                 if (sunxi_hdmi_ddc_do_command(
192                                 SUNXI_HDMI_DDC_CMND_EXPLICIT_EDDC_READ,
193                                 offset, n))
194                         return -ETIME;
195
196                 for (i = 0; i < n; i++)
197                         *buf++ = readb(&hdmi->ddc_fifo_data);
198
199                 offset += n;
200                 count -= n;
201         }
202
203         return 0;
204 }
205
206 static int sunxi_hdmi_edid_get_block(int block, u8 *buf)
207 {
208         int r, retries = 2;
209
210         do {
211                 r = sunxi_hdmi_ddc_read(block * 128, buf, 128);
212                 if (r)
213                         continue;
214                 r = edid_check_checksum(buf);
215                 if (r) {
216                         printf("EDID block %d: checksum error%s\n",
217                                block, retries ? ", retrying" : "");
218                 }
219         } while (r && retries--);
220
221         return r;
222 }
223
224 static int sunxi_hdmi_edid_get_mode(struct sunxi_display_priv *sunxi_display,
225                                     struct ctfb_res_modes *mode,
226                                     bool verbose_mode)
227 {
228         struct edid1_info edid1;
229         struct edid_cea861_info cea681[4];
230         struct edid_detailed_timing *t =
231                 (struct edid_detailed_timing *)edid1.monitor_details.timing;
232         struct sunxi_hdmi_reg * const hdmi =
233                 (struct sunxi_hdmi_reg *)SUNXI_HDMI_BASE;
234         struct sunxi_ccm_reg * const ccm =
235                 (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
236         int i, r, ext_blocks = 0;
237
238         /* Reset i2c controller */
239         setbits_le32(&ccm->hdmi_clk_cfg, CCM_HDMI_CTRL_DDC_GATE);
240         writel(SUNXI_HMDI_DDC_CTRL_ENABLE |
241                SUNXI_HMDI_DDC_CTRL_SDA_ENABLE |
242                SUNXI_HMDI_DDC_CTRL_SCL_ENABLE |
243                SUNXI_HMDI_DDC_CTRL_RESET, &hdmi->ddc_ctrl);
244         if (await_completion(&hdmi->ddc_ctrl, SUNXI_HMDI_DDC_CTRL_RESET, 0))
245                 return -EIO;
246
247         writel(SUNXI_HDMI_DDC_CLOCK, &hdmi->ddc_clock);
248 #ifndef CONFIG_MACH_SUN6I
249         writel(SUNXI_HMDI_DDC_LINE_CTRL_SDA_ENABLE |
250                SUNXI_HMDI_DDC_LINE_CTRL_SCL_ENABLE, &hdmi->ddc_line_ctrl);
251 #endif
252
253         r = sunxi_hdmi_edid_get_block(0, (u8 *)&edid1);
254         if (r == 0) {
255                 r = edid_check_info(&edid1);
256                 if (r) {
257                         if (verbose_mode)
258                                 printf("EDID: invalid EDID data\n");
259                         r = -EINVAL;
260                 }
261         }
262         if (r == 0) {
263                 ext_blocks = edid1.extension_flag;
264                 if (ext_blocks > 4)
265                         ext_blocks = 4;
266                 for (i = 0; i < ext_blocks; i++) {
267                         if (sunxi_hdmi_edid_get_block(1 + i,
268                                                 (u8 *)&cea681[i]) != 0) {
269                                 ext_blocks = i;
270                                 break;
271                         }
272                 }
273         }
274
275         /* Disable DDC engine, no longer needed */
276         clrbits_le32(&hdmi->ddc_ctrl, SUNXI_HMDI_DDC_CTRL_ENABLE);
277         clrbits_le32(&ccm->hdmi_clk_cfg, CCM_HDMI_CTRL_DDC_GATE);
278
279         if (r)
280                 return r;
281
282         /* We want version 1.3 or 1.2 with detailed timing info */
283         if (edid1.version != 1 || (edid1.revision < 3 &&
284                         !EDID1_INFO_FEATURE_PREFERRED_TIMING_MODE(edid1))) {
285                 printf("EDID: unsupported version %d.%d\n",
286                        edid1.version, edid1.revision);
287                 return -EINVAL;
288         }
289
290         /* Take the first usable detailed timing */
291         for (i = 0; i < 4; i++, t++) {
292                 r = video_edid_dtd_to_ctfb_res_modes(t, mode);
293                 if (r == 0)
294                         break;
295         }
296         if (i == 4) {
297                 printf("EDID: no usable detailed timing found\n");
298                 return -ENOENT;
299         }
300
301         /* Check for basic audio support, if found enable hdmi output */
302         sunxi_display->monitor = sunxi_monitor_dvi;
303         for (i = 0; i < ext_blocks; i++) {
304                 if (cea681[i].extension_tag != EDID_CEA861_EXTENSION_TAG ||
305                     cea681[i].revision < 2)
306                         continue;
307
308                 if (EDID_CEA861_SUPPORTS_BASIC_AUDIO(cea681[i]))
309                         sunxi_display->monitor = sunxi_monitor_hdmi;
310         }
311
312         return 0;
313 }
314
315 #endif /* CONFIG_VIDEO_HDMI */
316
317 #ifdef CONFIG_MACH_SUN4I
318 /*
319  * Testing has shown that on sun4i the display backend engine does not have
320  * deep enough fifo-s causing flickering / tearing in full-hd mode due to
321  * fifo underruns. So on sun4i we use the display frontend engine to do the
322  * dma from memory, as the frontend does have deep enough fifo-s.
323  */
324
325 static const u32 sun4i_vert_coef[32] = {
326         0x00004000, 0x000140ff, 0x00033ffe, 0x00043ffd,
327         0x00063efc, 0xff083dfc, 0x000a3bfb, 0xff0d39fb,
328         0xff0f37fb, 0xff1136fa, 0xfe1433fb, 0xfe1631fb,
329         0xfd192ffb, 0xfd1c2cfb, 0xfd1f29fb, 0xfc2127fc,
330         0xfc2424fc, 0xfc2721fc, 0xfb291ffd, 0xfb2c1cfd,
331         0xfb2f19fd, 0xfb3116fe, 0xfb3314fe, 0xfa3611ff,
332         0xfb370fff, 0xfb390dff, 0xfb3b0a00, 0xfc3d08ff,
333         0xfc3e0600, 0xfd3f0400, 0xfe3f0300, 0xff400100,
334 };
335
336 static const u32 sun4i_horz_coef[64] = {
337         0x40000000, 0x00000000, 0x40fe0000, 0x0000ff03,
338         0x3ffd0000, 0x0000ff05, 0x3ffc0000, 0x0000ff06,
339         0x3efb0000, 0x0000ff08, 0x3dfb0000, 0x0000ff09,
340         0x3bfa0000, 0x0000fe0d, 0x39fa0000, 0x0000fe0f,
341         0x38fa0000, 0x0000fe10, 0x36fa0000, 0x0000fe12,
342         0x33fa0000, 0x0000fd16, 0x31fa0000, 0x0000fd18,
343         0x2ffa0000, 0x0000fd1a, 0x2cfa0000, 0x0000fc1e,
344         0x29fa0000, 0x0000fc21, 0x27fb0000, 0x0000fb23,
345         0x24fb0000, 0x0000fb26, 0x21fb0000, 0x0000fb29,
346         0x1ffc0000, 0x0000fa2b, 0x1cfc0000, 0x0000fa2e,
347         0x19fd0000, 0x0000fa30, 0x16fd0000, 0x0000fa33,
348         0x14fd0000, 0x0000fa35, 0x11fe0000, 0x0000fa37,
349         0x0ffe0000, 0x0000fa39, 0x0dfe0000, 0x0000fa3b,
350         0x0afe0000, 0x0000fa3e, 0x08ff0000, 0x0000fb3e,
351         0x06ff0000, 0x0000fb40, 0x05ff0000, 0x0000fc40,
352         0x03ff0000, 0x0000fd41, 0x01ff0000, 0x0000fe42,
353 };
354
355 static void sunxi_frontend_init(void)
356 {
357         struct sunxi_ccm_reg * const ccm =
358                 (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
359         struct sunxi_de_fe_reg * const de_fe =
360                 (struct sunxi_de_fe_reg *)SUNXI_DE_FE0_BASE;
361         int i;
362
363         /* Clocks on */
364         setbits_le32(&ccm->ahb_gate1, 1 << AHB_GATE_OFFSET_DE_FE0);
365         setbits_le32(&ccm->dram_clk_gate, 1 << CCM_DRAM_GATE_OFFSET_DE_FE0);
366         clock_set_de_mod_clock(&ccm->fe0_clk_cfg, 300000000);
367
368         setbits_le32(&de_fe->enable, SUNXI_DE_FE_ENABLE_EN);
369
370         for (i = 0; i < 32; i++) {
371                 writel(sun4i_horz_coef[2 * i], &de_fe->ch0_horzcoef0[i]);
372                 writel(sun4i_horz_coef[2 * i + 1], &de_fe->ch0_horzcoef1[i]);
373                 writel(sun4i_vert_coef[i], &de_fe->ch0_vertcoef[i]);
374                 writel(sun4i_horz_coef[2 * i], &de_fe->ch1_horzcoef0[i]);
375                 writel(sun4i_horz_coef[2 * i + 1], &de_fe->ch1_horzcoef1[i]);
376                 writel(sun4i_vert_coef[i], &de_fe->ch1_vertcoef[i]);
377         }
378
379         setbits_le32(&de_fe->frame_ctrl, SUNXI_DE_FE_FRAME_CTRL_COEF_RDY);
380 }
381
382 static void sunxi_frontend_mode_set(const struct ctfb_res_modes *mode,
383                                     unsigned int address)
384 {
385         struct sunxi_de_fe_reg * const de_fe =
386                 (struct sunxi_de_fe_reg *)SUNXI_DE_FE0_BASE;
387
388         setbits_le32(&de_fe->bypass, SUNXI_DE_FE_BYPASS_CSC_BYPASS);
389         writel(CONFIG_SYS_SDRAM_BASE + address, &de_fe->ch0_addr);
390         writel(mode->xres * 4, &de_fe->ch0_stride);
391         writel(SUNXI_DE_FE_INPUT_FMT_ARGB8888, &de_fe->input_fmt);
392         writel(SUNXI_DE_FE_OUTPUT_FMT_ARGB8888, &de_fe->output_fmt);
393
394         writel(SUNXI_DE_FE_HEIGHT(mode->yres) | SUNXI_DE_FE_WIDTH(mode->xres),
395                &de_fe->ch0_insize);
396         writel(SUNXI_DE_FE_HEIGHT(mode->yres) | SUNXI_DE_FE_WIDTH(mode->xres),
397                &de_fe->ch0_outsize);
398         writel(SUNXI_DE_FE_FACTOR_INT(1), &de_fe->ch0_horzfact);
399         writel(SUNXI_DE_FE_FACTOR_INT(1), &de_fe->ch0_vertfact);
400
401         writel(SUNXI_DE_FE_HEIGHT(mode->yres) | SUNXI_DE_FE_WIDTH(mode->xres),
402                &de_fe->ch1_insize);
403         writel(SUNXI_DE_FE_HEIGHT(mode->yres) | SUNXI_DE_FE_WIDTH(mode->xres),
404                &de_fe->ch1_outsize);
405         writel(SUNXI_DE_FE_FACTOR_INT(1), &de_fe->ch1_horzfact);
406         writel(SUNXI_DE_FE_FACTOR_INT(1), &de_fe->ch1_vertfact);
407
408         setbits_le32(&de_fe->frame_ctrl, SUNXI_DE_FE_FRAME_CTRL_REG_RDY);
409 }
410
411 static void sunxi_frontend_enable(void)
412 {
413         struct sunxi_de_fe_reg * const de_fe =
414                 (struct sunxi_de_fe_reg *)SUNXI_DE_FE0_BASE;
415
416         setbits_le32(&de_fe->frame_ctrl, SUNXI_DE_FE_FRAME_CTRL_FRM_START);
417 }
418 #else
419 static void sunxi_frontend_init(void) {}
420 static void sunxi_frontend_mode_set(const struct ctfb_res_modes *mode,
421                                     unsigned int address) {}
422 static void sunxi_frontend_enable(void) {}
423 #endif
424
425 static bool sunxi_is_composite(enum sunxi_monitor monitor)
426 {
427         switch (monitor) {
428         case sunxi_monitor_none:
429         case sunxi_monitor_dvi:
430         case sunxi_monitor_hdmi:
431         case sunxi_monitor_lcd:
432         case sunxi_monitor_vga:
433                 return false;
434         case sunxi_monitor_composite_pal:
435         case sunxi_monitor_composite_ntsc:
436         case sunxi_monitor_composite_pal_m:
437         case sunxi_monitor_composite_pal_nc:
438                 return true;
439         }
440
441         return false; /* Never reached */
442 }
443
444 /*
445  * This is the entity that mixes and matches the different layers and inputs.
446  * Allwinner calls it the back-end, but i like composer better.
447  */
448 static void sunxi_composer_init(void)
449 {
450         struct sunxi_ccm_reg * const ccm =
451                 (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
452         struct sunxi_de_be_reg * const de_be =
453                 (struct sunxi_de_be_reg *)SUNXI_DE_BE0_BASE;
454         int i;
455
456         sunxi_frontend_init();
457
458 #ifdef CONFIG_SUNXI_GEN_SUN6I
459         /* Reset off */
460         setbits_le32(&ccm->ahb_reset1_cfg, 1 << AHB_RESET_OFFSET_DE_BE0);
461 #endif
462
463         /* Clocks on */
464         setbits_le32(&ccm->ahb_gate1, 1 << AHB_GATE_OFFSET_DE_BE0);
465 #ifndef CONFIG_MACH_SUN4I /* On sun4i the frontend does the dma */
466         setbits_le32(&ccm->dram_clk_gate, 1 << CCM_DRAM_GATE_OFFSET_DE_BE0);
467 #endif
468         clock_set_de_mod_clock(&ccm->be0_clk_cfg, 300000000);
469
470         /* Engine bug, clear registers after reset */
471         for (i = 0x0800; i < 0x1000; i += 4)
472                 writel(0, SUNXI_DE_BE0_BASE + i);
473
474         setbits_le32(&de_be->mode, SUNXI_DE_BE_MODE_ENABLE);
475 }
476
477 static const u32 sunxi_rgb2yuv_coef[12] = {
478         0x00000107, 0x00000204, 0x00000064, 0x00000108,
479         0x00003f69, 0x00003ed6, 0x000001c1, 0x00000808,
480         0x000001c1, 0x00003e88, 0x00003fb8, 0x00000808
481 };
482
483 static void sunxi_composer_mode_set(const struct ctfb_res_modes *mode,
484                                     unsigned int address,
485                                     enum sunxi_monitor monitor)
486 {
487         struct sunxi_de_be_reg * const de_be =
488                 (struct sunxi_de_be_reg *)SUNXI_DE_BE0_BASE;
489         int i;
490
491         sunxi_frontend_mode_set(mode, address);
492
493         writel(SUNXI_DE_BE_HEIGHT(mode->yres) | SUNXI_DE_BE_WIDTH(mode->xres),
494                &de_be->disp_size);
495         writel(SUNXI_DE_BE_HEIGHT(mode->yres) | SUNXI_DE_BE_WIDTH(mode->xres),
496                &de_be->layer0_size);
497 #ifndef CONFIG_MACH_SUN4I /* On sun4i the frontend does the dma */
498         writel(SUNXI_DE_BE_LAYER_STRIDE(mode->xres), &de_be->layer0_stride);
499         writel(address << 3, &de_be->layer0_addr_low32b);
500         writel(address >> 29, &de_be->layer0_addr_high4b);
501 #else
502         writel(SUNXI_DE_BE_LAYER_ATTR0_SRC_FE0, &de_be->layer0_attr0_ctrl);
503 #endif
504         writel(SUNXI_DE_BE_LAYER_ATTR1_FMT_XRGB8888, &de_be->layer0_attr1_ctrl);
505
506         setbits_le32(&de_be->mode, SUNXI_DE_BE_MODE_LAYER0_ENABLE);
507         if (mode->vmode == FB_VMODE_INTERLACED)
508                 setbits_le32(&de_be->mode,
509 #ifndef CONFIG_MACH_SUN5I
510                              SUNXI_DE_BE_MODE_DEFLICKER_ENABLE |
511 #endif
512                              SUNXI_DE_BE_MODE_INTERLACE_ENABLE);
513
514         if (sunxi_is_composite(monitor)) {
515                 writel(SUNXI_DE_BE_OUTPUT_COLOR_CTRL_ENABLE,
516                        &de_be->output_color_ctrl);
517                 for (i = 0; i < 12; i++)
518                         writel(sunxi_rgb2yuv_coef[i],
519                                &de_be->output_color_coef[i]);
520         }
521 }
522
523 static void sunxi_composer_enable(void)
524 {
525         struct sunxi_de_be_reg * const de_be =
526                 (struct sunxi_de_be_reg *)SUNXI_DE_BE0_BASE;
527
528         sunxi_frontend_enable();
529
530         setbits_le32(&de_be->reg_ctrl, SUNXI_DE_BE_REG_CTRL_LOAD_REGS);
531         setbits_le32(&de_be->mode, SUNXI_DE_BE_MODE_START);
532 }
533
534 static void sunxi_lcdc_init(void)
535 {
536         struct sunxi_ccm_reg * const ccm =
537                 (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
538         struct sunxi_lcdc_reg * const lcdc =
539                 (struct sunxi_lcdc_reg *)SUNXI_LCD0_BASE;
540
541         /* Reset off */
542 #ifdef CONFIG_SUNXI_GEN_SUN6I
543         setbits_le32(&ccm->ahb_reset1_cfg, 1 << AHB_RESET_OFFSET_LCD0);
544 #else
545         setbits_le32(&ccm->lcd0_ch0_clk_cfg, CCM_LCD_CH0_CTRL_RST);
546 #endif
547
548         /* Clock on */
549         setbits_le32(&ccm->ahb_gate1, 1 << AHB_GATE_OFFSET_LCD0);
550 #ifdef CONFIG_VIDEO_LCD_IF_LVDS
551 #ifdef CONFIG_SUNXI_GEN_SUN6I
552         setbits_le32(&ccm->ahb_reset2_cfg, 1 << AHB_RESET_OFFSET_LVDS);
553 #else
554         setbits_le32(&ccm->lvds_clk_cfg, CCM_LVDS_CTRL_RST);
555 #endif
556 #endif
557
558         lcdc_init(lcdc);
559 }
560
561 static void sunxi_lcdc_panel_enable(void)
562 {
563         int pin, reset_pin;
564
565         /*
566          * Start with backlight disabled to avoid the screen flashing to
567          * white while the lcd inits.
568          */
569         pin = sunxi_name_to_gpio(CONFIG_VIDEO_LCD_BL_EN);
570         if (pin >= 0) {
571                 gpio_request(pin, "lcd_backlight_enable");
572                 gpio_direction_output(pin, 0);
573         }
574
575         pin = sunxi_name_to_gpio(CONFIG_VIDEO_LCD_BL_PWM);
576         if (pin >= 0) {
577                 gpio_request(pin, "lcd_backlight_pwm");
578                 gpio_direction_output(pin, PWM_OFF);
579         }
580
581         reset_pin = sunxi_name_to_gpio(CONFIG_VIDEO_LCD_RESET);
582         if (reset_pin >= 0) {
583                 gpio_request(reset_pin, "lcd_reset");
584                 gpio_direction_output(reset_pin, 0); /* Assert reset */
585         }
586
587         /* Give the backlight some time to turn off and power up the panel. */
588         mdelay(40);
589         pin = sunxi_name_to_gpio(CONFIG_VIDEO_LCD_POWER);
590         if (pin >= 0) {
591                 gpio_request(pin, "lcd_power");
592                 gpio_direction_output(pin, 1);
593         }
594
595         if (reset_pin >= 0)
596                 gpio_direction_output(reset_pin, 1); /* De-assert reset */
597 }
598
599 static void sunxi_lcdc_backlight_enable(void)
600 {
601         int pin;
602
603         /*
604          * We want to have scanned out at least one frame before enabling the
605          * backlight to avoid the screen flashing to white when we enable it.
606          */
607         mdelay(40);
608
609         pin = sunxi_name_to_gpio(CONFIG_VIDEO_LCD_BL_EN);
610         if (pin >= 0)
611                 gpio_direction_output(pin, 1);
612
613         pin = sunxi_name_to_gpio(CONFIG_VIDEO_LCD_BL_PWM);
614 #ifdef SUNXI_PWM_PIN0
615         if (pin == SUNXI_PWM_PIN0) {
616                 writel(SUNXI_PWM_CTRL_POLARITY0(PWM_ON) |
617                        SUNXI_PWM_CTRL_ENABLE0 |
618                        SUNXI_PWM_CTRL_PRESCALE0(0xf), SUNXI_PWM_CTRL_REG);
619                 writel(SUNXI_PWM_PERIOD_80PCT, SUNXI_PWM_CH0_PERIOD);
620                 sunxi_gpio_set_cfgpin(pin, SUNXI_PWM_MUX);
621                 return;
622         }
623 #endif
624         if (pin >= 0)
625                 gpio_direction_output(pin, PWM_ON);
626 }
627
628 static void sunxi_lcdc_tcon0_mode_set(struct sunxi_display_priv *sunxi_display,
629                                       const struct ctfb_res_modes *mode,
630                                       bool for_ext_vga_dac)
631 {
632         struct sunxi_lcdc_reg * const lcdc =
633                 (struct sunxi_lcdc_reg *)SUNXI_LCD0_BASE;
634         struct sunxi_ccm_reg * const ccm =
635                 (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
636         int clk_div, clk_double, pin;
637         struct display_timing timing;
638
639 #if defined CONFIG_MACH_SUN8I && defined CONFIG_VIDEO_LCD_IF_LVDS
640         for (pin = SUNXI_GPD(18); pin <= SUNXI_GPD(27); pin++) {
641 #else
642         for (pin = SUNXI_GPD(0); pin <= SUNXI_GPD(27); pin++) {
643 #endif
644 #ifdef CONFIG_VIDEO_LCD_IF_PARALLEL
645                 sunxi_gpio_set_cfgpin(pin, SUNXI_GPD_LCD0);
646 #endif
647 #ifdef CONFIG_VIDEO_LCD_IF_LVDS
648                 sunxi_gpio_set_cfgpin(pin, SUNXI_GPD_LVDS0);
649 #endif
650 #ifdef CONFIG_VIDEO_LCD_PANEL_EDP_4_LANE_1620M_VIA_ANX9804
651                 sunxi_gpio_set_drv(pin, 3);
652 #endif
653         }
654
655         lcdc_pll_set(ccm, 0, mode->pixclock_khz, &clk_div, &clk_double,
656                      sunxi_is_composite(sunxi_display->monitor));
657
658         video_ctfb_mode_to_display_timing(mode, &timing);
659         lcdc_tcon0_mode_set(lcdc, &timing, clk_div, for_ext_vga_dac,
660                             sunxi_display->depth, CONFIG_VIDEO_LCD_DCLK_PHASE);
661 }
662
663 #if defined CONFIG_VIDEO_HDMI || defined CONFIG_VIDEO_VGA || defined CONFIG_VIDEO_COMPOSITE
664 static void sunxi_lcdc_tcon1_mode_set(const struct ctfb_res_modes *mode,
665                                       int *clk_div, int *clk_double,
666                                       bool use_portd_hvsync,
667                                       enum sunxi_monitor monitor)
668 {
669         struct sunxi_lcdc_reg * const lcdc =
670                 (struct sunxi_lcdc_reg *)SUNXI_LCD0_BASE;
671         struct sunxi_ccm_reg * const ccm =
672                 (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
673         struct display_timing timing;
674
675         video_ctfb_mode_to_display_timing(mode, &timing);
676         lcdc_tcon1_mode_set(lcdc, &timing, use_portd_hvsync,
677                             sunxi_is_composite(monitor));
678
679         if (use_portd_hvsync) {
680                 sunxi_gpio_set_cfgpin(SUNXI_GPD(26), SUNXI_GPD_LCD0);
681                 sunxi_gpio_set_cfgpin(SUNXI_GPD(27), SUNXI_GPD_LCD0);
682         }
683
684         lcdc_pll_set(ccm, 1, mode->pixclock_khz, clk_div, clk_double,
685                      sunxi_is_composite(monitor));
686 }
687 #endif /* CONFIG_VIDEO_HDMI || defined CONFIG_VIDEO_VGA || CONFIG_VIDEO_COMPOSITE */
688
689 #ifdef CONFIG_VIDEO_HDMI
690
691 static void sunxi_hdmi_setup_info_frames(const struct ctfb_res_modes *mode)
692 {
693         struct sunxi_hdmi_reg * const hdmi =
694                 (struct sunxi_hdmi_reg *)SUNXI_HDMI_BASE;
695         u8 checksum = 0;
696         u8 avi_info_frame[17] = {
697                 0x82, 0x02, 0x0d, 0x00, 0x12, 0x00, 0x88, 0x00,
698                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
699                 0x00
700         };
701         u8 vendor_info_frame[19] = {
702                 0x81, 0x01, 0x06, 0x29, 0x03, 0x0c, 0x00, 0x40,
703                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
704                 0x00, 0x00, 0x00
705         };
706         int i;
707
708         if (mode->pixclock_khz <= 27000)
709                 avi_info_frame[5] = 0x40; /* SD-modes, ITU601 colorspace */
710         else
711                 avi_info_frame[5] = 0x80; /* HD-modes, ITU709 colorspace */
712
713         if (mode->xres * 100 / mode->yres < 156)
714                 avi_info_frame[5] |= 0x18; /* 4 : 3 */
715         else
716                 avi_info_frame[5] |= 0x28; /* 16 : 9 */
717
718         for (i = 0; i < ARRAY_SIZE(avi_info_frame); i++)
719                 checksum += avi_info_frame[i];
720
721         avi_info_frame[3] = 0x100 - checksum;
722
723         for (i = 0; i < ARRAY_SIZE(avi_info_frame); i++)
724                 writeb(avi_info_frame[i], &hdmi->avi_info_frame[i]);
725
726         writel(SUNXI_HDMI_QCP_PACKET0, &hdmi->qcp_packet0);
727         writel(SUNXI_HDMI_QCP_PACKET1, &hdmi->qcp_packet1);
728
729         for (i = 0; i < ARRAY_SIZE(vendor_info_frame); i++)
730                 writeb(vendor_info_frame[i], &hdmi->vendor_info_frame[i]);
731
732         writel(SUNXI_HDMI_PKT_CTRL0, &hdmi->pkt_ctrl0);
733         writel(SUNXI_HDMI_PKT_CTRL1, &hdmi->pkt_ctrl1);
734
735         setbits_le32(&hdmi->video_ctrl, SUNXI_HDMI_VIDEO_CTRL_HDMI);
736 }
737
738 static void sunxi_hdmi_mode_set(const struct ctfb_res_modes *mode,
739                                 int clk_div, int clk_double,
740                                 enum sunxi_monitor monitor)
741 {
742         struct sunxi_hdmi_reg * const hdmi =
743                 (struct sunxi_hdmi_reg *)SUNXI_HDMI_BASE;
744         int x, y;
745
746         /* Write clear interrupt status bits */
747         writel(SUNXI_HDMI_IRQ_STATUS_BITS, &hdmi->irq);
748
749         if (monitor == sunxi_monitor_hdmi)
750                 sunxi_hdmi_setup_info_frames(mode);
751
752         /* Set input sync enable */
753         writel(SUNXI_HDMI_UNKNOWN_INPUT_SYNC, &hdmi->unknown);
754
755         /* Init various registers, select pll3 as clock source */
756         writel(SUNXI_HDMI_VIDEO_POL_TX_CLK, &hdmi->video_polarity);
757         writel(SUNXI_HDMI_PAD_CTRL0_RUN, &hdmi->pad_ctrl0);
758         writel(SUNXI_HDMI_PAD_CTRL1, &hdmi->pad_ctrl1);
759         writel(SUNXI_HDMI_PLL_CTRL, &hdmi->pll_ctrl);
760         writel(SUNXI_HDMI_PLL_DBG0_PLL3, &hdmi->pll_dbg0);
761
762         /* Setup clk div and doubler */
763         clrsetbits_le32(&hdmi->pll_ctrl, SUNXI_HDMI_PLL_CTRL_DIV_MASK,
764                         SUNXI_HDMI_PLL_CTRL_DIV(clk_div));
765         if (!clk_double)
766                 setbits_le32(&hdmi->pad_ctrl1, SUNXI_HDMI_PAD_CTRL1_HALVE);
767
768         /* Setup timing registers */
769         writel(SUNXI_HDMI_Y(mode->yres) | SUNXI_HDMI_X(mode->xres),
770                &hdmi->video_size);
771
772         x = mode->hsync_len + mode->left_margin;
773         y = mode->vsync_len + mode->upper_margin;
774         writel(SUNXI_HDMI_Y(y) | SUNXI_HDMI_X(x), &hdmi->video_bp);
775
776         x = mode->right_margin;
777         y = mode->lower_margin;
778         writel(SUNXI_HDMI_Y(y) | SUNXI_HDMI_X(x), &hdmi->video_fp);
779
780         x = mode->hsync_len;
781         y = mode->vsync_len;
782         writel(SUNXI_HDMI_Y(y) | SUNXI_HDMI_X(x), &hdmi->video_spw);
783
784         if (mode->sync & FB_SYNC_HOR_HIGH_ACT)
785                 setbits_le32(&hdmi->video_polarity, SUNXI_HDMI_VIDEO_POL_HOR);
786
787         if (mode->sync & FB_SYNC_VERT_HIGH_ACT)
788                 setbits_le32(&hdmi->video_polarity, SUNXI_HDMI_VIDEO_POL_VER);
789 }
790
791 static void sunxi_hdmi_enable(void)
792 {
793         struct sunxi_hdmi_reg * const hdmi =
794                 (struct sunxi_hdmi_reg *)SUNXI_HDMI_BASE;
795
796         udelay(100);
797         setbits_le32(&hdmi->video_ctrl, SUNXI_HDMI_VIDEO_CTRL_ENABLE);
798 }
799
800 #endif /* CONFIG_VIDEO_HDMI */
801
802 #if defined CONFIG_VIDEO_VGA || defined CONFIG_VIDEO_COMPOSITE
803
804 static void sunxi_tvencoder_mode_set(enum sunxi_monitor monitor)
805 {
806         struct sunxi_ccm_reg * const ccm =
807                 (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
808         struct sunxi_tve_reg * const tve =
809                 (struct sunxi_tve_reg *)SUNXI_TVE0_BASE;
810
811         /* Reset off */
812         setbits_le32(&ccm->lcd0_ch0_clk_cfg, CCM_LCD_CH0_CTRL_TVE_RST);
813         /* Clock on */
814         setbits_le32(&ccm->ahb_gate1, 1 << AHB_GATE_OFFSET_TVE0);
815
816         switch (monitor) {
817         case sunxi_monitor_vga:
818                 tvencoder_mode_set(tve, tve_mode_vga);
819                 break;
820         case sunxi_monitor_composite_pal_nc:
821                 tvencoder_mode_set(tve, tve_mode_composite_pal_nc);
822                 break;
823         case sunxi_monitor_composite_pal:
824                 tvencoder_mode_set(tve, tve_mode_composite_pal);
825                 break;
826         case sunxi_monitor_composite_pal_m:
827                 tvencoder_mode_set(tve, tve_mode_composite_pal_m);
828                 break;
829         case sunxi_monitor_composite_ntsc:
830                 tvencoder_mode_set(tve, tve_mode_composite_ntsc);
831                 break;
832         case sunxi_monitor_none:
833         case sunxi_monitor_dvi:
834         case sunxi_monitor_hdmi:
835         case sunxi_monitor_lcd:
836                 break;
837         }
838 }
839
840 #endif /* CONFIG_VIDEO_VGA || defined CONFIG_VIDEO_COMPOSITE */
841
842 static void sunxi_drc_init(void)
843 {
844 #ifdef CONFIG_SUNXI_GEN_SUN6I
845         struct sunxi_ccm_reg * const ccm =
846                 (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
847
848         /* On sun6i the drc must be clocked even when in pass-through mode */
849 #ifdef CONFIG_MACH_SUN8I_A33
850         setbits_le32(&ccm->ahb_reset1_cfg, 1 << AHB_RESET_OFFSET_SAT);
851 #endif
852         setbits_le32(&ccm->ahb_reset1_cfg, 1 << AHB_RESET_OFFSET_DRC0);
853         clock_set_de_mod_clock(&ccm->iep_drc0_clk_cfg, 300000000);
854 #endif
855 }
856
857 #ifdef CONFIG_VIDEO_VGA_VIA_LCD
858 static void sunxi_vga_external_dac_enable(void)
859 {
860         int pin;
861
862         pin = sunxi_name_to_gpio(CONFIG_VIDEO_VGA_EXTERNAL_DAC_EN);
863         if (pin >= 0) {
864                 gpio_request(pin, "vga_enable");
865                 gpio_direction_output(pin, 1);
866         }
867 }
868 #endif /* CONFIG_VIDEO_VGA_VIA_LCD */
869
870 #ifdef CONFIG_VIDEO_LCD_SSD2828
871 static int sunxi_ssd2828_init(const struct ctfb_res_modes *mode)
872 {
873         struct ssd2828_config cfg = {
874                 .csx_pin = sunxi_name_to_gpio(CONFIG_VIDEO_LCD_SPI_CS),
875                 .sck_pin = sunxi_name_to_gpio(CONFIG_VIDEO_LCD_SPI_SCLK),
876                 .sdi_pin = sunxi_name_to_gpio(CONFIG_VIDEO_LCD_SPI_MOSI),
877                 .sdo_pin = sunxi_name_to_gpio(CONFIG_VIDEO_LCD_SPI_MISO),
878                 .reset_pin = sunxi_name_to_gpio(CONFIG_VIDEO_LCD_SSD2828_RESET),
879                 .ssd2828_tx_clk_khz  = CONFIG_VIDEO_LCD_SSD2828_TX_CLK * 1000,
880                 .ssd2828_color_depth = 24,
881 #ifdef CONFIG_VIDEO_LCD_PANEL_MIPI_4_LANE_513_MBPS_VIA_SSD2828
882                 .mipi_dsi_number_of_data_lanes           = 4,
883                 .mipi_dsi_bitrate_per_data_lane_mbps     = 513,
884                 .mipi_dsi_delay_after_exit_sleep_mode_ms = 100,
885                 .mipi_dsi_delay_after_set_display_on_ms  = 200
886 #else
887 #error MIPI LCD panel needs configuration parameters
888 #endif
889         };
890
891         if (cfg.csx_pin == -1 || cfg.sck_pin == -1 || cfg.sdi_pin == -1) {
892                 printf("SSD2828: SPI pins are not properly configured\n");
893                 return 1;
894         }
895         if (cfg.reset_pin == -1) {
896                 printf("SSD2828: Reset pin is not properly configured\n");
897                 return 1;
898         }
899
900         return ssd2828_init(&cfg, mode);
901 }
902 #endif /* CONFIG_VIDEO_LCD_SSD2828 */
903
904 #ifdef CONFIG_VIDEO_LCD_PANEL_I2C
905 static void sunxi_panel_i2c_init(struct sunxi_display_priv *sunxi_display)
906 {
907         const char *name = CONFIG_VIDEO_LCD_PANEL_I2C_NAME;
908         struct udevice *i2c_bus;
909         int ret;
910
911         ret = uclass_get_device_by_name(UCLASS_I2C, name, &i2c_bus);
912         if (ret)
913                 return;
914
915         if (IS_ENABLED(CONFIG_VIDEO_LCD_PANEL_EDP_4_LANE_1620M_VIA_ANX9804)) {
916                 /*
917                  * The anx9804 needs 1.8V from eldo3, we do this here
918                  * and not via CONFIG_AXP_ELDO3_VOLT from board_init()
919                  * to avoid turning this on when using hdmi output.
920                  */
921                 axp_set_eldo(3, 1800);
922                 anx9804_init(i2c_bus, 4,
923                              ANX9804_DATA_RATE_1620M,
924                              sunxi_display->depth);
925         }
926         if (IS_ENABLED(CONFIG_VIDEO_LCD_TL059WV5C0)) {
927                 struct udevice *chip;
928
929                 ret = i2c_get_chip(i2c_bus, 0x5c, 1, &chip);
930                 if (ret)
931                         return;
932
933                 dm_i2c_reg_write(chip, 0x04, 0x42); /* Turn on the LCD */
934         }
935 }
936 #else
937 static void sunxi_panel_i2c_init(struct sunxi_display_priv *sunxi_display) {}
938 #endif
939
940 static void sunxi_engines_init(void)
941 {
942         sunxi_composer_init();
943         sunxi_lcdc_init();
944         sunxi_drc_init();
945 }
946
947 static void sunxi_mode_set(struct sunxi_display_priv *sunxi_display,
948                            const struct ctfb_res_modes *mode,
949                            unsigned int address)
950 {
951         enum sunxi_monitor monitor = sunxi_display->monitor;
952         int __maybe_unused clk_div, clk_double;
953         struct sunxi_lcdc_reg * const lcdc =
954                 (struct sunxi_lcdc_reg *)SUNXI_LCD0_BASE;
955         struct sunxi_tve_reg * __maybe_unused const tve =
956                 (struct sunxi_tve_reg *)SUNXI_TVE0_BASE;
957
958         switch (sunxi_display->monitor) {
959         case sunxi_monitor_none:
960                 break;
961         case sunxi_monitor_dvi:
962         case sunxi_monitor_hdmi:
963 #ifdef CONFIG_VIDEO_HDMI
964                 sunxi_composer_mode_set(mode, address, monitor);
965                 sunxi_lcdc_tcon1_mode_set(mode, &clk_div, &clk_double, 0, monitor);
966                 sunxi_hdmi_mode_set(mode, clk_div, clk_double, monitor);
967                 sunxi_composer_enable();
968                 lcdc_enable(lcdc, sunxi_display->depth);
969                 sunxi_hdmi_enable();
970 #endif
971                 break;
972         case sunxi_monitor_lcd:
973                 sunxi_lcdc_panel_enable();
974                 if (IS_ENABLED(CONFIG_VIDEO_LCD_HITACHI_TX18D42VM)) {
975                         mdelay(50); /* Wait for lcd controller power on */
976                         hitachi_tx18d42vm_init();
977                 }
978                 if (IS_ENABLED(CONFIG_VIDEO_LCD_PANEL_I2C))
979                         sunxi_panel_i2c_init(sunxi_display);
980                 sunxi_composer_mode_set(mode, address, monitor);
981                 sunxi_lcdc_tcon0_mode_set(sunxi_display, mode, false);
982                 sunxi_composer_enable();
983                 lcdc_enable(lcdc, sunxi_display->depth);
984 #ifdef CONFIG_VIDEO_LCD_SSD2828
985                 sunxi_ssd2828_init(mode);
986 #endif
987                 sunxi_lcdc_backlight_enable();
988                 break;
989         case sunxi_monitor_vga:
990 #ifdef CONFIG_VIDEO_VGA
991                 sunxi_composer_mode_set(mode, address, monitor);
992                 sunxi_lcdc_tcon1_mode_set(mode, &clk_div, &clk_double, 1, monitor);
993                 sunxi_tvencoder_mode_set(monitor);
994                 sunxi_composer_enable();
995                 lcdc_enable(lcdc, sunxi_display->depth);
996                 tvencoder_enable(tve);
997 #elif defined CONFIG_VIDEO_VGA_VIA_LCD
998                 sunxi_composer_mode_set(mode, address, monitor);
999                 sunxi_lcdc_tcon0_mode_set(sunxi_display, mode, true);
1000                 sunxi_composer_enable();
1001                 lcdc_enable(lcdc, sunxi_display->depth);
1002                 sunxi_vga_external_dac_enable();
1003 #endif
1004                 break;
1005         case sunxi_monitor_composite_pal:
1006         case sunxi_monitor_composite_ntsc:
1007         case sunxi_monitor_composite_pal_m:
1008         case sunxi_monitor_composite_pal_nc:
1009 #ifdef CONFIG_VIDEO_COMPOSITE
1010                 sunxi_composer_mode_set(mode, address, monitor);
1011                 sunxi_lcdc_tcon1_mode_set(mode, &clk_div, &clk_double, 0, monitor);
1012                 sunxi_tvencoder_mode_set(monitor);
1013                 sunxi_composer_enable();
1014                 lcdc_enable(lcdc, sunxi_display->depth);
1015                 tvencoder_enable(tve);
1016 #endif
1017                 break;
1018         }
1019 }
1020
1021 static const char *sunxi_get_mon_desc(enum sunxi_monitor monitor)
1022 {
1023         switch (monitor) {
1024         case sunxi_monitor_dvi:                 return "dvi";
1025         case sunxi_monitor_hdmi:                return "hdmi";
1026         case sunxi_monitor_lcd:                 return "lcd";
1027         case sunxi_monitor_vga:                 return "vga";
1028         case sunxi_monitor_composite_pal:       return "composite-pal";
1029         case sunxi_monitor_composite_ntsc:      return "composite-ntsc";
1030         case sunxi_monitor_composite_pal_m:     return "composite-pal-m";
1031         case sunxi_monitor_composite_pal_nc:    return "composite-pal-nc";
1032         case sunxi_monitor_none:                /* fall through */
1033         default:                                return "none";
1034         }
1035 }
1036
1037 static bool sunxi_has_hdmi(void)
1038 {
1039 #ifdef CONFIG_VIDEO_HDMI
1040         return true;
1041 #else
1042         return false;
1043 #endif
1044 }
1045
1046 static bool sunxi_has_lcd(void)
1047 {
1048         char *lcd_mode = CONFIG_VIDEO_LCD_MODE;
1049
1050         return lcd_mode[0] != 0;
1051 }
1052
1053 static bool sunxi_has_vga(void)
1054 {
1055 #if defined CONFIG_VIDEO_VGA || defined CONFIG_VIDEO_VGA_VIA_LCD
1056         return true;
1057 #else
1058         return false;
1059 #endif
1060 }
1061
1062 static bool sunxi_has_composite(void)
1063 {
1064 #ifdef CONFIG_VIDEO_COMPOSITE
1065         return true;
1066 #else
1067         return false;
1068 #endif
1069 }
1070
1071 static enum sunxi_monitor sunxi_get_default_mon(bool allow_hdmi)
1072 {
1073         if (allow_hdmi && sunxi_has_hdmi())
1074                 return sunxi_monitor_dvi;
1075         else if (sunxi_has_lcd())
1076                 return sunxi_monitor_lcd;
1077         else if (sunxi_has_vga())
1078                 return sunxi_monitor_vga;
1079         else if (sunxi_has_composite())
1080                 return sunxi_monitor_composite_pal;
1081         else
1082                 return sunxi_monitor_none;
1083 }
1084
1085 static int sunxi_de_probe(struct udevice *dev)
1086 {
1087         struct video_priv *uc_priv = dev_get_uclass_priv(dev);
1088         struct video_uc_plat *plat = dev_get_uclass_plat(dev);
1089         struct sunxi_display_priv *sunxi_display = dev_get_priv(dev);
1090         const struct ctfb_res_modes *mode;
1091         struct ctfb_res_modes custom;
1092         const char *options;
1093 #ifdef CONFIG_VIDEO_HDMI
1094         int hpd, hpd_delay, edid;
1095         bool hdmi_present;
1096 #endif
1097         int i, overscan_offset, overscan_x, overscan_y;
1098         unsigned int fb_dma_addr;
1099         char mon[16];
1100         char *lcd_mode = CONFIG_VIDEO_LCD_MODE;
1101
1102         video_get_ctfb_res_modes(RES_MODE_1024x768, 24, &mode,
1103                                  &sunxi_display->depth, &options);
1104 #ifdef CONFIG_VIDEO_HDMI
1105         hpd = video_get_option_int(options, "hpd", 1);
1106         hpd_delay = video_get_option_int(options, "hpd_delay", 500);
1107         edid = video_get_option_int(options, "edid", 1);
1108 #endif
1109         overscan_x = video_get_option_int(options, "overscan_x", -1);
1110         overscan_y = video_get_option_int(options, "overscan_y", -1);
1111         sunxi_display->monitor = sunxi_get_default_mon(true);
1112         video_get_option_string(options, "monitor", mon, sizeof(mon),
1113                                 sunxi_get_mon_desc(sunxi_display->monitor));
1114         for (i = 0; i <= SUNXI_MONITOR_LAST; i++) {
1115                 if (strcmp(mon, sunxi_get_mon_desc(i)) == 0) {
1116                         sunxi_display->monitor = i;
1117                         break;
1118                 }
1119         }
1120         if (i > SUNXI_MONITOR_LAST)
1121                 printf("Unknown monitor: '%s', falling back to '%s'\n",
1122                        mon, sunxi_get_mon_desc(sunxi_display->monitor));
1123
1124 #ifdef CONFIG_VIDEO_HDMI
1125         /* If HDMI/DVI is selected do HPD & EDID, and handle fallback */
1126         if (sunxi_display->monitor == sunxi_monitor_dvi ||
1127             sunxi_display->monitor == sunxi_monitor_hdmi) {
1128                 /* Always call hdp_detect, as it also enables clocks, etc. */
1129                 hdmi_present = (sunxi_hdmi_hpd_detect(hpd_delay) == 1);
1130                 if (hdmi_present && edid) {
1131                         printf("HDMI connected: ");
1132                         if (sunxi_hdmi_edid_get_mode(sunxi_display, &custom, true) == 0)
1133                                 mode = &custom;
1134                         else
1135                                 hdmi_present = false;
1136                 }
1137                 /* Fall back to EDID in case HPD failed */
1138                 if (edid && !hdmi_present) {
1139                         if (sunxi_hdmi_edid_get_mode(sunxi_display, &custom, false) == 0) {
1140                                 mode = &custom;
1141                                 hdmi_present = true;
1142                         }
1143                 }
1144                 /* Shut down when display was not found */
1145                 if ((hpd || edid) && !hdmi_present) {
1146                         sunxi_hdmi_shutdown();
1147                         sunxi_display->monitor = sunxi_get_default_mon(false);
1148                 } /* else continue with hdmi/dvi without a cable connected */
1149         }
1150 #endif
1151
1152         switch (sunxi_display->monitor) {
1153         case sunxi_monitor_none:
1154                 printf("Unknown monitor\n");
1155                 return -EINVAL;
1156         case sunxi_monitor_dvi:
1157         case sunxi_monitor_hdmi:
1158                 if (!sunxi_has_hdmi()) {
1159                         printf("HDMI/DVI not supported on this board\n");
1160                         sunxi_display->monitor = sunxi_monitor_none;
1161                         return -EINVAL;
1162                 }
1163                 break;
1164         case sunxi_monitor_lcd:
1165                 if (!sunxi_has_lcd()) {
1166                         printf("LCD not supported on this board\n");
1167                         sunxi_display->monitor = sunxi_monitor_none;
1168                         return -EINVAL;
1169                 }
1170                 sunxi_display->depth = video_get_params(&custom, lcd_mode);
1171                 mode = &custom;
1172                 break;
1173         case sunxi_monitor_vga:
1174                 if (!sunxi_has_vga()) {
1175                         printf("VGA not supported on this board\n");
1176                         sunxi_display->monitor = sunxi_monitor_none;
1177                         return -EINVAL;
1178                 }
1179                 sunxi_display->depth = 18;
1180                 break;
1181         case sunxi_monitor_composite_pal:
1182         case sunxi_monitor_composite_ntsc:
1183         case sunxi_monitor_composite_pal_m:
1184         case sunxi_monitor_composite_pal_nc:
1185                 if (!sunxi_has_composite()) {
1186                         printf("Composite video not supported on this board\n");
1187                         sunxi_display->monitor = sunxi_monitor_none;
1188                         return -EINVAL;
1189                 }
1190                 if (sunxi_display->monitor == sunxi_monitor_composite_pal ||
1191                     sunxi_display->monitor == sunxi_monitor_composite_pal_nc)
1192                         mode = &composite_video_modes[0];
1193                 else
1194                         mode = &composite_video_modes[1];
1195                 sunxi_display->depth = 24;
1196                 break;
1197         }
1198
1199         /* Yes these defaults are quite high, overscan on composite sucks... */
1200         if (overscan_x == -1)
1201                 overscan_x = sunxi_is_composite(sunxi_display->monitor) ? 32 : 0;
1202         if (overscan_y == -1)
1203                 overscan_y = sunxi_is_composite(sunxi_display->monitor) ? 20 : 0;
1204
1205         sunxi_display->fb_size = plat->size;
1206         overscan_offset = (overscan_y * mode->xres + overscan_x) * 4;
1207         /* We want to keep the fb_base for simplefb page aligned, where as
1208          * the sunxi dma engines will happily accept an unaligned address. */
1209         if (overscan_offset)
1210                 sunxi_display->fb_size += 0x1000;
1211
1212         printf("Setting up a %dx%d%s %s console (overscan %dx%d)\n",
1213                mode->xres, mode->yres,
1214                (mode->vmode == FB_VMODE_INTERLACED) ? "i" : "",
1215                sunxi_get_mon_desc(sunxi_display->monitor),
1216                overscan_x, overscan_y);
1217
1218         sunxi_display->fb_addr = plat->base;
1219         sunxi_engines_init();
1220
1221 #ifdef CONFIG_EFI_LOADER
1222         efi_add_memory_map(sunxi_display->fb_addr, sunxi_display->fb_size,
1223                            EFI_RESERVED_MEMORY_TYPE);
1224 #endif
1225
1226         fb_dma_addr = sunxi_display->fb_addr - CONFIG_SYS_SDRAM_BASE;
1227         if (overscan_offset) {
1228                 fb_dma_addr += 0x1000 - (overscan_offset & 0xfff);
1229                 sunxi_display->fb_addr += ALIGN(overscan_offset, 0x1000);
1230                 memset((void *)sunxi_display->fb_addr, 0, sunxi_display->fb_size);
1231                 flush_cache(sunxi_display->fb_addr, sunxi_display->fb_size);
1232         }
1233         sunxi_mode_set(sunxi_display, mode, fb_dma_addr);
1234
1235         /* The members of struct video_priv to be set by the driver. */
1236         uc_priv->bpix = VIDEO_BPP32;
1237         uc_priv->xsize = mode->xres;
1238         uc_priv->ysize = mode->yres;
1239
1240         video_set_flush_dcache(dev, true);
1241
1242         return 0;
1243 }
1244
1245 static int sunxi_de_bind(struct udevice *dev)
1246 {
1247         struct video_uc_plat *plat = dev_get_uclass_plat(dev);
1248
1249         plat->size = LCD_MAX_WIDTH * LCD_MAX_HEIGHT * VNBYTES(LCD_MAX_LOG2_BPP);
1250
1251         return 0;
1252 }
1253
1254 static const struct video_ops sunxi_de_ops = {
1255 };
1256
1257 U_BOOT_DRIVER(sunxi_de) = {
1258         .name   = "sunxi_de",
1259         .id     = UCLASS_VIDEO,
1260         .ops    = &sunxi_de_ops,
1261         .bind   = sunxi_de_bind,
1262         .probe  = sunxi_de_probe,
1263         .priv_auto = sizeof(struct sunxi_display_priv),
1264         .flags  = DM_FLAG_PRE_RELOC,
1265 };
1266
1267 U_BOOT_DRVINFO(sunxi_de) = {
1268         .name = "sunxi_de"
1269 };
1270
1271 /*
1272  * Simplefb support.
1273  */
1274 #if defined(CONFIG_OF_BOARD_SETUP) && defined(CONFIG_VIDEO_DT_SIMPLEFB)
1275 int sunxi_simplefb_setup(void *blob)
1276 {
1277         struct sunxi_display_priv *sunxi_display;
1278         struct video_priv *uc_priv;
1279         struct udevice *de;
1280         int offset, ret;
1281         u64 start, size;
1282         const char *pipeline = NULL;
1283
1284 #ifdef CONFIG_MACH_SUN4I
1285 #define PIPELINE_PREFIX "de_fe0-"
1286 #else
1287 #define PIPELINE_PREFIX
1288 #endif
1289
1290         ret = uclass_find_device_by_name(UCLASS_VIDEO, "sunxi_de", &de);
1291         if (ret) {
1292                 printf("DE not present\n");
1293                 return 0;
1294         } else if (!device_active(de)) {
1295                 printf("DE is present but not probed\n");
1296                 return 0;
1297         }
1298
1299         uc_priv = dev_get_uclass_priv(de);
1300         sunxi_display = dev_get_priv(de);
1301
1302         switch (sunxi_display->monitor) {
1303         case sunxi_monitor_none:
1304                 return 0;
1305         case sunxi_monitor_dvi:
1306         case sunxi_monitor_hdmi:
1307                 pipeline = PIPELINE_PREFIX "de_be0-lcd0-hdmi";
1308                 break;
1309         case sunxi_monitor_lcd:
1310                 pipeline = PIPELINE_PREFIX "de_be0-lcd0";
1311                 break;
1312         case sunxi_monitor_vga:
1313 #ifdef CONFIG_VIDEO_VGA
1314                 pipeline = PIPELINE_PREFIX "de_be0-lcd0-tve0";
1315 #elif defined CONFIG_VIDEO_VGA_VIA_LCD
1316                 pipeline = PIPELINE_PREFIX "de_be0-lcd0";
1317 #endif
1318                 break;
1319         case sunxi_monitor_composite_pal:
1320         case sunxi_monitor_composite_ntsc:
1321         case sunxi_monitor_composite_pal_m:
1322         case sunxi_monitor_composite_pal_nc:
1323                 pipeline = PIPELINE_PREFIX "de_be0-lcd0-tve0";
1324                 break;
1325         }
1326
1327         offset = sunxi_simplefb_fdt_match(blob, pipeline);
1328         if (offset < 0) {
1329                 eprintf("Cannot setup simplefb: node not found\n");
1330                 return 0; /* Keep older kernels working */
1331         }
1332
1333         /*
1334          * Do not report the framebuffer as free RAM to the OS, note we cannot
1335          * use fdt_add_mem_rsv() here, because then it is still seen as RAM,
1336          * and e.g. Linux refuses to iomap RAM on ARM, see:
1337          * linux/arch/arm/mm/ioremap.c around line 301.
1338          */
1339         start = gd->bd->bi_dram[0].start;
1340         size = sunxi_display->fb_addr - start;
1341         ret = fdt_fixup_memory_banks(blob, &start, &size, 1);
1342         if (ret) {
1343                 eprintf("Cannot setup simplefb: Error reserving memory\n");
1344                 return ret;
1345         }
1346
1347         ret = fdt_setup_simplefb_node(blob, offset, sunxi_display->fb_addr,
1348                                       uc_priv->xsize, uc_priv->ysize,
1349                                       VNBYTES(uc_priv->bpix) * uc_priv->xsize,
1350                                       "x8r8g8b8");
1351         if (ret)
1352                 eprintf("Cannot setup simplefb: Error setting properties\n");
1353
1354         return ret;
1355 }
1356 #endif /* CONFIG_OF_BOARD_SETUP && CONFIG_VIDEO_DT_SIMPLEFB */