1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (C) 2017 NVIDIA CORPORATION. All rights reserved. 4 */ 5 6 #include <linux/clk.h> 7 #include <linux/delay.h> 8 #include <linux/host1x.h> 9 #include <linux/module.h> 10 #include <linux/of.h> 11 #include <linux/of_device.h> 12 #include <linux/of_graph.h> 13 #include <linux/platform_device.h> 14 #include <linux/pm_runtime.h> 15 #include <linux/reset.h> 16 17 #include <drm/drm_atomic.h> 18 #include <drm/drm_atomic_helper.h> 19 #include <drm/drm_fourcc.h> 20 #include <drm/drm_probe_helper.h> 21 22 #include "drm.h" 23 #include "dc.h" 24 #include "plane.h" 25 26 static const u32 tegra_shared_plane_formats[] = { 27 DRM_FORMAT_ARGB1555, 28 DRM_FORMAT_RGB565, 29 DRM_FORMAT_RGBA5551, 30 DRM_FORMAT_ARGB8888, 31 DRM_FORMAT_ABGR8888, 32 /* new on Tegra114 */ 33 DRM_FORMAT_ABGR4444, 34 DRM_FORMAT_ABGR1555, 35 DRM_FORMAT_BGRA5551, 36 DRM_FORMAT_XRGB1555, 37 DRM_FORMAT_RGBX5551, 38 DRM_FORMAT_XBGR1555, 39 DRM_FORMAT_BGRX5551, 40 DRM_FORMAT_BGR565, 41 DRM_FORMAT_XRGB8888, 42 DRM_FORMAT_XBGR8888, 43 /* planar formats */ 44 DRM_FORMAT_UYVY, 45 DRM_FORMAT_YUYV, 46 DRM_FORMAT_YUV420, 47 DRM_FORMAT_YUV422, 48 }; 49 50 static const u64 tegra_shared_plane_modifiers[] = { 51 DRM_FORMAT_MOD_LINEAR, 52 DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(0), 53 DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(1), 54 DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(2), 55 DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(3), 56 DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(4), 57 DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(5), 58 DRM_FORMAT_MOD_INVALID 59 }; 60 61 static inline unsigned int tegra_plane_offset(struct tegra_plane *plane, 62 unsigned int offset) 63 { 64 if (offset >= 0x500 && offset <= 0x581) { 65 offset = 0x000 + (offset - 0x500); 66 return plane->offset + offset; 67 } 68 69 if (offset >= 0x700 && offset <= 0x73c) { 70 offset = 0x180 + (offset - 0x700); 71 return plane->offset + offset; 72 } 73 74 if (offset >= 0x800 && offset <= 0x83e) { 75 offset = 0x1c0 + (offset - 0x800); 76 return plane->offset + offset; 77 } 78 79 dev_WARN(plane->dc->dev, "invalid offset: %x\n", offset); 80 81 return plane->offset + offset; 82 } 83 84 static inline u32 tegra_plane_readl(struct tegra_plane *plane, 85 unsigned int offset) 86 { 87 return tegra_dc_readl(plane->dc, tegra_plane_offset(plane, offset)); 88 } 89 90 static inline void tegra_plane_writel(struct tegra_plane *plane, u32 value, 91 unsigned int offset) 92 { 93 tegra_dc_writel(plane->dc, value, tegra_plane_offset(plane, offset)); 94 } 95 96 static int tegra_windowgroup_enable(struct tegra_windowgroup *wgrp) 97 { 98 int err = 0; 99 100 mutex_lock(&wgrp->lock); 101 102 if (wgrp->usecount == 0) { 103 err = host1x_client_resume(wgrp->parent); 104 if (err < 0) { 105 dev_err(wgrp->parent->dev, "failed to resume: %d\n", err); 106 goto unlock; 107 } 108 109 reset_control_deassert(wgrp->rst); 110 } 111 112 wgrp->usecount++; 113 114 unlock: 115 mutex_unlock(&wgrp->lock); 116 return err; 117 } 118 119 static void tegra_windowgroup_disable(struct tegra_windowgroup *wgrp) 120 { 121 int err; 122 123 mutex_lock(&wgrp->lock); 124 125 if (wgrp->usecount == 1) { 126 err = reset_control_assert(wgrp->rst); 127 if (err < 0) { 128 pr_err("failed to assert reset for window group %u\n", 129 wgrp->index); 130 } 131 132 host1x_client_suspend(wgrp->parent); 133 } 134 135 wgrp->usecount--; 136 mutex_unlock(&wgrp->lock); 137 } 138 139 int tegra_display_hub_prepare(struct tegra_display_hub *hub) 140 { 141 unsigned int i; 142 143 /* 144 * XXX Enabling/disabling windowgroups needs to happen when the owner 145 * display controller is disabled. There's currently no good point at 146 * which this could be executed, so unconditionally enable all window 147 * groups for now. 148 */ 149 for (i = 0; i < hub->soc->num_wgrps; i++) { 150 struct tegra_windowgroup *wgrp = &hub->wgrps[i]; 151 152 tegra_windowgroup_enable(wgrp); 153 } 154 155 return 0; 156 } 157 158 void tegra_display_hub_cleanup(struct tegra_display_hub *hub) 159 { 160 unsigned int i; 161 162 /* 163 * XXX Remove this once window groups can be more fine-grainedly 164 * enabled and disabled. 165 */ 166 for (i = 0; i < hub->soc->num_wgrps; i++) { 167 struct tegra_windowgroup *wgrp = &hub->wgrps[i]; 168 169 tegra_windowgroup_disable(wgrp); 170 } 171 } 172 173 static void tegra_shared_plane_update(struct tegra_plane *plane) 174 { 175 struct tegra_dc *dc = plane->dc; 176 unsigned long timeout; 177 u32 mask, value; 178 179 mask = COMMON_UPDATE | WIN_A_UPDATE << plane->base.index; 180 tegra_dc_writel(dc, mask, DC_CMD_STATE_CONTROL); 181 182 timeout = jiffies + msecs_to_jiffies(1000); 183 184 while (time_before(jiffies, timeout)) { 185 value = tegra_dc_readl(dc, DC_CMD_STATE_CONTROL); 186 if ((value & mask) == 0) 187 break; 188 189 usleep_range(100, 400); 190 } 191 } 192 193 static void tegra_shared_plane_activate(struct tegra_plane *plane) 194 { 195 struct tegra_dc *dc = plane->dc; 196 unsigned long timeout; 197 u32 mask, value; 198 199 mask = COMMON_ACTREQ | WIN_A_ACT_REQ << plane->base.index; 200 tegra_dc_writel(dc, mask, DC_CMD_STATE_CONTROL); 201 202 timeout = jiffies + msecs_to_jiffies(1000); 203 204 while (time_before(jiffies, timeout)) { 205 value = tegra_dc_readl(dc, DC_CMD_STATE_CONTROL); 206 if ((value & mask) == 0) 207 break; 208 209 usleep_range(100, 400); 210 } 211 } 212 213 static unsigned int 214 tegra_shared_plane_get_owner(struct tegra_plane *plane, struct tegra_dc *dc) 215 { 216 unsigned int offset = 217 tegra_plane_offset(plane, DC_WIN_CORE_WINDOWGROUP_SET_CONTROL); 218 219 return tegra_dc_readl(dc, offset) & OWNER_MASK; 220 } 221 222 static bool tegra_dc_owns_shared_plane(struct tegra_dc *dc, 223 struct tegra_plane *plane) 224 { 225 struct device *dev = dc->dev; 226 227 if (tegra_shared_plane_get_owner(plane, dc) == dc->pipe) { 228 if (plane->dc == dc) 229 return true; 230 231 dev_WARN(dev, "head %u owns window %u but is not attached\n", 232 dc->pipe, plane->index); 233 } 234 235 return false; 236 } 237 238 static int tegra_shared_plane_set_owner(struct tegra_plane *plane, 239 struct tegra_dc *new) 240 { 241 unsigned int offset = 242 tegra_plane_offset(plane, DC_WIN_CORE_WINDOWGROUP_SET_CONTROL); 243 struct tegra_dc *old = plane->dc, *dc = new ? new : old; 244 struct device *dev = new ? new->dev : old->dev; 245 unsigned int owner, index = plane->index; 246 u32 value; 247 248 value = tegra_dc_readl(dc, offset); 249 owner = value & OWNER_MASK; 250 251 if (new && (owner != OWNER_MASK && owner != new->pipe)) { 252 dev_WARN(dev, "window %u owned by head %u\n", index, owner); 253 return -EBUSY; 254 } 255 256 /* 257 * This seems to happen whenever the head has been disabled with one 258 * or more windows being active. This is harmless because we'll just 259 * reassign the window to the new head anyway. 260 */ 261 if (old && owner == OWNER_MASK) 262 dev_dbg(dev, "window %u not owned by head %u but %u\n", index, 263 old->pipe, owner); 264 265 value &= ~OWNER_MASK; 266 267 if (new) 268 value |= OWNER(new->pipe); 269 else 270 value |= OWNER_MASK; 271 272 tegra_dc_writel(dc, value, offset); 273 274 plane->dc = new; 275 276 return 0; 277 } 278 279 static void tegra_dc_assign_shared_plane(struct tegra_dc *dc, 280 struct tegra_plane *plane) 281 { 282 u32 value; 283 int err; 284 285 if (!tegra_dc_owns_shared_plane(dc, plane)) { 286 err = tegra_shared_plane_set_owner(plane, dc); 287 if (err < 0) 288 return; 289 } 290 291 value = tegra_plane_readl(plane, DC_WIN_CORE_IHUB_LINEBUF_CONFIG); 292 value |= MODE_FOUR_LINES; 293 tegra_plane_writel(plane, value, DC_WIN_CORE_IHUB_LINEBUF_CONFIG); 294 295 value = tegra_plane_readl(plane, DC_WIN_CORE_IHUB_WGRP_FETCH_METER); 296 value = SLOTS(1); 297 tegra_plane_writel(plane, value, DC_WIN_CORE_IHUB_WGRP_FETCH_METER); 298 299 /* disable watermark */ 300 value = tegra_plane_readl(plane, DC_WIN_CORE_IHUB_WGRP_LATENCY_CTLA); 301 value &= ~LATENCY_CTL_MODE_ENABLE; 302 tegra_plane_writel(plane, value, DC_WIN_CORE_IHUB_WGRP_LATENCY_CTLA); 303 304 value = tegra_plane_readl(plane, DC_WIN_CORE_IHUB_WGRP_LATENCY_CTLB); 305 value |= WATERMARK_MASK; 306 tegra_plane_writel(plane, value, DC_WIN_CORE_IHUB_WGRP_LATENCY_CTLB); 307 308 /* pipe meter */ 309 value = tegra_plane_readl(plane, DC_WIN_CORE_PRECOMP_WGRP_PIPE_METER); 310 value = PIPE_METER_INT(0) | PIPE_METER_FRAC(0); 311 tegra_plane_writel(plane, value, DC_WIN_CORE_PRECOMP_WGRP_PIPE_METER); 312 313 /* mempool entries */ 314 value = tegra_plane_readl(plane, DC_WIN_CORE_IHUB_WGRP_POOL_CONFIG); 315 value = MEMPOOL_ENTRIES(0x331); 316 tegra_plane_writel(plane, value, DC_WIN_CORE_IHUB_WGRP_POOL_CONFIG); 317 318 value = tegra_plane_readl(plane, DC_WIN_CORE_IHUB_THREAD_GROUP); 319 value &= ~THREAD_NUM_MASK; 320 value |= THREAD_NUM(plane->base.index); 321 value |= THREAD_GROUP_ENABLE; 322 tegra_plane_writel(plane, value, DC_WIN_CORE_IHUB_THREAD_GROUP); 323 324 tegra_shared_plane_update(plane); 325 tegra_shared_plane_activate(plane); 326 } 327 328 static void tegra_dc_remove_shared_plane(struct tegra_dc *dc, 329 struct tegra_plane *plane) 330 { 331 tegra_shared_plane_set_owner(plane, NULL); 332 } 333 334 static int tegra_shared_plane_atomic_check(struct drm_plane *plane, 335 struct drm_plane_state *state) 336 { 337 struct tegra_plane_state *plane_state = to_tegra_plane_state(state); 338 struct tegra_shared_plane *tegra = to_tegra_shared_plane(plane); 339 struct tegra_bo_tiling *tiling = &plane_state->tiling; 340 struct tegra_dc *dc = to_tegra_dc(state->crtc); 341 int err; 342 343 /* no need for further checks if the plane is being disabled */ 344 if (!state->crtc || !state->fb) 345 return 0; 346 347 err = tegra_plane_format(state->fb->format->format, 348 &plane_state->format, 349 &plane_state->swap); 350 if (err < 0) 351 return err; 352 353 err = tegra_fb_get_tiling(state->fb, tiling); 354 if (err < 0) 355 return err; 356 357 if (tiling->mode == TEGRA_BO_TILING_MODE_BLOCK && 358 !dc->soc->supports_block_linear) { 359 DRM_ERROR("hardware doesn't support block linear mode\n"); 360 return -EINVAL; 361 } 362 363 /* 364 * Tegra doesn't support different strides for U and V planes so we 365 * error out if the user tries to display a framebuffer with such a 366 * configuration. 367 */ 368 if (state->fb->format->num_planes > 2) { 369 if (state->fb->pitches[2] != state->fb->pitches[1]) { 370 DRM_ERROR("unsupported UV-plane configuration\n"); 371 return -EINVAL; 372 } 373 } 374 375 /* XXX scaling is not yet supported, add a check here */ 376 377 err = tegra_plane_state_add(&tegra->base, state); 378 if (err < 0) 379 return err; 380 381 return 0; 382 } 383 384 static void tegra_shared_plane_atomic_disable(struct drm_plane *plane, 385 struct drm_plane_state *old_state) 386 { 387 struct tegra_plane *p = to_tegra_plane(plane); 388 struct tegra_dc *dc; 389 u32 value; 390 int err; 391 392 /* rien ne va plus */ 393 if (!old_state || !old_state->crtc) 394 return; 395 396 dc = to_tegra_dc(old_state->crtc); 397 398 err = host1x_client_resume(&dc->client); 399 if (err < 0) { 400 dev_err(dc->dev, "failed to resume: %d\n", err); 401 return; 402 } 403 404 /* 405 * XXX Legacy helpers seem to sometimes call ->atomic_disable() even 406 * on planes that are already disabled. Make sure we fallback to the 407 * head for this particular state instead of crashing. 408 */ 409 if (WARN_ON(p->dc == NULL)) 410 p->dc = dc; 411 412 value = tegra_plane_readl(p, DC_WIN_WIN_OPTIONS); 413 value &= ~WIN_ENABLE; 414 tegra_plane_writel(p, value, DC_WIN_WIN_OPTIONS); 415 416 tegra_dc_remove_shared_plane(dc, p); 417 418 host1x_client_suspend(&dc->client); 419 } 420 421 static void tegra_shared_plane_atomic_update(struct drm_plane *plane, 422 struct drm_plane_state *old_state) 423 { 424 struct tegra_plane_state *state = to_tegra_plane_state(plane->state); 425 struct tegra_dc *dc = to_tegra_dc(plane->state->crtc); 426 unsigned int zpos = plane->state->normalized_zpos; 427 struct drm_framebuffer *fb = plane->state->fb; 428 struct tegra_plane *p = to_tegra_plane(plane); 429 dma_addr_t base; 430 u32 value; 431 int err; 432 433 /* rien ne va plus */ 434 if (!plane->state->crtc || !plane->state->fb) 435 return; 436 437 if (!plane->state->visible) { 438 tegra_shared_plane_atomic_disable(plane, old_state); 439 return; 440 } 441 442 err = host1x_client_resume(&dc->client); 443 if (err < 0) { 444 dev_err(dc->dev, "failed to resume: %d\n", err); 445 return; 446 } 447 448 tegra_dc_assign_shared_plane(dc, p); 449 450 tegra_plane_writel(p, VCOUNTER, DC_WIN_CORE_ACT_CONTROL); 451 452 /* blending */ 453 value = BLEND_FACTOR_DST_ALPHA_ZERO | BLEND_FACTOR_SRC_ALPHA_K2 | 454 BLEND_FACTOR_DST_COLOR_NEG_K1_TIMES_SRC | 455 BLEND_FACTOR_SRC_COLOR_K1_TIMES_SRC; 456 tegra_plane_writel(p, value, DC_WIN_BLEND_MATCH_SELECT); 457 458 value = BLEND_FACTOR_DST_ALPHA_ZERO | BLEND_FACTOR_SRC_ALPHA_K2 | 459 BLEND_FACTOR_DST_COLOR_NEG_K1_TIMES_SRC | 460 BLEND_FACTOR_SRC_COLOR_K1_TIMES_SRC; 461 tegra_plane_writel(p, value, DC_WIN_BLEND_NOMATCH_SELECT); 462 463 value = K2(255) | K1(255) | WINDOW_LAYER_DEPTH(255 - zpos); 464 tegra_plane_writel(p, value, DC_WIN_BLEND_LAYER_CONTROL); 465 466 /* bypass scaling */ 467 value = HORIZONTAL_TAPS_5 | VERTICAL_TAPS_5; 468 tegra_plane_writel(p, value, DC_WIN_WINDOWGROUP_SET_CONTROL_INPUT_SCALER); 469 470 value = INPUT_SCALER_VBYPASS | INPUT_SCALER_HBYPASS; 471 tegra_plane_writel(p, value, DC_WIN_WINDOWGROUP_SET_INPUT_SCALER_USAGE); 472 473 /* disable compression */ 474 tegra_plane_writel(p, 0, DC_WINBUF_CDE_CONTROL); 475 476 base = state->iova[0] + fb->offsets[0]; 477 478 tegra_plane_writel(p, state->format, DC_WIN_COLOR_DEPTH); 479 tegra_plane_writel(p, 0, DC_WIN_PRECOMP_WGRP_PARAMS); 480 481 value = V_POSITION(plane->state->crtc_y) | 482 H_POSITION(plane->state->crtc_x); 483 tegra_plane_writel(p, value, DC_WIN_POSITION); 484 485 value = V_SIZE(plane->state->crtc_h) | H_SIZE(plane->state->crtc_w); 486 tegra_plane_writel(p, value, DC_WIN_SIZE); 487 488 value = WIN_ENABLE | COLOR_EXPAND; 489 tegra_plane_writel(p, value, DC_WIN_WIN_OPTIONS); 490 491 value = V_SIZE(plane->state->crtc_h) | H_SIZE(plane->state->crtc_w); 492 tegra_plane_writel(p, value, DC_WIN_CROPPED_SIZE); 493 494 tegra_plane_writel(p, upper_32_bits(base), DC_WINBUF_START_ADDR_HI); 495 tegra_plane_writel(p, lower_32_bits(base), DC_WINBUF_START_ADDR); 496 497 value = PITCH(fb->pitches[0]); 498 tegra_plane_writel(p, value, DC_WIN_PLANAR_STORAGE); 499 500 value = CLAMP_BEFORE_BLEND | DEGAMMA_SRGB | INPUT_RANGE_FULL; 501 tegra_plane_writel(p, value, DC_WIN_SET_PARAMS); 502 503 value = OFFSET_X(plane->state->src_y >> 16) | 504 OFFSET_Y(plane->state->src_x >> 16); 505 tegra_plane_writel(p, value, DC_WINBUF_CROPPED_POINT); 506 507 if (dc->soc->supports_block_linear) { 508 unsigned long height = state->tiling.value; 509 510 /* XXX */ 511 switch (state->tiling.mode) { 512 case TEGRA_BO_TILING_MODE_PITCH: 513 value = DC_WINBUF_SURFACE_KIND_BLOCK_HEIGHT(0) | 514 DC_WINBUF_SURFACE_KIND_PITCH; 515 break; 516 517 /* XXX not supported on Tegra186 and later */ 518 case TEGRA_BO_TILING_MODE_TILED: 519 value = DC_WINBUF_SURFACE_KIND_TILED; 520 break; 521 522 case TEGRA_BO_TILING_MODE_BLOCK: 523 value = DC_WINBUF_SURFACE_KIND_BLOCK_HEIGHT(height) | 524 DC_WINBUF_SURFACE_KIND_BLOCK; 525 break; 526 } 527 528 tegra_plane_writel(p, value, DC_WINBUF_SURFACE_KIND); 529 } 530 531 /* disable gamut CSC */ 532 value = tegra_plane_readl(p, DC_WIN_WINDOW_SET_CONTROL); 533 value &= ~CONTROL_CSC_ENABLE; 534 tegra_plane_writel(p, value, DC_WIN_WINDOW_SET_CONTROL); 535 536 host1x_client_suspend(&dc->client); 537 } 538 539 static const struct drm_plane_helper_funcs tegra_shared_plane_helper_funcs = { 540 .prepare_fb = tegra_plane_prepare_fb, 541 .cleanup_fb = tegra_plane_cleanup_fb, 542 .atomic_check = tegra_shared_plane_atomic_check, 543 .atomic_update = tegra_shared_plane_atomic_update, 544 .atomic_disable = tegra_shared_plane_atomic_disable, 545 }; 546 547 struct drm_plane *tegra_shared_plane_create(struct drm_device *drm, 548 struct tegra_dc *dc, 549 unsigned int wgrp, 550 unsigned int index) 551 { 552 enum drm_plane_type type = DRM_PLANE_TYPE_OVERLAY; 553 struct tegra_drm *tegra = drm->dev_private; 554 struct tegra_display_hub *hub = tegra->hub; 555 /* planes can be assigned to arbitrary CRTCs */ 556 unsigned int possible_crtcs = 0x7; 557 struct tegra_shared_plane *plane; 558 unsigned int num_formats; 559 const u64 *modifiers; 560 struct drm_plane *p; 561 const u32 *formats; 562 int err; 563 564 plane = kzalloc(sizeof(*plane), GFP_KERNEL); 565 if (!plane) 566 return ERR_PTR(-ENOMEM); 567 568 plane->base.offset = 0x0a00 + 0x0300 * index; 569 plane->base.index = index; 570 571 plane->wgrp = &hub->wgrps[wgrp]; 572 plane->wgrp->parent = &dc->client; 573 574 p = &plane->base.base; 575 576 num_formats = ARRAY_SIZE(tegra_shared_plane_formats); 577 formats = tegra_shared_plane_formats; 578 modifiers = tegra_shared_plane_modifiers; 579 580 err = drm_universal_plane_init(drm, p, possible_crtcs, 581 &tegra_plane_funcs, formats, 582 num_formats, modifiers, type, NULL); 583 if (err < 0) { 584 kfree(plane); 585 return ERR_PTR(err); 586 } 587 588 drm_plane_helper_add(p, &tegra_shared_plane_helper_funcs); 589 drm_plane_create_zpos_property(p, 0, 0, 255); 590 591 return p; 592 } 593 594 static struct drm_private_state * 595 tegra_display_hub_duplicate_state(struct drm_private_obj *obj) 596 { 597 struct tegra_display_hub_state *state; 598 599 state = kmemdup(obj->state, sizeof(*state), GFP_KERNEL); 600 if (!state) 601 return NULL; 602 603 __drm_atomic_helper_private_obj_duplicate_state(obj, &state->base); 604 605 return &state->base; 606 } 607 608 static void tegra_display_hub_destroy_state(struct drm_private_obj *obj, 609 struct drm_private_state *state) 610 { 611 struct tegra_display_hub_state *hub_state = 612 to_tegra_display_hub_state(state); 613 614 kfree(hub_state); 615 } 616 617 static const struct drm_private_state_funcs tegra_display_hub_state_funcs = { 618 .atomic_duplicate_state = tegra_display_hub_duplicate_state, 619 .atomic_destroy_state = tegra_display_hub_destroy_state, 620 }; 621 622 static struct tegra_display_hub_state * 623 tegra_display_hub_get_state(struct tegra_display_hub *hub, 624 struct drm_atomic_state *state) 625 { 626 struct drm_private_state *priv; 627 628 priv = drm_atomic_get_private_obj_state(state, &hub->base); 629 if (IS_ERR(priv)) 630 return ERR_CAST(priv); 631 632 return to_tegra_display_hub_state(priv); 633 } 634 635 int tegra_display_hub_atomic_check(struct drm_device *drm, 636 struct drm_atomic_state *state) 637 { 638 struct tegra_drm *tegra = drm->dev_private; 639 struct tegra_display_hub_state *hub_state; 640 struct drm_crtc_state *old, *new; 641 struct drm_crtc *crtc; 642 unsigned int i; 643 644 if (!tegra->hub) 645 return 0; 646 647 hub_state = tegra_display_hub_get_state(tegra->hub, state); 648 if (IS_ERR(hub_state)) 649 return PTR_ERR(hub_state); 650 651 /* 652 * The display hub display clock needs to be fed by the display clock 653 * with the highest frequency to ensure proper functioning of all the 654 * displays. 655 * 656 * Note that this isn't used before Tegra186, but it doesn't hurt and 657 * conditionalizing it would make the code less clean. 658 */ 659 for_each_oldnew_crtc_in_state(state, crtc, old, new, i) { 660 struct tegra_dc_state *dc = to_dc_state(new); 661 662 if (new->active) { 663 if (!hub_state->clk || dc->pclk > hub_state->rate) { 664 hub_state->dc = to_tegra_dc(dc->base.crtc); 665 hub_state->clk = hub_state->dc->clk; 666 hub_state->rate = dc->pclk; 667 } 668 } 669 } 670 671 return 0; 672 } 673 674 static void tegra_display_hub_update(struct tegra_dc *dc) 675 { 676 u32 value; 677 int err; 678 679 err = host1x_client_resume(&dc->client); 680 if (err < 0) { 681 dev_err(dc->dev, "failed to resume: %d\n", err); 682 return; 683 } 684 685 value = tegra_dc_readl(dc, DC_CMD_IHUB_COMMON_MISC_CTL); 686 value &= ~LATENCY_EVENT; 687 tegra_dc_writel(dc, value, DC_CMD_IHUB_COMMON_MISC_CTL); 688 689 value = tegra_dc_readl(dc, DC_DISP_IHUB_COMMON_DISPLAY_FETCH_METER); 690 value = CURS_SLOTS(1) | WGRP_SLOTS(1); 691 tegra_dc_writel(dc, value, DC_DISP_IHUB_COMMON_DISPLAY_FETCH_METER); 692 693 tegra_dc_writel(dc, COMMON_UPDATE, DC_CMD_STATE_CONTROL); 694 tegra_dc_readl(dc, DC_CMD_STATE_CONTROL); 695 tegra_dc_writel(dc, COMMON_ACTREQ, DC_CMD_STATE_CONTROL); 696 tegra_dc_readl(dc, DC_CMD_STATE_CONTROL); 697 698 host1x_client_suspend(&dc->client); 699 } 700 701 void tegra_display_hub_atomic_commit(struct drm_device *drm, 702 struct drm_atomic_state *state) 703 { 704 struct tegra_drm *tegra = drm->dev_private; 705 struct tegra_display_hub *hub = tegra->hub; 706 struct tegra_display_hub_state *hub_state; 707 struct device *dev = hub->client.dev; 708 int err; 709 710 hub_state = to_tegra_display_hub_state(hub->base.state); 711 712 if (hub_state->clk) { 713 err = clk_set_rate(hub_state->clk, hub_state->rate); 714 if (err < 0) 715 dev_err(dev, "failed to set rate of %pC to %lu Hz\n", 716 hub_state->clk, hub_state->rate); 717 718 err = clk_set_parent(hub->clk_disp, hub_state->clk); 719 if (err < 0) 720 dev_err(dev, "failed to set parent of %pC to %pC: %d\n", 721 hub->clk_disp, hub_state->clk, err); 722 } 723 724 if (hub_state->dc) 725 tegra_display_hub_update(hub_state->dc); 726 } 727 728 static int tegra_display_hub_init(struct host1x_client *client) 729 { 730 struct tegra_display_hub *hub = to_tegra_display_hub(client); 731 struct drm_device *drm = dev_get_drvdata(client->host); 732 struct tegra_drm *tegra = drm->dev_private; 733 struct tegra_display_hub_state *state; 734 735 state = kzalloc(sizeof(*state), GFP_KERNEL); 736 if (!state) 737 return -ENOMEM; 738 739 drm_atomic_private_obj_init(drm, &hub->base, &state->base, 740 &tegra_display_hub_state_funcs); 741 742 tegra->hub = hub; 743 744 return 0; 745 } 746 747 static int tegra_display_hub_exit(struct host1x_client *client) 748 { 749 struct drm_device *drm = dev_get_drvdata(client->host); 750 struct tegra_drm *tegra = drm->dev_private; 751 752 drm_atomic_private_obj_fini(&tegra->hub->base); 753 tegra->hub = NULL; 754 755 return 0; 756 } 757 758 static int tegra_display_hub_runtime_suspend(struct host1x_client *client) 759 { 760 struct tegra_display_hub *hub = to_tegra_display_hub(client); 761 struct device *dev = client->dev; 762 unsigned int i = hub->num_heads; 763 int err; 764 765 err = reset_control_assert(hub->rst); 766 if (err < 0) 767 return err; 768 769 while (i--) 770 clk_disable_unprepare(hub->clk_heads[i]); 771 772 clk_disable_unprepare(hub->clk_hub); 773 clk_disable_unprepare(hub->clk_dsc); 774 clk_disable_unprepare(hub->clk_disp); 775 776 pm_runtime_put_sync(dev); 777 778 return 0; 779 } 780 781 static int tegra_display_hub_runtime_resume(struct host1x_client *client) 782 { 783 struct tegra_display_hub *hub = to_tegra_display_hub(client); 784 struct device *dev = client->dev; 785 unsigned int i; 786 int err; 787 788 err = pm_runtime_get_sync(dev); 789 if (err < 0) { 790 dev_err(dev, "failed to get runtime PM: %d\n", err); 791 return err; 792 } 793 794 err = clk_prepare_enable(hub->clk_disp); 795 if (err < 0) 796 goto put_rpm; 797 798 err = clk_prepare_enable(hub->clk_dsc); 799 if (err < 0) 800 goto disable_disp; 801 802 err = clk_prepare_enable(hub->clk_hub); 803 if (err < 0) 804 goto disable_dsc; 805 806 for (i = 0; i < hub->num_heads; i++) { 807 err = clk_prepare_enable(hub->clk_heads[i]); 808 if (err < 0) 809 goto disable_heads; 810 } 811 812 err = reset_control_deassert(hub->rst); 813 if (err < 0) 814 goto disable_heads; 815 816 return 0; 817 818 disable_heads: 819 while (i--) 820 clk_disable_unprepare(hub->clk_heads[i]); 821 822 clk_disable_unprepare(hub->clk_hub); 823 disable_dsc: 824 clk_disable_unprepare(hub->clk_dsc); 825 disable_disp: 826 clk_disable_unprepare(hub->clk_disp); 827 put_rpm: 828 pm_runtime_put_sync(dev); 829 return err; 830 } 831 832 static const struct host1x_client_ops tegra_display_hub_ops = { 833 .init = tegra_display_hub_init, 834 .exit = tegra_display_hub_exit, 835 .suspend = tegra_display_hub_runtime_suspend, 836 .resume = tegra_display_hub_runtime_resume, 837 }; 838 839 static int tegra_display_hub_probe(struct platform_device *pdev) 840 { 841 struct device_node *child = NULL; 842 struct tegra_display_hub *hub; 843 struct clk *clk; 844 unsigned int i; 845 int err; 846 847 hub = devm_kzalloc(&pdev->dev, sizeof(*hub), GFP_KERNEL); 848 if (!hub) 849 return -ENOMEM; 850 851 hub->soc = of_device_get_match_data(&pdev->dev); 852 853 hub->clk_disp = devm_clk_get(&pdev->dev, "disp"); 854 if (IS_ERR(hub->clk_disp)) { 855 err = PTR_ERR(hub->clk_disp); 856 return err; 857 } 858 859 if (hub->soc->supports_dsc) { 860 hub->clk_dsc = devm_clk_get(&pdev->dev, "dsc"); 861 if (IS_ERR(hub->clk_dsc)) { 862 err = PTR_ERR(hub->clk_dsc); 863 return err; 864 } 865 } 866 867 hub->clk_hub = devm_clk_get(&pdev->dev, "hub"); 868 if (IS_ERR(hub->clk_hub)) { 869 err = PTR_ERR(hub->clk_hub); 870 return err; 871 } 872 873 hub->rst = devm_reset_control_get(&pdev->dev, "misc"); 874 if (IS_ERR(hub->rst)) { 875 err = PTR_ERR(hub->rst); 876 return err; 877 } 878 879 hub->wgrps = devm_kcalloc(&pdev->dev, hub->soc->num_wgrps, 880 sizeof(*hub->wgrps), GFP_KERNEL); 881 if (!hub->wgrps) 882 return -ENOMEM; 883 884 for (i = 0; i < hub->soc->num_wgrps; i++) { 885 struct tegra_windowgroup *wgrp = &hub->wgrps[i]; 886 char id[8]; 887 888 snprintf(id, sizeof(id), "wgrp%u", i); 889 mutex_init(&wgrp->lock); 890 wgrp->usecount = 0; 891 wgrp->index = i; 892 893 wgrp->rst = devm_reset_control_get(&pdev->dev, id); 894 if (IS_ERR(wgrp->rst)) 895 return PTR_ERR(wgrp->rst); 896 897 err = reset_control_assert(wgrp->rst); 898 if (err < 0) 899 return err; 900 } 901 902 hub->num_heads = of_get_child_count(pdev->dev.of_node); 903 904 hub->clk_heads = devm_kcalloc(&pdev->dev, hub->num_heads, sizeof(clk), 905 GFP_KERNEL); 906 if (!hub->clk_heads) 907 return -ENOMEM; 908 909 for (i = 0; i < hub->num_heads; i++) { 910 child = of_get_next_child(pdev->dev.of_node, child); 911 if (!child) { 912 dev_err(&pdev->dev, "failed to find node for head %u\n", 913 i); 914 return -ENODEV; 915 } 916 917 clk = devm_get_clk_from_child(&pdev->dev, child, "dc"); 918 if (IS_ERR(clk)) { 919 dev_err(&pdev->dev, "failed to get clock for head %u\n", 920 i); 921 of_node_put(child); 922 return PTR_ERR(clk); 923 } 924 925 hub->clk_heads[i] = clk; 926 } 927 928 of_node_put(child); 929 930 /* XXX: enable clock across reset? */ 931 err = reset_control_assert(hub->rst); 932 if (err < 0) 933 return err; 934 935 platform_set_drvdata(pdev, hub); 936 pm_runtime_enable(&pdev->dev); 937 938 INIT_LIST_HEAD(&hub->client.list); 939 hub->client.ops = &tegra_display_hub_ops; 940 hub->client.dev = &pdev->dev; 941 942 err = host1x_client_register(&hub->client); 943 if (err < 0) 944 dev_err(&pdev->dev, "failed to register host1x client: %d\n", 945 err); 946 947 return err; 948 } 949 950 static int tegra_display_hub_remove(struct platform_device *pdev) 951 { 952 struct tegra_display_hub *hub = platform_get_drvdata(pdev); 953 unsigned int i; 954 int err; 955 956 err = host1x_client_unregister(&hub->client); 957 if (err < 0) { 958 dev_err(&pdev->dev, "failed to unregister host1x client: %d\n", 959 err); 960 } 961 962 for (i = 0; i < hub->soc->num_wgrps; i++) { 963 struct tegra_windowgroup *wgrp = &hub->wgrps[i]; 964 965 mutex_destroy(&wgrp->lock); 966 } 967 968 pm_runtime_disable(&pdev->dev); 969 970 return err; 971 } 972 973 static const struct tegra_display_hub_soc tegra186_display_hub = { 974 .num_wgrps = 6, 975 .supports_dsc = true, 976 }; 977 978 static const struct tegra_display_hub_soc tegra194_display_hub = { 979 .num_wgrps = 6, 980 .supports_dsc = false, 981 }; 982 983 static const struct of_device_id tegra_display_hub_of_match[] = { 984 { 985 .compatible = "nvidia,tegra194-display", 986 .data = &tegra194_display_hub 987 }, { 988 .compatible = "nvidia,tegra186-display", 989 .data = &tegra186_display_hub 990 }, { 991 /* sentinel */ 992 } 993 }; 994 MODULE_DEVICE_TABLE(of, tegra_display_hub_of_match); 995 996 struct platform_driver tegra_display_hub_driver = { 997 .driver = { 998 .name = "tegra-display-hub", 999 .of_match_table = tegra_display_hub_of_match, 1000 }, 1001 .probe = tegra_display_hub_probe, 1002 .remove = tegra_display_hub_remove, 1003 }; 1004