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_ctfb_mode_to_display_timing(const struct ctfb_res_modes *mode,
725 					      struct display_timing *timing)
726 {
727 	timing->pixelclock.typ = mode->pixclock_khz * 1000;
728 
729 	timing->hactive.typ = mode->xres;
730 	timing->hfront_porch.typ = mode->right_margin;
731 	timing->hback_porch.typ = mode->left_margin;
732 	timing->hsync_len.typ = mode->hsync_len;
733 
734 	timing->vactive.typ = mode->yres;
735 	timing->vfront_porch.typ = mode->lower_margin;
736 	timing->vback_porch.typ = mode->upper_margin;
737 	timing->vsync_len.typ = mode->vsync_len;
738 
739 	if (mode->sync & FB_SYNC_HOR_HIGH_ACT)
740 		timing->flags |= DISPLAY_FLAGS_HSYNC_HIGH;
741 	else
742 		timing->flags |= DISPLAY_FLAGS_HSYNC_LOW;
743 	if (mode->sync & FB_SYNC_VERT_HIGH_ACT)
744 		timing->flags |= DISPLAY_FLAGS_VSYNC_HIGH;
745 	else
746 		timing->flags |= DISPLAY_FLAGS_VSYNC_LOW;
747 	if (mode->vmode == FB_VMODE_INTERLACED)
748 		timing->flags |= DISPLAY_FLAGS_INTERLACED;
749 }
750 
751 static void sunxi_lcdc_tcon0_mode_set(const struct ctfb_res_modes *mode,
752 				      bool for_ext_vga_dac)
753 {
754 	struct sunxi_lcdc_reg * const lcdc =
755 		(struct sunxi_lcdc_reg *)SUNXI_LCD0_BASE;
756 	int clk_div, clk_double, pin;
757 	struct display_timing timing;
758 
759 #if defined CONFIG_MACH_SUN8I && defined CONFIG_VIDEO_LCD_IF_LVDS
760 	for (pin = SUNXI_GPD(18); pin <= SUNXI_GPD(27); pin++) {
761 #else
762 	for (pin = SUNXI_GPD(0); pin <= SUNXI_GPD(27); pin++) {
763 #endif
764 #ifdef CONFIG_VIDEO_LCD_IF_PARALLEL
765 		sunxi_gpio_set_cfgpin(pin, SUNXI_GPD_LCD0);
766 #endif
767 #ifdef CONFIG_VIDEO_LCD_IF_LVDS
768 		sunxi_gpio_set_cfgpin(pin, SUNXI_GPD_LVDS0);
769 #endif
770 #ifdef CONFIG_VIDEO_LCD_PANEL_EDP_4_LANE_1620M_VIA_ANX9804
771 		sunxi_gpio_set_drv(pin, 3);
772 #endif
773 	}
774 
775 	sunxi_lcdc_pll_set(0, mode->pixclock_khz, &clk_div, &clk_double);
776 
777 	sunxi_ctfb_mode_to_display_timing(mode, &timing);
778 	lcdc_tcon0_mode_set(lcdc, &timing, clk_div, for_ext_vga_dac,
779 			    sunxi_display.depth, CONFIG_VIDEO_LCD_DCLK_PHASE);
780 }
781 
782 #if defined CONFIG_VIDEO_HDMI || defined CONFIG_VIDEO_VGA || defined CONFIG_VIDEO_COMPOSITE
783 static void sunxi_lcdc_tcon1_mode_set(const struct ctfb_res_modes *mode,
784 				      int *clk_div, int *clk_double,
785 				      bool use_portd_hvsync)
786 {
787 	struct sunxi_lcdc_reg * const lcdc =
788 		(struct sunxi_lcdc_reg *)SUNXI_LCD0_BASE;
789 	struct display_timing timing;
790 
791 	sunxi_ctfb_mode_to_display_timing(mode, &timing);
792 	lcdc_tcon1_mode_set(lcdc, &timing, use_portd_hvsync,
793 			    sunxi_is_composite());
794 
795 	if (use_portd_hvsync) {
796 		sunxi_gpio_set_cfgpin(SUNXI_GPD(26), SUNXI_GPD_LCD0);
797 		sunxi_gpio_set_cfgpin(SUNXI_GPD(27), SUNXI_GPD_LCD0);
798 	}
799 
800 	sunxi_lcdc_pll_set(1, mode->pixclock_khz, clk_div, clk_double);
801 }
802 #endif /* CONFIG_VIDEO_HDMI || defined CONFIG_VIDEO_VGA || CONFIG_VIDEO_COMPOSITE */
803 
804 #ifdef CONFIG_VIDEO_HDMI
805 
806 static void sunxi_hdmi_setup_info_frames(const struct ctfb_res_modes *mode)
807 {
808 	struct sunxi_hdmi_reg * const hdmi =
809 		(struct sunxi_hdmi_reg *)SUNXI_HDMI_BASE;
810 	u8 checksum = 0;
811 	u8 avi_info_frame[17] = {
812 		0x82, 0x02, 0x0d, 0x00, 0x12, 0x00, 0x88, 0x00,
813 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
814 		0x00
815 	};
816 	u8 vendor_info_frame[19] = {
817 		0x81, 0x01, 0x06, 0x29, 0x03, 0x0c, 0x00, 0x40,
818 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
819 		0x00, 0x00, 0x00
820 	};
821 	int i;
822 
823 	if (mode->pixclock_khz <= 27000)
824 		avi_info_frame[5] = 0x40; /* SD-modes, ITU601 colorspace */
825 	else
826 		avi_info_frame[5] = 0x80; /* HD-modes, ITU709 colorspace */
827 
828 	if (mode->xres * 100 / mode->yres < 156)
829 		avi_info_frame[5] |= 0x18; /* 4 : 3 */
830 	else
831 		avi_info_frame[5] |= 0x28; /* 16 : 9 */
832 
833 	for (i = 0; i < ARRAY_SIZE(avi_info_frame); i++)
834 		checksum += avi_info_frame[i];
835 
836 	avi_info_frame[3] = 0x100 - checksum;
837 
838 	for (i = 0; i < ARRAY_SIZE(avi_info_frame); i++)
839 		writeb(avi_info_frame[i], &hdmi->avi_info_frame[i]);
840 
841 	writel(SUNXI_HDMI_QCP_PACKET0, &hdmi->qcp_packet0);
842 	writel(SUNXI_HDMI_QCP_PACKET1, &hdmi->qcp_packet1);
843 
844 	for (i = 0; i < ARRAY_SIZE(vendor_info_frame); i++)
845 		writeb(vendor_info_frame[i], &hdmi->vendor_info_frame[i]);
846 
847 	writel(SUNXI_HDMI_PKT_CTRL0, &hdmi->pkt_ctrl0);
848 	writel(SUNXI_HDMI_PKT_CTRL1, &hdmi->pkt_ctrl1);
849 
850 	setbits_le32(&hdmi->video_ctrl, SUNXI_HDMI_VIDEO_CTRL_HDMI);
851 }
852 
853 static void sunxi_hdmi_mode_set(const struct ctfb_res_modes *mode,
854 				int clk_div, int clk_double)
855 {
856 	struct sunxi_hdmi_reg * const hdmi =
857 		(struct sunxi_hdmi_reg *)SUNXI_HDMI_BASE;
858 	int x, y;
859 
860 	/* Write clear interrupt status bits */
861 	writel(SUNXI_HDMI_IRQ_STATUS_BITS, &hdmi->irq);
862 
863 	if (sunxi_display.monitor == sunxi_monitor_hdmi)
864 		sunxi_hdmi_setup_info_frames(mode);
865 
866 	/* Set input sync enable */
867 	writel(SUNXI_HDMI_UNKNOWN_INPUT_SYNC, &hdmi->unknown);
868 
869 	/* Init various registers, select pll3 as clock source */
870 	writel(SUNXI_HDMI_VIDEO_POL_TX_CLK, &hdmi->video_polarity);
871 	writel(SUNXI_HDMI_PAD_CTRL0_RUN, &hdmi->pad_ctrl0);
872 	writel(SUNXI_HDMI_PAD_CTRL1, &hdmi->pad_ctrl1);
873 	writel(SUNXI_HDMI_PLL_CTRL, &hdmi->pll_ctrl);
874 	writel(SUNXI_HDMI_PLL_DBG0_PLL3, &hdmi->pll_dbg0);
875 
876 	/* Setup clk div and doubler */
877 	clrsetbits_le32(&hdmi->pll_ctrl, SUNXI_HDMI_PLL_CTRL_DIV_MASK,
878 			SUNXI_HDMI_PLL_CTRL_DIV(clk_div));
879 	if (!clk_double)
880 		setbits_le32(&hdmi->pad_ctrl1, SUNXI_HDMI_PAD_CTRL1_HALVE);
881 
882 	/* Setup timing registers */
883 	writel(SUNXI_HDMI_Y(mode->yres) | SUNXI_HDMI_X(mode->xres),
884 	       &hdmi->video_size);
885 
886 	x = mode->hsync_len + mode->left_margin;
887 	y = mode->vsync_len + mode->upper_margin;
888 	writel(SUNXI_HDMI_Y(y) | SUNXI_HDMI_X(x), &hdmi->video_bp);
889 
890 	x = mode->right_margin;
891 	y = mode->lower_margin;
892 	writel(SUNXI_HDMI_Y(y) | SUNXI_HDMI_X(x), &hdmi->video_fp);
893 
894 	x = mode->hsync_len;
895 	y = mode->vsync_len;
896 	writel(SUNXI_HDMI_Y(y) | SUNXI_HDMI_X(x), &hdmi->video_spw);
897 
898 	if (mode->sync & FB_SYNC_HOR_HIGH_ACT)
899 		setbits_le32(&hdmi->video_polarity, SUNXI_HDMI_VIDEO_POL_HOR);
900 
901 	if (mode->sync & FB_SYNC_VERT_HIGH_ACT)
902 		setbits_le32(&hdmi->video_polarity, SUNXI_HDMI_VIDEO_POL_VER);
903 }
904 
905 static void sunxi_hdmi_enable(void)
906 {
907 	struct sunxi_hdmi_reg * const hdmi =
908 		(struct sunxi_hdmi_reg *)SUNXI_HDMI_BASE;
909 
910 	udelay(100);
911 	setbits_le32(&hdmi->video_ctrl, SUNXI_HDMI_VIDEO_CTRL_ENABLE);
912 }
913 
914 #endif /* CONFIG_VIDEO_HDMI */
915 
916 #if defined CONFIG_VIDEO_VGA || defined CONFIG_VIDEO_COMPOSITE
917 
918 static void sunxi_tvencoder_mode_set(void)
919 {
920 	struct sunxi_ccm_reg * const ccm =
921 		(struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
922 	struct sunxi_tve_reg * const tve =
923 		(struct sunxi_tve_reg *)SUNXI_TVE0_BASE;
924 
925 	/* Reset off */
926 	setbits_le32(&ccm->lcd0_ch0_clk_cfg, CCM_LCD_CH0_CTRL_TVE_RST);
927 	/* Clock on */
928 	setbits_le32(&ccm->ahb_gate1, 1 << AHB_GATE_OFFSET_TVE0);
929 
930 	switch (sunxi_display.monitor) {
931 	case sunxi_monitor_vga:
932 		writel(SUNXI_TVE_GCTRL_DAC_INPUT(0, 1) |
933 		       SUNXI_TVE_GCTRL_DAC_INPUT(1, 2) |
934 		       SUNXI_TVE_GCTRL_DAC_INPUT(2, 3), &tve->gctrl);
935 		writel(SUNXI_TVE_CFG0_VGA, &tve->cfg0);
936 		writel(SUNXI_TVE_DAC_CFG0_VGA, &tve->dac_cfg0);
937 		writel(SUNXI_TVE_UNKNOWN1_VGA, &tve->unknown1);
938 		break;
939 	case sunxi_monitor_composite_pal_nc:
940 		writel(SUNXI_TVE_CHROMA_FREQ_PAL_NC, &tve->chroma_freq);
941 		/* Fall through */
942 	case sunxi_monitor_composite_pal:
943 		writel(SUNXI_TVE_GCTRL_DAC_INPUT(0, 1) |
944 		       SUNXI_TVE_GCTRL_DAC_INPUT(1, 2) |
945 		       SUNXI_TVE_GCTRL_DAC_INPUT(2, 3) |
946 		       SUNXI_TVE_GCTRL_DAC_INPUT(3, 4), &tve->gctrl);
947 		writel(SUNXI_TVE_CFG0_PAL, &tve->cfg0);
948 		writel(SUNXI_TVE_DAC_CFG0_COMPOSITE, &tve->dac_cfg0);
949 		writel(SUNXI_TVE_FILTER_COMPOSITE, &tve->filter);
950 		writel(SUNXI_TVE_PORCH_NUM_PAL, &tve->porch_num);
951 		writel(SUNXI_TVE_LINE_NUM_PAL, &tve->line_num);
952 		writel(SUNXI_TVE_BLANK_BLACK_LEVEL_PAL, &tve->blank_black_level);
953 		writel(SUNXI_TVE_UNKNOWN1_COMPOSITE, &tve->unknown1);
954 		writel(SUNXI_TVE_CBR_LEVEL_PAL, &tve->cbr_level);
955 		writel(SUNXI_TVE_BURST_WIDTH_COMPOSITE, &tve->burst_width);
956 		writel(SUNXI_TVE_UNKNOWN2_PAL, &tve->unknown2);
957 		writel(SUNXI_TVE_ACTIVE_NUM_COMPOSITE, &tve->active_num);
958 		writel(SUNXI_TVE_CHROMA_BW_GAIN_COMP, &tve->chroma_bw_gain);
959 		writel(SUNXI_TVE_NOTCH_WIDTH_COMPOSITE, &tve->notch_width);
960 		writel(SUNXI_TVE_RESYNC_NUM_PAL, &tve->resync_num);
961 		writel(SUNXI_TVE_SLAVE_PARA_COMPOSITE, &tve->slave_para);
962 		break;
963 	case sunxi_monitor_composite_pal_m:
964 		writel(SUNXI_TVE_CHROMA_FREQ_PAL_M, &tve->chroma_freq);
965 		writel(SUNXI_TVE_COLOR_BURST_PAL_M, &tve->color_burst);
966 		/* Fall through */
967 	case sunxi_monitor_composite_ntsc:
968 		writel(SUNXI_TVE_GCTRL_DAC_INPUT(0, 1) |
969 		       SUNXI_TVE_GCTRL_DAC_INPUT(1, 2) |
970 		       SUNXI_TVE_GCTRL_DAC_INPUT(2, 3) |
971 		       SUNXI_TVE_GCTRL_DAC_INPUT(3, 4), &tve->gctrl);
972 		writel(SUNXI_TVE_CFG0_NTSC, &tve->cfg0);
973 		writel(SUNXI_TVE_DAC_CFG0_COMPOSITE, &tve->dac_cfg0);
974 		writel(SUNXI_TVE_FILTER_COMPOSITE, &tve->filter);
975 		writel(SUNXI_TVE_PORCH_NUM_NTSC, &tve->porch_num);
976 		writel(SUNXI_TVE_LINE_NUM_NTSC, &tve->line_num);
977 		writel(SUNXI_TVE_BLANK_BLACK_LEVEL_NTSC, &tve->blank_black_level);
978 		writel(SUNXI_TVE_UNKNOWN1_COMPOSITE, &tve->unknown1);
979 		writel(SUNXI_TVE_CBR_LEVEL_NTSC, &tve->cbr_level);
980 		writel(SUNXI_TVE_BURST_PHASE_NTSC, &tve->burst_phase);
981 		writel(SUNXI_TVE_BURST_WIDTH_COMPOSITE, &tve->burst_width);
982 		writel(SUNXI_TVE_UNKNOWN2_NTSC, &tve->unknown2);
983 		writel(SUNXI_TVE_SYNC_VBI_LEVEL_NTSC, &tve->sync_vbi_level);
984 		writel(SUNXI_TVE_ACTIVE_NUM_COMPOSITE, &tve->active_num);
985 		writel(SUNXI_TVE_CHROMA_BW_GAIN_COMP, &tve->chroma_bw_gain);
986 		writel(SUNXI_TVE_NOTCH_WIDTH_COMPOSITE, &tve->notch_width);
987 		writel(SUNXI_TVE_RESYNC_NUM_NTSC, &tve->resync_num);
988 		writel(SUNXI_TVE_SLAVE_PARA_COMPOSITE, &tve->slave_para);
989 		break;
990 	case sunxi_monitor_none:
991 	case sunxi_monitor_dvi:
992 	case sunxi_monitor_hdmi:
993 	case sunxi_monitor_lcd:
994 		break;
995 	}
996 }
997 
998 static void sunxi_tvencoder_enable(void)
999 {
1000 	struct sunxi_tve_reg * const tve =
1001 		(struct sunxi_tve_reg *)SUNXI_TVE0_BASE;
1002 
1003 	setbits_le32(&tve->gctrl, SUNXI_TVE_GCTRL_ENABLE);
1004 }
1005 
1006 #endif /* CONFIG_VIDEO_VGA || defined CONFIG_VIDEO_COMPOSITE */
1007 
1008 static void sunxi_drc_init(void)
1009 {
1010 #ifdef CONFIG_SUNXI_GEN_SUN6I
1011 	struct sunxi_ccm_reg * const ccm =
1012 		(struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
1013 
1014 	/* On sun6i the drc must be clocked even when in pass-through mode */
1015 #ifdef CONFIG_MACH_SUN8I_A33
1016 	setbits_le32(&ccm->ahb_reset1_cfg, 1 << AHB_RESET_OFFSET_SAT);
1017 #endif
1018 	setbits_le32(&ccm->ahb_reset1_cfg, 1 << AHB_RESET_OFFSET_DRC0);
1019 	clock_set_de_mod_clock(&ccm->iep_drc0_clk_cfg, 300000000);
1020 #endif
1021 }
1022 
1023 #ifdef CONFIG_VIDEO_VGA_VIA_LCD
1024 static void sunxi_vga_external_dac_enable(void)
1025 {
1026 	int pin;
1027 
1028 	pin = sunxi_name_to_gpio(CONFIG_VIDEO_VGA_EXTERNAL_DAC_EN);
1029 	if (pin >= 0) {
1030 		gpio_request(pin, "vga_enable");
1031 		gpio_direction_output(pin, 1);
1032 	}
1033 }
1034 #endif /* CONFIG_VIDEO_VGA_VIA_LCD */
1035 
1036 #ifdef CONFIG_VIDEO_LCD_SSD2828
1037 static int sunxi_ssd2828_init(const struct ctfb_res_modes *mode)
1038 {
1039 	struct ssd2828_config cfg = {
1040 		.csx_pin = name_to_gpio(CONFIG_VIDEO_LCD_SPI_CS),
1041 		.sck_pin = name_to_gpio(CONFIG_VIDEO_LCD_SPI_SCLK),
1042 		.sdi_pin = name_to_gpio(CONFIG_VIDEO_LCD_SPI_MOSI),
1043 		.sdo_pin = name_to_gpio(CONFIG_VIDEO_LCD_SPI_MISO),
1044 		.reset_pin = name_to_gpio(CONFIG_VIDEO_LCD_SSD2828_RESET),
1045 		.ssd2828_tx_clk_khz  = CONFIG_VIDEO_LCD_SSD2828_TX_CLK * 1000,
1046 		.ssd2828_color_depth = 24,
1047 #ifdef CONFIG_VIDEO_LCD_PANEL_MIPI_4_LANE_513_MBPS_VIA_SSD2828
1048 		.mipi_dsi_number_of_data_lanes           = 4,
1049 		.mipi_dsi_bitrate_per_data_lane_mbps     = 513,
1050 		.mipi_dsi_delay_after_exit_sleep_mode_ms = 100,
1051 		.mipi_dsi_delay_after_set_display_on_ms  = 200
1052 #else
1053 #error MIPI LCD panel needs configuration parameters
1054 #endif
1055 	};
1056 
1057 	if (cfg.csx_pin == -1 || cfg.sck_pin == -1 || cfg.sdi_pin == -1) {
1058 		printf("SSD2828: SPI pins are not properly configured\n");
1059 		return 1;
1060 	}
1061 	if (cfg.reset_pin == -1) {
1062 		printf("SSD2828: Reset pin is not properly configured\n");
1063 		return 1;
1064 	}
1065 
1066 	return ssd2828_init(&cfg, mode);
1067 }
1068 #endif /* CONFIG_VIDEO_LCD_SSD2828 */
1069 
1070 static void sunxi_engines_init(void)
1071 {
1072 	sunxi_composer_init();
1073 	sunxi_lcdc_init();
1074 	sunxi_drc_init();
1075 }
1076 
1077 static void sunxi_mode_set(const struct ctfb_res_modes *mode,
1078 			   unsigned int address)
1079 {
1080 	int __maybe_unused clk_div, clk_double;
1081 	struct sunxi_lcdc_reg * const lcdc =
1082 		(struct sunxi_lcdc_reg *)SUNXI_LCD0_BASE;
1083 
1084 	switch (sunxi_display.monitor) {
1085 	case sunxi_monitor_none:
1086 		break;
1087 	case sunxi_monitor_dvi:
1088 	case sunxi_monitor_hdmi:
1089 #ifdef CONFIG_VIDEO_HDMI
1090 		sunxi_composer_mode_set(mode, address);
1091 		sunxi_lcdc_tcon1_mode_set(mode, &clk_div, &clk_double, 0);
1092 		sunxi_hdmi_mode_set(mode, clk_div, clk_double);
1093 		sunxi_composer_enable();
1094 		lcdc_enable(lcdc, sunxi_display.depth);
1095 		sunxi_hdmi_enable();
1096 #endif
1097 		break;
1098 	case sunxi_monitor_lcd:
1099 		sunxi_lcdc_panel_enable();
1100 		if (IS_ENABLED(CONFIG_VIDEO_LCD_PANEL_EDP_4_LANE_1620M_VIA_ANX9804)) {
1101 			/*
1102 			 * The anx9804 needs 1.8V from eldo3, we do this here
1103 			 * and not via CONFIG_AXP_ELDO3_VOLT from board_init()
1104 			 * to avoid turning this on when using hdmi output.
1105 			 */
1106 			axp_set_eldo(3, 1800);
1107 			anx9804_init(CONFIG_VIDEO_LCD_I2C_BUS, 4,
1108 				     ANX9804_DATA_RATE_1620M,
1109 				     sunxi_display.depth);
1110 		}
1111 		if (IS_ENABLED(CONFIG_VIDEO_LCD_HITACHI_TX18D42VM)) {
1112 			mdelay(50); /* Wait for lcd controller power on */
1113 			hitachi_tx18d42vm_init();
1114 		}
1115 		if (IS_ENABLED(CONFIG_VIDEO_LCD_TL059WV5C0)) {
1116 			unsigned int orig_i2c_bus = i2c_get_bus_num();
1117 			i2c_set_bus_num(CONFIG_VIDEO_LCD_I2C_BUS);
1118 			i2c_reg_write(0x5c, 0x04, 0x42); /* Turn on the LCD */
1119 			i2c_set_bus_num(orig_i2c_bus);
1120 		}
1121 		sunxi_composer_mode_set(mode, address);
1122 		sunxi_lcdc_tcon0_mode_set(mode, false);
1123 		sunxi_composer_enable();
1124 		lcdc_enable(lcdc, sunxi_display.depth);
1125 #ifdef CONFIG_VIDEO_LCD_SSD2828
1126 		sunxi_ssd2828_init(mode);
1127 #endif
1128 		sunxi_lcdc_backlight_enable();
1129 		break;
1130 	case sunxi_monitor_vga:
1131 #ifdef CONFIG_VIDEO_VGA
1132 		sunxi_composer_mode_set(mode, address);
1133 		sunxi_lcdc_tcon1_mode_set(mode, &clk_div, &clk_double, 1);
1134 		sunxi_tvencoder_mode_set();
1135 		sunxi_composer_enable();
1136 		lcdc_enable(lcdc, sunxi_display.depth);
1137 		sunxi_tvencoder_enable();
1138 #elif defined CONFIG_VIDEO_VGA_VIA_LCD
1139 		sunxi_composer_mode_set(mode, address);
1140 		sunxi_lcdc_tcon0_mode_set(mode, true);
1141 		sunxi_composer_enable();
1142 		lcdc_enable(lcdc, sunxi_display.depth);
1143 		sunxi_vga_external_dac_enable();
1144 #endif
1145 		break;
1146 	case sunxi_monitor_composite_pal:
1147 	case sunxi_monitor_composite_ntsc:
1148 	case sunxi_monitor_composite_pal_m:
1149 	case sunxi_monitor_composite_pal_nc:
1150 #ifdef CONFIG_VIDEO_COMPOSITE
1151 		sunxi_composer_mode_set(mode, address);
1152 		sunxi_lcdc_tcon1_mode_set(mode, &clk_div, &clk_double, 0);
1153 		sunxi_tvencoder_mode_set();
1154 		sunxi_composer_enable();
1155 		lcdc_enable(lcdc, sunxi_display.depth);
1156 		sunxi_tvencoder_enable();
1157 #endif
1158 		break;
1159 	}
1160 }
1161 
1162 static const char *sunxi_get_mon_desc(enum sunxi_monitor monitor)
1163 {
1164 	switch (monitor) {
1165 	case sunxi_monitor_none:		return "none";
1166 	case sunxi_monitor_dvi:			return "dvi";
1167 	case sunxi_monitor_hdmi:		return "hdmi";
1168 	case sunxi_monitor_lcd:			return "lcd";
1169 	case sunxi_monitor_vga:			return "vga";
1170 	case sunxi_monitor_composite_pal:	return "composite-pal";
1171 	case sunxi_monitor_composite_ntsc:	return "composite-ntsc";
1172 	case sunxi_monitor_composite_pal_m:	return "composite-pal-m";
1173 	case sunxi_monitor_composite_pal_nc:	return "composite-pal-nc";
1174 	}
1175 	return NULL; /* never reached */
1176 }
1177 
1178 ulong board_get_usable_ram_top(ulong total_size)
1179 {
1180 	return gd->ram_top - CONFIG_SUNXI_MAX_FB_SIZE;
1181 }
1182 
1183 static bool sunxi_has_hdmi(void)
1184 {
1185 #ifdef CONFIG_VIDEO_HDMI
1186 	return true;
1187 #else
1188 	return false;
1189 #endif
1190 }
1191 
1192 static bool sunxi_has_lcd(void)
1193 {
1194 	char *lcd_mode = CONFIG_VIDEO_LCD_MODE;
1195 
1196 	return lcd_mode[0] != 0;
1197 }
1198 
1199 static bool sunxi_has_vga(void)
1200 {
1201 #if defined CONFIG_VIDEO_VGA || defined CONFIG_VIDEO_VGA_VIA_LCD
1202 	return true;
1203 #else
1204 	return false;
1205 #endif
1206 }
1207 
1208 static bool sunxi_has_composite(void)
1209 {
1210 #ifdef CONFIG_VIDEO_COMPOSITE
1211 	return true;
1212 #else
1213 	return false;
1214 #endif
1215 }
1216 
1217 static enum sunxi_monitor sunxi_get_default_mon(bool allow_hdmi)
1218 {
1219 	if (allow_hdmi && sunxi_has_hdmi())
1220 		return sunxi_monitor_dvi;
1221 	else if (sunxi_has_lcd())
1222 		return sunxi_monitor_lcd;
1223 	else if (sunxi_has_vga())
1224 		return sunxi_monitor_vga;
1225 	else if (sunxi_has_composite())
1226 		return sunxi_monitor_composite_pal;
1227 	else
1228 		return sunxi_monitor_none;
1229 }
1230 
1231 void *video_hw_init(void)
1232 {
1233 	static GraphicDevice *graphic_device = &sunxi_display.graphic_device;
1234 	const struct ctfb_res_modes *mode;
1235 	struct ctfb_res_modes custom;
1236 	const char *options;
1237 #ifdef CONFIG_VIDEO_HDMI
1238 	int ret, hpd, hpd_delay, edid;
1239 #endif
1240 	int i, overscan_offset, overscan_x, overscan_y;
1241 	unsigned int fb_dma_addr;
1242 	char mon[16];
1243 	char *lcd_mode = CONFIG_VIDEO_LCD_MODE;
1244 
1245 	memset(&sunxi_display, 0, sizeof(struct sunxi_display));
1246 
1247 	video_get_ctfb_res_modes(RES_MODE_1024x768, 24, &mode,
1248 				 &sunxi_display.depth, &options);
1249 #ifdef CONFIG_VIDEO_HDMI
1250 	hpd = video_get_option_int(options, "hpd", 1);
1251 	hpd_delay = video_get_option_int(options, "hpd_delay", 500);
1252 	edid = video_get_option_int(options, "edid", 1);
1253 #endif
1254 	overscan_x = video_get_option_int(options, "overscan_x", -1);
1255 	overscan_y = video_get_option_int(options, "overscan_y", -1);
1256 	sunxi_display.monitor = sunxi_get_default_mon(true);
1257 	video_get_option_string(options, "monitor", mon, sizeof(mon),
1258 				sunxi_get_mon_desc(sunxi_display.monitor));
1259 	for (i = 0; i <= SUNXI_MONITOR_LAST; i++) {
1260 		if (strcmp(mon, sunxi_get_mon_desc(i)) == 0) {
1261 			sunxi_display.monitor = i;
1262 			break;
1263 		}
1264 	}
1265 	if (i > SUNXI_MONITOR_LAST)
1266 		printf("Unknown monitor: '%s', falling back to '%s'\n",
1267 		       mon, sunxi_get_mon_desc(sunxi_display.monitor));
1268 
1269 #ifdef CONFIG_VIDEO_HDMI
1270 	/* If HDMI/DVI is selected do HPD & EDID, and handle fallback */
1271 	if (sunxi_display.monitor == sunxi_monitor_dvi ||
1272 	    sunxi_display.monitor == sunxi_monitor_hdmi) {
1273 		/* Always call hdp_detect, as it also enables clocks, etc. */
1274 		ret = sunxi_hdmi_hpd_detect(hpd_delay);
1275 		if (ret) {
1276 			printf("HDMI connected: ");
1277 			if (edid && sunxi_hdmi_edid_get_mode(&custom) == 0)
1278 				mode = &custom;
1279 		} else if (hpd) {
1280 			sunxi_hdmi_shutdown();
1281 			sunxi_display.monitor = sunxi_get_default_mon(false);
1282 		} /* else continue with hdmi/dvi without a cable connected */
1283 	}
1284 #endif
1285 
1286 	switch (sunxi_display.monitor) {
1287 	case sunxi_monitor_none:
1288 		return NULL;
1289 	case sunxi_monitor_dvi:
1290 	case sunxi_monitor_hdmi:
1291 		if (!sunxi_has_hdmi()) {
1292 			printf("HDMI/DVI not supported on this board\n");
1293 			sunxi_display.monitor = sunxi_monitor_none;
1294 			return NULL;
1295 		}
1296 		break;
1297 	case sunxi_monitor_lcd:
1298 		if (!sunxi_has_lcd()) {
1299 			printf("LCD not supported on this board\n");
1300 			sunxi_display.monitor = sunxi_monitor_none;
1301 			return NULL;
1302 		}
1303 		sunxi_display.depth = video_get_params(&custom, lcd_mode);
1304 		mode = &custom;
1305 		break;
1306 	case sunxi_monitor_vga:
1307 		if (!sunxi_has_vga()) {
1308 			printf("VGA not supported on this board\n");
1309 			sunxi_display.monitor = sunxi_monitor_none;
1310 			return NULL;
1311 		}
1312 		sunxi_display.depth = 18;
1313 		break;
1314 	case sunxi_monitor_composite_pal:
1315 	case sunxi_monitor_composite_ntsc:
1316 	case sunxi_monitor_composite_pal_m:
1317 	case sunxi_monitor_composite_pal_nc:
1318 		if (!sunxi_has_composite()) {
1319 			printf("Composite video not supported on this board\n");
1320 			sunxi_display.monitor = sunxi_monitor_none;
1321 			return NULL;
1322 		}
1323 		if (sunxi_display.monitor == sunxi_monitor_composite_pal ||
1324 		    sunxi_display.monitor == sunxi_monitor_composite_pal_nc)
1325 			mode = &composite_video_modes[0];
1326 		else
1327 			mode = &composite_video_modes[1];
1328 		sunxi_display.depth = 24;
1329 		break;
1330 	}
1331 
1332 	/* Yes these defaults are quite high, overscan on composite sucks... */
1333 	if (overscan_x == -1)
1334 		overscan_x = sunxi_is_composite() ? 32 : 0;
1335 	if (overscan_y == -1)
1336 		overscan_y = sunxi_is_composite() ? 20 : 0;
1337 
1338 	sunxi_display.fb_size =
1339 		(mode->xres * mode->yres * 4 + 0xfff) & ~0xfff;
1340 	overscan_offset = (overscan_y * mode->xres + overscan_x) * 4;
1341 	/* We want to keep the fb_base for simplefb page aligned, where as
1342 	 * the sunxi dma engines will happily accept an unaligned address. */
1343 	if (overscan_offset)
1344 		sunxi_display.fb_size += 0x1000;
1345 
1346 	if (sunxi_display.fb_size > CONFIG_SUNXI_MAX_FB_SIZE) {
1347 		printf("Error need %dkB for fb, but only %dkB is reserved\n",
1348 		       sunxi_display.fb_size >> 10,
1349 		       CONFIG_SUNXI_MAX_FB_SIZE >> 10);
1350 		return NULL;
1351 	}
1352 
1353 	printf("Setting up a %dx%d%s %s console (overscan %dx%d)\n",
1354 	       mode->xres, mode->yres,
1355 	       (mode->vmode == FB_VMODE_INTERLACED) ? "i" : "",
1356 	       sunxi_get_mon_desc(sunxi_display.monitor),
1357 	       overscan_x, overscan_y);
1358 
1359 	gd->fb_base = gd->bd->bi_dram[0].start +
1360 		      gd->bd->bi_dram[0].size - sunxi_display.fb_size;
1361 	sunxi_engines_init();
1362 
1363 	fb_dma_addr = gd->fb_base - CONFIG_SYS_SDRAM_BASE;
1364 	sunxi_display.fb_addr = gd->fb_base;
1365 	if (overscan_offset) {
1366 		fb_dma_addr += 0x1000 - (overscan_offset & 0xfff);
1367 		sunxi_display.fb_addr += (overscan_offset + 0xfff) & ~0xfff;
1368 		memset((void *)gd->fb_base, 0, sunxi_display.fb_size);
1369 		flush_cache(gd->fb_base, sunxi_display.fb_size);
1370 	}
1371 	sunxi_mode_set(mode, fb_dma_addr);
1372 
1373 	/*
1374 	 * These are the only members of this structure that are used. All the
1375 	 * others are driver specific. The pitch is stored in plnSizeX.
1376 	 */
1377 	graphic_device->frameAdrs = sunxi_display.fb_addr;
1378 	graphic_device->gdfIndex = GDF_32BIT_X888RGB;
1379 	graphic_device->gdfBytesPP = 4;
1380 	graphic_device->winSizeX = mode->xres - 2 * overscan_x;
1381 	graphic_device->winSizeY = mode->yres - 2 * overscan_y;
1382 	graphic_device->plnSizeX = mode->xres * graphic_device->gdfBytesPP;
1383 
1384 	return graphic_device;
1385 }
1386 
1387 /*
1388  * Simplefb support.
1389  */
1390 #if defined(CONFIG_OF_BOARD_SETUP) && defined(CONFIG_VIDEO_DT_SIMPLEFB)
1391 int sunxi_simplefb_setup(void *blob)
1392 {
1393 	static GraphicDevice *graphic_device = &sunxi_display.graphic_device;
1394 	int offset, ret;
1395 	u64 start, size;
1396 	const char *pipeline = NULL;
1397 
1398 #ifdef CONFIG_MACH_SUN4I
1399 #define PIPELINE_PREFIX "de_fe0-"
1400 #else
1401 #define PIPELINE_PREFIX
1402 #endif
1403 
1404 	switch (sunxi_display.monitor) {
1405 	case sunxi_monitor_none:
1406 		return 0;
1407 	case sunxi_monitor_dvi:
1408 	case sunxi_monitor_hdmi:
1409 		pipeline = PIPELINE_PREFIX "de_be0-lcd0-hdmi";
1410 		break;
1411 	case sunxi_monitor_lcd:
1412 		pipeline = PIPELINE_PREFIX "de_be0-lcd0";
1413 		break;
1414 	case sunxi_monitor_vga:
1415 #ifdef CONFIG_VIDEO_VGA
1416 		pipeline = PIPELINE_PREFIX "de_be0-lcd0-tve0";
1417 #elif defined CONFIG_VIDEO_VGA_VIA_LCD
1418 		pipeline = PIPELINE_PREFIX "de_be0-lcd0";
1419 #endif
1420 		break;
1421 	case sunxi_monitor_composite_pal:
1422 	case sunxi_monitor_composite_ntsc:
1423 	case sunxi_monitor_composite_pal_m:
1424 	case sunxi_monitor_composite_pal_nc:
1425 		pipeline = PIPELINE_PREFIX "de_be0-lcd0-tve0";
1426 		break;
1427 	}
1428 
1429 	/* Find a prefilled simpefb node, matching out pipeline config */
1430 	offset = fdt_node_offset_by_compatible(blob, -1,
1431 					       "allwinner,simple-framebuffer");
1432 	while (offset >= 0) {
1433 		ret = fdt_stringlist_search(blob, offset, "allwinner,pipeline",
1434 					    pipeline);
1435 		if (ret == 0)
1436 			break;
1437 		offset = fdt_node_offset_by_compatible(blob, offset,
1438 					       "allwinner,simple-framebuffer");
1439 	}
1440 	if (offset < 0) {
1441 		eprintf("Cannot setup simplefb: node not found\n");
1442 		return 0; /* Keep older kernels working */
1443 	}
1444 
1445 	/*
1446 	 * Do not report the framebuffer as free RAM to the OS, note we cannot
1447 	 * use fdt_add_mem_rsv() here, because then it is still seen as RAM,
1448 	 * and e.g. Linux refuses to iomap RAM on ARM, see:
1449 	 * linux/arch/arm/mm/ioremap.c around line 301.
1450 	 */
1451 	start = gd->bd->bi_dram[0].start;
1452 	size = gd->bd->bi_dram[0].size - sunxi_display.fb_size;
1453 	ret = fdt_fixup_memory_banks(blob, &start, &size, 1);
1454 	if (ret) {
1455 		eprintf("Cannot setup simplefb: Error reserving memory\n");
1456 		return ret;
1457 	}
1458 
1459 	ret = fdt_setup_simplefb_node(blob, offset, sunxi_display.fb_addr,
1460 			graphic_device->winSizeX, graphic_device->winSizeY,
1461 			graphic_device->plnSizeX, "x8r8g8b8");
1462 	if (ret)
1463 		eprintf("Cannot setup simplefb: Error setting properties\n");
1464 
1465 	return ret;
1466 }
1467 #endif /* CONFIG_OF_BOARD_SETUP && CONFIG_VIDEO_DT_SIMPLEFB */
1468