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