drm/{i915, xe}: move fbdev fb calls to parent interface

Move the driver specific fbdev fb calls to the display parent
interface. Reuse the existing struct intel_display_bo_interface, as this
is mostly about gem objects.

Put everything behind IS_ENABLED(CONFIG_DRM_FBDEV_EMULATION) to catch
configuration issues at build or link time.

v2: Rebase

Reviewed-by: Michał Grzelak <michal.grzelak@intel.com> # v1
Link: https://patch.msgid.link/a6bb24909a58181cfc41b91a4c6538a181d27158.1774950508.git.jani.nikula@intel.com
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
This commit is contained in:
Jani Nikula
2026-03-31 12:49:16 +03:00
parent b35b3148a7
commit 89f55d5859
15 changed files with 303 additions and 276 deletions

View File

@@ -326,8 +326,7 @@ i915-$(CONFIG_ACPI) += \
display/intel_acpi.o \
display/intel_opregion.o
i915-$(CONFIG_DRM_FBDEV_EMULATION) += \
display/intel_fbdev.o \
display/intel_fbdev_fb.o
display/intel_fbdev.o
i915-$(CONFIG_DEBUG_FS) += \
display/intel_display_debugfs.o \
display/intel_display_debugfs_params.o \

View File

@@ -85,3 +85,30 @@ struct drm_gem_object *intel_bo_framebuffer_lookup(struct intel_display *display
{
return display->parent->bo->framebuffer_lookup(display->drm, filp, user_mode_cmd);
}
#if IS_ENABLED(CONFIG_DRM_FBDEV_EMULATION)
u32 intel_bo_fbdev_pitch_align(struct intel_display *display, u32 stride)
{
return display->parent->bo->fbdev_pitch_align(stride);
}
struct drm_gem_object *intel_bo_fbdev_create(struct intel_display *display, int size)
{
return display->parent->bo->fbdev_create(display->drm, size);
}
void intel_bo_fbdev_destroy(struct drm_gem_object *obj)
{
struct intel_display *display = to_intel_display(obj->dev);
display->parent->bo->fbdev_destroy(obj);
}
int intel_bo_fbdev_fill_info(struct drm_gem_object *obj, struct fb_info *info,
struct i915_vma *vma)
{
struct intel_display *display = to_intel_display(obj->dev);
return display->parent->bo->fbdev_fill_info(obj, info, vma);
}
#endif

View File

@@ -10,6 +10,8 @@ struct drm_file;
struct drm_gem_object;
struct drm_mode_fb_cmd2;
struct drm_scanout_buffer;
struct fb_info;
struct i915_vma;
struct intel_display;
struct intel_framebuffer;
struct seq_file;
@@ -31,4 +33,10 @@ struct drm_gem_object *intel_bo_framebuffer_lookup(struct intel_display *display
struct drm_file *filp,
const struct drm_mode_fb_cmd2 *user_mode_cmd);
u32 intel_bo_fbdev_pitch_align(struct intel_display *display, u32 stride);
struct drm_gem_object *intel_bo_fbdev_create(struct intel_display *display, int size);
void intel_bo_fbdev_destroy(struct drm_gem_object *obj);
int intel_bo_fbdev_fill_info(struct drm_gem_object *obj, struct fb_info *info,
struct i915_vma *vma);
#endif /* __INTEL_BO__ */

View File

@@ -54,7 +54,6 @@
#include "intel_fb.h"
#include "intel_fb_pin.h"
#include "intel_fbdev.h"
#include "intel_fbdev_fb.h"
#include "intel_frontbuffer.h"
struct intel_fbdev {
@@ -204,7 +203,8 @@ static const struct drm_fb_helper_funcs intel_fb_helper_funcs = {
.fb_set_suspend = intelfb_set_suspend,
};
static void intel_fbdev_fill_mode_cmd(struct drm_fb_helper_surface_size *sizes,
static void intel_fbdev_fill_mode_cmd(struct intel_display *display,
struct drm_fb_helper_surface_size *sizes,
struct drm_mode_fb_cmd2 *mode_cmd)
{
/* we don't do packed 24bpp */
@@ -215,7 +215,7 @@ static void intel_fbdev_fill_mode_cmd(struct drm_fb_helper_surface_size *sizes,
mode_cmd->width = sizes->surface_width;
mode_cmd->height = sizes->surface_height;
mode_cmd->pitches[0] = intel_fbdev_fb_pitch_align(mode_cmd->width * DIV_ROUND_UP(sizes->surface_bpp, 8));
mode_cmd->pitches[0] = intel_bo_fbdev_pitch_align(display, mode_cmd->width * DIV_ROUND_UP(sizes->surface_bpp, 8));
mode_cmd->pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp,
sizes->surface_depth);
mode_cmd->modifier[0] = DRM_FORMAT_MOD_LINEAR;
@@ -230,12 +230,12 @@ __intel_fbdev_fb_alloc(struct intel_display *display,
struct drm_gem_object *obj;
int size;
intel_fbdev_fill_mode_cmd(sizes, &mode_cmd);
intel_fbdev_fill_mode_cmd(display, sizes, &mode_cmd);
size = mode_cmd.pitches[0] * mode_cmd.height;
size = PAGE_ALIGN(size);
obj = intel_fbdev_fb_bo_create(display->drm, size);
obj = intel_bo_fbdev_create(display, size);
if (IS_ERR(obj)) {
fb = ERR_CAST(obj);
goto err;
@@ -247,7 +247,7 @@ __intel_fbdev_fb_alloc(struct intel_display *display,
mode_cmd.modifier[0]),
&mode_cmd);
if (IS_ERR(fb)) {
intel_fbdev_fb_bo_destroy(obj);
intel_bo_fbdev_destroy(obj);
goto err;
}
@@ -327,7 +327,7 @@ int intel_fbdev_driver_fbdev_probe(struct drm_fb_helper *helper,
obj = intel_fb_bo(&fb->base);
ret = intel_fbdev_fb_fill_info(obj, info, vma);
ret = intel_bo_fbdev_fill_info(obj, info, vma);
if (ret)
goto out_unpin;

View File

@@ -1,118 +0,0 @@
/* SPDX-License-Identifier: MIT */
/*
* Copyright © 2023 Intel Corporation
*/
#include <linux/fb.h>
#include <drm/drm_print.h>
#include "gem/i915_gem_lmem.h"
#include "i915_drv.h"
#include "intel_fbdev_fb.h"
u32 intel_fbdev_fb_pitch_align(u32 stride)
{
return ALIGN(stride, 64);
}
bool intel_fbdev_fb_prefer_stolen(struct drm_device *drm, unsigned int size)
{
struct drm_i915_private *i915 = to_i915(drm);
/* Skip stolen on MTL as Wa_22018444074 mitigation. */
if (IS_METEORLAKE(i915))
return false;
/*
* If the FB is too big, just don't use it since fbdev is not very
* important and we should probably use that space with FBC or other
* features.
*/
return i915->dsm.usable_size >= size * 2;
}
struct drm_gem_object *intel_fbdev_fb_bo_create(struct drm_device *drm, int size)
{
struct drm_i915_private *i915 = to_i915(drm);
struct drm_i915_gem_object *obj;
obj = ERR_PTR(-ENODEV);
if (HAS_LMEM(i915)) {
obj = i915_gem_object_create_lmem(i915, size,
I915_BO_ALLOC_CONTIGUOUS |
I915_BO_ALLOC_USER);
} else {
if (intel_fbdev_fb_prefer_stolen(drm, size))
obj = i915_gem_object_create_stolen(i915, size);
else
drm_info(drm, "Allocating fbdev: Stolen memory not preferred.\n");
if (IS_ERR(obj))
obj = i915_gem_object_create_shmem(i915, size);
}
if (IS_ERR(obj)) {
drm_err(drm, "failed to allocate framebuffer (%pe)\n", obj);
return ERR_PTR(-ENOMEM);
}
return &obj->base;
}
void intel_fbdev_fb_bo_destroy(struct drm_gem_object *obj)
{
drm_gem_object_put(obj);
}
int intel_fbdev_fb_fill_info(struct drm_gem_object *_obj, struct fb_info *info,
struct i915_vma *vma)
{
struct drm_i915_private *i915 = to_i915(_obj->dev);
struct drm_i915_gem_object *obj = to_intel_bo(_obj);
struct i915_gem_ww_ctx ww;
void __iomem *vaddr;
int ret;
if (i915_gem_object_is_lmem(obj)) {
struct intel_memory_region *mem = obj->mm.region;
/* Use fbdev's framebuffer from lmem for discrete */
info->fix.smem_start =
(unsigned long)(mem->io.start +
i915_gem_object_get_dma_address(obj, 0) -
mem->region.start);
info->fix.smem_len = obj->base.size;
} else {
struct i915_ggtt *ggtt = to_gt(i915)->ggtt;
/* Our framebuffer is the entirety of fbdev's system memory */
info->fix.smem_start =
(unsigned long)(ggtt->gmadr.start + i915_ggtt_offset(vma));
info->fix.smem_len = vma->size;
}
for_i915_gem_ww(&ww, ret, false) {
ret = i915_gem_object_lock(vma->obj, &ww);
if (ret)
continue;
vaddr = i915_vma_pin_iomap(vma);
if (IS_ERR(vaddr)) {
drm_err(&i915->drm,
"Failed to remap framebuffer into virtual memory (%pe)\n", vaddr);
ret = PTR_ERR(vaddr);
continue;
}
}
if (ret)
return ret;
info->screen_base = vaddr;
info->screen_size = intel_bo_to_drm_bo(obj)->size;
return 0;
}

View File

@@ -1,24 +0,0 @@
/* SPDX-License-Identifier: MIT */
/*
* Copyright © 2023 Intel Corporation
*/
#ifndef __INTEL_FBDEV_FB_H__
#define __INTEL_FBDEV_FB_H__
#include <linux/types.h>
struct drm_device;
struct drm_gem_object;
struct drm_mode_fb_cmd2;
struct fb_info;
struct i915_vma;
u32 intel_fbdev_fb_pitch_align(u32 stride);
struct drm_gem_object *intel_fbdev_fb_bo_create(struct drm_device *drm, int size);
void intel_fbdev_fb_bo_destroy(struct drm_gem_object *obj);
int intel_fbdev_fb_fill_info(struct drm_gem_object *obj, struct fb_info *info,
struct i915_vma *vma);
bool intel_fbdev_fb_prefer_stolen(struct drm_device *drm, unsigned int size);
#endif

View File

@@ -1,11 +1,14 @@
// SPDX-License-Identifier: MIT
/* Copyright © 2024 Intel Corporation */
#include <linux/fb.h>
#include <drm/drm_panic.h>
#include <drm/drm_print.h>
#include <drm/intel/display_parent_interface.h>
#include "display/intel_fb.h"
#include "gem/i915_gem_lmem.h"
#include "gem/i915_gem_mman.h"
#include "gem/i915_gem_object.h"
#include "gem/i915_gem_object_frontbuffer.h"
@@ -141,6 +144,113 @@ i915_bo_framebuffer_lookup(struct drm_device *drm,
return intel_bo_to_drm_bo(obj);
}
#if IS_ENABLED(CONFIG_DRM_FBDEV_EMULATION)
static u32 i915_bo_fbdev_pitch_align(u32 stride)
{
return ALIGN(stride, 64);
}
bool i915_bo_fbdev_prefer_stolen(struct drm_device *drm, unsigned int size)
{
struct drm_i915_private *i915 = to_i915(drm);
/* Skip stolen on MTL as Wa_22018444074 mitigation. */
if (IS_METEORLAKE(i915))
return false;
/*
* If the FB is too big, just don't use it since fbdev is not very
* important and we should probably use that space with FBC or other
* features.
*/
return i915->dsm.usable_size >= size * 2;
}
static struct drm_gem_object *i915_bo_fbdev_create(struct drm_device *drm, int size)
{
struct drm_i915_private *i915 = to_i915(drm);
struct drm_i915_gem_object *obj;
obj = ERR_PTR(-ENODEV);
if (HAS_LMEM(i915)) {
obj = i915_gem_object_create_lmem(i915, size,
I915_BO_ALLOC_CONTIGUOUS |
I915_BO_ALLOC_USER);
} else {
if (i915_bo_fbdev_prefer_stolen(drm, size))
obj = i915_gem_object_create_stolen(i915, size);
else
drm_info(drm, "Allocating fbdev: Stolen memory not preferred.\n");
if (IS_ERR(obj))
obj = i915_gem_object_create_shmem(i915, size);
}
if (IS_ERR(obj)) {
drm_err(drm, "failed to allocate framebuffer (%pe)\n", obj);
return ERR_PTR(-ENOMEM);
}
return &obj->base;
}
static void i915_bo_fbdev_destroy(struct drm_gem_object *obj)
{
drm_gem_object_put(obj);
}
static int i915_bo_fbdev_fill_info(struct drm_gem_object *_obj, struct fb_info *info,
struct i915_vma *vma)
{
struct drm_i915_private *i915 = to_i915(_obj->dev);
struct drm_i915_gem_object *obj = to_intel_bo(_obj);
struct i915_gem_ww_ctx ww;
void __iomem *vaddr;
int ret;
if (i915_gem_object_is_lmem(obj)) {
struct intel_memory_region *mem = obj->mm.region;
/* Use fbdev's framebuffer from lmem for discrete */
info->fix.smem_start =
(unsigned long)(mem->io.start +
i915_gem_object_get_dma_address(obj, 0) -
mem->region.start);
info->fix.smem_len = obj->base.size;
} else {
struct i915_ggtt *ggtt = to_gt(i915)->ggtt;
/* Our framebuffer is the entirety of fbdev's system memory */
info->fix.smem_start =
(unsigned long)(ggtt->gmadr.start + i915_ggtt_offset(vma));
info->fix.smem_len = vma->size;
}
for_i915_gem_ww(&ww, ret, false) {
ret = i915_gem_object_lock(vma->obj, &ww);
if (ret)
continue;
vaddr = i915_vma_pin_iomap(vma);
if (IS_ERR(vaddr)) {
drm_err(&i915->drm,
"Failed to remap framebuffer into virtual memory (%pe)\n", vaddr);
ret = PTR_ERR(vaddr);
continue;
}
}
if (ret)
return ret;
info->screen_base = vaddr;
info->screen_size = intel_bo_to_drm_bo(obj)->size;
return 0;
}
#endif
const struct intel_display_bo_interface i915_display_bo_interface = {
.is_tiled = i915_bo_is_tiled,
.is_userptr = i915_bo_is_userptr,
@@ -153,4 +263,10 @@ const struct intel_display_bo_interface i915_display_bo_interface = {
.framebuffer_init = i915_bo_framebuffer_init,
.framebuffer_fini = i915_bo_framebuffer_fini,
.framebuffer_lookup = i915_bo_framebuffer_lookup,
#if IS_ENABLED(CONFIG_DRM_FBDEV_EMULATION)
.fbdev_create = i915_bo_fbdev_create,
.fbdev_destroy = i915_bo_fbdev_destroy,
.fbdev_fill_info = i915_bo_fbdev_fill_info,
.fbdev_pitch_align = i915_bo_fbdev_pitch_align,
#endif
};

View File

@@ -4,6 +4,12 @@
#ifndef __I915_BO_H__
#define __I915_BO_H__
#include <linux/types.h>
struct drm_device;
bool i915_bo_fbdev_prefer_stolen(struct drm_device *drm, unsigned int size);
extern const struct intel_display_bo_interface i915_display_bo_interface;
#endif /* __I915_BO_H__ */

View File

@@ -9,10 +9,10 @@
#include "display/intel_crtc.h"
#include "display/intel_display_types.h"
#include "display/intel_fb.h"
#include "display/intel_fbdev_fb.h"
#include "gem/i915_gem_lmem.h"
#include "gem/i915_gem_region.h"
#include "i915_bo.h"
#include "i915_drv.h"
#include "i915_initial_plane.h"
@@ -118,7 +118,7 @@ initial_plane_vma(struct drm_i915_private *i915,
if (IS_ENABLED(CONFIG_DRM_FBDEV_EMULATION) &&
IS_ENABLED(CONFIG_FRAMEBUFFER_CONSOLE) &&
mem == i915->mm.stolen_region &&
!intel_fbdev_fb_prefer_stolen(&i915->drm, size)) {
!i915_bo_fbdev_prefer_stolen(&i915->drm, size)) {
drm_dbg_kms(&i915->drm, "Initial FB size exceeds half of stolen, discarding\n");
return NULL;
}

View File

@@ -211,7 +211,6 @@ $(obj)/i915-display/%.o: $(srctree)/drivers/gpu/drm/i915/display/%.c FORCE
# Display code specific to xe
xe-$(CONFIG_DRM_XE_DISPLAY) += \
display/intel_fbdev_fb.o \
display/xe_display.o \
display/xe_display_bo.o \
display/xe_display_pcode.o \

View File

@@ -1,120 +0,0 @@
/* SPDX-License-Identifier: MIT */
/*
* Copyright © 2023 Intel Corporation
*/
#include <linux/fb.h>
#include "intel_fbdev_fb.h"
#include "xe_bo.h"
#include "xe_ttm_stolen_mgr.h"
#include "xe_wa.h"
#include <generated/xe_device_wa_oob.h>
/*
* FIXME: There shouldn't be any reason to have XE_PAGE_SIZE stride
* alignment. The same 64 as i915 uses should be fine, and we shouldn't need to
* have driver specific values. However, dropping the stride alignment to 64
* leads to underflowing the bo pin count in the atomic cleanup work.
*/
u32 intel_fbdev_fb_pitch_align(u32 stride)
{
return ALIGN(stride, XE_PAGE_SIZE);
}
bool intel_fbdev_fb_prefer_stolen(struct drm_device *drm, unsigned int size)
{
struct xe_device *xe = to_xe_device(drm);
struct ttm_resource_manager *stolen;
stolen = ttm_manager_type(&xe->ttm, XE_PL_STOLEN);
if (!stolen)
return false;
if (IS_DGFX(xe))
return false;
if (XE_DEVICE_WA(xe, 22019338487_display))
return false;
/*
* If the FB is too big, just don't use it since fbdev is not very
* important and we should probably use that space with FBC or other
* features.
*/
return stolen->size >= size * 2;
}
struct drm_gem_object *intel_fbdev_fb_bo_create(struct drm_device *drm, int size)
{
struct xe_device *xe = to_xe_device(drm);
struct xe_bo *obj;
obj = ERR_PTR(-ENODEV);
if (intel_fbdev_fb_prefer_stolen(drm, size)) {
obj = xe_bo_create_pin_map_novm(xe, xe_device_get_root_tile(xe),
size,
ttm_bo_type_kernel,
XE_BO_FLAG_FORCE_WC |
XE_BO_FLAG_STOLEN |
XE_BO_FLAG_GGTT,
false);
if (!IS_ERR(obj))
drm_info(&xe->drm, "Allocated fbdev into stolen\n");
else
drm_info(&xe->drm, "Allocated fbdev into stolen failed: %li\n", PTR_ERR(obj));
} else {
drm_info(&xe->drm, "Allocating fbdev: Stolen memory not preferred.\n");
}
if (IS_ERR(obj)) {
obj = xe_bo_create_pin_map_novm(xe, xe_device_get_root_tile(xe), size,
ttm_bo_type_kernel,
XE_BO_FLAG_FORCE_WC |
XE_BO_FLAG_VRAM_IF_DGFX(xe_device_get_root_tile(xe)) |
XE_BO_FLAG_GGTT,
false);
}
if (IS_ERR(obj)) {
drm_err(&xe->drm, "failed to allocate framebuffer (%pe)\n", obj);
return ERR_PTR(-ENOMEM);
}
return &obj->ttm.base;
}
void intel_fbdev_fb_bo_destroy(struct drm_gem_object *obj)
{
xe_bo_unpin_map_no_vm(gem_to_xe_bo(obj));
}
int intel_fbdev_fb_fill_info(struct drm_gem_object *_obj, struct fb_info *info,
struct i915_vma *vma)
{
struct xe_bo *obj = gem_to_xe_bo(_obj);
struct pci_dev *pdev = to_pci_dev(_obj->dev->dev);
if (!(obj->flags & XE_BO_FLAG_SYSTEM)) {
if (obj->flags & XE_BO_FLAG_STOLEN)
info->fix.smem_start = xe_ttm_stolen_io_offset(obj, 0);
else
info->fix.smem_start =
pci_resource_start(pdev, 2) +
xe_bo_addr(obj, 0, XE_PAGE_SIZE);
info->fix.smem_len = obj->ttm.base.size;
} else {
/* XXX: Pure fiction, as the BO may not be physically accessible.. */
info->fix.smem_start = 0;
info->fix.smem_len = obj->ttm.base.size;
}
XE_WARN_ON(iosys_map_is_null(&obj->vmap));
info->screen_base = obj->vmap.vaddr_iomem;
info->screen_size = obj->ttm.base.size;
return 0;
}

View File

@@ -1,6 +1,8 @@
// SPDX-License-Identifier: MIT
/* Copyright © 2024 Intel Corporation */
#include <linux/fb.h>
#include <drm/drm_gem.h>
#include <drm/intel/display_parent_interface.h>
@@ -8,6 +10,10 @@
#include "xe_bo.h"
#include "xe_display_bo.h"
#include "xe_pxp.h"
#include "xe_ttm_stolen_mgr.h"
#include "xe_wa.h"
#include <generated/xe_device_wa_oob.h>
static bool xe_display_bo_is_protected(struct drm_gem_object *obj)
{
@@ -101,6 +107,115 @@ xe_display_bo_framebuffer_lookup(struct drm_device *drm,
return gem;
}
#if IS_ENABLED(CONFIG_DRM_FBDEV_EMULATION)
/*
* FIXME: There shouldn't be any reason to have XE_PAGE_SIZE stride
* alignment. The same 64 as i915 uses should be fine, and we shouldn't need to
* have driver specific values. However, dropping the stride alignment to 64
* leads to underflowing the bo pin count in the atomic cleanup work.
*/
static u32 xe_display_bo_fbdev_pitch_align(u32 stride)
{
return ALIGN(stride, XE_PAGE_SIZE);
}
bool xe_display_bo_fbdev_prefer_stolen(struct drm_device *drm, unsigned int size)
{
struct xe_device *xe = to_xe_device(drm);
struct ttm_resource_manager *stolen;
stolen = ttm_manager_type(&xe->ttm, XE_PL_STOLEN);
if (!stolen)
return false;
if (IS_DGFX(xe))
return false;
if (XE_DEVICE_WA(xe, 22019338487_display))
return false;
/*
* If the FB is too big, just don't use it since fbdev is not very
* important and we should probably use that space with FBC or other
* features.
*/
return stolen->size >= size * 2;
}
static struct drm_gem_object *xe_display_bo_fbdev_create(struct drm_device *drm, int size)
{
struct xe_device *xe = to_xe_device(drm);
struct xe_bo *obj;
obj = ERR_PTR(-ENODEV);
if (xe_display_bo_fbdev_prefer_stolen(drm, size)) {
obj = xe_bo_create_pin_map_novm(xe, xe_device_get_root_tile(xe),
size,
ttm_bo_type_kernel,
XE_BO_FLAG_FORCE_WC |
XE_BO_FLAG_STOLEN |
XE_BO_FLAG_GGTT,
false);
if (!IS_ERR(obj))
drm_info(&xe->drm, "Allocated fbdev into stolen\n");
else
drm_info(&xe->drm, "Allocated fbdev into stolen failed: %li\n", PTR_ERR(obj));
} else {
drm_info(&xe->drm, "Allocating fbdev: Stolen memory not preferred.\n");
}
if (IS_ERR(obj)) {
obj = xe_bo_create_pin_map_novm(xe, xe_device_get_root_tile(xe), size,
ttm_bo_type_kernel,
XE_BO_FLAG_FORCE_WC |
XE_BO_FLAG_VRAM_IF_DGFX(xe_device_get_root_tile(xe)) |
XE_BO_FLAG_GGTT,
false);
}
if (IS_ERR(obj)) {
drm_err(&xe->drm, "failed to allocate framebuffer (%pe)\n", obj);
return ERR_PTR(-ENOMEM);
}
return &obj->ttm.base;
}
static void xe_display_bo_fbdev_destroy(struct drm_gem_object *obj)
{
xe_bo_unpin_map_no_vm(gem_to_xe_bo(obj));
}
static int xe_display_bo_fbdev_fill_info(struct drm_gem_object *_obj, struct fb_info *info,
struct i915_vma *vma)
{
struct xe_bo *obj = gem_to_xe_bo(_obj);
struct pci_dev *pdev = to_pci_dev(_obj->dev->dev);
if (!(obj->flags & XE_BO_FLAG_SYSTEM)) {
if (obj->flags & XE_BO_FLAG_STOLEN)
info->fix.smem_start = xe_ttm_stolen_io_offset(obj, 0);
else
info->fix.smem_start =
pci_resource_start(pdev, 2) +
xe_bo_addr(obj, 0, XE_PAGE_SIZE);
info->fix.smem_len = obj->ttm.base.size;
} else {
/* XXX: Pure fiction, as the BO may not be physically accessible.. */
info->fix.smem_start = 0;
info->fix.smem_len = obj->ttm.base.size;
}
XE_WARN_ON(iosys_map_is_null(&obj->vmap));
info->screen_base = obj->vmap.vaddr_iomem;
info->screen_size = obj->ttm.base.size;
return 0;
}
#endif
const struct intel_display_bo_interface xe_display_bo_interface = {
.is_protected = xe_display_bo_is_protected,
.key_check = xe_pxp_obj_key_check,
@@ -109,4 +224,10 @@ const struct intel_display_bo_interface xe_display_bo_interface = {
.framebuffer_init = xe_display_bo_framebuffer_init,
.framebuffer_fini = xe_display_bo_framebuffer_fini,
.framebuffer_lookup = xe_display_bo_framebuffer_lookup,
#if IS_ENABLED(CONFIG_DRM_FBDEV_EMULATION)
.fbdev_create = xe_display_bo_fbdev_create,
.fbdev_destroy = xe_display_bo_fbdev_destroy,
.fbdev_fill_info = xe_display_bo_fbdev_fill_info,
.fbdev_pitch_align = xe_display_bo_fbdev_pitch_align,
#endif
};

View File

@@ -4,6 +4,12 @@
#ifndef __XE_DISPLAY_BO_H__
#define __XE_DISPLAY_BO_H__
#include <linux/types.h>
struct drm_device;
bool xe_display_bo_fbdev_prefer_stolen(struct drm_device *drm, unsigned int size);
extern const struct intel_display_bo_interface xe_display_bo_interface;
#endif

View File

@@ -12,8 +12,8 @@
#include "intel_display_types.h"
#include "intel_fb.h"
#include "intel_fb_pin.h"
#include "intel_fbdev_fb.h"
#include "xe_bo.h"
#include "xe_display_bo.h"
#include "xe_display_vma.h"
#include "xe_ggtt.h"
#include "xe_mmio.h"
@@ -87,7 +87,7 @@ initial_plane_bo(struct xe_device *xe,
if (IS_ENABLED(CONFIG_FRAMEBUFFER_CONSOLE) &&
IS_ENABLED(CONFIG_DRM_FBDEV_EMULATION) &&
!intel_fbdev_fb_prefer_stolen(&xe->drm, plane_config->size)) {
!xe_display_bo_fbdev_prefer_stolen(&xe->drm, plane_config->size)) {
drm_info(&xe->drm, "Initial FB size exceeds half of stolen, discarding\n");
return NULL;
}

View File

@@ -16,6 +16,7 @@ struct drm_gem_object;
struct drm_mode_fb_cmd2;
struct drm_plane_state;
struct drm_scanout_buffer;
struct fb_info;
struct i915_vma;
struct intel_dpt;
struct intel_dsb_buffer;
@@ -44,6 +45,12 @@ struct intel_display_bo_interface {
struct drm_gem_object *(*framebuffer_lookup)(struct drm_device *drm,
struct drm_file *filp,
const struct drm_mode_fb_cmd2 *user_mode_cmd);
#if IS_ENABLED(CONFIG_DRM_FBDEV_EMULATION)
struct drm_gem_object *(*fbdev_create)(struct drm_device *drm, int size);
void (*fbdev_destroy)(struct drm_gem_object *obj);
int (*fbdev_fill_info)(struct drm_gem_object *obj, struct fb_info *info, struct i915_vma *vma);
u32 (*fbdev_pitch_align)(u32 stride);
#endif
};
struct intel_display_dpt_interface {