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