1 // SPDX-License-Identifier: MIT 2 /* 3 * Copyright © 2021 Intel Corporation 4 */ 5 6 #include <drm/drm_blend.h> 7 #include <drm/drm_modeset_helper.h> 8 9 #include <linux/dma-fence.h> 10 #include <linux/dma-resv.h> 11 12 #include "gem/i915_gem_object.h" 13 #include "i915_drv.h" 14 #include "intel_atomic_plane.h" 15 #include "intel_display.h" 16 #include "intel_display_types.h" 17 #include "intel_dpt.h" 18 #include "intel_fb.h" 19 #include "intel_fb_bo.h" 20 #include "intel_frontbuffer.h" 21 22 #define check_array_bounds(i915, a, i) drm_WARN_ON(&(i915)->drm, (i) >= ARRAY_SIZE(a)) 23 24 /* 25 * From the Sky Lake PRM: 26 * "The Color Control Surface (CCS) contains the compression status of 27 * the cache-line pairs. The compression state of the cache-line pair 28 * is specified by 2 bits in the CCS. Each CCS cache-line represents 29 * an area on the main surface of 16 x16 sets of 128 byte Y-tiled 30 * cache-line-pairs. CCS is always Y tiled." 31 * 32 * Since cache line pairs refers to horizontally adjacent cache lines, 33 * each cache line in the CCS corresponds to an area of 32x16 cache 34 * lines on the main surface. Since each pixel is 4 bytes, this gives 35 * us a ratio of one byte in the CCS for each 8x16 pixels in the 36 * main surface. 37 */ 38 static const struct drm_format_info skl_ccs_formats[] = { 39 { .format = DRM_FORMAT_XRGB8888, .depth = 24, .num_planes = 2, 40 .cpp = { 4, 1, }, .hsub = 8, .vsub = 16, }, 41 { .format = DRM_FORMAT_XBGR8888, .depth = 24, .num_planes = 2, 42 .cpp = { 4, 1, }, .hsub = 8, .vsub = 16, }, 43 { .format = DRM_FORMAT_ARGB8888, .depth = 32, .num_planes = 2, 44 .cpp = { 4, 1, }, .hsub = 8, .vsub = 16, .has_alpha = true, }, 45 { .format = DRM_FORMAT_ABGR8888, .depth = 32, .num_planes = 2, 46 .cpp = { 4, 1, }, .hsub = 8, .vsub = 16, .has_alpha = true, }, 47 }; 48 49 /* 50 * Gen-12 compression uses 4 bits of CCS data for each cache line pair in the 51 * main surface. And each 64B CCS cache line represents an area of 4x1 Y-tiles 52 * in the main surface. With 4 byte pixels and each Y-tile having dimensions of 53 * 32x32 pixels, the ratio turns out to 1B in the CCS for every 2x32 pixels in 54 * the main surface. 55 */ 56 static const struct drm_format_info gen12_ccs_formats[] = { 57 { .format = DRM_FORMAT_XRGB8888, .depth = 24, .num_planes = 2, 58 .char_per_block = { 4, 1 }, .block_w = { 1, 2 }, .block_h = { 1, 1 }, 59 .hsub = 1, .vsub = 1, }, 60 { .format = DRM_FORMAT_XBGR8888, .depth = 24, .num_planes = 2, 61 .char_per_block = { 4, 1 }, .block_w = { 1, 2 }, .block_h = { 1, 1 }, 62 .hsub = 1, .vsub = 1, }, 63 { .format = DRM_FORMAT_ARGB8888, .depth = 32, .num_planes = 2, 64 .char_per_block = { 4, 1 }, .block_w = { 1, 2 }, .block_h = { 1, 1 }, 65 .hsub = 1, .vsub = 1, .has_alpha = true }, 66 { .format = DRM_FORMAT_ABGR8888, .depth = 32, .num_planes = 2, 67 .char_per_block = { 4, 1 }, .block_w = { 1, 2 }, .block_h = { 1, 1 }, 68 .hsub = 1, .vsub = 1, .has_alpha = true }, 69 { .format = DRM_FORMAT_YUYV, .num_planes = 2, 70 .char_per_block = { 2, 1 }, .block_w = { 1, 2 }, .block_h = { 1, 1 }, 71 .hsub = 2, .vsub = 1, .is_yuv = true }, 72 { .format = DRM_FORMAT_YVYU, .num_planes = 2, 73 .char_per_block = { 2, 1 }, .block_w = { 1, 2 }, .block_h = { 1, 1 }, 74 .hsub = 2, .vsub = 1, .is_yuv = true }, 75 { .format = DRM_FORMAT_UYVY, .num_planes = 2, 76 .char_per_block = { 2, 1 }, .block_w = { 1, 2 }, .block_h = { 1, 1 }, 77 .hsub = 2, .vsub = 1, .is_yuv = true }, 78 { .format = DRM_FORMAT_VYUY, .num_planes = 2, 79 .char_per_block = { 2, 1 }, .block_w = { 1, 2 }, .block_h = { 1, 1 }, 80 .hsub = 2, .vsub = 1, .is_yuv = true }, 81 { .format = DRM_FORMAT_XYUV8888, .num_planes = 2, 82 .char_per_block = { 4, 1 }, .block_w = { 1, 2 }, .block_h = { 1, 1 }, 83 .hsub = 1, .vsub = 1, .is_yuv = true }, 84 { .format = DRM_FORMAT_NV12, .num_planes = 4, 85 .char_per_block = { 1, 2, 1, 1 }, .block_w = { 1, 1, 4, 4 }, .block_h = { 1, 1, 1, 1 }, 86 .hsub = 2, .vsub = 2, .is_yuv = true }, 87 { .format = DRM_FORMAT_P010, .num_planes = 4, 88 .char_per_block = { 2, 4, 1, 1 }, .block_w = { 1, 1, 2, 2 }, .block_h = { 1, 1, 1, 1 }, 89 .hsub = 2, .vsub = 2, .is_yuv = true }, 90 { .format = DRM_FORMAT_P012, .num_planes = 4, 91 .char_per_block = { 2, 4, 1, 1 }, .block_w = { 1, 1, 2, 2 }, .block_h = { 1, 1, 1, 1 }, 92 .hsub = 2, .vsub = 2, .is_yuv = true }, 93 { .format = DRM_FORMAT_P016, .num_planes = 4, 94 .char_per_block = { 2, 4, 1, 1 }, .block_w = { 1, 1, 2, 2 }, .block_h = { 1, 1, 1, 1 }, 95 .hsub = 2, .vsub = 2, .is_yuv = true }, 96 }; 97 98 /* 99 * Same as gen12_ccs_formats[] above, but with additional surface used 100 * to pass Clear Color information in plane 2 with 64 bits of data. 101 */ 102 static const struct drm_format_info gen12_ccs_cc_formats[] = { 103 { .format = DRM_FORMAT_XRGB8888, .depth = 24, .num_planes = 3, 104 .char_per_block = { 4, 1, 0 }, .block_w = { 1, 2, 2 }, .block_h = { 1, 1, 1 }, 105 .hsub = 1, .vsub = 1, }, 106 { .format = DRM_FORMAT_XBGR8888, .depth = 24, .num_planes = 3, 107 .char_per_block = { 4, 1, 0 }, .block_w = { 1, 2, 2 }, .block_h = { 1, 1, 1 }, 108 .hsub = 1, .vsub = 1, }, 109 { .format = DRM_FORMAT_ARGB8888, .depth = 32, .num_planes = 3, 110 .char_per_block = { 4, 1, 0 }, .block_w = { 1, 2, 2 }, .block_h = { 1, 1, 1 }, 111 .hsub = 1, .vsub = 1, .has_alpha = true }, 112 { .format = DRM_FORMAT_ABGR8888, .depth = 32, .num_planes = 3, 113 .char_per_block = { 4, 1, 0 }, .block_w = { 1, 2, 2 }, .block_h = { 1, 1, 1 }, 114 .hsub = 1, .vsub = 1, .has_alpha = true }, 115 }; 116 117 static const struct drm_format_info gen12_flat_ccs_cc_formats[] = { 118 { .format = DRM_FORMAT_XRGB8888, .depth = 24, .num_planes = 2, 119 .char_per_block = { 4, 0 }, .block_w = { 1, 2 }, .block_h = { 1, 1 }, 120 .hsub = 1, .vsub = 1, }, 121 { .format = DRM_FORMAT_XBGR8888, .depth = 24, .num_planes = 2, 122 .char_per_block = { 4, 0 }, .block_w = { 1, 2 }, .block_h = { 1, 1 }, 123 .hsub = 1, .vsub = 1, }, 124 { .format = DRM_FORMAT_ARGB8888, .depth = 32, .num_planes = 2, 125 .char_per_block = { 4, 0 }, .block_w = { 1, 2 }, .block_h = { 1, 1 }, 126 .hsub = 1, .vsub = 1, .has_alpha = true }, 127 { .format = DRM_FORMAT_ABGR8888, .depth = 32, .num_planes = 2, 128 .char_per_block = { 4, 0 }, .block_w = { 1, 2 }, .block_h = { 1, 1 }, 129 .hsub = 1, .vsub = 1, .has_alpha = true }, 130 }; 131 132 struct intel_modifier_desc { 133 u64 modifier; 134 struct { 135 u8 from; 136 u8 until; 137 } display_ver; 138 #define DISPLAY_VER_ALL { 0, -1 } 139 140 const struct drm_format_info *formats; 141 int format_count; 142 #define FORMAT_OVERRIDE(format_list) \ 143 .formats = format_list, \ 144 .format_count = ARRAY_SIZE(format_list) 145 146 u8 plane_caps; 147 148 struct { 149 u8 cc_planes:3; 150 u8 packed_aux_planes:4; 151 u8 planar_aux_planes:4; 152 } ccs; 153 }; 154 155 #define INTEL_PLANE_CAP_CCS_MASK (INTEL_PLANE_CAP_CCS_RC | \ 156 INTEL_PLANE_CAP_CCS_RC_CC | \ 157 INTEL_PLANE_CAP_CCS_MC) 158 #define INTEL_PLANE_CAP_TILING_MASK (INTEL_PLANE_CAP_TILING_X | \ 159 INTEL_PLANE_CAP_TILING_Y | \ 160 INTEL_PLANE_CAP_TILING_Yf | \ 161 INTEL_PLANE_CAP_TILING_4) 162 #define INTEL_PLANE_CAP_TILING_NONE 0 163 164 static const struct intel_modifier_desc intel_modifiers[] = { 165 { 166 .modifier = I915_FORMAT_MOD_4_TILED_MTL_MC_CCS, 167 .display_ver = { 14, 14 }, 168 .plane_caps = INTEL_PLANE_CAP_TILING_4 | INTEL_PLANE_CAP_CCS_MC, 169 170 .ccs.packed_aux_planes = BIT(1), 171 .ccs.planar_aux_planes = BIT(2) | BIT(3), 172 173 FORMAT_OVERRIDE(gen12_ccs_formats), 174 }, { 175 .modifier = I915_FORMAT_MOD_4_TILED_MTL_RC_CCS, 176 .display_ver = { 14, 14 }, 177 .plane_caps = INTEL_PLANE_CAP_TILING_4 | INTEL_PLANE_CAP_CCS_RC, 178 179 .ccs.packed_aux_planes = BIT(1), 180 181 FORMAT_OVERRIDE(gen12_ccs_formats), 182 }, { 183 .modifier = I915_FORMAT_MOD_4_TILED_MTL_RC_CCS_CC, 184 .display_ver = { 14, 14 }, 185 .plane_caps = INTEL_PLANE_CAP_TILING_4 | INTEL_PLANE_CAP_CCS_RC_CC, 186 187 .ccs.cc_planes = BIT(2), 188 .ccs.packed_aux_planes = BIT(1), 189 190 FORMAT_OVERRIDE(gen12_ccs_cc_formats), 191 }, { 192 .modifier = I915_FORMAT_MOD_4_TILED_DG2_MC_CCS, 193 .display_ver = { 13, 13 }, 194 .plane_caps = INTEL_PLANE_CAP_TILING_4 | INTEL_PLANE_CAP_CCS_MC, 195 }, { 196 .modifier = I915_FORMAT_MOD_4_TILED_DG2_RC_CCS_CC, 197 .display_ver = { 13, 13 }, 198 .plane_caps = INTEL_PLANE_CAP_TILING_4 | INTEL_PLANE_CAP_CCS_RC_CC, 199 200 .ccs.cc_planes = BIT(1), 201 202 FORMAT_OVERRIDE(gen12_flat_ccs_cc_formats), 203 }, { 204 .modifier = I915_FORMAT_MOD_4_TILED_DG2_RC_CCS, 205 .display_ver = { 13, 13 }, 206 .plane_caps = INTEL_PLANE_CAP_TILING_4 | INTEL_PLANE_CAP_CCS_RC, 207 }, { 208 .modifier = I915_FORMAT_MOD_4_TILED, 209 .display_ver = { 13, -1 }, 210 .plane_caps = INTEL_PLANE_CAP_TILING_4, 211 }, { 212 .modifier = I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS, 213 .display_ver = { 12, 13 }, 214 .plane_caps = INTEL_PLANE_CAP_TILING_Y | INTEL_PLANE_CAP_CCS_MC, 215 216 .ccs.packed_aux_planes = BIT(1), 217 .ccs.planar_aux_planes = BIT(2) | BIT(3), 218 219 FORMAT_OVERRIDE(gen12_ccs_formats), 220 }, { 221 .modifier = I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS, 222 .display_ver = { 12, 13 }, 223 .plane_caps = INTEL_PLANE_CAP_TILING_Y | INTEL_PLANE_CAP_CCS_RC, 224 225 .ccs.packed_aux_planes = BIT(1), 226 227 FORMAT_OVERRIDE(gen12_ccs_formats), 228 }, { 229 .modifier = I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC, 230 .display_ver = { 12, 13 }, 231 .plane_caps = INTEL_PLANE_CAP_TILING_Y | INTEL_PLANE_CAP_CCS_RC_CC, 232 233 .ccs.cc_planes = BIT(2), 234 .ccs.packed_aux_planes = BIT(1), 235 236 FORMAT_OVERRIDE(gen12_ccs_cc_formats), 237 }, { 238 .modifier = I915_FORMAT_MOD_Yf_TILED_CCS, 239 .display_ver = { 9, 11 }, 240 .plane_caps = INTEL_PLANE_CAP_TILING_Yf | INTEL_PLANE_CAP_CCS_RC, 241 242 .ccs.packed_aux_planes = BIT(1), 243 244 FORMAT_OVERRIDE(skl_ccs_formats), 245 }, { 246 .modifier = I915_FORMAT_MOD_Y_TILED_CCS, 247 .display_ver = { 9, 11 }, 248 .plane_caps = INTEL_PLANE_CAP_TILING_Y | INTEL_PLANE_CAP_CCS_RC, 249 250 .ccs.packed_aux_planes = BIT(1), 251 252 FORMAT_OVERRIDE(skl_ccs_formats), 253 }, { 254 .modifier = I915_FORMAT_MOD_Yf_TILED, 255 .display_ver = { 9, 11 }, 256 .plane_caps = INTEL_PLANE_CAP_TILING_Yf, 257 }, { 258 .modifier = I915_FORMAT_MOD_Y_TILED, 259 .display_ver = { 9, 13 }, 260 .plane_caps = INTEL_PLANE_CAP_TILING_Y, 261 }, { 262 .modifier = I915_FORMAT_MOD_X_TILED, 263 .display_ver = DISPLAY_VER_ALL, 264 .plane_caps = INTEL_PLANE_CAP_TILING_X, 265 }, { 266 .modifier = DRM_FORMAT_MOD_LINEAR, 267 .display_ver = DISPLAY_VER_ALL, 268 }, 269 }; 270 271 static const struct intel_modifier_desc *lookup_modifier_or_null(u64 modifier) 272 { 273 int i; 274 275 for (i = 0; i < ARRAY_SIZE(intel_modifiers); i++) 276 if (intel_modifiers[i].modifier == modifier) 277 return &intel_modifiers[i]; 278 279 return NULL; 280 } 281 282 static const struct intel_modifier_desc *lookup_modifier(u64 modifier) 283 { 284 const struct intel_modifier_desc *md = lookup_modifier_or_null(modifier); 285 286 if (WARN_ON(!md)) 287 return &intel_modifiers[0]; 288 289 return md; 290 } 291 292 static const struct drm_format_info * 293 lookup_format_info(const struct drm_format_info formats[], 294 int num_formats, u32 format) 295 { 296 int i; 297 298 for (i = 0; i < num_formats; i++) { 299 if (formats[i].format == format) 300 return &formats[i]; 301 } 302 303 return NULL; 304 } 305 306 unsigned int intel_fb_modifier_to_tiling(u64 fb_modifier) 307 { 308 const struct intel_modifier_desc *md; 309 u8 tiling_caps; 310 311 md = lookup_modifier_or_null(fb_modifier); 312 if (!md) 313 return I915_TILING_NONE; 314 315 tiling_caps = lookup_modifier_or_null(fb_modifier)->plane_caps & 316 INTEL_PLANE_CAP_TILING_MASK; 317 318 switch (tiling_caps) { 319 case INTEL_PLANE_CAP_TILING_Y: 320 return I915_TILING_Y; 321 case INTEL_PLANE_CAP_TILING_X: 322 return I915_TILING_X; 323 case INTEL_PLANE_CAP_TILING_4: 324 case INTEL_PLANE_CAP_TILING_Yf: 325 case INTEL_PLANE_CAP_TILING_NONE: 326 return I915_TILING_NONE; 327 default: 328 MISSING_CASE(tiling_caps); 329 return I915_TILING_NONE; 330 } 331 } 332 333 /** 334 * intel_fb_get_format_info: Get a modifier specific format information 335 * @cmd: FB add command structure 336 * 337 * Returns: 338 * Returns the format information for @cmd->pixel_format specific to @cmd->modifier[0], 339 * or %NULL if the modifier doesn't override the format. 340 */ 341 const struct drm_format_info * 342 intel_fb_get_format_info(const struct drm_mode_fb_cmd2 *cmd) 343 { 344 const struct intel_modifier_desc *md = lookup_modifier_or_null(cmd->modifier[0]); 345 346 if (!md || !md->formats) 347 return NULL; 348 349 return lookup_format_info(md->formats, md->format_count, cmd->pixel_format); 350 } 351 352 static bool plane_caps_contain_any(u8 caps, u8 mask) 353 { 354 return caps & mask; 355 } 356 357 static bool plane_caps_contain_all(u8 caps, u8 mask) 358 { 359 return (caps & mask) == mask; 360 } 361 362 /** 363 * intel_fb_is_tiled_modifier: Check if a modifier is a tiled modifier type 364 * @modifier: Modifier to check 365 * 366 * Returns: 367 * Returns %true if @modifier is a tiled modifier. 368 */ 369 bool intel_fb_is_tiled_modifier(u64 modifier) 370 { 371 return plane_caps_contain_any(lookup_modifier(modifier)->plane_caps, 372 INTEL_PLANE_CAP_TILING_MASK); 373 } 374 375 /** 376 * intel_fb_is_ccs_modifier: Check if a modifier is a CCS modifier type 377 * @modifier: Modifier to check 378 * 379 * Returns: 380 * Returns %true if @modifier is a render, render with color clear or 381 * media compression modifier. 382 */ 383 bool intel_fb_is_ccs_modifier(u64 modifier) 384 { 385 return plane_caps_contain_any(lookup_modifier(modifier)->plane_caps, 386 INTEL_PLANE_CAP_CCS_MASK); 387 } 388 389 /** 390 * intel_fb_is_rc_ccs_cc_modifier: Check if a modifier is an RC CCS CC modifier type 391 * @modifier: Modifier to check 392 * 393 * Returns: 394 * Returns %true if @modifier is a render with color clear modifier. 395 */ 396 bool intel_fb_is_rc_ccs_cc_modifier(u64 modifier) 397 { 398 return plane_caps_contain_any(lookup_modifier(modifier)->plane_caps, 399 INTEL_PLANE_CAP_CCS_RC_CC); 400 } 401 402 /** 403 * intel_fb_is_mc_ccs_modifier: Check if a modifier is an MC CCS modifier type 404 * @modifier: Modifier to check 405 * 406 * Returns: 407 * Returns %true if @modifier is a media compression modifier. 408 */ 409 bool intel_fb_is_mc_ccs_modifier(u64 modifier) 410 { 411 return plane_caps_contain_any(lookup_modifier(modifier)->plane_caps, 412 INTEL_PLANE_CAP_CCS_MC); 413 } 414 415 static bool check_modifier_display_ver_range(const struct intel_modifier_desc *md, 416 u8 display_ver_from, u8 display_ver_until) 417 { 418 return md->display_ver.from <= display_ver_until && 419 display_ver_from <= md->display_ver.until; 420 } 421 422 static bool plane_has_modifier(struct drm_i915_private *i915, 423 u8 plane_caps, 424 const struct intel_modifier_desc *md) 425 { 426 if (!IS_DISPLAY_VER(i915, md->display_ver.from, md->display_ver.until)) 427 return false; 428 429 if (!plane_caps_contain_all(plane_caps, md->plane_caps)) 430 return false; 431 432 /* 433 * Separate AuxCCS and Flat CCS modifiers to be run only on platforms 434 * where supported. 435 */ 436 if (intel_fb_is_ccs_modifier(md->modifier) && 437 HAS_FLAT_CCS(i915) != !md->ccs.packed_aux_planes) 438 return false; 439 440 return true; 441 } 442 443 /** 444 * intel_fb_plane_get_modifiers: Get the modifiers for the given platform and plane capabilities 445 * @i915: i915 device instance 446 * @plane_caps: capabilities for the plane the modifiers are queried for 447 * 448 * Returns: 449 * Returns the list of modifiers allowed by the @i915 platform and @plane_caps. 450 * The caller must free the returned buffer. 451 */ 452 u64 *intel_fb_plane_get_modifiers(struct drm_i915_private *i915, 453 u8 plane_caps) 454 { 455 u64 *list, *p; 456 int count = 1; /* +1 for invalid modifier terminator */ 457 int i; 458 459 for (i = 0; i < ARRAY_SIZE(intel_modifiers); i++) { 460 if (plane_has_modifier(i915, plane_caps, &intel_modifiers[i])) 461 count++; 462 } 463 464 list = kmalloc_array(count, sizeof(*list), GFP_KERNEL); 465 if (drm_WARN_ON(&i915->drm, !list)) 466 return NULL; 467 468 p = list; 469 for (i = 0; i < ARRAY_SIZE(intel_modifiers); i++) { 470 if (plane_has_modifier(i915, plane_caps, &intel_modifiers[i])) 471 *p++ = intel_modifiers[i].modifier; 472 } 473 *p++ = DRM_FORMAT_MOD_INVALID; 474 475 return list; 476 } 477 478 /** 479 * intel_fb_plane_supports_modifier: Determine if a modifier is supported by the given plane 480 * @plane: Plane to check the modifier support for 481 * @modifier: The modifier to check the support for 482 * 483 * Returns: 484 * %true if the @modifier is supported on @plane. 485 */ 486 bool intel_fb_plane_supports_modifier(struct intel_plane *plane, u64 modifier) 487 { 488 int i; 489 490 for (i = 0; i < plane->base.modifier_count; i++) 491 if (plane->base.modifiers[i] == modifier) 492 return true; 493 494 return false; 495 } 496 497 static bool format_is_yuv_semiplanar(const struct intel_modifier_desc *md, 498 const struct drm_format_info *info) 499 { 500 if (!info->is_yuv) 501 return false; 502 503 if (hweight8(md->ccs.planar_aux_planes) == 2) 504 return info->num_planes == 4; 505 else 506 return info->num_planes == 2; 507 } 508 509 /** 510 * intel_format_info_is_yuv_semiplanar: Check if the given format is YUV semiplanar 511 * @info: format to check 512 * @modifier: modifier used with the format 513 * 514 * Returns: 515 * %true if @info / @modifier is YUV semiplanar. 516 */ 517 bool intel_format_info_is_yuv_semiplanar(const struct drm_format_info *info, 518 u64 modifier) 519 { 520 return format_is_yuv_semiplanar(lookup_modifier(modifier), info); 521 } 522 523 static u8 ccs_aux_plane_mask(const struct intel_modifier_desc *md, 524 const struct drm_format_info *format) 525 { 526 if (format_is_yuv_semiplanar(md, format)) 527 return md->ccs.planar_aux_planes; 528 else 529 return md->ccs.packed_aux_planes; 530 } 531 532 /** 533 * intel_fb_is_ccs_aux_plane: Check if a framebuffer color plane is a CCS AUX plane 534 * @fb: Framebuffer 535 * @color_plane: color plane index to check 536 * 537 * Returns: 538 * Returns %true if @fb's color plane at index @color_plane is a CCS AUX plane. 539 */ 540 bool intel_fb_is_ccs_aux_plane(const struct drm_framebuffer *fb, int color_plane) 541 { 542 const struct intel_modifier_desc *md = lookup_modifier(fb->modifier); 543 544 return ccs_aux_plane_mask(md, fb->format) & BIT(color_plane); 545 } 546 547 /** 548 * intel_fb_is_gen12_ccs_aux_plane: Check if a framebuffer color plane is a GEN12 CCS AUX plane 549 * @fb: Framebuffer 550 * @color_plane: color plane index to check 551 * 552 * Returns: 553 * Returns %true if @fb's color plane at index @color_plane is a GEN12 CCS AUX plane. 554 */ 555 static bool intel_fb_is_gen12_ccs_aux_plane(const struct drm_framebuffer *fb, int color_plane) 556 { 557 const struct intel_modifier_desc *md = lookup_modifier(fb->modifier); 558 559 return check_modifier_display_ver_range(md, 12, 14) && 560 ccs_aux_plane_mask(md, fb->format) & BIT(color_plane); 561 } 562 563 /** 564 * intel_fb_rc_ccs_cc_plane: Get the CCS CC color plane index for a framebuffer 565 * @fb: Framebuffer 566 * 567 * Returns: 568 * Returns the index of the color clear plane for @fb, or -1 if @fb is not a 569 * framebuffer using a render compression/color clear modifier. 570 */ 571 int intel_fb_rc_ccs_cc_plane(const struct drm_framebuffer *fb) 572 { 573 const struct intel_modifier_desc *md = lookup_modifier(fb->modifier); 574 575 if (!md->ccs.cc_planes) 576 return -1; 577 578 drm_WARN_ON_ONCE(fb->dev, hweight8(md->ccs.cc_planes) > 1); 579 580 return ilog2((int)md->ccs.cc_planes); 581 } 582 583 static bool is_gen12_ccs_cc_plane(const struct drm_framebuffer *fb, int color_plane) 584 { 585 return intel_fb_rc_ccs_cc_plane(fb) == color_plane; 586 } 587 588 bool is_surface_linear(const struct drm_framebuffer *fb, int color_plane) 589 { 590 return fb->modifier == DRM_FORMAT_MOD_LINEAR || 591 intel_fb_is_gen12_ccs_aux_plane(fb, color_plane) || 592 is_gen12_ccs_cc_plane(fb, color_plane); 593 } 594 595 int main_to_ccs_plane(const struct drm_framebuffer *fb, int main_plane) 596 { 597 drm_WARN_ON(fb->dev, !intel_fb_is_ccs_modifier(fb->modifier) || 598 (main_plane && main_plane >= fb->format->num_planes / 2)); 599 600 return fb->format->num_planes / 2 + main_plane; 601 } 602 603 int skl_ccs_to_main_plane(const struct drm_framebuffer *fb, int ccs_plane) 604 { 605 drm_WARN_ON(fb->dev, !intel_fb_is_ccs_modifier(fb->modifier) || 606 ccs_plane < fb->format->num_planes / 2); 607 608 if (is_gen12_ccs_cc_plane(fb, ccs_plane)) 609 return 0; 610 611 return ccs_plane - fb->format->num_planes / 2; 612 } 613 614 static unsigned int gen12_ccs_aux_stride(struct intel_framebuffer *fb, int ccs_plane) 615 { 616 int main_plane = skl_ccs_to_main_plane(&fb->base, ccs_plane); 617 unsigned int main_stride = fb->base.pitches[main_plane]; 618 unsigned int main_tile_width = intel_tile_width_bytes(&fb->base, main_plane); 619 620 return DIV_ROUND_UP(main_stride, 4 * main_tile_width) * 64; 621 } 622 623 int skl_main_to_aux_plane(const struct drm_framebuffer *fb, int main_plane) 624 { 625 const struct intel_modifier_desc *md = lookup_modifier(fb->modifier); 626 struct drm_i915_private *i915 = to_i915(fb->dev); 627 628 if (md->ccs.packed_aux_planes | md->ccs.planar_aux_planes) 629 return main_to_ccs_plane(fb, main_plane); 630 else if (DISPLAY_VER(i915) < 11 && 631 format_is_yuv_semiplanar(md, fb->format)) 632 return 1; 633 else 634 return 0; 635 } 636 637 unsigned int intel_tile_size(const struct drm_i915_private *i915) 638 { 639 return DISPLAY_VER(i915) == 2 ? 2048 : 4096; 640 } 641 642 unsigned int 643 intel_tile_width_bytes(const struct drm_framebuffer *fb, int color_plane) 644 { 645 struct drm_i915_private *dev_priv = to_i915(fb->dev); 646 unsigned int cpp = fb->format->cpp[color_plane]; 647 648 switch (fb->modifier) { 649 case DRM_FORMAT_MOD_LINEAR: 650 return intel_tile_size(dev_priv); 651 case I915_FORMAT_MOD_X_TILED: 652 if (DISPLAY_VER(dev_priv) == 2) 653 return 128; 654 else 655 return 512; 656 case I915_FORMAT_MOD_4_TILED_DG2_RC_CCS: 657 case I915_FORMAT_MOD_4_TILED_DG2_RC_CCS_CC: 658 case I915_FORMAT_MOD_4_TILED_DG2_MC_CCS: 659 case I915_FORMAT_MOD_4_TILED: 660 /* 661 * Each 4K tile consists of 64B(8*8) subtiles, with 662 * same shape as Y Tile(i.e 4*16B OWords) 663 */ 664 return 128; 665 case I915_FORMAT_MOD_Y_TILED_CCS: 666 if (intel_fb_is_ccs_aux_plane(fb, color_plane)) 667 return 128; 668 fallthrough; 669 case I915_FORMAT_MOD_4_TILED_MTL_RC_CCS: 670 case I915_FORMAT_MOD_4_TILED_MTL_RC_CCS_CC: 671 case I915_FORMAT_MOD_4_TILED_MTL_MC_CCS: 672 case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS: 673 case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC: 674 case I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS: 675 if (intel_fb_is_ccs_aux_plane(fb, color_plane) || 676 is_gen12_ccs_cc_plane(fb, color_plane)) 677 return 64; 678 fallthrough; 679 case I915_FORMAT_MOD_Y_TILED: 680 if (DISPLAY_VER(dev_priv) == 2 || HAS_128_BYTE_Y_TILING(dev_priv)) 681 return 128; 682 else 683 return 512; 684 case I915_FORMAT_MOD_Yf_TILED_CCS: 685 if (intel_fb_is_ccs_aux_plane(fb, color_plane)) 686 return 128; 687 fallthrough; 688 case I915_FORMAT_MOD_Yf_TILED: 689 switch (cpp) { 690 case 1: 691 return 64; 692 case 2: 693 case 4: 694 return 128; 695 case 8: 696 case 16: 697 return 256; 698 default: 699 MISSING_CASE(cpp); 700 return cpp; 701 } 702 break; 703 default: 704 MISSING_CASE(fb->modifier); 705 return cpp; 706 } 707 } 708 709 unsigned int intel_tile_height(const struct drm_framebuffer *fb, int color_plane) 710 { 711 return intel_tile_size(to_i915(fb->dev)) / 712 intel_tile_width_bytes(fb, color_plane); 713 } 714 715 /* 716 * Return the tile dimensions in pixel units, based on the (2 or 4 kbyte) GTT 717 * page tile size. 718 */ 719 static void intel_tile_dims(const struct drm_framebuffer *fb, int color_plane, 720 unsigned int *tile_width, 721 unsigned int *tile_height) 722 { 723 unsigned int tile_width_bytes = intel_tile_width_bytes(fb, color_plane); 724 unsigned int cpp = fb->format->cpp[color_plane]; 725 726 *tile_width = tile_width_bytes / cpp; 727 *tile_height = intel_tile_height(fb, color_plane); 728 } 729 730 /* 731 * Return the tile dimensions in pixel units, based on the tile block size. 732 * The block covers the full GTT page sized tile on all tiled surfaces and 733 * it's a 64 byte portion of the tile on TGL+ CCS surfaces. 734 */ 735 static void intel_tile_block_dims(const struct drm_framebuffer *fb, int color_plane, 736 unsigned int *tile_width, 737 unsigned int *tile_height) 738 { 739 intel_tile_dims(fb, color_plane, tile_width, tile_height); 740 741 if (intel_fb_is_gen12_ccs_aux_plane(fb, color_plane)) 742 *tile_height = 1; 743 } 744 745 unsigned int intel_tile_row_size(const struct drm_framebuffer *fb, int color_plane) 746 { 747 unsigned int tile_width, tile_height; 748 749 intel_tile_dims(fb, color_plane, &tile_width, &tile_height); 750 751 return fb->pitches[color_plane] * tile_height; 752 } 753 754 unsigned int 755 intel_fb_align_height(const struct drm_framebuffer *fb, 756 int color_plane, unsigned int height) 757 { 758 unsigned int tile_height = intel_tile_height(fb, color_plane); 759 760 return ALIGN(height, tile_height); 761 } 762 763 bool intel_fb_modifier_uses_dpt(struct drm_i915_private *i915, u64 modifier) 764 { 765 return HAS_DPT(i915) && modifier != DRM_FORMAT_MOD_LINEAR; 766 } 767 768 bool intel_fb_uses_dpt(const struct drm_framebuffer *fb) 769 { 770 return to_i915(fb->dev)->display.params.enable_dpt && 771 intel_fb_modifier_uses_dpt(to_i915(fb->dev), fb->modifier); 772 } 773 774 void intel_fb_plane_get_subsampling(int *hsub, int *vsub, 775 const struct drm_framebuffer *fb, 776 int color_plane) 777 { 778 int main_plane; 779 780 if (color_plane == 0) { 781 *hsub = 1; 782 *vsub = 1; 783 784 return; 785 } 786 787 /* 788 * TODO: Deduct the subsampling from the char block for all CCS 789 * formats and planes. 790 */ 791 if (!intel_fb_is_gen12_ccs_aux_plane(fb, color_plane)) { 792 *hsub = fb->format->hsub; 793 *vsub = fb->format->vsub; 794 795 return; 796 } 797 798 main_plane = skl_ccs_to_main_plane(fb, color_plane); 799 *hsub = drm_format_info_block_width(fb->format, color_plane) / 800 drm_format_info_block_width(fb->format, main_plane); 801 802 /* 803 * The min stride check in the core framebuffer_check() function 804 * assumes that format->hsub applies to every plane except for the 805 * first plane. That's incorrect for the CCS AUX plane of the first 806 * plane, but for the above check to pass we must define the block 807 * width with that subsampling applied to it. Adjust the width here 808 * accordingly, so we can calculate the actual subsampling factor. 809 */ 810 if (main_plane == 0) 811 *hsub *= fb->format->hsub; 812 813 *vsub = 32; 814 } 815 816 static void intel_fb_plane_dims(const struct intel_framebuffer *fb, int color_plane, int *w, int *h) 817 { 818 int main_plane = intel_fb_is_ccs_aux_plane(&fb->base, color_plane) ? 819 skl_ccs_to_main_plane(&fb->base, color_plane) : 0; 820 unsigned int main_width = fb->base.width; 821 unsigned int main_height = fb->base.height; 822 int main_hsub, main_vsub; 823 int hsub, vsub; 824 825 intel_fb_plane_get_subsampling(&main_hsub, &main_vsub, &fb->base, main_plane); 826 intel_fb_plane_get_subsampling(&hsub, &vsub, &fb->base, color_plane); 827 828 *w = DIV_ROUND_UP(main_width, main_hsub * hsub); 829 *h = DIV_ROUND_UP(main_height, main_vsub * vsub); 830 } 831 832 static u32 intel_adjust_tile_offset(int *x, int *y, 833 unsigned int tile_width, 834 unsigned int tile_height, 835 unsigned int tile_size, 836 unsigned int pitch_tiles, 837 u32 old_offset, 838 u32 new_offset) 839 { 840 unsigned int pitch_pixels = pitch_tiles * tile_width; 841 unsigned int tiles; 842 843 WARN_ON(old_offset & (tile_size - 1)); 844 WARN_ON(new_offset & (tile_size - 1)); 845 WARN_ON(new_offset > old_offset); 846 847 tiles = (old_offset - new_offset) / tile_size; 848 849 *y += tiles / pitch_tiles * tile_height; 850 *x += tiles % pitch_tiles * tile_width; 851 852 /* minimize x in case it got needlessly big */ 853 *y += *x / pitch_pixels * tile_height; 854 *x %= pitch_pixels; 855 856 return new_offset; 857 } 858 859 static u32 intel_adjust_linear_offset(int *x, int *y, 860 unsigned int cpp, 861 unsigned int pitch, 862 u32 old_offset, 863 u32 new_offset) 864 { 865 old_offset += *y * pitch + *x * cpp; 866 867 *y = (old_offset - new_offset) / pitch; 868 *x = ((old_offset - new_offset) - *y * pitch) / cpp; 869 870 return new_offset; 871 } 872 873 static u32 intel_adjust_aligned_offset(int *x, int *y, 874 const struct drm_framebuffer *fb, 875 int color_plane, 876 unsigned int rotation, 877 unsigned int pitch, 878 u32 old_offset, u32 new_offset) 879 { 880 struct drm_i915_private *i915 = to_i915(fb->dev); 881 unsigned int cpp = fb->format->cpp[color_plane]; 882 883 drm_WARN_ON(&i915->drm, new_offset > old_offset); 884 885 if (!is_surface_linear(fb, color_plane)) { 886 unsigned int tile_size, tile_width, tile_height; 887 unsigned int pitch_tiles; 888 889 tile_size = intel_tile_size(i915); 890 intel_tile_dims(fb, color_plane, &tile_width, &tile_height); 891 892 if (drm_rotation_90_or_270(rotation)) { 893 pitch_tiles = pitch / tile_height; 894 swap(tile_width, tile_height); 895 } else { 896 pitch_tiles = pitch / (tile_width * cpp); 897 } 898 899 intel_adjust_tile_offset(x, y, tile_width, tile_height, 900 tile_size, pitch_tiles, 901 old_offset, new_offset); 902 } else { 903 intel_adjust_linear_offset(x, y, cpp, pitch, 904 old_offset, new_offset); 905 } 906 907 return new_offset; 908 } 909 910 /* 911 * Adjust the tile offset by moving the difference into 912 * the x/y offsets. 913 */ 914 u32 intel_plane_adjust_aligned_offset(int *x, int *y, 915 const struct intel_plane_state *state, 916 int color_plane, 917 u32 old_offset, u32 new_offset) 918 { 919 return intel_adjust_aligned_offset(x, y, state->hw.fb, color_plane, 920 state->hw.rotation, 921 state->view.color_plane[color_plane].mapping_stride, 922 old_offset, new_offset); 923 } 924 925 /* 926 * Computes the aligned offset to the base tile and adjusts 927 * x, y. bytes per pixel is assumed to be a power-of-two. 928 * 929 * In the 90/270 rotated case, x and y are assumed 930 * to be already rotated to match the rotated GTT view, and 931 * pitch is the tile_height aligned framebuffer height. 932 * 933 * This function is used when computing the derived information 934 * under intel_framebuffer, so using any of that information 935 * here is not allowed. Anything under drm_framebuffer can be 936 * used. This is why the user has to pass in the pitch since it 937 * is specified in the rotated orientation. 938 */ 939 static u32 intel_compute_aligned_offset(struct drm_i915_private *i915, 940 int *x, int *y, 941 const struct drm_framebuffer *fb, 942 int color_plane, 943 unsigned int pitch, 944 unsigned int rotation, 945 unsigned int alignment) 946 { 947 unsigned int cpp = fb->format->cpp[color_plane]; 948 u32 offset, offset_aligned; 949 950 if (!is_surface_linear(fb, color_plane)) { 951 unsigned int tile_size, tile_width, tile_height; 952 unsigned int tile_rows, tiles, pitch_tiles; 953 954 tile_size = intel_tile_size(i915); 955 intel_tile_dims(fb, color_plane, &tile_width, &tile_height); 956 957 if (drm_rotation_90_or_270(rotation)) { 958 pitch_tiles = pitch / tile_height; 959 swap(tile_width, tile_height); 960 } else { 961 pitch_tiles = pitch / (tile_width * cpp); 962 } 963 964 tile_rows = *y / tile_height; 965 *y %= tile_height; 966 967 tiles = *x / tile_width; 968 *x %= tile_width; 969 970 offset = (tile_rows * pitch_tiles + tiles) * tile_size; 971 972 offset_aligned = offset; 973 if (alignment) 974 offset_aligned = rounddown(offset_aligned, alignment); 975 976 intel_adjust_tile_offset(x, y, tile_width, tile_height, 977 tile_size, pitch_tiles, 978 offset, offset_aligned); 979 } else { 980 offset = *y * pitch + *x * cpp; 981 offset_aligned = offset; 982 if (alignment) { 983 offset_aligned = rounddown(offset_aligned, alignment); 984 *y = (offset % alignment) / pitch; 985 *x = ((offset % alignment) - *y * pitch) / cpp; 986 } else { 987 *y = *x = 0; 988 } 989 } 990 991 return offset_aligned; 992 } 993 994 u32 intel_plane_compute_aligned_offset(int *x, int *y, 995 const struct intel_plane_state *state, 996 int color_plane) 997 { 998 struct intel_plane *plane = to_intel_plane(state->uapi.plane); 999 struct drm_i915_private *i915 = to_i915(plane->base.dev); 1000 const struct drm_framebuffer *fb = state->hw.fb; 1001 unsigned int rotation = state->hw.rotation; 1002 unsigned int pitch = state->view.color_plane[color_plane].mapping_stride; 1003 unsigned int alignment = plane->min_alignment(plane, fb, color_plane); 1004 1005 return intel_compute_aligned_offset(i915, x, y, fb, color_plane, 1006 pitch, rotation, alignment); 1007 } 1008 1009 /* Convert the fb->offset[] into x/y offsets */ 1010 static int intel_fb_offset_to_xy(int *x, int *y, 1011 const struct drm_framebuffer *fb, 1012 int color_plane) 1013 { 1014 struct drm_i915_private *i915 = to_i915(fb->dev); 1015 unsigned int height, alignment, unused; 1016 1017 if (fb->modifier != DRM_FORMAT_MOD_LINEAR) 1018 alignment = intel_tile_size(i915); 1019 else 1020 alignment = 0; 1021 1022 if (alignment != 0 && fb->offsets[color_plane] % alignment) { 1023 drm_dbg_kms(&i915->drm, 1024 "Misaligned offset 0x%08x for color plane %d\n", 1025 fb->offsets[color_plane], color_plane); 1026 return -EINVAL; 1027 } 1028 1029 height = drm_format_info_plane_height(fb->format, fb->height, color_plane); 1030 height = ALIGN(height, intel_tile_height(fb, color_plane)); 1031 1032 /* Catch potential overflows early */ 1033 if (check_add_overflow(mul_u32_u32(height, fb->pitches[color_plane]), 1034 fb->offsets[color_plane], &unused)) { 1035 drm_dbg_kms(&i915->drm, 1036 "Bad offset 0x%08x or pitch %d for color plane %d\n", 1037 fb->offsets[color_plane], fb->pitches[color_plane], 1038 color_plane); 1039 return -ERANGE; 1040 } 1041 1042 *x = 0; 1043 *y = 0; 1044 1045 intel_adjust_aligned_offset(x, y, 1046 fb, color_plane, DRM_MODE_ROTATE_0, 1047 fb->pitches[color_plane], 1048 fb->offsets[color_plane], 0); 1049 1050 return 0; 1051 } 1052 1053 static int intel_fb_check_ccs_xy(const struct drm_framebuffer *fb, int ccs_plane, int x, int y) 1054 { 1055 struct drm_i915_private *i915 = to_i915(fb->dev); 1056 const struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb); 1057 int main_plane; 1058 int hsub, vsub; 1059 int tile_width, tile_height; 1060 int ccs_x, ccs_y; 1061 int main_x, main_y; 1062 1063 if (!intel_fb_is_ccs_aux_plane(fb, ccs_plane)) 1064 return 0; 1065 1066 /* 1067 * While all the tile dimensions are based on a 2k or 4k GTT page size 1068 * here the main and CCS coordinates must match only within a (64 byte 1069 * on TGL+) block inside the tile. 1070 */ 1071 intel_tile_block_dims(fb, ccs_plane, &tile_width, &tile_height); 1072 intel_fb_plane_get_subsampling(&hsub, &vsub, fb, ccs_plane); 1073 1074 tile_width *= hsub; 1075 tile_height *= vsub; 1076 1077 ccs_x = (x * hsub) % tile_width; 1078 ccs_y = (y * vsub) % tile_height; 1079 1080 main_plane = skl_ccs_to_main_plane(fb, ccs_plane); 1081 main_x = intel_fb->normal_view.color_plane[main_plane].x % tile_width; 1082 main_y = intel_fb->normal_view.color_plane[main_plane].y % tile_height; 1083 1084 /* 1085 * CCS doesn't have its own x/y offset register, so the intra CCS tile 1086 * x/y offsets must match between CCS and the main surface. 1087 */ 1088 if (main_x != ccs_x || main_y != ccs_y) { 1089 drm_dbg_kms(&i915->drm, 1090 "Bad CCS x/y (main %d,%d ccs %d,%d) full (main %d,%d ccs %d,%d)\n", 1091 main_x, main_y, 1092 ccs_x, ccs_y, 1093 intel_fb->normal_view.color_plane[main_plane].x, 1094 intel_fb->normal_view.color_plane[main_plane].y, 1095 x, y); 1096 return -EINVAL; 1097 } 1098 1099 return 0; 1100 } 1101 1102 static bool intel_plane_can_remap(const struct intel_plane_state *plane_state) 1103 { 1104 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); 1105 struct drm_i915_private *i915 = to_i915(plane->base.dev); 1106 const struct drm_framebuffer *fb = plane_state->hw.fb; 1107 int i; 1108 1109 /* We don't want to deal with remapping with cursors */ 1110 if (plane->id == PLANE_CURSOR) 1111 return false; 1112 1113 /* 1114 * The display engine limits already match/exceed the 1115 * render engine limits, so not much point in remapping. 1116 * Would also need to deal with the fence POT alignment 1117 * and gen2 2KiB GTT tile size. 1118 */ 1119 if (DISPLAY_VER(i915) < 4) 1120 return false; 1121 1122 /* 1123 * The new CCS hash mode isn't compatible with remapping as 1124 * the virtual address of the pages affects the compressed data. 1125 */ 1126 if (intel_fb_is_ccs_modifier(fb->modifier)) 1127 return false; 1128 1129 /* Linear needs a page aligned stride for remapping */ 1130 if (fb->modifier == DRM_FORMAT_MOD_LINEAR) { 1131 unsigned int alignment = intel_tile_size(i915) - 1; 1132 1133 for (i = 0; i < fb->format->num_planes; i++) { 1134 if (fb->pitches[i] & alignment) 1135 return false; 1136 } 1137 } 1138 1139 return true; 1140 } 1141 1142 bool intel_fb_needs_pot_stride_remap(const struct intel_framebuffer *fb) 1143 { 1144 struct drm_i915_private *i915 = to_i915(fb->base.dev); 1145 1146 return (IS_ALDERLAKE_P(i915) || DISPLAY_VER(i915) >= 14) && 1147 intel_fb_uses_dpt(&fb->base); 1148 } 1149 1150 static int intel_fb_pitch(const struct intel_framebuffer *fb, int color_plane, unsigned int rotation) 1151 { 1152 if (drm_rotation_90_or_270(rotation)) 1153 return fb->rotated_view.color_plane[color_plane].mapping_stride; 1154 else if (intel_fb_needs_pot_stride_remap(fb)) 1155 return fb->remapped_view.color_plane[color_plane].mapping_stride; 1156 else 1157 return fb->normal_view.color_plane[color_plane].mapping_stride; 1158 } 1159 1160 static bool intel_plane_needs_remap(const struct intel_plane_state *plane_state) 1161 { 1162 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); 1163 const struct intel_framebuffer *fb = to_intel_framebuffer(plane_state->hw.fb); 1164 unsigned int rotation = plane_state->hw.rotation; 1165 u32 stride, max_stride; 1166 1167 /* 1168 * No remapping for invisible planes since we don't have 1169 * an actual source viewport to remap. 1170 */ 1171 if (!plane_state->uapi.visible) 1172 return false; 1173 1174 if (!intel_plane_can_remap(plane_state)) 1175 return false; 1176 1177 /* 1178 * FIXME: aux plane limits on gen9+ are 1179 * unclear in Bspec, for now no checking. 1180 */ 1181 stride = intel_fb_pitch(fb, 0, rotation); 1182 max_stride = plane->max_stride(plane, fb->base.format->format, 1183 fb->base.modifier, rotation); 1184 1185 return stride > max_stride; 1186 } 1187 1188 static int convert_plane_offset_to_xy(const struct intel_framebuffer *fb, int color_plane, 1189 int plane_width, int *x, int *y) 1190 { 1191 struct drm_i915_gem_object *obj = intel_fb_obj(&fb->base); 1192 int ret; 1193 1194 ret = intel_fb_offset_to_xy(x, y, &fb->base, color_plane); 1195 if (ret) { 1196 drm_dbg_kms(fb->base.dev, 1197 "bad fb plane %d offset: 0x%x\n", 1198 color_plane, fb->base.offsets[color_plane]); 1199 return ret; 1200 } 1201 1202 ret = intel_fb_check_ccs_xy(&fb->base, color_plane, *x, *y); 1203 if (ret) 1204 return ret; 1205 1206 /* 1207 * The fence (if used) is aligned to the start of the object 1208 * so having the framebuffer wrap around across the edge of the 1209 * fenced region doesn't really work. We have no API to configure 1210 * the fence start offset within the object (nor could we probably 1211 * on gen2/3). So it's just easier if we just require that the 1212 * fb layout agrees with the fence layout. We already check that the 1213 * fb stride matches the fence stride elsewhere. 1214 */ 1215 if (color_plane == 0 && i915_gem_object_is_tiled(obj) && 1216 (*x + plane_width) * fb->base.format->cpp[color_plane] > fb->base.pitches[color_plane]) { 1217 drm_dbg_kms(fb->base.dev, 1218 "bad fb plane %d offset: 0x%x\n", 1219 color_plane, fb->base.offsets[color_plane]); 1220 return -EINVAL; 1221 } 1222 1223 return 0; 1224 } 1225 1226 static u32 calc_plane_aligned_offset(const struct intel_framebuffer *fb, int color_plane, int *x, int *y) 1227 { 1228 struct drm_i915_private *i915 = to_i915(fb->base.dev); 1229 unsigned int tile_size = intel_tile_size(i915); 1230 u32 offset; 1231 1232 offset = intel_compute_aligned_offset(i915, x, y, &fb->base, color_plane, 1233 fb->base.pitches[color_plane], 1234 DRM_MODE_ROTATE_0, 1235 tile_size); 1236 1237 return offset / tile_size; 1238 } 1239 1240 struct fb_plane_view_dims { 1241 unsigned int width, height; 1242 unsigned int tile_width, tile_height; 1243 }; 1244 1245 static void init_plane_view_dims(const struct intel_framebuffer *fb, int color_plane, 1246 unsigned int width, unsigned int height, 1247 struct fb_plane_view_dims *dims) 1248 { 1249 dims->width = width; 1250 dims->height = height; 1251 1252 intel_tile_dims(&fb->base, color_plane, &dims->tile_width, &dims->tile_height); 1253 } 1254 1255 static unsigned int 1256 plane_view_src_stride_tiles(const struct intel_framebuffer *fb, int color_plane, 1257 const struct fb_plane_view_dims *dims) 1258 { 1259 return DIV_ROUND_UP(fb->base.pitches[color_plane], 1260 dims->tile_width * fb->base.format->cpp[color_plane]); 1261 } 1262 1263 static unsigned int 1264 plane_view_dst_stride_tiles(const struct intel_framebuffer *fb, int color_plane, 1265 unsigned int pitch_tiles) 1266 { 1267 if (intel_fb_needs_pot_stride_remap(fb)) { 1268 /* 1269 * ADL_P, the only platform needing a POT stride has a minimum 1270 * of 8 main surface tiles. 1271 */ 1272 return roundup_pow_of_two(max(pitch_tiles, 8u)); 1273 } else { 1274 return pitch_tiles; 1275 } 1276 } 1277 1278 static unsigned int 1279 plane_view_scanout_stride(const struct intel_framebuffer *fb, int color_plane, 1280 unsigned int tile_width, 1281 unsigned int src_stride_tiles, unsigned int dst_stride_tiles) 1282 { 1283 struct drm_i915_private *i915 = to_i915(fb->base.dev); 1284 unsigned int stride_tiles; 1285 1286 if ((IS_ALDERLAKE_P(i915) || DISPLAY_VER(i915) >= 14) && 1287 src_stride_tiles < dst_stride_tiles) 1288 stride_tiles = src_stride_tiles; 1289 else 1290 stride_tiles = dst_stride_tiles; 1291 1292 return stride_tiles * tile_width * fb->base.format->cpp[color_plane]; 1293 } 1294 1295 static unsigned int 1296 plane_view_width_tiles(const struct intel_framebuffer *fb, int color_plane, 1297 const struct fb_plane_view_dims *dims, 1298 int x) 1299 { 1300 return DIV_ROUND_UP(x + dims->width, dims->tile_width); 1301 } 1302 1303 static unsigned int 1304 plane_view_height_tiles(const struct intel_framebuffer *fb, int color_plane, 1305 const struct fb_plane_view_dims *dims, 1306 int y) 1307 { 1308 return DIV_ROUND_UP(y + dims->height, dims->tile_height); 1309 } 1310 1311 static unsigned int 1312 plane_view_linear_tiles(const struct intel_framebuffer *fb, int color_plane, 1313 const struct fb_plane_view_dims *dims, 1314 int x, int y) 1315 { 1316 struct drm_i915_private *i915 = to_i915(fb->base.dev); 1317 unsigned int size; 1318 1319 size = (y + dims->height) * fb->base.pitches[color_plane] + 1320 x * fb->base.format->cpp[color_plane]; 1321 1322 return DIV_ROUND_UP(size, intel_tile_size(i915)); 1323 } 1324 1325 #define assign_chk_ovf(i915, var, val) ({ \ 1326 drm_WARN_ON(&(i915)->drm, overflows_type(val, var)); \ 1327 (var) = (val); \ 1328 }) 1329 1330 #define assign_bfld_chk_ovf(i915, var, val) ({ \ 1331 (var) = (val); \ 1332 drm_WARN_ON(&(i915)->drm, (var) != (val)); \ 1333 (var); \ 1334 }) 1335 1336 static u32 calc_plane_remap_info(const struct intel_framebuffer *fb, int color_plane, 1337 const struct fb_plane_view_dims *dims, 1338 u32 obj_offset, u32 gtt_offset, int x, int y, 1339 struct intel_fb_view *view) 1340 { 1341 struct drm_i915_private *i915 = to_i915(fb->base.dev); 1342 struct intel_remapped_plane_info *remap_info = &view->gtt.remapped.plane[color_plane]; 1343 struct i915_color_plane_view *color_plane_info = &view->color_plane[color_plane]; 1344 unsigned int tile_width = dims->tile_width; 1345 unsigned int tile_height = dims->tile_height; 1346 unsigned int tile_size = intel_tile_size(i915); 1347 struct drm_rect r; 1348 u32 size = 0; 1349 1350 assign_bfld_chk_ovf(i915, remap_info->offset, obj_offset); 1351 1352 if (intel_fb_is_gen12_ccs_aux_plane(&fb->base, color_plane)) { 1353 remap_info->linear = 1; 1354 1355 assign_chk_ovf(i915, remap_info->size, 1356 plane_view_linear_tiles(fb, color_plane, dims, x, y)); 1357 } else { 1358 remap_info->linear = 0; 1359 1360 assign_chk_ovf(i915, remap_info->src_stride, 1361 plane_view_src_stride_tiles(fb, color_plane, dims)); 1362 assign_chk_ovf(i915, remap_info->width, 1363 plane_view_width_tiles(fb, color_plane, dims, x)); 1364 assign_chk_ovf(i915, remap_info->height, 1365 plane_view_height_tiles(fb, color_plane, dims, y)); 1366 } 1367 1368 if (view->gtt.type == I915_GTT_VIEW_ROTATED) { 1369 drm_WARN_ON(&i915->drm, remap_info->linear); 1370 check_array_bounds(i915, view->gtt.rotated.plane, color_plane); 1371 1372 assign_chk_ovf(i915, remap_info->dst_stride, 1373 plane_view_dst_stride_tiles(fb, color_plane, remap_info->height)); 1374 1375 /* rotate the x/y offsets to match the GTT view */ 1376 drm_rect_init(&r, x, y, dims->width, dims->height); 1377 drm_rect_rotate(&r, 1378 remap_info->width * tile_width, 1379 remap_info->height * tile_height, 1380 DRM_MODE_ROTATE_270); 1381 1382 color_plane_info->x = r.x1; 1383 color_plane_info->y = r.y1; 1384 1385 color_plane_info->mapping_stride = remap_info->dst_stride * tile_height; 1386 color_plane_info->scanout_stride = color_plane_info->mapping_stride; 1387 1388 size += remap_info->dst_stride * remap_info->width; 1389 1390 /* rotate the tile dimensions to match the GTT view */ 1391 swap(tile_width, tile_height); 1392 } else { 1393 drm_WARN_ON(&i915->drm, view->gtt.type != I915_GTT_VIEW_REMAPPED); 1394 1395 check_array_bounds(i915, view->gtt.remapped.plane, color_plane); 1396 1397 if (view->gtt.remapped.plane_alignment) { 1398 u32 aligned_offset = ALIGN(gtt_offset, 1399 view->gtt.remapped.plane_alignment); 1400 1401 size += aligned_offset - gtt_offset; 1402 gtt_offset = aligned_offset; 1403 } 1404 1405 color_plane_info->x = x; 1406 color_plane_info->y = y; 1407 1408 if (remap_info->linear) { 1409 color_plane_info->mapping_stride = fb->base.pitches[color_plane]; 1410 color_plane_info->scanout_stride = color_plane_info->mapping_stride; 1411 1412 size += remap_info->size; 1413 } else { 1414 unsigned int dst_stride; 1415 1416 /* 1417 * The hardware automagically calculates the CCS AUX surface 1418 * stride from the main surface stride so can't really remap a 1419 * smaller subset (unless we'd remap in whole AUX page units). 1420 */ 1421 if (intel_fb_needs_pot_stride_remap(fb) && 1422 intel_fb_is_ccs_modifier(fb->base.modifier)) 1423 dst_stride = remap_info->src_stride; 1424 else 1425 dst_stride = remap_info->width; 1426 1427 dst_stride = plane_view_dst_stride_tiles(fb, color_plane, dst_stride); 1428 1429 assign_chk_ovf(i915, remap_info->dst_stride, dst_stride); 1430 color_plane_info->mapping_stride = dst_stride * 1431 tile_width * 1432 fb->base.format->cpp[color_plane]; 1433 color_plane_info->scanout_stride = 1434 plane_view_scanout_stride(fb, color_plane, tile_width, 1435 remap_info->src_stride, 1436 dst_stride); 1437 1438 size += dst_stride * remap_info->height; 1439 } 1440 } 1441 1442 /* 1443 * We only keep the x/y offsets, so push all of the gtt offset into 1444 * the x/y offsets. x,y will hold the first pixel of the framebuffer 1445 * plane from the start of the remapped/rotated gtt mapping. 1446 */ 1447 if (remap_info->linear) 1448 intel_adjust_linear_offset(&color_plane_info->x, &color_plane_info->y, 1449 fb->base.format->cpp[color_plane], 1450 color_plane_info->mapping_stride, 1451 gtt_offset * tile_size, 0); 1452 else 1453 intel_adjust_tile_offset(&color_plane_info->x, &color_plane_info->y, 1454 tile_width, tile_height, 1455 tile_size, remap_info->dst_stride, 1456 gtt_offset * tile_size, 0); 1457 1458 return size; 1459 } 1460 1461 #undef assign_chk_ovf 1462 1463 /* Return number of tiles @color_plane needs. */ 1464 static unsigned int 1465 calc_plane_normal_size(const struct intel_framebuffer *fb, int color_plane, 1466 const struct fb_plane_view_dims *dims, 1467 int x, int y) 1468 { 1469 unsigned int tiles; 1470 1471 if (is_surface_linear(&fb->base, color_plane)) { 1472 tiles = plane_view_linear_tiles(fb, color_plane, dims, x, y); 1473 } else { 1474 tiles = plane_view_src_stride_tiles(fb, color_plane, dims) * 1475 plane_view_height_tiles(fb, color_plane, dims, y); 1476 /* 1477 * If the plane isn't horizontally tile aligned, 1478 * we need one more tile. 1479 */ 1480 if (x != 0) 1481 tiles++; 1482 } 1483 1484 return tiles; 1485 } 1486 1487 static void intel_fb_view_init(struct drm_i915_private *i915, struct intel_fb_view *view, 1488 enum i915_gtt_view_type view_type) 1489 { 1490 memset(view, 0, sizeof(*view)); 1491 view->gtt.type = view_type; 1492 1493 if (view_type == I915_GTT_VIEW_REMAPPED && 1494 (IS_ALDERLAKE_P(i915) || DISPLAY_VER(i915) >= 14)) 1495 view->gtt.remapped.plane_alignment = SZ_2M / PAGE_SIZE; 1496 } 1497 1498 bool intel_fb_supports_90_270_rotation(const struct intel_framebuffer *fb) 1499 { 1500 if (DISPLAY_VER(to_i915(fb->base.dev)) >= 13) 1501 return false; 1502 1503 return fb->base.modifier == I915_FORMAT_MOD_Y_TILED || 1504 fb->base.modifier == I915_FORMAT_MOD_Yf_TILED; 1505 } 1506 1507 static unsigned int intel_fb_min_alignment(const struct drm_framebuffer *fb) 1508 { 1509 struct drm_i915_private *i915 = to_i915(fb->dev); 1510 struct intel_plane *plane; 1511 unsigned int min_alignment = 0; 1512 1513 for_each_intel_plane(&i915->drm, plane) { 1514 unsigned int plane_min_alignment; 1515 1516 if (!drm_plane_has_format(&plane->base, fb->format->format, fb->modifier)) 1517 continue; 1518 1519 plane_min_alignment = plane->min_alignment(plane, fb, 0); 1520 1521 drm_WARN_ON(&i915->drm, plane_min_alignment && 1522 !is_power_of_2(plane_min_alignment)); 1523 1524 if (intel_plane_needs_physical(plane)) 1525 continue; 1526 1527 min_alignment = max(min_alignment, plane_min_alignment); 1528 } 1529 1530 return min_alignment; 1531 } 1532 1533 int intel_fill_fb_info(struct drm_i915_private *i915, struct intel_framebuffer *fb) 1534 { 1535 struct drm_i915_gem_object *obj = intel_fb_obj(&fb->base); 1536 u32 gtt_offset_rotated = 0; 1537 u32 gtt_offset_remapped = 0; 1538 unsigned int max_size = 0; 1539 int i, num_planes = fb->base.format->num_planes; 1540 unsigned int tile_size = intel_tile_size(i915); 1541 1542 intel_fb_view_init(i915, &fb->normal_view, I915_GTT_VIEW_NORMAL); 1543 1544 drm_WARN_ON(&i915->drm, 1545 intel_fb_supports_90_270_rotation(fb) && 1546 intel_fb_needs_pot_stride_remap(fb)); 1547 1548 if (intel_fb_supports_90_270_rotation(fb)) 1549 intel_fb_view_init(i915, &fb->rotated_view, I915_GTT_VIEW_ROTATED); 1550 if (intel_fb_needs_pot_stride_remap(fb)) 1551 intel_fb_view_init(i915, &fb->remapped_view, I915_GTT_VIEW_REMAPPED); 1552 1553 for (i = 0; i < num_planes; i++) { 1554 struct fb_plane_view_dims view_dims; 1555 unsigned int width, height; 1556 unsigned int size; 1557 u32 offset; 1558 int x, y; 1559 int ret; 1560 1561 /* 1562 * Plane 2 of Render Compression with Clear Color fb modifier 1563 * is consumed by the driver and not passed to DE. Skip the 1564 * arithmetic related to alignment and offset calculation. 1565 */ 1566 if (is_gen12_ccs_cc_plane(&fb->base, i)) { 1567 if (IS_ALIGNED(fb->base.offsets[i], PAGE_SIZE)) 1568 continue; 1569 else 1570 return -EINVAL; 1571 } 1572 1573 intel_fb_plane_dims(fb, i, &width, &height); 1574 1575 ret = convert_plane_offset_to_xy(fb, i, width, &x, &y); 1576 if (ret) 1577 return ret; 1578 1579 init_plane_view_dims(fb, i, width, height, &view_dims); 1580 1581 /* 1582 * First pixel of the framebuffer from 1583 * the start of the normal gtt mapping. 1584 */ 1585 fb->normal_view.color_plane[i].x = x; 1586 fb->normal_view.color_plane[i].y = y; 1587 fb->normal_view.color_plane[i].mapping_stride = fb->base.pitches[i]; 1588 fb->normal_view.color_plane[i].scanout_stride = 1589 fb->normal_view.color_plane[i].mapping_stride; 1590 1591 offset = calc_plane_aligned_offset(fb, i, &x, &y); 1592 1593 if (intel_fb_supports_90_270_rotation(fb)) 1594 gtt_offset_rotated += calc_plane_remap_info(fb, i, &view_dims, 1595 offset, gtt_offset_rotated, x, y, 1596 &fb->rotated_view); 1597 1598 if (intel_fb_needs_pot_stride_remap(fb)) 1599 gtt_offset_remapped += calc_plane_remap_info(fb, i, &view_dims, 1600 offset, gtt_offset_remapped, x, y, 1601 &fb->remapped_view); 1602 1603 size = calc_plane_normal_size(fb, i, &view_dims, x, y); 1604 /* how many tiles in total needed in the bo */ 1605 max_size = max(max_size, offset + size); 1606 } 1607 1608 if (mul_u32_u32(max_size, tile_size) > intel_bo_to_drm_bo(obj)->size) { 1609 drm_dbg_kms(&i915->drm, 1610 "fb too big for bo (need %llu bytes, have %zu bytes)\n", 1611 mul_u32_u32(max_size, tile_size), intel_bo_to_drm_bo(obj)->size); 1612 return -EINVAL; 1613 } 1614 1615 fb->min_alignment = intel_fb_min_alignment(&fb->base); 1616 1617 return 0; 1618 } 1619 1620 static void intel_plane_remap_gtt(struct intel_plane_state *plane_state) 1621 { 1622 struct drm_i915_private *i915 = 1623 to_i915(plane_state->uapi.plane->dev); 1624 struct drm_framebuffer *fb = plane_state->hw.fb; 1625 struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb); 1626 unsigned int rotation = plane_state->hw.rotation; 1627 int i, num_planes = fb->format->num_planes; 1628 unsigned int src_x, src_y; 1629 unsigned int src_w, src_h; 1630 u32 gtt_offset = 0; 1631 1632 intel_fb_view_init(i915, &plane_state->view, 1633 drm_rotation_90_or_270(rotation) ? I915_GTT_VIEW_ROTATED : 1634 I915_GTT_VIEW_REMAPPED); 1635 1636 src_x = plane_state->uapi.src.x1 >> 16; 1637 src_y = plane_state->uapi.src.y1 >> 16; 1638 src_w = drm_rect_width(&plane_state->uapi.src) >> 16; 1639 src_h = drm_rect_height(&plane_state->uapi.src) >> 16; 1640 1641 drm_WARN_ON(&i915->drm, intel_fb_is_ccs_modifier(fb->modifier)); 1642 1643 /* Make src coordinates relative to the viewport */ 1644 drm_rect_translate(&plane_state->uapi.src, 1645 -(src_x << 16), -(src_y << 16)); 1646 1647 /* Rotate src coordinates to match rotated GTT view */ 1648 if (drm_rotation_90_or_270(rotation)) 1649 drm_rect_rotate(&plane_state->uapi.src, 1650 src_w << 16, src_h << 16, 1651 DRM_MODE_ROTATE_270); 1652 1653 for (i = 0; i < num_planes; i++) { 1654 unsigned int hsub = i ? fb->format->hsub : 1; 1655 unsigned int vsub = i ? fb->format->vsub : 1; 1656 struct fb_plane_view_dims view_dims; 1657 unsigned int width, height; 1658 unsigned int x, y; 1659 u32 offset; 1660 1661 x = src_x / hsub; 1662 y = src_y / vsub; 1663 width = src_w / hsub; 1664 height = src_h / vsub; 1665 1666 init_plane_view_dims(intel_fb, i, width, height, &view_dims); 1667 1668 /* 1669 * First pixel of the src viewport from the 1670 * start of the normal gtt mapping. 1671 */ 1672 x += intel_fb->normal_view.color_plane[i].x; 1673 y += intel_fb->normal_view.color_plane[i].y; 1674 1675 offset = calc_plane_aligned_offset(intel_fb, i, &x, &y); 1676 1677 gtt_offset += calc_plane_remap_info(intel_fb, i, &view_dims, 1678 offset, gtt_offset, x, y, 1679 &plane_state->view); 1680 } 1681 } 1682 1683 void intel_fb_fill_view(const struct intel_framebuffer *fb, unsigned int rotation, 1684 struct intel_fb_view *view) 1685 { 1686 if (drm_rotation_90_or_270(rotation)) 1687 *view = fb->rotated_view; 1688 else if (intel_fb_needs_pot_stride_remap(fb)) 1689 *view = fb->remapped_view; 1690 else 1691 *view = fb->normal_view; 1692 } 1693 1694 static 1695 u32 intel_fb_max_stride(struct drm_i915_private *dev_priv, 1696 u32 pixel_format, u64 modifier) 1697 { 1698 /* 1699 * Arbitrary limit for gen4+ chosen to match the 1700 * render engine max stride. 1701 * 1702 * The new CCS hash mode makes remapping impossible 1703 */ 1704 if (DISPLAY_VER(dev_priv) < 4 || intel_fb_is_ccs_modifier(modifier) || 1705 intel_fb_modifier_uses_dpt(dev_priv, modifier)) 1706 return intel_plane_fb_max_stride(dev_priv, pixel_format, modifier); 1707 else if (DISPLAY_VER(dev_priv) >= 7) 1708 return 256 * 1024; 1709 else 1710 return 128 * 1024; 1711 } 1712 1713 static unsigned int 1714 intel_fb_stride_alignment(const struct drm_framebuffer *fb, int color_plane) 1715 { 1716 struct drm_i915_private *dev_priv = to_i915(fb->dev); 1717 unsigned int tile_width; 1718 1719 if (is_surface_linear(fb, color_plane)) { 1720 unsigned int max_stride = intel_plane_fb_max_stride(dev_priv, 1721 fb->format->format, 1722 fb->modifier); 1723 1724 /* 1725 * To make remapping with linear generally feasible 1726 * we need the stride to be page aligned. 1727 */ 1728 if (fb->pitches[color_plane] > max_stride && 1729 !intel_fb_is_ccs_modifier(fb->modifier)) 1730 return intel_tile_size(dev_priv); 1731 else 1732 return 64; 1733 } 1734 1735 tile_width = intel_tile_width_bytes(fb, color_plane); 1736 if (intel_fb_is_ccs_modifier(fb->modifier)) { 1737 /* 1738 * On TGL the surface stride must be 4 tile aligned, mapped by 1739 * one 64 byte cacheline on the CCS AUX surface. 1740 */ 1741 if (DISPLAY_VER(dev_priv) >= 12) 1742 tile_width *= 4; 1743 /* 1744 * Display WA #0531: skl,bxt,kbl,glk 1745 * 1746 * Render decompression and plane width > 3840 1747 * combined with horizontal panning requires the 1748 * plane stride to be a multiple of 4. We'll just 1749 * require the entire fb to accommodate that to avoid 1750 * potential runtime errors at plane configuration time. 1751 */ 1752 else if ((DISPLAY_VER(dev_priv) == 9 || IS_GEMINILAKE(dev_priv)) && 1753 color_plane == 0 && fb->width > 3840) 1754 tile_width *= 4; 1755 } 1756 return tile_width; 1757 } 1758 1759 static int intel_plane_check_stride(const struct intel_plane_state *plane_state) 1760 { 1761 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); 1762 const struct drm_framebuffer *fb = plane_state->hw.fb; 1763 unsigned int rotation = plane_state->hw.rotation; 1764 u32 stride, max_stride; 1765 1766 /* 1767 * We ignore stride for all invisible planes that 1768 * can be remapped. Otherwise we could end up 1769 * with a false positive when the remapping didn't 1770 * kick in due the plane being invisible. 1771 */ 1772 if (intel_plane_can_remap(plane_state) && 1773 !plane_state->uapi.visible) 1774 return 0; 1775 1776 /* FIXME other color planes? */ 1777 stride = plane_state->view.color_plane[0].mapping_stride; 1778 max_stride = plane->max_stride(plane, fb->format->format, 1779 fb->modifier, rotation); 1780 1781 if (stride > max_stride) { 1782 drm_dbg_kms(plane->base.dev, 1783 "[FB:%d] stride (%d) exceeds [PLANE:%d:%s] max stride (%d)\n", 1784 fb->base.id, stride, 1785 plane->base.base.id, plane->base.name, max_stride); 1786 return -EINVAL; 1787 } 1788 1789 return 0; 1790 } 1791 1792 int intel_plane_compute_gtt(struct intel_plane_state *plane_state) 1793 { 1794 const struct intel_framebuffer *fb = 1795 to_intel_framebuffer(plane_state->hw.fb); 1796 unsigned int rotation = plane_state->hw.rotation; 1797 1798 if (!fb) 1799 return 0; 1800 1801 if (intel_plane_needs_remap(plane_state)) { 1802 intel_plane_remap_gtt(plane_state); 1803 1804 /* 1805 * Sometimes even remapping can't overcome 1806 * the stride limitations :( Can happen with 1807 * big plane sizes and suitably misaligned 1808 * offsets. 1809 */ 1810 return intel_plane_check_stride(plane_state); 1811 } 1812 1813 intel_fb_fill_view(fb, rotation, &plane_state->view); 1814 1815 /* Rotate src coordinates to match rotated GTT view */ 1816 if (drm_rotation_90_or_270(rotation)) 1817 drm_rect_rotate(&plane_state->uapi.src, 1818 fb->base.width << 16, fb->base.height << 16, 1819 DRM_MODE_ROTATE_270); 1820 1821 return intel_plane_check_stride(plane_state); 1822 } 1823 1824 static void intel_user_framebuffer_destroy(struct drm_framebuffer *fb) 1825 { 1826 struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb); 1827 1828 drm_framebuffer_cleanup(fb); 1829 1830 if (intel_fb_uses_dpt(fb)) 1831 intel_dpt_destroy(intel_fb->dpt_vm); 1832 1833 intel_frontbuffer_put(intel_fb->frontbuffer); 1834 1835 intel_fb_bo_framebuffer_fini(intel_fb_obj(fb)); 1836 1837 kfree(intel_fb); 1838 } 1839 1840 static int intel_user_framebuffer_create_handle(struct drm_framebuffer *fb, 1841 struct drm_file *file, 1842 unsigned int *handle) 1843 { 1844 struct drm_i915_gem_object *obj = intel_fb_obj(fb); 1845 struct drm_i915_private *i915 = to_i915(intel_bo_to_drm_bo(obj)->dev); 1846 1847 if (i915_gem_object_is_userptr(obj)) { 1848 drm_dbg(&i915->drm, 1849 "attempting to use a userptr for a framebuffer, denied\n"); 1850 return -EINVAL; 1851 } 1852 1853 return drm_gem_handle_create(file, intel_bo_to_drm_bo(obj), handle); 1854 } 1855 1856 struct frontbuffer_fence_cb { 1857 struct dma_fence_cb base; 1858 struct intel_frontbuffer *front; 1859 }; 1860 1861 static void intel_user_framebuffer_fence_wake(struct dma_fence *dma, 1862 struct dma_fence_cb *data) 1863 { 1864 struct frontbuffer_fence_cb *cb = container_of(data, typeof(*cb), base); 1865 1866 intel_frontbuffer_queue_flush(cb->front); 1867 kfree(cb); 1868 dma_fence_put(dma); 1869 } 1870 1871 static int intel_user_framebuffer_dirty(struct drm_framebuffer *fb, 1872 struct drm_file *file, 1873 unsigned int flags, unsigned int color, 1874 struct drm_clip_rect *clips, 1875 unsigned int num_clips) 1876 { 1877 struct drm_i915_gem_object *obj = intel_fb_obj(fb); 1878 struct intel_frontbuffer *front = to_intel_frontbuffer(fb); 1879 struct dma_fence *fence; 1880 struct frontbuffer_fence_cb *cb; 1881 int ret = 0; 1882 1883 if (!atomic_read(&front->bits)) 1884 return 0; 1885 1886 if (dma_resv_test_signaled(intel_bo_to_drm_bo(obj)->resv, dma_resv_usage_rw(false))) 1887 goto flush; 1888 1889 ret = dma_resv_get_singleton(intel_bo_to_drm_bo(obj)->resv, dma_resv_usage_rw(false), 1890 &fence); 1891 if (ret || !fence) 1892 goto flush; 1893 1894 cb = kmalloc(sizeof(*cb), GFP_KERNEL); 1895 if (!cb) { 1896 dma_fence_put(fence); 1897 ret = -ENOMEM; 1898 goto flush; 1899 } 1900 1901 cb->front = front; 1902 1903 intel_frontbuffer_invalidate(front, ORIGIN_DIRTYFB); 1904 1905 ret = dma_fence_add_callback(fence, &cb->base, 1906 intel_user_framebuffer_fence_wake); 1907 if (ret) { 1908 intel_user_framebuffer_fence_wake(fence, &cb->base); 1909 if (ret == -ENOENT) 1910 ret = 0; 1911 } 1912 1913 return ret; 1914 1915 flush: 1916 i915_gem_object_flush_if_display(obj); 1917 intel_frontbuffer_flush(front, ORIGIN_DIRTYFB); 1918 return ret; 1919 } 1920 1921 static const struct drm_framebuffer_funcs intel_fb_funcs = { 1922 .destroy = intel_user_framebuffer_destroy, 1923 .create_handle = intel_user_framebuffer_create_handle, 1924 .dirty = intel_user_framebuffer_dirty, 1925 }; 1926 1927 int intel_framebuffer_init(struct intel_framebuffer *intel_fb, 1928 struct drm_i915_gem_object *obj, 1929 struct drm_mode_fb_cmd2 *mode_cmd) 1930 { 1931 struct drm_i915_private *dev_priv = to_i915(intel_bo_to_drm_bo(obj)->dev); 1932 struct drm_framebuffer *fb = &intel_fb->base; 1933 u32 max_stride; 1934 int ret = -EINVAL; 1935 int i; 1936 1937 ret = intel_fb_bo_framebuffer_init(intel_fb, obj, mode_cmd); 1938 if (ret) 1939 return ret; 1940 1941 intel_fb->frontbuffer = intel_frontbuffer_get(obj); 1942 if (!intel_fb->frontbuffer) { 1943 ret = -ENOMEM; 1944 goto err; 1945 } 1946 1947 ret = -EINVAL; 1948 if (!drm_any_plane_has_format(&dev_priv->drm, 1949 mode_cmd->pixel_format, 1950 mode_cmd->modifier[0])) { 1951 drm_dbg_kms(&dev_priv->drm, 1952 "unsupported pixel format %p4cc / modifier 0x%llx\n", 1953 &mode_cmd->pixel_format, mode_cmd->modifier[0]); 1954 goto err_frontbuffer_put; 1955 } 1956 1957 max_stride = intel_fb_max_stride(dev_priv, mode_cmd->pixel_format, 1958 mode_cmd->modifier[0]); 1959 if (mode_cmd->pitches[0] > max_stride) { 1960 drm_dbg_kms(&dev_priv->drm, 1961 "%s pitch (%u) must be at most %d\n", 1962 mode_cmd->modifier[0] != DRM_FORMAT_MOD_LINEAR ? 1963 "tiled" : "linear", 1964 mode_cmd->pitches[0], max_stride); 1965 goto err_frontbuffer_put; 1966 } 1967 1968 /* FIXME need to adjust LINOFF/TILEOFF accordingly. */ 1969 if (mode_cmd->offsets[0] != 0) { 1970 drm_dbg_kms(&dev_priv->drm, 1971 "plane 0 offset (0x%08x) must be 0\n", 1972 mode_cmd->offsets[0]); 1973 goto err_frontbuffer_put; 1974 } 1975 1976 drm_helper_mode_fill_fb_struct(&dev_priv->drm, fb, mode_cmd); 1977 1978 for (i = 0; i < fb->format->num_planes; i++) { 1979 unsigned int stride_alignment; 1980 1981 if (mode_cmd->handles[i] != mode_cmd->handles[0]) { 1982 drm_dbg_kms(&dev_priv->drm, "bad plane %d handle\n", 1983 i); 1984 goto err_frontbuffer_put; 1985 } 1986 1987 stride_alignment = intel_fb_stride_alignment(fb, i); 1988 if (fb->pitches[i] & (stride_alignment - 1)) { 1989 drm_dbg_kms(&dev_priv->drm, 1990 "plane %d pitch (%d) must be at least %u byte aligned\n", 1991 i, fb->pitches[i], stride_alignment); 1992 goto err_frontbuffer_put; 1993 } 1994 1995 if (intel_fb_is_gen12_ccs_aux_plane(fb, i)) { 1996 unsigned int ccs_aux_stride = gen12_ccs_aux_stride(intel_fb, i); 1997 1998 if (fb->pitches[i] != ccs_aux_stride) { 1999 drm_dbg_kms(&dev_priv->drm, 2000 "ccs aux plane %d pitch (%d) must be %d\n", 2001 i, 2002 fb->pitches[i], ccs_aux_stride); 2003 goto err_frontbuffer_put; 2004 } 2005 } 2006 2007 fb->obj[i] = intel_bo_to_drm_bo(obj); 2008 } 2009 2010 ret = intel_fill_fb_info(dev_priv, intel_fb); 2011 if (ret) 2012 goto err_frontbuffer_put; 2013 2014 if (intel_fb_uses_dpt(fb)) { 2015 struct i915_address_space *vm; 2016 2017 vm = intel_dpt_create(intel_fb); 2018 if (IS_ERR(vm)) { 2019 drm_dbg_kms(&dev_priv->drm, "failed to create DPT\n"); 2020 ret = PTR_ERR(vm); 2021 goto err_frontbuffer_put; 2022 } 2023 2024 intel_fb->dpt_vm = vm; 2025 } 2026 2027 ret = drm_framebuffer_init(&dev_priv->drm, fb, &intel_fb_funcs); 2028 if (ret) { 2029 drm_err(&dev_priv->drm, "framebuffer init failed %d\n", ret); 2030 goto err_free_dpt; 2031 } 2032 2033 return 0; 2034 2035 err_free_dpt: 2036 if (intel_fb_uses_dpt(fb)) 2037 intel_dpt_destroy(intel_fb->dpt_vm); 2038 err_frontbuffer_put: 2039 intel_frontbuffer_put(intel_fb->frontbuffer); 2040 err: 2041 intel_fb_bo_framebuffer_fini(obj); 2042 return ret; 2043 } 2044 2045 struct drm_framebuffer * 2046 intel_user_framebuffer_create(struct drm_device *dev, 2047 struct drm_file *filp, 2048 const struct drm_mode_fb_cmd2 *user_mode_cmd) 2049 { 2050 struct drm_framebuffer *fb; 2051 struct drm_i915_gem_object *obj; 2052 struct drm_mode_fb_cmd2 mode_cmd = *user_mode_cmd; 2053 struct drm_i915_private *i915 = to_i915(dev); 2054 2055 obj = intel_fb_bo_lookup_valid_bo(i915, filp, &mode_cmd); 2056 if (IS_ERR(obj)) 2057 return ERR_CAST(obj); 2058 2059 fb = intel_framebuffer_create(obj, &mode_cmd); 2060 drm_gem_object_put(intel_bo_to_drm_bo(obj)); 2061 2062 return fb; 2063 } 2064 2065 struct drm_framebuffer * 2066 intel_framebuffer_create(struct drm_i915_gem_object *obj, 2067 struct drm_mode_fb_cmd2 *mode_cmd) 2068 { 2069 struct intel_framebuffer *intel_fb; 2070 int ret; 2071 2072 intel_fb = kzalloc(sizeof(*intel_fb), GFP_KERNEL); 2073 if (!intel_fb) 2074 return ERR_PTR(-ENOMEM); 2075 2076 ret = intel_framebuffer_init(intel_fb, obj, mode_cmd); 2077 if (ret) 2078 goto err; 2079 2080 return &intel_fb->base; 2081 2082 err: 2083 kfree(intel_fb); 2084 return ERR_PTR(ret); 2085 } 2086