]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
drm/tegra: fbdev: Use a DRM client buffer
authorThomas Zimmermann <tzimmermann@suse.de>
Tue, 21 Apr 2026 07:29:08 +0000 (09:29 +0200)
committerThierry Reding <treding@nvidia.com>
Thu, 28 May 2026 15:19:29 +0000 (17:19 +0200)
Replace the internal DRM framebuffer with a DRM client buffer. The
client buffer allocates the DRM framebuffer on a file and also uses
GEM object handles via the regular ADDFB2 interfaces.

Using client-buffer interfaces unifies framebuffer allocation for
DRM clients in user space and tegra's internal fbdev emulation. It
also simplifies the clean-up side of the fbdev emulation.

Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
Signed-off-by: Thierry Reding <treding@nvidia.com>
Link: https://patch.msgid.link/20260421073646.144712-5-tzimmermann@suse.de
drivers/gpu/drm/tegra/fbdev.c

index bcf32cfcf81802374079f8a5fdd63e5547c5be8a..003e80cf7b9a1b5b54106e36f10ba4000544ca53 100644 (file)
@@ -40,8 +40,7 @@ static int tegra_fb_mmap(struct fb_info *info, struct vm_area_struct *vma)
 static void tegra_fbdev_fb_destroy(struct fb_info *info)
 {
        struct drm_fb_helper *helper = info->par;
-       struct drm_framebuffer *fb = helper->fb;
-       struct tegra_bo *bo = tegra_fb_get_plane(fb, 0);
+       struct tegra_bo *bo = tegra_fb_get_plane(helper->fb, 0);
 
        drm_fb_helper_fini(helper);
 
@@ -50,8 +49,8 @@ static void tegra_fbdev_fb_destroy(struct fb_info *info)
                vunmap(bo->vaddr);
                bo->vaddr = NULL;
        }
-       drm_framebuffer_remove(fb);
 
+       drm_client_buffer_delete(helper->buffer);
        drm_client_release(&helper->client);
 }
 
@@ -70,15 +69,18 @@ static const struct drm_fb_helper_funcs tegra_fbdev_helper_funcs = {
 int tegra_fbdev_driver_fbdev_probe(struct drm_fb_helper *helper,
                                   struct drm_fb_helper_surface_size *sizes)
 {
-       struct tegra_drm *tegra = helper->dev->dev_private;
-       struct drm_device *drm = helper->dev;
-       struct drm_mode_fb_cmd2 cmd = { 0 };
+       struct drm_client_dev *client = &helper->client;
+       struct drm_device *drm = client->dev;
+       struct drm_file *file = client->file;
+       struct tegra_drm *tegra = drm->dev_private;
        struct fb_info *info = helper->info;
        u32 fourcc, pitch;
        u64 size;
        const struct drm_format_info *format;
-       struct drm_framebuffer *fb;
        struct tegra_bo *bo;
+       struct drm_gem_object *gem;
+       u32 handle;
+       struct drm_client_buffer *buffer;
        int err;
 
        fourcc = drm_mode_legacy_fb_format(sizes->surface_bpp, sizes->surface_depth);
@@ -90,23 +92,22 @@ int tegra_fbdev_driver_fbdev_probe(struct drm_fb_helper *helper,
        bo = tegra_bo_create(drm, size, 0);
        if (IS_ERR(bo))
                return PTR_ERR(bo);
+       gem = &bo->gem;
 
-       cmd.pixel_format = fourcc;
-       cmd.width = sizes->surface_width;
-       cmd.height = sizes->surface_height;
-       cmd.pitches[0] = pitch;
-
-       fb = tegra_fb_alloc(drm, format, &cmd, &bo, 1);
-       if (IS_ERR(fb)) {
-               err = PTR_ERR(fb);
-               dev_err(drm->dev, "failed to allocate DRM framebuffer: %d\n",
-                       err);
-               drm_gem_object_put(&bo->gem);
-               return PTR_ERR(fb);
+       err = drm_gem_handle_create(file, gem, &handle);
+       if (err)
+               goto err_drm_gem_object_put;
+
+       buffer = drm_client_buffer_create(client, sizes->surface_width, sizes->surface_height,
+                                         fourcc, handle, pitch);
+       if (IS_ERR(buffer)) {
+               err = PTR_ERR(buffer);
+               goto err_drm_gem_handle_delete;
        }
 
        helper->funcs = &tegra_fbdev_helper_funcs;
-       helper->fb = fb;
+       helper->buffer = buffer;
+       helper->fb = buffer->fb;
 
        info->fbops = &tegra_fb_ops;
 
@@ -118,19 +119,29 @@ int tegra_fbdev_driver_fbdev_probe(struct drm_fb_helper *helper,
                if (!bo->vaddr) {
                        dev_err(drm->dev, "failed to vmap() framebuffer\n");
                        err = -ENOMEM;
-                       goto destroy;
+                       goto err_drm_client_buffer_delete;
                }
        }
 
        info->flags |= FBINFO_VIRTFB;
        info->screen_buffer = bo->vaddr;
-       info->screen_size = bo->gem.size;
+       info->screen_size = gem->size;
        info->fix.smem_start = (unsigned long)(bo->iova);
-       info->fix.smem_len = bo->gem.size;
+       info->fix.smem_len = gem->size;
+
+       /* The handle is only needed for creating the framebuffer. */
+       drm_gem_handle_delete(file, handle);
+
+       /* The framebuffer still holds a reference on the GEM object. */
+       drm_gem_object_put(gem);
 
        return 0;
 
-destroy:
-       drm_framebuffer_remove(fb);
+err_drm_client_buffer_delete:
+       drm_client_buffer_delete(buffer);
+err_drm_gem_handle_delete:
+       drm_gem_handle_delete(file, handle);
+err_drm_gem_object_put:
+       drm_gem_object_put(gem);
        return err;
 }