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