看了不少人写的LCD驱动解释,看之前很懵逼,看之后还是很懵逼。都是放一大堆内核代码,我当时就想吐槽,能写就写,写不明白放一大堆代码是啥意思。后来,实在没办法,只能去看内核代码,结果,真香,原来别人放一堆代码是有用的。就很邪门,翻翻内核源码,不用细究,看看大概的框架,突然就悟了,所以如果大家看完我这篇博客后还是不太明白,去翻翻源码吧!

前言

首先,LCD驱动,linux中本身就包含了,并不需要我们自己去编写,我们要做的只是根据自己的LCD改改参数即可。驱动具体是如何现实的呢?我认为主要分为两个部分,一个部分在“fbmem.c这个文件中,我们想想,如何用户需要自己去修改一些底层的配置,难道让他们去修改驱动么?显然是不能的,所以是不是得提供应用层的接口函数?这不还得是走一遍老套路,进行字符设备的注册。另一个部分就是真正的LCD驱动了 ,通过字符设备提供的接口函数可以修改真正的LCD驱动(NXP 官方编写的 Linux 下的 LCD 驱动mxsfb.c(当然这是不一定的,你也可以自己在写个驱动))”

什么是Framebuffer设备

Framebuffer 是用一个视频输出设备从包含完整的帧数据的一个内存缓冲区中来驱动一个视频显
示设备。也就是说 Framebuffer 是一块内存保存着一帧的图像,向这块内存写入数据就相当于向
屏幕中写入数据,如果使用 32 位的数据来表示一个像素点(使用 BBP 表示),假设屏幕的显示
频分辨率为 1920x1080,那么 Framebuffer 所需要的内存为 1920x1080x32/8=8,294,400 字节约等于
7.9M。
简单来说 Framebuffer 把屏幕上的每个点映射成一段线性内存空间,程序可以简单的改变这段内
存的值来改变屏幕上某一点的颜色。

Framebuffer 子系统为用户空间操作显示设备提供了统一的接口,屏蔽了底层硬件之间的差异,用
户只需要操作一块内存缓冲区即可把需要的图像显示到 LCD 设备上

第一步注册字符设备类 ,创建设备类

在内核启动时,LCD驱动的第一步是,调用fbmem_init()

fbmem_init(void)
{proc_create("fb", 0, NULL, &fb_proc_fops);if (register_chrdev(FB_MAJOR,"fb",&fb_fops))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;
}#ifdef MODULE
module_init(fbmem_init);

好好瞅瞅,是不是很眼熟,这不就是我们平时写字符设备的入口函数么 ,看到这个,fb_fops没,显然它是显示设备提供通用的文件操作接口,代码如下:

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,
};

fd_read 和 fd_write的代码就不放了,几乎字符设备驱动必备函数,感兴趣的可以自己去看看,我暂时没时间深究,不过这两个函数,一般都是进行应用层和内核层数据的交互嘛。重点来看看 fb_ioctl()函数:

static long fb_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{struct fb_info *info = file_fb_info(file);if (!info)return -ENODEV;return do_fb_ioctl(info, cmd, arg);
}

来来来,家人们看这个 fb_info ,这个结构体就是真正LCD驱动的核心了,这个提醒一下,大家有点印象,fb_ioctl() 函数从全局数组 registered_fb 获取到 fb_info 结构体后,调用的是 do_fb_ioctl() 函数通过传入的 cmd 命令参数设置或者获取 fb_info 结构体的相关信息,do_fb_ioctl这个函数大家自己去翻翻。
所以到这里为止,都是方便在应用层来修改底层的一下参数,接下来就是LCD驱动的编写了

LCD硬件设备层分析

在我们编写具体的 LCD 驱动程序时,我们只需要关系硬件设备层,在硬件设备层根据具体的单
板和 LCD 屏幕参数编写对应驱动程序。每一个 LCD 驱动对应一个 fb_info 结构体(自己去fb.c 这个文件找),编写驱动程序时需要把它注册到核心层的 registered_fb 数组,以便内核管理。

