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