1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (C) 2015 Broadcom 4 */ 5 6 /** 7 * DOC: VC4 plane module 8 * 9 * Each DRM plane is a layer of pixels being scanned out by the HVS. 10 * 11 * At atomic modeset check time, we compute the HVS display element 12 * state that would be necessary for displaying the plane (giving us a 13 * chance to figure out if a plane configuration is invalid), then at 14 * atomic flush time the CRTC will ask us to write our element state 15 * into the region of the HVS that it has allocated for us. 16 */ 17 18 #include <drm/drm_atomic.h> 19 #include <drm/drm_atomic_helper.h> 20 #include <drm/drm_atomic_uapi.h> 21 #include <drm/drm_blend.h> 22 #include <drm/drm_drv.h> 23 #include <drm/drm_fb_dma_helper.h> 24 #include <drm/drm_fourcc.h> 25 #include <drm/drm_framebuffer.h> 26 #include <drm/drm_gem_atomic_helper.h> 27 28 #include "uapi/drm/vc4_drm.h" 29 30 #include "vc4_drv.h" 31 #include "vc4_regs.h" 32 33 static const struct hvs_format { 34 u32 drm; /* DRM_FORMAT_* */ 35 u32 hvs; /* HVS_FORMAT_* */ 36 u32 pixel_order; 37 u32 pixel_order_hvs5; 38 bool hvs5_only; 39 } hvs_formats[] = { 40 { 41 .drm = DRM_FORMAT_XRGB8888, 42 .hvs = HVS_PIXEL_FORMAT_RGBA8888, 43 .pixel_order = HVS_PIXEL_ORDER_ABGR, 44 .pixel_order_hvs5 = HVS_PIXEL_ORDER_ARGB, 45 }, 46 { 47 .drm = DRM_FORMAT_ARGB8888, 48 .hvs = HVS_PIXEL_FORMAT_RGBA8888, 49 .pixel_order = HVS_PIXEL_ORDER_ABGR, 50 .pixel_order_hvs5 = HVS_PIXEL_ORDER_ARGB, 51 }, 52 { 53 .drm = DRM_FORMAT_ABGR8888, 54 .hvs = HVS_PIXEL_FORMAT_RGBA8888, 55 .pixel_order = HVS_PIXEL_ORDER_ARGB, 56 .pixel_order_hvs5 = HVS_PIXEL_ORDER_ABGR, 57 }, 58 { 59 .drm = DRM_FORMAT_XBGR8888, 60 .hvs = HVS_PIXEL_FORMAT_RGBA8888, 61 .pixel_order = HVS_PIXEL_ORDER_ARGB, 62 .pixel_order_hvs5 = HVS_PIXEL_ORDER_ABGR, 63 }, 64 { 65 .drm = DRM_FORMAT_RGB565, 66 .hvs = HVS_PIXEL_FORMAT_RGB565, 67 .pixel_order = HVS_PIXEL_ORDER_XRGB, 68 .pixel_order_hvs5 = HVS_PIXEL_ORDER_XRGB, 69 }, 70 { 71 .drm = DRM_FORMAT_BGR565, 72 .hvs = HVS_PIXEL_FORMAT_RGB565, 73 .pixel_order = HVS_PIXEL_ORDER_XBGR, 74 .pixel_order_hvs5 = HVS_PIXEL_ORDER_XBGR, 75 }, 76 { 77 .drm = DRM_FORMAT_ARGB1555, 78 .hvs = HVS_PIXEL_FORMAT_RGBA5551, 79 .pixel_order = HVS_PIXEL_ORDER_ABGR, 80 .pixel_order_hvs5 = HVS_PIXEL_ORDER_ARGB, 81 }, 82 { 83 .drm = DRM_FORMAT_XRGB1555, 84 .hvs = HVS_PIXEL_FORMAT_RGBA5551, 85 .pixel_order = HVS_PIXEL_ORDER_ABGR, 86 .pixel_order_hvs5 = HVS_PIXEL_ORDER_ARGB, 87 }, 88 { 89 .drm = DRM_FORMAT_RGB888, 90 .hvs = HVS_PIXEL_FORMAT_RGB888, 91 .pixel_order = HVS_PIXEL_ORDER_XRGB, 92 .pixel_order_hvs5 = HVS_PIXEL_ORDER_XRGB, 93 }, 94 { 95 .drm = DRM_FORMAT_BGR888, 96 .hvs = HVS_PIXEL_FORMAT_RGB888, 97 .pixel_order = HVS_PIXEL_ORDER_XBGR, 98 .pixel_order_hvs5 = HVS_PIXEL_ORDER_XBGR, 99 }, 100 { 101 .drm = DRM_FORMAT_YUV422, 102 .hvs = HVS_PIXEL_FORMAT_YCBCR_YUV422_3PLANE, 103 .pixel_order = HVS_PIXEL_ORDER_XYCBCR, 104 .pixel_order_hvs5 = HVS_PIXEL_ORDER_XYCBCR, 105 }, 106 { 107 .drm = DRM_FORMAT_YVU422, 108 .hvs = HVS_PIXEL_FORMAT_YCBCR_YUV422_3PLANE, 109 .pixel_order = HVS_PIXEL_ORDER_XYCRCB, 110 .pixel_order_hvs5 = HVS_PIXEL_ORDER_XYCRCB, 111 }, 112 { 113 .drm = DRM_FORMAT_YUV420, 114 .hvs = HVS_PIXEL_FORMAT_YCBCR_YUV420_3PLANE, 115 .pixel_order = HVS_PIXEL_ORDER_XYCBCR, 116 .pixel_order_hvs5 = HVS_PIXEL_ORDER_XYCBCR, 117 }, 118 { 119 .drm = DRM_FORMAT_YVU420, 120 .hvs = HVS_PIXEL_FORMAT_YCBCR_YUV420_3PLANE, 121 .pixel_order = HVS_PIXEL_ORDER_XYCRCB, 122 .pixel_order_hvs5 = HVS_PIXEL_ORDER_XYCRCB, 123 }, 124 { 125 .drm = DRM_FORMAT_NV12, 126 .hvs = HVS_PIXEL_FORMAT_YCBCR_YUV420_2PLANE, 127 .pixel_order = HVS_PIXEL_ORDER_XYCBCR, 128 .pixel_order_hvs5 = HVS_PIXEL_ORDER_XYCBCR, 129 }, 130 { 131 .drm = DRM_FORMAT_NV21, 132 .hvs = HVS_PIXEL_FORMAT_YCBCR_YUV420_2PLANE, 133 .pixel_order = HVS_PIXEL_ORDER_XYCRCB, 134 .pixel_order_hvs5 = HVS_PIXEL_ORDER_XYCRCB, 135 }, 136 { 137 .drm = DRM_FORMAT_NV16, 138 .hvs = HVS_PIXEL_FORMAT_YCBCR_YUV422_2PLANE, 139 .pixel_order = HVS_PIXEL_ORDER_XYCBCR, 140 .pixel_order_hvs5 = HVS_PIXEL_ORDER_XYCBCR, 141 }, 142 { 143 .drm = DRM_FORMAT_NV61, 144 .hvs = HVS_PIXEL_FORMAT_YCBCR_YUV422_2PLANE, 145 .pixel_order = HVS_PIXEL_ORDER_XYCRCB, 146 .pixel_order_hvs5 = HVS_PIXEL_ORDER_XYCRCB, 147 }, 148 { 149 .drm = DRM_FORMAT_P030, 150 .hvs = HVS_PIXEL_FORMAT_YCBCR_10BIT, 151 .pixel_order_hvs5 = HVS_PIXEL_ORDER_XYCBCR, 152 .hvs5_only = true, 153 }, 154 { 155 .drm = DRM_FORMAT_XRGB2101010, 156 .hvs = HVS_PIXEL_FORMAT_RGBA1010102, 157 .pixel_order_hvs5 = HVS_PIXEL_ORDER_ARGB, 158 .hvs5_only = true, 159 }, 160 { 161 .drm = DRM_FORMAT_ARGB2101010, 162 .hvs = HVS_PIXEL_FORMAT_RGBA1010102, 163 .pixel_order_hvs5 = HVS_PIXEL_ORDER_ARGB, 164 .hvs5_only = true, 165 }, 166 { 167 .drm = DRM_FORMAT_ABGR2101010, 168 .hvs = HVS_PIXEL_FORMAT_RGBA1010102, 169 .pixel_order_hvs5 = HVS_PIXEL_ORDER_ABGR, 170 .hvs5_only = true, 171 }, 172 { 173 .drm = DRM_FORMAT_XBGR2101010, 174 .hvs = HVS_PIXEL_FORMAT_RGBA1010102, 175 .pixel_order_hvs5 = HVS_PIXEL_ORDER_ABGR, 176 .hvs5_only = true, 177 }, 178 { 179 .drm = DRM_FORMAT_RGB332, 180 .hvs = HVS_PIXEL_FORMAT_RGB332, 181 .pixel_order = HVS_PIXEL_ORDER_ARGB, 182 .pixel_order_hvs5 = HVS_PIXEL_ORDER_ARGB, 183 }, 184 { 185 .drm = DRM_FORMAT_BGR233, 186 .hvs = HVS_PIXEL_FORMAT_RGB332, 187 .pixel_order = HVS_PIXEL_ORDER_ABGR, 188 .pixel_order_hvs5 = HVS_PIXEL_ORDER_ABGR, 189 }, 190 { 191 .drm = DRM_FORMAT_XRGB4444, 192 .hvs = HVS_PIXEL_FORMAT_RGBA4444, 193 .pixel_order = HVS_PIXEL_ORDER_ABGR, 194 .pixel_order_hvs5 = HVS_PIXEL_ORDER_ARGB, 195 }, 196 { 197 .drm = DRM_FORMAT_ARGB4444, 198 .hvs = HVS_PIXEL_FORMAT_RGBA4444, 199 .pixel_order = HVS_PIXEL_ORDER_ABGR, 200 .pixel_order_hvs5 = HVS_PIXEL_ORDER_ARGB, 201 }, 202 { 203 .drm = DRM_FORMAT_XBGR4444, 204 .hvs = HVS_PIXEL_FORMAT_RGBA4444, 205 .pixel_order = HVS_PIXEL_ORDER_ARGB, 206 .pixel_order_hvs5 = HVS_PIXEL_ORDER_ABGR, 207 }, 208 { 209 .drm = DRM_FORMAT_ABGR4444, 210 .hvs = HVS_PIXEL_FORMAT_RGBA4444, 211 .pixel_order = HVS_PIXEL_ORDER_ARGB, 212 .pixel_order_hvs5 = HVS_PIXEL_ORDER_ABGR, 213 }, 214 { 215 .drm = DRM_FORMAT_BGRX4444, 216 .hvs = HVS_PIXEL_FORMAT_RGBA4444, 217 .pixel_order = HVS_PIXEL_ORDER_RGBA, 218 .pixel_order_hvs5 = HVS_PIXEL_ORDER_BGRA, 219 }, 220 { 221 .drm = DRM_FORMAT_BGRA4444, 222 .hvs = HVS_PIXEL_FORMAT_RGBA4444, 223 .pixel_order = HVS_PIXEL_ORDER_RGBA, 224 .pixel_order_hvs5 = HVS_PIXEL_ORDER_BGRA, 225 }, 226 { 227 .drm = DRM_FORMAT_RGBX4444, 228 .hvs = HVS_PIXEL_FORMAT_RGBA4444, 229 .pixel_order = HVS_PIXEL_ORDER_BGRA, 230 .pixel_order_hvs5 = HVS_PIXEL_ORDER_RGBA, 231 }, 232 { 233 .drm = DRM_FORMAT_RGBA4444, 234 .hvs = HVS_PIXEL_FORMAT_RGBA4444, 235 .pixel_order = HVS_PIXEL_ORDER_BGRA, 236 .pixel_order_hvs5 = HVS_PIXEL_ORDER_RGBA, 237 }, 238 }; 239 240 static const struct hvs_format *vc4_get_hvs_format(u32 drm_format) 241 { 242 unsigned i; 243 244 for (i = 0; i < ARRAY_SIZE(hvs_formats); i++) { 245 if (hvs_formats[i].drm == drm_format) 246 return &hvs_formats[i]; 247 } 248 249 return NULL; 250 } 251 252 static enum vc4_scaling_mode vc4_get_scaling_mode(u32 src, u32 dst) 253 { 254 if (dst == src) 255 return VC4_SCALING_NONE; 256 if (3 * dst >= 2 * src) 257 return VC4_SCALING_PPF; 258 else 259 return VC4_SCALING_TPZ; 260 } 261 262 static bool plane_enabled(struct drm_plane_state *state) 263 { 264 return state->fb && !WARN_ON(!state->crtc); 265 } 266 267 static struct drm_plane_state *vc4_plane_duplicate_state(struct drm_plane *plane) 268 { 269 struct vc4_plane_state *vc4_state; 270 271 if (WARN_ON(!plane->state)) 272 return NULL; 273 274 vc4_state = kmemdup(plane->state, sizeof(*vc4_state), GFP_KERNEL); 275 if (!vc4_state) 276 return NULL; 277 278 memset(&vc4_state->lbm, 0, sizeof(vc4_state->lbm)); 279 vc4_state->dlist_initialized = 0; 280 281 __drm_atomic_helper_plane_duplicate_state(plane, &vc4_state->base); 282 283 if (vc4_state->dlist) { 284 vc4_state->dlist = kmemdup(vc4_state->dlist, 285 vc4_state->dlist_count * 4, 286 GFP_KERNEL); 287 if (!vc4_state->dlist) { 288 kfree(vc4_state); 289 return NULL; 290 } 291 vc4_state->dlist_size = vc4_state->dlist_count; 292 } 293 294 return &vc4_state->base; 295 } 296 297 static void vc4_plane_destroy_state(struct drm_plane *plane, 298 struct drm_plane_state *state) 299 { 300 struct vc4_dev *vc4 = to_vc4_dev(plane->dev); 301 struct vc4_plane_state *vc4_state = to_vc4_plane_state(state); 302 303 if (drm_mm_node_allocated(&vc4_state->lbm)) { 304 unsigned long irqflags; 305 306 spin_lock_irqsave(&vc4->hvs->mm_lock, irqflags); 307 drm_mm_remove_node(&vc4_state->lbm); 308 spin_unlock_irqrestore(&vc4->hvs->mm_lock, irqflags); 309 } 310 311 kfree(vc4_state->dlist); 312 __drm_atomic_helper_plane_destroy_state(&vc4_state->base); 313 kfree(state); 314 } 315 316 /* Called during init to allocate the plane's atomic state. */ 317 static void vc4_plane_reset(struct drm_plane *plane) 318 { 319 struct vc4_plane_state *vc4_state; 320 321 WARN_ON(plane->state); 322 323 vc4_state = kzalloc(sizeof(*vc4_state), GFP_KERNEL); 324 if (!vc4_state) 325 return; 326 327 __drm_atomic_helper_plane_reset(plane, &vc4_state->base); 328 } 329 330 static void vc4_dlist_counter_increment(struct vc4_plane_state *vc4_state) 331 { 332 if (vc4_state->dlist_count == vc4_state->dlist_size) { 333 u32 new_size = max(4u, vc4_state->dlist_count * 2); 334 u32 *new_dlist = kmalloc_array(new_size, 4, GFP_KERNEL); 335 336 if (!new_dlist) 337 return; 338 memcpy(new_dlist, vc4_state->dlist, vc4_state->dlist_count * 4); 339 340 kfree(vc4_state->dlist); 341 vc4_state->dlist = new_dlist; 342 vc4_state->dlist_size = new_size; 343 } 344 345 vc4_state->dlist_count++; 346 } 347 348 static void vc4_dlist_write(struct vc4_plane_state *vc4_state, u32 val) 349 { 350 unsigned int idx = vc4_state->dlist_count; 351 352 vc4_dlist_counter_increment(vc4_state); 353 vc4_state->dlist[idx] = val; 354 } 355 356 /* Returns the scl0/scl1 field based on whether the dimensions need to 357 * be up/down/non-scaled. 358 * 359 * This is a replication of a table from the spec. 360 */ 361 static u32 vc4_get_scl_field(struct drm_plane_state *state, int plane) 362 { 363 struct vc4_plane_state *vc4_state = to_vc4_plane_state(state); 364 365 switch (vc4_state->x_scaling[plane] << 2 | vc4_state->y_scaling[plane]) { 366 case VC4_SCALING_PPF << 2 | VC4_SCALING_PPF: 367 return SCALER_CTL0_SCL_H_PPF_V_PPF; 368 case VC4_SCALING_TPZ << 2 | VC4_SCALING_PPF: 369 return SCALER_CTL0_SCL_H_TPZ_V_PPF; 370 case VC4_SCALING_PPF << 2 | VC4_SCALING_TPZ: 371 return SCALER_CTL0_SCL_H_PPF_V_TPZ; 372 case VC4_SCALING_TPZ << 2 | VC4_SCALING_TPZ: 373 return SCALER_CTL0_SCL_H_TPZ_V_TPZ; 374 case VC4_SCALING_PPF << 2 | VC4_SCALING_NONE: 375 return SCALER_CTL0_SCL_H_PPF_V_NONE; 376 case VC4_SCALING_NONE << 2 | VC4_SCALING_PPF: 377 return SCALER_CTL0_SCL_H_NONE_V_PPF; 378 case VC4_SCALING_NONE << 2 | VC4_SCALING_TPZ: 379 return SCALER_CTL0_SCL_H_NONE_V_TPZ; 380 case VC4_SCALING_TPZ << 2 | VC4_SCALING_NONE: 381 return SCALER_CTL0_SCL_H_TPZ_V_NONE; 382 default: 383 case VC4_SCALING_NONE << 2 | VC4_SCALING_NONE: 384 /* The unity case is independently handled by 385 * SCALER_CTL0_UNITY. 386 */ 387 return 0; 388 } 389 } 390 391 static int vc4_plane_margins_adj(struct drm_plane_state *pstate) 392 { 393 struct vc4_plane_state *vc4_pstate = to_vc4_plane_state(pstate); 394 unsigned int left, right, top, bottom, adjhdisplay, adjvdisplay; 395 struct drm_crtc_state *crtc_state; 396 397 crtc_state = drm_atomic_get_new_crtc_state(pstate->state, 398 pstate->crtc); 399 400 vc4_crtc_get_margins(crtc_state, &left, &right, &top, &bottom); 401 if (!left && !right && !top && !bottom) 402 return 0; 403 404 if (left + right >= crtc_state->mode.hdisplay || 405 top + bottom >= crtc_state->mode.vdisplay) 406 return -EINVAL; 407 408 adjhdisplay = crtc_state->mode.hdisplay - (left + right); 409 vc4_pstate->crtc_x = DIV_ROUND_CLOSEST(vc4_pstate->crtc_x * 410 adjhdisplay, 411 crtc_state->mode.hdisplay); 412 vc4_pstate->crtc_x += left; 413 if (vc4_pstate->crtc_x > crtc_state->mode.hdisplay - right) 414 vc4_pstate->crtc_x = crtc_state->mode.hdisplay - right; 415 416 adjvdisplay = crtc_state->mode.vdisplay - (top + bottom); 417 vc4_pstate->crtc_y = DIV_ROUND_CLOSEST(vc4_pstate->crtc_y * 418 adjvdisplay, 419 crtc_state->mode.vdisplay); 420 vc4_pstate->crtc_y += top; 421 if (vc4_pstate->crtc_y > crtc_state->mode.vdisplay - bottom) 422 vc4_pstate->crtc_y = crtc_state->mode.vdisplay - bottom; 423 424 vc4_pstate->crtc_w = DIV_ROUND_CLOSEST(vc4_pstate->crtc_w * 425 adjhdisplay, 426 crtc_state->mode.hdisplay); 427 vc4_pstate->crtc_h = DIV_ROUND_CLOSEST(vc4_pstate->crtc_h * 428 adjvdisplay, 429 crtc_state->mode.vdisplay); 430 431 if (!vc4_pstate->crtc_w || !vc4_pstate->crtc_h) 432 return -EINVAL; 433 434 return 0; 435 } 436 437 static int vc4_plane_setup_clipping_and_scaling(struct drm_plane_state *state) 438 { 439 struct vc4_plane_state *vc4_state = to_vc4_plane_state(state); 440 struct drm_framebuffer *fb = state->fb; 441 struct drm_gem_dma_object *bo = drm_fb_dma_get_gem_obj(fb, 0); 442 int num_planes = fb->format->num_planes; 443 struct drm_crtc_state *crtc_state; 444 u32 h_subsample = fb->format->hsub; 445 u32 v_subsample = fb->format->vsub; 446 int i, ret; 447 448 crtc_state = drm_atomic_get_existing_crtc_state(state->state, 449 state->crtc); 450 if (!crtc_state) { 451 DRM_DEBUG_KMS("Invalid crtc state\n"); 452 return -EINVAL; 453 } 454 455 ret = drm_atomic_helper_check_plane_state(state, crtc_state, 1, 456 INT_MAX, true, true); 457 if (ret) 458 return ret; 459 460 for (i = 0; i < num_planes; i++) 461 vc4_state->offsets[i] = bo->dma_addr + fb->offsets[i]; 462 463 /* 464 * We don't support subpixel source positioning for scaling, 465 * but fractional coordinates can be generated by clipping 466 * so just round for now 467 */ 468 vc4_state->src_x = DIV_ROUND_CLOSEST(state->src.x1, 1 << 16); 469 vc4_state->src_y = DIV_ROUND_CLOSEST(state->src.y1, 1 << 16); 470 vc4_state->src_w[0] = DIV_ROUND_CLOSEST(state->src.x2, 1 << 16) - vc4_state->src_x; 471 vc4_state->src_h[0] = DIV_ROUND_CLOSEST(state->src.y2, 1 << 16) - vc4_state->src_y; 472 473 vc4_state->crtc_x = state->dst.x1; 474 vc4_state->crtc_y = state->dst.y1; 475 vc4_state->crtc_w = state->dst.x2 - state->dst.x1; 476 vc4_state->crtc_h = state->dst.y2 - state->dst.y1; 477 478 ret = vc4_plane_margins_adj(state); 479 if (ret) 480 return ret; 481 482 vc4_state->x_scaling[0] = vc4_get_scaling_mode(vc4_state->src_w[0], 483 vc4_state->crtc_w); 484 vc4_state->y_scaling[0] = vc4_get_scaling_mode(vc4_state->src_h[0], 485 vc4_state->crtc_h); 486 487 vc4_state->is_unity = (vc4_state->x_scaling[0] == VC4_SCALING_NONE && 488 vc4_state->y_scaling[0] == VC4_SCALING_NONE); 489 490 if (num_planes > 1) { 491 vc4_state->is_yuv = true; 492 493 vc4_state->src_w[1] = vc4_state->src_w[0] / h_subsample; 494 vc4_state->src_h[1] = vc4_state->src_h[0] / v_subsample; 495 496 vc4_state->x_scaling[1] = 497 vc4_get_scaling_mode(vc4_state->src_w[1], 498 vc4_state->crtc_w); 499 vc4_state->y_scaling[1] = 500 vc4_get_scaling_mode(vc4_state->src_h[1], 501 vc4_state->crtc_h); 502 503 /* YUV conversion requires that horizontal scaling be enabled 504 * on the UV plane even if vc4_get_scaling_mode() returned 505 * VC4_SCALING_NONE (which can happen when the down-scaling 506 * ratio is 0.5). Let's force it to VC4_SCALING_PPF in this 507 * case. 508 */ 509 if (vc4_state->x_scaling[1] == VC4_SCALING_NONE) 510 vc4_state->x_scaling[1] = VC4_SCALING_PPF; 511 } else { 512 vc4_state->is_yuv = false; 513 vc4_state->x_scaling[1] = VC4_SCALING_NONE; 514 vc4_state->y_scaling[1] = VC4_SCALING_NONE; 515 } 516 517 return 0; 518 } 519 520 static void vc4_write_tpz(struct vc4_plane_state *vc4_state, u32 src, u32 dst) 521 { 522 u32 scale, recip; 523 524 scale = (1 << 16) * src / dst; 525 526 /* The specs note that while the reciprocal would be defined 527 * as (1<<32)/scale, ~0 is close enough. 528 */ 529 recip = ~0 / scale; 530 531 vc4_dlist_write(vc4_state, 532 VC4_SET_FIELD(scale, SCALER_TPZ0_SCALE) | 533 VC4_SET_FIELD(0, SCALER_TPZ0_IPHASE)); 534 vc4_dlist_write(vc4_state, 535 VC4_SET_FIELD(recip, SCALER_TPZ1_RECIP)); 536 } 537 538 static void vc4_write_ppf(struct vc4_plane_state *vc4_state, u32 src, u32 dst) 539 { 540 u32 scale = (1 << 16) * src / dst; 541 542 vc4_dlist_write(vc4_state, 543 SCALER_PPF_AGC | 544 VC4_SET_FIELD(scale, SCALER_PPF_SCALE) | 545 VC4_SET_FIELD(0, SCALER_PPF_IPHASE)); 546 } 547 548 static u32 vc4_lbm_size(struct drm_plane_state *state) 549 { 550 struct vc4_plane_state *vc4_state = to_vc4_plane_state(state); 551 struct vc4_dev *vc4 = to_vc4_dev(state->plane->dev); 552 u32 pix_per_line; 553 u32 lbm; 554 555 /* LBM is not needed when there's no vertical scaling. */ 556 if (vc4_state->y_scaling[0] == VC4_SCALING_NONE && 557 vc4_state->y_scaling[1] == VC4_SCALING_NONE) 558 return 0; 559 560 /* 561 * This can be further optimized in the RGB/YUV444 case if the PPF 562 * decimation factor is between 0.5 and 1.0 by using crtc_w. 563 * 564 * It's not an issue though, since in that case since src_w[0] is going 565 * to be greater than or equal to crtc_w. 566 */ 567 if (vc4_state->x_scaling[0] == VC4_SCALING_TPZ) 568 pix_per_line = vc4_state->crtc_w; 569 else 570 pix_per_line = vc4_state->src_w[0]; 571 572 if (!vc4_state->is_yuv) { 573 if (vc4_state->y_scaling[0] == VC4_SCALING_TPZ) 574 lbm = pix_per_line * 8; 575 else { 576 /* In special cases, this multiplier might be 12. */ 577 lbm = pix_per_line * 16; 578 } 579 } else { 580 /* There are cases for this going down to a multiplier 581 * of 2, but according to the firmware source, the 582 * table in the docs is somewhat wrong. 583 */ 584 lbm = pix_per_line * 16; 585 } 586 587 /* Align it to 64 or 128 (hvs5) bytes */ 588 lbm = roundup(lbm, vc4->is_vc5 ? 128 : 64); 589 590 /* Each "word" of the LBM memory contains 2 or 4 (hvs5) pixels */ 591 lbm /= vc4->is_vc5 ? 4 : 2; 592 593 return lbm; 594 } 595 596 static void vc4_write_scaling_parameters(struct drm_plane_state *state, 597 int channel) 598 { 599 struct vc4_plane_state *vc4_state = to_vc4_plane_state(state); 600 601 /* Ch0 H-PPF Word 0: Scaling Parameters */ 602 if (vc4_state->x_scaling[channel] == VC4_SCALING_PPF) { 603 vc4_write_ppf(vc4_state, 604 vc4_state->src_w[channel], vc4_state->crtc_w); 605 } 606 607 /* Ch0 V-PPF Words 0-1: Scaling Parameters, Context */ 608 if (vc4_state->y_scaling[channel] == VC4_SCALING_PPF) { 609 vc4_write_ppf(vc4_state, 610 vc4_state->src_h[channel], vc4_state->crtc_h); 611 vc4_dlist_write(vc4_state, 0xc0c0c0c0); 612 } 613 614 /* Ch0 H-TPZ Words 0-1: Scaling Parameters, Recip */ 615 if (vc4_state->x_scaling[channel] == VC4_SCALING_TPZ) { 616 vc4_write_tpz(vc4_state, 617 vc4_state->src_w[channel], vc4_state->crtc_w); 618 } 619 620 /* Ch0 V-TPZ Words 0-2: Scaling Parameters, Recip, Context */ 621 if (vc4_state->y_scaling[channel] == VC4_SCALING_TPZ) { 622 vc4_write_tpz(vc4_state, 623 vc4_state->src_h[channel], vc4_state->crtc_h); 624 vc4_dlist_write(vc4_state, 0xc0c0c0c0); 625 } 626 } 627 628 static void vc4_plane_calc_load(struct drm_plane_state *state) 629 { 630 unsigned int hvs_load_shift, vrefresh, i; 631 struct drm_framebuffer *fb = state->fb; 632 struct vc4_plane_state *vc4_state; 633 struct drm_crtc_state *crtc_state; 634 unsigned int vscale_factor; 635 636 vc4_state = to_vc4_plane_state(state); 637 crtc_state = drm_atomic_get_existing_crtc_state(state->state, 638 state->crtc); 639 vrefresh = drm_mode_vrefresh(&crtc_state->adjusted_mode); 640 641 /* The HVS is able to process 2 pixels/cycle when scaling the source, 642 * 4 pixels/cycle otherwise. 643 * Alpha blending step seems to be pipelined and it's always operating 644 * at 4 pixels/cycle, so the limiting aspect here seems to be the 645 * scaler block. 646 * HVS load is expressed in clk-cycles/sec (AKA Hz). 647 */ 648 if (vc4_state->x_scaling[0] != VC4_SCALING_NONE || 649 vc4_state->x_scaling[1] != VC4_SCALING_NONE || 650 vc4_state->y_scaling[0] != VC4_SCALING_NONE || 651 vc4_state->y_scaling[1] != VC4_SCALING_NONE) 652 hvs_load_shift = 1; 653 else 654 hvs_load_shift = 2; 655 656 vc4_state->membus_load = 0; 657 vc4_state->hvs_load = 0; 658 for (i = 0; i < fb->format->num_planes; i++) { 659 /* Even if the bandwidth/plane required for a single frame is 660 * 661 * vc4_state->src_w[i] * vc4_state->src_h[i] * cpp * vrefresh 662 * 663 * when downscaling, we have to read more pixels per line in 664 * the time frame reserved for a single line, so the bandwidth 665 * demand can be punctually higher. To account for that, we 666 * calculate the down-scaling factor and multiply the plane 667 * load by this number. We're likely over-estimating the read 668 * demand, but that's better than under-estimating it. 669 */ 670 vscale_factor = DIV_ROUND_UP(vc4_state->src_h[i], 671 vc4_state->crtc_h); 672 vc4_state->membus_load += vc4_state->src_w[i] * 673 vc4_state->src_h[i] * vscale_factor * 674 fb->format->cpp[i]; 675 vc4_state->hvs_load += vc4_state->crtc_h * vc4_state->crtc_w; 676 } 677 678 vc4_state->hvs_load *= vrefresh; 679 vc4_state->hvs_load >>= hvs_load_shift; 680 vc4_state->membus_load *= vrefresh; 681 } 682 683 static int vc4_plane_allocate_lbm(struct drm_plane_state *state) 684 { 685 struct vc4_dev *vc4 = to_vc4_dev(state->plane->dev); 686 struct vc4_plane_state *vc4_state = to_vc4_plane_state(state); 687 unsigned long irqflags; 688 u32 lbm_size; 689 690 lbm_size = vc4_lbm_size(state); 691 if (!lbm_size) 692 return 0; 693 694 if (WARN_ON(!vc4_state->lbm_offset)) 695 return -EINVAL; 696 697 /* Allocate the LBM memory that the HVS will use for temporary 698 * storage due to our scaling/format conversion. 699 */ 700 if (!drm_mm_node_allocated(&vc4_state->lbm)) { 701 int ret; 702 703 spin_lock_irqsave(&vc4->hvs->mm_lock, irqflags); 704 ret = drm_mm_insert_node_generic(&vc4->hvs->lbm_mm, 705 &vc4_state->lbm, 706 lbm_size, 707 vc4->is_vc5 ? 64 : 32, 708 0, 0); 709 spin_unlock_irqrestore(&vc4->hvs->mm_lock, irqflags); 710 711 if (ret) 712 return ret; 713 } else { 714 WARN_ON_ONCE(lbm_size != vc4_state->lbm.size); 715 } 716 717 vc4_state->dlist[vc4_state->lbm_offset] = vc4_state->lbm.start; 718 719 return 0; 720 } 721 722 /* 723 * The colorspace conversion matrices are held in 3 entries in the dlist. 724 * Create an array of them, with entries for each full and limited mode, and 725 * each supported colorspace. 726 */ 727 static const u32 colorspace_coeffs[2][DRM_COLOR_ENCODING_MAX][3] = { 728 { 729 /* Limited range */ 730 { 731 /* BT601 */ 732 SCALER_CSC0_ITR_R_601_5, 733 SCALER_CSC1_ITR_R_601_5, 734 SCALER_CSC2_ITR_R_601_5, 735 }, { 736 /* BT709 */ 737 SCALER_CSC0_ITR_R_709_3, 738 SCALER_CSC1_ITR_R_709_3, 739 SCALER_CSC2_ITR_R_709_3, 740 }, { 741 /* BT2020 */ 742 SCALER_CSC0_ITR_R_2020, 743 SCALER_CSC1_ITR_R_2020, 744 SCALER_CSC2_ITR_R_2020, 745 } 746 }, { 747 /* Full range */ 748 { 749 /* JFIF */ 750 SCALER_CSC0_JPEG_JFIF, 751 SCALER_CSC1_JPEG_JFIF, 752 SCALER_CSC2_JPEG_JFIF, 753 }, { 754 /* BT709 */ 755 SCALER_CSC0_ITR_R_709_3_FR, 756 SCALER_CSC1_ITR_R_709_3_FR, 757 SCALER_CSC2_ITR_R_709_3_FR, 758 }, { 759 /* BT2020 */ 760 SCALER_CSC0_ITR_R_2020_FR, 761 SCALER_CSC1_ITR_R_2020_FR, 762 SCALER_CSC2_ITR_R_2020_FR, 763 } 764 } 765 }; 766 767 static u32 vc4_hvs4_get_alpha_blend_mode(struct drm_plane_state *state) 768 { 769 if (!state->fb->format->has_alpha) 770 return VC4_SET_FIELD(SCALER_POS2_ALPHA_MODE_FIXED, 771 SCALER_POS2_ALPHA_MODE); 772 773 switch (state->pixel_blend_mode) { 774 case DRM_MODE_BLEND_PIXEL_NONE: 775 return VC4_SET_FIELD(SCALER_POS2_ALPHA_MODE_FIXED, 776 SCALER_POS2_ALPHA_MODE); 777 default: 778 case DRM_MODE_BLEND_PREMULTI: 779 return VC4_SET_FIELD(SCALER_POS2_ALPHA_MODE_PIPELINE, 780 SCALER_POS2_ALPHA_MODE) | 781 SCALER_POS2_ALPHA_PREMULT; 782 case DRM_MODE_BLEND_COVERAGE: 783 return VC4_SET_FIELD(SCALER_POS2_ALPHA_MODE_PIPELINE, 784 SCALER_POS2_ALPHA_MODE); 785 } 786 } 787 788 static u32 vc4_hvs5_get_alpha_blend_mode(struct drm_plane_state *state) 789 { 790 if (!state->fb->format->has_alpha) 791 return VC4_SET_FIELD(SCALER5_CTL2_ALPHA_MODE_FIXED, 792 SCALER5_CTL2_ALPHA_MODE); 793 794 switch (state->pixel_blend_mode) { 795 case DRM_MODE_BLEND_PIXEL_NONE: 796 return VC4_SET_FIELD(SCALER5_CTL2_ALPHA_MODE_FIXED, 797 SCALER5_CTL2_ALPHA_MODE); 798 default: 799 case DRM_MODE_BLEND_PREMULTI: 800 return VC4_SET_FIELD(SCALER5_CTL2_ALPHA_MODE_PIPELINE, 801 SCALER5_CTL2_ALPHA_MODE) | 802 SCALER5_CTL2_ALPHA_PREMULT; 803 case DRM_MODE_BLEND_COVERAGE: 804 return VC4_SET_FIELD(SCALER5_CTL2_ALPHA_MODE_PIPELINE, 805 SCALER5_CTL2_ALPHA_MODE); 806 } 807 } 808 809 /* Writes out a full display list for an active plane to the plane's 810 * private dlist state. 811 */ 812 static int vc4_plane_mode_set(struct drm_plane *plane, 813 struct drm_plane_state *state) 814 { 815 struct vc4_dev *vc4 = to_vc4_dev(plane->dev); 816 struct vc4_plane_state *vc4_state = to_vc4_plane_state(state); 817 struct drm_framebuffer *fb = state->fb; 818 u32 ctl0_offset = vc4_state->dlist_count; 819 const struct hvs_format *format = vc4_get_hvs_format(fb->format->format); 820 u64 base_format_mod = fourcc_mod_broadcom_mod(fb->modifier); 821 int num_planes = fb->format->num_planes; 822 u32 h_subsample = fb->format->hsub; 823 u32 v_subsample = fb->format->vsub; 824 bool mix_plane_alpha; 825 bool covers_screen; 826 u32 scl0, scl1, pitch0; 827 u32 tiling, src_y; 828 u32 hvs_format = format->hvs; 829 unsigned int rotation; 830 int ret, i; 831 832 if (vc4_state->dlist_initialized) 833 return 0; 834 835 ret = vc4_plane_setup_clipping_and_scaling(state); 836 if (ret) 837 return ret; 838 839 /* SCL1 is used for Cb/Cr scaling of planar formats. For RGB 840 * and 4:4:4, scl1 should be set to scl0 so both channels of 841 * the scaler do the same thing. For YUV, the Y plane needs 842 * to be put in channel 1 and Cb/Cr in channel 0, so we swap 843 * the scl fields here. 844 */ 845 if (num_planes == 1) { 846 scl0 = vc4_get_scl_field(state, 0); 847 scl1 = scl0; 848 } else { 849 scl0 = vc4_get_scl_field(state, 1); 850 scl1 = vc4_get_scl_field(state, 0); 851 } 852 853 rotation = drm_rotation_simplify(state->rotation, 854 DRM_MODE_ROTATE_0 | 855 DRM_MODE_REFLECT_X | 856 DRM_MODE_REFLECT_Y); 857 858 /* We must point to the last line when Y reflection is enabled. */ 859 src_y = vc4_state->src_y; 860 if (rotation & DRM_MODE_REFLECT_Y) 861 src_y += vc4_state->src_h[0] - 1; 862 863 switch (base_format_mod) { 864 case DRM_FORMAT_MOD_LINEAR: 865 tiling = SCALER_CTL0_TILING_LINEAR; 866 pitch0 = VC4_SET_FIELD(fb->pitches[0], SCALER_SRC_PITCH); 867 868 /* Adjust the base pointer to the first pixel to be scanned 869 * out. 870 */ 871 for (i = 0; i < num_planes; i++) { 872 vc4_state->offsets[i] += src_y / 873 (i ? v_subsample : 1) * 874 fb->pitches[i]; 875 876 vc4_state->offsets[i] += vc4_state->src_x / 877 (i ? h_subsample : 1) * 878 fb->format->cpp[i]; 879 } 880 881 break; 882 883 case DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED: { 884 u32 tile_size_shift = 12; /* T tiles are 4kb */ 885 /* Whole-tile offsets, mostly for setting the pitch. */ 886 u32 tile_w_shift = fb->format->cpp[0] == 2 ? 6 : 5; 887 u32 tile_h_shift = 5; /* 16 and 32bpp are 32 pixels high */ 888 u32 tile_w_mask = (1 << tile_w_shift) - 1; 889 /* The height mask on 32-bit-per-pixel tiles is 63, i.e. twice 890 * the height (in pixels) of a 4k tile. 891 */ 892 u32 tile_h_mask = (2 << tile_h_shift) - 1; 893 /* For T-tiled, the FB pitch is "how many bytes from one row to 894 * the next, such that 895 * 896 * pitch * tile_h == tile_size * tiles_per_row 897 */ 898 u32 tiles_w = fb->pitches[0] >> (tile_size_shift - tile_h_shift); 899 u32 tiles_l = vc4_state->src_x >> tile_w_shift; 900 u32 tiles_r = tiles_w - tiles_l; 901 u32 tiles_t = src_y >> tile_h_shift; 902 /* Intra-tile offsets, which modify the base address (the 903 * SCALER_PITCH0_TILE_Y_OFFSET tells HVS how to walk from that 904 * base address). 905 */ 906 u32 tile_y = (src_y >> 4) & 1; 907 u32 subtile_y = (src_y >> 2) & 3; 908 u32 utile_y = src_y & 3; 909 u32 x_off = vc4_state->src_x & tile_w_mask; 910 u32 y_off = src_y & tile_h_mask; 911 912 /* When Y reflection is requested we must set the 913 * SCALER_PITCH0_TILE_LINE_DIR flag to tell HVS that all lines 914 * after the initial one should be fetched in descending order, 915 * which makes sense since we start from the last line and go 916 * backward. 917 * Don't know why we need y_off = max_y_off - y_off, but it's 918 * definitely required (I guess it's also related to the "going 919 * backward" situation). 920 */ 921 if (rotation & DRM_MODE_REFLECT_Y) { 922 y_off = tile_h_mask - y_off; 923 pitch0 = SCALER_PITCH0_TILE_LINE_DIR; 924 } else { 925 pitch0 = 0; 926 } 927 928 tiling = SCALER_CTL0_TILING_256B_OR_T; 929 pitch0 |= (VC4_SET_FIELD(x_off, SCALER_PITCH0_SINK_PIX) | 930 VC4_SET_FIELD(y_off, SCALER_PITCH0_TILE_Y_OFFSET) | 931 VC4_SET_FIELD(tiles_l, SCALER_PITCH0_TILE_WIDTH_L) | 932 VC4_SET_FIELD(tiles_r, SCALER_PITCH0_TILE_WIDTH_R)); 933 vc4_state->offsets[0] += tiles_t * (tiles_w << tile_size_shift); 934 vc4_state->offsets[0] += subtile_y << 8; 935 vc4_state->offsets[0] += utile_y << 4; 936 937 /* Rows of tiles alternate left-to-right and right-to-left. */ 938 if (tiles_t & 1) { 939 pitch0 |= SCALER_PITCH0_TILE_INITIAL_LINE_DIR; 940 vc4_state->offsets[0] += (tiles_w - tiles_l) << 941 tile_size_shift; 942 vc4_state->offsets[0] -= (1 + !tile_y) << 10; 943 } else { 944 vc4_state->offsets[0] += tiles_l << tile_size_shift; 945 vc4_state->offsets[0] += tile_y << 10; 946 } 947 948 break; 949 } 950 951 case DRM_FORMAT_MOD_BROADCOM_SAND64: 952 case DRM_FORMAT_MOD_BROADCOM_SAND128: 953 case DRM_FORMAT_MOD_BROADCOM_SAND256: { 954 uint32_t param = fourcc_mod_broadcom_param(fb->modifier); 955 956 if (param > SCALER_TILE_HEIGHT_MASK) { 957 DRM_DEBUG_KMS("SAND height too large (%d)\n", 958 param); 959 return -EINVAL; 960 } 961 962 if (fb->format->format == DRM_FORMAT_P030) { 963 hvs_format = HVS_PIXEL_FORMAT_YCBCR_10BIT; 964 tiling = SCALER_CTL0_TILING_128B; 965 } else { 966 hvs_format = HVS_PIXEL_FORMAT_H264; 967 968 switch (base_format_mod) { 969 case DRM_FORMAT_MOD_BROADCOM_SAND64: 970 tiling = SCALER_CTL0_TILING_64B; 971 break; 972 case DRM_FORMAT_MOD_BROADCOM_SAND128: 973 tiling = SCALER_CTL0_TILING_128B; 974 break; 975 case DRM_FORMAT_MOD_BROADCOM_SAND256: 976 tiling = SCALER_CTL0_TILING_256B_OR_T; 977 break; 978 default: 979 return -EINVAL; 980 } 981 } 982 983 /* Adjust the base pointer to the first pixel to be scanned 984 * out. 985 * 986 * For P030, y_ptr [31:4] is the 128bit word for the start pixel 987 * y_ptr [3:0] is the pixel (0-11) contained within that 128bit 988 * word that should be taken as the first pixel. 989 * Ditto uv_ptr [31:4] vs [3:0], however [3:0] contains the 990 * element within the 128bit word, eg for pixel 3 the value 991 * should be 6. 992 */ 993 for (i = 0; i < num_planes; i++) { 994 u32 tile_w, tile, x_off, pix_per_tile; 995 996 if (fb->format->format == DRM_FORMAT_P030) { 997 /* 998 * Spec says: bits [31:4] of the given address 999 * should point to the 128-bit word containing 1000 * the desired starting pixel, and bits[3:0] 1001 * should be between 0 and 11, indicating which 1002 * of the 12-pixels in that 128-bit word is the 1003 * first pixel to be used 1004 */ 1005 u32 remaining_pixels = vc4_state->src_x % 96; 1006 u32 aligned = remaining_pixels / 12; 1007 u32 last_bits = remaining_pixels % 12; 1008 1009 x_off = aligned * 16 + last_bits; 1010 tile_w = 128; 1011 pix_per_tile = 96; 1012 } else { 1013 switch (base_format_mod) { 1014 case DRM_FORMAT_MOD_BROADCOM_SAND64: 1015 tile_w = 64; 1016 break; 1017 case DRM_FORMAT_MOD_BROADCOM_SAND128: 1018 tile_w = 128; 1019 break; 1020 case DRM_FORMAT_MOD_BROADCOM_SAND256: 1021 tile_w = 256; 1022 break; 1023 default: 1024 return -EINVAL; 1025 } 1026 pix_per_tile = tile_w / fb->format->cpp[0]; 1027 x_off = (vc4_state->src_x % pix_per_tile) / 1028 (i ? h_subsample : 1) * 1029 fb->format->cpp[i]; 1030 } 1031 1032 tile = vc4_state->src_x / pix_per_tile; 1033 1034 vc4_state->offsets[i] += param * tile_w * tile; 1035 vc4_state->offsets[i] += src_y / 1036 (i ? v_subsample : 1) * 1037 tile_w; 1038 vc4_state->offsets[i] += x_off & ~(i ? 1 : 0); 1039 } 1040 1041 pitch0 = VC4_SET_FIELD(param, SCALER_TILE_HEIGHT); 1042 break; 1043 } 1044 1045 default: 1046 DRM_DEBUG_KMS("Unsupported FB tiling flag 0x%16llx", 1047 (long long)fb->modifier); 1048 return -EINVAL; 1049 } 1050 1051 /* Don't waste cycles mixing with plane alpha if the set alpha 1052 * is opaque or there is no per-pixel alpha information. 1053 * In any case we use the alpha property value as the fixed alpha. 1054 */ 1055 mix_plane_alpha = state->alpha != DRM_BLEND_ALPHA_OPAQUE && 1056 fb->format->has_alpha; 1057 1058 if (!vc4->is_vc5) { 1059 /* Control word */ 1060 vc4_dlist_write(vc4_state, 1061 SCALER_CTL0_VALID | 1062 (rotation & DRM_MODE_REFLECT_X ? SCALER_CTL0_HFLIP : 0) | 1063 (rotation & DRM_MODE_REFLECT_Y ? SCALER_CTL0_VFLIP : 0) | 1064 VC4_SET_FIELD(SCALER_CTL0_RGBA_EXPAND_ROUND, SCALER_CTL0_RGBA_EXPAND) | 1065 (format->pixel_order << SCALER_CTL0_ORDER_SHIFT) | 1066 (hvs_format << SCALER_CTL0_PIXEL_FORMAT_SHIFT) | 1067 VC4_SET_FIELD(tiling, SCALER_CTL0_TILING) | 1068 (vc4_state->is_unity ? SCALER_CTL0_UNITY : 0) | 1069 VC4_SET_FIELD(scl0, SCALER_CTL0_SCL0) | 1070 VC4_SET_FIELD(scl1, SCALER_CTL0_SCL1)); 1071 1072 /* Position Word 0: Image Positions and Alpha Value */ 1073 vc4_state->pos0_offset = vc4_state->dlist_count; 1074 vc4_dlist_write(vc4_state, 1075 VC4_SET_FIELD(state->alpha >> 8, SCALER_POS0_FIXED_ALPHA) | 1076 VC4_SET_FIELD(vc4_state->crtc_x, SCALER_POS0_START_X) | 1077 VC4_SET_FIELD(vc4_state->crtc_y, SCALER_POS0_START_Y)); 1078 1079 /* Position Word 1: Scaled Image Dimensions. */ 1080 if (!vc4_state->is_unity) { 1081 vc4_dlist_write(vc4_state, 1082 VC4_SET_FIELD(vc4_state->crtc_w, 1083 SCALER_POS1_SCL_WIDTH) | 1084 VC4_SET_FIELD(vc4_state->crtc_h, 1085 SCALER_POS1_SCL_HEIGHT)); 1086 } 1087 1088 /* Position Word 2: Source Image Size, Alpha */ 1089 vc4_state->pos2_offset = vc4_state->dlist_count; 1090 vc4_dlist_write(vc4_state, 1091 (mix_plane_alpha ? SCALER_POS2_ALPHA_MIX : 0) | 1092 vc4_hvs4_get_alpha_blend_mode(state) | 1093 VC4_SET_FIELD(vc4_state->src_w[0], 1094 SCALER_POS2_WIDTH) | 1095 VC4_SET_FIELD(vc4_state->src_h[0], 1096 SCALER_POS2_HEIGHT)); 1097 1098 /* Position Word 3: Context. Written by the HVS. */ 1099 vc4_dlist_write(vc4_state, 0xc0c0c0c0); 1100 1101 } else { 1102 /* Control word */ 1103 vc4_dlist_write(vc4_state, 1104 SCALER_CTL0_VALID | 1105 (format->pixel_order_hvs5 << SCALER_CTL0_ORDER_SHIFT) | 1106 (hvs_format << SCALER_CTL0_PIXEL_FORMAT_SHIFT) | 1107 VC4_SET_FIELD(tiling, SCALER_CTL0_TILING) | 1108 (vc4_state->is_unity ? 1109 SCALER5_CTL0_UNITY : 0) | 1110 VC4_SET_FIELD(scl0, SCALER_CTL0_SCL0) | 1111 VC4_SET_FIELD(scl1, SCALER_CTL0_SCL1) | 1112 SCALER5_CTL0_ALPHA_EXPAND | 1113 SCALER5_CTL0_RGB_EXPAND); 1114 1115 /* Position Word 0: Image Positions and Alpha Value */ 1116 vc4_state->pos0_offset = vc4_state->dlist_count; 1117 vc4_dlist_write(vc4_state, 1118 (rotation & DRM_MODE_REFLECT_Y ? 1119 SCALER5_POS0_VFLIP : 0) | 1120 VC4_SET_FIELD(vc4_state->crtc_x, 1121 SCALER_POS0_START_X) | 1122 (rotation & DRM_MODE_REFLECT_X ? 1123 SCALER5_POS0_HFLIP : 0) | 1124 VC4_SET_FIELD(vc4_state->crtc_y, 1125 SCALER5_POS0_START_Y) 1126 ); 1127 1128 /* Control Word 2 */ 1129 vc4_dlist_write(vc4_state, 1130 VC4_SET_FIELD(state->alpha >> 4, 1131 SCALER5_CTL2_ALPHA) | 1132 vc4_hvs5_get_alpha_blend_mode(state) | 1133 (mix_plane_alpha ? 1134 SCALER5_CTL2_ALPHA_MIX : 0) 1135 ); 1136 1137 /* Position Word 1: Scaled Image Dimensions. */ 1138 if (!vc4_state->is_unity) { 1139 vc4_dlist_write(vc4_state, 1140 VC4_SET_FIELD(vc4_state->crtc_w, 1141 SCALER5_POS1_SCL_WIDTH) | 1142 VC4_SET_FIELD(vc4_state->crtc_h, 1143 SCALER5_POS1_SCL_HEIGHT)); 1144 } 1145 1146 /* Position Word 2: Source Image Size */ 1147 vc4_state->pos2_offset = vc4_state->dlist_count; 1148 vc4_dlist_write(vc4_state, 1149 VC4_SET_FIELD(vc4_state->src_w[0], 1150 SCALER5_POS2_WIDTH) | 1151 VC4_SET_FIELD(vc4_state->src_h[0], 1152 SCALER5_POS2_HEIGHT)); 1153 1154 /* Position Word 3: Context. Written by the HVS. */ 1155 vc4_dlist_write(vc4_state, 0xc0c0c0c0); 1156 } 1157 1158 1159 /* Pointer Word 0/1/2: RGB / Y / Cb / Cr Pointers 1160 * 1161 * The pointers may be any byte address. 1162 */ 1163 vc4_state->ptr0_offset = vc4_state->dlist_count; 1164 for (i = 0; i < num_planes; i++) 1165 vc4_dlist_write(vc4_state, vc4_state->offsets[i]); 1166 1167 /* Pointer Context Word 0/1/2: Written by the HVS */ 1168 for (i = 0; i < num_planes; i++) 1169 vc4_dlist_write(vc4_state, 0xc0c0c0c0); 1170 1171 /* Pitch word 0 */ 1172 vc4_dlist_write(vc4_state, pitch0); 1173 1174 /* Pitch word 1/2 */ 1175 for (i = 1; i < num_planes; i++) { 1176 if (hvs_format != HVS_PIXEL_FORMAT_H264 && 1177 hvs_format != HVS_PIXEL_FORMAT_YCBCR_10BIT) { 1178 vc4_dlist_write(vc4_state, 1179 VC4_SET_FIELD(fb->pitches[i], 1180 SCALER_SRC_PITCH)); 1181 } else { 1182 vc4_dlist_write(vc4_state, pitch0); 1183 } 1184 } 1185 1186 /* Colorspace conversion words */ 1187 if (vc4_state->is_yuv) { 1188 enum drm_color_encoding color_encoding = state->color_encoding; 1189 enum drm_color_range color_range = state->color_range; 1190 const u32 *ccm; 1191 1192 if (color_encoding >= DRM_COLOR_ENCODING_MAX) 1193 color_encoding = DRM_COLOR_YCBCR_BT601; 1194 if (color_range >= DRM_COLOR_RANGE_MAX) 1195 color_range = DRM_COLOR_YCBCR_LIMITED_RANGE; 1196 1197 ccm = colorspace_coeffs[color_range][color_encoding]; 1198 1199 vc4_dlist_write(vc4_state, ccm[0]); 1200 vc4_dlist_write(vc4_state, ccm[1]); 1201 vc4_dlist_write(vc4_state, ccm[2]); 1202 } 1203 1204 vc4_state->lbm_offset = 0; 1205 1206 if (vc4_state->x_scaling[0] != VC4_SCALING_NONE || 1207 vc4_state->x_scaling[1] != VC4_SCALING_NONE || 1208 vc4_state->y_scaling[0] != VC4_SCALING_NONE || 1209 vc4_state->y_scaling[1] != VC4_SCALING_NONE) { 1210 /* Reserve a slot for the LBM Base Address. The real value will 1211 * be set when calling vc4_plane_allocate_lbm(). 1212 */ 1213 if (vc4_state->y_scaling[0] != VC4_SCALING_NONE || 1214 vc4_state->y_scaling[1] != VC4_SCALING_NONE) { 1215 vc4_state->lbm_offset = vc4_state->dlist_count; 1216 vc4_dlist_counter_increment(vc4_state); 1217 } 1218 1219 if (num_planes > 1) { 1220 /* Emit Cb/Cr as channel 0 and Y as channel 1221 * 1. This matches how we set up scl0/scl1 1222 * above. 1223 */ 1224 vc4_write_scaling_parameters(state, 1); 1225 } 1226 vc4_write_scaling_parameters(state, 0); 1227 1228 /* If any PPF setup was done, then all the kernel 1229 * pointers get uploaded. 1230 */ 1231 if (vc4_state->x_scaling[0] == VC4_SCALING_PPF || 1232 vc4_state->y_scaling[0] == VC4_SCALING_PPF || 1233 vc4_state->x_scaling[1] == VC4_SCALING_PPF || 1234 vc4_state->y_scaling[1] == VC4_SCALING_PPF) { 1235 u32 kernel = VC4_SET_FIELD(vc4->hvs->mitchell_netravali_filter.start, 1236 SCALER_PPF_KERNEL_OFFSET); 1237 1238 /* HPPF plane 0 */ 1239 vc4_dlist_write(vc4_state, kernel); 1240 /* VPPF plane 0 */ 1241 vc4_dlist_write(vc4_state, kernel); 1242 /* HPPF plane 1 */ 1243 vc4_dlist_write(vc4_state, kernel); 1244 /* VPPF plane 1 */ 1245 vc4_dlist_write(vc4_state, kernel); 1246 } 1247 } 1248 1249 vc4_state->dlist[ctl0_offset] |= 1250 VC4_SET_FIELD(vc4_state->dlist_count, SCALER_CTL0_SIZE); 1251 1252 /* crtc_* are already clipped coordinates. */ 1253 covers_screen = vc4_state->crtc_x == 0 && vc4_state->crtc_y == 0 && 1254 vc4_state->crtc_w == state->crtc->mode.hdisplay && 1255 vc4_state->crtc_h == state->crtc->mode.vdisplay; 1256 /* Background fill might be necessary when the plane has per-pixel 1257 * alpha content or a non-opaque plane alpha and could blend from the 1258 * background or does not cover the entire screen. 1259 */ 1260 vc4_state->needs_bg_fill = fb->format->has_alpha || !covers_screen || 1261 state->alpha != DRM_BLEND_ALPHA_OPAQUE; 1262 1263 /* Flag the dlist as initialized to avoid checking it twice in case 1264 * the async update check already called vc4_plane_mode_set() and 1265 * decided to fallback to sync update because async update was not 1266 * possible. 1267 */ 1268 vc4_state->dlist_initialized = 1; 1269 1270 vc4_plane_calc_load(state); 1271 1272 return 0; 1273 } 1274 1275 /* If a modeset involves changing the setup of a plane, the atomic 1276 * infrastructure will call this to validate a proposed plane setup. 1277 * However, if a plane isn't getting updated, this (and the 1278 * corresponding vc4_plane_atomic_update) won't get called. Thus, we 1279 * compute the dlist here and have all active plane dlists get updated 1280 * in the CRTC's flush. 1281 */ 1282 static int vc4_plane_atomic_check(struct drm_plane *plane, 1283 struct drm_atomic_state *state) 1284 { 1285 struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state, 1286 plane); 1287 struct vc4_plane_state *vc4_state = to_vc4_plane_state(new_plane_state); 1288 int ret; 1289 1290 vc4_state->dlist_count = 0; 1291 1292 if (!plane_enabled(new_plane_state)) 1293 return 0; 1294 1295 ret = vc4_plane_mode_set(plane, new_plane_state); 1296 if (ret) 1297 return ret; 1298 1299 return vc4_plane_allocate_lbm(new_plane_state); 1300 } 1301 1302 static void vc4_plane_atomic_update(struct drm_plane *plane, 1303 struct drm_atomic_state *state) 1304 { 1305 /* No contents here. Since we don't know where in the CRTC's 1306 * dlist we should be stored, our dlist is uploaded to the 1307 * hardware with vc4_plane_write_dlist() at CRTC atomic_flush 1308 * time. 1309 */ 1310 } 1311 1312 u32 vc4_plane_write_dlist(struct drm_plane *plane, u32 __iomem *dlist) 1313 { 1314 struct vc4_plane_state *vc4_state = to_vc4_plane_state(plane->state); 1315 int i; 1316 int idx; 1317 1318 if (!drm_dev_enter(plane->dev, &idx)) 1319 goto out; 1320 1321 vc4_state->hw_dlist = dlist; 1322 1323 /* Can't memcpy_toio() because it needs to be 32-bit writes. */ 1324 for (i = 0; i < vc4_state->dlist_count; i++) 1325 writel(vc4_state->dlist[i], &dlist[i]); 1326 1327 drm_dev_exit(idx); 1328 1329 out: 1330 return vc4_state->dlist_count; 1331 } 1332 1333 u32 vc4_plane_dlist_size(const struct drm_plane_state *state) 1334 { 1335 const struct vc4_plane_state *vc4_state = 1336 container_of(state, typeof(*vc4_state), base); 1337 1338 return vc4_state->dlist_count; 1339 } 1340 1341 /* Updates the plane to immediately (well, once the FIFO needs 1342 * refilling) scan out from at a new framebuffer. 1343 */ 1344 void vc4_plane_async_set_fb(struct drm_plane *plane, struct drm_framebuffer *fb) 1345 { 1346 struct vc4_plane_state *vc4_state = to_vc4_plane_state(plane->state); 1347 struct drm_gem_dma_object *bo = drm_fb_dma_get_gem_obj(fb, 0); 1348 uint32_t addr; 1349 int idx; 1350 1351 if (!drm_dev_enter(plane->dev, &idx)) 1352 return; 1353 1354 /* We're skipping the address adjustment for negative origin, 1355 * because this is only called on the primary plane. 1356 */ 1357 WARN_ON_ONCE(plane->state->crtc_x < 0 || plane->state->crtc_y < 0); 1358 addr = bo->dma_addr + fb->offsets[0]; 1359 1360 /* Write the new address into the hardware immediately. The 1361 * scanout will start from this address as soon as the FIFO 1362 * needs to refill with pixels. 1363 */ 1364 writel(addr, &vc4_state->hw_dlist[vc4_state->ptr0_offset]); 1365 1366 /* Also update the CPU-side dlist copy, so that any later 1367 * atomic updates that don't do a new modeset on our plane 1368 * also use our updated address. 1369 */ 1370 vc4_state->dlist[vc4_state->ptr0_offset] = addr; 1371 1372 drm_dev_exit(idx); 1373 } 1374 1375 static void vc4_plane_atomic_async_update(struct drm_plane *plane, 1376 struct drm_atomic_state *state) 1377 { 1378 struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state, 1379 plane); 1380 struct vc4_plane_state *vc4_state, *new_vc4_state; 1381 int idx; 1382 1383 if (!drm_dev_enter(plane->dev, &idx)) 1384 return; 1385 1386 swap(plane->state->fb, new_plane_state->fb); 1387 plane->state->crtc_x = new_plane_state->crtc_x; 1388 plane->state->crtc_y = new_plane_state->crtc_y; 1389 plane->state->crtc_w = new_plane_state->crtc_w; 1390 plane->state->crtc_h = new_plane_state->crtc_h; 1391 plane->state->src_x = new_plane_state->src_x; 1392 plane->state->src_y = new_plane_state->src_y; 1393 plane->state->src_w = new_plane_state->src_w; 1394 plane->state->src_h = new_plane_state->src_h; 1395 plane->state->alpha = new_plane_state->alpha; 1396 plane->state->pixel_blend_mode = new_plane_state->pixel_blend_mode; 1397 plane->state->rotation = new_plane_state->rotation; 1398 plane->state->zpos = new_plane_state->zpos; 1399 plane->state->normalized_zpos = new_plane_state->normalized_zpos; 1400 plane->state->color_encoding = new_plane_state->color_encoding; 1401 plane->state->color_range = new_plane_state->color_range; 1402 plane->state->src = new_plane_state->src; 1403 plane->state->dst = new_plane_state->dst; 1404 plane->state->visible = new_plane_state->visible; 1405 1406 new_vc4_state = to_vc4_plane_state(new_plane_state); 1407 vc4_state = to_vc4_plane_state(plane->state); 1408 1409 vc4_state->crtc_x = new_vc4_state->crtc_x; 1410 vc4_state->crtc_y = new_vc4_state->crtc_y; 1411 vc4_state->crtc_h = new_vc4_state->crtc_h; 1412 vc4_state->crtc_w = new_vc4_state->crtc_w; 1413 vc4_state->src_x = new_vc4_state->src_x; 1414 vc4_state->src_y = new_vc4_state->src_y; 1415 memcpy(vc4_state->src_w, new_vc4_state->src_w, 1416 sizeof(vc4_state->src_w)); 1417 memcpy(vc4_state->src_h, new_vc4_state->src_h, 1418 sizeof(vc4_state->src_h)); 1419 memcpy(vc4_state->x_scaling, new_vc4_state->x_scaling, 1420 sizeof(vc4_state->x_scaling)); 1421 memcpy(vc4_state->y_scaling, new_vc4_state->y_scaling, 1422 sizeof(vc4_state->y_scaling)); 1423 vc4_state->is_unity = new_vc4_state->is_unity; 1424 vc4_state->is_yuv = new_vc4_state->is_yuv; 1425 memcpy(vc4_state->offsets, new_vc4_state->offsets, 1426 sizeof(vc4_state->offsets)); 1427 vc4_state->needs_bg_fill = new_vc4_state->needs_bg_fill; 1428 1429 /* Update the current vc4_state pos0, pos2 and ptr0 dlist entries. */ 1430 vc4_state->dlist[vc4_state->pos0_offset] = 1431 new_vc4_state->dlist[vc4_state->pos0_offset]; 1432 vc4_state->dlist[vc4_state->pos2_offset] = 1433 new_vc4_state->dlist[vc4_state->pos2_offset]; 1434 vc4_state->dlist[vc4_state->ptr0_offset] = 1435 new_vc4_state->dlist[vc4_state->ptr0_offset]; 1436 1437 /* Note that we can't just call vc4_plane_write_dlist() 1438 * because that would smash the context data that the HVS is 1439 * currently using. 1440 */ 1441 writel(vc4_state->dlist[vc4_state->pos0_offset], 1442 &vc4_state->hw_dlist[vc4_state->pos0_offset]); 1443 writel(vc4_state->dlist[vc4_state->pos2_offset], 1444 &vc4_state->hw_dlist[vc4_state->pos2_offset]); 1445 writel(vc4_state->dlist[vc4_state->ptr0_offset], 1446 &vc4_state->hw_dlist[vc4_state->ptr0_offset]); 1447 1448 drm_dev_exit(idx); 1449 } 1450 1451 static int vc4_plane_atomic_async_check(struct drm_plane *plane, 1452 struct drm_atomic_state *state) 1453 { 1454 struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state, 1455 plane); 1456 struct vc4_plane_state *old_vc4_state, *new_vc4_state; 1457 int ret; 1458 u32 i; 1459 1460 ret = vc4_plane_mode_set(plane, new_plane_state); 1461 if (ret) 1462 return ret; 1463 1464 old_vc4_state = to_vc4_plane_state(plane->state); 1465 new_vc4_state = to_vc4_plane_state(new_plane_state); 1466 1467 if (!new_vc4_state->hw_dlist) 1468 return -EINVAL; 1469 1470 if (old_vc4_state->dlist_count != new_vc4_state->dlist_count || 1471 old_vc4_state->pos0_offset != new_vc4_state->pos0_offset || 1472 old_vc4_state->pos2_offset != new_vc4_state->pos2_offset || 1473 old_vc4_state->ptr0_offset != new_vc4_state->ptr0_offset || 1474 vc4_lbm_size(plane->state) != vc4_lbm_size(new_plane_state)) 1475 return -EINVAL; 1476 1477 /* Only pos0, pos2 and ptr0 DWORDS can be updated in an async update 1478 * if anything else has changed, fallback to a sync update. 1479 */ 1480 for (i = 0; i < new_vc4_state->dlist_count; i++) { 1481 if (i == new_vc4_state->pos0_offset || 1482 i == new_vc4_state->pos2_offset || 1483 i == new_vc4_state->ptr0_offset || 1484 (new_vc4_state->lbm_offset && 1485 i == new_vc4_state->lbm_offset)) 1486 continue; 1487 1488 if (new_vc4_state->dlist[i] != old_vc4_state->dlist[i]) 1489 return -EINVAL; 1490 } 1491 1492 return 0; 1493 } 1494 1495 static int vc4_prepare_fb(struct drm_plane *plane, 1496 struct drm_plane_state *state) 1497 { 1498 struct vc4_bo *bo; 1499 1500 if (!state->fb) 1501 return 0; 1502 1503 bo = to_vc4_bo(&drm_fb_dma_get_gem_obj(state->fb, 0)->base); 1504 1505 drm_gem_plane_helper_prepare_fb(plane, state); 1506 1507 if (plane->state->fb == state->fb) 1508 return 0; 1509 1510 return vc4_bo_inc_usecnt(bo); 1511 } 1512 1513 static void vc4_cleanup_fb(struct drm_plane *plane, 1514 struct drm_plane_state *state) 1515 { 1516 struct vc4_bo *bo; 1517 1518 if (plane->state->fb == state->fb || !state->fb) 1519 return; 1520 1521 bo = to_vc4_bo(&drm_fb_dma_get_gem_obj(state->fb, 0)->base); 1522 vc4_bo_dec_usecnt(bo); 1523 } 1524 1525 static const struct drm_plane_helper_funcs vc4_plane_helper_funcs = { 1526 .atomic_check = vc4_plane_atomic_check, 1527 .atomic_update = vc4_plane_atomic_update, 1528 .prepare_fb = vc4_prepare_fb, 1529 .cleanup_fb = vc4_cleanup_fb, 1530 .atomic_async_check = vc4_plane_atomic_async_check, 1531 .atomic_async_update = vc4_plane_atomic_async_update, 1532 }; 1533 1534 static const struct drm_plane_helper_funcs vc5_plane_helper_funcs = { 1535 .atomic_check = vc4_plane_atomic_check, 1536 .atomic_update = vc4_plane_atomic_update, 1537 .atomic_async_check = vc4_plane_atomic_async_check, 1538 .atomic_async_update = vc4_plane_atomic_async_update, 1539 }; 1540 1541 static bool vc4_format_mod_supported(struct drm_plane *plane, 1542 uint32_t format, 1543 uint64_t modifier) 1544 { 1545 /* Support T_TILING for RGB formats only. */ 1546 switch (format) { 1547 case DRM_FORMAT_XRGB8888: 1548 case DRM_FORMAT_ARGB8888: 1549 case DRM_FORMAT_ABGR8888: 1550 case DRM_FORMAT_XBGR8888: 1551 case DRM_FORMAT_RGB565: 1552 case DRM_FORMAT_BGR565: 1553 case DRM_FORMAT_ARGB1555: 1554 case DRM_FORMAT_XRGB1555: 1555 switch (fourcc_mod_broadcom_mod(modifier)) { 1556 case DRM_FORMAT_MOD_LINEAR: 1557 case DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED: 1558 return true; 1559 default: 1560 return false; 1561 } 1562 case DRM_FORMAT_NV12: 1563 case DRM_FORMAT_NV21: 1564 switch (fourcc_mod_broadcom_mod(modifier)) { 1565 case DRM_FORMAT_MOD_LINEAR: 1566 case DRM_FORMAT_MOD_BROADCOM_SAND64: 1567 case DRM_FORMAT_MOD_BROADCOM_SAND128: 1568 case DRM_FORMAT_MOD_BROADCOM_SAND256: 1569 return true; 1570 default: 1571 return false; 1572 } 1573 case DRM_FORMAT_P030: 1574 switch (fourcc_mod_broadcom_mod(modifier)) { 1575 case DRM_FORMAT_MOD_BROADCOM_SAND128: 1576 return true; 1577 default: 1578 return false; 1579 } 1580 case DRM_FORMAT_RGBX1010102: 1581 case DRM_FORMAT_BGRX1010102: 1582 case DRM_FORMAT_RGBA1010102: 1583 case DRM_FORMAT_BGRA1010102: 1584 case DRM_FORMAT_XRGB4444: 1585 case DRM_FORMAT_ARGB4444: 1586 case DRM_FORMAT_XBGR4444: 1587 case DRM_FORMAT_ABGR4444: 1588 case DRM_FORMAT_RGBX4444: 1589 case DRM_FORMAT_RGBA4444: 1590 case DRM_FORMAT_BGRX4444: 1591 case DRM_FORMAT_BGRA4444: 1592 case DRM_FORMAT_RGB332: 1593 case DRM_FORMAT_BGR233: 1594 case DRM_FORMAT_YUV422: 1595 case DRM_FORMAT_YVU422: 1596 case DRM_FORMAT_YUV420: 1597 case DRM_FORMAT_YVU420: 1598 case DRM_FORMAT_NV16: 1599 case DRM_FORMAT_NV61: 1600 default: 1601 return (modifier == DRM_FORMAT_MOD_LINEAR); 1602 } 1603 } 1604 1605 static const struct drm_plane_funcs vc4_plane_funcs = { 1606 .update_plane = drm_atomic_helper_update_plane, 1607 .disable_plane = drm_atomic_helper_disable_plane, 1608 .reset = vc4_plane_reset, 1609 .atomic_duplicate_state = vc4_plane_duplicate_state, 1610 .atomic_destroy_state = vc4_plane_destroy_state, 1611 .format_mod_supported = vc4_format_mod_supported, 1612 }; 1613 1614 struct drm_plane *vc4_plane_init(struct drm_device *dev, 1615 enum drm_plane_type type, 1616 uint32_t possible_crtcs) 1617 { 1618 struct vc4_dev *vc4 = to_vc4_dev(dev); 1619 struct drm_plane *plane; 1620 struct vc4_plane *vc4_plane; 1621 u32 formats[ARRAY_SIZE(hvs_formats)]; 1622 int num_formats = 0; 1623 unsigned i; 1624 static const uint64_t modifiers[] = { 1625 DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED, 1626 DRM_FORMAT_MOD_BROADCOM_SAND128, 1627 DRM_FORMAT_MOD_BROADCOM_SAND64, 1628 DRM_FORMAT_MOD_BROADCOM_SAND256, 1629 DRM_FORMAT_MOD_LINEAR, 1630 DRM_FORMAT_MOD_INVALID 1631 }; 1632 1633 for (i = 0; i < ARRAY_SIZE(hvs_formats); i++) { 1634 if (!hvs_formats[i].hvs5_only || vc4->is_vc5) { 1635 formats[num_formats] = hvs_formats[i].drm; 1636 num_formats++; 1637 } 1638 } 1639 1640 vc4_plane = drmm_universal_plane_alloc(dev, struct vc4_plane, base, 1641 possible_crtcs, 1642 &vc4_plane_funcs, 1643 formats, num_formats, 1644 modifiers, type, NULL); 1645 if (IS_ERR(vc4_plane)) 1646 return ERR_CAST(vc4_plane); 1647 plane = &vc4_plane->base; 1648 1649 if (vc4->is_vc5) 1650 drm_plane_helper_add(plane, &vc5_plane_helper_funcs); 1651 else 1652 drm_plane_helper_add(plane, &vc4_plane_helper_funcs); 1653 1654 drm_plane_create_alpha_property(plane); 1655 drm_plane_create_blend_mode_property(plane, 1656 BIT(DRM_MODE_BLEND_PIXEL_NONE) | 1657 BIT(DRM_MODE_BLEND_PREMULTI) | 1658 BIT(DRM_MODE_BLEND_COVERAGE)); 1659 drm_plane_create_rotation_property(plane, DRM_MODE_ROTATE_0, 1660 DRM_MODE_ROTATE_0 | 1661 DRM_MODE_ROTATE_180 | 1662 DRM_MODE_REFLECT_X | 1663 DRM_MODE_REFLECT_Y); 1664 1665 drm_plane_create_color_properties(plane, 1666 BIT(DRM_COLOR_YCBCR_BT601) | 1667 BIT(DRM_COLOR_YCBCR_BT709) | 1668 BIT(DRM_COLOR_YCBCR_BT2020), 1669 BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) | 1670 BIT(DRM_COLOR_YCBCR_FULL_RANGE), 1671 DRM_COLOR_YCBCR_BT709, 1672 DRM_COLOR_YCBCR_LIMITED_RANGE); 1673 1674 if (type == DRM_PLANE_TYPE_PRIMARY) 1675 drm_plane_create_zpos_immutable_property(plane, 0); 1676 1677 return plane; 1678 } 1679 1680 #define VC4_NUM_OVERLAY_PLANES 16 1681 1682 int vc4_plane_create_additional_planes(struct drm_device *drm) 1683 { 1684 struct drm_plane *cursor_plane; 1685 struct drm_crtc *crtc; 1686 unsigned int i; 1687 1688 /* Set up some arbitrary number of planes. We're not limited 1689 * by a set number of physical registers, just the space in 1690 * the HVS (16k) and how small an plane can be (28 bytes). 1691 * However, each plane we set up takes up some memory, and 1692 * increases the cost of looping over planes, which atomic 1693 * modesetting does quite a bit. As a result, we pick a 1694 * modest number of planes to expose, that should hopefully 1695 * still cover any sane usecase. 1696 */ 1697 for (i = 0; i < VC4_NUM_OVERLAY_PLANES; i++) { 1698 struct drm_plane *plane = 1699 vc4_plane_init(drm, DRM_PLANE_TYPE_OVERLAY, 1700 GENMASK(drm->mode_config.num_crtc - 1, 0)); 1701 1702 if (IS_ERR(plane)) 1703 continue; 1704 1705 /* Create zpos property. Max of all the overlays + 1 primary + 1706 * 1 cursor plane on a crtc. 1707 */ 1708 drm_plane_create_zpos_property(plane, i + 1, 1, 1709 VC4_NUM_OVERLAY_PLANES + 1); 1710 } 1711 1712 drm_for_each_crtc(crtc, drm) { 1713 /* Set up the legacy cursor after overlay initialization, 1714 * since the zpos fallback is that planes are rendered by plane 1715 * ID order, and that then puts the cursor on top. 1716 */ 1717 cursor_plane = vc4_plane_init(drm, DRM_PLANE_TYPE_CURSOR, 1718 drm_crtc_mask(crtc)); 1719 if (!IS_ERR(cursor_plane)) { 1720 crtc->cursor = cursor_plane; 1721 1722 drm_plane_create_zpos_property(cursor_plane, 1723 VC4_NUM_OVERLAY_PLANES + 1, 1724 1, 1725 VC4_NUM_OVERLAY_PLANES + 1); 1726 } 1727 } 1728 1729 return 0; 1730 } 1731