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