1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (C) 2017 NVIDIA CORPORATION. All rights reserved. 4 */ 5 6 #include <linux/iommu.h> 7 8 #include <drm/drm_atomic.h> 9 #include <drm/drm_atomic_helper.h> 10 #include <drm/drm_fourcc.h> 11 #include <drm/drm_gem_framebuffer_helper.h> 12 #include <drm/drm_plane_helper.h> 13 14 #include "dc.h" 15 #include "plane.h" 16 17 static void tegra_plane_destroy(struct drm_plane *plane) 18 { 19 struct tegra_plane *p = to_tegra_plane(plane); 20 21 drm_plane_cleanup(plane); 22 kfree(p); 23 } 24 25 static void tegra_plane_reset(struct drm_plane *plane) 26 { 27 struct tegra_plane *p = to_tegra_plane(plane); 28 struct tegra_plane_state *state; 29 unsigned int i; 30 31 if (plane->state) 32 __drm_atomic_helper_plane_destroy_state(plane->state); 33 34 kfree(plane->state); 35 plane->state = NULL; 36 37 state = kzalloc(sizeof(*state), GFP_KERNEL); 38 if (state) { 39 plane->state = &state->base; 40 plane->state->plane = plane; 41 plane->state->zpos = p->index; 42 plane->state->normalized_zpos = p->index; 43 44 for (i = 0; i < 3; i++) 45 state->iova[i] = DMA_MAPPING_ERROR; 46 } 47 } 48 49 static struct drm_plane_state * 50 tegra_plane_atomic_duplicate_state(struct drm_plane *plane) 51 { 52 struct tegra_plane_state *state = to_tegra_plane_state(plane->state); 53 struct tegra_plane_state *copy; 54 unsigned int i; 55 56 copy = kmalloc(sizeof(*copy), GFP_KERNEL); 57 if (!copy) 58 return NULL; 59 60 __drm_atomic_helper_plane_duplicate_state(plane, ©->base); 61 copy->tiling = state->tiling; 62 copy->format = state->format; 63 copy->swap = state->swap; 64 copy->reflect_x = state->reflect_x; 65 copy->reflect_y = state->reflect_y; 66 copy->opaque = state->opaque; 67 68 for (i = 0; i < 2; i++) 69 copy->blending[i] = state->blending[i]; 70 71 for (i = 0; i < 3; i++) { 72 copy->iova[i] = DMA_MAPPING_ERROR; 73 copy->sgt[i] = NULL; 74 } 75 76 return ©->base; 77 } 78 79 static void tegra_plane_atomic_destroy_state(struct drm_plane *plane, 80 struct drm_plane_state *state) 81 { 82 __drm_atomic_helper_plane_destroy_state(state); 83 kfree(state); 84 } 85 86 static bool tegra_plane_format_mod_supported(struct drm_plane *plane, 87 uint32_t format, 88 uint64_t modifier) 89 { 90 const struct drm_format_info *info = drm_format_info(format); 91 92 if (modifier == DRM_FORMAT_MOD_LINEAR) 93 return true; 94 95 if (info->num_planes == 1) 96 return true; 97 98 return false; 99 } 100 101 const struct drm_plane_funcs tegra_plane_funcs = { 102 .update_plane = drm_atomic_helper_update_plane, 103 .disable_plane = drm_atomic_helper_disable_plane, 104 .destroy = tegra_plane_destroy, 105 .reset = tegra_plane_reset, 106 .atomic_duplicate_state = tegra_plane_atomic_duplicate_state, 107 .atomic_destroy_state = tegra_plane_atomic_destroy_state, 108 .format_mod_supported = tegra_plane_format_mod_supported, 109 }; 110 111 static int tegra_dc_pin(struct tegra_dc *dc, struct tegra_plane_state *state) 112 { 113 struct iommu_domain *domain = iommu_get_domain_for_dev(dc->dev); 114 unsigned int i; 115 int err; 116 117 for (i = 0; i < state->base.fb->format->num_planes; i++) { 118 struct tegra_bo *bo = tegra_fb_get_plane(state->base.fb, i); 119 dma_addr_t phys_addr, *phys; 120 struct sg_table *sgt; 121 122 if (!domain || dc->client.group) 123 phys = &phys_addr; 124 else 125 phys = NULL; 126 127 sgt = host1x_bo_pin(dc->dev, &bo->base, phys); 128 if (IS_ERR(sgt)) { 129 err = PTR_ERR(sgt); 130 goto unpin; 131 } 132 133 if (sgt) { 134 err = dma_map_sgtable(dc->dev, sgt, DMA_TO_DEVICE, 0); 135 if (err) 136 goto unpin; 137 138 /* 139 * The display controller needs contiguous memory, so 140 * fail if the buffer is discontiguous and we fail to 141 * map its SG table to a single contiguous chunk of 142 * I/O virtual memory. 143 */ 144 if (sgt->nents > 1) { 145 err = -EINVAL; 146 goto unpin; 147 } 148 149 state->iova[i] = sg_dma_address(sgt->sgl); 150 state->sgt[i] = sgt; 151 } else { 152 state->iova[i] = phys_addr; 153 } 154 } 155 156 return 0; 157 158 unpin: 159 dev_err(dc->dev, "failed to map plane %u: %d\n", i, err); 160 161 while (i--) { 162 struct tegra_bo *bo = tegra_fb_get_plane(state->base.fb, i); 163 struct sg_table *sgt = state->sgt[i]; 164 165 if (sgt) 166 dma_unmap_sgtable(dc->dev, sgt, DMA_TO_DEVICE, 0); 167 168 host1x_bo_unpin(dc->dev, &bo->base, sgt); 169 state->iova[i] = DMA_MAPPING_ERROR; 170 state->sgt[i] = NULL; 171 } 172 173 return err; 174 } 175 176 static void tegra_dc_unpin(struct tegra_dc *dc, struct tegra_plane_state *state) 177 { 178 unsigned int i; 179 180 for (i = 0; i < state->base.fb->format->num_planes; i++) { 181 struct tegra_bo *bo = tegra_fb_get_plane(state->base.fb, i); 182 struct sg_table *sgt = state->sgt[i]; 183 184 if (sgt) 185 dma_unmap_sgtable(dc->dev, sgt, DMA_TO_DEVICE, 0); 186 187 host1x_bo_unpin(dc->dev, &bo->base, sgt); 188 state->iova[i] = DMA_MAPPING_ERROR; 189 state->sgt[i] = NULL; 190 } 191 } 192 193 int tegra_plane_prepare_fb(struct drm_plane *plane, 194 struct drm_plane_state *state) 195 { 196 struct tegra_dc *dc = to_tegra_dc(state->crtc); 197 198 if (!state->fb) 199 return 0; 200 201 drm_gem_fb_prepare_fb(plane, state); 202 203 return tegra_dc_pin(dc, to_tegra_plane_state(state)); 204 } 205 206 void tegra_plane_cleanup_fb(struct drm_plane *plane, 207 struct drm_plane_state *state) 208 { 209 struct tegra_dc *dc = to_tegra_dc(state->crtc); 210 211 if (dc) 212 tegra_dc_unpin(dc, to_tegra_plane_state(state)); 213 } 214 215 int tegra_plane_state_add(struct tegra_plane *plane, 216 struct drm_plane_state *state) 217 { 218 struct drm_crtc_state *crtc_state; 219 struct tegra_dc_state *tegra; 220 int err; 221 222 /* Propagate errors from allocation or locking failures. */ 223 crtc_state = drm_atomic_get_crtc_state(state->state, state->crtc); 224 if (IS_ERR(crtc_state)) 225 return PTR_ERR(crtc_state); 226 227 /* Check plane state for visibility and calculate clipping bounds */ 228 err = drm_atomic_helper_check_plane_state(state, crtc_state, 229 0, INT_MAX, true, true); 230 if (err < 0) 231 return err; 232 233 tegra = to_dc_state(crtc_state); 234 235 tegra->planes |= WIN_A_ACT_REQ << plane->index; 236 237 return 0; 238 } 239 240 int tegra_plane_format(u32 fourcc, u32 *format, u32 *swap) 241 { 242 /* assume no swapping of fetched data */ 243 if (swap) 244 *swap = BYTE_SWAP_NOSWAP; 245 246 switch (fourcc) { 247 case DRM_FORMAT_ARGB4444: 248 *format = WIN_COLOR_DEPTH_B4G4R4A4; 249 break; 250 251 case DRM_FORMAT_ARGB1555: 252 *format = WIN_COLOR_DEPTH_B5G5R5A1; 253 break; 254 255 case DRM_FORMAT_RGB565: 256 *format = WIN_COLOR_DEPTH_B5G6R5; 257 break; 258 259 case DRM_FORMAT_RGBA5551: 260 *format = WIN_COLOR_DEPTH_A1B5G5R5; 261 break; 262 263 case DRM_FORMAT_ARGB8888: 264 *format = WIN_COLOR_DEPTH_B8G8R8A8; 265 break; 266 267 case DRM_FORMAT_ABGR8888: 268 *format = WIN_COLOR_DEPTH_R8G8B8A8; 269 break; 270 271 case DRM_FORMAT_ABGR4444: 272 *format = WIN_COLOR_DEPTH_R4G4B4A4; 273 break; 274 275 case DRM_FORMAT_ABGR1555: 276 *format = WIN_COLOR_DEPTH_R5G5B5A; 277 break; 278 279 case DRM_FORMAT_BGRA5551: 280 *format = WIN_COLOR_DEPTH_AR5G5B5; 281 break; 282 283 case DRM_FORMAT_XRGB1555: 284 *format = WIN_COLOR_DEPTH_B5G5R5X1; 285 break; 286 287 case DRM_FORMAT_RGBX5551: 288 *format = WIN_COLOR_DEPTH_X1B5G5R5; 289 break; 290 291 case DRM_FORMAT_XBGR1555: 292 *format = WIN_COLOR_DEPTH_R5G5B5X1; 293 break; 294 295 case DRM_FORMAT_BGRX5551: 296 *format = WIN_COLOR_DEPTH_X1R5G5B5; 297 break; 298 299 case DRM_FORMAT_BGR565: 300 *format = WIN_COLOR_DEPTH_R5G6B5; 301 break; 302 303 case DRM_FORMAT_BGRA8888: 304 *format = WIN_COLOR_DEPTH_A8R8G8B8; 305 break; 306 307 case DRM_FORMAT_RGBA8888: 308 *format = WIN_COLOR_DEPTH_A8B8G8R8; 309 break; 310 311 case DRM_FORMAT_XRGB8888: 312 *format = WIN_COLOR_DEPTH_B8G8R8X8; 313 break; 314 315 case DRM_FORMAT_XBGR8888: 316 *format = WIN_COLOR_DEPTH_R8G8B8X8; 317 break; 318 319 case DRM_FORMAT_UYVY: 320 *format = WIN_COLOR_DEPTH_YCbCr422; 321 break; 322 323 case DRM_FORMAT_YUYV: 324 if (!swap) 325 return -EINVAL; 326 327 *format = WIN_COLOR_DEPTH_YCbCr422; 328 *swap = BYTE_SWAP_SWAP2; 329 break; 330 331 case DRM_FORMAT_YUV420: 332 *format = WIN_COLOR_DEPTH_YCbCr420P; 333 break; 334 335 case DRM_FORMAT_YUV422: 336 *format = WIN_COLOR_DEPTH_YCbCr422P; 337 break; 338 339 default: 340 return -EINVAL; 341 } 342 343 return 0; 344 } 345 346 bool tegra_plane_format_is_yuv(unsigned int format, bool *planar) 347 { 348 switch (format) { 349 case WIN_COLOR_DEPTH_YCbCr422: 350 case WIN_COLOR_DEPTH_YUV422: 351 if (planar) 352 *planar = false; 353 354 return true; 355 356 case WIN_COLOR_DEPTH_YCbCr420P: 357 case WIN_COLOR_DEPTH_YUV420P: 358 case WIN_COLOR_DEPTH_YCbCr422P: 359 case WIN_COLOR_DEPTH_YUV422P: 360 case WIN_COLOR_DEPTH_YCbCr422R: 361 case WIN_COLOR_DEPTH_YUV422R: 362 case WIN_COLOR_DEPTH_YCbCr422RA: 363 case WIN_COLOR_DEPTH_YUV422RA: 364 if (planar) 365 *planar = true; 366 367 return true; 368 } 369 370 if (planar) 371 *planar = false; 372 373 return false; 374 } 375 376 static bool __drm_format_has_alpha(u32 format) 377 { 378 switch (format) { 379 case DRM_FORMAT_ARGB1555: 380 case DRM_FORMAT_RGBA5551: 381 case DRM_FORMAT_ABGR8888: 382 case DRM_FORMAT_ARGB8888: 383 return true; 384 } 385 386 return false; 387 } 388 389 static int tegra_plane_format_get_alpha(unsigned int opaque, 390 unsigned int *alpha) 391 { 392 if (tegra_plane_format_is_yuv(opaque, NULL)) { 393 *alpha = opaque; 394 return 0; 395 } 396 397 switch (opaque) { 398 case WIN_COLOR_DEPTH_B5G5R5X1: 399 *alpha = WIN_COLOR_DEPTH_B5G5R5A1; 400 return 0; 401 402 case WIN_COLOR_DEPTH_X1B5G5R5: 403 *alpha = WIN_COLOR_DEPTH_A1B5G5R5; 404 return 0; 405 406 case WIN_COLOR_DEPTH_R8G8B8X8: 407 *alpha = WIN_COLOR_DEPTH_R8G8B8A8; 408 return 0; 409 410 case WIN_COLOR_DEPTH_B8G8R8X8: 411 *alpha = WIN_COLOR_DEPTH_B8G8R8A8; 412 return 0; 413 414 case WIN_COLOR_DEPTH_B5G6R5: 415 *alpha = opaque; 416 return 0; 417 } 418 419 return -EINVAL; 420 } 421 422 /* 423 * This is applicable to Tegra20 and Tegra30 only where the opaque formats can 424 * be emulated using the alpha formats and alpha blending disabled. 425 */ 426 static int tegra_plane_setup_opacity(struct tegra_plane *tegra, 427 struct tegra_plane_state *state) 428 { 429 unsigned int format; 430 int err; 431 432 switch (state->format) { 433 case WIN_COLOR_DEPTH_B5G5R5A1: 434 case WIN_COLOR_DEPTH_A1B5G5R5: 435 case WIN_COLOR_DEPTH_R8G8B8A8: 436 case WIN_COLOR_DEPTH_B8G8R8A8: 437 state->opaque = false; 438 break; 439 440 default: 441 err = tegra_plane_format_get_alpha(state->format, &format); 442 if (err < 0) 443 return err; 444 445 state->format = format; 446 state->opaque = true; 447 break; 448 } 449 450 return 0; 451 } 452 453 static int tegra_plane_check_transparency(struct tegra_plane *tegra, 454 struct tegra_plane_state *state) 455 { 456 struct drm_plane_state *old, *plane_state; 457 struct drm_plane *plane; 458 459 old = drm_atomic_get_old_plane_state(state->base.state, &tegra->base); 460 461 /* check if zpos / transparency changed */ 462 if (old->normalized_zpos == state->base.normalized_zpos && 463 to_tegra_plane_state(old)->opaque == state->opaque) 464 return 0; 465 466 /* include all sibling planes into this commit */ 467 drm_for_each_plane(plane, tegra->base.dev) { 468 struct tegra_plane *p = to_tegra_plane(plane); 469 470 /* skip this plane and planes on different CRTCs */ 471 if (p == tegra || p->dc != tegra->dc) 472 continue; 473 474 plane_state = drm_atomic_get_plane_state(state->base.state, 475 plane); 476 if (IS_ERR(plane_state)) 477 return PTR_ERR(plane_state); 478 } 479 480 return 1; 481 } 482 483 static unsigned int tegra_plane_get_overlap_index(struct tegra_plane *plane, 484 struct tegra_plane *other) 485 { 486 unsigned int index = 0, i; 487 488 WARN_ON(plane == other); 489 490 for (i = 0; i < 3; i++) { 491 if (i == plane->index) 492 continue; 493 494 if (i == other->index) 495 break; 496 497 index++; 498 } 499 500 return index; 501 } 502 503 static void tegra_plane_update_transparency(struct tegra_plane *tegra, 504 struct tegra_plane_state *state) 505 { 506 struct drm_plane_state *new; 507 struct drm_plane *plane; 508 unsigned int i; 509 510 for_each_new_plane_in_state(state->base.state, plane, new, i) { 511 struct tegra_plane *p = to_tegra_plane(plane); 512 unsigned index; 513 514 /* skip this plane and planes on different CRTCs */ 515 if (p == tegra || p->dc != tegra->dc) 516 continue; 517 518 index = tegra_plane_get_overlap_index(tegra, p); 519 520 if (new->fb && __drm_format_has_alpha(new->fb->format->format)) 521 state->blending[index].alpha = true; 522 else 523 state->blending[index].alpha = false; 524 525 if (new->normalized_zpos > state->base.normalized_zpos) 526 state->blending[index].top = true; 527 else 528 state->blending[index].top = false; 529 530 /* 531 * Missing framebuffer means that plane is disabled, in this 532 * case mark B / C window as top to be able to differentiate 533 * windows indices order in regards to zPos for the middle 534 * window X / Y registers programming. 535 */ 536 if (!new->fb) 537 state->blending[index].top = (index == 1); 538 } 539 } 540 541 static int tegra_plane_setup_transparency(struct tegra_plane *tegra, 542 struct tegra_plane_state *state) 543 { 544 struct tegra_plane_state *tegra_state; 545 struct drm_plane_state *new; 546 struct drm_plane *plane; 547 int err; 548 549 /* 550 * If planes zpos / transparency changed, sibling planes blending 551 * state may require adjustment and in this case they will be included 552 * into this atom commit, otherwise blending state is unchanged. 553 */ 554 err = tegra_plane_check_transparency(tegra, state); 555 if (err <= 0) 556 return err; 557 558 /* 559 * All planes are now in the atomic state, walk them up and update 560 * transparency state for each plane. 561 */ 562 drm_for_each_plane(plane, tegra->base.dev) { 563 struct tegra_plane *p = to_tegra_plane(plane); 564 565 /* skip planes on different CRTCs */ 566 if (p->dc != tegra->dc) 567 continue; 568 569 new = drm_atomic_get_new_plane_state(state->base.state, plane); 570 tegra_state = to_tegra_plane_state(new); 571 572 /* 573 * There is no need to update blending state for the disabled 574 * plane. 575 */ 576 if (new->fb) 577 tegra_plane_update_transparency(p, tegra_state); 578 } 579 580 return 0; 581 } 582 583 int tegra_plane_setup_legacy_state(struct tegra_plane *tegra, 584 struct tegra_plane_state *state) 585 { 586 int err; 587 588 err = tegra_plane_setup_opacity(tegra, state); 589 if (err < 0) 590 return err; 591 592 err = tegra_plane_setup_transparency(tegra, state); 593 if (err < 0) 594 return err; 595 596 return 0; 597 } 598