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