我们简单看一下 NXP 官方编写的 Linux 下的 LCD 驱动,打开 imx6ull.dtsi,然后找到 lcdif

节点内容,如下所示:

 lcdif: lcdif@021c8000 {compatible = "fsl,imx6ul-lcdif", "fsl,imx28-lcdif";reg = <0x021c8000 0x4000>;interrupts = <GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH>;clocks = <&clks IMX6UL_CLK_LCDIF_PIX>,<&clks IMX6UL_CLK_LCDIF_APB>,<&clks IMX6UL_CLK_DUMMY>;clock-names = "pix", "axi", "disp_axi";status = "disabled";};
 static const struct of_device_id mxsfb_dt_ids[] = {{ .compatible = "fsl,imx23-lcdif", .data = &mxsfb_devtype[0], },{ .compatible = "fsl,imx28-lcdif", .data = &mxsfb_devtype[1], },{ /* sentinel */ }};static struct platform_driver mxsfb_driver = {.probe = mxsfb_probe,.remove = mxsfb_remove,.shutdown = mxsfb_shutdown,.id_table = mxsfb_devtype,.driver = {.name = DRIVER_NAME,.of_match_table = mxsfb_dt_ids,.pm = &mxsfb_pm_ops,},
};

platform 通过 compatible 进行 ,drive和device的匹配 。这是一个标准的 platform 驱动,当驱动和设备匹配以后mxsfb_probe 函数就会执行,我们来看看mxsfb_probe函数

static int mxsfb_probe(struct platform_device *pdev)
{const struct of_device_id *of_id =of_match_device(mxsfb_dt_ids, &pdev->dev);struct resource *res;struct mxsfb_info *host;struct fb_info *fb_info;struct pinctrl *pinctrl;int irq = platform_get_irq(pdev, 0);int gpio, ret;if (of_id)pdev->id_entry = of_id->data;gpio = of_get_named_gpio(pdev->dev.of_node, "enable-gpio", 0);if (gpio == -EPROBE_DEFER)return -EPROBE_DEFER;if (gpio_is_valid(gpio)) {ret = devm_gpio_request_one(&pdev->dev, gpio, GPIOF_OUT_INIT_LOW, "lcd_pwr_en");if (ret) {dev_err(&pdev->dev, "faild to request gpio %d, ret = %d\n", gpio, ret);return ret;}}res = platform_get_resource(pdev, IORESOURCE_MEM, 0);if (!res) {dev_err(&pdev->dev, "Cannot get memory IO resource\n");return -ENODEV;}host = devm_kzalloc(&pdev->dev, sizeof(struct mxsfb_info), GFP_KERNEL);if (!host) {dev_err(&pdev->dev, "Failed to allocate IO resource\n");return -ENOMEM;}
.............................
...........................fb_info = framebuffer_alloc(sizeof(struct fb_info), &pdev->dev);if (!fb_info) {dev_err(&pdev->dev, "Failed to allocate fbdev\n");devm_kfree(&pdev->dev, host);return -ENOMEM;}host->fb_info = fb_info;fb_info->par = host;dev_info(&pdev->dev, "initialized\n");return 0;}

mxsfb_probe 函数的主要工作内容为:
①、申请 fb_info。(虽迟但到)
②、初始化 fb_info 结构体中的各个成员变量。
③、初始化 eLCDIF 控制器。
使用 register_framebuffer 函数向 Linux 内核注册初始化好的 fb_info。register_framebuffer
函数原型如下:

int register_framebuffer(struct fb_info *fb_info)

LCD驱动的流程就算走完了,希望对你们有帮助!

