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.20-rc7 842 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 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} 292 293static struct drm_plane_state * 294ipu_plane_duplicate_state(struct drm_plane *plane) 295{ 296 struct ipu_plane_state *state; 297 298 if (WARN_ON(!plane->state)) 299 return NULL; 300 301 state = kmalloc(sizeof(*state), GFP_KERNEL); 302 if (state) 303 __drm_atomic_helper_plane_duplicate_state(plane, &state->base); 304 305 return &state->base; 306} 307 308static void ipu_plane_destroy_state(struct drm_plane *plane, 309 struct drm_plane_state *state) 310{ 311 struct ipu_plane_state *ipu_state = to_ipu_plane_state(state); 312 313 __drm_atomic_helper_plane_destroy_state(state); 314 kfree(ipu_state); 315} 316 317static bool ipu_plane_format_mod_supported(struct drm_plane *plane, 318 uint32_t format, uint64_t modifier) 319{ 320 struct ipu_soc *ipu = to_ipu_plane(plane)->ipu; 321 322 /* linear is supported for all planes and formats */ 323 if (modifier == DRM_FORMAT_MOD_LINEAR) 324 return true; 325 326 /* without a PRG there are no supported modifiers */ 327 if (!ipu_prg_present(ipu)) 328 return false; 329 330 return ipu_prg_format_supported(ipu, format, modifier); 331} 332 333static const struct drm_plane_funcs ipu_plane_funcs = { 334 .update_plane = drm_atomic_helper_update_plane, 335 .disable_plane = drm_atomic_helper_disable_plane, 336 .destroy = ipu_plane_destroy, 337 .reset = ipu_plane_state_reset, 338 .atomic_duplicate_state = ipu_plane_duplicate_state, 339 .atomic_destroy_state = ipu_plane_destroy_state, 340 .format_mod_supported = ipu_plane_format_mod_supported, 341}; 342 343static int ipu_plane_atomic_check(struct drm_plane *plane, 344 struct drm_plane_state *state) 345{ 346 struct drm_plane_state *old_state = plane->state; 347 struct drm_crtc_state *crtc_state; 348 struct device *dev = plane->dev->dev; 349 struct drm_framebuffer *fb = state->fb; 350 struct drm_framebuffer *old_fb = old_state->fb; 351 unsigned long eba, ubo, vbo, old_ubo, old_vbo, alpha_eba; 352 bool can_position = (plane->type == DRM_PLANE_TYPE_OVERLAY); 353 int hsub, vsub; 354 int ret; 355 356 /* Ok to disable */ 357 if (!fb) 358 return 0; 359 360 if (!state->crtc) 361 return -EINVAL; 362 363 crtc_state = 364 drm_atomic_get_existing_crtc_state(state->state, state->crtc); 365 if (WARN_ON(!crtc_state)) 366 return -EINVAL; 367 368 ret = drm_atomic_helper_check_plane_state(state, crtc_state, 369 DRM_PLANE_HELPER_NO_SCALING, 370 DRM_PLANE_HELPER_NO_SCALING, 371 can_position, true); 372 if (ret) 373 return ret; 374 375 /* CRTC should be enabled */ 376 if (!crtc_state->enable) 377 return -EINVAL; 378 379 switch (plane->type) { 380 case DRM_PLANE_TYPE_PRIMARY: 381 /* full plane minimum width is 13 pixels */ 382 if (drm_rect_width(&state->dst) < 13) 383 return -EINVAL; 384 break; 385 case DRM_PLANE_TYPE_OVERLAY: 386 break; 387 default: 388 dev_warn(dev, "Unsupported plane type %d\n", plane->type); 389 return -EINVAL; 390 } 391 392 if (drm_rect_height(&state->dst) < 2) 393 return -EINVAL; 394 395 /* 396 * We support resizing active plane or changing its format by 397 * forcing CRTC mode change in plane's ->atomic_check callback 398 * and disabling all affected active planes in CRTC's ->atomic_disable 399 * callback. The planes will be reenabled in plane's ->atomic_update 400 * callback. 401 */ 402 if (old_fb && 403 (drm_rect_width(&state->dst) != drm_rect_width(&old_state->dst) || 404 drm_rect_height(&state->dst) != drm_rect_height(&old_state->dst) || 405 fb->format != old_fb->format)) 406 crtc_state->mode_changed = true; 407 408 eba = drm_plane_state_to_eba(state, 0); 409 410 if (eba & 0x7) 411 return -EINVAL; 412 413 if (fb->pitches[0] < 1 || fb->pitches[0] > 16384) 414 return -EINVAL; 415 416 if (old_fb && fb->pitches[0] != old_fb->pitches[0]) 417 crtc_state->mode_changed = true; 418 419 switch (fb->format->format) { 420 case DRM_FORMAT_YUV420: 421 case DRM_FORMAT_YVU420: 422 case DRM_FORMAT_YUV422: 423 case DRM_FORMAT_YVU422: 424 case DRM_FORMAT_YUV444: 425 case DRM_FORMAT_YVU444: 426 /* 427 * Multiplanar formats have to meet the following restrictions: 428 * - The (up to) three plane addresses are EBA, EBA+UBO, EBA+VBO 429 * - EBA, UBO and VBO are a multiple of 8 430 * - UBO and VBO are unsigned and not larger than 0xfffff8 431 * - Only EBA may be changed while scanout is active 432 * - The strides of U and V planes must be identical. 433 */ 434 vbo = drm_plane_state_to_vbo(state); 435 436 if (vbo & 0x7 || vbo > 0xfffff8) 437 return -EINVAL; 438 439 if (old_fb && (fb->format == old_fb->format)) { 440 old_vbo = drm_plane_state_to_vbo(old_state); 441 if (vbo != old_vbo) 442 crtc_state->mode_changed = true; 443 } 444 445 if (fb->pitches[1] != fb->pitches[2]) 446 return -EINVAL; 447 448 /* fall-through */ 449 case DRM_FORMAT_NV12: 450 case DRM_FORMAT_NV16: 451 ubo = drm_plane_state_to_ubo(state); 452 453 if (ubo & 0x7 || ubo > 0xfffff8) 454 return -EINVAL; 455 456 if (old_fb && (fb->format == old_fb->format)) { 457 old_ubo = drm_plane_state_to_ubo(old_state); 458 if (ubo != old_ubo) 459 crtc_state->mode_changed = true; 460 } 461 462 if (fb->pitches[1] < 1 || fb->pitches[1] > 16384) 463 return -EINVAL; 464 465 if (old_fb && old_fb->pitches[1] != fb->pitches[1]) 466 crtc_state->mode_changed = true; 467 468 /* 469 * The x/y offsets must be even in case of horizontal/vertical 470 * chroma subsampling. 471 */ 472 hsub = drm_format_horz_chroma_subsampling(fb->format->format); 473 vsub = drm_format_vert_chroma_subsampling(fb->format->format); 474 if (((state->src.x1 >> 16) & (hsub - 1)) || 475 ((state->src.y1 >> 16) & (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 eba = drm_plane_state_to_eba(state, 0); 566 567 /* 568 * Configure PRG channel and attached PRE, this changes the EBA to an 569 * internal SRAM location. 570 */ 571 if (ipu_state->use_pre) { 572 axi_id = ipu_chan_assign_axi_id(ipu_plane->dma); 573 ipu_prg_channel_configure(ipu_plane->ipu_ch, axi_id, 574 drm_rect_width(&state->src) >> 16, 575 drm_rect_height(&state->src) >> 16, 576 fb->pitches[0], fb->format->format, 577 fb->modifier, &eba); 578 } 579 580 if (old_state->fb && !drm_atomic_crtc_needs_modeset(crtc_state)) { 581 /* nothing to do if PRE is used */ 582 if (ipu_state->use_pre) 583 return; 584 active = ipu_idmac_get_current_buffer(ipu_plane->ipu_ch); 585 ipu_cpmem_set_buffer(ipu_plane->ipu_ch, !active, eba); 586 ipu_idmac_select_buffer(ipu_plane->ipu_ch, !active); 587 if (ipu_plane_separate_alpha(ipu_plane)) { 588 active = ipu_idmac_get_current_buffer(ipu_plane->alpha_ch); 589 ipu_cpmem_set_buffer(ipu_plane->alpha_ch, !active, 590 alpha_eba); 591 ipu_idmac_select_buffer(ipu_plane->alpha_ch, !active); 592 } 593 return; 594 } 595 596 ics = ipu_drm_fourcc_to_colorspace(fb->format->format); 597 switch (ipu_plane->dp_flow) { 598 case IPU_DP_FLOW_SYNC_BG: 599 ipu_dp_setup_channel(ipu_plane->dp, ics, IPUV3_COLORSPACE_RGB); 600 ipu_dp_set_global_alpha(ipu_plane->dp, true, 0, true); 601 break; 602 case IPU_DP_FLOW_SYNC_FG: 603 ipu_dp_setup_channel(ipu_plane->dp, ics, 604 IPUV3_COLORSPACE_UNKNOWN); 605 /* Enable local alpha on partial plane */ 606 switch (fb->format->format) { 607 case DRM_FORMAT_ARGB1555: 608 case DRM_FORMAT_ABGR1555: 609 case DRM_FORMAT_RGBA5551: 610 case DRM_FORMAT_BGRA5551: 611 case DRM_FORMAT_ARGB4444: 612 case DRM_FORMAT_ARGB8888: 613 case DRM_FORMAT_ABGR8888: 614 case DRM_FORMAT_RGBA8888: 615 case DRM_FORMAT_BGRA8888: 616 case DRM_FORMAT_RGB565_A8: 617 case DRM_FORMAT_BGR565_A8: 618 case DRM_FORMAT_RGB888_A8: 619 case DRM_FORMAT_BGR888_A8: 620 case DRM_FORMAT_RGBX8888_A8: 621 case DRM_FORMAT_BGRX8888_A8: 622 ipu_dp_set_global_alpha(ipu_plane->dp, false, 0, false); 623 break; 624 default: 625 ipu_dp_set_global_alpha(ipu_plane->dp, true, 0, true); 626 break; 627 } 628 } 629 630 ipu_dmfc_config_wait4eot(ipu_plane->dmfc, drm_rect_width(dst)); 631 632 width = drm_rect_width(&state->src) >> 16; 633 height = drm_rect_height(&state->src) >> 16; 634 info = drm_format_info(fb->format->format); 635 ipu_calculate_bursts(width, info->cpp[0], fb->pitches[0], 636 &burstsize, &num_bursts); 637 638 ipu_cpmem_zero(ipu_plane->ipu_ch); 639 ipu_cpmem_set_resolution(ipu_plane->ipu_ch, width, height); 640 ipu_cpmem_set_fmt(ipu_plane->ipu_ch, fb->format->format); 641 ipu_cpmem_set_burstsize(ipu_plane->ipu_ch, burstsize); 642 ipu_cpmem_set_high_priority(ipu_plane->ipu_ch); 643 ipu_idmac_set_double_buffer(ipu_plane->ipu_ch, 1); 644 ipu_cpmem_set_stride(ipu_plane->ipu_ch, fb->pitches[0]); 645 ipu_cpmem_set_axi_id(ipu_plane->ipu_ch, axi_id); 646 647 switch (fb->format->format) { 648 case DRM_FORMAT_YUV420: 649 case DRM_FORMAT_YVU420: 650 case DRM_FORMAT_YUV422: 651 case DRM_FORMAT_YVU422: 652 case DRM_FORMAT_YUV444: 653 case DRM_FORMAT_YVU444: 654 ubo = drm_plane_state_to_ubo(state); 655 vbo = drm_plane_state_to_vbo(state); 656 if (fb->format->format == DRM_FORMAT_YVU420 || 657 fb->format->format == DRM_FORMAT_YVU422 || 658 fb->format->format == DRM_FORMAT_YVU444) 659 swap(ubo, vbo); 660 661 ipu_cpmem_set_yuv_planar_full(ipu_plane->ipu_ch, 662 fb->pitches[1], ubo, vbo); 663 664 dev_dbg(ipu_plane->base.dev->dev, 665 "phy = %lu %lu %lu, x = %d, y = %d", eba, ubo, vbo, 666 state->src.x1 >> 16, state->src.y1 >> 16); 667 break; 668 case DRM_FORMAT_NV12: 669 case DRM_FORMAT_NV16: 670 ubo = drm_plane_state_to_ubo(state); 671 672 ipu_cpmem_set_yuv_planar_full(ipu_plane->ipu_ch, 673 fb->pitches[1], ubo, ubo); 674 675 dev_dbg(ipu_plane->base.dev->dev, 676 "phy = %lu %lu, x = %d, y = %d", eba, ubo, 677 state->src.x1 >> 16, state->src.y1 >> 16); 678 break; 679 case DRM_FORMAT_RGB565_A8: 680 case DRM_FORMAT_BGR565_A8: 681 case DRM_FORMAT_RGB888_A8: 682 case DRM_FORMAT_BGR888_A8: 683 case DRM_FORMAT_RGBX8888_A8: 684 case DRM_FORMAT_BGRX8888_A8: 685 alpha_eba = drm_plane_state_to_eba(state, 1); 686 num_bursts = 0; 687 688 dev_dbg(ipu_plane->base.dev->dev, "phys = %lu %lu, x = %d, y = %d", 689 eba, alpha_eba, state->src.x1 >> 16, state->src.y1 >> 16); 690 691 ipu_cpmem_set_burstsize(ipu_plane->ipu_ch, 16); 692 693 ipu_cpmem_zero(ipu_plane->alpha_ch); 694 ipu_cpmem_set_resolution(ipu_plane->alpha_ch, 695 drm_rect_width(&state->src) >> 16, 696 drm_rect_height(&state->src) >> 16); 697 ipu_cpmem_set_format_passthrough(ipu_plane->alpha_ch, 8); 698 ipu_cpmem_set_high_priority(ipu_plane->alpha_ch); 699 ipu_idmac_set_double_buffer(ipu_plane->alpha_ch, 1); 700 ipu_cpmem_set_stride(ipu_plane->alpha_ch, fb->pitches[1]); 701 ipu_cpmem_set_burstsize(ipu_plane->alpha_ch, 16); 702 ipu_cpmem_set_buffer(ipu_plane->alpha_ch, 0, alpha_eba); 703 ipu_cpmem_set_buffer(ipu_plane->alpha_ch, 1, alpha_eba); 704 break; 705 default: 706 dev_dbg(ipu_plane->base.dev->dev, "phys = %lu, x = %d, y = %d", 707 eba, state->src.x1 >> 16, state->src.y1 >> 16); 708 break; 709 } 710 ipu_cpmem_set_buffer(ipu_plane->ipu_ch, 0, eba); 711 ipu_cpmem_set_buffer(ipu_plane->ipu_ch, 1, eba); 712 ipu_idmac_lock_enable(ipu_plane->ipu_ch, num_bursts); 713 ipu_plane_enable(ipu_plane); 714} 715 716static const struct drm_plane_helper_funcs ipu_plane_helper_funcs = { 717 .prepare_fb = drm_gem_fb_prepare_fb, 718 .atomic_check = ipu_plane_atomic_check, 719 .atomic_disable = ipu_plane_atomic_disable, 720 .atomic_update = ipu_plane_atomic_update, 721}; 722 723int ipu_planes_assign_pre(struct drm_device *dev, 724 struct drm_atomic_state *state) 725{ 726 struct drm_crtc_state *old_crtc_state, *crtc_state; 727 struct drm_plane_state *plane_state; 728 struct ipu_plane_state *ipu_state; 729 struct ipu_plane *ipu_plane; 730 struct drm_plane *plane; 731 struct drm_crtc *crtc; 732 int available_pres = ipu_prg_max_active_channels(); 733 int ret, i; 734 735 for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, crtc_state, i) { 736 ret = drm_atomic_add_affected_planes(state, crtc); 737 if (ret) 738 return ret; 739 } 740 741 /* 742 * We are going over the planes in 2 passes: first we assign PREs to 743 * planes with a tiling modifier, which need the PREs to resolve into 744 * linear. Any failure to assign a PRE there is fatal. In the second 745 * pass we try to assign PREs to linear FBs, to improve memory access 746 * patterns for them. Failure at this point is non-fatal, as we can 747 * scan out linear FBs without a PRE. 748 */ 749 for_each_new_plane_in_state(state, plane, plane_state, i) { 750 ipu_state = to_ipu_plane_state(plane_state); 751 ipu_plane = to_ipu_plane(plane); 752 753 if (!plane_state->fb) { 754 ipu_state->use_pre = false; 755 continue; 756 } 757 758 if (!(plane_state->fb->flags & DRM_MODE_FB_MODIFIERS) || 759 plane_state->fb->modifier == DRM_FORMAT_MOD_LINEAR) 760 continue; 761 762 if (!ipu_prg_present(ipu_plane->ipu) || !available_pres) 763 return -EINVAL; 764 765 if (!ipu_prg_format_supported(ipu_plane->ipu, 766 plane_state->fb->format->format, 767 plane_state->fb->modifier)) 768 return -EINVAL; 769 770 ipu_state->use_pre = true; 771 available_pres--; 772 } 773 774 for_each_new_plane_in_state(state, plane, plane_state, i) { 775 ipu_state = to_ipu_plane_state(plane_state); 776 ipu_plane = to_ipu_plane(plane); 777 778 if (!plane_state->fb) { 779 ipu_state->use_pre = false; 780 continue; 781 } 782 783 if ((plane_state->fb->flags & DRM_MODE_FB_MODIFIERS) && 784 plane_state->fb->modifier != DRM_FORMAT_MOD_LINEAR) 785 continue; 786 787 /* make sure that modifier is initialized */ 788 plane_state->fb->modifier = DRM_FORMAT_MOD_LINEAR; 789 790 if (ipu_prg_present(ipu_plane->ipu) && available_pres && 791 ipu_prg_format_supported(ipu_plane->ipu, 792 plane_state->fb->format->format, 793 plane_state->fb->modifier)) { 794 ipu_state->use_pre = true; 795 available_pres--; 796 } else { 797 ipu_state->use_pre = false; 798 } 799 } 800 801 return 0; 802} 803EXPORT_SYMBOL_GPL(ipu_planes_assign_pre); 804 805struct ipu_plane *ipu_plane_init(struct drm_device *dev, struct ipu_soc *ipu, 806 int dma, int dp, unsigned int possible_crtcs, 807 enum drm_plane_type type) 808{ 809 struct ipu_plane *ipu_plane; 810 const uint64_t *modifiers = ipu_format_modifiers; 811 int ret; 812 813 DRM_DEBUG_KMS("channel %d, dp flow %d, possible_crtcs=0x%x\n", 814 dma, dp, possible_crtcs); 815 816 ipu_plane = kzalloc(sizeof(*ipu_plane), GFP_KERNEL); 817 if (!ipu_plane) { 818 DRM_ERROR("failed to allocate plane\n"); 819 return ERR_PTR(-ENOMEM); 820 } 821 822 ipu_plane->ipu = ipu; 823 ipu_plane->dma = dma; 824 ipu_plane->dp_flow = dp; 825 826 if (ipu_prg_present(ipu)) 827 modifiers = pre_format_modifiers; 828 829 ret = drm_universal_plane_init(dev, &ipu_plane->base, possible_crtcs, 830 &ipu_plane_funcs, ipu_plane_formats, 831 ARRAY_SIZE(ipu_plane_formats), 832 modifiers, type, NULL); 833 if (ret) { 834 DRM_ERROR("failed to initialize plane\n"); 835 kfree(ipu_plane); 836 return ERR_PTR(ret); 837 } 838 839 drm_plane_helper_add(&ipu_plane->base, &ipu_plane_helper_funcs); 840 841 return ipu_plane; 842}