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