Linux下LCD驱动的详解相关推荐

  1. linux下测试ftp传输,linux下ftp命令使用详解---linux文件传输ftp命令

    linux下ftp命令使用详解---linux文件传输ftp命令 上一篇 / 下一篇  2010-12-18 09:15:35 / 个人分类:Linux ftp(file transfer proto ...

  2. linux下sort命令使用详解---linux将文本文件内容加以排序命令

    转载自:http://www.cnblogs.com/hitwtx/archive/2011/12/03/2274592.html linux下sort命令使用详解---linux将文本文件内容加以排 ...

  3. Linux下的awk用法详解

    Linux下的awk用法详解 一.awk介绍 二.awk的语法 三.awk常见用法 四.awk其他用法 五.awk语言特性 一.awk介绍 1.AWK 是一种处理文本文件的语言,是一个强大的文本分析工 ...

  4. linux输入一个用户看是否在工作,linux下的用户管理详解

    linux下的用户管理详解 useradd 命令详解 添加用户 想要对linux下面的帐号了解的话首先必须要了解的4个配置文件[root@localhost /]# cat /etc/passwd 首 ...

  5. Linux下find命令用法详解

    Linux下find命令用法详解 学神VIP烟火 学神IT教育:XueGod-IT 最负责任的线上直播教育平台 本文作者为VIP学员 烟火 第一部分:根据文件名查找 1.在当前目录查找名称为test的 ...

  6. linux中which命令详解,Linux下which命令使用详解(转)

    我们经常在linux要查找某个文件,但不知道放在哪里了,可以使用下面的一些命令来搜索: which 查看可执行文件的位置. whereis 查看文件的位置. locate 配合数据库查看文件位置. f ...

  7. rm命令linux00,linux下rm命令使用详解 | Soo Smart!

    linux下rm命令使用详解---linux删除文件或目录命令 用户可以用rm命令删除不需要的文件.该命令的功能为删除一个目录中的一个或多个文件或目录,它也可以将某个目录及其下的所有文件及子目录均删除 ...

  8. linux下top命令参数详解

    linux下top命令参数详解 top命令是Linux下常用的性能分析工具,能够实时显示系统中各个进程的资源占用状况,类似于Windows的任务管理器.下面详细介绍它的使用方法. 内存信息.内容如下: ...

  9. Linux下文件查找使用详解-羽飞作品

    Linux下文件查找使用详解 (1/3) http://www.boobooke.com/v/bbk1579 Linux下文件查找使用详解 (2/3) http://www.boobooke.com/ ...

最新文章

  1. c语言const与*位置关系,C语言程序的存储区域与const关键字的使用方法
  2. 损失函数/成本函数/目标函数的区别
  3. 我在 SUN TECH DAY
  4. 求数组最小值及其下标
  5. 2013年上半年工作总结,哇哈哈哈,给自己看的。
  6. python导入包相当于什么_Python中使用语句导入模块或包的机制研究
  7. keil和proteus的联调设置
  8. 第四十三篇 面向对象进阶2
  9. (1)深度学习_梯度下降与优化
  10. 响应式设计就是这个时代最值得学习、时间的趋势
  11. 国内完全免费的电子图书下载网址
  12. [Python从零到壹] 七.网络爬虫之Requests爬取豆瓣电影TOP250及CSV存储
  13. OpenCV/kornia/Pillow/Halcon/NI Vision/MIL/*计算机视觉资料汇总
  14. 为什么hashmap的容量必须是2的n次幂
  15. 一篇文章带你了解和学会VCN安卓快速开发
  16. CSUOJ-1986: 玄学
  17. 国外优秀的域名注册商介绍
  18. Druid(Druid.io)简单使用
  19. 使用rufus 制作 windows / CentOS /ubuntu 系统盘 [ U 盘 ]
  20. HttpClient的释放资源到底在释放什么?如何正确的释放资源?

热门文章

  1. VSCode官网下载慢问题解决
  2. 【ldap】ldap系列-java对ActiveDirectory的增删改查,包含加密密码字段:unicodePwd
  3. 16.实时绘制加速技术
  4. JSON学习及cJSON使用
  5. Centos 7搭建、配置ftp(匿名用户)
  6. 我只是一个普通的程序员08【下】
  7. Medical X-rays Dataset汇总(长期更新)
  8. 二本学历做Java程序员还有出路吗?本科生和研究生程序员差别大吗
  9. 程序员如何拓展自己的社交圈(超实用)
  10. android app测试方案,Android App响应时间测试方案优化