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