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