drivers/gpu/drm/drm_fbdev_shmem.c

Source file repositories/reference/linux-study-clean/drivers/gpu/drm/drm_fbdev_shmem.c

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/drm_fbdev_shmem.c
Extension
.c
Size
5449 bytes
Lines
204
Domain
Driver Families
Bucket
drivers/gpu
Inferred role
Driver Families: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

// SPDX-License-Identifier: MIT

#include <linux/export.h>
#include <linux/fb.h>

#include <drm/drm_drv.h>
#include <drm/drm_fbdev_shmem.h>
#include <drm/drm_fb_helper.h>
#include <drm/drm_framebuffer.h>
#include <drm/drm_gem_framebuffer_helper.h>
#include <drm/drm_gem_shmem_helper.h>
#include <drm/drm_print.h>

/*
 * struct fb_ops
 */

static int drm_fbdev_shmem_fb_open(struct fb_info *info, int user)
{
	struct drm_fb_helper *fb_helper = info->par;

	/* No need to take a ref for fbcon because it unbinds on unregister */
	if (user && !try_module_get(fb_helper->dev->driver->fops->owner))
		return -ENODEV;

	return 0;
}

static int drm_fbdev_shmem_fb_release(struct fb_info *info, int user)
{
	struct drm_fb_helper *fb_helper = info->par;

	if (user)
		module_put(fb_helper->dev->driver->fops->owner);

	return 0;
}

FB_GEN_DEFAULT_DEFERRED_SYSMEM_OPS(drm_fbdev_shmem,
				   drm_fb_helper_damage_range,
				   drm_fb_helper_damage_area);

static int drm_fbdev_shmem_fb_mmap(struct fb_info *info, struct vm_area_struct *vma)
{
	struct drm_fb_helper *fb_helper = info->par;
	struct drm_framebuffer *fb = fb_helper->fb;
	struct drm_gem_object *obj = drm_gem_fb_get_obj(fb, 0);
	struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(obj);

	if (shmem->map_wc)
		vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);

	return fb_deferred_io_mmap(info, vma);
}

static void drm_fbdev_shmem_fb_destroy(struct fb_info *info)
{
	struct drm_fb_helper *fb_helper = info->par;

	if (!fb_helper->dev)
		return;

	fb_deferred_io_cleanup(info);
	drm_fb_helper_fini(fb_helper);

	drm_client_buffer_vunmap(fb_helper->buffer);
	drm_client_buffer_delete(fb_helper->buffer);
	drm_client_release(&fb_helper->client);
}

static const struct fb_ops drm_fbdev_shmem_fb_ops = {
	.owner = THIS_MODULE,
	.fb_open = drm_fbdev_shmem_fb_open,
	.fb_release = drm_fbdev_shmem_fb_release,
	__FB_DEFAULT_DEFERRED_OPS_RDWR(drm_fbdev_shmem),
	DRM_FB_HELPER_DEFAULT_OPS,
	__FB_DEFAULT_DEFERRED_OPS_DRAW(drm_fbdev_shmem),
	.fb_mmap = drm_fbdev_shmem_fb_mmap,
	.fb_destroy = drm_fbdev_shmem_fb_destroy,
};

static struct page *drm_fbdev_shmem_get_page(struct fb_info *info, unsigned long offset)
{
	struct drm_fb_helper *fb_helper = info->par;
	struct drm_framebuffer *fb = fb_helper->fb;
	struct drm_gem_object *obj = drm_gem_fb_get_obj(fb, 0);
	struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(obj);
	unsigned int i = offset >> PAGE_SHIFT;
	struct page *page;

Annotation

Implementation Notes