xref: /rk3399_rockchip-uboot/drivers/video/tegra.c (revision ce0c474a72a72efe83808473a3411986a564e86b)
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