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