1 // SPDX-License-Identifier: MIT 2 /* 3 * Copyright © 2021 Intel Corporation 4 */ 5 6 #include <drm/intel/display_parent_interface.h> 7 8 #include "regs/xe_gtt_defs.h" 9 10 /* FIXME move intel_remapped_info_size() & co. */ 11 #include "intel_fb.h" 12 13 /* FIXME move intel_initial_plane_config */ 14 #include "intel_display_types.h" 15 16 #include "xe_bo.h" 17 #include "xe_display_bo.h" 18 #include "xe_display_vma.h" 19 #include "xe_fb_pin.h" 20 #include "xe_ggtt.h" 21 #include "xe_mmio.h" 22 #include "xe_ttm_stolen_mgr.h" 23 #include "xe_vram_types.h" 24 25 static bool is_pte_local(u64 pte) 26 { 27 return pte & XE_GGTT_PTE_DM; 28 } 29 30 static bool has_lmembar(struct xe_device *xe) 31 { 32 return GRAPHICS_VERx100(xe) >= 1270; 33 } 34 35 static bool need_pte_local(struct xe_device *xe) 36 { 37 return IS_DGFX(xe) || has_lmembar(xe); 38 } 39 40 static struct xe_bo * 41 initial_plane_bo(struct xe_device *xe, 42 struct intel_initial_plane_config *plane_config) 43 { 44 struct xe_tile *tile0 = xe_device_get_root_tile(xe); 45 struct xe_bo *bo; 46 resource_size_t phys_base; 47 u32 base, size, flags; 48 u64 page_size = xe->info.vram_flags & XE_VRAM_FLAGS_NEED64K ? SZ_64K : SZ_4K; 49 50 if (plane_config->size == 0) 51 return NULL; 52 53 flags = XE_BO_FLAG_FORCE_WC | XE_BO_FLAG_GGTT; 54 55 base = round_down(plane_config->base, page_size); 56 size = round_up(plane_config->base + plane_config->size, 57 page_size); 58 size -= base; 59 60 if (IS_DGFX(xe)) { 61 u64 pte = xe_ggtt_read_pte(tile0->mem.ggtt, base); 62 63 if (is_pte_local(pte) != need_pte_local(xe)) { 64 drm_err(&xe->drm, "Initial plane PTE has bad local memory bit\n"); 65 return NULL; 66 } 67 68 phys_base = pte & ~(page_size - 1); 69 70 flags |= XE_BO_FLAG_VRAM0; 71 72 /* 73 * We don't currently expect this to ever be placed in the 74 * stolen portion. 75 */ 76 if (phys_base >= xe_vram_region_usable_size(tile0->mem.vram)) { 77 drm_err(&xe->drm, 78 "Initial plane programming using invalid range, phys_base=%pa\n", 79 &phys_base); 80 return NULL; 81 } 82 83 drm_dbg_kms(&xe->drm, 84 "Using phys_base=%pa, based on initial plane programming\n", 85 &phys_base); 86 } else { 87 struct ttm_resource_manager *stolen; 88 u64 pte; 89 90 stolen = ttm_manager_type(&xe->ttm, XE_PL_STOLEN); 91 if (!stolen) { 92 drm_dbg_kms(&xe->drm, "No stolen for initial FB\n"); 93 return NULL; 94 } 95 96 pte = xe_ggtt_read_pte(tile0->mem.ggtt, base); 97 98 if (is_pte_local(pte) != need_pte_local(xe)) { 99 drm_err(&xe->drm, "Initial plane PTE has bad local memory bit\n"); 100 return NULL; 101 } 102 103 phys_base = base; 104 flags |= XE_BO_FLAG_STOLEN; 105 106 if (IS_ENABLED(CONFIG_FRAMEBUFFER_CONSOLE) && 107 IS_ENABLED(CONFIG_DRM_FBDEV_EMULATION) && 108 !xe_display_bo_fbdev_prefer_stolen(xe, plane_config->size)) { 109 drm_info(&xe->drm, "Initial FB size exceeds half of stolen, discarding\n"); 110 return NULL; 111 } 112 } 113 114 bo = xe_bo_create_pin_map_at_novm(xe, tile0, size, phys_base, 115 ttm_bo_type_kernel, flags, 0, false); 116 if (IS_ERR(bo)) { 117 drm_dbg_kms(&xe->drm, 118 "Failed to create bo phys_base=%pa size %u with flags %x: %li\n", 119 &phys_base, size, flags, PTR_ERR(bo)); 120 return NULL; 121 } 122 123 return bo; 124 } 125 126 static struct drm_gem_object * 127 xe_alloc_initial_plane_obj(struct drm_device *drm, 128 struct intel_initial_plane_config *plane_config) 129 { 130 struct xe_device *xe = to_xe_device(drm); 131 struct drm_mode_fb_cmd2 mode_cmd = { 0 }; 132 struct drm_framebuffer *fb = plane_config->fb; 133 struct xe_bo *bo; 134 135 mode_cmd.pixel_format = fb->format->format; 136 mode_cmd.width = fb->width; 137 mode_cmd.height = fb->height; 138 mode_cmd.pitches[0] = fb->pitches[0]; 139 mode_cmd.modifier[0] = fb->modifier; 140 mode_cmd.flags = DRM_MODE_FB_MODIFIERS; 141 142 bo = initial_plane_bo(xe, plane_config); 143 if (!bo) 144 return NULL; 145 146 if (intel_framebuffer_init(to_intel_framebuffer(fb), 147 &bo->ttm.base, fb->format, &mode_cmd)) { 148 drm_dbg_kms(&xe->drm, "intel fb init failed\n"); 149 goto err_bo; 150 } 151 /* Reference handed over to fb */ 152 xe_bo_put(bo); 153 154 return &bo->ttm.base; 155 156 err_bo: 157 xe_bo_unpin_map_no_vm(bo); 158 return NULL; 159 } 160 161 static int 162 xe_initial_plane_setup(struct drm_plane_state *_plane_state, 163 struct intel_initial_plane_config *plane_config, 164 struct drm_framebuffer *fb, 165 struct i915_vma *_unused) 166 { 167 struct intel_plane_state *plane_state = to_intel_plane_state(_plane_state); 168 struct i915_vma *vma; 169 struct intel_fb_pin_params pin_params = { 170 .view = &plane_state->view.gtt, 171 }; 172 u32 offset; 173 int ret; 174 175 ret = xe_fb_pin_ggtt_pin(intel_fb_bo(fb), &pin_params, &vma, &offset, NULL); 176 if (ret) 177 return ret; 178 179 plane_state->ggtt_vma = vma; 180 181 plane_state->surf = offset; 182 183 plane_config->vma = vma; 184 185 return 0; 186 } 187 188 static void xe_plane_config_fini(struct intel_initial_plane_config *plane_config) 189 { 190 } 191 192 const struct intel_display_initial_plane_interface xe_display_initial_plane_interface = { 193 .alloc_obj = xe_alloc_initial_plane_obj, 194 .setup = xe_initial_plane_setup, 195 .config_fini = xe_plane_config_fini, 196 }; 197