SPDX: Convert all of our single license tags to Linux Kernel style
[platform/kernel/u-boot.git] / drivers / video / sunxi / sunxi_display.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Display driver for Allwinner SoCs.
4  *
5  * (C) Copyright 2013-2014 Luc Verhaegen <libv@skynet.be>
6  * (C) Copyright 2014-2015 Hans de Goede <hdegoede@redhat.com>
7  */
8
9 #include <common.h>
10 #include <efi_loader.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         timing->flags = 0;
629
630         if (mode->sync & FB_SYNC_HOR_HIGH_ACT)
631                 timing->flags |= DISPLAY_FLAGS_HSYNC_HIGH;
632         else
633                 timing->flags |= DISPLAY_FLAGS_HSYNC_LOW;
634         if (mode->sync & FB_SYNC_VERT_HIGH_ACT)
635                 timing->flags |= DISPLAY_FLAGS_VSYNC_HIGH;
636         else
637                 timing->flags |= DISPLAY_FLAGS_VSYNC_LOW;
638         if (mode->vmode == FB_VMODE_INTERLACED)
639                 timing->flags |= DISPLAY_FLAGS_INTERLACED;
640 }
641
642 static void sunxi_lcdc_tcon0_mode_set(const struct ctfb_res_modes *mode,
643                                       bool for_ext_vga_dac)
644 {
645         struct sunxi_lcdc_reg * const lcdc =
646                 (struct sunxi_lcdc_reg *)SUNXI_LCD0_BASE;
647         struct sunxi_ccm_reg * const ccm =
648                 (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
649         int clk_div, clk_double, pin;
650         struct display_timing timing;
651
652 #if defined CONFIG_MACH_SUN8I && defined CONFIG_VIDEO_LCD_IF_LVDS
653         for (pin = SUNXI_GPD(18); pin <= SUNXI_GPD(27); pin++) {
654 #else
655         for (pin = SUNXI_GPD(0); pin <= SUNXI_GPD(27); pin++) {
656 #endif
657 #ifdef CONFIG_VIDEO_LCD_IF_PARALLEL
658                 sunxi_gpio_set_cfgpin(pin, SUNXI_GPD_LCD0);
659 #endif
660 #ifdef CONFIG_VIDEO_LCD_IF_LVDS
661                 sunxi_gpio_set_cfgpin(pin, SUNXI_GPD_LVDS0);
662 #endif
663 #ifdef CONFIG_VIDEO_LCD_PANEL_EDP_4_LANE_1620M_VIA_ANX9804
664                 sunxi_gpio_set_drv(pin, 3);
665 #endif
666         }
667
668         lcdc_pll_set(ccm, 0, mode->pixclock_khz, &clk_div, &clk_double,
669                      sunxi_is_composite());
670
671         sunxi_ctfb_mode_to_display_timing(mode, &timing);
672         lcdc_tcon0_mode_set(lcdc, &timing, clk_div, for_ext_vga_dac,
673                             sunxi_display.depth, CONFIG_VIDEO_LCD_DCLK_PHASE);
674 }
675
676 #if defined CONFIG_VIDEO_HDMI || defined CONFIG_VIDEO_VGA || defined CONFIG_VIDEO_COMPOSITE
677 static void sunxi_lcdc_tcon1_mode_set(const struct ctfb_res_modes *mode,
678                                       int *clk_div, int *clk_double,
679                                       bool use_portd_hvsync)
680 {
681         struct sunxi_lcdc_reg * const lcdc =
682                 (struct sunxi_lcdc_reg *)SUNXI_LCD0_BASE;
683         struct sunxi_ccm_reg * const ccm =
684                 (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
685         struct display_timing timing;
686
687         sunxi_ctfb_mode_to_display_timing(mode, &timing);
688         lcdc_tcon1_mode_set(lcdc, &timing, use_portd_hvsync,
689                             sunxi_is_composite());
690
691         if (use_portd_hvsync) {
692                 sunxi_gpio_set_cfgpin(SUNXI_GPD(26), SUNXI_GPD_LCD0);
693                 sunxi_gpio_set_cfgpin(SUNXI_GPD(27), SUNXI_GPD_LCD0);
694         }
695
696         lcdc_pll_set(ccm, 1, mode->pixclock_khz, clk_div, clk_double,
697                      sunxi_is_composite());
698 }
699 #endif /* CONFIG_VIDEO_HDMI || defined CONFIG_VIDEO_VGA || CONFIG_VIDEO_COMPOSITE */
700
701 #ifdef CONFIG_VIDEO_HDMI
702
703 static void sunxi_hdmi_setup_info_frames(const struct ctfb_res_modes *mode)
704 {
705         struct sunxi_hdmi_reg * const hdmi =
706                 (struct sunxi_hdmi_reg *)SUNXI_HDMI_BASE;
707         u8 checksum = 0;
708         u8 avi_info_frame[17] = {
709                 0x82, 0x02, 0x0d, 0x00, 0x12, 0x00, 0x88, 0x00,
710                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
711                 0x00
712         };
713         u8 vendor_info_frame[19] = {
714                 0x81, 0x01, 0x06, 0x29, 0x03, 0x0c, 0x00, 0x40,
715                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
716                 0x00, 0x00, 0x00
717         };
718         int i;
719
720         if (mode->pixclock_khz <= 27000)
721                 avi_info_frame[5] = 0x40; /* SD-modes, ITU601 colorspace */
722         else
723                 avi_info_frame[5] = 0x80; /* HD-modes, ITU709 colorspace */
724
725         if (mode->xres * 100 / mode->yres < 156)
726                 avi_info_frame[5] |= 0x18; /* 4 : 3 */
727         else
728                 avi_info_frame[5] |= 0x28; /* 16 : 9 */
729
730         for (i = 0; i < ARRAY_SIZE(avi_info_frame); i++)
731                 checksum += avi_info_frame[i];
732
733         avi_info_frame[3] = 0x100 - checksum;
734
735         for (i = 0; i < ARRAY_SIZE(avi_info_frame); i++)
736                 writeb(avi_info_frame[i], &hdmi->avi_info_frame[i]);
737
738         writel(SUNXI_HDMI_QCP_PACKET0, &hdmi->qcp_packet0);
739         writel(SUNXI_HDMI_QCP_PACKET1, &hdmi->qcp_packet1);
740
741         for (i = 0; i < ARRAY_SIZE(vendor_info_frame); i++)
742                 writeb(vendor_info_frame[i], &hdmi->vendor_info_frame[i]);
743
744         writel(SUNXI_HDMI_PKT_CTRL0, &hdmi->pkt_ctrl0);
745         writel(SUNXI_HDMI_PKT_CTRL1, &hdmi->pkt_ctrl1);
746
747         setbits_le32(&hdmi->video_ctrl, SUNXI_HDMI_VIDEO_CTRL_HDMI);
748 }
749
750 static void sunxi_hdmi_mode_set(const struct ctfb_res_modes *mode,
751                                 int clk_div, int clk_double)
752 {
753         struct sunxi_hdmi_reg * const hdmi =
754                 (struct sunxi_hdmi_reg *)SUNXI_HDMI_BASE;
755         int x, y;
756
757         /* Write clear interrupt status bits */
758         writel(SUNXI_HDMI_IRQ_STATUS_BITS, &hdmi->irq);
759
760         if (sunxi_display.monitor == sunxi_monitor_hdmi)
761                 sunxi_hdmi_setup_info_frames(mode);
762
763         /* Set input sync enable */
764         writel(SUNXI_HDMI_UNKNOWN_INPUT_SYNC, &hdmi->unknown);
765
766         /* Init various registers, select pll3 as clock source */
767         writel(SUNXI_HDMI_VIDEO_POL_TX_CLK, &hdmi->video_polarity);
768         writel(SUNXI_HDMI_PAD_CTRL0_RUN, &hdmi->pad_ctrl0);
769         writel(SUNXI_HDMI_PAD_CTRL1, &hdmi->pad_ctrl1);
770         writel(SUNXI_HDMI_PLL_CTRL, &hdmi->pll_ctrl);
771         writel(SUNXI_HDMI_PLL_DBG0_PLL3, &hdmi->pll_dbg0);
772
773         /* Setup clk div and doubler */
774         clrsetbits_le32(&hdmi->pll_ctrl, SUNXI_HDMI_PLL_CTRL_DIV_MASK,
775                         SUNXI_HDMI_PLL_CTRL_DIV(clk_div));
776         if (!clk_double)
777                 setbits_le32(&hdmi->pad_ctrl1, SUNXI_HDMI_PAD_CTRL1_HALVE);
778
779         /* Setup timing registers */
780         writel(SUNXI_HDMI_Y(mode->yres) | SUNXI_HDMI_X(mode->xres),
781                &hdmi->video_size);
782
783         x = mode->hsync_len + mode->left_margin;
784         y = mode->vsync_len + mode->upper_margin;
785         writel(SUNXI_HDMI_Y(y) | SUNXI_HDMI_X(x), &hdmi->video_bp);
786
787         x = mode->right_margin;
788         y = mode->lower_margin;
789         writel(SUNXI_HDMI_Y(y) | SUNXI_HDMI_X(x), &hdmi->video_fp);
790
791         x = mode->hsync_len;
792         y = mode->vsync_len;
793         writel(SUNXI_HDMI_Y(y) | SUNXI_HDMI_X(x), &hdmi->video_spw);
794
795         if (mode->sync & FB_SYNC_HOR_HIGH_ACT)
796                 setbits_le32(&hdmi->video_polarity, SUNXI_HDMI_VIDEO_POL_HOR);
797
798         if (mode->sync & FB_SYNC_VERT_HIGH_ACT)
799                 setbits_le32(&hdmi->video_polarity, SUNXI_HDMI_VIDEO_POL_VER);
800 }
801
802 static void sunxi_hdmi_enable(void)
803 {
804         struct sunxi_hdmi_reg * const hdmi =
805                 (struct sunxi_hdmi_reg *)SUNXI_HDMI_BASE;
806
807         udelay(100);
808         setbits_le32(&hdmi->video_ctrl, SUNXI_HDMI_VIDEO_CTRL_ENABLE);
809 }
810
811 #endif /* CONFIG_VIDEO_HDMI */
812
813 #if defined CONFIG_VIDEO_VGA || defined CONFIG_VIDEO_COMPOSITE
814
815 static void sunxi_tvencoder_mode_set(void)
816 {
817         struct sunxi_ccm_reg * const ccm =
818                 (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
819         struct sunxi_tve_reg * const tve =
820                 (struct sunxi_tve_reg *)SUNXI_TVE0_BASE;
821
822         /* Reset off */
823         setbits_le32(&ccm->lcd0_ch0_clk_cfg, CCM_LCD_CH0_CTRL_TVE_RST);
824         /* Clock on */
825         setbits_le32(&ccm->ahb_gate1, 1 << AHB_GATE_OFFSET_TVE0);
826
827         switch (sunxi_display.monitor) {
828         case sunxi_monitor_vga:
829                 tvencoder_mode_set(tve, tve_mode_vga);
830                 break;
831         case sunxi_monitor_composite_pal_nc:
832                 tvencoder_mode_set(tve, tve_mode_composite_pal_nc);
833                 break;
834         case sunxi_monitor_composite_pal:
835                 tvencoder_mode_set(tve, tve_mode_composite_pal);
836                 break;
837         case sunxi_monitor_composite_pal_m:
838                 tvencoder_mode_set(tve, tve_mode_composite_pal_m);
839                 break;
840         case sunxi_monitor_composite_ntsc:
841                 tvencoder_mode_set(tve, tve_mode_composite_ntsc);
842                 break;
843         case sunxi_monitor_none:
844         case sunxi_monitor_dvi:
845         case sunxi_monitor_hdmi:
846         case sunxi_monitor_lcd:
847                 break;
848         }
849 }
850
851 #endif /* CONFIG_VIDEO_VGA || defined CONFIG_VIDEO_COMPOSITE */
852
853 static void sunxi_drc_init(void)
854 {
855 #ifdef CONFIG_SUNXI_GEN_SUN6I
856         struct sunxi_ccm_reg * const ccm =
857                 (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
858
859         /* On sun6i the drc must be clocked even when in pass-through mode */
860 #ifdef CONFIG_MACH_SUN8I_A33
861         setbits_le32(&ccm->ahb_reset1_cfg, 1 << AHB_RESET_OFFSET_SAT);
862 #endif
863         setbits_le32(&ccm->ahb_reset1_cfg, 1 << AHB_RESET_OFFSET_DRC0);
864         clock_set_de_mod_clock(&ccm->iep_drc0_clk_cfg, 300000000);
865 #endif
866 }
867
868 #ifdef CONFIG_VIDEO_VGA_VIA_LCD
869 static void sunxi_vga_external_dac_enable(void)
870 {
871         int pin;
872
873         pin = sunxi_name_to_gpio(CONFIG_VIDEO_VGA_EXTERNAL_DAC_EN);
874         if (pin >= 0) {
875                 gpio_request(pin, "vga_enable");
876                 gpio_direction_output(pin, 1);
877         }
878 }
879 #endif /* CONFIG_VIDEO_VGA_VIA_LCD */
880
881 #ifdef CONFIG_VIDEO_LCD_SSD2828
882 static int sunxi_ssd2828_init(const struct ctfb_res_modes *mode)
883 {
884         struct ssd2828_config cfg = {
885                 .csx_pin = name_to_gpio(CONFIG_VIDEO_LCD_SPI_CS),
886                 .sck_pin = name_to_gpio(CONFIG_VIDEO_LCD_SPI_SCLK),
887                 .sdi_pin = name_to_gpio(CONFIG_VIDEO_LCD_SPI_MOSI),
888                 .sdo_pin = name_to_gpio(CONFIG_VIDEO_LCD_SPI_MISO),
889                 .reset_pin = name_to_gpio(CONFIG_VIDEO_LCD_SSD2828_RESET),
890                 .ssd2828_tx_clk_khz  = CONFIG_VIDEO_LCD_SSD2828_TX_CLK * 1000,
891                 .ssd2828_color_depth = 24,
892 #ifdef CONFIG_VIDEO_LCD_PANEL_MIPI_4_LANE_513_MBPS_VIA_SSD2828
893                 .mipi_dsi_number_of_data_lanes           = 4,
894                 .mipi_dsi_bitrate_per_data_lane_mbps     = 513,
895                 .mipi_dsi_delay_after_exit_sleep_mode_ms = 100,
896                 .mipi_dsi_delay_after_set_display_on_ms  = 200
897 #else
898 #error MIPI LCD panel needs configuration parameters
899 #endif
900         };
901
902         if (cfg.csx_pin == -1 || cfg.sck_pin == -1 || cfg.sdi_pin == -1) {
903                 printf("SSD2828: SPI pins are not properly configured\n");
904                 return 1;
905         }
906         if (cfg.reset_pin == -1) {
907                 printf("SSD2828: Reset pin is not properly configured\n");
908                 return 1;
909         }
910
911         return ssd2828_init(&cfg, mode);
912 }
913 #endif /* CONFIG_VIDEO_LCD_SSD2828 */
914
915 static void sunxi_engines_init(void)
916 {
917         sunxi_composer_init();
918         sunxi_lcdc_init();
919         sunxi_drc_init();
920 }
921
922 static void sunxi_mode_set(const struct ctfb_res_modes *mode,
923                            unsigned int address)
924 {
925         int __maybe_unused clk_div, clk_double;
926         struct sunxi_lcdc_reg * const lcdc =
927                 (struct sunxi_lcdc_reg *)SUNXI_LCD0_BASE;
928         struct sunxi_tve_reg * __maybe_unused const tve =
929                 (struct sunxi_tve_reg *)SUNXI_TVE0_BASE;
930
931         switch (sunxi_display.monitor) {
932         case sunxi_monitor_none:
933                 break;
934         case sunxi_monitor_dvi:
935         case sunxi_monitor_hdmi:
936 #ifdef CONFIG_VIDEO_HDMI
937                 sunxi_composer_mode_set(mode, address);
938                 sunxi_lcdc_tcon1_mode_set(mode, &clk_div, &clk_double, 0);
939                 sunxi_hdmi_mode_set(mode, clk_div, clk_double);
940                 sunxi_composer_enable();
941                 lcdc_enable(lcdc, sunxi_display.depth);
942                 sunxi_hdmi_enable();
943 #endif
944                 break;
945         case sunxi_monitor_lcd:
946                 sunxi_lcdc_panel_enable();
947                 if (IS_ENABLED(CONFIG_VIDEO_LCD_PANEL_EDP_4_LANE_1620M_VIA_ANX9804)) {
948                         /*
949                          * The anx9804 needs 1.8V from eldo3, we do this here
950                          * and not via CONFIG_AXP_ELDO3_VOLT from board_init()
951                          * to avoid turning this on when using hdmi output.
952                          */
953                         axp_set_eldo(3, 1800);
954                         anx9804_init(CONFIG_VIDEO_LCD_I2C_BUS, 4,
955                                      ANX9804_DATA_RATE_1620M,
956                                      sunxi_display.depth);
957                 }
958                 if (IS_ENABLED(CONFIG_VIDEO_LCD_HITACHI_TX18D42VM)) {
959                         mdelay(50); /* Wait for lcd controller power on */
960                         hitachi_tx18d42vm_init();
961                 }
962                 if (IS_ENABLED(CONFIG_VIDEO_LCD_TL059WV5C0)) {
963                         unsigned int orig_i2c_bus = i2c_get_bus_num();
964                         i2c_set_bus_num(CONFIG_VIDEO_LCD_I2C_BUS);
965                         i2c_reg_write(0x5c, 0x04, 0x42); /* Turn on the LCD */
966                         i2c_set_bus_num(orig_i2c_bus);
967                 }
968                 sunxi_composer_mode_set(mode, address);
969                 sunxi_lcdc_tcon0_mode_set(mode, false);
970                 sunxi_composer_enable();
971                 lcdc_enable(lcdc, sunxi_display.depth);
972 #ifdef CONFIG_VIDEO_LCD_SSD2828
973                 sunxi_ssd2828_init(mode);
974 #endif
975                 sunxi_lcdc_backlight_enable();
976                 break;
977         case sunxi_monitor_vga:
978 #ifdef CONFIG_VIDEO_VGA
979                 sunxi_composer_mode_set(mode, address);
980                 sunxi_lcdc_tcon1_mode_set(mode, &clk_div, &clk_double, 1);
981                 sunxi_tvencoder_mode_set();
982                 sunxi_composer_enable();
983                 lcdc_enable(lcdc, sunxi_display.depth);
984                 tvencoder_enable(tve);
985 #elif defined CONFIG_VIDEO_VGA_VIA_LCD
986                 sunxi_composer_mode_set(mode, address);
987                 sunxi_lcdc_tcon0_mode_set(mode, true);
988                 sunxi_composer_enable();
989                 lcdc_enable(lcdc, sunxi_display.depth);
990                 sunxi_vga_external_dac_enable();
991 #endif
992                 break;
993         case sunxi_monitor_composite_pal:
994         case sunxi_monitor_composite_ntsc:
995         case sunxi_monitor_composite_pal_m:
996         case sunxi_monitor_composite_pal_nc:
997 #ifdef CONFIG_VIDEO_COMPOSITE
998                 sunxi_composer_mode_set(mode, address);
999                 sunxi_lcdc_tcon1_mode_set(mode, &clk_div, &clk_double, 0);
1000                 sunxi_tvencoder_mode_set();
1001                 sunxi_composer_enable();
1002                 lcdc_enable(lcdc, sunxi_display.depth);
1003                 tvencoder_enable(tve);
1004 #endif
1005                 break;
1006         }
1007 }
1008
1009 static const char *sunxi_get_mon_desc(enum sunxi_monitor monitor)
1010 {
1011         switch (monitor) {
1012         case sunxi_monitor_none:                return "none";
1013         case sunxi_monitor_dvi:                 return "dvi";
1014         case sunxi_monitor_hdmi:                return "hdmi";
1015         case sunxi_monitor_lcd:                 return "lcd";
1016         case sunxi_monitor_vga:                 return "vga";
1017         case sunxi_monitor_composite_pal:       return "composite-pal";
1018         case sunxi_monitor_composite_ntsc:      return "composite-ntsc";
1019         case sunxi_monitor_composite_pal_m:     return "composite-pal-m";
1020         case sunxi_monitor_composite_pal_nc:    return "composite-pal-nc";
1021         }
1022         return NULL; /* never reached */
1023 }
1024
1025 ulong board_get_usable_ram_top(ulong total_size)
1026 {
1027         return gd->ram_top - CONFIG_SUNXI_MAX_FB_SIZE;
1028 }
1029
1030 static bool sunxi_has_hdmi(void)
1031 {
1032 #ifdef CONFIG_VIDEO_HDMI
1033         return true;
1034 #else
1035         return false;
1036 #endif
1037 }
1038
1039 static bool sunxi_has_lcd(void)
1040 {
1041         char *lcd_mode = CONFIG_VIDEO_LCD_MODE;
1042
1043         return lcd_mode[0] != 0;
1044 }
1045
1046 static bool sunxi_has_vga(void)
1047 {
1048 #if defined CONFIG_VIDEO_VGA || defined CONFIG_VIDEO_VGA_VIA_LCD
1049         return true;
1050 #else
1051         return false;
1052 #endif
1053 }
1054
1055 static bool sunxi_has_composite(void)
1056 {
1057 #ifdef CONFIG_VIDEO_COMPOSITE
1058         return true;
1059 #else
1060         return false;
1061 #endif
1062 }
1063
1064 static enum sunxi_monitor sunxi_get_default_mon(bool allow_hdmi)
1065 {
1066         if (allow_hdmi && sunxi_has_hdmi())
1067                 return sunxi_monitor_dvi;
1068         else if (sunxi_has_lcd())
1069                 return sunxi_monitor_lcd;
1070         else if (sunxi_has_vga())
1071                 return sunxi_monitor_vga;
1072         else if (sunxi_has_composite())
1073                 return sunxi_monitor_composite_pal;
1074         else
1075                 return sunxi_monitor_none;
1076 }
1077
1078 void *video_hw_init(void)
1079 {
1080         static GraphicDevice *graphic_device = &sunxi_display.graphic_device;
1081         const struct ctfb_res_modes *mode;
1082         struct ctfb_res_modes custom;
1083         const char *options;
1084 #ifdef CONFIG_VIDEO_HDMI
1085         int ret, hpd, hpd_delay, edid;
1086 #endif
1087         int i, overscan_offset, overscan_x, overscan_y;
1088         unsigned int fb_dma_addr;
1089         char mon[16];
1090         char *lcd_mode = CONFIG_VIDEO_LCD_MODE;
1091
1092         memset(&sunxi_display, 0, sizeof(struct sunxi_display));
1093
1094         video_get_ctfb_res_modes(RES_MODE_1024x768, 24, &mode,
1095                                  &sunxi_display.depth, &options);
1096 #ifdef CONFIG_VIDEO_HDMI
1097         hpd = video_get_option_int(options, "hpd", 1);
1098         hpd_delay = video_get_option_int(options, "hpd_delay", 500);
1099         edid = video_get_option_int(options, "edid", 1);
1100 #endif
1101         overscan_x = video_get_option_int(options, "overscan_x", -1);
1102         overscan_y = video_get_option_int(options, "overscan_y", -1);
1103         sunxi_display.monitor = sunxi_get_default_mon(true);
1104         video_get_option_string(options, "monitor", mon, sizeof(mon),
1105                                 sunxi_get_mon_desc(sunxi_display.monitor));
1106         for (i = 0; i <= SUNXI_MONITOR_LAST; i++) {
1107                 if (strcmp(mon, sunxi_get_mon_desc(i)) == 0) {
1108                         sunxi_display.monitor = i;
1109                         break;
1110                 }
1111         }
1112         if (i > SUNXI_MONITOR_LAST)
1113                 printf("Unknown monitor: '%s', falling back to '%s'\n",
1114                        mon, sunxi_get_mon_desc(sunxi_display.monitor));
1115
1116 #ifdef CONFIG_VIDEO_HDMI
1117         /* If HDMI/DVI is selected do HPD & EDID, and handle fallback */
1118         if (sunxi_display.monitor == sunxi_monitor_dvi ||
1119             sunxi_display.monitor == sunxi_monitor_hdmi) {
1120                 /* Always call hdp_detect, as it also enables clocks, etc. */
1121                 ret = sunxi_hdmi_hpd_detect(hpd_delay);
1122                 if (ret) {
1123                         printf("HDMI connected: ");
1124                         if (edid && sunxi_hdmi_edid_get_mode(&custom) == 0)
1125                                 mode = &custom;
1126                 } else if (hpd) {
1127                         sunxi_hdmi_shutdown();
1128                         sunxi_display.monitor = sunxi_get_default_mon(false);
1129                 } /* else continue with hdmi/dvi without a cable connected */
1130         }
1131 #endif
1132
1133         switch (sunxi_display.monitor) {
1134         case sunxi_monitor_none:
1135                 return NULL;
1136         case sunxi_monitor_dvi:
1137         case sunxi_monitor_hdmi:
1138                 if (!sunxi_has_hdmi()) {
1139                         printf("HDMI/DVI not supported on this board\n");
1140                         sunxi_display.monitor = sunxi_monitor_none;
1141                         return NULL;
1142                 }
1143                 break;
1144         case sunxi_monitor_lcd:
1145                 if (!sunxi_has_lcd()) {
1146                         printf("LCD not supported on this board\n");
1147                         sunxi_display.monitor = sunxi_monitor_none;
1148                         return NULL;
1149                 }
1150                 sunxi_display.depth = video_get_params(&custom, lcd_mode);
1151                 mode = &custom;
1152                 break;
1153         case sunxi_monitor_vga:
1154                 if (!sunxi_has_vga()) {
1155                         printf("VGA not supported on this board\n");
1156                         sunxi_display.monitor = sunxi_monitor_none;
1157                         return NULL;
1158                 }
1159                 sunxi_display.depth = 18;
1160                 break;
1161         case sunxi_monitor_composite_pal:
1162         case sunxi_monitor_composite_ntsc:
1163         case sunxi_monitor_composite_pal_m:
1164         case sunxi_monitor_composite_pal_nc:
1165                 if (!sunxi_has_composite()) {
1166                         printf("Composite video not supported on this board\n");
1167                         sunxi_display.monitor = sunxi_monitor_none;
1168                         return NULL;
1169                 }
1170                 if (sunxi_display.monitor == sunxi_monitor_composite_pal ||
1171                     sunxi_display.monitor == sunxi_monitor_composite_pal_nc)
1172                         mode = &composite_video_modes[0];
1173                 else
1174                         mode = &composite_video_modes[1];
1175                 sunxi_display.depth = 24;
1176                 break;
1177         }
1178
1179         /* Yes these defaults are quite high, overscan on composite sucks... */
1180         if (overscan_x == -1)
1181                 overscan_x = sunxi_is_composite() ? 32 : 0;
1182         if (overscan_y == -1)
1183                 overscan_y = sunxi_is_composite() ? 20 : 0;
1184
1185         sunxi_display.fb_size =
1186                 (mode->xres * mode->yres * 4 + 0xfff) & ~0xfff;
1187         overscan_offset = (overscan_y * mode->xres + overscan_x) * 4;
1188         /* We want to keep the fb_base for simplefb page aligned, where as
1189          * the sunxi dma engines will happily accept an unaligned address. */
1190         if (overscan_offset)
1191                 sunxi_display.fb_size += 0x1000;
1192
1193         if (sunxi_display.fb_size > CONFIG_SUNXI_MAX_FB_SIZE) {
1194                 printf("Error need %dkB for fb, but only %dkB is reserved\n",
1195                        sunxi_display.fb_size >> 10,
1196                        CONFIG_SUNXI_MAX_FB_SIZE >> 10);
1197                 return NULL;
1198         }
1199
1200         printf("Setting up a %dx%d%s %s console (overscan %dx%d)\n",
1201                mode->xres, mode->yres,
1202                (mode->vmode == FB_VMODE_INTERLACED) ? "i" : "",
1203                sunxi_get_mon_desc(sunxi_display.monitor),
1204                overscan_x, overscan_y);
1205
1206         gd->fb_base = gd->bd->bi_dram[0].start +
1207                       gd->bd->bi_dram[0].size - sunxi_display.fb_size;
1208         sunxi_engines_init();
1209
1210 #ifdef CONFIG_EFI_LOADER
1211         efi_add_memory_map(gd->fb_base,
1212                            ALIGN(sunxi_display.fb_size, EFI_PAGE_SIZE) >>
1213                            EFI_PAGE_SHIFT,
1214                            EFI_RESERVED_MEMORY_TYPE, false);
1215 #endif
1216
1217         fb_dma_addr = gd->fb_base - CONFIG_SYS_SDRAM_BASE;
1218         sunxi_display.fb_addr = gd->fb_base;
1219         if (overscan_offset) {
1220                 fb_dma_addr += 0x1000 - (overscan_offset & 0xfff);
1221                 sunxi_display.fb_addr += (overscan_offset + 0xfff) & ~0xfff;
1222                 memset((void *)gd->fb_base, 0, sunxi_display.fb_size);
1223                 flush_cache(gd->fb_base, sunxi_display.fb_size);
1224         }
1225         sunxi_mode_set(mode, fb_dma_addr);
1226
1227         /*
1228          * These are the only members of this structure that are used. All the
1229          * others are driver specific. The pitch is stored in plnSizeX.
1230          */
1231         graphic_device->frameAdrs = sunxi_display.fb_addr;
1232         graphic_device->gdfIndex = GDF_32BIT_X888RGB;
1233         graphic_device->gdfBytesPP = 4;
1234         graphic_device->winSizeX = mode->xres - 2 * overscan_x;
1235         graphic_device->winSizeY = mode->yres - 2 * overscan_y;
1236         graphic_device->plnSizeX = mode->xres * graphic_device->gdfBytesPP;
1237
1238         return graphic_device;
1239 }
1240
1241 /*
1242  * Simplefb support.
1243  */
1244 #if defined(CONFIG_OF_BOARD_SETUP) && defined(CONFIG_VIDEO_DT_SIMPLEFB)
1245 int sunxi_simplefb_setup(void *blob)
1246 {
1247         static GraphicDevice *graphic_device = &sunxi_display.graphic_device;
1248         int offset, ret;
1249         u64 start, size;
1250         const char *pipeline = NULL;
1251
1252 #ifdef CONFIG_MACH_SUN4I
1253 #define PIPELINE_PREFIX "de_fe0-"
1254 #else
1255 #define PIPELINE_PREFIX
1256 #endif
1257
1258         switch (sunxi_display.monitor) {
1259         case sunxi_monitor_none:
1260                 return 0;
1261         case sunxi_monitor_dvi:
1262         case sunxi_monitor_hdmi:
1263                 pipeline = PIPELINE_PREFIX "de_be0-lcd0-hdmi";
1264                 break;
1265         case sunxi_monitor_lcd:
1266                 pipeline = PIPELINE_PREFIX "de_be0-lcd0";
1267                 break;
1268         case sunxi_monitor_vga:
1269 #ifdef CONFIG_VIDEO_VGA
1270                 pipeline = PIPELINE_PREFIX "de_be0-lcd0-tve0";
1271 #elif defined CONFIG_VIDEO_VGA_VIA_LCD
1272                 pipeline = PIPELINE_PREFIX "de_be0-lcd0";
1273 #endif
1274                 break;
1275         case sunxi_monitor_composite_pal:
1276         case sunxi_monitor_composite_ntsc:
1277         case sunxi_monitor_composite_pal_m:
1278         case sunxi_monitor_composite_pal_nc:
1279                 pipeline = PIPELINE_PREFIX "de_be0-lcd0-tve0";
1280                 break;
1281         }
1282
1283         offset = sunxi_simplefb_fdt_match(blob, pipeline);
1284         if (offset < 0) {
1285                 eprintf("Cannot setup simplefb: node not found\n");
1286                 return 0; /* Keep older kernels working */
1287         }
1288
1289         /*
1290          * Do not report the framebuffer as free RAM to the OS, note we cannot
1291          * use fdt_add_mem_rsv() here, because then it is still seen as RAM,
1292          * and e.g. Linux refuses to iomap RAM on ARM, see:
1293          * linux/arch/arm/mm/ioremap.c around line 301.
1294          */
1295         start = gd->bd->bi_dram[0].start;
1296         size = gd->bd->bi_dram[0].size - sunxi_display.fb_size;
1297         ret = fdt_fixup_memory_banks(blob, &start, &size, 1);
1298         if (ret) {
1299                 eprintf("Cannot setup simplefb: Error reserving memory\n");
1300                 return ret;
1301         }
1302
1303         ret = fdt_setup_simplefb_node(blob, offset, sunxi_display.fb_addr,
1304                         graphic_device->winSizeX, graphic_device->winSizeY,
1305                         graphic_device->plnSizeX, "x8r8g8b8");
1306         if (ret)
1307                 eprintf("Cannot setup simplefb: Error setting properties\n");
1308
1309         return ret;
1310 }
1311 #endif /* CONFIG_OF_BOARD_SETUP && CONFIG_VIDEO_DT_SIMPLEFB */