1 // SPDX-License-Identifier: MIT 2 /* 3 * Copyright © 2021 Intel Corporation 4 */ 5 6 #include "i915_drv.h" 7 #include "intel_atomic_plane.h" 8 #include "intel_display.h" 9 #include "intel_display_types.h" 10 #include "intel_fb.h" 11 #include "intel_plane_initial.h" 12 13 static bool 14 intel_reuse_initial_plane_obj(struct drm_i915_private *i915, 15 const struct intel_initial_plane_config *plane_config, 16 struct drm_framebuffer **fb, 17 struct i915_vma **vma) 18 { 19 struct intel_crtc *crtc; 20 21 for_each_intel_crtc(&i915->drm, crtc) { 22 struct intel_crtc_state *crtc_state = 23 to_intel_crtc_state(crtc->base.state); 24 struct intel_plane *plane = 25 to_intel_plane(crtc->base.primary); 26 struct intel_plane_state *plane_state = 27 to_intel_plane_state(plane->base.state); 28 29 if (!crtc_state->uapi.active) 30 continue; 31 32 if (!plane_state->ggtt_vma) 33 continue; 34 35 if (intel_plane_ggtt_offset(plane_state) == plane_config->base) { 36 *fb = plane_state->hw.fb; 37 *vma = plane_state->ggtt_vma; 38 return true; 39 } 40 } 41 42 return false; 43 } 44 45 static struct i915_vma * 46 initial_plane_vma(struct drm_i915_private *i915, 47 struct intel_initial_plane_config *plane_config) 48 { 49 struct intel_memory_region *mem = i915->mm.stolen_region; 50 struct drm_i915_gem_object *obj; 51 struct i915_vma *vma; 52 u32 base, size; 53 54 if (!mem || plane_config->size == 0) 55 return NULL; 56 57 base = round_down(plane_config->base, 58 I915_GTT_MIN_ALIGNMENT); 59 size = round_up(plane_config->base + plane_config->size, 60 mem->min_page_size); 61 size -= base; 62 63 /* 64 * If the FB is too big, just don't use it since fbdev is not very 65 * important and we should probably use that space with FBC or other 66 * features. 67 */ 68 if (IS_ENABLED(CONFIG_FRAMEBUFFER_CONSOLE) && 69 size * 2 > i915->stolen_usable_size) 70 return NULL; 71 72 obj = i915_gem_object_create_stolen_for_preallocated(i915, base, size); 73 if (IS_ERR(obj)) 74 return NULL; 75 76 /* 77 * Mark it WT ahead of time to avoid changing the 78 * cache_level during fbdev initialization. The 79 * unbind there would get stuck waiting for rcu. 80 */ 81 i915_gem_object_set_cache_coherency(obj, HAS_WT(i915) ? 82 I915_CACHE_WT : I915_CACHE_NONE); 83 84 switch (plane_config->tiling) { 85 case I915_TILING_NONE: 86 break; 87 case I915_TILING_X: 88 case I915_TILING_Y: 89 obj->tiling_and_stride = 90 plane_config->fb->base.pitches[0] | 91 plane_config->tiling; 92 break; 93 default: 94 MISSING_CASE(plane_config->tiling); 95 goto err_obj; 96 } 97 98 vma = i915_vma_instance(obj, &to_gt(i915)->ggtt->vm, NULL); 99 if (IS_ERR(vma)) 100 goto err_obj; 101 102 if (i915_ggtt_pin(vma, NULL, 0, PIN_MAPPABLE | PIN_OFFSET_FIXED | base)) 103 goto err_obj; 104 105 if (i915_gem_object_is_tiled(obj) && 106 !i915_vma_is_map_and_fenceable(vma)) 107 goto err_obj; 108 109 return vma; 110 111 err_obj: 112 i915_gem_object_put(obj); 113 return NULL; 114 } 115 116 static bool 117 intel_alloc_initial_plane_obj(struct intel_crtc *crtc, 118 struct intel_initial_plane_config *plane_config) 119 { 120 struct drm_device *dev = crtc->base.dev; 121 struct drm_i915_private *dev_priv = to_i915(dev); 122 struct drm_mode_fb_cmd2 mode_cmd = { 0 }; 123 struct drm_framebuffer *fb = &plane_config->fb->base; 124 struct i915_vma *vma; 125 126 switch (fb->modifier) { 127 case DRM_FORMAT_MOD_LINEAR: 128 case I915_FORMAT_MOD_X_TILED: 129 case I915_FORMAT_MOD_Y_TILED: 130 break; 131 default: 132 drm_dbg(&dev_priv->drm, 133 "Unsupported modifier for initial FB: 0x%llx\n", 134 fb->modifier); 135 return false; 136 } 137 138 vma = initial_plane_vma(dev_priv, plane_config); 139 if (!vma) 140 return false; 141 142 mode_cmd.pixel_format = fb->format->format; 143 mode_cmd.width = fb->width; 144 mode_cmd.height = fb->height; 145 mode_cmd.pitches[0] = fb->pitches[0]; 146 mode_cmd.modifier[0] = fb->modifier; 147 mode_cmd.flags = DRM_MODE_FB_MODIFIERS; 148 149 if (intel_framebuffer_init(to_intel_framebuffer(fb), 150 vma->obj, &mode_cmd)) { 151 drm_dbg_kms(&dev_priv->drm, "intel fb init failed\n"); 152 goto err_vma; 153 } 154 155 plane_config->vma = vma; 156 return true; 157 158 err_vma: 159 i915_vma_put(vma); 160 return false; 161 } 162 163 static void 164 intel_find_initial_plane_obj(struct intel_crtc *crtc, 165 struct intel_initial_plane_config *plane_config) 166 { 167 struct drm_device *dev = crtc->base.dev; 168 struct drm_i915_private *dev_priv = to_i915(dev); 169 struct intel_plane *plane = 170 to_intel_plane(crtc->base.primary); 171 struct intel_plane_state *plane_state = 172 to_intel_plane_state(plane->base.state); 173 struct drm_framebuffer *fb; 174 struct i915_vma *vma; 175 176 /* 177 * TODO: 178 * Disable planes if get_initial_plane_config() failed. 179 * Make sure things work if the surface base is not page aligned. 180 */ 181 if (!plane_config->fb) 182 return; 183 184 if (intel_alloc_initial_plane_obj(crtc, plane_config)) { 185 fb = &plane_config->fb->base; 186 vma = plane_config->vma; 187 goto valid_fb; 188 } 189 190 /* 191 * Failed to alloc the obj, check to see if we should share 192 * an fb with another CRTC instead 193 */ 194 if (intel_reuse_initial_plane_obj(dev_priv, plane_config, &fb, &vma)) 195 goto valid_fb; 196 197 /* 198 * We've failed to reconstruct the BIOS FB. Current display state 199 * indicates that the primary plane is visible, but has a NULL FB, 200 * which will lead to problems later if we don't fix it up. The 201 * simplest solution is to just disable the primary plane now and 202 * pretend the BIOS never had it enabled. 203 */ 204 intel_plane_disable_noatomic(crtc, plane); 205 206 return; 207 208 valid_fb: 209 plane_state->uapi.rotation = plane_config->rotation; 210 intel_fb_fill_view(to_intel_framebuffer(fb), 211 plane_state->uapi.rotation, &plane_state->view); 212 213 __i915_vma_pin(vma); 214 plane_state->ggtt_vma = i915_vma_get(vma); 215 if (intel_plane_uses_fence(plane_state) && 216 i915_vma_pin_fence(vma) == 0 && vma->fence) 217 plane_state->flags |= PLANE_HAS_FENCE; 218 219 plane_state->uapi.src_x = 0; 220 plane_state->uapi.src_y = 0; 221 plane_state->uapi.src_w = fb->width << 16; 222 plane_state->uapi.src_h = fb->height << 16; 223 224 plane_state->uapi.crtc_x = 0; 225 plane_state->uapi.crtc_y = 0; 226 plane_state->uapi.crtc_w = fb->width; 227 plane_state->uapi.crtc_h = fb->height; 228 229 if (plane_config->tiling) 230 dev_priv->preserve_bios_swizzle = true; 231 232 plane_state->uapi.fb = fb; 233 drm_framebuffer_get(fb); 234 235 plane_state->uapi.crtc = &crtc->base; 236 intel_plane_copy_uapi_to_hw_state(plane_state, plane_state, crtc); 237 238 atomic_or(plane->frontbuffer_bit, &to_intel_frontbuffer(fb)->bits); 239 } 240 241 static void plane_config_fini(struct intel_initial_plane_config *plane_config) 242 { 243 if (plane_config->fb) { 244 struct drm_framebuffer *fb = &plane_config->fb->base; 245 246 /* We may only have the stub and not a full framebuffer */ 247 if (drm_framebuffer_read_refcount(fb)) 248 drm_framebuffer_put(fb); 249 else 250 kfree(fb); 251 } 252 253 if (plane_config->vma) 254 i915_vma_put(plane_config->vma); 255 } 256 257 void intel_crtc_initial_plane_config(struct intel_crtc *crtc) 258 { 259 struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); 260 struct intel_initial_plane_config plane_config = {}; 261 262 /* 263 * Note that reserving the BIOS fb up front prevents us 264 * from stuffing other stolen allocations like the ring 265 * on top. This prevents some ugliness at boot time, and 266 * can even allow for smooth boot transitions if the BIOS 267 * fb is large enough for the active pipe configuration. 268 */ 269 dev_priv->display->get_initial_plane_config(crtc, &plane_config); 270 271 /* 272 * If the fb is shared between multiple heads, we'll 273 * just get the first one. 274 */ 275 intel_find_initial_plane_obj(crtc, &plane_config); 276 277 plane_config_fini(&plane_config); 278 } 279