tegra.c 19 KB

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