1 /* 2 * Copyright (c) 2011 The Chromium OS Authors. 3 * SPDX-License-Identifier: GPL-2.0+ 4 */ 5 6 #include <common.h> 7 #include <fdtdec.h> 8 #include <lcd.h> 9 10 #include <asm/system.h> 11 #include <asm/gpio.h> 12 #include <asm/io.h> 13 14 #include <asm/arch/clock.h> 15 #include <asm/arch/funcmux.h> 16 #include <asm/arch/pinmux.h> 17 #include <asm/arch/pwm.h> 18 #include <asm/arch/display.h> 19 #include <asm/arch-tegra/timer.h> 20 21 DECLARE_GLOBAL_DATA_PTR; 22 23 /* These are the stages we go throuh in enabling the LCD */ 24 enum stage_t { 25 STAGE_START, 26 STAGE_PANEL_VDD, 27 STAGE_LVDS, 28 STAGE_BACKLIGHT_VDD, 29 STAGE_PWM, 30 STAGE_BACKLIGHT_EN, 31 STAGE_DONE, 32 }; 33 34 static enum stage_t stage; /* Current stage we are at */ 35 static unsigned long timer_next; /* Time we can move onto next stage */ 36 37 /* Information about the display controller */ 38 struct tegra_lcd_priv { 39 int valid; /* config is valid */ 40 int width; /* width in pixels */ 41 int height; /* height in pixels */ 42 int bpp; /* number of bits per pixel */ 43 44 /* 45 * log2 of number of bpp, in general, unless it bpp is 24 in which 46 * case this field holds 24 also! This is a U-Boot thing. 47 */ 48 int log2_bpp; 49 struct disp_ctlr *disp; /* Display controller to use */ 50 fdt_addr_t frame_buffer; /* Address of frame buffer */ 51 unsigned pixel_clock; /* Pixel clock in Hz */ 52 uint horiz_timing[FDT_LCD_TIMING_COUNT]; /* Horizontal timing */ 53 uint vert_timing[FDT_LCD_TIMING_COUNT]; /* Vertical timing */ 54 int panel_node; /* node offset of panel information */ 55 int pwm_channel; /* PWM channel to use for backlight */ 56 enum lcd_cache_t cache_type; 57 58 struct gpio_desc backlight_en; /* GPIO for backlight enable */ 59 struct gpio_desc lvds_shutdown; /* GPIO for lvds shutdown */ 60 struct gpio_desc backlight_vdd; /* GPIO for backlight vdd */ 61 struct gpio_desc panel_vdd; /* GPIO for panel vdd */ 62 /* 63 * Panel required timings 64 * Timing 1: delay between panel_vdd-rise and data-rise 65 * Timing 2: delay between data-rise and backlight_vdd-rise 66 * Timing 3: delay between backlight_vdd and pwm-rise 67 * Timing 4: delay between pwm-rise and backlight_en-rise 68 */ 69 uint panel_timings[FDT_LCD_TIMINGS]; 70 }; 71 72 /* Our LCD config, set up in handle_stage() */ 73 static struct tegra_lcd_priv config; 74 struct tegra_lcd_priv *disp_config; /* Display controller config */ 75 76 enum { 77 /* Maximum LCD size we support */ 78 LCD_MAX_WIDTH = 1366, 79 LCD_MAX_HEIGHT = 768, 80 LCD_MAX_LOG2_BPP = 4, /* 2^4 = 16 bpp */ 81 }; 82 83 vidinfo_t panel_info = { 84 /* Insert a value here so that we don't end up in the BSS */ 85 .vl_col = -1, 86 }; 87 88 static void update_window(struct dc_ctlr *dc, struct disp_ctl_win *win) 89 { 90 unsigned h_dda, v_dda; 91 unsigned long val; 92 93 val = readl(&dc->cmd.disp_win_header); 94 val |= WINDOW_A_SELECT; 95 writel(val, &dc->cmd.disp_win_header); 96 97 writel(win->fmt, &dc->win.color_depth); 98 99 clrsetbits_le32(&dc->win.byte_swap, BYTE_SWAP_MASK, 100 BYTE_SWAP_NOSWAP << BYTE_SWAP_SHIFT); 101 102 val = win->out_x << H_POSITION_SHIFT; 103 val |= win->out_y << V_POSITION_SHIFT; 104 writel(val, &dc->win.pos); 105 106 val = win->out_w << H_SIZE_SHIFT; 107 val |= win->out_h << V_SIZE_SHIFT; 108 writel(val, &dc->win.size); 109 110 val = (win->w * win->bpp / 8) << H_PRESCALED_SIZE_SHIFT; 111 val |= win->h << V_PRESCALED_SIZE_SHIFT; 112 writel(val, &dc->win.prescaled_size); 113 114 writel(0, &dc->win.h_initial_dda); 115 writel(0, &dc->win.v_initial_dda); 116 117 h_dda = (win->w * 0x1000) / max(win->out_w - 1, 1U); 118 v_dda = (win->h * 0x1000) / max(win->out_h - 1, 1U); 119 120 val = h_dda << H_DDA_INC_SHIFT; 121 val |= v_dda << V_DDA_INC_SHIFT; 122 writel(val, &dc->win.dda_increment); 123 124 writel(win->stride, &dc->win.line_stride); 125 writel(0, &dc->win.buf_stride); 126 127 val = WIN_ENABLE; 128 if (win->bpp < 24) 129 val |= COLOR_EXPAND; 130 writel(val, &dc->win.win_opt); 131 132 writel((unsigned long)win->phys_addr, &dc->winbuf.start_addr); 133 writel(win->x, &dc->winbuf.addr_h_offset); 134 writel(win->y, &dc->winbuf.addr_v_offset); 135 136 writel(0xff00, &dc->win.blend_nokey); 137 writel(0xff00, &dc->win.blend_1win); 138 139 val = GENERAL_ACT_REQ | WIN_A_ACT_REQ; 140 val |= GENERAL_UPDATE | WIN_A_UPDATE; 141 writel(val, &dc->cmd.state_ctrl); 142 } 143 144 static void write_pair(struct tegra_lcd_priv *config, int item, u32 *reg) 145 { 146 writel(config->horiz_timing[item] | 147 (config->vert_timing[item] << 16), reg); 148 } 149 150 static int update_display_mode(struct dc_disp_reg *disp, 151 struct tegra_lcd_priv *config) 152 { 153 unsigned long val; 154 unsigned long rate; 155 unsigned long div; 156 157 writel(0x0, &disp->disp_timing_opt); 158 write_pair(config, FDT_LCD_TIMING_REF_TO_SYNC, &disp->ref_to_sync); 159 write_pair(config, FDT_LCD_TIMING_SYNC_WIDTH, &disp->sync_width); 160 write_pair(config, FDT_LCD_TIMING_BACK_PORCH, &disp->back_porch); 161 write_pair(config, FDT_LCD_TIMING_FRONT_PORCH, &disp->front_porch); 162 163 writel(config->width | (config->height << 16), &disp->disp_active); 164 165 val = DE_SELECT_ACTIVE << DE_SELECT_SHIFT; 166 val |= DE_CONTROL_NORMAL << DE_CONTROL_SHIFT; 167 writel(val, &disp->data_enable_opt); 168 169 val = DATA_FORMAT_DF1P1C << DATA_FORMAT_SHIFT; 170 val |= DATA_ALIGNMENT_MSB << DATA_ALIGNMENT_SHIFT; 171 val |= DATA_ORDER_RED_BLUE << DATA_ORDER_SHIFT; 172 writel(val, &disp->disp_interface_ctrl); 173 174 /* 175 * The pixel clock divider is in 7.1 format (where the bottom bit 176 * represents 0.5). Here we calculate the divider needed to get from 177 * the display clock (typically 600MHz) to the pixel clock. We round 178 * up or down as requried. 179 */ 180 rate = clock_get_periph_rate(PERIPH_ID_DISP1, CLOCK_ID_CGENERAL); 181 div = ((rate * 2 + config->pixel_clock / 2) / config->pixel_clock) - 2; 182 debug("Display clock %lu, divider %lu\n", rate, div); 183 184 writel(0x00010001, &disp->shift_clk_opt); 185 186 val = PIXEL_CLK_DIVIDER_PCD1 << PIXEL_CLK_DIVIDER_SHIFT; 187 val |= div << SHIFT_CLK_DIVIDER_SHIFT; 188 writel(val, &disp->disp_clk_ctrl); 189 190 return 0; 191 } 192 193 /* Start up the display and turn on power to PWMs */ 194 static void basic_init(struct dc_cmd_reg *cmd) 195 { 196 u32 val; 197 198 writel(0x00000100, &cmd->gen_incr_syncpt_ctrl); 199 writel(0x0000011a, &cmd->cont_syncpt_vsync); 200 writel(0x00000000, &cmd->int_type); 201 writel(0x00000000, &cmd->int_polarity); 202 writel(0x00000000, &cmd->int_mask); 203 writel(0x00000000, &cmd->int_enb); 204 205 val = PW0_ENABLE | PW1_ENABLE | PW2_ENABLE; 206 val |= PW3_ENABLE | PW4_ENABLE | PM0_ENABLE; 207 val |= PM1_ENABLE; 208 writel(val, &cmd->disp_pow_ctrl); 209 210 val = readl(&cmd->disp_cmd); 211 val |= CTRL_MODE_C_DISPLAY << CTRL_MODE_SHIFT; 212 writel(val, &cmd->disp_cmd); 213 } 214 215 static void basic_init_timer(struct dc_disp_reg *disp) 216 { 217 writel(0x00000020, &disp->mem_high_pri); 218 writel(0x00000001, &disp->mem_high_pri_timer); 219 } 220 221 static const u32 rgb_enb_tab[PIN_REG_COUNT] = { 222 0x00000000, 223 0x00000000, 224 0x00000000, 225 0x00000000, 226 }; 227 228 static const u32 rgb_polarity_tab[PIN_REG_COUNT] = { 229 0x00000000, 230 0x01000000, 231 0x00000000, 232 0x00000000, 233 }; 234 235 static const u32 rgb_data_tab[PIN_REG_COUNT] = { 236 0x00000000, 237 0x00000000, 238 0x00000000, 239 0x00000000, 240 }; 241 242 static const u32 rgb_sel_tab[PIN_OUTPUT_SEL_COUNT] = { 243 0x00000000, 244 0x00000000, 245 0x00000000, 246 0x00000000, 247 0x00210222, 248 0x00002200, 249 0x00020000, 250 }; 251 252 static void rgb_enable(struct dc_com_reg *com) 253 { 254 int i; 255 256 for (i = 0; i < PIN_REG_COUNT; i++) { 257 writel(rgb_enb_tab[i], &com->pin_output_enb[i]); 258 writel(rgb_polarity_tab[i], &com->pin_output_polarity[i]); 259 writel(rgb_data_tab[i], &com->pin_output_data[i]); 260 } 261 262 for (i = 0; i < PIN_OUTPUT_SEL_COUNT; i++) 263 writel(rgb_sel_tab[i], &com->pin_output_sel[i]); 264 } 265 266 static int setup_window(struct disp_ctl_win *win, 267 struct tegra_lcd_priv *config) 268 { 269 win->x = 0; 270 win->y = 0; 271 win->w = config->width; 272 win->h = config->height; 273 win->out_x = 0; 274 win->out_y = 0; 275 win->out_w = config->width; 276 win->out_h = config->height; 277 win->phys_addr = config->frame_buffer; 278 win->stride = config->width * (1 << config->log2_bpp) / 8; 279 debug("%s: depth = %d\n", __func__, config->log2_bpp); 280 switch (config->log2_bpp) { 281 case 5: 282 case 24: 283 win->fmt = COLOR_DEPTH_R8G8B8A8; 284 win->bpp = 32; 285 break; 286 case 4: 287 win->fmt = COLOR_DEPTH_B5G6R5; 288 win->bpp = 16; 289 break; 290 291 default: 292 debug("Unsupported LCD bit depth"); 293 return -1; 294 } 295 296 return 0; 297 } 298 299 /** 300 * Return the current display configuration 301 * 302 * @return pointer to display configuration, or NULL if there is no valid 303 * config 304 */ 305 struct tegra_lcd_priv *tegra_display_get_config(void) 306 { 307 return config.valid ? &config : NULL; 308 } 309 310 static void debug_timing(const char *name, unsigned int timing[]) 311 { 312 #ifdef DEBUG 313 int i; 314 315 debug("%s timing: ", name); 316 for (i = 0; i < FDT_LCD_TIMING_COUNT; i++) 317 debug("%d ", timing[i]); 318 debug("\n"); 319 #endif 320 } 321 322 /** 323 * Decode panel information from the fdt, according to a standard binding 324 * 325 * @param blob fdt blob 326 * @param node offset of fdt node to read from 327 * @param config structure to store fdt config into 328 * @return 0 if ok, -ve on error 329 */ 330 static int tegra_decode_panel(const void *blob, int node, 331 struct tegra_lcd_priv *config) 332 { 333 int front, back, ref; 334 335 config->width = fdtdec_get_int(blob, node, "xres", -1); 336 config->height = fdtdec_get_int(blob, node, "yres", -1); 337 config->pixel_clock = fdtdec_get_int(blob, node, "clock", 0); 338 if (!config->pixel_clock || config->width == -1 || 339 config->height == -1) { 340 debug("%s: Pixel parameters missing\n", __func__); 341 return -FDT_ERR_NOTFOUND; 342 } 343 344 back = fdtdec_get_int(blob, node, "left-margin", -1); 345 front = fdtdec_get_int(blob, node, "right-margin", -1); 346 ref = fdtdec_get_int(blob, node, "hsync-len", -1); 347 if ((back | front | ref) == -1) { 348 debug("%s: Horizontal parameters missing\n", __func__); 349 return -FDT_ERR_NOTFOUND; 350 } 351 352 /* Use a ref-to-sync of 1 always, and take this from the front porch */ 353 config->horiz_timing[FDT_LCD_TIMING_REF_TO_SYNC] = 1; 354 config->horiz_timing[FDT_LCD_TIMING_SYNC_WIDTH] = ref; 355 config->horiz_timing[FDT_LCD_TIMING_BACK_PORCH] = back; 356 config->horiz_timing[FDT_LCD_TIMING_FRONT_PORCH] = front - 357 config->horiz_timing[FDT_LCD_TIMING_REF_TO_SYNC]; 358 debug_timing("horiz", config->horiz_timing); 359 360 back = fdtdec_get_int(blob, node, "upper-margin", -1); 361 front = fdtdec_get_int(blob, node, "lower-margin", -1); 362 ref = fdtdec_get_int(blob, node, "vsync-len", -1); 363 if ((back | front | ref) == -1) { 364 debug("%s: Vertical parameters missing\n", __func__); 365 return -FDT_ERR_NOTFOUND; 366 } 367 368 config->vert_timing[FDT_LCD_TIMING_REF_TO_SYNC] = 1; 369 config->vert_timing[FDT_LCD_TIMING_SYNC_WIDTH] = ref; 370 config->vert_timing[FDT_LCD_TIMING_BACK_PORCH] = back; 371 config->vert_timing[FDT_LCD_TIMING_FRONT_PORCH] = front - 372 config->vert_timing[FDT_LCD_TIMING_REF_TO_SYNC]; 373 debug_timing("vert", config->vert_timing); 374 375 return 0; 376 } 377 378 /** 379 * Decode the display controller information from the fdt. 380 * 381 * @param blob fdt blob 382 * @param config structure to store fdt config into 383 * @return 0 if ok, -ve on error 384 */ 385 static int tegra_display_decode_config(const void *blob, 386 struct tegra_lcd_priv *config) 387 { 388 int node, rgb; 389 int bpp, bit; 390 391 /* TODO: Support multiple controllers */ 392 node = fdtdec_next_compatible(blob, 0, COMPAT_NVIDIA_TEGRA20_DC); 393 if (node < 0) { 394 debug("%s: Cannot find display controller node in fdt\n", 395 __func__); 396 return node; 397 } 398 config->disp = (struct disp_ctlr *)fdtdec_get_addr(blob, node, "reg"); 399 if (!config->disp) { 400 debug("%s: No display controller address\n", __func__); 401 return -1; 402 } 403 404 rgb = fdt_subnode_offset(blob, node, "rgb"); 405 406 config->panel_node = fdtdec_lookup_phandle(blob, rgb, "nvidia,panel"); 407 if (config->panel_node < 0) { 408 debug("%s: Cannot find panel information\n", __func__); 409 return -1; 410 } 411 412 if (tegra_decode_panel(blob, config->panel_node, config)) { 413 debug("%s: Failed to decode panel information\n", __func__); 414 return -1; 415 } 416 417 bpp = fdtdec_get_int(blob, config->panel_node, "nvidia,bits-per-pixel", 418 -1); 419 bit = ffs(bpp) - 1; 420 if (bpp == (1 << bit)) 421 config->log2_bpp = bit; 422 else 423 config->log2_bpp = bpp; 424 if (bpp == -1) { 425 debug("%s: Pixel bpp parameters missing\n", __func__); 426 return -FDT_ERR_NOTFOUND; 427 } 428 config->bpp = bpp; 429 430 config->valid = 1; /* we have a valid configuration */ 431 432 return 0; 433 } 434 435 /** 436 * Register a new display based on device tree configuration. 437 * 438 * The frame buffer can be positioned by U-Boot or overriden by the fdt. 439 * You should pass in the U-Boot address here, and check the contents of 440 * struct tegra_lcd_priv to see what was actually chosen. 441 * 442 * @param blob Device tree blob 443 * @param default_lcd_base Default address of LCD frame buffer 444 * @return 0 if ok, -1 on error (unsupported bits per pixel) 445 */ 446 static int tegra_display_probe(const void *blob, void *default_lcd_base) 447 { 448 struct disp_ctl_win window; 449 struct dc_ctlr *dc; 450 451 if (tegra_display_decode_config(blob, &config)) 452 return -1; 453 454 config.frame_buffer = (u32)default_lcd_base; 455 456 dc = (struct dc_ctlr *)config.disp; 457 458 /* 459 * A header file for clock constants was NAKed upstream. 460 * TODO: Put this into the FDT and fdt_lcd struct when we have clock 461 * support there 462 */ 463 clock_start_periph_pll(PERIPH_ID_HOST1X, CLOCK_ID_PERIPH, 464 144 * 1000000); 465 clock_start_periph_pll(PERIPH_ID_DISP1, CLOCK_ID_CGENERAL, 466 600 * 1000000); 467 basic_init(&dc->cmd); 468 basic_init_timer(&dc->disp); 469 rgb_enable(&dc->com); 470 471 if (config.pixel_clock) 472 update_display_mode(&dc->disp, &config); 473 474 if (setup_window(&window, &config)) 475 return -1; 476 477 update_window(dc, &window); 478 479 return 0; 480 } 481 482 static void update_panel_size(struct tegra_lcd_priv *config) 483 { 484 panel_info.vl_col = config->width; 485 panel_info.vl_row = config->height; 486 panel_info.vl_bpix = config->log2_bpp; 487 } 488 489 /* 490 * Main init function called by lcd driver. 491 * Inits and then prints test pattern if required. 492 */ 493 494 void lcd_ctrl_init(void *lcdbase) 495 { 496 int type = DCACHE_OFF; 497 int size; 498 499 assert(disp_config); 500 501 /* Make sure that we can acommodate the selected LCD */ 502 assert(disp_config->width <= LCD_MAX_WIDTH); 503 assert(disp_config->height <= LCD_MAX_HEIGHT); 504 assert(disp_config->log2_bpp <= LCD_MAX_LOG2_BPP); 505 if (disp_config->width <= LCD_MAX_WIDTH 506 && disp_config->height <= LCD_MAX_HEIGHT 507 && disp_config->log2_bpp <= LCD_MAX_LOG2_BPP) 508 update_panel_size(disp_config); 509 size = lcd_get_size(&lcd_line_length); 510 511 /* Set up the LCD caching as requested */ 512 if (config.cache_type & FDT_LCD_CACHE_WRITE_THROUGH) 513 type = DCACHE_WRITETHROUGH; 514 else if (config.cache_type & FDT_LCD_CACHE_WRITE_BACK) 515 type = DCACHE_WRITEBACK; 516 mmu_set_region_dcache_behaviour(disp_config->frame_buffer, size, type); 517 518 /* Enable flushing after LCD writes if requested */ 519 lcd_set_flush_dcache(config.cache_type & FDT_LCD_CACHE_FLUSH); 520 521 debug("LCD frame buffer at %pa\n", &disp_config->frame_buffer); 522 } 523 524 ulong calc_fbsize(void) 525 { 526 return (panel_info.vl_col * panel_info.vl_row * 527 NBITS(panel_info.vl_bpix)) / 8; 528 } 529 530 void lcd_setcolreg(ushort regno, ushort red, ushort green, ushort blue) 531 { 532 } 533 534 void tegra_lcd_early_init(const void *blob) 535 { 536 /* 537 * Go with the maximum size for now. We will fix this up after 538 * relocation. These values are only used for memory alocation. 539 */ 540 panel_info.vl_col = LCD_MAX_WIDTH; 541 panel_info.vl_row = LCD_MAX_HEIGHT; 542 panel_info.vl_bpix = LCD_MAX_LOG2_BPP; 543 } 544 545 /** 546 * Decode the panel information from the fdt. 547 * 548 * @param blob fdt blob 549 * @param config structure to store fdt config into 550 * @return 0 if ok, -ve on error 551 */ 552 static int fdt_decode_lcd(const void *blob, struct tegra_lcd_priv *config) 553 { 554 int display_node; 555 556 disp_config = tegra_display_get_config(); 557 if (!disp_config) { 558 debug("%s: Display controller is not configured\n", __func__); 559 return -1; 560 } 561 display_node = disp_config->panel_node; 562 if (display_node < 0) { 563 debug("%s: No panel configuration available\n", __func__); 564 return -1; 565 } 566 567 config->pwm_channel = pwm_request(blob, display_node, "nvidia,pwm"); 568 if (config->pwm_channel < 0) { 569 debug("%s: Unable to request PWM channel\n", __func__); 570 return -1; 571 } 572 573 config->cache_type = fdtdec_get_int(blob, display_node, 574 "nvidia,cache-type", 575 FDT_LCD_CACHE_WRITE_BACK_FLUSH); 576 577 /* These GPIOs are all optional */ 578 gpio_request_by_name_nodev(blob, display_node, 579 "nvidia,backlight-enable-gpios", 0, 580 &config->backlight_en, GPIOD_IS_OUT); 581 gpio_request_by_name_nodev(blob, display_node, 582 "nvidia,lvds-shutdown-gpios", 0, 583 &config->lvds_shutdown, GPIOD_IS_OUT); 584 gpio_request_by_name_nodev(blob, display_node, 585 "nvidia,backlight-vdd-gpios", 0, 586 &config->backlight_vdd, GPIOD_IS_OUT); 587 gpio_request_by_name_nodev(blob, display_node, 588 "nvidia,panel-vdd-gpios", 0, 589 &config->panel_vdd, GPIOD_IS_OUT); 590 591 return fdtdec_get_int_array(blob, display_node, "nvidia,panel-timings", 592 config->panel_timings, FDT_LCD_TIMINGS); 593 } 594 595 /** 596 * Handle the next stage of device init 597 */ 598 static int handle_stage(const void *blob) 599 { 600 debug("%s: stage %d\n", __func__, stage); 601 602 /* do the things for this stage */ 603 switch (stage) { 604 case STAGE_START: 605 /* Initialize the Tegra display controller */ 606 if (tegra_display_probe(gd->fdt_blob, (void *)gd->fb_base)) { 607 printf("%s: Failed to probe display driver\n", 608 __func__); 609 return -1; 610 } 611 612 /* get panel details */ 613 if (fdt_decode_lcd(blob, &config)) { 614 printf("No valid LCD information in device tree\n"); 615 return -1; 616 } 617 618 /* 619 * It is possible that the FDT has requested that the LCD be 620 * disabled. We currently don't support this. It would require 621 * changes to U-Boot LCD subsystem to have LCD support 622 * compiled in but not used. An easier option might be to 623 * still have a frame buffer, but leave the backlight off and 624 * remove all mention of lcd in the stdout environment 625 * variable. 626 */ 627 628 funcmux_select(PERIPH_ID_DISP1, FUNCMUX_DEFAULT); 629 break; 630 case STAGE_PANEL_VDD: 631 if (dm_gpio_is_valid(&config.panel_vdd)) 632 dm_gpio_set_value(&config.panel_vdd, 1); 633 break; 634 case STAGE_LVDS: 635 if (dm_gpio_is_valid(&config.lvds_shutdown)) 636 dm_gpio_set_value(&config.lvds_shutdown, 1); 637 break; 638 case STAGE_BACKLIGHT_VDD: 639 if (dm_gpio_is_valid(&config.backlight_vdd)) 640 dm_gpio_set_value(&config.backlight_vdd, 1); 641 break; 642 case STAGE_PWM: 643 /* Enable PWM at 15/16 high, 32768 Hz with divider 1 */ 644 pinmux_set_func(PMUX_PINGRP_GPU, PMUX_FUNC_PWM); 645 pinmux_tristate_disable(PMUX_PINGRP_GPU); 646 647 pwm_enable(config.pwm_channel, 32768, 0xdf, 1); 648 break; 649 case STAGE_BACKLIGHT_EN: 650 if (dm_gpio_is_valid(&config.backlight_en)) 651 dm_gpio_set_value(&config.backlight_en, 1); 652 break; 653 case STAGE_DONE: 654 break; 655 } 656 657 /* set up timer for next stage */ 658 timer_next = timer_get_us(); 659 if (stage < FDT_LCD_TIMINGS) 660 timer_next += config.panel_timings[stage] * 1000; 661 662 /* move to next stage */ 663 stage++; 664 return 0; 665 } 666 667 int tegra_lcd_check_next_stage(const void *blob, int wait) 668 { 669 if (stage == STAGE_DONE) 670 return 0; 671 672 do { 673 /* wait if we need to */ 674 debug("%s: stage %d\n", __func__, stage); 675 if (stage != STAGE_START) { 676 int delay = timer_next - timer_get_us(); 677 678 if (delay > 0) { 679 if (wait) 680 udelay(delay); 681 else 682 return 0; 683 } 684 } 685 686 if (handle_stage(blob)) 687 return -1; 688 } while (wait && stage != STAGE_DONE); 689 if (stage == STAGE_DONE) 690 debug("%s: LCD init complete\n", __func__); 691 692 return 0; 693 } 694 695 void lcd_enable(void) 696 { 697 /* 698 * Backlight and power init will be done separately in 699 * tegra_lcd_check_next_stage(), which should be called in 700 * board_late_init(). 701 * 702 * U-Boot code supports only colour depth, selected at compile time. 703 * The device tree setting should match this. Otherwise the display 704 * will not look right, and U-Boot may crash. 705 */ 706 if (disp_config->log2_bpp != LCD_BPP) { 707 printf("%s: Error: LCD depth configured in FDT (%d = %dbpp)" 708 " must match setting of LCD_BPP (%d)\n", __func__, 709 disp_config->log2_bpp, disp_config->bpp, LCD_BPP); 710 } 711 } 712