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