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