linux中LCD设备驱动framebuffer

linux中LCD设备驱动framebuffer

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/qq_30624591/article/details/88678254
         <!--一个博主专栏付费入口结束-->
        <link rel="stylesheet" href="https://csdnimg.cn/release/phoenix/template/css/ck_htmledit_views-d284373521.css">
                                    <div id="content_views" class="markdown_views prism-atom-one-dark">
                <!-- flowchart 箭头图标 勿删 -->
                <svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
                    <path stroke-linecap="round" d="M5,0 0,2.5 5,5z" id="raphael-marker-block" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></path>
                </svg>
                                        <p>帧缓冲设备在Linux中也可以看做是一个完整的子系统,大体由fbmem.c和 xxxfb.c(例如mtk平台的mtkfb.c)组成。向上给应用程序提供完善的设备文件操作接口(即对FrameBuffer设备进行read、write、ioctl等操作),接口在 Linux提供的fbmem.c文件中实现;向下提供了硬件操作的接口,只是这些接口Linux并没有提供实现,因为这要根据具体的LCD控制器硬件进行设置,所以这就是我们要做的事情了(即xxxfb.c部分的实现)。</p>

fbmem.c中实现了对framebuffer的共性的抽象,lcd驱动其实就是设置lcd控制器的工作方式,然后对显存进行读写,对显存的操作其实不管什么lcd,都是差不多的,所以这些相似的操作都抽取到了内核的fbmem.c里面,实现驱动的时候只需要填fb_info结构体,把lcd硬件相关的参数填入该结构体中,然后用register_framebuffer函数进行注册,该函数会自动生成设备节点,就是/dev/fb0,/dev/fb1 等等,对于显存的读写函数就用内核已经实现的默认的cfb_fillrect, cfb_copyarea, cfb_imageblit即可,其实不用自己去做实现,对于简单的lcd显示操作而言已经足够了

对于用户程序而言,它和其他的设备并没有什么区别,用户可以把fb看成是一块内存,既可以向内存中写数据,也可以读数据。fb的显示缓冲区位于内核空间,应用程序可以把此空间映射到自己的用户空间,再进行操作。

在应用程序中,操作/dev/fbn的一般步骤如下:
(1)打开/dev/fbn设备文件。
(2)用ioctl()操作取得当前显示屏幕的参数,如屏幕分辨率、每
个像素点的比特数。根据屏幕参数可计算屏幕缓冲区的大小。
(3)用mmap()函数,将屏幕缓冲区映射到用户空间。
(4)映射后就可以直接读/写屏幕缓冲区,进行绘图和图片显示了

LCD核心层fbmem.c给上层提供接口调用
file_operations fb_fops = {
.read = fb_read,
.write = fb_write,
.unlocked_ioctl = fb_ioctl,
.open = fb_open,
}
||---------------------------------------------||
|| 调用下面的具体framebuffer驱动
||---------------------------------------------||

LCD具体framebuffer驱动:(drivers/video/xxfb.c,如mtk的mtkfb.c)
1、实现fb_info结构体
(1)分配一个fb_info 结构
(2)设置里边的成员:LCD可变参数、LCD固定参数、显存基地址、操作函数。
(3)注册fb_info: 用函数register_framebuffer(),函数具体在fbmem.c中实现;

2、 硬件相关的初始化:
GPIO配置成LCD引脚、时序极性等。


代码分析:

1、 在 xxxfb.c(例如mtk平台的mtkfb.c)文件中注册了帧缓冲设备
r = register_framebuffer(fbi);

2、 register_framebuffer函数中registered_fb[i] = fb_info;初始化了一个全局的fb_info。
具体调用如下:
mtkfb_probe
==> r = register_framebuffer(fbi) //mtkfb.c文件中
==> int register_framebuffer(struct fb_info *fb_info) //fbmem.c
==> ret = do_register_framebuffer(fb_info); //fbmem.c
==> registered_fb[i] = fb_info; //fbmem.c

3、 Kernel初始化时对fbmem进行了初始化(fbmem.c文件中)

static int __init fbmem_init(void)
{
proc_create(“fb”, 0, NULL, &fb_proc_fops); //在proc文件夹下了创建了一个设备文件fb,用来提供系统中有关进程的信息;

if (register_chrdev(FB_MAJOR,“fb”,&fb_fops)) //注册字符设备,提供fb设备的操作方式
printk(“unable to get major %d for fb devs\n”, FB_MAJOR);

fb_class = class_create(THIS_MODULE, “graphics”); //创建类
if (IS_ERR(fb_class)) {
printk(KERN_WARNING “Unable to create fb class; errno = %ld\n”, PTR_ERR(fb_class));
fb_class = NULL;
}
return 0;
}

4、 fb_fops 成员函数如下:为用户提供了读写、控制、映射、打开和关闭等函数调用。(fbmem.c文件中)
static const struct file_operations fb_fops = {
.owner = THIS_MODULE,
.read = fb_read, //读
.write = fb_write,
.unlocked_ioctl = fb_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl = fb_compat_ioctl,
#endif
.mmap = fb_mmap,
.open = fb_open,
.release = fb_release,
#ifdef HAVE_ARCH_FB_UNMAPPED_AREA
.get_unmapped_area = get_fb_unmapped_area,
#endif
#ifdef CONFIG_FB_DEFERRED_IO
.fsync = fb_deferred_io_fsync,
#endif
.llseek = default_llseek,
};

5、 用户一开始需要打开fb设备,对应于 fb_open函数 (fbmem.c文件中)

static int
fb_open(struct inode *inode, struct file *file)
__acquires(&info->lock)
__releases(&info->lock)
{
int fbidx = iminor(inode); //取出设备次设备号
struct fb_info *info; //定义了一个fb_info结构
int res = 0;

info = get_fb_info(fbidx); //在次设备里面得到fb_info结构信息赋值给info
if (!info) {
request_module(“fb%d”, fbidx);
info = get_fb_info(fbidx);
if (!info)
return -ENODEV;
}
if (IS_ERR(info))
return PTR_ERR(info);

mutex_lock(&info->lock);
if (!try_module_get(info->fbops->owner)) {
res = -ENODEV;
goto out;
}
file->private_data = info;
if (info->fbops->fb_open) {
res = info->fbops->fb_open(info,1);
if (res)
module_put(info->fbops->owner);
}
#ifdef CONFIG_FB_DEFERRED_IO
if (info->fbdefio)
fb_deferred_io_open(info, inode, file);
#endif
out:
mutex_unlock(&info->lock);
if (res)
put_fb_info(info);
return res;
}

6、用ioctl()操作取得当前显示屏幕的参数,如屏幕分辨率、每个像素点的比特数。根据屏幕参数可计算屏幕缓冲区的大小。

7、 打开之后,用户就可以通过映射mmap,将显示缓冲区映射到用户空间,从而使得用户空间可以直接操作显示缓冲区,而省去一次用户空间到内核空间的内存复制过程。

8、 显示图像到LCD设备就相当于往帧缓冲区中写入数据,获取LCD设备上的图像就相当于拷贝帧缓冲区中的数据(读操作),具体可以看源代码(fbmem.c文件中)。

用户打开fb总体流程如下图所示(图片来自网上):
在这里插入图片描述

                                </div>
            <link href="https://csdnimg.cn/release/phoenix/mdeditor/markdown_views-b6c3c6d139.css" rel="stylesheet">
                </div>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值