]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - drivers/video/sunxi_display.c
Merge branch 'master' of git://git.denx.de/u-boot-atmel
[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 {
650         struct sunxi_lcdc_reg * const lcdc =
651                 (struct sunxi_lcdc_reg *)SUNXI_LCD0_BASE;
652         int bp, clk_delay, clk_div, clk_double, pin, total, val;
653
654         for (pin = SUNXI_GPD(0); pin <= SUNXI_GPD(27); pin++)
655 #ifdef CONFIG_VIDEO_LCD_IF_PARALLEL
656                 sunxi_gpio_set_cfgpin(pin, SUNXI_GPD0_LCD0);
657 #endif
658 #ifdef CONFIG_VIDEO_LCD_IF_LVDS
659                 sunxi_gpio_set_cfgpin(pin, SUNXI_GPD0_LVDS0);
660 #endif
661
662         sunxi_lcdc_pll_set(0, mode->pixclock_khz, &clk_div, &clk_double);
663
664         /* Use tcon0 */
665         clrsetbits_le32(&lcdc->ctrl, SUNXI_LCDC_CTRL_IO_MAP_MASK,
666                         SUNXI_LCDC_CTRL_IO_MAP_TCON0);
667
668         clk_delay = sunxi_lcdc_get_clk_delay(mode);
669         writel(SUNXI_LCDC_TCON0_CTRL_ENABLE |
670                SUNXI_LCDC_TCON0_CTRL_CLK_DELAY(clk_delay), &lcdc->tcon0_ctrl);
671
672         writel(SUNXI_LCDC_TCON0_DCLK_ENABLE |
673                SUNXI_LCDC_TCON0_DCLK_DIV(clk_div), &lcdc->tcon0_dclk);
674
675         writel(SUNXI_LCDC_X(mode->xres) | SUNXI_LCDC_Y(mode->yres),
676                &lcdc->tcon0_timing_active);
677
678         bp = mode->hsync_len + mode->left_margin;
679         total = mode->xres + mode->right_margin + bp;
680         writel(SUNXI_LCDC_TCON0_TIMING_H_TOTAL(total) |
681                SUNXI_LCDC_TCON0_TIMING_H_BP(bp), &lcdc->tcon0_timing_h);
682
683         bp = mode->vsync_len + mode->upper_margin;
684         total = mode->yres + mode->lower_margin + bp;
685         writel(SUNXI_LCDC_TCON0_TIMING_V_TOTAL(total) |
686                SUNXI_LCDC_TCON0_TIMING_V_BP(bp), &lcdc->tcon0_timing_v);
687
688 #ifdef CONFIG_VIDEO_LCD_IF_PARALLEL
689         writel(SUNXI_LCDC_X(mode->hsync_len) | SUNXI_LCDC_Y(mode->vsync_len),
690                &lcdc->tcon0_timing_sync);
691
692         writel(0, &lcdc->tcon0_hv_intf);
693         writel(0, &lcdc->tcon0_cpu_intf);
694 #endif
695 #ifdef CONFIG_VIDEO_LCD_IF_LVDS
696         val = (sunxi_display.depth == 18) ? 1 : 0;
697         writel(SUNXI_LCDC_TCON0_LVDS_INTF_BITWIDTH(val), &lcdc->tcon0_lvds_intf);
698 #endif
699
700         if (sunxi_display.depth == 18 || sunxi_display.depth == 16) {
701                 writel(SUNXI_LCDC_TCON0_FRM_SEED, &lcdc->tcon0_frm_seed[0]);
702                 writel(SUNXI_LCDC_TCON0_FRM_SEED, &lcdc->tcon0_frm_seed[1]);
703                 writel(SUNXI_LCDC_TCON0_FRM_SEED, &lcdc->tcon0_frm_seed[2]);
704                 writel(SUNXI_LCDC_TCON0_FRM_SEED, &lcdc->tcon0_frm_seed[3]);
705                 writel(SUNXI_LCDC_TCON0_FRM_SEED, &lcdc->tcon0_frm_seed[4]);
706                 writel(SUNXI_LCDC_TCON0_FRM_SEED, &lcdc->tcon0_frm_seed[5]);
707                 writel(SUNXI_LCDC_TCON0_FRM_TAB0, &lcdc->tcon0_frm_table[0]);
708                 writel(SUNXI_LCDC_TCON0_FRM_TAB1, &lcdc->tcon0_frm_table[1]);
709                 writel(SUNXI_LCDC_TCON0_FRM_TAB2, &lcdc->tcon0_frm_table[2]);
710                 writel(SUNXI_LCDC_TCON0_FRM_TAB3, &lcdc->tcon0_frm_table[3]);
711                 writel(((sunxi_display.depth == 18) ?
712                         SUNXI_LCDC_TCON0_FRM_CTRL_RGB666 :
713                         SUNXI_LCDC_TCON0_FRM_CTRL_RGB565),
714                        &lcdc->tcon0_frm_ctrl);
715         }
716
717         val = SUNXI_LCDC_TCON0_IO_POL_DCLK_PHASE(CONFIG_VIDEO_LCD_DCLK_PHASE);
718         if (!(mode->sync & FB_SYNC_HOR_HIGH_ACT))
719                 val |= SUNXI_LCDC_TCON_HSYNC_MASK;
720         if (!(mode->sync & FB_SYNC_VERT_HIGH_ACT))
721                 val |= SUNXI_LCDC_TCON_VSYNC_MASK;
722         writel(val, &lcdc->tcon0_io_polarity);
723
724         writel(0, &lcdc->tcon0_io_tristate);
725 }
726
727 #if defined CONFIG_VIDEO_HDMI || defined CONFIG_VIDEO_VGA
728 static void sunxi_lcdc_tcon1_mode_set(const struct ctfb_res_modes *mode,
729                                       int *clk_div, int *clk_double,
730                                       bool use_portd_hvsync)
731 {
732         struct sunxi_lcdc_reg * const lcdc =
733                 (struct sunxi_lcdc_reg *)SUNXI_LCD0_BASE;
734         int bp, clk_delay, total, val;
735
736         /* Use tcon1 */
737         clrsetbits_le32(&lcdc->ctrl, SUNXI_LCDC_CTRL_IO_MAP_MASK,
738                         SUNXI_LCDC_CTRL_IO_MAP_TCON1);
739
740         clk_delay = sunxi_lcdc_get_clk_delay(mode);
741         writel(SUNXI_LCDC_TCON1_CTRL_ENABLE |
742                SUNXI_LCDC_TCON1_CTRL_CLK_DELAY(clk_delay), &lcdc->tcon1_ctrl);
743
744         writel(SUNXI_LCDC_X(mode->xres) | SUNXI_LCDC_Y(mode->yres),
745                &lcdc->tcon1_timing_source);
746         writel(SUNXI_LCDC_X(mode->xres) | SUNXI_LCDC_Y(mode->yres),
747                &lcdc->tcon1_timing_scale);
748         writel(SUNXI_LCDC_X(mode->xres) | SUNXI_LCDC_Y(mode->yres),
749                &lcdc->tcon1_timing_out);
750
751         bp = mode->hsync_len + mode->left_margin;
752         total = mode->xres + mode->right_margin + bp;
753         writel(SUNXI_LCDC_TCON1_TIMING_H_TOTAL(total) |
754                SUNXI_LCDC_TCON1_TIMING_H_BP(bp), &lcdc->tcon1_timing_h);
755
756         bp = mode->vsync_len + mode->upper_margin;
757         total = mode->yres + mode->lower_margin + bp;
758         writel(SUNXI_LCDC_TCON1_TIMING_V_TOTAL(total) |
759                SUNXI_LCDC_TCON1_TIMING_V_BP(bp), &lcdc->tcon1_timing_v);
760
761         writel(SUNXI_LCDC_X(mode->hsync_len) | SUNXI_LCDC_Y(mode->vsync_len),
762                &lcdc->tcon1_timing_sync);
763
764         if (use_portd_hvsync) {
765                 sunxi_gpio_set_cfgpin(SUNXI_GPD(26), SUNXI_GPD0_LCD0);
766                 sunxi_gpio_set_cfgpin(SUNXI_GPD(27), SUNXI_GPD0_LCD0);
767
768                 val = 0;
769                 if (mode->sync & FB_SYNC_HOR_HIGH_ACT)
770                         val |= SUNXI_LCDC_TCON_HSYNC_MASK;
771                 if (mode->sync & FB_SYNC_VERT_HIGH_ACT)
772                         val |= SUNXI_LCDC_TCON_VSYNC_MASK;
773                 writel(val, &lcdc->tcon1_io_polarity);
774
775                 clrbits_le32(&lcdc->tcon1_io_tristate,
776                              SUNXI_LCDC_TCON_VSYNC_MASK |
777                              SUNXI_LCDC_TCON_HSYNC_MASK);
778         }
779         sunxi_lcdc_pll_set(1, mode->pixclock_khz, clk_div, clk_double);
780 }
781 #endif /* CONFIG_VIDEO_HDMI || defined CONFIG_VIDEO_VGA */
782
783 #ifdef CONFIG_VIDEO_HDMI
784
785 static void sunxi_hdmi_setup_info_frames(const struct ctfb_res_modes *mode)
786 {
787         struct sunxi_hdmi_reg * const hdmi =
788                 (struct sunxi_hdmi_reg *)SUNXI_HDMI_BASE;
789         u8 checksum = 0;
790         u8 avi_info_frame[17] = {
791                 0x82, 0x02, 0x0d, 0x00, 0x12, 0x00, 0x88, 0x00,
792                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
793                 0x00
794         };
795         u8 vendor_info_frame[19] = {
796                 0x81, 0x01, 0x06, 0x29, 0x03, 0x0c, 0x00, 0x40,
797                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
798                 0x00, 0x00, 0x00
799         };
800         int i;
801
802         if (mode->pixclock_khz <= 27000)
803                 avi_info_frame[5] = 0x40; /* SD-modes, ITU601 colorspace */
804         else
805                 avi_info_frame[5] = 0x80; /* HD-modes, ITU709 colorspace */
806
807         if (mode->xres * 100 / mode->yres < 156)
808                 avi_info_frame[5] |= 0x18; /* 4 : 3 */
809         else
810                 avi_info_frame[5] |= 0x28; /* 16 : 9 */
811
812         for (i = 0; i < ARRAY_SIZE(avi_info_frame); i++)
813                 checksum += avi_info_frame[i];
814
815         avi_info_frame[3] = 0x100 - checksum;
816
817         for (i = 0; i < ARRAY_SIZE(avi_info_frame); i++)
818                 writeb(avi_info_frame[i], &hdmi->avi_info_frame[i]);
819
820         writel(SUNXI_HDMI_QCP_PACKET0, &hdmi->qcp_packet0);
821         writel(SUNXI_HDMI_QCP_PACKET1, &hdmi->qcp_packet1);
822
823         for (i = 0; i < ARRAY_SIZE(vendor_info_frame); i++)
824                 writeb(vendor_info_frame[i], &hdmi->vendor_info_frame[i]);
825
826         writel(SUNXI_HDMI_PKT_CTRL0, &hdmi->pkt_ctrl0);
827         writel(SUNXI_HDMI_PKT_CTRL1, &hdmi->pkt_ctrl1);
828
829         setbits_le32(&hdmi->video_ctrl, SUNXI_HDMI_VIDEO_CTRL_HDMI);
830 }
831
832 static void sunxi_hdmi_mode_set(const struct ctfb_res_modes *mode,
833                                 int clk_div, int clk_double)
834 {
835         struct sunxi_hdmi_reg * const hdmi =
836                 (struct sunxi_hdmi_reg *)SUNXI_HDMI_BASE;
837         int x, y;
838
839         /* Write clear interrupt status bits */
840         writel(SUNXI_HDMI_IRQ_STATUS_BITS, &hdmi->irq);
841
842         if (sunxi_display.monitor == sunxi_monitor_hdmi)
843                 sunxi_hdmi_setup_info_frames(mode);
844
845         /* Set input sync enable */
846         writel(SUNXI_HDMI_UNKNOWN_INPUT_SYNC, &hdmi->unknown);
847
848         /* Init various registers, select pll3 as clock source */
849         writel(SUNXI_HDMI_VIDEO_POL_TX_CLK, &hdmi->video_polarity);
850         writel(SUNXI_HDMI_PAD_CTRL0_RUN, &hdmi->pad_ctrl0);
851         writel(SUNXI_HDMI_PAD_CTRL1, &hdmi->pad_ctrl1);
852         writel(SUNXI_HDMI_PLL_CTRL, &hdmi->pll_ctrl);
853         writel(SUNXI_HDMI_PLL_DBG0_PLL3, &hdmi->pll_dbg0);
854
855         /* Setup clk div and doubler */
856         clrsetbits_le32(&hdmi->pll_ctrl, SUNXI_HDMI_PLL_CTRL_DIV_MASK,
857                         SUNXI_HDMI_PLL_CTRL_DIV(clk_div));
858         if (!clk_double)
859                 setbits_le32(&hdmi->pad_ctrl1, SUNXI_HDMI_PAD_CTRL1_HALVE);
860
861         /* Setup timing registers */
862         writel(SUNXI_HDMI_Y(mode->yres) | SUNXI_HDMI_X(mode->xres),
863                &hdmi->video_size);
864
865         x = mode->hsync_len + mode->left_margin;
866         y = mode->vsync_len + mode->upper_margin;
867         writel(SUNXI_HDMI_Y(y) | SUNXI_HDMI_X(x), &hdmi->video_bp);
868
869         x = mode->right_margin;
870         y = mode->lower_margin;
871         writel(SUNXI_HDMI_Y(y) | SUNXI_HDMI_X(x), &hdmi->video_fp);
872
873         x = mode->hsync_len;
874         y = mode->vsync_len;
875         writel(SUNXI_HDMI_Y(y) | SUNXI_HDMI_X(x), &hdmi->video_spw);
876
877         if (mode->sync & FB_SYNC_HOR_HIGH_ACT)
878                 setbits_le32(&hdmi->video_polarity, SUNXI_HDMI_VIDEO_POL_HOR);
879
880         if (mode->sync & FB_SYNC_VERT_HIGH_ACT)
881                 setbits_le32(&hdmi->video_polarity, SUNXI_HDMI_VIDEO_POL_VER);
882 }
883
884 static void sunxi_hdmi_enable(void)
885 {
886         struct sunxi_hdmi_reg * const hdmi =
887                 (struct sunxi_hdmi_reg *)SUNXI_HDMI_BASE;
888
889         udelay(100);
890         setbits_le32(&hdmi->video_ctrl, SUNXI_HDMI_VIDEO_CTRL_ENABLE);
891 }
892
893 #endif /* CONFIG_VIDEO_HDMI */
894
895 #ifdef CONFIG_VIDEO_VGA
896
897 static void sunxi_vga_mode_set(void)
898 {
899         struct sunxi_ccm_reg * const ccm =
900                 (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
901         struct sunxi_tve_reg * const tve =
902                 (struct sunxi_tve_reg *)SUNXI_TVE0_BASE;
903
904         /* Clock on */
905         setbits_le32(&ccm->ahb_gate1, 1 << AHB_GATE_OFFSET_TVE0);
906
907         /* Set TVE in VGA mode */
908         writel(SUNXI_TVE_GCTRL_DAC_INPUT(0, 1) |
909                SUNXI_TVE_GCTRL_DAC_INPUT(1, 2) |
910                SUNXI_TVE_GCTRL_DAC_INPUT(2, 3), &tve->gctrl);
911         writel(SUNXI_TVE_GCTRL_CFG0_VGA, &tve->cfg0);
912         writel(SUNXI_TVE_GCTRL_DAC_CFG0_VGA, &tve->dac_cfg0);
913         writel(SUNXI_TVE_GCTRL_UNKNOWN1_VGA, &tve->unknown1);
914 }
915
916 static void sunxi_vga_enable(void)
917 {
918         struct sunxi_tve_reg * const tve =
919                 (struct sunxi_tve_reg *)SUNXI_TVE0_BASE;
920
921         setbits_le32(&tve->gctrl, SUNXI_TVE_GCTRL_ENABLE);
922 }
923
924 #endif /* CONFIG_VIDEO_VGA */
925
926 static void sunxi_drc_init(void)
927 {
928 #if defined CONFIG_MACH_SUN6I || defined CONFIG_MACH_SUN8I
929         struct sunxi_ccm_reg * const ccm =
930                 (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
931
932         /* On sun6i the drc must be clocked even when in pass-through mode */
933         setbits_le32(&ccm->ahb_reset1_cfg, 1 << AHB_RESET_OFFSET_DRC0);
934         clock_set_de_mod_clock(&ccm->iep_drc0_clk_cfg, 300000000);
935 #endif
936 }
937
938 #ifdef CONFIG_VIDEO_VGA_VIA_LCD
939 static void sunxi_vga_external_dac_enable(void)
940 {
941         int pin;
942
943         pin = sunxi_name_to_gpio(CONFIG_VIDEO_VGA_EXTERNAL_DAC_EN);
944         if (pin != -1) {
945                 gpio_request(pin, "vga_enable");
946                 gpio_direction_output(pin, 1);
947         }
948 }
949 #endif /* CONFIG_VIDEO_VGA_VIA_LCD */
950
951 #ifdef CONFIG_VIDEO_LCD_SSD2828
952 static int sunxi_ssd2828_init(const struct ctfb_res_modes *mode)
953 {
954         struct ssd2828_config cfg = {
955                 .csx_pin = name_to_gpio(CONFIG_VIDEO_LCD_SPI_CS),
956                 .sck_pin = name_to_gpio(CONFIG_VIDEO_LCD_SPI_SCLK),
957                 .sdi_pin = name_to_gpio(CONFIG_VIDEO_LCD_SPI_MOSI),
958                 .sdo_pin = name_to_gpio(CONFIG_VIDEO_LCD_SPI_MISO),
959                 .reset_pin = name_to_gpio(CONFIG_VIDEO_LCD_SSD2828_RESET),
960                 .ssd2828_tx_clk_khz  = CONFIG_VIDEO_LCD_SSD2828_TX_CLK * 1000,
961                 .ssd2828_color_depth = 24,
962 #ifdef CONFIG_VIDEO_LCD_PANEL_MIPI_4_LANE_513_MBPS_VIA_SSD2828
963                 .mipi_dsi_number_of_data_lanes           = 4,
964                 .mipi_dsi_bitrate_per_data_lane_mbps     = 513,
965                 .mipi_dsi_delay_after_exit_sleep_mode_ms = 100,
966                 .mipi_dsi_delay_after_set_display_on_ms  = 200
967 #else
968 #error MIPI LCD panel needs configuration parameters
969 #endif
970         };
971
972         if (cfg.csx_pin == -1 || cfg.sck_pin == -1 || cfg.sdi_pin == -1) {
973                 printf("SSD2828: SPI pins are not properly configured\n");
974                 return 1;
975         }
976         if (cfg.reset_pin == -1) {
977                 printf("SSD2828: Reset pin is not properly configured\n");
978                 return 1;
979         }
980
981         return ssd2828_init(&cfg, mode);
982 }
983 #endif /* CONFIG_VIDEO_LCD_SSD2828 */
984
985 static void sunxi_engines_init(void)
986 {
987         sunxi_composer_init();
988         sunxi_lcdc_init();
989         sunxi_drc_init();
990 }
991
992 static void sunxi_mode_set(const struct ctfb_res_modes *mode,
993                            unsigned int address)
994 {
995         int __maybe_unused clk_div, clk_double;
996
997         switch (sunxi_display.monitor) {
998         case sunxi_monitor_none:
999                 break;
1000         case sunxi_monitor_dvi:
1001         case sunxi_monitor_hdmi:
1002 #ifdef CONFIG_VIDEO_HDMI
1003                 sunxi_composer_mode_set(mode, address);
1004                 sunxi_lcdc_tcon1_mode_set(mode, &clk_div, &clk_double, 0);
1005                 sunxi_hdmi_mode_set(mode, clk_div, clk_double);
1006                 sunxi_composer_enable();
1007                 sunxi_lcdc_enable();
1008                 sunxi_hdmi_enable();
1009 #endif
1010                 break;
1011         case sunxi_monitor_lcd:
1012                 sunxi_lcdc_panel_enable();
1013                 if (IS_ENABLED(CONFIG_VIDEO_LCD_HITACHI_TX18D42VM)) {
1014                         mdelay(50); /* Wait for lcd controller power on */
1015                         hitachi_tx18d42vm_init();
1016                 }
1017                 sunxi_composer_mode_set(mode, address);
1018                 sunxi_lcdc_tcon0_mode_set(mode);
1019                 sunxi_composer_enable();
1020                 sunxi_lcdc_enable();
1021 #ifdef CONFIG_VIDEO_LCD_SSD2828
1022                 sunxi_ssd2828_init(mode);
1023 #endif
1024                 sunxi_lcdc_backlight_enable();
1025                 break;
1026         case sunxi_monitor_vga:
1027 #ifdef CONFIG_VIDEO_VGA
1028                 sunxi_composer_mode_set(mode, address);
1029                 sunxi_lcdc_tcon1_mode_set(mode, &clk_div, &clk_double, 1);
1030                 sunxi_vga_mode_set();
1031                 sunxi_composer_enable();
1032                 sunxi_lcdc_enable();
1033                 sunxi_vga_enable();
1034 #elif defined CONFIG_VIDEO_VGA_VIA_LCD
1035                 sunxi_composer_mode_set(mode, address);
1036                 sunxi_lcdc_tcon0_mode_set(mode);
1037                 sunxi_composer_enable();
1038                 sunxi_lcdc_enable();
1039                 sunxi_vga_external_dac_enable();
1040 #endif
1041                 break;
1042         }
1043 }
1044
1045 static const char *sunxi_get_mon_desc(enum sunxi_monitor monitor)
1046 {
1047         switch (monitor) {
1048         case sunxi_monitor_none:        return "none";
1049         case sunxi_monitor_dvi:         return "dvi";
1050         case sunxi_monitor_hdmi:        return "hdmi";
1051         case sunxi_monitor_lcd:         return "lcd";
1052         case sunxi_monitor_vga:         return "vga";
1053         }
1054         return NULL; /* never reached */
1055 }
1056
1057 void *video_hw_init(void)
1058 {
1059         static GraphicDevice *graphic_device = &sunxi_display.graphic_device;
1060         const struct ctfb_res_modes *mode;
1061         struct ctfb_res_modes custom;
1062         const char *options;
1063 #ifdef CONFIG_VIDEO_HDMI
1064         int ret, hpd, hpd_delay, edid;
1065 #endif
1066         char mon[16];
1067         char *lcd_mode = CONFIG_VIDEO_LCD_MODE;
1068         int i;
1069
1070         memset(&sunxi_display, 0, sizeof(struct sunxi_display));
1071
1072         printf("Reserved %dkB of RAM for Framebuffer.\n",
1073                CONFIG_SUNXI_FB_SIZE >> 10);
1074         gd->fb_base = gd->ram_top;
1075
1076         video_get_ctfb_res_modes(RES_MODE_1024x768, 24, &mode,
1077                                  &sunxi_display.depth, &options);
1078 #ifdef CONFIG_VIDEO_HDMI
1079         hpd = video_get_option_int(options, "hpd", 1);
1080         hpd_delay = video_get_option_int(options, "hpd_delay", 500);
1081         edid = video_get_option_int(options, "edid", 1);
1082         sunxi_display.monitor = sunxi_monitor_dvi;
1083 #elif defined CONFIG_VIDEO_VGA_VIA_LCD
1084         sunxi_display.monitor = sunxi_monitor_vga;
1085 #else
1086         sunxi_display.monitor = sunxi_monitor_lcd;
1087 #endif
1088         video_get_option_string(options, "monitor", mon, sizeof(mon),
1089                                 sunxi_get_mon_desc(sunxi_display.monitor));
1090         for (i = 0; i <= SUNXI_MONITOR_LAST; i++) {
1091                 if (strcmp(mon, sunxi_get_mon_desc(i)) == 0) {
1092                         sunxi_display.monitor = i;
1093                         break;
1094                 }
1095         }
1096         if (i > SUNXI_MONITOR_LAST)
1097                 printf("Unknown monitor: '%s', falling back to '%s'\n",
1098                        mon, sunxi_get_mon_desc(sunxi_display.monitor));
1099
1100 #ifdef CONFIG_VIDEO_HDMI
1101         /* If HDMI/DVI is selected do HPD & EDID, and handle fallback */
1102         if (sunxi_display.monitor == sunxi_monitor_dvi ||
1103             sunxi_display.monitor == sunxi_monitor_hdmi) {
1104                 /* Always call hdp_detect, as it also enables clocks, etc. */
1105                 ret = sunxi_hdmi_hpd_detect(hpd_delay);
1106                 if (ret) {
1107                         printf("HDMI connected: ");
1108                         if (edid && sunxi_hdmi_edid_get_mode(&custom) == 0)
1109                                 mode = &custom;
1110                 } else if (hpd) {
1111                         sunxi_hdmi_shutdown();
1112                         /* Fallback to lcd / vga / none */
1113                         if (lcd_mode[0]) {
1114                                 sunxi_display.monitor = sunxi_monitor_lcd;
1115                         } else {
1116 #if defined CONFIG_VIDEO_VGA_VIA_LCD || defined CONFIG_VIDEO_VGA
1117                                 sunxi_display.monitor = sunxi_monitor_vga;
1118 #else
1119                                 sunxi_display.monitor = sunxi_monitor_none;
1120 #endif
1121                         }
1122                 } /* else continue with hdmi/dvi without a cable connected */
1123         }
1124 #endif
1125
1126         switch (sunxi_display.monitor) {
1127         case sunxi_monitor_none:
1128                 return NULL;
1129         case sunxi_monitor_dvi:
1130         case sunxi_monitor_hdmi:
1131 #ifdef CONFIG_VIDEO_HDMI
1132                 break;
1133 #else
1134                 printf("HDMI/DVI not supported on this board\n");
1135                 sunxi_display.monitor = sunxi_monitor_none;
1136                 return NULL;
1137 #endif
1138         case sunxi_monitor_lcd:
1139                 if (lcd_mode[0]) {
1140                         sunxi_display.depth = video_get_params(&custom, lcd_mode);
1141                         mode = &custom;
1142                         break;
1143                 }
1144                 printf("LCD not supported on this board\n");
1145                 sunxi_display.monitor = sunxi_monitor_none;
1146                 return NULL;
1147         case sunxi_monitor_vga:
1148 #if defined CONFIG_VIDEO_VGA_VIA_LCD || defined CONFIG_VIDEO_VGA
1149                 sunxi_display.depth = 18;
1150                 break;
1151 #else
1152                 printf("VGA not supported on this board\n");
1153                 sunxi_display.monitor = sunxi_monitor_none;
1154                 return NULL;
1155 #endif
1156         }
1157
1158         if (mode->vmode != FB_VMODE_NONINTERLACED) {
1159                 printf("Only non-interlaced modes supported, falling back to 1024x768\n");
1160                 mode = &res_mode_init[RES_MODE_1024x768];
1161         } else {
1162                 printf("Setting up a %dx%d %s console\n", mode->xres,
1163                        mode->yres, sunxi_get_mon_desc(sunxi_display.monitor));
1164         }
1165
1166         sunxi_engines_init();
1167         sunxi_mode_set(mode, gd->fb_base - CONFIG_SYS_SDRAM_BASE);
1168
1169         /*
1170          * These are the only members of this structure that are used. All the
1171          * others are driver specific. There is nothing to decribe pitch or
1172          * stride, but we are lucky with our hw.
1173          */
1174         graphic_device->frameAdrs = gd->fb_base;
1175         graphic_device->gdfIndex = GDF_32BIT_X888RGB;
1176         graphic_device->gdfBytesPP = 4;
1177         graphic_device->winSizeX = mode->xres;
1178         graphic_device->winSizeY = mode->yres;
1179
1180         return graphic_device;
1181 }
1182
1183 /*
1184  * Simplefb support.
1185  */
1186 #if defined(CONFIG_OF_BOARD_SETUP) && defined(CONFIG_VIDEO_DT_SIMPLEFB)
1187 int sunxi_simplefb_setup(void *blob)
1188 {
1189         static GraphicDevice *graphic_device = &sunxi_display.graphic_device;
1190         int offset, ret;
1191         const char *pipeline = NULL;
1192
1193 #ifdef CONFIG_MACH_SUN4I
1194 #define PIPELINE_PREFIX "de_fe0-"
1195 #else
1196 #define PIPELINE_PREFIX
1197 #endif
1198
1199         switch (sunxi_display.monitor) {
1200         case sunxi_monitor_none:
1201                 return 0;
1202         case sunxi_monitor_dvi:
1203         case sunxi_monitor_hdmi:
1204                 pipeline = PIPELINE_PREFIX "de_be0-lcd0-hdmi";
1205                 break;
1206         case sunxi_monitor_lcd:
1207                 pipeline = PIPELINE_PREFIX "de_be0-lcd0";
1208                 break;
1209         case sunxi_monitor_vga:
1210 #ifdef CONFIG_VIDEO_VGA
1211                 pipeline = PIPELINE_PREFIX "de_be0-lcd0-tve0";
1212 #elif defined CONFIG_VIDEO_VGA_VIA_LCD
1213                 pipeline = PIPELINE_PREFIX "de_be0-lcd0";
1214 #endif
1215                 break;
1216         }
1217
1218         /* Find a prefilled simpefb node, matching out pipeline config */
1219         offset = fdt_node_offset_by_compatible(blob, -1,
1220                                                "allwinner,simple-framebuffer");
1221         while (offset >= 0) {
1222                 ret = fdt_find_string(blob, offset, "allwinner,pipeline",
1223                                       pipeline);
1224                 if (ret == 0)
1225                         break;
1226                 offset = fdt_node_offset_by_compatible(blob, offset,
1227                                                "allwinner,simple-framebuffer");
1228         }
1229         if (offset < 0) {
1230                 eprintf("Cannot setup simplefb: node not found\n");
1231                 return 0; /* Keep older kernels working */
1232         }
1233
1234         ret = fdt_setup_simplefb_node(blob, offset, gd->fb_base,
1235                         graphic_device->winSizeX, graphic_device->winSizeY,
1236                         graphic_device->winSizeX * graphic_device->gdfBytesPP,
1237                         "x8r8g8b8");
1238         if (ret)
1239                 eprintf("Cannot setup simplefb: Error setting properties\n");
1240
1241         return ret;
1242 }
1243 #endif /* CONFIG_OF_BOARD_SETUP && CONFIG_VIDEO_DT_SIMPLEFB */