1 // SPDX-License-Identifier: MIT 2 /* 3 * Copyright © 2021 Intel Corporation 4 */ 5 6 /* for ioread64 */ 7 #include <linux/io-64-nonatomic-lo-hi.h> 8 9 #include "xe_ggtt.h" 10 11 #include "i915_drv.h" 12 #include "intel_atomic_plane.h" 13 #include "intel_display.h" 14 #include "intel_display_types.h" 15 #include "intel_fb.h" 16 #include "intel_fb_pin.h" 17 #include "intel_frontbuffer.h" 18 #include "intel_plane_initial.h" 19 20 static bool 21 intel_reuse_initial_plane_obj(struct drm_i915_private *i915, 22 const struct intel_initial_plane_config *plane_config, 23 struct drm_framebuffer **fb) 24 { 25 struct intel_crtc *crtc; 26 27 for_each_intel_crtc(&i915->drm, crtc) { 28 struct intel_crtc_state *crtc_state = 29 to_intel_crtc_state(crtc->base.state); 30 struct intel_plane *plane = 31 to_intel_plane(crtc->base.primary); 32 struct intel_plane_state *plane_state = 33 to_intel_plane_state(plane->base.state); 34 35 if (!crtc_state->uapi.active) 36 continue; 37 38 if (!plane_state->ggtt_vma) 39 continue; 40 41 if (intel_plane_ggtt_offset(plane_state) == plane_config->base) { 42 *fb = plane_state->hw.fb; 43 return true; 44 } 45 } 46 47 return false; 48 } 49 50 static struct xe_bo * 51 initial_plane_bo(struct xe_device *xe, 52 struct intel_initial_plane_config *plane_config) 53 { 54 struct xe_tile *tile0 = xe_device_get_root_tile(xe); 55 struct xe_bo *bo; 56 resource_size_t phys_base; 57 u32 base, size, flags; 58 u64 page_size = xe->info.vram_flags & XE_VRAM_FLAGS_NEED64K ? SZ_64K : SZ_4K; 59 60 if (plane_config->size == 0) 61 return NULL; 62 63 flags = XE_BO_CREATE_PINNED_BIT | XE_BO_SCANOUT_BIT | XE_BO_CREATE_GGTT_BIT; 64 65 base = round_down(plane_config->base, page_size); 66 if (IS_DGFX(xe)) { 67 u64 __iomem *gte = tile0->mem.ggtt->gsm; 68 u64 pte; 69 70 gte += base / XE_PAGE_SIZE; 71 72 pte = ioread64(gte); 73 if (!(pte & XE_GGTT_PTE_DM)) { 74 drm_err(&xe->drm, 75 "Initial plane programming missing DM bit\n"); 76 return NULL; 77 } 78 79 phys_base = pte & ~(page_size - 1); 80 flags |= XE_BO_CREATE_VRAM0_BIT; 81 82 /* 83 * We don't currently expect this to ever be placed in the 84 * stolen portion. 85 */ 86 if (phys_base >= tile0->mem.vram.usable_size) { 87 drm_err(&xe->drm, 88 "Initial plane programming using invalid range, phys_base=%pa\n", 89 &phys_base); 90 return NULL; 91 } 92 93 drm_dbg(&xe->drm, 94 "Using phys_base=%pa, based on initial plane programming\n", 95 &phys_base); 96 } else { 97 struct ttm_resource_manager *stolen = ttm_manager_type(&xe->ttm, XE_PL_STOLEN); 98 99 if (!stolen) 100 return NULL; 101 phys_base = base; 102 flags |= XE_BO_CREATE_STOLEN_BIT; 103 104 /* 105 * If the FB is too big, just don't use it since fbdev is not very 106 * important and we should probably use that space with FBC or other 107 * features. 108 */ 109 if (IS_ENABLED(CONFIG_FRAMEBUFFER_CONSOLE) && 110 plane_config->size * 2 >> PAGE_SHIFT >= stolen->size) 111 return NULL; 112 } 113 114 size = round_up(plane_config->base + plane_config->size, 115 page_size); 116 size -= base; 117 118 bo = xe_bo_create_pin_map_at(xe, tile0, NULL, size, phys_base, 119 ttm_bo_type_kernel, flags); 120 if (IS_ERR(bo)) { 121 drm_dbg(&xe->drm, 122 "Failed to create bo phys_base=%pa size %u with flags %x: %li\n", 123 &phys_base, size, flags, PTR_ERR(bo)); 124 return NULL; 125 } 126 127 return bo; 128 } 129 130 static bool 131 intel_alloc_initial_plane_obj(struct intel_crtc *crtc, 132 struct intel_initial_plane_config *plane_config) 133 { 134 struct drm_device *dev = crtc->base.dev; 135 struct drm_i915_private *dev_priv = to_i915(dev); 136 struct drm_mode_fb_cmd2 mode_cmd = { 0 }; 137 struct drm_framebuffer *fb = &plane_config->fb->base; 138 struct xe_bo *bo; 139 140 switch (fb->modifier) { 141 case DRM_FORMAT_MOD_LINEAR: 142 case I915_FORMAT_MOD_X_TILED: 143 case I915_FORMAT_MOD_Y_TILED: 144 case I915_FORMAT_MOD_4_TILED: 145 break; 146 default: 147 drm_dbg(&dev_priv->drm, 148 "Unsupported modifier for initial FB: 0x%llx\n", 149 fb->modifier); 150 return false; 151 } 152 153 mode_cmd.pixel_format = fb->format->format; 154 mode_cmd.width = fb->width; 155 mode_cmd.height = fb->height; 156 mode_cmd.pitches[0] = fb->pitches[0]; 157 mode_cmd.modifier[0] = fb->modifier; 158 mode_cmd.flags = DRM_MODE_FB_MODIFIERS; 159 160 bo = initial_plane_bo(dev_priv, plane_config); 161 if (!bo) 162 return false; 163 164 if (intel_framebuffer_init(to_intel_framebuffer(fb), 165 bo, &mode_cmd)) { 166 drm_dbg_kms(&dev_priv->drm, "intel fb init failed\n"); 167 goto err_bo; 168 } 169 /* Reference handed over to fb */ 170 xe_bo_put(bo); 171 172 return true; 173 174 err_bo: 175 xe_bo_unpin_map_no_vm(bo); 176 return false; 177 } 178 179 static void 180 intel_find_initial_plane_obj(struct intel_crtc *crtc, 181 struct intel_initial_plane_config *plane_config) 182 { 183 struct drm_device *dev = crtc->base.dev; 184 struct drm_i915_private *dev_priv = to_i915(dev); 185 struct intel_plane *plane = 186 to_intel_plane(crtc->base.primary); 187 struct intel_plane_state *plane_state = 188 to_intel_plane_state(plane->base.state); 189 struct intel_crtc_state *crtc_state = 190 to_intel_crtc_state(crtc->base.state); 191 struct drm_framebuffer *fb; 192 struct i915_vma *vma; 193 194 /* 195 * TODO: 196 * Disable planes if get_initial_plane_config() failed. 197 * Make sure things work if the surface base is not page aligned. 198 */ 199 if (!plane_config->fb) 200 return; 201 202 if (intel_alloc_initial_plane_obj(crtc, plane_config)) 203 fb = &plane_config->fb->base; 204 else if (!intel_reuse_initial_plane_obj(dev_priv, plane_config, &fb)) 205 goto nofb; 206 207 plane_state->uapi.rotation = plane_config->rotation; 208 intel_fb_fill_view(to_intel_framebuffer(fb), 209 plane_state->uapi.rotation, &plane_state->view); 210 211 vma = intel_pin_and_fence_fb_obj(fb, false, &plane_state->view.gtt, 212 false, &plane_state->flags); 213 if (IS_ERR(vma)) 214 goto nofb; 215 216 plane_state->ggtt_vma = vma; 217 plane_state->uapi.src_x = 0; 218 plane_state->uapi.src_y = 0; 219 plane_state->uapi.src_w = fb->width << 16; 220 plane_state->uapi.src_h = fb->height << 16; 221 222 plane_state->uapi.crtc_x = 0; 223 plane_state->uapi.crtc_y = 0; 224 plane_state->uapi.crtc_w = fb->width; 225 plane_state->uapi.crtc_h = fb->height; 226 227 plane_state->uapi.fb = fb; 228 drm_framebuffer_get(fb); 229 230 plane_state->uapi.crtc = &crtc->base; 231 intel_plane_copy_uapi_to_hw_state(plane_state, plane_state, crtc); 232 233 atomic_or(plane->frontbuffer_bit, &to_intel_frontbuffer(fb)->bits); 234 235 plane_config->vma = vma; 236 237 /* 238 * Flip to the newly created mapping ASAP, so we can re-use the 239 * first part of GGTT for WOPCM, prevent flickering, and prevent 240 * the lookup of sysmem scratch pages. 241 */ 242 plane->check_plane(crtc_state, plane_state); 243 plane->async_flip(plane, crtc_state, plane_state, true); 244 return; 245 246 nofb: 247 /* 248 * We've failed to reconstruct the BIOS FB. Current display state 249 * indicates that the primary plane is visible, but has a NULL FB, 250 * which will lead to problems later if we don't fix it up. The 251 * simplest solution is to just disable the primary plane now and 252 * pretend the BIOS never had it enabled. 253 */ 254 intel_plane_disable_noatomic(crtc, plane); 255 } 256 257 static void plane_config_fini(struct intel_initial_plane_config *plane_config) 258 { 259 if (plane_config->fb) { 260 struct drm_framebuffer *fb = &plane_config->fb->base; 261 262 /* We may only have the stub and not a full framebuffer */ 263 if (drm_framebuffer_read_refcount(fb)) 264 drm_framebuffer_put(fb); 265 else 266 kfree(fb); 267 } 268 } 269 270 void intel_crtc_initial_plane_config(struct intel_crtc *crtc) 271 { 272 struct xe_device *xe = to_xe_device(crtc->base.dev); 273 struct intel_initial_plane_config plane_config = {}; 274 275 /* 276 * Note that reserving the BIOS fb up front prevents us 277 * from stuffing other stolen allocations like the ring 278 * on top. This prevents some ugliness at boot time, and 279 * can even allow for smooth boot transitions if the BIOS 280 * fb is large enough for the active pipe configuration. 281 */ 282 xe->display.funcs.display->get_initial_plane_config(crtc, &plane_config); 283 284 /* 285 * If the fb is shared between multiple heads, we'll 286 * just get the first one. 287 */ 288 intel_find_initial_plane_obj(crtc, &plane_config); 289 290 plane_config_fini(&plane_config); 291 } 292