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