sunxi: GPIO pin mux hardware-feature-specific function index defines
[oweals/u-boot.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_MACH_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_MACH_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 #if defined CONFIG_MACH_SUN6I || defined CONFIG_MACH_SUN8I
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 #if defined CONFIG_MACH_SUN6I || defined CONFIG_MACH_SUN8I
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 != -1) {
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 != -1) {
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 != -1) {
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 != -1) {
624                 gpio_request(pin, "lcd_power");
625                 gpio_direction_output(pin, 1);
626         }
627
628         if (reset_pin != -1)
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 != -1)
644                 gpio_direction_output(pin, 1);
645
646         pin = sunxi_name_to_gpio(CONFIG_VIDEO_LCD_BL_PWM);
647         if (pin != -1)
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 #if defined CONFIG_MACH_SUN6I || defined CONFIG_MACH_SUN8I
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         setbits_le32(&ccm->ahb_reset1_cfg, 1 << AHB_RESET_OFFSET_DRC0);
951         clock_set_de_mod_clock(&ccm->iep_drc0_clk_cfg, 300000000);
952 #endif
953 }
954
955 #ifdef CONFIG_VIDEO_VGA_VIA_LCD
956 static void sunxi_vga_external_dac_enable(void)
957 {
958         int pin;
959
960         pin = sunxi_name_to_gpio(CONFIG_VIDEO_VGA_EXTERNAL_DAC_EN);
961         if (pin != -1) {
962                 gpio_request(pin, "vga_enable");
963                 gpio_direction_output(pin, 1);
964         }
965 }
966 #endif /* CONFIG_VIDEO_VGA_VIA_LCD */
967
968 #ifdef CONFIG_VIDEO_LCD_SSD2828
969 static int sunxi_ssd2828_init(const struct ctfb_res_modes *mode)
970 {
971         struct ssd2828_config cfg = {
972                 .csx_pin = name_to_gpio(CONFIG_VIDEO_LCD_SPI_CS),
973                 .sck_pin = name_to_gpio(CONFIG_VIDEO_LCD_SPI_SCLK),
974                 .sdi_pin = name_to_gpio(CONFIG_VIDEO_LCD_SPI_MOSI),
975                 .sdo_pin = name_to_gpio(CONFIG_VIDEO_LCD_SPI_MISO),
976                 .reset_pin = name_to_gpio(CONFIG_VIDEO_LCD_SSD2828_RESET),
977                 .ssd2828_tx_clk_khz  = CONFIG_VIDEO_LCD_SSD2828_TX_CLK * 1000,
978                 .ssd2828_color_depth = 24,
979 #ifdef CONFIG_VIDEO_LCD_PANEL_MIPI_4_LANE_513_MBPS_VIA_SSD2828
980                 .mipi_dsi_number_of_data_lanes           = 4,
981                 .mipi_dsi_bitrate_per_data_lane_mbps     = 513,
982                 .mipi_dsi_delay_after_exit_sleep_mode_ms = 100,
983                 .mipi_dsi_delay_after_set_display_on_ms  = 200
984 #else
985 #error MIPI LCD panel needs configuration parameters
986 #endif
987         };
988
989         if (cfg.csx_pin == -1 || cfg.sck_pin == -1 || cfg.sdi_pin == -1) {
990                 printf("SSD2828: SPI pins are not properly configured\n");
991                 return 1;
992         }
993         if (cfg.reset_pin == -1) {
994                 printf("SSD2828: Reset pin is not properly configured\n");
995                 return 1;
996         }
997
998         return ssd2828_init(&cfg, mode);
999 }
1000 #endif /* CONFIG_VIDEO_LCD_SSD2828 */
1001
1002 static void sunxi_engines_init(void)
1003 {
1004         sunxi_composer_init();
1005         sunxi_lcdc_init();
1006         sunxi_drc_init();
1007 }
1008
1009 static void sunxi_mode_set(const struct ctfb_res_modes *mode,
1010                            unsigned int address)
1011 {
1012         int __maybe_unused clk_div, clk_double;
1013
1014         switch (sunxi_display.monitor) {
1015         case sunxi_monitor_none:
1016                 break;
1017         case sunxi_monitor_dvi:
1018         case sunxi_monitor_hdmi:
1019 #ifdef CONFIG_VIDEO_HDMI
1020                 sunxi_composer_mode_set(mode, address);
1021                 sunxi_lcdc_tcon1_mode_set(mode, &clk_div, &clk_double, 0);
1022                 sunxi_hdmi_mode_set(mode, clk_div, clk_double);
1023                 sunxi_composer_enable();
1024                 sunxi_lcdc_enable();
1025                 sunxi_hdmi_enable();
1026 #endif
1027                 break;
1028         case sunxi_monitor_lcd:
1029                 sunxi_lcdc_panel_enable();
1030                 if (IS_ENABLED(CONFIG_VIDEO_LCD_HITACHI_TX18D42VM)) {
1031                         mdelay(50); /* Wait for lcd controller power on */
1032                         hitachi_tx18d42vm_init();
1033                 }
1034                 if (IS_ENABLED(CONFIG_VIDEO_LCD_TL059WV5C0)) {
1035                         unsigned int orig_i2c_bus = i2c_get_bus_num();
1036                         i2c_set_bus_num(CONFIG_VIDEO_LCD_I2C_BUS);
1037                         i2c_reg_write(0x5c, 0x04, 0x42); /* Turn on the LCD */
1038                         i2c_set_bus_num(orig_i2c_bus);
1039                 }
1040                 sunxi_composer_mode_set(mode, address);
1041                 sunxi_lcdc_tcon0_mode_set(mode, false);
1042                 sunxi_composer_enable();
1043                 sunxi_lcdc_enable();
1044 #ifdef CONFIG_VIDEO_LCD_SSD2828
1045                 sunxi_ssd2828_init(mode);
1046 #endif
1047                 sunxi_lcdc_backlight_enable();
1048                 break;
1049         case sunxi_monitor_vga:
1050 #ifdef CONFIG_VIDEO_VGA
1051                 sunxi_composer_mode_set(mode, address);
1052                 sunxi_lcdc_tcon1_mode_set(mode, &clk_div, &clk_double, 1);
1053                 sunxi_vga_mode_set();
1054                 sunxi_composer_enable();
1055                 sunxi_lcdc_enable();
1056                 sunxi_vga_enable();
1057 #elif defined CONFIG_VIDEO_VGA_VIA_LCD
1058                 sunxi_composer_mode_set(mode, address);
1059                 sunxi_lcdc_tcon0_mode_set(mode, true);
1060                 sunxi_composer_enable();
1061                 sunxi_lcdc_enable();
1062                 sunxi_vga_external_dac_enable();
1063 #endif
1064                 break;
1065         }
1066 }
1067
1068 static const char *sunxi_get_mon_desc(enum sunxi_monitor monitor)
1069 {
1070         switch (monitor) {
1071         case sunxi_monitor_none:        return "none";
1072         case sunxi_monitor_dvi:         return "dvi";
1073         case sunxi_monitor_hdmi:        return "hdmi";
1074         case sunxi_monitor_lcd:         return "lcd";
1075         case sunxi_monitor_vga:         return "vga";
1076         }
1077         return NULL; /* never reached */
1078 }
1079
1080 ulong board_get_usable_ram_top(ulong total_size)
1081 {
1082         return gd->ram_top - CONFIG_SUNXI_MAX_FB_SIZE;
1083 }
1084
1085 void *video_hw_init(void)
1086 {
1087         static GraphicDevice *graphic_device = &sunxi_display.graphic_device;
1088         const struct ctfb_res_modes *mode;
1089         struct ctfb_res_modes custom;
1090         const char *options;
1091 #ifdef CONFIG_VIDEO_HDMI
1092         int ret, hpd, hpd_delay, edid;
1093 #endif
1094         char mon[16];
1095         char *lcd_mode = CONFIG_VIDEO_LCD_MODE;
1096         int i;
1097
1098         memset(&sunxi_display, 0, sizeof(struct sunxi_display));
1099
1100         video_get_ctfb_res_modes(RES_MODE_1024x768, 24, &mode,
1101                                  &sunxi_display.depth, &options);
1102 #ifdef CONFIG_VIDEO_HDMI
1103         hpd = video_get_option_int(options, "hpd", 1);
1104         hpd_delay = video_get_option_int(options, "hpd_delay", 500);
1105         edid = video_get_option_int(options, "edid", 1);
1106         sunxi_display.monitor = sunxi_monitor_dvi;
1107 #elif defined CONFIG_VIDEO_VGA_VIA_LCD
1108         sunxi_display.monitor = sunxi_monitor_vga;
1109 #else
1110         sunxi_display.monitor = sunxi_monitor_lcd;
1111 #endif
1112         video_get_option_string(options, "monitor", mon, sizeof(mon),
1113                                 sunxi_get_mon_desc(sunxi_display.monitor));
1114         for (i = 0; i <= SUNXI_MONITOR_LAST; i++) {
1115                 if (strcmp(mon, sunxi_get_mon_desc(i)) == 0) {
1116                         sunxi_display.monitor = i;
1117                         break;
1118                 }
1119         }
1120         if (i > SUNXI_MONITOR_LAST)
1121                 printf("Unknown monitor: '%s', falling back to '%s'\n",
1122                        mon, sunxi_get_mon_desc(sunxi_display.monitor));
1123
1124 #ifdef CONFIG_VIDEO_HDMI
1125         /* If HDMI/DVI is selected do HPD & EDID, and handle fallback */
1126         if (sunxi_display.monitor == sunxi_monitor_dvi ||
1127             sunxi_display.monitor == sunxi_monitor_hdmi) {
1128                 /* Always call hdp_detect, as it also enables clocks, etc. */
1129                 ret = sunxi_hdmi_hpd_detect(hpd_delay);
1130                 if (ret) {
1131                         printf("HDMI connected: ");
1132                         if (edid && sunxi_hdmi_edid_get_mode(&custom) == 0)
1133                                 mode = &custom;
1134                 } else if (hpd) {
1135                         sunxi_hdmi_shutdown();
1136                         /* Fallback to lcd / vga / none */
1137                         if (lcd_mode[0]) {
1138                                 sunxi_display.monitor = sunxi_monitor_lcd;
1139                         } else {
1140 #if defined CONFIG_VIDEO_VGA_VIA_LCD || defined CONFIG_VIDEO_VGA
1141                                 sunxi_display.monitor = sunxi_monitor_vga;
1142 #else
1143                                 sunxi_display.monitor = sunxi_monitor_none;
1144 #endif
1145                         }
1146                 } /* else continue with hdmi/dvi without a cable connected */
1147         }
1148 #endif
1149
1150         switch (sunxi_display.monitor) {
1151         case sunxi_monitor_none:
1152                 return NULL;
1153         case sunxi_monitor_dvi:
1154         case sunxi_monitor_hdmi:
1155 #ifdef CONFIG_VIDEO_HDMI
1156                 break;
1157 #else
1158                 printf("HDMI/DVI not supported on this board\n");
1159                 sunxi_display.monitor = sunxi_monitor_none;
1160                 return NULL;
1161 #endif
1162         case sunxi_monitor_lcd:
1163                 if (lcd_mode[0]) {
1164                         sunxi_display.depth = video_get_params(&custom, lcd_mode);
1165                         mode = &custom;
1166                         break;
1167                 }
1168                 printf("LCD not supported on this board\n");
1169                 sunxi_display.monitor = sunxi_monitor_none;
1170                 return NULL;
1171         case sunxi_monitor_vga:
1172 #if defined CONFIG_VIDEO_VGA_VIA_LCD || defined CONFIG_VIDEO_VGA
1173                 sunxi_display.depth = 18;
1174                 break;
1175 #else
1176                 printf("VGA not supported on this board\n");
1177                 sunxi_display.monitor = sunxi_monitor_none;
1178                 return NULL;
1179 #endif
1180         }
1181
1182         if (mode->vmode != FB_VMODE_NONINTERLACED) {
1183                 printf("Only non-interlaced modes supported, falling back to 1024x768\n");
1184                 mode = &res_mode_init[RES_MODE_1024x768];
1185         } else {
1186                 printf("Setting up a %dx%d %s console\n", mode->xres,
1187                        mode->yres, sunxi_get_mon_desc(sunxi_display.monitor));
1188         }
1189
1190         sunxi_display.fb_size =
1191                 (mode->xres * mode->yres * 4 + 0xfff) & ~0xfff;
1192         if (sunxi_display.fb_size > CONFIG_SUNXI_MAX_FB_SIZE) {
1193                 printf("Error need %dkB for fb, but only %dkB is reserved\n",
1194                        sunxi_display.fb_size >> 10,
1195                        CONFIG_SUNXI_MAX_FB_SIZE >> 10);
1196                 return NULL;
1197         }
1198
1199         gd->fb_base = gd->bd->bi_dram[0].start +
1200                       gd->bd->bi_dram[0].size - sunxi_display.fb_size;
1201         sunxi_engines_init();
1202         sunxi_mode_set(mode, gd->fb_base - CONFIG_SYS_SDRAM_BASE);
1203
1204         /*
1205          * These are the only members of this structure that are used. All the
1206          * others are driver specific. There is nothing to decribe pitch or
1207          * stride, but we are lucky with our hw.
1208          */
1209         graphic_device->frameAdrs = gd->fb_base;
1210         graphic_device->gdfIndex = GDF_32BIT_X888RGB;
1211         graphic_device->gdfBytesPP = 4;
1212         graphic_device->winSizeX = mode->xres;
1213         graphic_device->winSizeY = mode->yres;
1214
1215         return graphic_device;
1216 }
1217
1218 /*
1219  * Simplefb support.
1220  */
1221 #if defined(CONFIG_OF_BOARD_SETUP) && defined(CONFIG_VIDEO_DT_SIMPLEFB)
1222 int sunxi_simplefb_setup(void *blob)
1223 {
1224         static GraphicDevice *graphic_device = &sunxi_display.graphic_device;
1225         int offset, ret;
1226         u64 start, size;
1227         const char *pipeline = NULL;
1228
1229 #ifdef CONFIG_MACH_SUN4I
1230 #define PIPELINE_PREFIX "de_fe0-"
1231 #else
1232 #define PIPELINE_PREFIX
1233 #endif
1234
1235         switch (sunxi_display.monitor) {
1236         case sunxi_monitor_none:
1237                 return 0;
1238         case sunxi_monitor_dvi:
1239         case sunxi_monitor_hdmi:
1240                 pipeline = PIPELINE_PREFIX "de_be0-lcd0-hdmi";
1241                 break;
1242         case sunxi_monitor_lcd:
1243                 pipeline = PIPELINE_PREFIX "de_be0-lcd0";
1244                 break;
1245         case sunxi_monitor_vga:
1246 #ifdef CONFIG_VIDEO_VGA
1247                 pipeline = PIPELINE_PREFIX "de_be0-lcd0-tve0";
1248 #elif defined CONFIG_VIDEO_VGA_VIA_LCD
1249                 pipeline = PIPELINE_PREFIX "de_be0-lcd0";
1250 #endif
1251                 break;
1252         }
1253
1254         /* Find a prefilled simpefb node, matching out pipeline config */
1255         offset = fdt_node_offset_by_compatible(blob, -1,
1256                                                "allwinner,simple-framebuffer");
1257         while (offset >= 0) {
1258                 ret = fdt_find_string(blob, offset, "allwinner,pipeline",
1259                                       pipeline);
1260                 if (ret == 0)
1261                         break;
1262                 offset = fdt_node_offset_by_compatible(blob, offset,
1263                                                "allwinner,simple-framebuffer");
1264         }
1265         if (offset < 0) {
1266                 eprintf("Cannot setup simplefb: node not found\n");
1267                 return 0; /* Keep older kernels working */
1268         }
1269
1270         /*
1271          * Do not report the framebuffer as free RAM to the OS, note we cannot
1272          * use fdt_add_mem_rsv() here, because then it is still seen as RAM,
1273          * and e.g. Linux refuses to iomap RAM on ARM, see:
1274          * linux/arch/arm/mm/ioremap.c around line 301.
1275          */
1276         start = gd->bd->bi_dram[0].start;
1277         size = gd->bd->bi_dram[0].size - sunxi_display.fb_size;
1278         ret = fdt_fixup_memory_banks(blob, &start, &size, 1);
1279         if (ret) {
1280                 eprintf("Cannot setup simplefb: Error reserving memory\n");
1281                 return ret;
1282         }
1283
1284         ret = fdt_setup_simplefb_node(blob, offset, gd->fb_base,
1285                         graphic_device->winSizeX, graphic_device->winSizeY,
1286                         graphic_device->winSizeX * graphic_device->gdfBytesPP,
1287                         "x8r8g8b8");
1288         if (ret)
1289                 eprintf("Cannot setup simplefb: Error setting properties\n");
1290
1291         return ret;
1292 }
1293 #endif /* CONFIG_OF_BOARD_SETUP && CONFIG_VIDEO_DT_SIMPLEFB */