轉自:https://blog.csdn.net/jingxia2008/article/details/48804859
drm 驅動是如何創建 fb device 的
drm 驅動是如何創建 fb device 的
什么是 drm
如何使用 drm 接口
libdrm
fb device
本文討論的問題是 drm 驅動是如何虛擬 drm crts 為 fb device
設備驅動創建 fbdev
完成 fb 設備的創建
流程圖
什么是 drm?
drm 是一個 Linux 內核的顯示系統驅動框架,區別於另外一個 DRM數字版權保護
drm 是一個管理 GPU 的顯示框架
在內核級別提供內存管理,中斷處理, DMA控
為應用程序提供統一的操作接口
如何使用 drm 接口
libdrm
fb device
libdrm
內核提供的 IOCTRL 太多,libdrm 用於簡化編程管理當前的顯示器,並修改當前的模式成為 KMS ( drm-kms - Kernel Mode-Setting)
借助 libdrm 的強大 API 接口,如果內核支持 PRIME API ,也可以使用 PRIME 接口實現更為靈活的內存操作。
fb device
drm 驅動可以模擬一個 fb device, 默認是 default CRTC, 更多關於 fb device ,可以參考 內核 framebuffer 文檔, fb device 是大多數 Linux 系統顯示的基礎。
The X Server, Linux 桌面系統的顯示服務
Android gralloc, 安卓系統顯示 HAL
本文討論的問題是 drm 驅動是如何虛擬 drm crts 為 fb device
文章基於內核版本 linux-3.18
VERSION = 3
PATCHLEVEL = 18
SUBLEVEL = 0
EXTRAVERSION = -linux4sam_5.0-alpha7
NAME = Diseased Newt
1
2
3
4
5
drm 的代碼位於:
drivers/gpu/drm/
1
1. 設備驅動創建 fbdev
drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c: dc->fbdev = drm_fbdev_cma_init(dev, 24,
drivers/gpu/drm/sti/sti_drm_drv.c: drm_fbdev_cma_init(dev, 32,
drivers/gpu/drm/tilcdc/tilcdc_drv.c: priv->fbdev = drm_fbdev_cma_init(dev, bpp,
drivers/gpu/drm/rcar-du/rcar_du_kms.c: fbdev = drm_fbdev_cma_init(dev, 32, dev->mode_config.num_crtc,
調用的是 drm_fbdev_cma_init
struct drm_fbdev_cma *drm_fbdev_cma_init(struct drm_device *dev,
unsigned int preferred_bpp, unsigned int num_crtc,
unsigned int max_conn_count)
{
struct drm_fbdev_cma *fbdev_cma;
struct drm_fb_helper *helper;
int ret;
fbdev_cma = kzalloc(sizeof(*fbdev_cma), GFP_KERNEL);
...
helper = &fbdev_cma->fb_helper;
drm_fb_helper_prepare(dev, helper, &drm_fb_cma_helper_funcs);
...
ret = drm_fb_helper_initial_config(helper, preferred_bpp);
if (ret < 0) {
dev_err(dev->dev, "Failed to set initial hw configuration.\n");
goto err_drm_fb_helper_fini;
}
return fbdev_cma;
其中最重要的數據結構是 drm_fb_helper_funcs
static const struct drm_fb_helper_funcs drm_fb_cma_helper_funcs = {
.fb_probe = drm_fbdev_cma_create,
1
2
};
2. 完成 fb 設備的創建:
static int drm_fbdev_cma_create(struct drm_fb_helper *helper,
struct drm_fb_helper_surface_size *sizes)
{
struct drm_fbdev_cma *fbdev_cma = to_fbdev_cma(helper);
struct drm_mode_fb_cmd2 mode_cmd = { 0 };
struct drm_device *dev = helper->dev;
struct drm_gem_cma_object *obj;
struct drm_framebuffer *fb;
unsigned int bytes_per_pixel;
unsigned long offset;
struct fb_info *fbi;
size_t size;
int ret;
DRM_DEBUG_KMS("surface width(%d), height(%d) and bpp(%d)\n",
sizes->surface_width, sizes->surface_height,
sizes->surface_bpp);
bytes_per_pixel = DIV_ROUND_UP(sizes->surface_bpp, 8);
mode_cmd.width = sizes->surface_width;
mode_cmd.height = sizes->surface_height;
mode_cmd.pitches[0] = sizes->surface_width * bytes_per_pixel;
mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp,
sizes->surface_depth);
size = mode_cmd.pitches[0] * mode_cmd.height;
obj = drm_gem_cma_create(dev, size);
if (IS_ERR(obj))
return -ENOMEM;
fbi = framebuffer_alloc(0, dev->dev);
if (!fbi) {
dev_err(dev->dev, "Failed to allocate framebuffer info.\n");
ret = -ENOMEM;
goto err_drm_gem_cma_free_object;
}
fbdev_cma->fb = drm_fb_cma_alloc(dev, &mode_cmd, &obj, 1);
if (IS_ERR(fbdev_cma->fb)) {
dev_err(dev->dev, "Failed to allocate DRM framebuffer.\n");
ret = PTR_ERR(fbdev_cma->fb);
goto err_framebuffer_release;
}
fb = &fbdev_cma->fb->fb;
helper->fb = fb;
helper->fbdev = fbi;
fbi->par = helper;
fbi->flags = FBINFO_FLAG_DEFAULT;
fbi->fbops = &drm_fbdev_cma_ops;
ret = fb_alloc_cmap(&fbi->cmap, 256, 0);
if (ret) {
dev_err(dev->dev, "Failed to allocate color map.\n");
goto err_drm_fb_cma_destroy;
}
drm_fb_helper_fill_fix(fbi, fb->pitches[0], fb->depth);
drm_fb_helper_fill_var(fbi, helper, fb->width, fb->height);
offset = fbi->var.xoffset * bytes_per_pixel;
offset += fbi->var.yoffset * fb->pitches[0];
dev->mode_config.fb_base = (resource_size_t)obj->paddr;
fbi->screen_base = obj->vaddr + offset;
fbi->fix.smem_start = (unsigned long)(obj->paddr + offset);
fbi->screen_size = size;
fbi->fix.smem_len = size;
return 0;
err_drm_fb_cma_destroy:
drm_framebuffer_unregister_private(fb);
drm_fb_cma_destroy(fb);
err_framebuffer_release:
framebuffer_release(fbi);
err_drm_gem_cma_free_object:
drm_gem_cma_free_object(&obj->base);
return ret;
}
1
流程圖
drm_fbdev_cma_init
drm_fb_helper_initial_config
drm_fb_helper_single_fb_probe
register_framebuffer
————————————————
版權聲明:本文為CSDN博主「無才頑石」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/jingxia2008/article/details/48804859