1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * Copyright (c) 2011 The Chromium OS Authors. 4 */ 5 6#include <backlight.h> 7#include <cpu_func.h> 8#include <dm.h> 9#include <fdtdec.h> 10#include <log.h> 11#include <panel.h> 12#include <part.h> 13#include <pwm.h> 14#include <video.h> 15#include <asm/cache.h> 16#include <asm/global_data.h> 17#include <asm/system.h> 18#include <asm/gpio.h> 19#include <asm/io.h> 20 21#include <asm/arch/clock.h> 22#include <asm/arch/funcmux.h> 23#include <asm/arch/pinmux.h> 24#include <asm/arch/powergate.h> 25#include <asm/arch/pwm.h> 26 27#include "tegra-dc.h" 28 29DECLARE_GLOBAL_DATA_PTR; 30 31/* Holder of Tegra per-SOC DC differences */ 32struct tegra_dc_soc_info { 33 bool has_timer; 34 bool has_rgb; 35 bool has_pgate; 36}; 37 38/* Information about the display controller */ 39struct tegra_lcd_priv { 40 int width; /* width in pixels */ 41 int height; /* height in pixels */ 42 enum video_log2_bpp log2_bpp; /* colour depth */ 43 struct display_timing timing; 44 struct udevice *panel; 45 struct dc_ctlr *dc; /* Display controller regmap */ 46 const struct tegra_dc_soc_info *soc; 47 fdt_addr_t frame_buffer; /* Address of frame buffer */ 48 unsigned pixel_clock; /* Pixel clock in Hz */ 49 int dc_clk[2]; /* Contains clk and its parent */ 50 ulong scdiv; /* Clock divider used by disp_clk_ctrl */ 51 bool rotation; /* 180 degree panel turn */ 52 bool pipe; /* DC controller: 0 for A, 1 for B */ 53}; 54 55enum { 56 /* Maximum LCD size we support */ 57 LCD_MAX_WIDTH = 2560, 58 LCD_MAX_HEIGHT = 1600, 59 LCD_MAX_LOG2_BPP = VIDEO_BPP16, 60}; 61 62static void update_window(struct tegra_lcd_priv *priv, 63 struct disp_ctl_win *win) 64{ 65 struct dc_ctlr *dc = priv->dc; 66 unsigned h_dda, v_dda; 67 unsigned long val; 68 69 val = readl(&dc->cmd.disp_win_header); 70 val |= WINDOW_A_SELECT; 71 writel(val, &dc->cmd.disp_win_header); 72 73 writel(win->fmt, &dc->win.color_depth); 74 75 clrsetbits_le32(&dc->win.byte_swap, BYTE_SWAP_MASK, 76 BYTE_SWAP_NOSWAP << BYTE_SWAP_SHIFT); 77 78 val = win->out_x << H_POSITION_SHIFT; 79 val |= win->out_y << V_POSITION_SHIFT; 80 writel(val, &dc->win.pos); 81 82 val = win->out_w << H_SIZE_SHIFT; 83 val |= win->out_h << V_SIZE_SHIFT; 84 writel(val, &dc->win.size); 85 86 val = (win->w * win->bpp / 8) << H_PRESCALED_SIZE_SHIFT; 87 val |= win->h << V_PRESCALED_SIZE_SHIFT; 88 writel(val, &dc->win.prescaled_size); 89 90 writel(0, &dc->win.h_initial_dda); 91 writel(0, &dc->win.v_initial_dda); 92 93 h_dda = (win->w * 0x1000) / max(win->out_w - 1, 1U); 94 v_dda = (win->h * 0x1000) / max(win->out_h - 1, 1U); 95 96 val = h_dda << H_DDA_INC_SHIFT; 97 val |= v_dda << V_DDA_INC_SHIFT; 98 writel(val, &dc->win.dda_increment); 99 100 writel(win->stride, &dc->win.line_stride); 101 writel(0, &dc->win.buf_stride); 102 103 val = WIN_ENABLE; 104 if (win->bpp < 24) 105 val |= COLOR_EXPAND; 106 107 if (priv->rotation) 108 val |= H_DIRECTION | V_DIRECTION; 109 110 writel(val, &dc->win.win_opt); 111 112 writel((unsigned long)win->phys_addr, &dc->winbuf.start_addr); 113 writel(win->x, &dc->winbuf.addr_h_offset); 114 writel(win->y, &dc->winbuf.addr_v_offset); 115 116 writel(0xff00, &dc->win.blend_nokey); 117 writel(0xff00, &dc->win.blend_1win); 118 119 val = GENERAL_ACT_REQ | WIN_A_ACT_REQ; 120 val |= GENERAL_UPDATE | WIN_A_UPDATE; 121 writel(val, &dc->cmd.state_ctrl); 122} 123 124static int update_display_mode(struct tegra_lcd_priv *priv) 125{ 126 struct dc_disp_reg *disp = &priv->dc->disp; 127 struct display_timing *dt = &priv->timing; 128 unsigned long val; 129 130 writel(0x0, &disp->disp_timing_opt); 131 132 writel(1 | 1 << 16, &disp->ref_to_sync); 133 writel(dt->hsync_len.typ | dt->vsync_len.typ << 16, &disp->sync_width); 134 writel(dt->hback_porch.typ | dt->vback_porch.typ << 16, 135 &disp->back_porch); 136 writel((dt->hfront_porch.typ - 1) | (dt->vfront_porch.typ - 1) << 16, 137 &disp->front_porch); 138 writel(dt->hactive.typ | (dt->vactive.typ << 16), &disp->disp_active); 139 140 if (priv->soc->has_rgb) { 141 val = DE_SELECT_ACTIVE << DE_SELECT_SHIFT; 142 val |= DE_CONTROL_NORMAL << DE_CONTROL_SHIFT; 143 writel(val, &disp->data_enable_opt); 144 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 151 if (priv->soc->has_rgb) 152 writel(0x00010001, &disp->shift_clk_opt); 153 154 val = PIXEL_CLK_DIVIDER_PCD1 << PIXEL_CLK_DIVIDER_SHIFT; 155 val |= priv->scdiv << SHIFT_CLK_DIVIDER_SHIFT; 156 writel(val, &disp->disp_clk_ctrl); 157 158 return 0; 159} 160 161/* Start up the display and turn on power to PWMs */ 162static void basic_init(struct dc_cmd_reg *cmd) 163{ 164 u32 val; 165 166 writel(0x00000100, &cmd->gen_incr_syncpt_ctrl); 167 writel(0x0000011a, &cmd->cont_syncpt_vsync); 168 writel(0x00000000, &cmd->int_type); 169 writel(0x00000000, &cmd->int_polarity); 170 writel(0x00000000, &cmd->int_mask); 171 writel(0x00000000, &cmd->int_enb); 172 173 val = PW0_ENABLE | PW1_ENABLE | PW2_ENABLE; 174 val |= PW3_ENABLE | PW4_ENABLE | PM0_ENABLE; 175 val |= PM1_ENABLE; 176 writel(val, &cmd->disp_pow_ctrl); 177 178 val = readl(&cmd->disp_cmd); 179 val &= ~CTRL_MODE_MASK; 180 val |= CTRL_MODE_C_DISPLAY << CTRL_MODE_SHIFT; 181 writel(val, &cmd->disp_cmd); 182} 183 184static void basic_init_timer(struct dc_disp_reg *disp) 185{ 186 writel(0x00000020, &disp->mem_high_pri); 187 writel(0x00000001, &disp->mem_high_pri_timer); 188} 189 190static const u32 rgb_enb_tab[PIN_REG_COUNT] = { 191 0x00000000, 192 0x00000000, 193 0x00000000, 194 0x00000000, 195}; 196 197static const u32 rgb_polarity_tab[PIN_REG_COUNT] = { 198 0x00000000, 199 0x01000000, 200 0x00000000, 201 0x00000000, 202}; 203 204static const u32 rgb_data_tab[PIN_REG_COUNT] = { 205 0x00000000, 206 0x00000000, 207 0x00000000, 208 0x00000000, 209}; 210 211static const u32 rgb_sel_tab[PIN_OUTPUT_SEL_COUNT] = { 212 0x00000000, 213 0x00000000, 214 0x00000000, 215 0x00000000, 216 0x00210222, 217 0x00002200, 218 0x00020000, 219}; 220 221static void rgb_enable(struct tegra_lcd_priv *priv) 222{ 223 struct dc_com_reg *com = &priv->dc->com; 224 struct display_timing *dt = &priv->timing; 225 u32 value; 226 int i; 227 228 for (i = 0; i < PIN_REG_COUNT; i++) { 229 writel(rgb_enb_tab[i], &com->pin_output_enb[i]); 230 writel(rgb_polarity_tab[i], &com->pin_output_polarity[i]); 231 writel(rgb_data_tab[i], &com->pin_output_data[i]); 232 } 233 234 /* configure H- and V-sync signal polarities */ 235 value = readl(&com->pin_output_polarity[1]); 236 237 if (dt->flags & DISPLAY_FLAGS_HSYNC_LOW) 238 value |= LHS_OUTPUT_POLARITY_LOW; 239 else 240 value &= ~LHS_OUTPUT_POLARITY_LOW; 241 242 if (dt->flags & DISPLAY_FLAGS_VSYNC_LOW) 243 value |= LVS_OUTPUT_POLARITY_LOW; 244 else 245 value &= ~LVS_OUTPUT_POLARITY_LOW; 246 247 writel(value, &com->pin_output_polarity[1]); 248 249 for (i = 0; i < PIN_OUTPUT_SEL_COUNT; i++) 250 writel(rgb_sel_tab[i], &com->pin_output_sel[i]); 251} 252 253static int setup_window(struct tegra_lcd_priv *priv, 254 struct disp_ctl_win *win) 255{ 256 if (priv->rotation) { 257 win->x = priv->width * 2 - 1; 258 win->y = priv->height - 1; 259 } else { 260 win->x = 0; 261 win->y = 0; 262 } 263 264 win->w = priv->width; 265 win->h = priv->height; 266 win->out_x = 0; 267 win->out_y = 0; 268 win->out_w = priv->width; 269 win->out_h = priv->height; 270 win->phys_addr = priv->frame_buffer; 271 win->stride = priv->width * (1 << priv->log2_bpp) / 8; 272 debug("%s: depth = %d\n", __func__, priv->log2_bpp); 273 switch (priv->log2_bpp) { 274 case VIDEO_BPP32: 275 win->fmt = COLOR_DEPTH_R8G8B8A8; 276 win->bpp = 32; 277 break; 278 case VIDEO_BPP16: 279 win->fmt = COLOR_DEPTH_B5G6R5; 280 win->bpp = 16; 281 break; 282 283 default: 284 debug("Unsupported LCD bit depth"); 285 return -1; 286 } 287 288 return 0; 289} 290 291/** 292 * Register a new display based on device tree configuration. 293 * 294 * The frame buffer can be positioned by U-Boot or overridden by the fdt. 295 * You should pass in the U-Boot address here, and check the contents of 296 * struct tegra_lcd_priv to see what was actually chosen. 297 * 298 * @param priv Driver's private data 299 * @param default_lcd_base Default address of LCD frame buffer 300 * Return: 0 if ok, -1 on error (unsupported bits per pixel) 301 */ 302static int tegra_display_probe(struct tegra_lcd_priv *priv, 303 void *default_lcd_base) 304{ 305 struct disp_ctl_win window; 306 unsigned long rate = clock_get_rate(priv->dc_clk[1]); 307 308 priv->frame_buffer = (u32)default_lcd_base; 309 310 /* 311 * We halve the rate if DISP1 parent is PLLD, since actual parent 312 * is plld_out0 which is PLLD divided by 2. 313 */ 314 if (priv->dc_clk[1] == CLOCK_ID_DISPLAY) 315 rate /= 2; 316 317#ifndef CONFIG_TEGRA20 318 /* PLLD2 obeys same rules as PLLD but it is present only on T30+ */ 319 if (priv->dc_clk[1] == CLOCK_ID_DISPLAY2) 320 rate /= 2; 321#endif 322 323 /* 324 * The pixel clock divider is in 7.1 format (where the bottom bit 325 * represents 0.5). Here we calculate the divider needed to get from 326 * the display clock (typically 600MHz) to the pixel clock. We round 327 * up or down as required. 328 */ 329 if (!priv->scdiv) 330 priv->scdiv = ((rate * 2 + priv->pixel_clock / 2) 331 / priv->pixel_clock) - 2; 332 debug("Display clock %lu, divider %lu\n", rate, priv->scdiv); 333 334 /* 335 * HOST1X is init by default at 150MHz with PLLC as parent 336 */ 337 clock_start_periph_pll(PERIPH_ID_HOST1X, CLOCK_ID_CGENERAL, 338 150 * 1000000); 339 clock_start_periph_pll(priv->dc_clk[0], priv->dc_clk[1], 340 rate); 341 342 basic_init(&priv->dc->cmd); 343 344 if (priv->soc->has_timer) 345 basic_init_timer(&priv->dc->disp); 346 347 if (priv->soc->has_rgb) 348 rgb_enable(priv); 349 350 if (priv->pixel_clock) 351 update_display_mode(priv); 352 353 if (setup_window(priv, &window)) 354 return -1; 355 356 update_window(priv, &window); 357 358 return 0; 359} 360 361static int tegra_lcd_probe(struct udevice *dev) 362{ 363 struct video_uc_plat *plat = dev_get_uclass_plat(dev); 364 struct video_priv *uc_priv = dev_get_uclass_priv(dev); 365 struct tegra_lcd_priv *priv = dev_get_priv(dev); 366 int ret; 367 368 /* Initialize the Tegra display controller */ 369#ifdef CONFIG_TEGRA20 370 funcmux_select(PERIPH_ID_DISP1, FUNCMUX_DEFAULT); 371#endif 372 373 if (priv->soc->has_pgate) { 374 uint powergate; 375 376 if (priv->pipe) 377 powergate = TEGRA_POWERGATE_DISB; 378 else 379 powergate = TEGRA_POWERGATE_DIS; 380 381 ret = tegra_powergate_power_off(powergate); 382 if (ret < 0) { 383 log_err("failed to power off DISP gate: %d", ret); 384 return ret; 385 } 386 387 ret = tegra_powergate_sequence_power_up(powergate, 388 priv->dc_clk[0]); 389 if (ret < 0) { 390 log_err("failed to power up DISP gate: %d", ret); 391 return ret; 392 } 393 } 394 395 /* Get shift clock divider from Tegra DSI if used */ 396 if (!strcmp(priv->panel->name, TEGRA_DSI_A) || 397 !strcmp(priv->panel->name, TEGRA_DSI_B)) { 398 struct tegra_dc_plat *dc_plat = dev_get_plat(priv->panel); 399 400 priv->scdiv = dc_plat->scdiv; 401 } 402 403 /* Clean the framebuffer area */ 404 memset((u8 *)plat->base, 0, plat->size); 405 flush_dcache_all(); 406 407 if (tegra_display_probe(priv, (void *)plat->base)) { 408 debug("%s: Failed to probe display driver\n", __func__); 409 return -1; 410 } 411 412#ifdef CONFIG_TEGRA20 413 pinmux_set_func(PMUX_PINGRP_GPU, PMUX_FUNC_PWM); 414 pinmux_tristate_disable(PMUX_PINGRP_GPU); 415#endif 416 417 ret = panel_enable_backlight(priv->panel); 418 if (ret) { 419 debug("%s: Cannot enable backlight, ret=%d\n", __func__, ret); 420 return ret; 421 } 422 423 mmu_set_region_dcache_behaviour(priv->frame_buffer, plat->size, 424 DCACHE_WRITETHROUGH); 425 426 /* Enable flushing after LCD writes if requested */ 427 video_set_flush_dcache(dev, true); 428 429 uc_priv->xsize = priv->width; 430 uc_priv->ysize = priv->height; 431 uc_priv->bpix = priv->log2_bpp; 432 debug("LCD frame buffer at %08x, size %x\n", priv->frame_buffer, 433 plat->size); 434 435 return panel_set_backlight(priv->panel, BACKLIGHT_DEFAULT); 436} 437 438static int tegra_lcd_of_to_plat(struct udevice *dev) 439{ 440 struct tegra_lcd_priv *priv = dev_get_priv(dev); 441 const void *blob = gd->fdt_blob; 442 struct display_timing *timing; 443 int node = dev_of_offset(dev); 444 int panel_node; 445 int rgb; 446 int ret; 447 448 priv->dc = (struct dc_ctlr *)dev_read_addr_ptr(dev); 449 if (!priv->dc) { 450 debug("%s: No display controller address\n", __func__); 451 return -EINVAL; 452 } 453 454 priv->soc = (struct tegra_dc_soc_info *)dev_get_driver_data(dev); 455 456 ret = clock_decode_pair(dev, priv->dc_clk); 457 if (ret < 0) { 458 debug("%s: Cannot decode clocks for '%s' (ret = %d)\n", 459 __func__, dev->name, ret); 460 return -EINVAL; 461 } 462 463 priv->rotation = dev_read_bool(dev, "nvidia,180-rotation"); 464 465 if (!strcmp(dev->name, TEGRA_DC_B)) 466 priv->pipe = 1; 467 468 rgb = fdt_subnode_offset(blob, node, "rgb"); 469 if (rgb < 0) { 470 debug("%s: Cannot find rgb subnode for '%s' (ret=%d)\n", 471 __func__, dev->name, rgb); 472 return -EINVAL; 473 } 474 475 /* 476 * Sadly the panel phandle is in an rgb subnode so we cannot use 477 * uclass_get_device_by_phandle(). 478 */ 479 panel_node = fdtdec_lookup_phandle(blob, rgb, "nvidia,panel"); 480 if (panel_node < 0) { 481 debug("%s: Cannot find panel information\n", __func__); 482 return -EINVAL; 483 } 484 485 ret = uclass_get_device_by_of_offset(UCLASS_PANEL, panel_node, 486 &priv->panel); 487 if (ret) { 488 debug("%s: Cannot find panel for '%s' (ret=%d)\n", __func__, 489 dev->name, ret); 490 return ret; 491 } 492 493 /* Fill the platform data for internal devices */ 494 if (!strcmp(priv->panel->name, TEGRA_DSI_A) || 495 !strcmp(priv->panel->name, TEGRA_DSI_B)) { 496 struct tegra_dc_plat *dc_plat = dev_get_plat(priv->panel); 497 498 dc_plat->dev = dev; 499 dc_plat->dc = priv->dc; 500 dc_plat->pipe = priv->pipe; 501 } 502 503 ret = panel_get_display_timing(priv->panel, &priv->timing); 504 if (ret) { 505 ret = fdtdec_decode_display_timing(blob, rgb, 0, &priv->timing); 506 if (ret) { 507 debug("%s: Cannot read display timing for '%s' (ret=%d)\n", 508 __func__, dev->name, ret); 509 return -EINVAL; 510 } 511 } 512 513 timing = &priv->timing; 514 priv->width = timing->hactive.typ; 515 priv->height = timing->vactive.typ; 516 priv->pixel_clock = timing->pixelclock.typ; 517 priv->log2_bpp = VIDEO_BPP16; 518 519 return 0; 520} 521 522static int tegra_lcd_bind(struct udevice *dev) 523{ 524 struct video_uc_plat *plat = dev_get_uclass_plat(dev); 525 const void *blob = gd->fdt_blob; 526 int node = dev_of_offset(dev); 527 int rgb; 528 529 rgb = fdt_subnode_offset(blob, node, "rgb"); 530 if ((rgb < 0) || !fdtdec_get_is_enabled(blob, rgb)) 531 return -ENODEV; 532 533 plat->size = LCD_MAX_WIDTH * LCD_MAX_HEIGHT * 534 (1 << LCD_MAX_LOG2_BPP) / 8; 535 536 return 0; 537} 538 539static const struct video_ops tegra_lcd_ops = { 540}; 541 542static const struct tegra_dc_soc_info tegra20_dc_soc_info = { 543 .has_timer = true, 544 .has_rgb = true, 545 .has_pgate = false, 546}; 547 548static const struct tegra_dc_soc_info tegra30_dc_soc_info = { 549 .has_timer = false, 550 .has_rgb = true, 551 .has_pgate = false, 552}; 553 554static const struct tegra_dc_soc_info tegra114_dc_soc_info = { 555 .has_timer = false, 556 .has_rgb = false, 557 .has_pgate = true, 558}; 559 560static const struct udevice_id tegra_lcd_ids[] = { 561 { 562 .compatible = "nvidia,tegra20-dc", 563 .data = (ulong)&tegra20_dc_soc_info 564 }, { 565 .compatible = "nvidia,tegra30-dc", 566 .data = (ulong)&tegra30_dc_soc_info 567 }, { 568 .compatible = "nvidia,tegra114-dc", 569 .data = (ulong)&tegra114_dc_soc_info 570 }, { 571 /* sentinel */ 572 } 573}; 574 575U_BOOT_DRIVER(tegra_lcd) = { 576 .name = "tegra_lcd", 577 .id = UCLASS_VIDEO, 578 .of_match = tegra_lcd_ids, 579 .ops = &tegra_lcd_ops, 580 .bind = tegra_lcd_bind, 581 .probe = tegra_lcd_probe, 582 .of_to_plat = tegra_lcd_of_to_plat, 583 .priv_auto = sizeof(struct tegra_lcd_priv), 584}; 585