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