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
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -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
+13 −1
Original line number Diff line number Diff line
@@ -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,
+5 −109
Original line number Diff line number Diff line
@@ -198,11 +198,10 @@ 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,
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;
@@ -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 @@ static int radeon_fbdev_fb_helper_fb_probe(struct drm_fb_helper *fb_helper,
	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)
+9 −3
Original line number Diff line number Diff line
@@ -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)