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