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