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