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