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