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