zoukankan      html  css  js  c++  java
  • drm 驱动是如何创建 fb device 的【转】

    转自: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. ");
    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) ",
    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. ");
    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. ");
    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. ");
    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

  • 相关阅读:
    Problem C: 类的初体验(V)
    接口与继承
    类和对象
    java函数方法
    数组
    string类的一些函数方法
    java语法基础
    大道至简——做个懒人
    java编程 求和
    编程的精义
  • 原文地址:https://www.cnblogs.com/sky-heaven/p/12324022.html
Copyright © 2011-2022 走看看