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