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 */ 1312