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