drm/radeon: Run DRM default client setup

Rework fbdev probing to support fbdev_probe in struct drm_driver
and remove the old fb_probe callback. Provide an initializer macro
for struct drm_driver that sets the callback according to the kernel
configuration.

Call drm_client_setup() to run the kernel's default client setup
for DRM. Set fbdev_probe in struct drm_driver, so that the client
setup can start the common fbdev client.

The radeon driver specifies a preferred color mode depending on
the available video memory, with a default of 32. Adapt this for
the new client interface.

v5:
- select DRM_CLIENT_SELECTION
v2:
- style changes

Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
Cc: Alex Deucher <alexander.deucher@amd.com>
Cc: "Christian König" <christian.koenig@amd.com>
Cc: Xinhui Pan <Xinhui.Pan@amd.com>
Acked-by: Alex Deucher <alexander.deucher@amd.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20240924071734.98201-78-tzimmermann@suse.de
This commit is contained in:
Thomas Zimmermann 2024-09-24 09:13:15 +02:00
parent fe96a73ae5
commit 41d48e557e
4 changed files with 28 additions and 113 deletions

View File

@ -5,6 +5,7 @@ config DRM_RADEON
depends on DRM && PCI && MMU
depends on AGP || !AGP
select FW_LOADER
select DRM_CLIENT_SELECTION
select DRM_DISPLAY_DP_HELPER
select DRM_DISPLAY_HELPER
select DRM_KMS_HELPER

View File

