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