1 /* 2 * Copyright (C) 2015 Broadcom 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License version 2 as 6 * published by the Free Software Foundation. 7 */ 8 9 /** 10 * DOC: VC4 plane module 11 * 12 * Each DRM plane is a layer of pixels being scanned out by the HVS. 13 * 14 * At atomic modeset check time, we compute the HVS display element 15 * state that would be necessary for displaying the plane (giving us a 16 * chance to figure out if a plane configuration is invalid), then at 17 * atomic flush time the CRTC will ask us to write our element state 18 * into the region of the HVS that it has allocated for us. 19 */ 20 21 #include <drm/drm_atomic.h> 22 #include <drm/drm_atomic_helper.h> 23 #include <drm/drm_fb_cma_helper.h> 24 #include <drm/drm_plane_helper.h> 25 #include <drm/drm_atomic_uapi.h> 26 27 #include "uapi/drm/vc4_drm.h" 28 #include "vc4_drv.h" 29 #include "vc4_regs.h" 30 31 static const struct hvs_format { 32 u32 drm; /* DRM_FORMAT_* */ 33 u32 hvs; /* HVS_FORMAT_* */ 34 u32 pixel_order; 35 } hvs_formats[] = { 36 { 37 .drm = DRM_FORMAT_XRGB8888, .hvs = HVS_PIXEL_FORMAT_RGBA8888, 38 .pixel_order = HVS_PIXEL_ORDER_ABGR, 39 }, 40 { 41 .drm = DRM_FORMAT_ARGB8888, .hvs = HVS_PIXEL_FORMAT_RGBA8888, 42 .pixel_order = HVS_PIXEL_ORDER_ABGR, 43 }, 44 { 45 .drm = DRM_FORMAT_ABGR8888, .hvs = HVS_PIXEL_FORMAT_RGBA8888, 46 .pixel_order = HVS_PIXEL_ORDER_ARGB, 47 }, 48 { 49 .drm = DRM_FORMAT_XBGR8888, .hvs = HVS_PIXEL_FORMAT_RGBA8888, 50 .pixel_order = HVS_PIXEL_ORDER_ARGB, 51 }, 52 { 53 .drm = DRM_FORMAT_RGB565, .hvs = HVS_PIXEL_FORMAT_RGB565, 54 .pixel_order = HVS_PIXEL_ORDER_XRGB, 55 }, 56 { 57 .drm = DRM_FORMAT_BGR565, .hvs = HVS_PIXEL_FORMAT_RGB565, 58 .pixel_order = HVS_PIXEL_ORDER_XBGR, 59 }, 60 { 61 .drm = DRM_FORMAT_ARGB1555, .hvs = HVS_PIXEL_FORMAT_RGBA5551, 62 .pixel_order = HVS_PIXEL_ORDER_ABGR, 63 }, 64 { 65 .drm = DRM_FORMAT_XRGB1555, .hvs = HVS_PIXEL_FORMAT_RGBA5551, 66 .pixel_order = HVS_PIXEL_ORDER_ABGR, 67 }, 68 { 69 .drm = DRM_FORMAT_RGB888, .hvs = HVS_PIXEL_FORMAT_RGB888, 70 .pixel_order = HVS_PIXEL_ORDER_XRGB, 71 }, 72 { 73 .drm = DRM_FORMAT_BGR888, .hvs = HVS_PIXEL_FORMAT_RGB888, 74 .pixel_order = HVS_PIXEL_ORDER_XBGR, 75 }, 76 { 77 .drm = DRM_FORMAT_YUV422, 78 .hvs = HVS_PIXEL_FORMAT_YCBCR_YUV422_3PLANE, 79 .pixel_order = HVS_PIXEL_ORDER_XYCBCR, 80 }, 81 { 82 .drm = DRM_FORMAT_YVU422, 83 .hvs = HVS_PIXEL_FORMAT_YCBCR_YUV422_3PLANE, 84 .pixel_order = HVS_PIXEL_ORDER_XYCRCB, 85 }, 86 { 87 .drm = DRM_FORMAT_YUV420, 88 .hvs = HVS_PIXEL_FORMAT_YCBCR_YUV420_3PLANE, 89 .pixel_order = HVS_PIXEL_ORDER_XYCBCR, 90 }, 91 { 92 .drm = DRM_FORMAT_YVU420, 93 .hvs = HVS_PIXEL_FORMAT_YCBCR_YUV420_3PLANE, 94 .pixel_order = HVS_PIXEL_ORDER_XYCRCB, 95 }, 96 { 97 .drm = DRM_FORMAT_NV12, 98 .hvs = HVS_PIXEL_FORMAT_YCBCR_YUV420_2PLANE, 99 .pixel_order = HVS_PIXEL_ORDER_XYCBCR, 100 }, 101 { 102 .drm = DRM_FORMAT_NV21, 103 .hvs = HVS_PIXEL_FORMAT_YCBCR_YUV420_2PLANE, 104 .pixel_order = HVS_PIXEL_ORDER_XYCRCB, 105 }, 106 { 107 .drm = DRM_FORMAT_NV16, 108 .hvs = HVS_PIXEL_FORMAT_YCBCR_YUV422_2PLANE, 109 .pixel_order = HVS_PIXEL_ORDER_XYCBCR, 110 }, 111 { 112 .drm = DRM_FORMAT_NV61, 113 .hvs = HVS_PIXEL_FORMAT_YCBCR_YUV422_2PLANE, 114 .pixel_order = HVS_PIXEL_ORDER_XYCRCB, 115 }, 116 }; 117 118 static const struct hvs_format *vc4_get_hvs_format(u32 drm_format) 119 { 120 unsigned i; 121 122 for (i = 0; i < ARRAY_SIZE(hvs_formats); i++) { 123 if (hvs_formats[i].drm == drm_format) 124 return &hvs_formats[i]; 125 } 126 127 return NULL; 128 } 129 130 static enum vc4_scaling_mode vc4_get_scaling_mode(u32 src, u32 dst) 131 { 132 if (dst == src) 133 return VC4_SCALING_NONE; 134 if (3 * dst >= 2 * src) 135 return VC4_SCALING_PPF; 136 else 137 return VC4_SCALING_TPZ; 138 } 139 140 static bool plane_enabled(struct drm_plane_state *state) 141 { 142 return state->fb && state->crtc; 143 } 144 145 static struct drm_plane_state *vc4_plane_duplicate_state(struct drm_plane *plane) 146 { 147 struct vc4_plane_state *vc4_state; 148 149 if (WARN_ON(!plane->state)) 150 return NULL; 151 152 vc4_state = kmemdup(plane->state, sizeof(*vc4_state), GFP_KERNEL); 153 if (!vc4_state) 154 return NULL; 155 156 memset(&vc4_state->lbm, 0, sizeof(vc4_state->lbm)); 157 158 __drm_atomic_helper_plane_duplicate_state(plane, &vc4_state->base); 159 160 if (vc4_state->dlist) { 161 vc4_state->dlist = kmemdup(vc4_state->dlist, 162 vc4_state->dlist_count * 4, 163 GFP_KERNEL); 164 if (!vc4_state->dlist) { 165 kfree(vc4_state); 166 return NULL; 167 } 168 vc4_state->dlist_size = vc4_state->dlist_count; 169 } 170 171 return &vc4_state->base; 172 } 173 174 static void vc4_plane_destroy_state(struct drm_plane *plane, 175 struct drm_plane_state *state) 176 { 177 struct vc4_dev *vc4 = to_vc4_dev(plane->dev); 178 struct vc4_plane_state *vc4_state = to_vc4_plane_state(state); 179 180 if (vc4_state->lbm.allocated) { 181 unsigned long irqflags; 182 183 spin_lock_irqsave(&vc4->hvs->mm_lock, irqflags); 184 drm_mm_remove_node(&vc4_state->lbm); 185 spin_unlock_irqrestore(&vc4->hvs->mm_lock, irqflags); 186 } 187 188 kfree(vc4_state->dlist); 189 __drm_atomic_helper_plane_destroy_state(&vc4_state->base); 190 kfree(state); 191 } 192 193 /* Called during init to allocate the plane's atomic state. */ 194 static void vc4_plane_reset(struct drm_plane *plane) 195 { 196 struct vc4_plane_state *vc4_state; 197 198 WARN_ON(plane->state); 199 200 vc4_state = kzalloc(sizeof(*vc4_state), GFP_KERNEL); 201 if (!vc4_state) 202 return; 203 204 __drm_atomic_helper_plane_reset(plane, &vc4_state->base); 205 } 206 207 static void vc4_dlist_write(struct vc4_plane_state *vc4_state, u32 val) 208 { 209 if (vc4_state->dlist_count == vc4_state->dlist_size) { 210 u32 new_size = max(4u, vc4_state->dlist_count * 2); 211 u32 *new_dlist = kmalloc_array(new_size, 4, GFP_KERNEL); 212 213 if (!new_dlist) 214 return; 215 memcpy(new_dlist, vc4_state->dlist, vc4_state->dlist_count * 4); 216 217 kfree(vc4_state->dlist); 218 vc4_state->dlist = new_dlist; 219 vc4_state->dlist_size = new_size; 220 } 221 222 vc4_state->dlist[vc4_state->dlist_count++] = val; 223 } 224 225 /* Returns the scl0/scl1 field based on whether the dimensions need to 226 * be up/down/non-scaled. 227 * 228 * This is a replication of a table from the spec. 229 */ 230 static u32 vc4_get_scl_field(struct drm_plane_state *state, int plane) 231 { 232 struct vc4_plane_state *vc4_state = to_vc4_plane_state(state); 233 234 switch (vc4_state->x_scaling[plane] << 2 | vc4_state->y_scaling[plane]) { 235 case VC4_SCALING_PPF << 2 | VC4_SCALING_PPF: 236 return SCALER_CTL0_SCL_H_PPF_V_PPF; 237 case VC4_SCALING_TPZ << 2 | VC4_SCALING_PPF: 238 return SCALER_CTL0_SCL_H_TPZ_V_PPF; 239 case VC4_SCALING_PPF << 2 | VC4_SCALING_TPZ: 240 return SCALER_CTL0_SCL_H_PPF_V_TPZ; 241 case VC4_SCALING_TPZ << 2 | VC4_SCALING_TPZ: 242 return SCALER_CTL0_SCL_H_TPZ_V_TPZ; 243 case VC4_SCALING_PPF << 2 | VC4_SCALING_NONE: 244 return SCALER_CTL0_SCL_H_PPF_V_NONE; 245 case VC4_SCALING_NONE << 2 | VC4_SCALING_PPF: 246 return SCALER_CTL0_SCL_H_NONE_V_PPF; 247 case VC4_SCALING_NONE << 2 | VC4_SCALING_TPZ: 248 return SCALER_CTL0_SCL_H_NONE_V_TPZ; 249 case VC4_SCALING_TPZ << 2 | VC4_SCALING_NONE: 250 return SCALER_CTL0_SCL_H_TPZ_V_NONE; 251 default: 252 case VC4_SCALING_NONE << 2 | VC4_SCALING_NONE: 253 /* The unity case is independently handled by 254 * SCALER_CTL0_UNITY. 255 */ 256 return 0; 257 } 258 } 259 260 static int vc4_plane_setup_clipping_and_scaling(struct drm_plane_state *state) 261 { 262 struct drm_plane *plane = state->plane; 263 struct vc4_plane_state *vc4_state = to_vc4_plane_state(state); 264 struct drm_framebuffer *fb = state->fb; 265 struct drm_gem_cma_object *bo = drm_fb_cma_get_gem_obj(fb, 0); 266 u32 subpixel_src_mask = (1 << 16) - 1; 267 u32 format = fb->format->format; 268 int num_planes = fb->format->num_planes; 269 int min_scale = 1, max_scale = INT_MAX; 270 struct drm_crtc_state *crtc_state; 271 u32 h_subsample, v_subsample; 272 int i, ret; 273 274 crtc_state = drm_atomic_get_existing_crtc_state(state->state, 275 state->crtc); 276 if (!crtc_state) { 277 DRM_DEBUG_KMS("Invalid crtc state\n"); 278 return -EINVAL; 279 } 280 281 /* No configuring scaling on the cursor plane, since it gets 282 * non-vblank-synced updates, and scaling requires LBM changes which 283 * have to be vblank-synced. 284 */ 285 if (plane->type == DRM_PLANE_TYPE_CURSOR) { 286 min_scale = DRM_PLANE_HELPER_NO_SCALING; 287 max_scale = DRM_PLANE_HELPER_NO_SCALING; 288 } else { 289 min_scale = 1; 290 max_scale = INT_MAX; 291 } 292 293 ret = drm_atomic_helper_check_plane_state(state, crtc_state, 294 min_scale, max_scale, 295 true, true); 296 if (ret) 297 return ret; 298 299 h_subsample = drm_format_horz_chroma_subsampling(format); 300 v_subsample = drm_format_vert_chroma_subsampling(format); 301 302 for (i = 0; i < num_planes; i++) 303 vc4_state->offsets[i] = bo->paddr + fb->offsets[i]; 304 305 /* We don't support subpixel source positioning for scaling. */ 306 if ((state->src.x1 & subpixel_src_mask) || 307 (state->src.x2 & subpixel_src_mask) || 308 (state->src.y1 & subpixel_src_mask) || 309 (state->src.y2 & subpixel_src_mask)) { 310 return -EINVAL; 311 } 312 313 vc4_state->src_x = state->src.x1 >> 16; 314 vc4_state->src_y = state->src.y1 >> 16; 315 vc4_state->src_w[0] = (state->src.x2 - state->src.x1) >> 16; 316 vc4_state->src_h[0] = (state->src.y2 - state->src.y1) >> 16; 317 318 vc4_state->crtc_x = state->dst.x1; 319 vc4_state->crtc_y = state->dst.y1; 320 vc4_state->crtc_w = state->dst.x2 - state->dst.x1; 321 vc4_state->crtc_h = state->dst.y2 - state->dst.y1; 322 323 vc4_state->x_scaling[0] = vc4_get_scaling_mode(vc4_state->src_w[0], 324 vc4_state->crtc_w); 325 vc4_state->y_scaling[0] = vc4_get_scaling_mode(vc4_state->src_h[0], 326 vc4_state->crtc_h); 327 328 vc4_state->is_unity = (vc4_state->x_scaling[0] == VC4_SCALING_NONE && 329 vc4_state->y_scaling[0] == VC4_SCALING_NONE); 330 331 if (num_planes > 1) { 332 vc4_state->is_yuv = true; 333 334 vc4_state->src_w[1] = vc4_state->src_w[0] / h_subsample; 335 vc4_state->src_h[1] = vc4_state->src_h[0] / v_subsample; 336 337 vc4_state->x_scaling[1] = 338 vc4_get_scaling_mode(vc4_state->src_w[1], 339 vc4_state->crtc_w); 340 vc4_state->y_scaling[1] = 341 vc4_get_scaling_mode(vc4_state->src_h[1], 342 vc4_state->crtc_h); 343 344 /* YUV conversion requires that horizontal scaling be enabled 345 * on the UV plane even if vc4_get_scaling_mode() returned 346 * VC4_SCALING_NONE (which can happen when the down-scaling 347 * ratio is 0.5). Let's force it to VC4_SCALING_PPF in this 348 * case. 349 */ 350 if (vc4_state->x_scaling[1] == VC4_SCALING_NONE) 351 vc4_state->x_scaling[1] = VC4_SCALING_PPF; 352 } else { 353 vc4_state->is_yuv = false; 354 vc4_state->x_scaling[1] = VC4_SCALING_NONE; 355 vc4_state->y_scaling[1] = VC4_SCALING_NONE; 356 } 357 358 return 0; 359 } 360 361 static void vc4_write_tpz(struct vc4_plane_state *vc4_state, u32 src, u32 dst) 362 { 363 u32 scale, recip; 364 365 scale = (1 << 16) * src / dst; 366 367 /* The specs note that while the reciprocal would be defined 368 * as (1<<32)/scale, ~0 is close enough. 369 */ 370 recip = ~0 / scale; 371 372 vc4_dlist_write(vc4_state, 373 VC4_SET_FIELD(scale, SCALER_TPZ0_SCALE) | 374 VC4_SET_FIELD(0, SCALER_TPZ0_IPHASE)); 375 vc4_dlist_write(vc4_state, 376 VC4_SET_FIELD(recip, SCALER_TPZ1_RECIP)); 377 } 378 379 static void vc4_write_ppf(struct vc4_plane_state *vc4_state, u32 src, u32 dst) 380 { 381 u32 scale = (1 << 16) * src / dst; 382 383 vc4_dlist_write(vc4_state, 384 SCALER_PPF_AGC | 385 VC4_SET_FIELD(scale, SCALER_PPF_SCALE) | 386 VC4_SET_FIELD(0, SCALER_PPF_IPHASE)); 387 } 388 389 static u32 vc4_lbm_size(struct drm_plane_state *state) 390 { 391 struct vc4_plane_state *vc4_state = to_vc4_plane_state(state); 392 /* This is the worst case number. One of the two sizes will 393 * be used depending on the scaling configuration. 394 */ 395 u32 pix_per_line = max(vc4_state->src_w[0], (u32)vc4_state->crtc_w); 396 u32 lbm; 397 398 if (!vc4_state->is_yuv) { 399 if (vc4_state->is_unity) 400 return 0; 401 else if (vc4_state->y_scaling[0] == VC4_SCALING_TPZ) 402 lbm = pix_per_line * 8; 403 else { 404 /* In special cases, this multiplier might be 12. */ 405 lbm = pix_per_line * 16; 406 } 407 } else { 408 /* There are cases for this going down to a multiplier 409 * of 2, but according to the firmware source, the 410 * table in the docs is somewhat wrong. 411 */ 412 lbm = pix_per_line * 16; 413 } 414 415 lbm = roundup(lbm, 32); 416 417 return lbm; 418 } 419 420 static void vc4_write_scaling_parameters(struct drm_plane_state *state, 421 int channel) 422 { 423 struct vc4_plane_state *vc4_state = to_vc4_plane_state(state); 424 425 /* Ch0 H-PPF Word 0: Scaling Parameters */ 426 if (vc4_state->x_scaling[channel] == VC4_SCALING_PPF) { 427 vc4_write_ppf(vc4_state, 428 vc4_state->src_w[channel], vc4_state->crtc_w); 429 } 430 431 /* Ch0 V-PPF Words 0-1: Scaling Parameters, Context */ 432 if (vc4_state->y_scaling[channel] == VC4_SCALING_PPF) { 433 vc4_write_ppf(vc4_state, 434 vc4_state->src_h[channel], vc4_state->crtc_h); 435 vc4_dlist_write(vc4_state, 0xc0c0c0c0); 436 } 437 438 /* Ch0 H-TPZ Words 0-1: Scaling Parameters, Recip */ 439 if (vc4_state->x_scaling[channel] == VC4_SCALING_TPZ) { 440 vc4_write_tpz(vc4_state, 441 vc4_state->src_w[channel], vc4_state->crtc_w); 442 } 443 444 /* Ch0 V-TPZ Words 0-2: Scaling Parameters, Recip, Context */ 445 if (vc4_state->y_scaling[channel] == VC4_SCALING_TPZ) { 446 vc4_write_tpz(vc4_state, 447 vc4_state->src_h[channel], vc4_state->crtc_h); 448 vc4_dlist_write(vc4_state, 0xc0c0c0c0); 449 } 450 } 451 452 /* Writes out a full display list for an active plane to the plane's 453 * private dlist state. 454 */ 455 static int vc4_plane_mode_set(struct drm_plane *plane, 456 struct drm_plane_state *state) 457 { 458 struct vc4_dev *vc4 = to_vc4_dev(plane->dev); 459 struct vc4_plane_state *vc4_state = to_vc4_plane_state(state); 460 struct drm_framebuffer *fb = state->fb; 461 u32 ctl0_offset = vc4_state->dlist_count; 462 const struct hvs_format *format = vc4_get_hvs_format(fb->format->format); 463 u64 base_format_mod = fourcc_mod_broadcom_mod(fb->modifier); 464 int num_planes = drm_format_num_planes(format->drm); 465 u32 h_subsample, v_subsample; 466 bool mix_plane_alpha; 467 bool covers_screen; 468 u32 scl0, scl1, pitch0; 469 u32 lbm_size, tiling; 470 unsigned long irqflags; 471 u32 hvs_format = format->hvs; 472 int ret, i; 473 474 ret = vc4_plane_setup_clipping_and_scaling(state); 475 if (ret) 476 return ret; 477 478 /* Allocate the LBM memory that the HVS will use for temporary 479 * storage due to our scaling/format conversion. 480 */ 481 lbm_size = vc4_lbm_size(state); 482 if (lbm_size) { 483 if (!vc4_state->lbm.allocated) { 484 spin_lock_irqsave(&vc4->hvs->mm_lock, irqflags); 485 ret = drm_mm_insert_node_generic(&vc4->hvs->lbm_mm, 486 &vc4_state->lbm, 487 lbm_size, 32, 0, 0); 488 spin_unlock_irqrestore(&vc4->hvs->mm_lock, irqflags); 489 } else { 490 WARN_ON_ONCE(lbm_size != vc4_state->lbm.size); 491 } 492 } 493 494 if (ret) 495 return ret; 496 497 /* SCL1 is used for Cb/Cr scaling of planar formats. For RGB 498 * and 4:4:4, scl1 should be set to scl0 so both channels of 499 * the scaler do the same thing. For YUV, the Y plane needs 500 * to be put in channel 1 and Cb/Cr in channel 0, so we swap 501 * the scl fields here. 502 */ 503 if (num_planes == 1) { 504 scl0 = vc4_get_scl_field(state, 0); 505 scl1 = scl0; 506 } else { 507 scl0 = vc4_get_scl_field(state, 1); 508 scl1 = vc4_get_scl_field(state, 0); 509 } 510 511 h_subsample = drm_format_horz_chroma_subsampling(format->drm); 512 v_subsample = drm_format_vert_chroma_subsampling(format->drm); 513 514 switch (base_format_mod) { 515 case DRM_FORMAT_MOD_LINEAR: 516 tiling = SCALER_CTL0_TILING_LINEAR; 517 pitch0 = VC4_SET_FIELD(fb->pitches[0], SCALER_SRC_PITCH); 518 519 /* Adjust the base pointer to the first pixel to be scanned 520 * out. 521 */ 522 for (i = 0; i < num_planes; i++) { 523 vc4_state->offsets[i] += vc4_state->src_y / 524 (i ? v_subsample : 1) * 525 fb->pitches[i]; 526 vc4_state->offsets[i] += vc4_state->src_x / 527 (i ? h_subsample : 1) * 528 fb->format->cpp[i]; 529 } 530 531 break; 532 533 case DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED: { 534 u32 tile_size_shift = 12; /* T tiles are 4kb */ 535 /* Whole-tile offsets, mostly for setting the pitch. */ 536 u32 tile_w_shift = fb->format->cpp[0] == 2 ? 6 : 5; 537 u32 tile_h_shift = 5; /* 16 and 32bpp are 32 pixels high */ 538 u32 tile_w_mask = (1 << tile_w_shift) - 1; 539 /* The height mask on 32-bit-per-pixel tiles is 63, i.e. twice 540 * the height (in pixels) of a 4k tile. 541 */ 542 u32 tile_h_mask = (2 << tile_h_shift) - 1; 543 /* For T-tiled, the FB pitch is "how many bytes from one row to 544 * the next, such that 545 * 546 * pitch * tile_h == tile_size * tiles_per_row 547 */ 548 u32 tiles_w = fb->pitches[0] >> (tile_size_shift - tile_h_shift); 549 u32 tiles_l = vc4_state->src_x >> tile_w_shift; 550 u32 tiles_r = tiles_w - tiles_l; 551 u32 tiles_t = vc4_state->src_y >> tile_h_shift; 552 /* Intra-tile offsets, which modify the base address (the 553 * SCALER_PITCH0_TILE_Y_OFFSET tells HVS how to walk from that 554 * base address). 555 */ 556 u32 tile_y = (vc4_state->src_y >> 4) & 1; 557 u32 subtile_y = (vc4_state->src_y >> 2) & 3; 558 u32 utile_y = vc4_state->src_y & 3; 559 u32 x_off = vc4_state->src_x & tile_w_mask; 560 u32 y_off = vc4_state->src_y & tile_h_mask; 561 562 tiling = SCALER_CTL0_TILING_256B_OR_T; 563 pitch0 = (VC4_SET_FIELD(x_off, SCALER_PITCH0_SINK_PIX) | 564 VC4_SET_FIELD(y_off, SCALER_PITCH0_TILE_Y_OFFSET) | 565 VC4_SET_FIELD(tiles_l, SCALER_PITCH0_TILE_WIDTH_L) | 566 VC4_SET_FIELD(tiles_r, SCALER_PITCH0_TILE_WIDTH_R)); 567 vc4_state->offsets[0] += tiles_t * (tiles_w << tile_size_shift); 568 vc4_state->offsets[0] += subtile_y << 8; 569 vc4_state->offsets[0] += utile_y << 4; 570 571 /* Rows of tiles alternate left-to-right and right-to-left. */ 572 if (tiles_t & 1) { 573 pitch0 |= SCALER_PITCH0_TILE_INITIAL_LINE_DIR; 574 vc4_state->offsets[0] += (tiles_w - tiles_l) << 575 tile_size_shift; 576 vc4_state->offsets[0] -= (1 + !tile_y) << 10; 577 } else { 578 vc4_state->offsets[0] += tiles_l << tile_size_shift; 579 vc4_state->offsets[0] += tile_y << 10; 580 } 581 582 break; 583 } 584 585 case DRM_FORMAT_MOD_BROADCOM_SAND64: 586 case DRM_FORMAT_MOD_BROADCOM_SAND128: 587 case DRM_FORMAT_MOD_BROADCOM_SAND256: { 588 uint32_t param = fourcc_mod_broadcom_param(fb->modifier); 589 590 /* Column-based NV12 or RGBA. 591 */ 592 if (fb->format->num_planes > 1) { 593 if (hvs_format != HVS_PIXEL_FORMAT_YCBCR_YUV420_2PLANE) { 594 DRM_DEBUG_KMS("SAND format only valid for NV12/21"); 595 return -EINVAL; 596 } 597 hvs_format = HVS_PIXEL_FORMAT_H264; 598 } else { 599 if (base_format_mod == DRM_FORMAT_MOD_BROADCOM_SAND256) { 600 DRM_DEBUG_KMS("SAND256 format only valid for H.264"); 601 return -EINVAL; 602 } 603 } 604 605 switch (base_format_mod) { 606 case DRM_FORMAT_MOD_BROADCOM_SAND64: 607 tiling = SCALER_CTL0_TILING_64B; 608 break; 609 case DRM_FORMAT_MOD_BROADCOM_SAND128: 610 tiling = SCALER_CTL0_TILING_128B; 611 break; 612 case DRM_FORMAT_MOD_BROADCOM_SAND256: 613 tiling = SCALER_CTL0_TILING_256B_OR_T; 614 break; 615 default: 616 break; 617 } 618 619 if (param > SCALER_TILE_HEIGHT_MASK) { 620 DRM_DEBUG_KMS("SAND height too large (%d)\n", param); 621 return -EINVAL; 622 } 623 624 pitch0 = VC4_SET_FIELD(param, SCALER_TILE_HEIGHT); 625 break; 626 } 627 628 default: 629 DRM_DEBUG_KMS("Unsupported FB tiling flag 0x%16llx", 630 (long long)fb->modifier); 631 return -EINVAL; 632 } 633 634 /* Control word */ 635 vc4_dlist_write(vc4_state, 636 SCALER_CTL0_VALID | 637 VC4_SET_FIELD(SCALER_CTL0_RGBA_EXPAND_ROUND, SCALER_CTL0_RGBA_EXPAND) | 638 (format->pixel_order << SCALER_CTL0_ORDER_SHIFT) | 639 (hvs_format << SCALER_CTL0_PIXEL_FORMAT_SHIFT) | 640 VC4_SET_FIELD(tiling, SCALER_CTL0_TILING) | 641 (vc4_state->is_unity ? SCALER_CTL0_UNITY : 0) | 642 VC4_SET_FIELD(scl0, SCALER_CTL0_SCL0) | 643 VC4_SET_FIELD(scl1, SCALER_CTL0_SCL1)); 644 645 /* Position Word 0: Image Positions and Alpha Value */ 646 vc4_state->pos0_offset = vc4_state->dlist_count; 647 vc4_dlist_write(vc4_state, 648 VC4_SET_FIELD(state->alpha >> 8, SCALER_POS0_FIXED_ALPHA) | 649 VC4_SET_FIELD(vc4_state->crtc_x, SCALER_POS0_START_X) | 650 VC4_SET_FIELD(vc4_state->crtc_y, SCALER_POS0_START_Y)); 651 652 /* Position Word 1: Scaled Image Dimensions. */ 653 if (!vc4_state->is_unity) { 654 vc4_dlist_write(vc4_state, 655 VC4_SET_FIELD(vc4_state->crtc_w, 656 SCALER_POS1_SCL_WIDTH) | 657 VC4_SET_FIELD(vc4_state->crtc_h, 658 SCALER_POS1_SCL_HEIGHT)); 659 } 660 661 /* Don't waste cycles mixing with plane alpha if the set alpha 662 * is opaque or there is no per-pixel alpha information. 663 * In any case we use the alpha property value as the fixed alpha. 664 */ 665 mix_plane_alpha = state->alpha != DRM_BLEND_ALPHA_OPAQUE && 666 fb->format->has_alpha; 667 668 /* Position Word 2: Source Image Size, Alpha */ 669 vc4_state->pos2_offset = vc4_state->dlist_count; 670 vc4_dlist_write(vc4_state, 671 VC4_SET_FIELD(fb->format->has_alpha ? 672 SCALER_POS2_ALPHA_MODE_PIPELINE : 673 SCALER_POS2_ALPHA_MODE_FIXED, 674 SCALER_POS2_ALPHA_MODE) | 675 (mix_plane_alpha ? SCALER_POS2_ALPHA_MIX : 0) | 676 (fb->format->has_alpha ? SCALER_POS2_ALPHA_PREMULT : 0) | 677 VC4_SET_FIELD(vc4_state->src_w[0], SCALER_POS2_WIDTH) | 678 VC4_SET_FIELD(vc4_state->src_h[0], SCALER_POS2_HEIGHT)); 679 680 /* Position Word 3: Context. Written by the HVS. */ 681 vc4_dlist_write(vc4_state, 0xc0c0c0c0); 682 683 684 /* Pointer Word 0/1/2: RGB / Y / Cb / Cr Pointers 685 * 686 * The pointers may be any byte address. 687 */ 688 vc4_state->ptr0_offset = vc4_state->dlist_count; 689 for (i = 0; i < num_planes; i++) 690 vc4_dlist_write(vc4_state, vc4_state->offsets[i]); 691 692 /* Pointer Context Word 0/1/2: Written by the HVS */ 693 for (i = 0; i < num_planes; i++) 694 vc4_dlist_write(vc4_state, 0xc0c0c0c0); 695 696 /* Pitch word 0 */ 697 vc4_dlist_write(vc4_state, pitch0); 698 699 /* Pitch word 1/2 */ 700 for (i = 1; i < num_planes; i++) { 701 if (hvs_format != HVS_PIXEL_FORMAT_H264) { 702 vc4_dlist_write(vc4_state, 703 VC4_SET_FIELD(fb->pitches[i], 704 SCALER_SRC_PITCH)); 705 } else { 706 vc4_dlist_write(vc4_state, pitch0); 707 } 708 } 709 710 /* Colorspace conversion words */ 711 if (vc4_state->is_yuv) { 712 vc4_dlist_write(vc4_state, SCALER_CSC0_ITR_R_601_5); 713 vc4_dlist_write(vc4_state, SCALER_CSC1_ITR_R_601_5); 714 vc4_dlist_write(vc4_state, SCALER_CSC2_ITR_R_601_5); 715 } 716 717 if (vc4_state->x_scaling[0] != VC4_SCALING_NONE || 718 vc4_state->x_scaling[1] != VC4_SCALING_NONE || 719 vc4_state->y_scaling[0] != VC4_SCALING_NONE || 720 vc4_state->y_scaling[1] != VC4_SCALING_NONE) { 721 /* LBM Base Address. */ 722 if (vc4_state->y_scaling[0] != VC4_SCALING_NONE || 723 vc4_state->y_scaling[1] != VC4_SCALING_NONE) { 724 vc4_dlist_write(vc4_state, vc4_state->lbm.start); 725 } 726 727 if (num_planes > 1) { 728 /* Emit Cb/Cr as channel 0 and Y as channel 729 * 1. This matches how we set up scl0/scl1 730 * above. 731 */ 732 vc4_write_scaling_parameters(state, 1); 733 } 734 vc4_write_scaling_parameters(state, 0); 735 736 /* If any PPF setup was done, then all the kernel 737 * pointers get uploaded. 738 */ 739 if (vc4_state->x_scaling[0] == VC4_SCALING_PPF || 740 vc4_state->y_scaling[0] == VC4_SCALING_PPF || 741 vc4_state->x_scaling[1] == VC4_SCALING_PPF || 742 vc4_state->y_scaling[1] == VC4_SCALING_PPF) { 743 u32 kernel = VC4_SET_FIELD(vc4->hvs->mitchell_netravali_filter.start, 744 SCALER_PPF_KERNEL_OFFSET); 745 746 /* HPPF plane 0 */ 747 vc4_dlist_write(vc4_state, kernel); 748 /* VPPF plane 0 */ 749 vc4_dlist_write(vc4_state, kernel); 750 /* HPPF plane 1 */ 751 vc4_dlist_write(vc4_state, kernel); 752 /* VPPF plane 1 */ 753 vc4_dlist_write(vc4_state, kernel); 754 } 755 } 756 757 vc4_state->dlist[ctl0_offset] |= 758 VC4_SET_FIELD(vc4_state->dlist_count, SCALER_CTL0_SIZE); 759 760 /* crtc_* are already clipped coordinates. */ 761 covers_screen = vc4_state->crtc_x == 0 && vc4_state->crtc_y == 0 && 762 vc4_state->crtc_w == state->crtc->mode.hdisplay && 763 vc4_state->crtc_h == state->crtc->mode.vdisplay; 764 /* Background fill might be necessary when the plane has per-pixel 765 * alpha content or a non-opaque plane alpha and could blend from the 766 * background or does not cover the entire screen. 767 */ 768 vc4_state->needs_bg_fill = fb->format->has_alpha || !covers_screen || 769 state->alpha != DRM_BLEND_ALPHA_OPAQUE; 770 771 return 0; 772 } 773 774 /* If a modeset involves changing the setup of a plane, the atomic 775 * infrastructure will call this to validate a proposed plane setup. 776 * However, if a plane isn't getting updated, this (and the 777 * corresponding vc4_plane_atomic_update) won't get called. Thus, we 778 * compute the dlist here and have all active plane dlists get updated 779 * in the CRTC's flush. 780 */ 781 static int vc4_plane_atomic_check(struct drm_plane *plane, 782 struct drm_plane_state *state) 783 { 784 struct vc4_plane_state *vc4_state = to_vc4_plane_state(state); 785 786 vc4_state->dlist_count = 0; 787 788 if (plane_enabled(state)) 789 return vc4_plane_mode_set(plane, state); 790 else 791 return 0; 792 } 793 794 static void vc4_plane_atomic_update(struct drm_plane *plane, 795 struct drm_plane_state *old_state) 796 { 797 /* No contents here. Since we don't know where in the CRTC's 798 * dlist we should be stored, our dlist is uploaded to the 799 * hardware with vc4_plane_write_dlist() at CRTC atomic_flush 800 * time. 801 */ 802 } 803 804 u32 vc4_plane_write_dlist(struct drm_plane *plane, u32 __iomem *dlist) 805 { 806 struct vc4_plane_state *vc4_state = to_vc4_plane_state(plane->state); 807 int i; 808 809 vc4_state->hw_dlist = dlist; 810 811 /* Can't memcpy_toio() because it needs to be 32-bit writes. */ 812 for (i = 0; i < vc4_state->dlist_count; i++) 813 writel(vc4_state->dlist[i], &dlist[i]); 814 815 return vc4_state->dlist_count; 816 } 817 818 u32 vc4_plane_dlist_size(const struct drm_plane_state *state) 819 { 820 const struct vc4_plane_state *vc4_state = 821 container_of(state, typeof(*vc4_state), base); 822 823 return vc4_state->dlist_count; 824 } 825 826 /* Updates the plane to immediately (well, once the FIFO needs 827 * refilling) scan out from at a new framebuffer. 828 */ 829 void vc4_plane_async_set_fb(struct drm_plane *plane, struct drm_framebuffer *fb) 830 { 831 struct vc4_plane_state *vc4_state = to_vc4_plane_state(plane->state); 832 struct drm_gem_cma_object *bo = drm_fb_cma_get_gem_obj(fb, 0); 833 uint32_t addr; 834 835 /* We're skipping the address adjustment for negative origin, 836 * because this is only called on the primary plane. 837 */ 838 WARN_ON_ONCE(plane->state->crtc_x < 0 || plane->state->crtc_y < 0); 839 addr = bo->paddr + fb->offsets[0]; 840 841 /* Write the new address into the hardware immediately. The 842 * scanout will start from this address as soon as the FIFO 843 * needs to refill with pixels. 844 */ 845 writel(addr, &vc4_state->hw_dlist[vc4_state->ptr0_offset]); 846 847 /* Also update the CPU-side dlist copy, so that any later 848 * atomic updates that don't do a new modeset on our plane 849 * also use our updated address. 850 */ 851 vc4_state->dlist[vc4_state->ptr0_offset] = addr; 852 } 853 854 static void vc4_plane_atomic_async_update(struct drm_plane *plane, 855 struct drm_plane_state *state) 856 { 857 struct vc4_plane_state *vc4_state = to_vc4_plane_state(plane->state); 858 859 if (plane->state->fb != state->fb) { 860 vc4_plane_async_set_fb(plane, state->fb); 861 drm_atomic_set_fb_for_plane(plane->state, state->fb); 862 } 863 864 /* Set the cursor's position on the screen. This is the 865 * expected change from the drm_mode_cursor_universal() 866 * helper. 867 */ 868 plane->state->crtc_x = state->crtc_x; 869 plane->state->crtc_y = state->crtc_y; 870 871 /* Allow changing the start position within the cursor BO, if 872 * that matters. 873 */ 874 plane->state->src_x = state->src_x; 875 plane->state->src_y = state->src_y; 876 877 /* Update the display list based on the new crtc_x/y. */ 878 vc4_plane_atomic_check(plane, plane->state); 879 880 /* Note that we can't just call vc4_plane_write_dlist() 881 * because that would smash the context data that the HVS is 882 * currently using. 883 */ 884 writel(vc4_state->dlist[vc4_state->pos0_offset], 885 &vc4_state->hw_dlist[vc4_state->pos0_offset]); 886 writel(vc4_state->dlist[vc4_state->pos2_offset], 887 &vc4_state->hw_dlist[vc4_state->pos2_offset]); 888 writel(vc4_state->dlist[vc4_state->ptr0_offset], 889 &vc4_state->hw_dlist[vc4_state->ptr0_offset]); 890 } 891 892 static int vc4_plane_atomic_async_check(struct drm_plane *plane, 893 struct drm_plane_state *state) 894 { 895 /* No configuring new scaling in the fast path. */ 896 if (plane->state->crtc_w != state->crtc_w || 897 plane->state->crtc_h != state->crtc_h || 898 plane->state->src_w != state->src_w || 899 plane->state->src_h != state->src_h) 900 return -EINVAL; 901 902 return 0; 903 } 904 905 static int vc4_prepare_fb(struct drm_plane *plane, 906 struct drm_plane_state *state) 907 { 908 struct vc4_bo *bo; 909 struct dma_fence *fence; 910 int ret; 911 912 if (!state->fb) 913 return 0; 914 915 bo = to_vc4_bo(&drm_fb_cma_get_gem_obj(state->fb, 0)->base); 916 917 fence = reservation_object_get_excl_rcu(bo->resv); 918 drm_atomic_set_fence_for_plane(state, fence); 919 920 if (plane->state->fb == state->fb) 921 return 0; 922 923 ret = vc4_bo_inc_usecnt(bo); 924 if (ret) 925 return ret; 926 927 return 0; 928 } 929 930 static void vc4_cleanup_fb(struct drm_plane *plane, 931 struct drm_plane_state *state) 932 { 933 struct vc4_bo *bo; 934 935 if (plane->state->fb == state->fb || !state->fb) 936 return; 937 938 bo = to_vc4_bo(&drm_fb_cma_get_gem_obj(state->fb, 0)->base); 939 vc4_bo_dec_usecnt(bo); 940 } 941 942 static const struct drm_plane_helper_funcs vc4_plane_helper_funcs = { 943 .atomic_check = vc4_plane_atomic_check, 944 .atomic_update = vc4_plane_atomic_update, 945 .prepare_fb = vc4_prepare_fb, 946 .cleanup_fb = vc4_cleanup_fb, 947 .atomic_async_check = vc4_plane_atomic_async_check, 948 .atomic_async_update = vc4_plane_atomic_async_update, 949 }; 950 951 static void vc4_plane_destroy(struct drm_plane *plane) 952 { 953 drm_plane_cleanup(plane); 954 } 955 956 static bool vc4_format_mod_supported(struct drm_plane *plane, 957 uint32_t format, 958 uint64_t modifier) 959 { 960 /* Support T_TILING for RGB formats only. */ 961 switch (format) { 962 case DRM_FORMAT_XRGB8888: 963 case DRM_FORMAT_ARGB8888: 964 case DRM_FORMAT_ABGR8888: 965 case DRM_FORMAT_XBGR8888: 966 case DRM_FORMAT_RGB565: 967 case DRM_FORMAT_BGR565: 968 case DRM_FORMAT_ARGB1555: 969 case DRM_FORMAT_XRGB1555: 970 switch (fourcc_mod_broadcom_mod(modifier)) { 971 case DRM_FORMAT_MOD_LINEAR: 972 case DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED: 973 case DRM_FORMAT_MOD_BROADCOM_SAND64: 974 case DRM_FORMAT_MOD_BROADCOM_SAND128: 975 return true; 976 default: 977 return false; 978 } 979 case DRM_FORMAT_NV12: 980 case DRM_FORMAT_NV21: 981 switch (fourcc_mod_broadcom_mod(modifier)) { 982 case DRM_FORMAT_MOD_LINEAR: 983 case DRM_FORMAT_MOD_BROADCOM_SAND64: 984 case DRM_FORMAT_MOD_BROADCOM_SAND128: 985 case DRM_FORMAT_MOD_BROADCOM_SAND256: 986 return true; 987 default: 988 return false; 989 } 990 case DRM_FORMAT_YUV422: 991 case DRM_FORMAT_YVU422: 992 case DRM_FORMAT_YUV420: 993 case DRM_FORMAT_YVU420: 994 case DRM_FORMAT_NV16: 995 case DRM_FORMAT_NV61: 996 default: 997 return (modifier == DRM_FORMAT_MOD_LINEAR); 998 } 999 } 1000 1001 static const struct drm_plane_funcs vc4_plane_funcs = { 1002 .update_plane = drm_atomic_helper_update_plane, 1003 .disable_plane = drm_atomic_helper_disable_plane, 1004 .destroy = vc4_plane_destroy, 1005 .set_property = NULL, 1006 .reset = vc4_plane_reset, 1007 .atomic_duplicate_state = vc4_plane_duplicate_state, 1008 .atomic_destroy_state = vc4_plane_destroy_state, 1009 .format_mod_supported = vc4_format_mod_supported, 1010 }; 1011 1012 struct drm_plane *vc4_plane_init(struct drm_device *dev, 1013 enum drm_plane_type type) 1014 { 1015 struct drm_plane *plane = NULL; 1016 struct vc4_plane *vc4_plane; 1017 u32 formats[ARRAY_SIZE(hvs_formats)]; 1018 u32 num_formats = 0; 1019 int ret = 0; 1020 unsigned i; 1021 static const uint64_t modifiers[] = { 1022 DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED, 1023 DRM_FORMAT_MOD_BROADCOM_SAND128, 1024 DRM_FORMAT_MOD_BROADCOM_SAND64, 1025 DRM_FORMAT_MOD_BROADCOM_SAND256, 1026 DRM_FORMAT_MOD_LINEAR, 1027 DRM_FORMAT_MOD_INVALID 1028 }; 1029 1030 vc4_plane = devm_kzalloc(dev->dev, sizeof(*vc4_plane), 1031 GFP_KERNEL); 1032 if (!vc4_plane) 1033 return ERR_PTR(-ENOMEM); 1034 1035 for (i = 0; i < ARRAY_SIZE(hvs_formats); i++) { 1036 /* Don't allow YUV in cursor planes, since that means 1037 * tuning on the scaler, which we don't allow for the 1038 * cursor. 1039 */ 1040 if (type != DRM_PLANE_TYPE_CURSOR || 1041 hvs_formats[i].hvs < HVS_PIXEL_FORMAT_YCBCR_YUV420_3PLANE) { 1042 formats[num_formats++] = hvs_formats[i].drm; 1043 } 1044 } 1045 plane = &vc4_plane->base; 1046 ret = drm_universal_plane_init(dev, plane, 0, 1047 &vc4_plane_funcs, 1048 formats, num_formats, 1049 modifiers, type, NULL); 1050 1051 drm_plane_helper_add(plane, &vc4_plane_helper_funcs); 1052 1053 drm_plane_create_alpha_property(plane); 1054 1055 return plane; 1056 } 1057