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