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

    打开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);

    这是一个标准的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 };

    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。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值