ferreo
1666dcb0ea
Some checks failed
PikaOS Package Build Only (amd64-v3) / build (push) Failing after 36s
157 lines
5.5 KiB
Diff
157 lines
5.5 KiB
Diff
From 88b8ae7642ef21e685d51148e8f57c3dfa1323ac Mon Sep 17 00:00:00 2001
|
|
From: Bingwu Zhang <xtex@aosc.io>
|
|
Date: Sat, 7 Dec 2024 23:56:43 +0800
|
|
Subject: [PATCH 10/10] FROM AOSC: TTM fbdev emulation for Linux 6.13+
|
|
|
|
Link: https://github.com/torvalds/linux/commit/1000634477d8d178179b1ad45d92e925fabe3deb
|
|
Link: https://github.com/NVIDIA/open-gpu-kernel-modules/issues/749
|
|
Signed-off-by: xtex <xtexchooser@duck.com>
|
|
Signed-off-by: Eric Naim <dnaim@cachyos.org>
|
|
---
|
|
kernel-open/nvidia-drm/nvidia-drm-drv.c | 72 +++++++++++++++++++
|
|
kernel-open/nvidia-drm/nvidia-drm-linux.c | 4 ++
|
|
.../nvidia-drm/nvidia-drm-os-interface.h | 5 ++
|
|
3 files changed, 81 insertions(+)
|
|
|
|
diff --git a/kernel-open/nvidia-drm/nvidia-drm-drv.c b/kernel-open/nvidia-drm/nvidia-drm-drv.c
|
|
index 2e4f6404..ab85152f 100644
|
|
--- a/kernel-open/nvidia-drm/nvidia-drm-drv.c
|
|
+++ b/kernel-open/nvidia-drm/nvidia-drm-drv.c
|
|
@@ -1951,7 +1951,60 @@ void nv_drm_update_drm_driver_features(void)
|
|
#endif /* NV_DRM_ATOMIC_MODESET_AVAILABLE */
|
|
}
|
|
|
|
+#if !defined(NV_DRM_FBDEV_TTM_AVAILABLE) && \
|
|
+ !defined(NV_DRM_FBDEV_GENERIC_AVAILABLE)
|
|
+// AOSC OS: Workaround for Linux 6.13+
|
|
|
|
+static const struct drm_fb_helper_funcs nv_drm_fbdev_helper_funcs = {
|
|
+ .fb_probe = drm_fbdev_ttm_driver_fbdev_probe,
|
|
+};
|
|
+
|
|
+static void nv_drm_fbdev_client_unregister(struct drm_client_dev *client)
|
|
+{
|
|
+ struct drm_fb_helper *fb_helper = drm_fb_helper_from_client(client);
|
|
+ if (fb_helper->info) {
|
|
+ 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 nv_drm_fbdev_client_restore(struct drm_client_dev *client)
|
|
+{
|
|
+ drm_fb_helper_lastclose(client->dev);
|
|
+ return 0;
|
|
+}
|
|
+static int nv_drm_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;
|
|
+ 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;
|
|
+ return 0;
|
|
+err_drm_fb_helper_fini:
|
|
+ drm_fb_helper_fini(fb_helper);
|
|
+err_drm_err:
|
|
+ drm_err(dev, "AOSC OS: NV-DRM: fbdev: Failed to setup emulation (ret=%d)\n", ret);
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+static const struct drm_client_funcs nv_drm_fbdev_client_funcs = {
|
|
+ .owner = THIS_MODULE,
|
|
+ .unregister = nv_drm_fbdev_client_unregister,
|
|
+ .restore = nv_drm_fbdev_client_restore,
|
|
+ .hotplug = nv_drm_fbdev_client_hotplug,
|
|
+};
|
|
+#endif
|
|
|
|
/*
|
|
* Helper function for allocate/register DRM device for given NVIDIA GPU ID.
|
|
@@ -1961,6 +2014,7 @@ void nv_drm_register_drm_device(const nv_gpu_info_t *gpu_info)
|
|
struct nv_drm_device *nv_dev = NULL;
|
|
struct drm_device *dev = NULL;
|
|
struct device *device = gpu_info->os_device_ptr;
|
|
+ struct drm_fb_helper *fb_helper = NULL;
|
|
bool bus_is_pci;
|
|
|
|
DRM_DEBUG(
|
|
@@ -2039,6 +2093,20 @@ void nv_drm_register_drm_device(const nv_gpu_info_t *gpu_info)
|
|
drm_fbdev_ttm_setup(dev, 32);
|
|
#elif defined(NV_DRM_FBDEV_GENERIC_AVAILABLE)
|
|
drm_fbdev_generic_setup(dev, 32);
|
|
+ #else
|
|
+ // AOSC OS: Workaround for Linux 6.13+
|
|
+ int drm_client_ret;
|
|
+ fb_helper = kzalloc(sizeof(*fb_helper), GFP_KERNEL);
|
|
+ if (!fb_helper)
|
|
+ return;
|
|
+ drm_fb_helper_prepare(dev, fb_helper, 32, &nv_drm_fbdev_helper_funcs);
|
|
+ drm_client_ret = drm_client_init(dev, &fb_helper->client, "fbdev",
|
|
+ &nv_drm_fbdev_client_funcs);
|
|
+ if (drm_client_ret) {
|
|
+ drm_err(dev, "AOSC OS: NV-DRM: Failed to register DRM client: %d\n", drm_client_ret);
|
|
+ goto failed_drm_client_init;
|
|
+ }
|
|
+ drm_client_register(&fb_helper->client);
|
|
#endif
|
|
}
|
|
#endif /* defined(NV_DRM_FBDEV_AVAILABLE) */
|
|
@@ -2050,6 +2118,10 @@ void nv_drm_register_drm_device(const nv_gpu_info_t *gpu_info)
|
|
|
|
return; /* Success */
|
|
|
|
+failed_drm_client_init:
|
|
+ drm_fb_helper_unprepare(fb_helper);
|
|
+ kfree(fb_helper);
|
|
+
|
|
failed_drm_register:
|
|
|
|
nv_drm_dev_free(dev);
|
|
diff --git a/kernel-open/nvidia-drm/nvidia-drm-linux.c b/kernel-open/nvidia-drm/nvidia-drm-linux.c
|
|
index 83d40983..ac4fe967 100644
|
|
--- a/kernel-open/nvidia-drm/nvidia-drm-linux.c
|
|
+++ b/kernel-open/nvidia-drm/nvidia-drm-linux.c
|
|
@@ -39,8 +39,12 @@ MODULE_PARM_DESC(
|
|
fbdev,
|
|
"Create a framebuffer device (1 = enable (default), 0 = disable) (EXPERIMENTAL)");
|
|
module_param_named(fbdev, nv_drm_fbdev_module_param, bool, 0400);
|
|
+#else
|
|
+#error "nvidia-drm fbdev should always be available."
|
|
#endif
|
|
|
|
+#else
|
|
+#error "nvidia-drm is not available"
|
|
#endif /* NV_DRM_AVAILABLE */
|
|
|
|
/*************************************************************************
|
|
diff --git a/kernel-open/nvidia-drm/nvidia-drm-os-interface.h b/kernel-open/nvidia-drm/nvidia-drm-os-interface.h
|
|
index 71ca5f22..8195af32 100644
|
|
--- a/kernel-open/nvidia-drm/nvidia-drm-os-interface.h
|
|
+++ b/kernel-open/nvidia-drm/nvidia-drm-os-interface.h
|
|
@@ -78,6 +78,11 @@ typedef struct nv_timer nv_drm_timer;
|
|
#define NV_DRM_FBDEV_TTM_AVAILABLE
|
|
#endif
|
|
|
|
+// AOSC OS: Always enable DRM fbdev
|
|
+// FIXME: Add config test for drm helper functions.
|
|
+// The implementation uses drm_client_register, which is added in v5.2-rc1.
|
|
+#define NV_DRM_FBDEV_AVAILABLE
|
|
+
|
|
struct page;
|
|
|
|
/* Set to true when the atomic modeset feature is enabled. */
|
|
--
|
|
2.47.1
|
|
|