]> git.sur5r.net Git - u-boot/blob - drivers/video/sunxi_display.c
Merge git://git.denx.de/u-boot-fdt
[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         for (pin = SUNXI_GPD(0); pin <= SUNXI_GPD(27); pin++) {
771 #ifdef CONFIG_VIDEO_LCD_IF_PARALLEL
772                 sunxi_gpio_set_cfgpin(pin, SUNXI_GPD_LCD0);
773 #endif
774 #ifdef CONFIG_VIDEO_LCD_IF_LVDS
775                 sunxi_gpio_set_cfgpin(pin, SUNXI_GPD_LVDS0);
776 #endif
777 #ifdef CONFIG_VIDEO_LCD_PANEL_EDP_4_LANE_1620M_VIA_ANX9804
778                 sunxi_gpio_set_drv(pin, 3);
779 #endif
780         }
781
782         sunxi_lcdc_pll_set(0, mode->pixclock_khz, &clk_div, &clk_double);
783
784         /* Use tcon0 */
785         clrsetbits_le32(&lcdc->ctrl, SUNXI_LCDC_CTRL_IO_MAP_MASK,
786                         SUNXI_LCDC_CTRL_IO_MAP_TCON0);
787
788         clk_delay = sunxi_lcdc_get_clk_delay(mode, 0);
789         writel(SUNXI_LCDC_TCON0_CTRL_ENABLE |
790                SUNXI_LCDC_TCON0_CTRL_CLK_DELAY(clk_delay), &lcdc->tcon0_ctrl);
791
792         writel(SUNXI_LCDC_TCON0_DCLK_ENABLE |
793                SUNXI_LCDC_TCON0_DCLK_DIV(clk_div), &lcdc->tcon0_dclk);
794
795         writel(SUNXI_LCDC_X(mode->xres) | SUNXI_LCDC_Y(mode->yres),
796                &lcdc->tcon0_timing_active);
797
798         bp = mode->hsync_len + mode->left_margin;
799         total = mode->xres + mode->right_margin + bp;
800         writel(SUNXI_LCDC_TCON0_TIMING_H_TOTAL(total) |
801                SUNXI_LCDC_TCON0_TIMING_H_BP(bp), &lcdc->tcon0_timing_h);
802
803         bp = mode->vsync_len + mode->upper_margin;
804         total = mode->yres + mode->lower_margin + bp;
805         writel(SUNXI_LCDC_TCON0_TIMING_V_TOTAL(total) |
806                SUNXI_LCDC_TCON0_TIMING_V_BP(bp), &lcdc->tcon0_timing_v);
807
808 #ifdef CONFIG_VIDEO_LCD_IF_PARALLEL
809         writel(SUNXI_LCDC_X(mode->hsync_len) | SUNXI_LCDC_Y(mode->vsync_len),
810                &lcdc->tcon0_timing_sync);
811
812         writel(0, &lcdc->tcon0_hv_intf);
813         writel(0, &lcdc->tcon0_cpu_intf);
814 #endif
815 #ifdef CONFIG_VIDEO_LCD_IF_LVDS
816         val = (sunxi_display.depth == 18) ? 1 : 0;
817         writel(SUNXI_LCDC_TCON0_LVDS_INTF_BITWIDTH(val) |
818                SUNXI_LCDC_TCON0_LVDS_CLK_SEL_TCON0, &lcdc->tcon0_lvds_intf);
819 #endif
820
821         if (sunxi_display.depth == 18 || sunxi_display.depth == 16) {
822                 writel(SUNXI_LCDC_TCON0_FRM_SEED, &lcdc->tcon0_frm_seed[0]);
823                 writel(SUNXI_LCDC_TCON0_FRM_SEED, &lcdc->tcon0_frm_seed[1]);
824                 writel(SUNXI_LCDC_TCON0_FRM_SEED, &lcdc->tcon0_frm_seed[2]);
825                 writel(SUNXI_LCDC_TCON0_FRM_SEED, &lcdc->tcon0_frm_seed[3]);
826                 writel(SUNXI_LCDC_TCON0_FRM_SEED, &lcdc->tcon0_frm_seed[4]);
827                 writel(SUNXI_LCDC_TCON0_FRM_SEED, &lcdc->tcon0_frm_seed[5]);
828                 writel(SUNXI_LCDC_TCON0_FRM_TAB0, &lcdc->tcon0_frm_table[0]);
829                 writel(SUNXI_LCDC_TCON0_FRM_TAB1, &lcdc->tcon0_frm_table[1]);
830                 writel(SUNXI_LCDC_TCON0_FRM_TAB2, &lcdc->tcon0_frm_table[2]);
831                 writel(SUNXI_LCDC_TCON0_FRM_TAB3, &lcdc->tcon0_frm_table[3]);
832                 writel(((sunxi_display.depth == 18) ?
833                         SUNXI_LCDC_TCON0_FRM_CTRL_RGB666 :
834                         SUNXI_LCDC_TCON0_FRM_CTRL_RGB565),
835                        &lcdc->tcon0_frm_ctrl);
836         }
837
838         val = SUNXI_LCDC_TCON0_IO_POL_DCLK_PHASE(CONFIG_VIDEO_LCD_DCLK_PHASE);
839         if (!(mode->sync & FB_SYNC_HOR_HIGH_ACT))
840                 val |= SUNXI_LCDC_TCON_HSYNC_MASK;
841         if (!(mode->sync & FB_SYNC_VERT_HIGH_ACT))
842                 val |= SUNXI_LCDC_TCON_VSYNC_MASK;
843
844 #ifdef CONFIG_VIDEO_VGA_VIA_LCD_FORCE_SYNC_ACTIVE_HIGH
845         if (for_ext_vga_dac)
846                 val = 0;
847 #endif
848         writel(val, &lcdc->tcon0_io_polarity);
849
850         writel(0, &lcdc->tcon0_io_tristate);
851 }
852
853 #if defined CONFIG_VIDEO_HDMI || defined CONFIG_VIDEO_VGA || defined CONFIG_VIDEO_COMPOSITE
854 static void sunxi_lcdc_tcon1_mode_set(const struct ctfb_res_modes *mode,
855                                       int *clk_div, int *clk_double,
856                                       bool use_portd_hvsync)
857 {
858         struct sunxi_lcdc_reg * const lcdc =
859                 (struct sunxi_lcdc_reg *)SUNXI_LCD0_BASE;
860         int bp, clk_delay, total, val, yres;
861
862         /* Use tcon1 */
863         clrsetbits_le32(&lcdc->ctrl, SUNXI_LCDC_CTRL_IO_MAP_MASK,
864                         SUNXI_LCDC_CTRL_IO_MAP_TCON1);
865
866         clk_delay = sunxi_lcdc_get_clk_delay(mode, 1);
867         writel(SUNXI_LCDC_TCON1_CTRL_ENABLE |
868                ((mode->vmode == FB_VMODE_INTERLACED) ?
869                         SUNXI_LCDC_TCON1_CTRL_INTERLACE_ENABLE : 0) |
870                SUNXI_LCDC_TCON1_CTRL_CLK_DELAY(clk_delay), &lcdc->tcon1_ctrl);
871
872         yres = mode->yres;
873         if (mode->vmode == FB_VMODE_INTERLACED)
874                 yres /= 2;
875         writel(SUNXI_LCDC_X(mode->xres) | SUNXI_LCDC_Y(yres),
876                &lcdc->tcon1_timing_source);
877         writel(SUNXI_LCDC_X(mode->xres) | SUNXI_LCDC_Y(yres),
878                &lcdc->tcon1_timing_scale);
879         writel(SUNXI_LCDC_X(mode->xres) | SUNXI_LCDC_Y(yres),
880                &lcdc->tcon1_timing_out);
881
882         bp = mode->hsync_len + mode->left_margin;
883         total = mode->xres + mode->right_margin + bp;
884         writel(SUNXI_LCDC_TCON1_TIMING_H_TOTAL(total) |
885                SUNXI_LCDC_TCON1_TIMING_H_BP(bp), &lcdc->tcon1_timing_h);
886
887         bp = mode->vsync_len + mode->upper_margin;
888         total = mode->yres + mode->lower_margin + bp;
889         if (mode->vmode == FB_VMODE_NONINTERLACED)
890                 total *= 2;
891         writel(SUNXI_LCDC_TCON1_TIMING_V_TOTAL(total) |
892                SUNXI_LCDC_TCON1_TIMING_V_BP(bp), &lcdc->tcon1_timing_v);
893
894         writel(SUNXI_LCDC_X(mode->hsync_len) | SUNXI_LCDC_Y(mode->vsync_len),
895                &lcdc->tcon1_timing_sync);
896
897         if (use_portd_hvsync) {
898                 sunxi_gpio_set_cfgpin(SUNXI_GPD(26), SUNXI_GPD_LCD0);
899                 sunxi_gpio_set_cfgpin(SUNXI_GPD(27), SUNXI_GPD_LCD0);
900
901                 val = 0;
902                 if (mode->sync & FB_SYNC_HOR_HIGH_ACT)
903                         val |= SUNXI_LCDC_TCON_HSYNC_MASK;
904                 if (mode->sync & FB_SYNC_VERT_HIGH_ACT)
905                         val |= SUNXI_LCDC_TCON_VSYNC_MASK;
906                 writel(val, &lcdc->tcon1_io_polarity);
907
908                 clrbits_le32(&lcdc->tcon1_io_tristate,
909                              SUNXI_LCDC_TCON_VSYNC_MASK |
910                              SUNXI_LCDC_TCON_HSYNC_MASK);
911         }
912
913 #ifdef CONFIG_MACH_SUN5I
914         if (sunxi_is_composite())
915                 clrsetbits_le32(&lcdc->mux_ctrl, SUNXI_LCDC_MUX_CTRL_SRC0_MASK,
916                                 SUNXI_LCDC_MUX_CTRL_SRC0(1));
917 #endif
918
919         sunxi_lcdc_pll_set(1, mode->pixclock_khz, clk_div, clk_double);
920 }
921 #endif /* CONFIG_VIDEO_HDMI || defined CONFIG_VIDEO_VGA || CONFIG_VIDEO_COMPOSITE */
922
923 #ifdef CONFIG_VIDEO_HDMI
924
925 static void sunxi_hdmi_setup_info_frames(const struct ctfb_res_modes *mode)
926 {
927         struct sunxi_hdmi_reg * const hdmi =
928                 (struct sunxi_hdmi_reg *)SUNXI_HDMI_BASE;
929         u8 checksum = 0;
930         u8 avi_info_frame[17] = {
931                 0x82, 0x02, 0x0d, 0x00, 0x12, 0x00, 0x88, 0x00,
932                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
933                 0x00
934         };
935         u8 vendor_info_frame[19] = {
936                 0x81, 0x01, 0x06, 0x29, 0x03, 0x0c, 0x00, 0x40,
937                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
938                 0x00, 0x00, 0x00
939         };
940         int i;
941
942         if (mode->pixclock_khz <= 27000)
943                 avi_info_frame[5] = 0x40; /* SD-modes, ITU601 colorspace */
944         else
945                 avi_info_frame[5] = 0x80; /* HD-modes, ITU709 colorspace */
946
947         if (mode->xres * 100 / mode->yres < 156)
948                 avi_info_frame[5] |= 0x18; /* 4 : 3 */
949         else
950                 avi_info_frame[5] |= 0x28; /* 16 : 9 */
951
952         for (i = 0; i < ARRAY_SIZE(avi_info_frame); i++)
953                 checksum += avi_info_frame[i];
954
955         avi_info_frame[3] = 0x100 - checksum;
956
957         for (i = 0; i < ARRAY_SIZE(avi_info_frame); i++)
958                 writeb(avi_info_frame[i], &hdmi->avi_info_frame[i]);
959
960         writel(SUNXI_HDMI_QCP_PACKET0, &hdmi->qcp_packet0);
961         writel(SUNXI_HDMI_QCP_PACKET1, &hdmi->qcp_packet1);
962
963         for (i = 0; i < ARRAY_SIZE(vendor_info_frame); i++)
964                 writeb(vendor_info_frame[i], &hdmi->vendor_info_frame[i]);
965
966         writel(SUNXI_HDMI_PKT_CTRL0, &hdmi->pkt_ctrl0);
967         writel(SUNXI_HDMI_PKT_CTRL1, &hdmi->pkt_ctrl1);
968
969         setbits_le32(&hdmi->video_ctrl, SUNXI_HDMI_VIDEO_CTRL_HDMI);
970 }
971
972 static void sunxi_hdmi_mode_set(const struct ctfb_res_modes *mode,
973                                 int clk_div, int clk_double)
974 {
975         struct sunxi_hdmi_reg * const hdmi =
976                 (struct sunxi_hdmi_reg *)SUNXI_HDMI_BASE;
977         int x, y;
978
979         /* Write clear interrupt status bits */
980         writel(SUNXI_HDMI_IRQ_STATUS_BITS, &hdmi->irq);
981
982         if (sunxi_display.monitor == sunxi_monitor_hdmi)
983                 sunxi_hdmi_setup_info_frames(mode);
984
985         /* Set input sync enable */
986         writel(SUNXI_HDMI_UNKNOWN_INPUT_SYNC, &hdmi->unknown);
987
988         /* Init various registers, select pll3 as clock source */
989         writel(SUNXI_HDMI_VIDEO_POL_TX_CLK, &hdmi->video_polarity);
990         writel(SUNXI_HDMI_PAD_CTRL0_RUN, &hdmi->pad_ctrl0);
991         writel(SUNXI_HDMI_PAD_CTRL1, &hdmi->pad_ctrl1);
992         writel(SUNXI_HDMI_PLL_CTRL, &hdmi->pll_ctrl);
993         writel(SUNXI_HDMI_PLL_DBG0_PLL3, &hdmi->pll_dbg0);
994
995         /* Setup clk div and doubler */
996         clrsetbits_le32(&hdmi->pll_ctrl, SUNXI_HDMI_PLL_CTRL_DIV_MASK,
997                         SUNXI_HDMI_PLL_CTRL_DIV(clk_div));
998         if (!clk_double)
999                 setbits_le32(&hdmi->pad_ctrl1, SUNXI_HDMI_PAD_CTRL1_HALVE);
1000
1001         /* Setup timing registers */
1002         writel(SUNXI_HDMI_Y(mode->yres) | SUNXI_HDMI_X(mode->xres),
1003                &hdmi->video_size);
1004
1005         x = mode->hsync_len + mode->left_margin;
1006         y = mode->vsync_len + mode->upper_margin;
1007         writel(SUNXI_HDMI_Y(y) | SUNXI_HDMI_X(x), &hdmi->video_bp);
1008
1009         x = mode->right_margin;
1010         y = mode->lower_margin;
1011         writel(SUNXI_HDMI_Y(y) | SUNXI_HDMI_X(x), &hdmi->video_fp);
1012
1013         x = mode->hsync_len;
1014         y = mode->vsync_len;
1015         writel(SUNXI_HDMI_Y(y) | SUNXI_HDMI_X(x), &hdmi->video_spw);
1016
1017         if (mode->sync & FB_SYNC_HOR_HIGH_ACT)
1018                 setbits_le32(&hdmi->video_polarity, SUNXI_HDMI_VIDEO_POL_HOR);
1019
1020         if (mode->sync & FB_SYNC_VERT_HIGH_ACT)
1021                 setbits_le32(&hdmi->video_polarity, SUNXI_HDMI_VIDEO_POL_VER);
1022 }
1023
1024 static void sunxi_hdmi_enable(void)
1025 {
1026         struct sunxi_hdmi_reg * const hdmi =
1027                 (struct sunxi_hdmi_reg *)SUNXI_HDMI_BASE;
1028
1029         udelay(100);
1030         setbits_le32(&hdmi->video_ctrl, SUNXI_HDMI_VIDEO_CTRL_ENABLE);
1031 }
1032
1033 #endif /* CONFIG_VIDEO_HDMI */
1034
1035 #if defined CONFIG_VIDEO_VGA || defined CONFIG_VIDEO_COMPOSITE
1036
1037 static void sunxi_tvencoder_mode_set(void)
1038 {
1039         struct sunxi_ccm_reg * const ccm =
1040                 (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
1041         struct sunxi_tve_reg * const tve =
1042                 (struct sunxi_tve_reg *)SUNXI_TVE0_BASE;
1043
1044         /* Reset off */
1045         setbits_le32(&ccm->lcd0_ch0_clk_cfg, CCM_LCD_CH0_CTRL_TVE_RST);
1046         /* Clock on */
1047         setbits_le32(&ccm->ahb_gate1, 1 << AHB_GATE_OFFSET_TVE0);
1048
1049         switch (sunxi_display.monitor) {
1050         case sunxi_monitor_vga:
1051                 writel(SUNXI_TVE_GCTRL_DAC_INPUT(0, 1) |
1052                        SUNXI_TVE_GCTRL_DAC_INPUT(1, 2) |
1053                        SUNXI_TVE_GCTRL_DAC_INPUT(2, 3), &tve->gctrl);
1054                 writel(SUNXI_TVE_CFG0_VGA, &tve->cfg0);
1055                 writel(SUNXI_TVE_DAC_CFG0_VGA, &tve->dac_cfg0);
1056                 writel(SUNXI_TVE_UNKNOWN1_VGA, &tve->unknown1);
1057                 break;
1058         case sunxi_monitor_composite_pal_nc:
1059                 writel(SUNXI_TVE_CHROMA_FREQ_PAL_NC, &tve->chroma_freq);
1060                 /* Fall through */
1061         case sunxi_monitor_composite_pal:
1062                 writel(SUNXI_TVE_GCTRL_DAC_INPUT(0, 1) |
1063                        SUNXI_TVE_GCTRL_DAC_INPUT(1, 2) |
1064                        SUNXI_TVE_GCTRL_DAC_INPUT(2, 3) |
1065                        SUNXI_TVE_GCTRL_DAC_INPUT(3, 4), &tve->gctrl);
1066                 writel(SUNXI_TVE_CFG0_PAL, &tve->cfg0);
1067                 writel(SUNXI_TVE_DAC_CFG0_COMPOSITE, &tve->dac_cfg0);
1068                 writel(SUNXI_TVE_FILTER_COMPOSITE, &tve->filter);
1069                 writel(SUNXI_TVE_PORCH_NUM_PAL, &tve->porch_num);
1070                 writel(SUNXI_TVE_LINE_NUM_PAL, &tve->line_num);
1071                 writel(SUNXI_TVE_BLANK_BLACK_LEVEL_PAL, &tve->blank_black_level);
1072                 writel(SUNXI_TVE_UNKNOWN1_COMPOSITE, &tve->unknown1);
1073                 writel(SUNXI_TVE_CBR_LEVEL_PAL, &tve->cbr_level);
1074                 writel(SUNXI_TVE_BURST_WIDTH_COMPOSITE, &tve->burst_width);
1075                 writel(SUNXI_TVE_UNKNOWN2_PAL, &tve->unknown2);
1076                 writel(SUNXI_TVE_ACTIVE_NUM_COMPOSITE, &tve->active_num);
1077                 writel(SUNXI_TVE_CHROMA_BW_GAIN_COMP, &tve->chroma_bw_gain);
1078                 writel(SUNXI_TVE_NOTCH_WIDTH_COMPOSITE, &tve->notch_width);
1079                 writel(SUNXI_TVE_RESYNC_NUM_PAL, &tve->resync_num);
1080                 writel(SUNXI_TVE_SLAVE_PARA_COMPOSITE, &tve->slave_para);
1081                 break;
1082         case sunxi_monitor_composite_pal_m:
1083                 writel(SUNXI_TVE_CHROMA_FREQ_PAL_M, &tve->chroma_freq);
1084                 writel(SUNXI_TVE_COLOR_BURST_PAL_M, &tve->color_burst);
1085                 /* Fall through */
1086         case sunxi_monitor_composite_ntsc:
1087                 writel(SUNXI_TVE_GCTRL_DAC_INPUT(0, 1) |
1088                        SUNXI_TVE_GCTRL_DAC_INPUT(1, 2) |
1089                        SUNXI_TVE_GCTRL_DAC_INPUT(2, 3) |
1090                        SUNXI_TVE_GCTRL_DAC_INPUT(3, 4), &tve->gctrl);
1091                 writel(SUNXI_TVE_CFG0_NTSC, &tve->cfg0);
1092                 writel(SUNXI_TVE_DAC_CFG0_COMPOSITE, &tve->dac_cfg0);
1093                 writel(SUNXI_TVE_FILTER_COMPOSITE, &tve->filter);
1094                 writel(SUNXI_TVE_PORCH_NUM_NTSC, &tve->porch_num);
1095                 writel(SUNXI_TVE_LINE_NUM_NTSC, &tve->line_num);
1096                 writel(SUNXI_TVE_BLANK_BLACK_LEVEL_NTSC, &tve->blank_black_level);
1097                 writel(SUNXI_TVE_UNKNOWN1_COMPOSITE, &tve->unknown1);
1098                 writel(SUNXI_TVE_CBR_LEVEL_NTSC, &tve->cbr_level);
1099                 writel(SUNXI_TVE_BURST_PHASE_NTSC, &tve->burst_phase);
1100                 writel(SUNXI_TVE_BURST_WIDTH_COMPOSITE, &tve->burst_width);
1101                 writel(SUNXI_TVE_UNKNOWN2_NTSC, &tve->unknown2);
1102                 writel(SUNXI_TVE_SYNC_VBI_LEVEL_NTSC, &tve->sync_vbi_level);
1103                 writel(SUNXI_TVE_ACTIVE_NUM_COMPOSITE, &tve->active_num);
1104                 writel(SUNXI_TVE_CHROMA_BW_GAIN_COMP, &tve->chroma_bw_gain);
1105                 writel(SUNXI_TVE_NOTCH_WIDTH_COMPOSITE, &tve->notch_width);
1106                 writel(SUNXI_TVE_RESYNC_NUM_NTSC, &tve->resync_num);
1107                 writel(SUNXI_TVE_SLAVE_PARA_COMPOSITE, &tve->slave_para);
1108                 break;
1109         case sunxi_monitor_none:
1110         case sunxi_monitor_dvi:
1111         case sunxi_monitor_hdmi:
1112         case sunxi_monitor_lcd:
1113                 break;
1114         }
1115 }
1116
1117 static void sunxi_tvencoder_enable(void)
1118 {
1119         struct sunxi_tve_reg * const tve =
1120                 (struct sunxi_tve_reg *)SUNXI_TVE0_BASE;
1121
1122         setbits_le32(&tve->gctrl, SUNXI_TVE_GCTRL_ENABLE);
1123 }
1124
1125 #endif /* CONFIG_VIDEO_VGA || defined CONFIG_VIDEO_COMPOSITE */
1126
1127 static void sunxi_drc_init(void)
1128 {
1129 #ifdef CONFIG_SUNXI_GEN_SUN6I
1130         struct sunxi_ccm_reg * const ccm =
1131                 (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
1132
1133         /* On sun6i the drc must be clocked even when in pass-through mode */
1134 #ifdef CONFIG_MACH_SUN8I_A33
1135         setbits_le32(&ccm->ahb_reset1_cfg, 1 << AHB_RESET_OFFSET_SAT);
1136 #endif
1137         setbits_le32(&ccm->ahb_reset1_cfg, 1 << AHB_RESET_OFFSET_DRC0);
1138         clock_set_de_mod_clock(&ccm->iep_drc0_clk_cfg, 300000000);
1139 #endif
1140 }
1141
1142 #ifdef CONFIG_VIDEO_VGA_VIA_LCD
1143 static void sunxi_vga_external_dac_enable(void)
1144 {
1145         int pin;
1146
1147         pin = sunxi_name_to_gpio(CONFIG_VIDEO_VGA_EXTERNAL_DAC_EN);
1148         if (pin >= 0) {
1149                 gpio_request(pin, "vga_enable");
1150                 gpio_direction_output(pin, 1);
1151         }
1152 }
1153 #endif /* CONFIG_VIDEO_VGA_VIA_LCD */
1154
1155 #ifdef CONFIG_VIDEO_LCD_SSD2828
1156 static int sunxi_ssd2828_init(const struct ctfb_res_modes *mode)
1157 {
1158         struct ssd2828_config cfg = {
1159                 .csx_pin = name_to_gpio(CONFIG_VIDEO_LCD_SPI_CS),
1160                 .sck_pin = name_to_gpio(CONFIG_VIDEO_LCD_SPI_SCLK),
1161                 .sdi_pin = name_to_gpio(CONFIG_VIDEO_LCD_SPI_MOSI),
1162                 .sdo_pin = name_to_gpio(CONFIG_VIDEO_LCD_SPI_MISO),
1163                 .reset_pin = name_to_gpio(CONFIG_VIDEO_LCD_SSD2828_RESET),
1164                 .ssd2828_tx_clk_khz  = CONFIG_VIDEO_LCD_SSD2828_TX_CLK * 1000,
1165                 .ssd2828_color_depth = 24,
1166 #ifdef CONFIG_VIDEO_LCD_PANEL_MIPI_4_LANE_513_MBPS_VIA_SSD2828
1167                 .mipi_dsi_number_of_data_lanes           = 4,
1168                 .mipi_dsi_bitrate_per_data_lane_mbps     = 513,
1169                 .mipi_dsi_delay_after_exit_sleep_mode_ms = 100,
1170                 .mipi_dsi_delay_after_set_display_on_ms  = 200
1171 #else
1172 #error MIPI LCD panel needs configuration parameters
1173 #endif
1174         };
1175
1176         if (cfg.csx_pin == -1 || cfg.sck_pin == -1 || cfg.sdi_pin == -1) {
1177                 printf("SSD2828: SPI pins are not properly configured\n");
1178                 return 1;
1179         }
1180         if (cfg.reset_pin == -1) {
1181                 printf("SSD2828: Reset pin is not properly configured\n");
1182                 return 1;
1183         }
1184
1185         return ssd2828_init(&cfg, mode);
1186 }
1187 #endif /* CONFIG_VIDEO_LCD_SSD2828 */
1188
1189 static void sunxi_engines_init(void)
1190 {
1191         sunxi_composer_init();
1192         sunxi_lcdc_init();
1193         sunxi_drc_init();
1194 }
1195
1196 static void sunxi_mode_set(const struct ctfb_res_modes *mode,
1197                            unsigned int address)
1198 {
1199         int __maybe_unused clk_div, clk_double;
1200
1201         switch (sunxi_display.monitor) {
1202         case sunxi_monitor_none:
1203                 break;
1204         case sunxi_monitor_dvi:
1205         case sunxi_monitor_hdmi:
1206 #ifdef CONFIG_VIDEO_HDMI
1207                 sunxi_composer_mode_set(mode, address);
1208                 sunxi_lcdc_tcon1_mode_set(mode, &clk_div, &clk_double, 0);
1209                 sunxi_hdmi_mode_set(mode, clk_div, clk_double);
1210                 sunxi_composer_enable();
1211                 sunxi_lcdc_enable();
1212                 sunxi_hdmi_enable();
1213 #endif
1214                 break;
1215         case sunxi_monitor_lcd:
1216                 sunxi_lcdc_panel_enable();
1217                 if (IS_ENABLED(CONFIG_VIDEO_LCD_PANEL_EDP_4_LANE_1620M_VIA_ANX9804)) {
1218                         /*
1219                          * The anx9804 needs 1.8V from eldo3, we do this here
1220                          * and not via CONFIG_AXP_ELDO3_VOLT from board_init()
1221                          * to avoid turning this on when using hdmi output.
1222                          */
1223                         axp_set_eldo(3, 1800);
1224                         anx9804_init(CONFIG_VIDEO_LCD_I2C_BUS, 4,
1225                                      ANX9804_DATA_RATE_1620M,
1226                                      sunxi_display.depth);
1227                 }
1228                 if (IS_ENABLED(CONFIG_VIDEO_LCD_HITACHI_TX18D42VM)) {
1229                         mdelay(50); /* Wait for lcd controller power on */
1230                         hitachi_tx18d42vm_init();
1231                 }
1232                 if (IS_ENABLED(CONFIG_VIDEO_LCD_TL059WV5C0)) {
1233                         unsigned int orig_i2c_bus = i2c_get_bus_num();
1234                         i2c_set_bus_num(CONFIG_VIDEO_LCD_I2C_BUS);
1235                         i2c_reg_write(0x5c, 0x04, 0x42); /* Turn on the LCD */
1236                         i2c_set_bus_num(orig_i2c_bus);
1237                 }
1238                 sunxi_composer_mode_set(mode, address);
1239                 sunxi_lcdc_tcon0_mode_set(mode, false);
1240                 sunxi_composer_enable();
1241                 sunxi_lcdc_enable();
1242 #ifdef CONFIG_VIDEO_LCD_SSD2828
1243                 sunxi_ssd2828_init(mode);
1244 #endif
1245                 sunxi_lcdc_backlight_enable();
1246                 break;
1247         case sunxi_monitor_vga:
1248 #ifdef CONFIG_VIDEO_VGA
1249                 sunxi_composer_mode_set(mode, address);
1250                 sunxi_lcdc_tcon1_mode_set(mode, &clk_div, &clk_double, 1);
1251                 sunxi_tvencoder_mode_set();
1252                 sunxi_composer_enable();
1253                 sunxi_lcdc_enable();
1254                 sunxi_tvencoder_enable();
1255 #elif defined CONFIG_VIDEO_VGA_VIA_LCD
1256                 sunxi_composer_mode_set(mode, address);
1257                 sunxi_lcdc_tcon0_mode_set(mode, true);
1258                 sunxi_composer_enable();
1259                 sunxi_lcdc_enable();
1260                 sunxi_vga_external_dac_enable();
1261 #endif
1262                 break;
1263         case sunxi_monitor_composite_pal:
1264         case sunxi_monitor_composite_ntsc:
1265         case sunxi_monitor_composite_pal_m:
1266         case sunxi_monitor_composite_pal_nc:
1267 #ifdef CONFIG_VIDEO_COMPOSITE
1268                 sunxi_composer_mode_set(mode, address);
1269                 sunxi_lcdc_tcon1_mode_set(mode, &clk_div, &clk_double, 0);
1270                 sunxi_tvencoder_mode_set();
1271                 sunxi_composer_enable();
1272                 sunxi_lcdc_enable();
1273                 sunxi_tvencoder_enable();
1274 #endif
1275                 break;
1276         }
1277 }
1278
1279 static const char *sunxi_get_mon_desc(enum sunxi_monitor monitor)
1280 {
1281         switch (monitor) {
1282         case sunxi_monitor_none:                return "none";
1283         case sunxi_monitor_dvi:                 return "dvi";
1284         case sunxi_monitor_hdmi:                return "hdmi";
1285         case sunxi_monitor_lcd:                 return "lcd";
1286         case sunxi_monitor_vga:                 return "vga";
1287         case sunxi_monitor_composite_pal:       return "composite-pal";
1288         case sunxi_monitor_composite_ntsc:      return "composite-ntsc";
1289         case sunxi_monitor_composite_pal_m:     return "composite-pal-m";
1290         case sunxi_monitor_composite_pal_nc:    return "composite-pal-nc";
1291         }
1292         return NULL; /* never reached */
1293 }
1294
1295 ulong board_get_usable_ram_top(ulong total_size)
1296 {
1297         return gd->ram_top - CONFIG_SUNXI_MAX_FB_SIZE;
1298 }
1299
1300 static bool sunxi_has_hdmi(void)
1301 {
1302 #ifdef CONFIG_VIDEO_HDMI
1303         return true;
1304 #else
1305         return false;
1306 #endif
1307 }
1308
1309 static bool sunxi_has_lcd(void)
1310 {
1311         char *lcd_mode = CONFIG_VIDEO_LCD_MODE;
1312
1313         return lcd_mode[0] != 0;
1314 }
1315
1316 static bool sunxi_has_vga(void)
1317 {
1318 #if defined CONFIG_VIDEO_VGA || defined CONFIG_VIDEO_VGA_VIA_LCD
1319         return true;
1320 #else
1321         return false;
1322 #endif
1323 }
1324
1325 static bool sunxi_has_composite(void)
1326 {
1327 #ifdef CONFIG_VIDEO_COMPOSITE
1328         return true;
1329 #else
1330         return false;
1331 #endif
1332 }
1333
1334 static enum sunxi_monitor sunxi_get_default_mon(bool allow_hdmi)
1335 {
1336         if (allow_hdmi && sunxi_has_hdmi())
1337                 return sunxi_monitor_dvi;
1338         else if (sunxi_has_lcd())
1339                 return sunxi_monitor_lcd;
1340         else if (sunxi_has_vga())
1341                 return sunxi_monitor_vga;
1342         else if (sunxi_has_composite())
1343                 return sunxi_monitor_composite_pal;
1344         else
1345                 return sunxi_monitor_none;
1346 }
1347
1348 void *video_hw_init(void)
1349 {
1350         static GraphicDevice *graphic_device = &sunxi_display.graphic_device;
1351         const struct ctfb_res_modes *mode;
1352         struct ctfb_res_modes custom;
1353         const char *options;
1354 #ifdef CONFIG_VIDEO_HDMI
1355         int ret, hpd, hpd_delay, edid;
1356 #endif
1357         int i, overscan_offset, overscan_x, overscan_y;
1358         unsigned int fb_dma_addr;
1359         char mon[16];
1360         char *lcd_mode = CONFIG_VIDEO_LCD_MODE;
1361
1362         memset(&sunxi_display, 0, sizeof(struct sunxi_display));
1363
1364         video_get_ctfb_res_modes(RES_MODE_1024x768, 24, &mode,
1365                                  &sunxi_display.depth, &options);
1366 #ifdef CONFIG_VIDEO_HDMI
1367         hpd = video_get_option_int(options, "hpd", 1);
1368         hpd_delay = video_get_option_int(options, "hpd_delay", 500);
1369         edid = video_get_option_int(options, "edid", 1);
1370 #endif
1371         overscan_x = video_get_option_int(options, "overscan_x", -1);
1372         overscan_y = video_get_option_int(options, "overscan_y", -1);
1373         sunxi_display.monitor = sunxi_get_default_mon(true);
1374         video_get_option_string(options, "monitor", mon, sizeof(mon),
1375                                 sunxi_get_mon_desc(sunxi_display.monitor));
1376         for (i = 0; i <= SUNXI_MONITOR_LAST; i++) {
1377                 if (strcmp(mon, sunxi_get_mon_desc(i)) == 0) {
1378                         sunxi_display.monitor = i;
1379                         break;
1380                 }
1381         }
1382         if (i > SUNXI_MONITOR_LAST)
1383                 printf("Unknown monitor: '%s', falling back to '%s'\n",
1384                        mon, sunxi_get_mon_desc(sunxi_display.monitor));
1385
1386 #ifdef CONFIG_VIDEO_HDMI
1387         /* If HDMI/DVI is selected do HPD & EDID, and handle fallback */
1388         if (sunxi_display.monitor == sunxi_monitor_dvi ||
1389             sunxi_display.monitor == sunxi_monitor_hdmi) {
1390                 /* Always call hdp_detect, as it also enables clocks, etc. */
1391                 ret = sunxi_hdmi_hpd_detect(hpd_delay);
1392                 if (ret) {
1393                         printf("HDMI connected: ");
1394                         if (edid && sunxi_hdmi_edid_get_mode(&custom) == 0)
1395                                 mode = &custom;
1396                 } else if (hpd) {
1397                         sunxi_hdmi_shutdown();
1398                         sunxi_display.monitor = sunxi_get_default_mon(false);
1399                 } /* else continue with hdmi/dvi without a cable connected */
1400         }
1401 #endif
1402
1403         switch (sunxi_display.monitor) {
1404         case sunxi_monitor_none:
1405                 return NULL;
1406         case sunxi_monitor_dvi:
1407         case sunxi_monitor_hdmi:
1408                 if (!sunxi_has_hdmi()) {
1409                         printf("HDMI/DVI not supported on this board\n");
1410                         sunxi_display.monitor = sunxi_monitor_none;
1411                         return NULL;
1412                 }
1413                 break;
1414         case sunxi_monitor_lcd:
1415                 if (!sunxi_has_lcd()) {
1416                         printf("LCD not supported on this board\n");
1417                         sunxi_display.monitor = sunxi_monitor_none;
1418                         return NULL;
1419                 }
1420                 sunxi_display.depth = video_get_params(&custom, lcd_mode);
1421                 mode = &custom;
1422                 break;
1423         case sunxi_monitor_vga:
1424                 if (!sunxi_has_vga()) {
1425                         printf("VGA not supported on this board\n");
1426                         sunxi_display.monitor = sunxi_monitor_none;
1427                         return NULL;
1428                 }
1429                 sunxi_display.depth = 18;
1430                 break;
1431         case sunxi_monitor_composite_pal:
1432         case sunxi_monitor_composite_ntsc:
1433         case sunxi_monitor_composite_pal_m:
1434         case sunxi_monitor_composite_pal_nc:
1435                 if (!sunxi_has_composite()) {
1436                         printf("Composite video not supported on this board\n");
1437                         sunxi_display.monitor = sunxi_monitor_none;
1438                         return NULL;
1439                 }
1440                 if (sunxi_display.monitor == sunxi_monitor_composite_pal ||
1441                     sunxi_display.monitor == sunxi_monitor_composite_pal_nc)
1442                         mode = &composite_video_modes[0];
1443                 else
1444                         mode = &composite_video_modes[1];
1445                 sunxi_display.depth = 24;
1446                 break;
1447         }
1448
1449         /* Yes these defaults are quite high, overscan on composite sucks... */
1450         if (overscan_x == -1)
1451                 overscan_x = sunxi_is_composite() ? 32 : 0;
1452         if (overscan_y == -1)
1453                 overscan_y = sunxi_is_composite() ? 20 : 0;
1454
1455         sunxi_display.fb_size =
1456                 (mode->xres * mode->yres * 4 + 0xfff) & ~0xfff;
1457         overscan_offset = (overscan_y * mode->xres + overscan_x) * 4;
1458         /* We want to keep the fb_base for simplefb page aligned, where as
1459          * the sunxi dma engines will happily accept an unaligned address. */
1460         if (overscan_offset)
1461                 sunxi_display.fb_size += 0x1000;
1462
1463         if (sunxi_display.fb_size > CONFIG_SUNXI_MAX_FB_SIZE) {
1464                 printf("Error need %dkB for fb, but only %dkB is reserved\n",
1465                        sunxi_display.fb_size >> 10,
1466                        CONFIG_SUNXI_MAX_FB_SIZE >> 10);
1467                 return NULL;
1468         }
1469
1470         printf("Setting up a %dx%d%s %s console (overscan %dx%d)\n",
1471                mode->xres, mode->yres,
1472                (mode->vmode == FB_VMODE_INTERLACED) ? "i" : "",
1473                sunxi_get_mon_desc(sunxi_display.monitor),
1474                overscan_x, overscan_y);
1475
1476         gd->fb_base = gd->bd->bi_dram[0].start +
1477                       gd->bd->bi_dram[0].size - sunxi_display.fb_size;
1478         sunxi_engines_init();
1479
1480         fb_dma_addr = gd->fb_base - CONFIG_SYS_SDRAM_BASE;
1481         sunxi_display.fb_addr = gd->fb_base;
1482         if (overscan_offset) {
1483                 fb_dma_addr += 0x1000 - (overscan_offset & 0xfff);
1484                 sunxi_display.fb_addr += (overscan_offset + 0xfff) & ~0xfff;
1485                 memset((void *)gd->fb_base, 0, sunxi_display.fb_size);
1486                 flush_cache(gd->fb_base, sunxi_display.fb_size);
1487         }
1488         sunxi_mode_set(mode, fb_dma_addr);
1489
1490         /*
1491          * These are the only members of this structure that are used. All the
1492          * others are driver specific. The pitch is stored in plnSizeX.
1493          */
1494         graphic_device->frameAdrs = sunxi_display.fb_addr;
1495         graphic_device->gdfIndex = GDF_32BIT_X888RGB;
1496         graphic_device->gdfBytesPP = 4;
1497         graphic_device->winSizeX = mode->xres - 2 * overscan_x;
1498         graphic_device->winSizeY = mode->yres - 2 * overscan_y;
1499         graphic_device->plnSizeX = mode->xres * graphic_device->gdfBytesPP;
1500
1501         return graphic_device;
1502 }
1503
1504 /*
1505  * Simplefb support.
1506  */
1507 #if defined(CONFIG_OF_BOARD_SETUP) && defined(CONFIG_VIDEO_DT_SIMPLEFB)
1508 int sunxi_simplefb_setup(void *blob)
1509 {
1510         static GraphicDevice *graphic_device = &sunxi_display.graphic_device;
1511         int offset, ret;
1512         u64 start, size;
1513         const char *pipeline = NULL;
1514
1515 #ifdef CONFIG_MACH_SUN4I
1516 #define PIPELINE_PREFIX "de_fe0-"
1517 #else
1518 #define PIPELINE_PREFIX
1519 #endif
1520
1521         switch (sunxi_display.monitor) {
1522         case sunxi_monitor_none:
1523                 return 0;
1524         case sunxi_monitor_dvi:
1525         case sunxi_monitor_hdmi:
1526                 pipeline = PIPELINE_PREFIX "de_be0-lcd0-hdmi";
1527                 break;
1528         case sunxi_monitor_lcd:
1529                 pipeline = PIPELINE_PREFIX "de_be0-lcd0";
1530                 break;
1531         case sunxi_monitor_vga:
1532 #ifdef CONFIG_VIDEO_VGA
1533                 pipeline = PIPELINE_PREFIX "de_be0-lcd0-tve0";
1534 #elif defined CONFIG_VIDEO_VGA_VIA_LCD
1535                 pipeline = PIPELINE_PREFIX "de_be0-lcd0";
1536 #endif
1537                 break;
1538         case sunxi_monitor_composite_pal:
1539         case sunxi_monitor_composite_ntsc:
1540         case sunxi_monitor_composite_pal_m:
1541         case sunxi_monitor_composite_pal_nc:
1542                 pipeline = PIPELINE_PREFIX "de_be0-lcd0-tve0";
1543                 break;
1544         }
1545
1546         /* Find a prefilled simpefb node, matching out pipeline config */
1547         offset = fdt_node_offset_by_compatible(blob, -1,
1548                                                "allwinner,simple-framebuffer");
1549         while (offset >= 0) {
1550                 ret = fdt_find_string(blob, offset, "allwinner,pipeline",
1551                                       pipeline);
1552                 if (ret == 0)
1553                         break;
1554                 offset = fdt_node_offset_by_compatible(blob, offset,
1555                                                "allwinner,simple-framebuffer");
1556         }
1557         if (offset < 0) {
1558                 eprintf("Cannot setup simplefb: node not found\n");
1559                 return 0; /* Keep older kernels working */
1560         }
1561
1562         /*
1563          * Do not report the framebuffer as free RAM to the OS, note we cannot
1564          * use fdt_add_mem_rsv() here, because then it is still seen as RAM,
1565          * and e.g. Linux refuses to iomap RAM on ARM, see:
1566          * linux/arch/arm/mm/ioremap.c around line 301.
1567          */
1568         start = gd->bd->bi_dram[0].start;
1569         size = gd->bd->bi_dram[0].size - sunxi_display.fb_size;
1570         ret = fdt_fixup_memory_banks(blob, &start, &size, 1);
1571         if (ret) {
1572                 eprintf("Cannot setup simplefb: Error reserving memory\n");
1573                 return ret;
1574         }
1575
1576         ret = fdt_setup_simplefb_node(blob, offset, sunxi_display.fb_addr,
1577                         graphic_device->winSizeX, graphic_device->winSizeY,
1578                         graphic_device->plnSizeX, "x8r8g8b8");
1579         if (ret)
1580                 eprintf("Cannot setup simplefb: Error setting properties\n");
1581
1582         return ret;
1583 }
1584 #endif /* CONFIG_OF_BOARD_SETUP && CONFIG_VIDEO_DT_SIMPLEFB */