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