• Linux下LCD驱动的编写



    1. LCD和eLCDIF简介

        LCD即液晶显示器,显示原理如下:
    在这里插入图片描述

    1.1 LCD的几个要点

    1.1.2 分辨率

        LCD显示器是由一个一个像素点组成的,像素点类似一个灯,就是RGB灯,由红色、绿色和蓝色三种颜色组成。1080P就是像素数量是1920*1080个。

    1.1.3 像素格式

        如何控制RGB三种颜色的显示亮度?一般一个R、G、B这三部分分别使用8bit的数据,一个像素点就是24bit,一个像素点是3个字节,称为RGB888。,再加入8bit的Alpha通道的话一个像素就是4个字节,称为RGB8888。
    在这里插入图片描述

    1.1.4 时间参数

        可以把显示的过程想象成用一根笔在不同的像素点画上不同的颜色,按照从左至右、从上到下的顺序扫描每个像素点,并且在像素点上划出对应的颜色。

    1.1.5 显存

        一个像素需要4个字节,那么1024*600的分辨率就需要2.4MB的内存,但RGB LCD内部是没有内存的,所以需要在开发板上的DDR3中分出一段内存作为RGB LCD的显存。

    2. LCD驱动简析

    2.1 Framebuffer设备

        Linux下应用程序最终也是通过操作RGBLCD的显存来实现在LCD上显示字符、图片等信息。裸机中可以随意的分配内存,但Linux下内存的管理很严格。
        系统将所有跟显示有关的硬件和软件集合起来,虚拟出一个fb设备,编写好LCD驱动后会生成一个名为/dev/fbX的设备,应用程序通过访问这个设备就可以访问LCD。

    2.2 LCD驱动

        不同分辨率的LCD屏幕其eLCDIF控制器驱动代码都是一样的,只需要修改对应的屏幕参数即可,屏幕参数信息属于屏幕设备信息内容,要放到设备树中,打开对应的设备节点,进行修改。

    1 lcdif: lcdif@021c8000 { 
    2 compatible = "fsl,imx6ul-lcdif", "fsl,imx28-lcdif"; 
    3 reg = <0x021c8000 0x4000>;
    4 interrupts = <GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH>;
    5 clocks = <&clks IMX6UL_CLK_LCDIF_PIX>,
    6 <&clks IMX6UL_CLK_LCDIF_APB>,
    7 <&clks IMX6UL_CLK_DUMMY>;
    8 clock-names = "pix", "axi", "disp_axi"; 9 status = "disabled";
    10 };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

        打开imx6ull.dtsi文件,这是所有mx6ull芯片板子所共有的,并不是完整的节点信息。找到LCD的驱动文件。

    1362 static const struct of_device_id mxsfb_dt_ids[] = {
    1363 { .compatible = "fsl,imx23-lcdif", .data = &mxsfb_devtype[0], },
    1364 { .compatible = "fsl,imx28-lcdif", .data = &mxsfb_devtype[1], },
    1365 { /* sentinel */ }
    1366 };
    ......
    1625 static struct platform_driver mxsfb_driver = {
    1626 .probe = mxsfb_probe,
    1627 .remove = mxsfb_remove,
    1628 .shutdown = mxsfb_shutdown,
    1629 .id_table = mxsfb_devtype,
    1630 .driver = {
    1631 .name = DRIVER_NAME,
    1632 .of_match_table = mxsfb_dt_ids,
    1633 .pm = &mxsfb_pm_ops,
    1634 },
    1635 };
    1636
    1637 module_platform_driver(mxsfb_driver);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

        这是一个标准的platform驱动,驱动和设备匹配后mxsfb_probe函数就会执行。
        Linux内核将所有的Framebuffer抽象成一个叫做fb_info的结构体,包含了设备的完整属性和操作集合,fb_info结构体定义在include/linux/fb.h文件里。

    448 struct fb_info {
    449 atomic_t count;
    450 int node;
    451 int flags;
    452 struct mutex lock; /* 互斥锁 */
    453 struct mutex mm_lock; /* 互斥锁,用于 fb_mmap 和 smem_*域*/
    454 struct fb_var_screeninfo var; /* 当前可变参数 */
    455 struct fb_fix_screeninfo fix; /* 当前固定参数 */
    456 struct fb_monspecs monspecs; /* 当前显示器特性 */
    457 struct work_struct queue; /* 帧缓冲事件队列 */
    458 struct fb_pixmap pixmap; /* 图像硬件映射 */
    459 struct fb_pixmap sprite; /* 光标硬件映射 */
    460 struct fb_cmap cmap; /* 当前调色板 */
    461 struct list_head modelist; /* 当前模式列表 */
    462 struct fb_videomode *mode; /* 当前视频模式 */
    463
    464 #ifdef CONFIG_FB_BACKLIGHT /* 如果 LCD 支持背光的话 */
    465 /* assigned backlight device */
    466 /* set before framebuffer registration, 
    467 remove after unregister */
    468 struct backlight_device *bl_dev; /* 背光设备 */
    469
    470 /* Backlight level curve */
    471 struct mutex bl_curve_mutex; 
    472 u8 bl_curve[FB_BACKLIGHT_LEVELS];
    473 #endif
    ......
    479 struct fb_ops *fbops; /* 帧缓冲操作函数集 */ 
    480 struct device *device; /* 父设备 */
    481 struct device *dev; /* 当前 fb 设备 */
    482 int class_flag; /* 私有 sysfs 标志 */
    ......
    486 char __iomem *screen_base; /* 虚拟内存基地址(屏幕显存) */
    487 unsigned long screen_size; /* 虚拟内存大小(屏幕显存大小) */
    488 void *pseudo_palette; /* 伪 16 位调色板 */
    ......
    507 };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37

        fb_info结构体的成员变量很多,重点关注var\fix\fbops\screen_base\screen_size\pseudo_palette。
        mxsfb_probe函数的主要工作内容:

    1. 申请fb_info;
    2. 初始化fb_info结构体中的各个成员变量;
    3. 初始化eLCDIF控制器;
    4. 使用register_framebuffer函数向Linux内核注册初始化好的fb_info。
  • 相关阅读:
    RTL8380M/RTL8382M管理型交换机系统软件操作指南二:转发表
    Linux mmap原理
    openwrt 23.05.2 稳定版本 导入树莓派4B
    MySQL 本地安装
    王道3.1 顺序栈以及链式栈
    uniapp解决iOS切换语言——原生导航栏buttons文字不生效
    MySQL中的索引事务(1)索引----》数据库运行的原理知识+面试题~
    Windows 和 Linux 系统下,如何查看 Redis 的版本号?
    一款剧情特别优秀的ARPG 游戏《FC魔神英雄传》
    数据库三范式
  • 原文地址:https://blog.csdn.net/m0_56561130/article/details/125898581