Skip to content
Snippets Groups Projects
Commit 41d48e55 authored by Thomas Zimmermann's avatar Thomas Zimmermann
Browse files

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: default avatarThomas 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: default avatarAlex Deucher <alexander.deucher@amd.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20240924071734.98201-78-tzimmermann@suse.de
parent fe96a73a
Branches
No related tags found
No related merge requests found
...@@ -5,6 +5,7 @@ config DRM_RADEON ...@@ -5,6 +5,7 @@ config DRM_RADEON
depends on DRM && PCI && MMU depends on DRM && PCI && MMU
depends on AGP || !AGP depends on AGP || !AGP
select FW_LOADER select FW_LOADER
select DRM_CLIENT_SELECTION
select DRM_DISPLAY_DP_HELPER select DRM_DISPLAY_DP_HELPER
select DRM_DISPLAY_HELPER select DRM_DISPLAY_HELPER
select DRM_KMS_HELPER select DRM_KMS_HELPER
......
...@@ -38,8 +38,10 @@ ...@@ -38,8 +38,10 @@
#include <linux/pci.h> #include <linux/pci.h>
#include <drm/drm_aperture.h> #include <drm/drm_aperture.h>
#include <drm/drm_client_setup.h>
#include <drm/drm_drv.h> #include <drm/drm_drv.h>
#include <drm/drm_file.h> #include <drm/drm_file.h>
#include <drm/drm_fourcc.h>
#include <drm/drm_gem.h> #include <drm/drm_gem.h>
#include <drm/drm_ioctl.h> #include <drm/drm_ioctl.h>
#include <drm/drm_pciids.h> #include <drm/drm_pciids.h>
...@@ -261,6 +263,7 @@ static int radeon_pci_probe(struct pci_dev *pdev, ...@@ -261,6 +263,7 @@ static int radeon_pci_probe(struct pci_dev *pdev,
unsigned long flags = 0; unsigned long flags = 0;
struct drm_device *ddev; struct drm_device *ddev;
struct radeon_device *rdev; struct radeon_device *rdev;
const struct drm_format_info *format;
int ret; int ret;
if (!ent) if (!ent)
...@@ -324,7 +327,14 @@ static int radeon_pci_probe(struct pci_dev *pdev, ...@@ -324,7 +327,14 @@ static int radeon_pci_probe(struct pci_dev *pdev,
if (ret) if (ret)
goto err_agp; 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; return 0;
...@@ -590,6 +600,8 @@ static const struct drm_driver kms_driver = { ...@@ -590,6 +600,8 @@ static const struct drm_driver kms_driver = {
.gem_prime_import_sg_table = radeon_gem_prime_import_sg_table, .gem_prime_import_sg_table = radeon_gem_prime_import_sg_table,
RADEON_FBDEV_DRIVER_OPS,
.name = DRIVER_NAME, .name = DRIVER_NAME,
.desc = DRIVER_DESC, .desc = DRIVER_DESC,
.date = DRIVER_DATE, .date = DRIVER_DATE,
......
...@@ -198,11 +198,10 @@ static const struct fb_ops radeon_fbdev_fb_ops = { ...@@ -198,11 +198,10 @@ static const struct fb_ops radeon_fbdev_fb_ops = {
.fb_destroy = radeon_fbdev_fb_destroy, .fb_destroy = radeon_fbdev_fb_destroy,
}; };
/* static const struct drm_fb_helper_funcs radeon_fbdev_fb_helper_funcs = {
* Fbdev helpers and struct drm_fb_helper_funcs };
*/
static int radeon_fbdev_fb_helper_fb_probe(struct drm_fb_helper *fb_helper, int radeon_fbdev_driver_fbdev_probe(struct drm_fb_helper *fb_helper,
struct drm_fb_helper_surface_size *sizes) struct drm_fb_helper_surface_size *sizes)
{ {
struct radeon_device *rdev = fb_helper->dev->dev_private; struct radeon_device *rdev = fb_helper->dev->dev_private;
...@@ -243,6 +242,7 @@ static int radeon_fbdev_fb_helper_fb_probe(struct drm_fb_helper *fb_helper, ...@@ -243,6 +242,7 @@ static int radeon_fbdev_fb_helper_fb_probe(struct drm_fb_helper *fb_helper,
} }
/* setup helper */ /* setup helper */
fb_helper->funcs = &radeon_fbdev_fb_helper_funcs;
fb_helper->fb = fb; fb_helper->fb = fb;
/* okay we have an object now allocate the framebuffer */ /* okay we have an object now allocate the framebuffer */
...@@ -288,110 +288,6 @@ err_radeon_fbdev_destroy_pinned_object: ...@@ -288,110 +288,6 @@ err_radeon_fbdev_destroy_pinned_object:
return ret; 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) void radeon_fbdev_set_suspend(struct radeon_device *rdev, int state)
{ {
if (rdev_to_drm(rdev)->fb_helper) if (rdev_to_drm(rdev)->fb_helper)
......
...@@ -38,6 +38,9 @@ ...@@ -38,6 +38,9 @@
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/i2c-algo-bit.h> #include <linux/i2c-algo-bit.h>
struct drm_fb_helper;
struct drm_fb_helper_surface_size;
struct edid; struct edid;
struct drm_edid; struct drm_edid;
struct radeon_bo; struct radeon_bo;
...@@ -935,12 +938,15 @@ void dce8_program_fmt(struct drm_encoder *encoder); ...@@ -935,12 +938,15 @@ void dce8_program_fmt(struct drm_encoder *encoder);
/* fbdev layer */ /* fbdev layer */
#if defined(CONFIG_DRM_FBDEV_EMULATION) #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); 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); bool radeon_fbdev_robj_is_fb(struct radeon_device *rdev, struct radeon_bo *robj);
#else #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 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) static inline bool radeon_fbdev_robj_is_fb(struct radeon_device *rdev, struct radeon_bo *robj)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment