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 case I915_FORMAT_MOD_4_TILED: 129 break; 130 default: 131 drm_dbg(&dev_priv->drm, 132 "Unsupported modifier for initial FB: 0x%llx\n", 133 fb->modifier); 134 return false; 135 } 136 137 vma = initial_plane_vma(dev_priv, plane_config); 138 if (!vma) 139 return false; 140 141 mode_cmd.pixel_format = fb->format->format; 142 mode_cmd.width = fb->width; 143 mode_cmd.height = fb->height; 144 mode_cmd.pitches[0] = fb->pitches[0]; 145 mode_cmd.modifier[0] = fb->modifier; 146 mode_cmd.flags = DRM_MODE_FB_MODIFIERS; 147 148 if (intel_framebuffer_init(to_intel_framebuffer(fb), 149 vma->obj, &mode_cmd)) { 150 drm_dbg_kms(&dev_priv->drm, "intel fb init failed\n"); 151 goto err_vma; 152 } 153 154 plane_config->vma = vma; 155 return true; 156 157 err_vma: 158 i915_vma_put(vma); 159 return false; 160 } 161 162 static void 163 intel_find_initial_plane_obj(struct intel_crtc *crtc, 164 struct intel_initial_plane_config *plane_config) 165 { 166 struct drm_device *dev = crtc->base.dev; 167 struct drm_i915_private *dev_priv = to_i915(dev); 168 struct intel_crtc_state *crtc_state = 169 to_intel_crtc_state(crtc->base.state); 170 struct intel_plane *plane = 171 to_intel_plane(crtc->base.primary); 172 struct intel_plane_state *plane_state = 173 to_intel_plane_state(plane->base.state); 174 struct drm_framebuffer *fb; 175 struct i915_vma *vma; 176 177 /* 178 * TODO: 179 * Disable planes if get_initial_plane_config() failed. 180 * Make sure things work if the surface base is not page aligned. 181 */ 182 if (!plane_config->fb) 183 return; 184 185 if (intel_alloc_initial_plane_obj(crtc, plane_config)) { 186 fb = &plane_config->fb->base; 187 vma = plane_config->vma; 188 goto valid_fb; 189 } 190 191 /* 192 * Failed to alloc the obj, check to see if we should share 193 * an fb with another CRTC instead 194 */ 195 if (intel_reuse_initial_plane_obj(dev_priv, plane_config, &fb, &vma)) 196 goto valid_fb; 197 198 /* 199 * We've failed to reconstruct the BIOS FB. Current display state 200 * indicates that the primary plane is visible, but has a NULL FB, 201 * which will lead to problems later if we don't fix it up. The 202 * simplest solution is to just disable the primary plane now and 203 * pretend the BIOS never had it enabled. 204 */ 205 intel_plane_disable_noatomic(crtc, plane); 206 if (crtc_state->bigjoiner) { 207 struct intel_crtc *slave = 208 crtc_state->bigjoiner_linked_crtc; 209 intel_plane_disable_noatomic(slave, to_intel_plane(slave->base.primary)); 210 } 211 212 return; 213 214 valid_fb: 215 plane_state->uapi.rotation = plane_config->rotation; 216 intel_fb_fill_view(to_intel_framebuffer(fb), 217 plane_state->uapi.rotation, &plane_state->view); 218 219 __i915_vma_pin(vma); 220 plane_state->ggtt_vma = i915_vma_get(vma); 221 if (intel_plane_uses_fence(plane_state) && 222 i915_vma_pin_fence(vma) == 0 && vma->fence) 223 plane_state->flags |= PLANE_HAS_FENCE; 224 225 plane_state->uapi.src_x = 0; 226 plane_state->uapi.src_y = 0; 227 plane_state->uapi.src_w = fb->width << 16; 228 plane_state->uapi.src_h = fb->height << 16; 229 230 plane_state->uapi.crtc_x = 0; 231 plane_state->uapi.crtc_y = 0; 232 plane_state->uapi.crtc_w = fb->width; 233 plane_state->uapi.crtc_h = fb->height; 234 235 if (plane_config->tiling) 236 dev_priv->preserve_bios_swizzle = true; 237 238 plane_state->uapi.fb = fb; 239 drm_framebuffer_get(fb); 240 241 plane_state->uapi.crtc = &crtc->base; 242 intel_plane_copy_uapi_to_hw_state(plane_state, plane_state, crtc); 243 244 atomic_or(plane->frontbuffer_bit, &to_intel_frontbuffer(fb)->bits); 245 } 246 247 static void plane_config_fini(struct intel_initial_plane_config *plane_config) 248 { 249 if (plane_config->fb) { 250 struct drm_framebuffer *fb = &plane_config->fb->base; 251 252 /* We may only have the stub and not a full framebuffer */ 253 if (drm_framebuffer_read_refcount(fb)) 254 drm_framebuffer_put(fb); 255 else 256 kfree(fb); 257 } 258 259 if (plane_config->vma) 260 i915_vma_put(plane_config->vma); 261 } 262 263 void intel_crtc_initial_plane_config(struct intel_crtc *crtc) 264 { 265 struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); 266 struct intel_initial_plane_config plane_config = {}; 267 268 /* 269 * Note that reserving the BIOS fb up front prevents us 270 * from stuffing other stolen allocations like the ring 271 * on top. This prevents some ugliness at boot time, and 272 * can even allow for smooth boot transitions if the BIOS 273 * fb is large enough for the active pipe configuration. 274 */ 275 dev_priv->display->get_initial_plane_config(crtc, &plane_config); 276 277 /* 278 * If the fb is shared between multiple heads, we'll 279 * just get the first one. 280 */ 281 intel_find_initial_plane_obj(crtc, &plane_config); 282 283 plane_config_fini(&plane_config); 284 } 285