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