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 <drm/intel/display_parent_interface.h> 10 11 #include "regs/xe_gtt_defs.h" 12 #include "xe_ggtt.h" 13 #include "xe_mmio.h" 14 15 #include "i915_vma.h" 16 #include "intel_crtc.h" 17 #include "intel_display.h" 18 #include "intel_display_core.h" 19 #include "intel_display_regs.h" 20 #include "intel_display_types.h" 21 #include "intel_fb.h" 22 #include "intel_fb_pin.h" 23 #include "intel_frontbuffer.h" 24 #include "intel_initial_plane.h" 25 #include "intel_plane.h" 26 #include "xe_bo.h" 27 #include "xe_vram_types.h" 28 #include "xe_wa.h" 29 30 #include <generated/xe_device_wa_oob.h> 31 32 /* Early xe has no irq */ 33 static void xe_initial_plane_vblank_wait(struct drm_crtc *_crtc) 34 { 35 struct intel_crtc *crtc = to_intel_crtc(_crtc); 36 struct xe_device *xe = to_xe_device(crtc->base.dev); 37 struct xe_reg pipe_frmtmstmp = XE_REG(i915_mmio_reg_offset(PIPE_FRMTMSTMP(crtc->pipe))); 38 u32 timestamp; 39 int ret; 40 41 timestamp = xe_mmio_read32(xe_root_tile_mmio(xe), pipe_frmtmstmp); 42 43 ret = xe_mmio_wait32_not(xe_root_tile_mmio(xe), pipe_frmtmstmp, ~0U, timestamp, 40000U, ×tamp, false); 44 if (ret < 0) 45 drm_warn(&xe->drm, "waiting for early vblank failed with %i\n", ret); 46 } 47 48 static bool 49 intel_reuse_initial_plane_obj(struct intel_crtc *this, 50 const struct intel_initial_plane_config plane_configs[], 51 struct drm_framebuffer **fb) 52 { 53 struct xe_device *xe = to_xe_device(this->base.dev); 54 struct intel_crtc *crtc; 55 56 for_each_intel_crtc(&xe->drm, crtc) { 57 struct intel_plane *plane = 58 to_intel_plane(crtc->base.primary); 59 const struct intel_plane_state *plane_state = 60 to_intel_plane_state(plane->base.state); 61 const struct intel_crtc_state *crtc_state = 62 to_intel_crtc_state(crtc->base.state); 63 64 if (!crtc_state->hw.active) 65 continue; 66 67 if (!plane_state->ggtt_vma) 68 continue; 69 70 if (plane_configs[this->pipe].base == plane_configs[crtc->pipe].base) { 71 *fb = plane_state->hw.fb; 72 return true; 73 } 74 } 75 76 return false; 77 } 78 79 static struct xe_bo * 80 initial_plane_bo(struct xe_device *xe, 81 struct intel_initial_plane_config *plane_config) 82 { 83 struct xe_tile *tile0 = xe_device_get_root_tile(xe); 84 struct xe_bo *bo; 85 resource_size_t phys_base; 86 u32 base, size, flags; 87 u64 page_size = xe->info.vram_flags & XE_VRAM_FLAGS_NEED64K ? SZ_64K : SZ_4K; 88 89 if (plane_config->size == 0) 90 return NULL; 91 92 flags = XE_BO_FLAG_SCANOUT | XE_BO_FLAG_GGTT; 93 94 base = round_down(plane_config->base, page_size); 95 if (IS_DGFX(xe)) { 96 u64 pte = xe_ggtt_read_pte(tile0->mem.ggtt, base); 97 98 if (!(pte & XE_GGTT_PTE_DM)) { 99 drm_err(&xe->drm, 100 "Initial plane programming missing DM bit\n"); 101 return NULL; 102 } 103 104 phys_base = pte & ~(page_size - 1); 105 flags |= XE_BO_FLAG_VRAM0; 106 107 /* 108 * We don't currently expect this to ever be placed in the 109 * stolen portion. 110 */ 111 if (phys_base >= xe_vram_region_usable_size(tile0->mem.vram)) { 112 drm_err(&xe->drm, 113 "Initial plane programming using invalid range, phys_base=%pa\n", 114 &phys_base); 115 return NULL; 116 } 117 118 drm_dbg(&xe->drm, 119 "Using phys_base=%pa, based on initial plane programming\n", 120 &phys_base); 121 } else { 122 struct ttm_resource_manager *stolen = ttm_manager_type(&xe->ttm, XE_PL_STOLEN); 123 124 if (!stolen) 125 return NULL; 126 phys_base = base; 127 flags |= XE_BO_FLAG_STOLEN; 128 129 if (XE_DEVICE_WA(xe, 22019338487_display)) 130 return NULL; 131 132 /* 133 * If the FB is too big, just don't use it since fbdev is not very 134 * important and we should probably use that space with FBC or other 135 * features. 136 */ 137 if (IS_ENABLED(CONFIG_FRAMEBUFFER_CONSOLE) && 138 plane_config->size * 2 >> PAGE_SHIFT >= stolen->size) 139 return NULL; 140 } 141 142 size = round_up(plane_config->base + plane_config->size, 143 page_size); 144 size -= base; 145 146 bo = xe_bo_create_pin_map_at_novm(xe, tile0, size, phys_base, 147 ttm_bo_type_kernel, flags, 0, false); 148 if (IS_ERR(bo)) { 149 drm_dbg(&xe->drm, 150 "Failed to create bo phys_base=%pa size %u with flags %x: %li\n", 151 &phys_base, size, flags, PTR_ERR(bo)); 152 return NULL; 153 } 154 155 return bo; 156 } 157 158 static bool 159 intel_alloc_initial_plane_obj(struct intel_crtc *crtc, 160 struct intel_initial_plane_config *plane_config) 161 { 162 struct xe_device *xe = to_xe_device(crtc->base.dev); 163 struct drm_mode_fb_cmd2 mode_cmd = { 0 }; 164 struct drm_framebuffer *fb = &plane_config->fb->base; 165 struct xe_bo *bo; 166 167 switch (fb->modifier) { 168 case DRM_FORMAT_MOD_LINEAR: 169 case I915_FORMAT_MOD_X_TILED: 170 case I915_FORMAT_MOD_Y_TILED: 171 case I915_FORMAT_MOD_4_TILED: 172 break; 173 default: 174 drm_dbg_kms(&xe->drm, 175 "Unsupported modifier for initial FB: 0x%llx\n", 176 fb->modifier); 177 return false; 178 } 179 180 mode_cmd.pixel_format = fb->format->format; 181 mode_cmd.width = fb->width; 182 mode_cmd.height = fb->height; 183 mode_cmd.pitches[0] = fb->pitches[0]; 184 mode_cmd.modifier[0] = fb->modifier; 185 mode_cmd.flags = DRM_MODE_FB_MODIFIERS; 186 187 bo = initial_plane_bo(xe, plane_config); 188 if (!bo) 189 return false; 190 191 if (intel_framebuffer_init(to_intel_framebuffer(fb), 192 &bo->ttm.base, fb->format, &mode_cmd)) { 193 drm_dbg_kms(&xe->drm, "intel fb init failed\n"); 194 goto err_bo; 195 } 196 /* Reference handed over to fb */ 197 xe_bo_put(bo); 198 199 return true; 200 201 err_bo: 202 xe_bo_unpin_map_no_vm(bo); 203 return false; 204 } 205 206 static void 207 xe_find_initial_plane_obj(struct drm_crtc *_crtc, 208 struct intel_initial_plane_config plane_configs[]) 209 { 210 struct intel_crtc *crtc = to_intel_crtc(_crtc); 211 struct intel_initial_plane_config *plane_config = 212 &plane_configs[crtc->pipe]; 213 struct intel_plane *plane = 214 to_intel_plane(crtc->base.primary); 215 struct intel_plane_state *plane_state = 216 to_intel_plane_state(plane->base.state); 217 struct drm_framebuffer *fb; 218 struct i915_vma *vma; 219 220 /* 221 * TODO: 222 * Disable planes if get_initial_plane_config() failed. 223 * Make sure things work if the surface base is not page aligned. 224 */ 225 if (!plane_config->fb) 226 return; 227 228 if (intel_alloc_initial_plane_obj(crtc, plane_config)) 229 fb = &plane_config->fb->base; 230 else if (!intel_reuse_initial_plane_obj(crtc, plane_configs, &fb)) 231 goto nofb; 232 233 plane_state->uapi.rotation = plane_config->rotation; 234 intel_fb_fill_view(to_intel_framebuffer(fb), 235 plane_state->uapi.rotation, &plane_state->view); 236 237 vma = intel_fb_pin_to_ggtt(fb, &plane_state->view.gtt, 238 0, 0, 0, false, &plane_state->flags); 239 if (IS_ERR(vma)) 240 goto nofb; 241 242 plane_state->ggtt_vma = vma; 243 244 plane_state->surf = i915_ggtt_offset(plane_state->ggtt_vma); 245 246 plane_state->uapi.src_x = 0; 247 plane_state->uapi.src_y = 0; 248 plane_state->uapi.src_w = fb->width << 16; 249 plane_state->uapi.src_h = fb->height << 16; 250 251 plane_state->uapi.crtc_x = 0; 252 plane_state->uapi.crtc_y = 0; 253 plane_state->uapi.crtc_w = fb->width; 254 plane_state->uapi.crtc_h = fb->height; 255 256 plane_state->uapi.fb = fb; 257 drm_framebuffer_get(fb); 258 259 plane_state->uapi.crtc = &crtc->base; 260 intel_plane_copy_uapi_to_hw_state(plane_state, plane_state, crtc); 261 262 atomic_or(plane->frontbuffer_bit, &to_intel_frontbuffer(fb)->bits); 263 264 plane_config->vma = vma; 265 return; 266 267 nofb: 268 /* 269 * We've failed to reconstruct the BIOS FB. Current display state 270 * indicates that the primary plane is visible, but has a NULL FB, 271 * which will lead to problems later if we don't fix it up. The 272 * simplest solution is to just disable the primary plane now and 273 * pretend the BIOS never had it enabled. 274 */ 275 intel_plane_disable_noatomic(crtc, plane); 276 } 277 278 static void xe_plane_config_fini(struct intel_initial_plane_config *plane_config) 279 { 280 if (plane_config->fb) { 281 struct drm_framebuffer *fb = &plane_config->fb->base; 282 283 /* We may only have the stub and not a full framebuffer */ 284 if (drm_framebuffer_read_refcount(fb)) 285 drm_framebuffer_put(fb); 286 else 287 kfree(fb); 288 } 289 } 290 291 const struct intel_display_initial_plane_interface xe_display_initial_plane_interface = { 292 .vblank_wait = xe_initial_plane_vblank_wait, 293 .find_obj = xe_find_initial_plane_obj, 294 .config_fini = xe_plane_config_fini, 295 }; 296