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