Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v5.17-rc4 951 lines 27 kB view raw
1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * i.MX IPUv3 DP Overlay Planes 4 * 5 * Copyright (C) 2013 Philipp Zabel, Pengutronix 6 */ 7 8#include <drm/drm_atomic.h> 9#include <drm/drm_atomic_helper.h> 10#include <drm/drm_fb_cma_helper.h> 11#include <drm/drm_fourcc.h> 12#include <drm/drm_gem_atomic_helper.h> 13#include <drm/drm_gem_cma_helper.h> 14#include <drm/drm_managed.h> 15#include <drm/drm_plane_helper.h> 16 17#include <video/imx-ipu-v3.h> 18 19#include "imx-drm.h" 20#include "ipuv3-plane.h" 21 22struct ipu_plane_state { 23 struct drm_plane_state base; 24 bool use_pre; 25}; 26 27static inline struct ipu_plane_state * 28to_ipu_plane_state(struct drm_plane_state *p) 29{ 30 return container_of(p, struct ipu_plane_state, base); 31} 32 33static unsigned int ipu_src_rect_width(const struct drm_plane_state *state) 34{ 35 return ALIGN(drm_rect_width(&state->src) >> 16, 8); 36} 37 38static inline struct ipu_plane *to_ipu_plane(struct drm_plane *p) 39{ 40 return container_of(p, struct ipu_plane, base); 41} 42 43static const uint32_t ipu_plane_all_formats[] = { 44 DRM_FORMAT_ARGB1555, 45 DRM_FORMAT_XRGB1555, 46 DRM_FORMAT_ABGR1555, 47 DRM_FORMAT_XBGR1555, 48 DRM_FORMAT_RGBA5551, 49 DRM_FORMAT_BGRA5551, 50 DRM_FORMAT_ARGB4444, 51 DRM_FORMAT_ARGB8888, 52 DRM_FORMAT_XRGB8888, 53 DRM_FORMAT_ABGR8888, 54 DRM_FORMAT_XBGR8888, 55 DRM_FORMAT_RGBA8888, 56 DRM_FORMAT_RGBX8888, 57 DRM_FORMAT_BGRA8888, 58 DRM_FORMAT_BGRX8888, 59 DRM_FORMAT_UYVY, 60 DRM_FORMAT_VYUY, 61 DRM_FORMAT_YUYV, 62 DRM_FORMAT_YVYU, 63 DRM_FORMAT_YUV420, 64 DRM_FORMAT_YVU420, 65 DRM_FORMAT_YUV422, 66 DRM_FORMAT_YVU422, 67 DRM_FORMAT_YUV444, 68 DRM_FORMAT_YVU444, 69 DRM_FORMAT_NV12, 70 DRM_FORMAT_NV16, 71 DRM_FORMAT_RGB565, 72 DRM_FORMAT_RGB565_A8, 73 DRM_FORMAT_BGR565_A8, 74 DRM_FORMAT_RGB888_A8, 75 DRM_FORMAT_BGR888_A8, 76 DRM_FORMAT_RGBX8888_A8, 77 DRM_FORMAT_BGRX8888_A8, 78}; 79 80static const uint32_t ipu_plane_rgb_formats[] = { 81 DRM_FORMAT_ARGB1555, 82 DRM_FORMAT_XRGB1555, 83 DRM_FORMAT_ABGR1555, 84 DRM_FORMAT_XBGR1555, 85 DRM_FORMAT_RGBA5551, 86 DRM_FORMAT_BGRA5551, 87 DRM_FORMAT_ARGB4444, 88 DRM_FORMAT_ARGB8888, 89 DRM_FORMAT_XRGB8888, 90 DRM_FORMAT_ABGR8888, 91 DRM_FORMAT_XBGR8888, 92 DRM_FORMAT_RGBA8888, 93 DRM_FORMAT_RGBX8888, 94 DRM_FORMAT_BGRA8888, 95 DRM_FORMAT_BGRX8888, 96 DRM_FORMAT_RGB565, 97 DRM_FORMAT_RGB565_A8, 98 DRM_FORMAT_BGR565_A8, 99 DRM_FORMAT_RGB888_A8, 100 DRM_FORMAT_BGR888_A8, 101 DRM_FORMAT_RGBX8888_A8, 102 DRM_FORMAT_BGRX8888_A8, 103}; 104 105static const uint64_t ipu_format_modifiers[] = { 106 DRM_FORMAT_MOD_LINEAR, 107 DRM_FORMAT_MOD_INVALID 108}; 109 110static const uint64_t pre_format_modifiers[] = { 111 DRM_FORMAT_MOD_LINEAR, 112 DRM_FORMAT_MOD_VIVANTE_TILED, 113 DRM_FORMAT_MOD_VIVANTE_SUPER_TILED, 114 DRM_FORMAT_MOD_INVALID 115}; 116 117int ipu_plane_irq(struct ipu_plane *ipu_plane) 118{ 119 return ipu_idmac_channel_irq(ipu_plane->ipu, ipu_plane->ipu_ch, 120 IPU_IRQ_EOF); 121} 122 123static inline unsigned long 124drm_plane_state_to_eba(struct drm_plane_state *state, int plane) 125{ 126 struct drm_framebuffer *fb = state->fb; 127 struct drm_gem_cma_object *cma_obj; 128 int x = state->src.x1 >> 16; 129 int y = state->src.y1 >> 16; 130 131 cma_obj = drm_fb_cma_get_gem_obj(fb, plane); 132 BUG_ON(!cma_obj); 133 134 return cma_obj->paddr + fb->offsets[plane] + fb->pitches[plane] * y + 135 fb->format->cpp[plane] * x; 136} 137 138static inline unsigned long 139drm_plane_state_to_ubo(struct drm_plane_state *state) 140{ 141 struct drm_framebuffer *fb = state->fb; 142 struct drm_gem_cma_object *cma_obj; 143 unsigned long eba = drm_plane_state_to_eba(state, 0); 144 int x = state->src.x1 >> 16; 145 int y = state->src.y1 >> 16; 146 147 cma_obj = drm_fb_cma_get_gem_obj(fb, 1); 148 BUG_ON(!cma_obj); 149 150 x /= fb->format->hsub; 151 y /= fb->format->vsub; 152 153 return cma_obj->paddr + fb->offsets[1] + fb->pitches[1] * y + 154 fb->format->cpp[1] * x - eba; 155} 156 157static inline unsigned long 158drm_plane_state_to_vbo(struct drm_plane_state *state) 159{ 160 struct drm_framebuffer *fb = state->fb; 161 struct drm_gem_cma_object *cma_obj; 162 unsigned long eba = drm_plane_state_to_eba(state, 0); 163 int x = state->src.x1 >> 16; 164 int y = state->src.y1 >> 16; 165 166 cma_obj = drm_fb_cma_get_gem_obj(fb, 2); 167 BUG_ON(!cma_obj); 168 169 x /= fb->format->hsub; 170 y /= fb->format->vsub; 171 172 return cma_obj->paddr + fb->offsets[2] + fb->pitches[2] * y + 173 fb->format->cpp[2] * x - eba; 174} 175 176static void ipu_plane_put_resources(struct drm_device *dev, void *ptr) 177{ 178 struct ipu_plane *ipu_plane = ptr; 179 180 if (!IS_ERR_OR_NULL(ipu_plane->dp)) 181 ipu_dp_put(ipu_plane->dp); 182 if (!IS_ERR_OR_NULL(ipu_plane->dmfc)) 183 ipu_dmfc_put(ipu_plane->dmfc); 184 if (!IS_ERR_OR_NULL(ipu_plane->ipu_ch)) 185 ipu_idmac_put(ipu_plane->ipu_ch); 186 if (!IS_ERR_OR_NULL(ipu_plane->alpha_ch)) 187 ipu_idmac_put(ipu_plane->alpha_ch); 188} 189 190static int ipu_plane_get_resources(struct drm_device *dev, 191 struct ipu_plane *ipu_plane) 192{ 193 int ret; 194 int alpha_ch; 195 196 ipu_plane->ipu_ch = ipu_idmac_get(ipu_plane->ipu, ipu_plane->dma); 197 if (IS_ERR(ipu_plane->ipu_ch)) { 198 ret = PTR_ERR(ipu_plane->ipu_ch); 199 DRM_ERROR("failed to get idmac channel: %d\n", ret); 200 return ret; 201 } 202 203 ret = drmm_add_action_or_reset(dev, ipu_plane_put_resources, ipu_plane); 204 if (ret) 205 return ret; 206 207 alpha_ch = ipu_channel_alpha_channel(ipu_plane->dma); 208 if (alpha_ch >= 0) { 209 ipu_plane->alpha_ch = ipu_idmac_get(ipu_plane->ipu, alpha_ch); 210 if (IS_ERR(ipu_plane->alpha_ch)) { 211 ret = PTR_ERR(ipu_plane->alpha_ch); 212 DRM_ERROR("failed to get alpha idmac channel %d: %d\n", 213 alpha_ch, ret); 214 return ret; 215 } 216 } 217 218 ipu_plane->dmfc = ipu_dmfc_get(ipu_plane->ipu, ipu_plane->dma); 219 if (IS_ERR(ipu_plane->dmfc)) { 220 ret = PTR_ERR(ipu_plane->dmfc); 221 DRM_ERROR("failed to get dmfc: ret %d\n", ret); 222 return ret; 223 } 224 225 if (ipu_plane->dp_flow >= 0) { 226 ipu_plane->dp = ipu_dp_get(ipu_plane->ipu, ipu_plane->dp_flow); 227 if (IS_ERR(ipu_plane->dp)) { 228 ret = PTR_ERR(ipu_plane->dp); 229 DRM_ERROR("failed to get dp flow: %d\n", ret); 230 return ret; 231 } 232 } 233 234 return 0; 235} 236 237static bool ipu_plane_separate_alpha(struct ipu_plane *ipu_plane) 238{ 239 switch (ipu_plane->base.state->fb->format->format) { 240 case DRM_FORMAT_RGB565_A8: 241 case DRM_FORMAT_BGR565_A8: 242 case DRM_FORMAT_RGB888_A8: 243 case DRM_FORMAT_BGR888_A8: 244 case DRM_FORMAT_RGBX8888_A8: 245 case DRM_FORMAT_BGRX8888_A8: 246 return true; 247 default: 248 return false; 249 } 250} 251 252static void ipu_plane_enable(struct ipu_plane *ipu_plane) 253{ 254 if (ipu_plane->dp) 255 ipu_dp_enable(ipu_plane->ipu); 256 ipu_dmfc_enable_channel(ipu_plane->dmfc); 257 ipu_idmac_enable_channel(ipu_plane->ipu_ch); 258 if (ipu_plane_separate_alpha(ipu_plane)) 259 ipu_idmac_enable_channel(ipu_plane->alpha_ch); 260 if (ipu_plane->dp) 261 ipu_dp_enable_channel(ipu_plane->dp); 262} 263 264void ipu_plane_disable(struct ipu_plane *ipu_plane, bool disable_dp_channel) 265{ 266 int ret; 267 268 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); 269 270 ret = ipu_idmac_wait_busy(ipu_plane->ipu_ch, 50); 271 if (ret == -ETIMEDOUT) { 272 DRM_ERROR("[PLANE:%d] IDMAC timeout\n", 273 ipu_plane->base.base.id); 274 } 275 276 if (ipu_plane->dp && disable_dp_channel) 277 ipu_dp_disable_channel(ipu_plane->dp, false); 278 ipu_idmac_disable_channel(ipu_plane->ipu_ch); 279 if (ipu_plane->alpha_ch) 280 ipu_idmac_disable_channel(ipu_plane->alpha_ch); 281 ipu_dmfc_disable_channel(ipu_plane->dmfc); 282 if (ipu_plane->dp) 283 ipu_dp_disable(ipu_plane->ipu); 284 if (ipu_prg_present(ipu_plane->ipu)) 285 ipu_prg_channel_disable(ipu_plane->ipu_ch); 286} 287 288void ipu_plane_disable_deferred(struct drm_plane *plane) 289{ 290 struct ipu_plane *ipu_plane = to_ipu_plane(plane); 291 292 if (ipu_plane->disabling) { 293 ipu_plane->disabling = false; 294 ipu_plane_disable(ipu_plane, false); 295 } 296} 297 298static void ipu_plane_state_reset(struct drm_plane *plane) 299{ 300 unsigned int zpos = (plane->type == DRM_PLANE_TYPE_PRIMARY) ? 0 : 1; 301 struct ipu_plane_state *ipu_state; 302 303 if (plane->state) { 304 ipu_state = to_ipu_plane_state(plane->state); 305 __drm_atomic_helper_plane_destroy_state(plane->state); 306 kfree(ipu_state); 307 plane->state = NULL; 308 } 309 310 ipu_state = kzalloc(sizeof(*ipu_state), GFP_KERNEL); 311 312 if (ipu_state) { 313 __drm_atomic_helper_plane_reset(plane, &ipu_state->base); 314 ipu_state->base.zpos = zpos; 315 ipu_state->base.normalized_zpos = zpos; 316 ipu_state->base.color_encoding = DRM_COLOR_YCBCR_BT601; 317 ipu_state->base.color_range = DRM_COLOR_YCBCR_LIMITED_RANGE; 318 } 319} 320 321static struct drm_plane_state * 322ipu_plane_duplicate_state(struct drm_plane *plane) 323{ 324 struct ipu_plane_state *state; 325 326 if (WARN_ON(!plane->state)) 327 return NULL; 328 329 state = kmalloc(sizeof(*state), GFP_KERNEL); 330 if (state) 331 __drm_atomic_helper_plane_duplicate_state(plane, &state->base); 332 333 return &state->base; 334} 335 336static void ipu_plane_destroy_state(struct drm_plane *plane, 337 struct drm_plane_state *state) 338{ 339 struct ipu_plane_state *ipu_state = to_ipu_plane_state(state); 340 341 __drm_atomic_helper_plane_destroy_state(state); 342 kfree(ipu_state); 343} 344 345static bool ipu_plane_format_mod_supported(struct drm_plane *plane, 346 uint32_t format, uint64_t modifier) 347{ 348 struct ipu_soc *ipu = to_ipu_plane(plane)->ipu; 349 350 /* linear is supported for all planes and formats */ 351 if (modifier == DRM_FORMAT_MOD_LINEAR) 352 return true; 353 354 /* 355 * Without a PRG the possible modifiers list only includes the linear 356 * modifier, so we always take the early return from this function and 357 * only end up here if the PRG is present. 358 */ 359 return ipu_prg_format_supported(ipu, format, modifier); 360} 361 362static const struct drm_plane_funcs ipu_plane_funcs = { 363 .update_plane = drm_atomic_helper_update_plane, 364 .disable_plane = drm_atomic_helper_disable_plane, 365 .reset = ipu_plane_state_reset, 366 .atomic_duplicate_state = ipu_plane_duplicate_state, 367 .atomic_destroy_state = ipu_plane_destroy_state, 368 .format_mod_supported = ipu_plane_format_mod_supported, 369}; 370 371static int ipu_plane_atomic_check(struct drm_plane *plane, 372 struct drm_atomic_state *state) 373{ 374 struct drm_plane_state *new_state = drm_atomic_get_new_plane_state(state, 375 plane); 376 struct drm_plane_state *old_state = drm_atomic_get_old_plane_state(state, 377 plane); 378 struct drm_crtc_state *crtc_state; 379 struct device *dev = plane->dev->dev; 380 struct drm_framebuffer *fb = new_state->fb; 381 struct drm_framebuffer *old_fb = old_state->fb; 382 unsigned long eba, ubo, vbo, old_ubo, old_vbo, alpha_eba; 383 bool can_position = (plane->type == DRM_PLANE_TYPE_OVERLAY); 384 int ret; 385 386 /* Ok to disable */ 387 if (!fb) 388 return 0; 389 390 if (WARN_ON(!new_state->crtc)) 391 return -EINVAL; 392 393 crtc_state = 394 drm_atomic_get_existing_crtc_state(state, 395 new_state->crtc); 396 if (WARN_ON(!crtc_state)) 397 return -EINVAL; 398 399 ret = drm_atomic_helper_check_plane_state(new_state, crtc_state, 400 DRM_PLANE_HELPER_NO_SCALING, 401 DRM_PLANE_HELPER_NO_SCALING, 402 can_position, true); 403 if (ret) 404 return ret; 405 406 /* nothing to check when disabling or disabled */ 407 if (!crtc_state->enable) 408 return 0; 409 410 switch (plane->type) { 411 case DRM_PLANE_TYPE_PRIMARY: 412 /* full plane minimum width is 13 pixels */ 413 if (drm_rect_width(&new_state->dst) < 13) 414 return -EINVAL; 415 break; 416 case DRM_PLANE_TYPE_OVERLAY: 417 break; 418 default: 419 dev_warn(dev, "Unsupported plane type %d\n", plane->type); 420 return -EINVAL; 421 } 422 423 if (drm_rect_height(&new_state->dst) < 2) 424 return -EINVAL; 425 426 /* 427 * We support resizing active plane or changing its format by 428 * forcing CRTC mode change in plane's ->atomic_check callback 429 * and disabling all affected active planes in CRTC's ->atomic_disable 430 * callback. The planes will be reenabled in plane's ->atomic_update 431 * callback. 432 */ 433 if (old_fb && 434 (drm_rect_width(&new_state->dst) != drm_rect_width(&old_state->dst) || 435 drm_rect_height(&new_state->dst) != drm_rect_height(&old_state->dst) || 436 fb->format != old_fb->format)) 437 crtc_state->mode_changed = true; 438 439 eba = drm_plane_state_to_eba(new_state, 0); 440 441 if (eba & 0x7) 442 return -EINVAL; 443 444 if (fb->pitches[0] < 1 || fb->pitches[0] > 16384) 445 return -EINVAL; 446 447 if (old_fb && fb->pitches[0] != old_fb->pitches[0]) 448 crtc_state->mode_changed = true; 449 450 if (ALIGN(fb->width, 8) * fb->format->cpp[0] > 451 fb->pitches[0] + fb->offsets[0]) { 452 dev_warn(dev, "pitch is not big enough for 8 pixels alignment"); 453 return -EINVAL; 454 } 455 456 switch (fb->format->format) { 457 case DRM_FORMAT_YUV420: 458 case DRM_FORMAT_YVU420: 459 case DRM_FORMAT_YUV422: 460 case DRM_FORMAT_YVU422: 461 case DRM_FORMAT_YUV444: 462 case DRM_FORMAT_YVU444: 463 /* 464 * Multiplanar formats have to meet the following restrictions: 465 * - The (up to) three plane addresses are EBA, EBA+UBO, EBA+VBO 466 * - EBA, UBO and VBO are a multiple of 8 467 * - UBO and VBO are unsigned and not larger than 0xfffff8 468 * - Only EBA may be changed while scanout is active 469 * - The strides of U and V planes must be identical. 470 */ 471 vbo = drm_plane_state_to_vbo(new_state); 472 473 if (vbo & 0x7 || vbo > 0xfffff8) 474 return -EINVAL; 475 476 if (old_fb && (fb->format == old_fb->format)) { 477 old_vbo = drm_plane_state_to_vbo(old_state); 478 if (vbo != old_vbo) 479 crtc_state->mode_changed = true; 480 } 481 482 if (fb->pitches[1] != fb->pitches[2]) 483 return -EINVAL; 484 485 fallthrough; 486 case DRM_FORMAT_NV12: 487 case DRM_FORMAT_NV16: 488 ubo = drm_plane_state_to_ubo(new_state); 489 490 if (ubo & 0x7 || ubo > 0xfffff8) 491 return -EINVAL; 492 493 if (old_fb && (fb->format == old_fb->format)) { 494 old_ubo = drm_plane_state_to_ubo(old_state); 495 if (ubo != old_ubo) 496 crtc_state->mode_changed = true; 497 } 498 499 if (fb->pitches[1] < 1 || fb->pitches[1] > 16384) 500 return -EINVAL; 501 502 if (old_fb && old_fb->pitches[1] != fb->pitches[1]) 503 crtc_state->mode_changed = true; 504 505 /* 506 * The x/y offsets must be even in case of horizontal/vertical 507 * chroma subsampling. 508 */ 509 if (((new_state->src.x1 >> 16) & (fb->format->hsub - 1)) || 510 ((new_state->src.y1 >> 16) & (fb->format->vsub - 1))) 511 return -EINVAL; 512 break; 513 case DRM_FORMAT_RGB565_A8: 514 case DRM_FORMAT_BGR565_A8: 515 case DRM_FORMAT_RGB888_A8: 516 case DRM_FORMAT_BGR888_A8: 517 case DRM_FORMAT_RGBX8888_A8: 518 case DRM_FORMAT_BGRX8888_A8: 519 alpha_eba = drm_plane_state_to_eba(new_state, 1); 520 if (alpha_eba & 0x7) 521 return -EINVAL; 522 523 if (fb->pitches[1] < 1 || fb->pitches[1] > 16384) 524 return -EINVAL; 525 526 if (old_fb && old_fb->pitches[1] != fb->pitches[1]) 527 crtc_state->mode_changed = true; 528 break; 529 } 530 531 return 0; 532} 533 534static void ipu_plane_atomic_disable(struct drm_plane *plane, 535 struct drm_atomic_state *state) 536{ 537 struct ipu_plane *ipu_plane = to_ipu_plane(plane); 538 539 if (ipu_plane->dp) 540 ipu_dp_disable_channel(ipu_plane->dp, true); 541 ipu_plane->disabling = true; 542} 543 544static int ipu_chan_assign_axi_id(int ipu_chan) 545{ 546 switch (ipu_chan) { 547 case IPUV3_CHANNEL_MEM_BG_SYNC: 548 return 1; 549 case IPUV3_CHANNEL_MEM_FG_SYNC: 550 return 2; 551 case IPUV3_CHANNEL_MEM_DC_SYNC: 552 return 3; 553 default: 554 return 0; 555 } 556} 557 558static void ipu_calculate_bursts(u32 width, u32 cpp, u32 stride, 559 u8 *burstsize, u8 *num_bursts) 560{ 561 const unsigned int width_bytes = width * cpp; 562 unsigned int npb, bursts; 563 564 /* Maximum number of pixels per burst without overshooting stride */ 565 for (npb = 64 / cpp; npb > 0; --npb) { 566 if (round_up(width_bytes, npb * cpp) <= stride) 567 break; 568 } 569 *burstsize = npb; 570 571 /* Maximum number of consecutive bursts without overshooting stride */ 572 for (bursts = 8; bursts > 1; bursts /= 2) { 573 if (round_up(width_bytes, npb * cpp * bursts) <= stride) 574 break; 575 } 576 *num_bursts = bursts; 577} 578 579static void ipu_plane_atomic_update(struct drm_plane *plane, 580 struct drm_atomic_state *state) 581{ 582 struct drm_plane_state *old_state = drm_atomic_get_old_plane_state(state, 583 plane); 584 struct ipu_plane *ipu_plane = to_ipu_plane(plane); 585 struct drm_plane_state *new_state = drm_atomic_get_new_plane_state(state, 586 plane); 587 struct ipu_plane_state *ipu_state = to_ipu_plane_state(new_state); 588 struct drm_crtc_state *crtc_state = new_state->crtc->state; 589 struct drm_framebuffer *fb = new_state->fb; 590 struct drm_rect *dst = &new_state->dst; 591 unsigned long eba, ubo, vbo; 592 unsigned long alpha_eba = 0; 593 enum ipu_color_space ics; 594 unsigned int axi_id = 0; 595 const struct drm_format_info *info; 596 u8 burstsize, num_bursts; 597 u32 width, height; 598 int active; 599 600 if (ipu_plane->dp_flow == IPU_DP_FLOW_SYNC_FG) 601 ipu_dp_set_window_pos(ipu_plane->dp, dst->x1, dst->y1); 602 603 switch (ipu_plane->dp_flow) { 604 case IPU_DP_FLOW_SYNC_BG: 605 if (new_state->normalized_zpos == 1) { 606 ipu_dp_set_global_alpha(ipu_plane->dp, 607 !fb->format->has_alpha, 0xff, 608 true); 609 } else { 610 ipu_dp_set_global_alpha(ipu_plane->dp, true, 0, true); 611 } 612 break; 613 case IPU_DP_FLOW_SYNC_FG: 614 if (new_state->normalized_zpos == 1) { 615 ipu_dp_set_global_alpha(ipu_plane->dp, 616 !fb->format->has_alpha, 0xff, 617 false); 618 } 619 break; 620 } 621 622 eba = drm_plane_state_to_eba(new_state, 0); 623 624 /* 625 * Configure PRG channel and attached PRE, this changes the EBA to an 626 * internal SRAM location. 627 */ 628 if (ipu_state->use_pre) { 629 axi_id = ipu_chan_assign_axi_id(ipu_plane->dma); 630 ipu_prg_channel_configure(ipu_plane->ipu_ch, axi_id, 631 ipu_src_rect_width(new_state), 632 drm_rect_height(&new_state->src) >> 16, 633 fb->pitches[0], fb->format->format, 634 fb->modifier, &eba); 635 } 636 637 if (!old_state->fb || 638 old_state->fb->format->format != fb->format->format || 639 old_state->color_encoding != new_state->color_encoding || 640 old_state->color_range != new_state->color_range) { 641 ics = ipu_drm_fourcc_to_colorspace(fb->format->format); 642 switch (ipu_plane->dp_flow) { 643 case IPU_DP_FLOW_SYNC_BG: 644 ipu_dp_setup_channel(ipu_plane->dp, new_state->color_encoding, 645 new_state->color_range, ics, 646 IPUV3_COLORSPACE_RGB); 647 break; 648 case IPU_DP_FLOW_SYNC_FG: 649 ipu_dp_setup_channel(ipu_plane->dp, new_state->color_encoding, 650 new_state->color_range, ics, 651 IPUV3_COLORSPACE_UNKNOWN); 652 break; 653 } 654 } 655 656 if (old_state->fb && !drm_atomic_crtc_needs_modeset(crtc_state)) { 657 /* nothing to do if PRE is used */ 658 if (ipu_state->use_pre) 659 return; 660 active = ipu_idmac_get_current_buffer(ipu_plane->ipu_ch); 661 ipu_cpmem_set_buffer(ipu_plane->ipu_ch, !active, eba); 662 ipu_idmac_select_buffer(ipu_plane->ipu_ch, !active); 663 if (ipu_plane_separate_alpha(ipu_plane)) { 664 active = ipu_idmac_get_current_buffer(ipu_plane->alpha_ch); 665 ipu_cpmem_set_buffer(ipu_plane->alpha_ch, !active, 666 alpha_eba); 667 ipu_idmac_select_buffer(ipu_plane->alpha_ch, !active); 668 } 669 return; 670 } 671 672 ics = ipu_drm_fourcc_to_colorspace(fb->format->format); 673 switch (ipu_plane->dp_flow) { 674 case IPU_DP_FLOW_SYNC_BG: 675 ipu_dp_setup_channel(ipu_plane->dp, DRM_COLOR_YCBCR_BT601, 676 DRM_COLOR_YCBCR_LIMITED_RANGE, ics, 677 IPUV3_COLORSPACE_RGB); 678 break; 679 case IPU_DP_FLOW_SYNC_FG: 680 ipu_dp_setup_channel(ipu_plane->dp, DRM_COLOR_YCBCR_BT601, 681 DRM_COLOR_YCBCR_LIMITED_RANGE, ics, 682 IPUV3_COLORSPACE_UNKNOWN); 683 break; 684 } 685 686 ipu_dmfc_config_wait4eot(ipu_plane->dmfc, ALIGN(drm_rect_width(dst), 8)); 687 688 width = ipu_src_rect_width(new_state); 689 height = drm_rect_height(&new_state->src) >> 16; 690 info = drm_format_info(fb->format->format); 691 ipu_calculate_bursts(width, info->cpp[0], fb->pitches[0], 692 &burstsize, &num_bursts); 693 694 ipu_cpmem_zero(ipu_plane->ipu_ch); 695 ipu_cpmem_set_resolution(ipu_plane->ipu_ch, width, height); 696 ipu_cpmem_set_fmt(ipu_plane->ipu_ch, fb->format->format); 697 ipu_cpmem_set_burstsize(ipu_plane->ipu_ch, burstsize); 698 ipu_cpmem_set_high_priority(ipu_plane->ipu_ch); 699 ipu_idmac_enable_watermark(ipu_plane->ipu_ch, true); 700 ipu_idmac_set_double_buffer(ipu_plane->ipu_ch, 1); 701 ipu_cpmem_set_stride(ipu_plane->ipu_ch, fb->pitches[0]); 702 ipu_cpmem_set_axi_id(ipu_plane->ipu_ch, axi_id); 703 704 switch (fb->format->format) { 705 case DRM_FORMAT_YUV420: 706 case DRM_FORMAT_YVU420: 707 case DRM_FORMAT_YUV422: 708 case DRM_FORMAT_YVU422: 709 case DRM_FORMAT_YUV444: 710 case DRM_FORMAT_YVU444: 711 ubo = drm_plane_state_to_ubo(new_state); 712 vbo = drm_plane_state_to_vbo(new_state); 713 if (fb->format->format == DRM_FORMAT_YVU420 || 714 fb->format->format == DRM_FORMAT_YVU422 || 715 fb->format->format == DRM_FORMAT_YVU444) 716 swap(ubo, vbo); 717 718 ipu_cpmem_set_yuv_planar_full(ipu_plane->ipu_ch, 719 fb->pitches[1], ubo, vbo); 720 721 dev_dbg(ipu_plane->base.dev->dev, 722 "phy = %lu %lu %lu, x = %d, y = %d", eba, ubo, vbo, 723 new_state->src.x1 >> 16, new_state->src.y1 >> 16); 724 break; 725 case DRM_FORMAT_NV12: 726 case DRM_FORMAT_NV16: 727 ubo = drm_plane_state_to_ubo(new_state); 728 729 ipu_cpmem_set_yuv_planar_full(ipu_plane->ipu_ch, 730 fb->pitches[1], ubo, ubo); 731 732 dev_dbg(ipu_plane->base.dev->dev, 733 "phy = %lu %lu, x = %d, y = %d", eba, ubo, 734 new_state->src.x1 >> 16, new_state->src.y1 >> 16); 735 break; 736 case DRM_FORMAT_RGB565_A8: 737 case DRM_FORMAT_BGR565_A8: 738 case DRM_FORMAT_RGB888_A8: 739 case DRM_FORMAT_BGR888_A8: 740 case DRM_FORMAT_RGBX8888_A8: 741 case DRM_FORMAT_BGRX8888_A8: 742 alpha_eba = drm_plane_state_to_eba(new_state, 1); 743 num_bursts = 0; 744 745 dev_dbg(ipu_plane->base.dev->dev, "phys = %lu %lu, x = %d, y = %d", 746 eba, alpha_eba, new_state->src.x1 >> 16, 747 new_state->src.y1 >> 16); 748 749 ipu_cpmem_set_burstsize(ipu_plane->ipu_ch, 16); 750 751 ipu_cpmem_zero(ipu_plane->alpha_ch); 752 ipu_cpmem_set_resolution(ipu_plane->alpha_ch, 753 ipu_src_rect_width(new_state), 754 drm_rect_height(&new_state->src) >> 16); 755 ipu_cpmem_set_format_passthrough(ipu_plane->alpha_ch, 8); 756 ipu_cpmem_set_high_priority(ipu_plane->alpha_ch); 757 ipu_idmac_set_double_buffer(ipu_plane->alpha_ch, 1); 758 ipu_cpmem_set_stride(ipu_plane->alpha_ch, fb->pitches[1]); 759 ipu_cpmem_set_burstsize(ipu_plane->alpha_ch, 16); 760 ipu_cpmem_set_buffer(ipu_plane->alpha_ch, 0, alpha_eba); 761 ipu_cpmem_set_buffer(ipu_plane->alpha_ch, 1, alpha_eba); 762 break; 763 default: 764 dev_dbg(ipu_plane->base.dev->dev, "phys = %lu, x = %d, y = %d", 765 eba, new_state->src.x1 >> 16, new_state->src.y1 >> 16); 766 break; 767 } 768 ipu_cpmem_set_buffer(ipu_plane->ipu_ch, 0, eba); 769 ipu_cpmem_set_buffer(ipu_plane->ipu_ch, 1, eba); 770 ipu_idmac_lock_enable(ipu_plane->ipu_ch, num_bursts); 771 ipu_plane_enable(ipu_plane); 772} 773 774static const struct drm_plane_helper_funcs ipu_plane_helper_funcs = { 775 .atomic_check = ipu_plane_atomic_check, 776 .atomic_disable = ipu_plane_atomic_disable, 777 .atomic_update = ipu_plane_atomic_update, 778}; 779 780bool ipu_plane_atomic_update_pending(struct drm_plane *plane) 781{ 782 struct ipu_plane *ipu_plane = to_ipu_plane(plane); 783 struct drm_plane_state *state = plane->state; 784 struct ipu_plane_state *ipu_state = to_ipu_plane_state(state); 785 786 /* disabled crtcs must not block the update */ 787 if (!state->crtc) 788 return false; 789 790 if (ipu_state->use_pre) 791 return ipu_prg_channel_configure_pending(ipu_plane->ipu_ch); 792 793 /* 794 * Pretend no update is pending in the non-PRE/PRG case. For this to 795 * happen, an atomic update would have to be deferred until after the 796 * start of the next frame and simultaneously interrupt latency would 797 * have to be high enough to let the atomic update finish and issue an 798 * event before the previous end of frame interrupt handler can be 799 * executed. 800 */ 801 return false; 802} 803int ipu_planes_assign_pre(struct drm_device *dev, 804 struct drm_atomic_state *state) 805{ 806 struct drm_crtc_state *old_crtc_state, *crtc_state; 807 struct drm_plane_state *plane_state; 808 struct ipu_plane_state *ipu_state; 809 struct ipu_plane *ipu_plane; 810 struct drm_plane *plane; 811 struct drm_crtc *crtc; 812 int available_pres = ipu_prg_max_active_channels(); 813 int ret, i; 814 815 for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, crtc_state, i) { 816 ret = drm_atomic_add_affected_planes(state, crtc); 817 if (ret) 818 return ret; 819 } 820 821 /* 822 * We are going over the planes in 2 passes: first we assign PREs to 823 * planes with a tiling modifier, which need the PREs to resolve into 824 * linear. Any failure to assign a PRE there is fatal. In the second 825 * pass we try to assign PREs to linear FBs, to improve memory access 826 * patterns for them. Failure at this point is non-fatal, as we can 827 * scan out linear FBs without a PRE. 828 */ 829 for_each_new_plane_in_state(state, plane, plane_state, i) { 830 ipu_state = to_ipu_plane_state(plane_state); 831 ipu_plane = to_ipu_plane(plane); 832 833 if (!plane_state->fb) { 834 ipu_state->use_pre = false; 835 continue; 836 } 837 838 if (!(plane_state->fb->flags & DRM_MODE_FB_MODIFIERS) || 839 plane_state->fb->modifier == DRM_FORMAT_MOD_LINEAR) 840 continue; 841 842 if (!ipu_prg_present(ipu_plane->ipu) || !available_pres) 843 return -EINVAL; 844 845 if (!ipu_prg_format_supported(ipu_plane->ipu, 846 plane_state->fb->format->format, 847 plane_state->fb->modifier)) 848 return -EINVAL; 849 850 ipu_state->use_pre = true; 851 available_pres--; 852 } 853 854 for_each_new_plane_in_state(state, plane, plane_state, i) { 855 ipu_state = to_ipu_plane_state(plane_state); 856 ipu_plane = to_ipu_plane(plane); 857 858 if (!plane_state->fb) { 859 ipu_state->use_pre = false; 860 continue; 861 } 862 863 if ((plane_state->fb->flags & DRM_MODE_FB_MODIFIERS) && 864 plane_state->fb->modifier != DRM_FORMAT_MOD_LINEAR) 865 continue; 866 867 /* make sure that modifier is initialized */ 868 plane_state->fb->modifier = DRM_FORMAT_MOD_LINEAR; 869 870 if (ipu_prg_present(ipu_plane->ipu) && available_pres && 871 ipu_prg_format_supported(ipu_plane->ipu, 872 plane_state->fb->format->format, 873 plane_state->fb->modifier)) { 874 ipu_state->use_pre = true; 875 available_pres--; 876 } else { 877 ipu_state->use_pre = false; 878 } 879 } 880 881 return 0; 882} 883 884struct ipu_plane *ipu_plane_init(struct drm_device *dev, struct ipu_soc *ipu, 885 int dma, int dp, unsigned int possible_crtcs, 886 enum drm_plane_type type) 887{ 888 struct ipu_plane *ipu_plane; 889 const uint64_t *modifiers = ipu_format_modifiers; 890 unsigned int zpos = (type == DRM_PLANE_TYPE_PRIMARY) ? 0 : 1; 891 unsigned int format_count; 892 const uint32_t *formats; 893 int ret; 894 895 DRM_DEBUG_KMS("channel %d, dp flow %d, possible_crtcs=0x%x\n", 896 dma, dp, possible_crtcs); 897 898 if (dp == IPU_DP_FLOW_SYNC_BG || dp == IPU_DP_FLOW_SYNC_FG) { 899 formats = ipu_plane_all_formats; 900 format_count = ARRAY_SIZE(ipu_plane_all_formats); 901 } else { 902 formats = ipu_plane_rgb_formats; 903 format_count = ARRAY_SIZE(ipu_plane_rgb_formats); 904 } 905 906 if (ipu_prg_present(ipu)) 907 modifiers = pre_format_modifiers; 908 909 ipu_plane = drmm_universal_plane_alloc(dev, struct ipu_plane, base, 910 possible_crtcs, &ipu_plane_funcs, 911 formats, format_count, modifiers, 912 type, NULL); 913 if (IS_ERR(ipu_plane)) { 914 DRM_ERROR("failed to allocate and initialize %s plane\n", 915 zpos ? "overlay" : "primary"); 916 return ipu_plane; 917 } 918 919 ipu_plane->ipu = ipu; 920 ipu_plane->dma = dma; 921 ipu_plane->dp_flow = dp; 922 923 drm_plane_helper_add(&ipu_plane->base, &ipu_plane_helper_funcs); 924 925 if (dp == IPU_DP_FLOW_SYNC_BG || dp == IPU_DP_FLOW_SYNC_FG) 926 ret = drm_plane_create_zpos_property(&ipu_plane->base, zpos, 0, 927 1); 928 else 929 ret = drm_plane_create_zpos_immutable_property(&ipu_plane->base, 930 0); 931 if (ret) 932 return ERR_PTR(ret); 933 934 ret = drm_plane_create_color_properties(&ipu_plane->base, 935 BIT(DRM_COLOR_YCBCR_BT601) | 936 BIT(DRM_COLOR_YCBCR_BT709), 937 BIT(DRM_COLOR_YCBCR_LIMITED_RANGE), 938 DRM_COLOR_YCBCR_BT601, 939 DRM_COLOR_YCBCR_LIMITED_RANGE); 940 if (ret) 941 return ERR_PTR(ret); 942 943 ret = ipu_plane_get_resources(dev, ipu_plane); 944 if (ret) { 945 DRM_ERROR("failed to get %s plane resources: %pe\n", 946 zpos ? "overlay" : "primary", &ret); 947 return ERR_PTR(ret); 948 } 949 950 return ipu_plane; 951}