|
3 | 3 | * Copyright © 2021 Intel Corporation |
4 | 4 | */ |
5 | 5 |
|
| 6 | +#include "gem/i915_gem_lmem.h" |
6 | 7 | #include "gem/i915_gem_region.h" |
7 | 8 | #include "i915_drv.h" |
8 | 9 | #include "intel_atomic_plane.h" |
| 10 | +#include "intel_crtc.h" |
9 | 11 | #include "intel_display.h" |
10 | 12 | #include "intel_display_types.h" |
11 | 13 | #include "intel_fb.h" |
@@ -138,6 +140,7 @@ initial_plane_vma(struct drm_i915_private *i915, |
138 | 140 | { |
139 | 141 | struct intel_memory_region *mem; |
140 | 142 | struct drm_i915_gem_object *obj; |
| 143 | + struct drm_mm_node orig_mm = {}; |
141 | 144 | struct i915_vma *vma; |
142 | 145 | resource_size_t phys_base; |
143 | 146 | u32 base, size; |
@@ -195,23 +198,66 @@ initial_plane_vma(struct drm_i915_private *i915, |
195 | 198 | goto err_obj; |
196 | 199 | } |
197 | 200 |
|
| 201 | + /* |
| 202 | + * MTL GOP likes to place the framebuffer high up in ggtt, |
| 203 | + * which can cause problems for ggtt_reserve_guc_top(). |
| 204 | + * Try to pin it to a low ggtt address instead to avoid that. |
| 205 | + */ |
| 206 | + base = 0; |
| 207 | + |
| 208 | + if (base != plane_config->base) { |
| 209 | + struct i915_ggtt *ggtt = to_gt(i915)->ggtt; |
| 210 | + int ret; |
| 211 | + |
| 212 | + /* |
| 213 | + * Make sure the original and new locations |
| 214 | + * can't overlap. That would corrupt the original |
| 215 | + * PTEs which are still being used for scanout. |
| 216 | + */ |
| 217 | + ret = i915_gem_gtt_reserve(&ggtt->vm, NULL, &orig_mm, |
| 218 | + size, plane_config->base, |
| 219 | + I915_COLOR_UNEVICTABLE, PIN_NOEVICT); |
| 220 | + if (ret) |
| 221 | + goto err_obj; |
| 222 | + } |
| 223 | + |
198 | 224 | vma = i915_vma_instance(obj, &to_gt(i915)->ggtt->vm, NULL); |
199 | 225 | if (IS_ERR(vma)) |
200 | 226 | goto err_obj; |
201 | 227 |
|
| 228 | +retry: |
202 | 229 | pinctl = PIN_GLOBAL | PIN_OFFSET_FIXED | base; |
203 | | - if (HAS_GMCH(i915)) |
| 230 | + if (!i915_gem_object_is_lmem(obj)) |
204 | 231 | pinctl |= PIN_MAPPABLE; |
205 | | - if (i915_vma_pin(vma, 0, 0, pinctl)) |
| 232 | + if (i915_vma_pin(vma, 0, 0, pinctl)) { |
| 233 | + if (drm_mm_node_allocated(&orig_mm)) { |
| 234 | + drm_mm_remove_node(&orig_mm); |
| 235 | + /* |
| 236 | + * Try again, but this time pin |
| 237 | + * it to its original location. |
| 238 | + */ |
| 239 | + base = plane_config->base; |
| 240 | + goto retry; |
| 241 | + } |
206 | 242 | goto err_obj; |
| 243 | + } |
207 | 244 |
|
208 | 245 | if (i915_gem_object_is_tiled(obj) && |
209 | 246 | !i915_vma_is_map_and_fenceable(vma)) |
210 | 247 | goto err_obj; |
211 | 248 |
|
| 249 | + if (drm_mm_node_allocated(&orig_mm)) |
| 250 | + drm_mm_remove_node(&orig_mm); |
| 251 | + |
| 252 | + drm_dbg_kms(&i915->drm, |
| 253 | + "Initial plane fb bound to 0x%x in the ggtt (original 0x%x)\n", |
| 254 | + i915_ggtt_offset(vma), plane_config->base); |
| 255 | + |
212 | 256 | return vma; |
213 | 257 |
|
214 | 258 | err_obj: |
| 259 | + if (drm_mm_node_allocated(&orig_mm)) |
| 260 | + drm_mm_remove_node(&orig_mm); |
215 | 261 | i915_gem_object_put(obj); |
216 | 262 | return NULL; |
217 | 263 | } |
@@ -386,6 +432,9 @@ void intel_initial_plane_config(struct drm_i915_private *i915) |
386 | 432 | */ |
387 | 433 | intel_find_initial_plane_obj(crtc, plane_configs); |
388 | 434 |
|
| 435 | + if (i915->display.funcs.display->fixup_initial_plane_config(crtc, plane_config)) |
| 436 | + intel_crtc_wait_for_next_vblank(crtc); |
| 437 | + |
389 | 438 | plane_config_fini(plane_config); |
390 | 439 | } |
391 | 440 | } |
0 commit comments