@ -38,8 +38,10 @@
#include <linux/pci.h>
#include <drm/drm_aperture.h>
#include <drm/drm_client_setup.h>
#include <drm/drm_drv.h>
#include <drm/drm_file.h>
#include <drm/drm_fourcc.h>
#include <drm/drm_gem.h>
#include <drm/drm_ioctl.h>
#include <drm/drm_pciids.h>
@ -261,6 +263,7 @@ static int radeon_pci_probe(struct pci_dev *pdev,
unsigned long flags = 0;
struct drm_device *ddev;
struct radeon_device *rdev;
const struct drm_format_info *format;
int ret;
if (!ent)
@ -324,7 +327,14 @@ static int radeon_pci_probe(struct pci_dev *pdev,
if (ret)
goto err_agp;
radeon_fbdev_setup(ddev->dev_private);
if (rdev->mc.real_vram_size <= (8 * 1024 * 1024))
format = drm_format_info(DRM_FORMAT_C8);
else if (ASIC_IS_RN50(rdev) || rdev->mc.real_vram_size <= (32 * 1024 * 1024))
format = drm_format_info(DRM_FORMAT_RGB565);
else
format = NULL;
drm_client_setup(ddev, format);
return 0;
@ -590,6 +600,8 @@ static const struct drm_driver kms_driver = {
.gem_prime_import_sg_table = radeon_gem_prime_import_sg_table,
RADEON_FBDEV_DRIVER_OPS,
.name = DRIVER_NAME,
.desc = DRIVER_DESC,
.date = DRIVER_DATE,

View File

@ -198,12 +198,11 @@ static const struct fb_ops radeon_fbdev_fb_ops = {
.fb_destroy = radeon_fbdev_fb_destroy,
};
/*
* Fbdev helpers and struct drm_fb_helper_funcs
*/
static const struct drm_fb_helper_funcs radeon_fbdev_fb_helper_funcs = {
};
static int radeon_fbdev_fb_helper_fb_probe(struct drm_fb_helper *fb_helper,
struct drm_fb_helper_surface_size *sizes)
int radeon_fbdev_driver_fbdev_probe(struct drm_fb_helper *fb_helper,
struct drm_fb_helper_surface_size *sizes)
{
struct radeon_device *rdev = fb_helper->dev->dev_private;
struct drm_mode_fb_cmd2 mode_cmd = { };
@ -243,6 +242,7 @@ static int radeon_fbdev_fb_helper_fb_probe(struct drm_fb_helper *fb_helper,
}
/* setup helper */
fb_helper->funcs = &radeon_fbdev_fb_helper_funcs;
fb_helper->fb = fb;
/* okay we have an object now allocate the framebuffer */
@ -288,110 +288,6 @@ err_radeon_fbdev_destroy_pinned_object:
return ret;
}
static const struct drm_fb_helper_funcs radeon_fbdev_fb_helper_funcs = {
.fb_probe = radeon_fbdev_fb_helper_fb_probe,
};
/*
* Fbdev client and struct drm_client_funcs
*/
static void radeon_fbdev_client_unregister(struct drm_client_dev *client)
{
struct drm_fb_helper *fb_helper = drm_fb_helper_from_client(client);
struct drm_device *dev = fb_helper->dev;
struct radeon_device *rdev = dev->dev_private;
if (fb_helper->info) {
vga_switcheroo_client_fb_set(rdev->pdev, NULL);
drm_helper_force_disable_all(dev);
drm_fb_helper_unregister_info(fb_helper);
} else {
drm_client_release(&fb_helper->client);
drm_fb_helper_unprepare(fb_helper);
kfree(fb_helper);
}
}
static int radeon_fbdev_client_restore(struct drm_client_dev *client)
{
drm_fb_helper_lastclose(client->dev);
vga_switcheroo_process_delayed_switch();
return 0;
}
static int radeon_fbdev_client_hotplug(struct drm_client_dev *client)
{
struct drm_fb_helper *fb_helper = drm_fb_helper_from_client(client);
struct drm_device *dev = client->dev;
struct radeon_device *rdev = dev->dev_private;
int ret;
if (dev->fb_helper)
return drm_fb_helper_hotplug_event(dev->fb_helper);
ret = drm_fb_helper_init(dev, fb_helper);
if (ret)
goto err_drm_err;
if (!drm_drv_uses_atomic_modeset(dev))
drm_helper_disable_unused_functions(dev);
ret = drm_fb_helper_initial_config(fb_helper);
if (ret)
goto err_drm_fb_helper_fini;
vga_switcheroo_client_fb_set(rdev->pdev, fb_helper->info);
return 0;
err_drm_fb_helper_fini:
drm_fb_helper_fini(fb_helper);
err_drm_err:
drm_err(dev, "Failed to setup radeon fbdev emulation (ret=%d)\n", ret);
return ret;
}
static const struct drm_client_funcs radeon_fbdev_client_funcs = {
.owner = THIS_MODULE,
.unregister = radeon_fbdev_client_unregister,
.restore = radeon_fbdev_client_restore,
.hotplug = radeon_fbdev_client_hotplug,
};
void radeon_fbdev_setup(struct radeon_device *rdev)
{
struct drm_fb_helper *fb_helper;
int bpp_sel = 32;
int ret;
if (rdev->mc.real_vram_size <= (8 * 1024 * 1024))
bpp_sel = 8;
else if (ASIC_IS_RN50(rdev) || rdev->mc.real_vram_size <= (32 * 1024 * 1024))
bpp_sel = 16;
fb_helper = kzalloc(sizeof(*fb_helper), GFP_KERNEL);
if (!fb_helper)
return;
drm_fb_helper_prepare(rdev_to_drm(rdev), fb_helper, bpp_sel, &radeon_fbdev_fb_helper_funcs);
ret = drm_client_init(rdev_to_drm(rdev), &fb_helper->client, "radeon-fbdev",
&radeon_fbdev_client_funcs);
if (ret) {
drm_err(rdev_to_drm(rdev), "Failed to register client: %d\n", ret);
goto err_drm_client_init;
}
drm_client_register(&fb_helper->client);
return;
err_drm_client_init:
drm_fb_helper_unprepare(fb_helper);
kfree(fb_helper);
}
void radeon_fbdev_set_suspend(struct radeon_device *rdev, int state)
{
if (rdev_to_drm(rdev)->fb_helper)

View File

@ -38,6 +38,9 @@
#include <linux/i2c.h>
#include <linux/i2c-algo-bit.h>
struct drm_fb_helper;
struct drm_fb_helper_surface_size;
struct edid;
struct drm_edid;
struct radeon_bo;
@ -935,12 +938,15 @@ void dce8_program_fmt(struct drm_encoder *encoder);
/* fbdev layer */
#if defined(CONFIG_DRM_FBDEV_EMULATION)
void radeon_fbdev_setup(struct radeon_device *rdev);
int radeon_fbdev_driver_fbdev_probe(struct drm_fb_helper *fb_helper,
struct drm_fb_helper_surface_size *sizes);
#define RADEON_FBDEV_DRIVER_OPS \
.fbdev_probe = radeon_fbdev_driver_fbdev_probe
void radeon_fbdev_set_suspend(struct radeon_device *rdev, int state);
bool radeon_fbdev_robj_is_fb(struct radeon_device *rdev, struct radeon_bo *robj);
#else
static inline void radeon_fbdev_setup(struct radeon_device *rdev)
{ }
#define RADEON_FBDEV_DRIVER_OPS \
.fbdev_probe = NULL
static inline void radeon_fbdev_set_suspend(struct radeon_device *rdev, int state)
{ }
static inline bool radeon_fbdev_robj_is_fb(struct radeon_device *rdev, struct radeon_bo *robj)