Skip to content

Commit

Permalink
FROM AOSC: TTM fbdev emulation for Linux 6.13+
Browse files Browse the repository at this point in the history
Link: torvalds/linux@1000634
Link: NVIDIA#749
Signed-off-by: xtex <[email protected]>
Signed-off-by: Eric Naim <[email protected]>
  • Loading branch information
xtexChooser authored and 1Naim committed Jan 5, 2025
1 parent 7d37a4f commit 69be813
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 0 deletions.
72 changes: 72 additions & 0 deletions kernel-open/nvidia-drm/nvidia-drm-drv.c
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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(
Expand Down Expand Up @@ -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) */
Expand All @@ -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);
Expand Down
4 changes: 4 additions & 0 deletions kernel-open/nvidia-drm/nvidia-drm-linux.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 */

/*************************************************************************
Expand Down
5 changes: 5 additions & 0 deletions kernel-open/nvidia-drm/nvidia-drm-os-interface.h
Original file line number Diff line number Diff line change
Expand Up @@ -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. */
Expand Down

0 comments on commit 69be813

Please sign in to comment.