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