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