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