From: Thomas Zimmermann Date: Tue, 21 Apr 2026 07:29:08 +0000 (+0200) Subject: drm/tegra: fbdev: Use a DRM client buffer X-Git-Url: http://git.ipfire.org/gitweb/?a=commitdiff_plain;h=0daa4b50fc6a6e636f4f0b2b462860f36ef67a6a;p=thirdparty%2Flinux.git drm/tegra: fbdev: Use a DRM client buffer 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 Signed-off-by: Thierry Reding Link: https://patch.msgid.link/20260421073646.144712-5-tzimmermann@suse.de --- diff --git a/drivers/gpu/drm/tegra/fbdev.c b/drivers/gpu/drm/tegra/fbdev.c index bcf32cfcf8180..003e80cf7b9a1 100644 --- a/drivers/gpu/drm/tegra/fbdev.c +++ b/drivers/gpu/drm/tegra/fbdev.c @@ -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; }