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