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