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