From: Thomas Zimmermann <tzimmermann@suse.de>
To: alexander.deucher@amd.com, christian.koenig@amd.com,
Xinhui.Pan@amd.com, airlied@gmail.com, daniel@ffwll.ch,
javierm@redhat.com
Cc: Thomas Zimmermann <tzimmermann@suse.de>,
amd-gfx@lists.freedesktop.org, dri-devel@lists.freedesktop.org
Subject: [PATCH 09/10] drm/radeon: Implement client-based fbdev emulation
Date: Thu, 16 Mar 2023 10:37:37 +0100 [thread overview]
Message-ID: <20230316093738.28866-10-tzimmermann@suse.de> (raw)
In-Reply-To: <20230316093738.28866-1-tzimmermann@suse.de>
Implement fbdev emulation on top of struct drm_client and its helpers.
Replaces ad-hoc interfaces for restoring and closing fbdev emulation with
per-client callbacks for hotplugging, restoring and unregistering.
A single function, radeon_fbdev_setup(), starts fbdev emulation after
the DRM device has been registered. Hence, fbdev acts like a regular
DRM client.
The setup call prepares the fbdev emulation and invokes connector
hotplugging. The first successful hotplug event initializes fbdev
emulation with a framebuffer, device file, etc.
Unregistering depends on the hotplug status. Fully initialized emulation
is cleaned up through drm_fb_helper_unregister_info() and fb_destroy.
For prepared-only setups, unregistering unprepares the emulation and
releases all resources. In both cases, fbdev emulation will be cleaned
up.
Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
---
drivers/gpu/drm/radeon/radeon_display.c | 4 -
drivers/gpu/drm/radeon/radeon_drv.c | 3 +-
drivers/gpu/drm/radeon/radeon_drv.h | 1 -
drivers/gpu/drm/radeon/radeon_fb.c | 126 ++++++++++++++++--------
drivers/gpu/drm/radeon/radeon_kms.c | 18 ----
drivers/gpu/drm/radeon/radeon_mode.h | 3 +-
6 files changed, 89 insertions(+), 66 deletions(-)
diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c
index f34a7f63261d..901e75ec70ff 100644
--- a/drivers/gpu/drm/radeon/radeon_display.c
+++ b/drivers/gpu/drm/radeon/radeon_display.c
@@ -34,7 +34,6 @@
#include <drm/drm_device.h>
#include <drm/drm_drv.h>
#include <drm/drm_edid.h>
-#include <drm/drm_fb_helper.h>
#include <drm/drm_fourcc.h>
#include <drm/drm_framebuffer.h>
#include <drm/drm_gem_framebuffer_helper.h>
@@ -1354,7 +1353,6 @@ radeon_user_framebuffer_create(struct drm_device *dev,
static const struct drm_mode_config_funcs radeon_mode_funcs = {
.fb_create = radeon_user_framebuffer_create,
- .output_poll_changed = drm_fb_helper_output_poll_changed,
};
static const struct drm_prop_enum_list radeon_tmds_pll_enum_list[] =
@@ -1642,7 +1640,6 @@ int radeon_modeset_init(struct radeon_device *rdev)
/* setup afmt */
radeon_afmt_init(rdev);
- radeon_fbdev_init(rdev);
drm_kms_helper_poll_init(rdev->ddev);
/* do pm late init */
@@ -1657,7 +1654,6 @@ void radeon_modeset_fini(struct radeon_device *rdev)
drm_kms_helper_poll_fini(rdev->ddev);
radeon_hpd_fini(rdev);
drm_helper_force_disable_all(rdev->ddev);
- radeon_fbdev_fini(rdev);
radeon_afmt_fini(rdev);
drm_mode_config_cleanup(rdev->ddev);
rdev->mode_info.mode_config_initialized = false;
diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c
index 716ab85a376b..e4374814f0ef 100644
--- a/drivers/gpu/drm/radeon/radeon_drv.c
+++ b/drivers/gpu/drm/radeon/radeon_drv.c
@@ -341,6 +341,8 @@ static int radeon_pci_probe(struct pci_dev *pdev,
if (ret)
goto err_agp;
+ radeon_fbdev_setup(dev->dev_private);
+
return 0;
err_agp:
@@ -595,7 +597,6 @@ static const struct drm_driver kms_driver = {
.load = radeon_driver_load_kms,
.open = radeon_driver_open_kms,
.postclose = radeon_driver_postclose_kms,
- .lastclose = radeon_driver_lastclose_kms,
.unload = radeon_driver_unload_kms,
.ioctls = radeon_ioctls_kms,
.num_ioctls = ARRAY_SIZE(radeon_ioctls_kms),
diff --git a/drivers/gpu/drm/radeon/radeon_drv.h b/drivers/gpu/drm/radeon/radeon_drv.h
index ac7970919c4d..2ffe0975ee54 100644
--- a/drivers/gpu/drm/radeon/radeon_drv.h
+++ b/drivers/gpu/drm/radeon/radeon_drv.h
@@ -120,7 +120,6 @@ long radeon_drm_ioctl(struct file *filp,
int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags);
void radeon_driver_unload_kms(struct drm_device *dev);
-void radeon_driver_lastclose_kms(struct drm_device *dev);
int radeon_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv);
void radeon_driver_postclose_kms(struct drm_device *dev,
struct drm_file *file_priv);
diff --git a/drivers/gpu/drm/radeon/radeon_fb.c b/drivers/gpu/drm/radeon/radeon_fb.c
index 2b629bb23be8..fe76e29910ef 100644
--- a/drivers/gpu/drm/radeon/radeon_fb.c
+++ b/drivers/gpu/drm/radeon/radeon_fb.c
@@ -24,19 +24,16 @@
* David Airlie
*/
-#include <linux/module.h>
#include <linux/pci.h>
#include <linux/pm_runtime.h>
-#include <linux/slab.h>
#include <linux/vga_switcheroo.h>
-#include <drm/drm_crtc.h>
#include <drm/drm_crtc_helper.h>
+#include <drm/drm_drv.h>
#include <drm/drm_fb_helper.h>
#include <drm/drm_fourcc.h>
#include <drm/drm_framebuffer.h>
#include <drm/drm_gem_framebuffer_helper.h>
-#include <drm/radeon_drm.h>
#include "radeon.h"
@@ -179,14 +176,16 @@ static void radeon_fbdev_fb_destroy(struct fb_info *info)
struct drm_framebuffer *fb = fb_helper->fb;
struct drm_gem_object *gobj = drm_gem_fb_get_obj(fb, 0);
+ drm_fb_helper_fini(fb_helper);
+
drm_framebuffer_unregister_private(fb);
drm_framebuffer_cleanup(fb);
kfree(fb);
- fb_helper->fb = NULL;
-
radeon_fbdev_destroy_pinned_object(gobj);
- drm_fb_helper_fini(fb_helper);
+ drm_client_release(&fb_helper->client);
+ drm_fb_helper_unprepare(fb_helper);
+ kfree(fb_helper);
}
static const struct fb_ops radeon_fbdev_fb_ops = {
@@ -279,7 +278,6 @@ static int radeon_fbdev_fb_helper_fb_probe(struct drm_fb_helper *fb_helper,
DRM_INFO("fb depth is %d\n", fb->format->depth);
DRM_INFO(" pitch is %d\n", fb->pitches[0]);
- vga_switcheroo_client_fb_set(rdev->pdev, info);
return 0;
err_drm_framebuffer_unregister_private:
@@ -297,59 +295,107 @@ static const struct drm_fb_helper_funcs radeon_fbdev_fb_helper_funcs = {
.fb_probe = radeon_fbdev_fb_helper_fb_probe,
};
-int radeon_fbdev_init(struct radeon_device *rdev)
+/*
+ * Fbdev client and struct drm_client_funcs
+ */
+
+static void radeon_fbdev_client_unregister(struct drm_client_dev *client)
{
- struct drm_fb_helper *fb_helper;
- int bpp_sel = 32;
- int ret;
+ 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_fb_helper_unregister_info(fb_helper);
+ } else {
+ drm_client_release(&fb_helper->client);
+ drm_fb_helper_unprepare(fb_helper);
+ kfree(fb_helper);
+ }
+}
- /* don't enable fbdev if no connectors */
- if (list_empty(&rdev->ddev->mode_config.connector_list))
- return 0;
+static int radeon_fbdev_client_restore(struct drm_client_dev *client)
+{
+ drm_fb_helper_lastclose(client->dev);
+ vga_switcheroo_process_delayed_switch();
- /* select 8 bpp console on 8MB cards, or 16 bpp on RN50 or 32MB */
- 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;
+ return 0;
+}
- fb_helper = kzalloc(sizeof(*fb_helper), GFP_KERNEL);
- if (!fb_helper)
- return -ENOMEM;
+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;
- drm_fb_helper_prepare(rdev->ddev, fb_helper, bpp_sel, &radeon_fbdev_fb_helper_funcs);
+ if (dev->fb_helper)
+ return drm_fb_helper_hotplug_event(dev->fb_helper);
- ret = drm_fb_helper_init(rdev->ddev, fb_helper);
+ ret = drm_fb_helper_init(dev, fb_helper);
if (ret)
- goto free;
+ goto err_drm_err;
- /* disable all the possible outputs/crtcs before entering KMS mode */
- drm_helper_disable_unused_functions(rdev->ddev);
+ if (!drm_drv_uses_atomic_modeset(dev))
+ drm_helper_disable_unused_functions(dev);
ret = drm_fb_helper_initial_config(fb_helper);
if (ret)
- goto fini;
+ goto err_drm_fb_helper_fini;
+
+ vga_switcheroo_client_fb_set(rdev->pdev, fb_helper->info);
return 0;
-fini:
+err_drm_fb_helper_fini:
drm_fb_helper_fini(fb_helper);
-free:
- drm_fb_helper_unprepare(fb_helper);
- kfree(fb_helper);
+err_drm_err:
+ drm_err(dev, "Failed to setup radeon fbdev emulation (ret=%d)\n", ret);
return ret;
}
-void radeon_fbdev_fini(struct radeon_device *rdev)
+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)
{
- if (!rdev->ddev->fb_helper)
+ 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->ddev, fb_helper, bpp_sel, &radeon_fbdev_fb_helper_funcs);
+
+ ret = drm_client_init(rdev->ddev, &fb_helper->client, "radeon-fbdev",
+ &radeon_fbdev_client_funcs);
+ if (ret) {
+ drm_err(rdev->ddev, "Failed to register client: %d\n", ret);
+ goto err_drm_client_init;
+ }
- drm_fb_helper_unregister_info(rdev->ddev->fb_helper);
- drm_fb_helper_unprepare(rdev->ddev->fb_helper);
- kfree(rdev->ddev->fb_helper);
- rdev->ddev->fb_helper = NULL;
+ ret = radeon_fbdev_client_hotplug(&fb_helper->client);
+ if (ret)
+ drm_dbg_kms(rdev->ddev, "client hotplug ret=%d\n", ret);
+
+ 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)
diff --git a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c
index 965161b8565b..e0214cf1b43b 100644
--- a/drivers/gpu/drm/radeon/radeon_kms.c
+++ b/drivers/gpu/drm/radeon/radeon_kms.c
@@ -32,7 +32,6 @@
#include <linux/uaccess.h>
#include <linux/vga_switcheroo.h>
-#include <drm/drm_fb_helper.h>
#include <drm/drm_file.h>
#include <drm/drm_ioctl.h>
#include <drm/radeon_drm.h>
@@ -622,23 +621,6 @@ int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
return 0;
}
-
-/*
- * Outdated mess for old drm with Xorg being in charge (void function now).
- */
-/**
- * radeon_driver_lastclose_kms - drm callback for last close
- *
- * @dev: drm dev pointer
- *
- * Switch vga_switcheroo state after last close (all asics).
- */
-void radeon_driver_lastclose_kms(struct drm_device *dev)
-{
- drm_fb_helper_lastclose(dev);
- vga_switcheroo_process_delayed_switch();
-}
-
/**
* radeon_driver_open_kms - drm callback for open
*
diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h
index 64cf263ae646..d81f61e5a95c 100644
--- a/drivers/gpu/drm/radeon/radeon_mode.h
+++ b/drivers/gpu/drm/radeon/radeon_mode.h
@@ -939,8 +939,7 @@ void dce4_program_fmt(struct drm_encoder *encoder);
void dce8_program_fmt(struct drm_encoder *encoder);
/* fbdev layer */
-int radeon_fbdev_init(struct radeon_device *rdev);
-void radeon_fbdev_fini(struct radeon_device *rdev);
+void radeon_fbdev_setup(struct radeon_device *rdev);
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);
--
2.39.2
next prev parent reply other threads:[~2023-03-16 9:38 UTC|newest]
Thread overview: 19+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-03-16 9:37 [PATCH 00/10] drm/radeon: Convert fbdev to DRM client Thomas Zimmermann
2023-03-16 9:37 ` [PATCH 01/10] drm/radeon: Move radeon_align_pitch() next to dumb-buffer helpers Thomas Zimmermann
2023-03-16 9:37 ` [PATCH 02/10] drm/radeon: Improve fbdev object-test helper Thomas Zimmermann
2023-03-16 9:37 ` [PATCH 03/10] drm/radeon: Remove struct radeon_fbdev Thomas Zimmermann
2023-03-16 9:37 ` [PATCH 04/10] drm/radeon: Remove test for !screen_base in fbdev probing Thomas Zimmermann
2023-03-16 9:37 ` [PATCH 05/10] drm/radeon: Move fbdev object helpers before struct fb_ops et al Thomas Zimmermann
2023-03-16 9:37 ` [PATCH 06/10] drm/radeon: Fix coding style in fbdev emulation Thomas Zimmermann
2023-03-16 9:37 ` [PATCH 07/10] drm/radeon: Move fbdev cleanup code into fb_destroy callback Thomas Zimmermann
2023-03-16 9:37 ` [PATCH 08/10] drm/radeon: Correctly clean up failed display probing Thomas Zimmermann
2023-03-16 9:37 ` Thomas Zimmermann [this message]
2023-03-16 9:37 ` [PATCH 10/10] drm/radeon: Only build fbdev if DRM_FBDEV_EMULATION is set Thomas Zimmermann
2023-03-17 8:53 ` [PATCH 00/10] drm/radeon: Convert fbdev to DRM client Christian König
2023-03-17 9:20 ` Thomas Zimmermann
2023-03-20 15:11 ` Christian König
2023-03-20 15:19 ` Thomas Zimmermann
2023-03-20 15:23 ` Alex Deucher
2023-03-21 9:33 ` Thomas Zimmermann
2023-03-24 21:44 ` Alex Deucher
2023-03-27 22:39 ` Alex Deucher
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20230316093738.28866-10-tzimmermann@suse.de \
--to=tzimmermann@suse.de \
--cc=Xinhui.Pan@amd.com \
--cc=airlied@gmail.com \
--cc=alexander.deucher@amd.com \
--cc=amd-gfx@lists.freedesktop.org \
--cc=christian.koenig@amd.com \
--cc=daniel@ffwll.ch \
--cc=dri-devel@lists.freedesktop.org \
--cc=javierm@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).