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