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