显示设备例如LCD,在Linux中用Framebuffer来表征,在/dev目录下显示设备一般表示成这样:/dev/fbX,应用程序通过访问这个设备来访问LCD,实际上应用程序通过操作显存来操作显示设备,显存由驱动程序设置。

Linux中使用fb_info结构体来表示Framebuffer设备,其内容如下:

struct fb_info {
atomic_t count;
int node;
int flags;
struct mutex lock; /* 互斥锁 */
struct mutex mm_lock; /* 互斥锁,用于 fb_mmap 和 smem_*域*/
struct fb_var_screeninfo var; /* 当前可变参数 */
struct fb_fix_screeninfo fix; /* 当前固定参数 */
struct fb_monspecs monspecs; /* 当前显示器特性 */
struct work_struct queue; /* 帧缓冲事件队列 */
struct fb_pixmap pixmap; /* 图像硬件映射 */
struct fb_pixmap sprite; /* 光标硬件映射 */
struct fb_cmap cmap; /* 当前调色板 */
struct list_head modelist; /* 当前模式列表 */
struct fb_videomode *mode; /* 当前视频模式 */
#ifdef CONFIG_FB_BACKLIGHT /* 如果 LCD 支持背光的话 */
/* assigned backlight device */
/* set before framebuffer registration,
remove after unregister */
struct backlight_device *bl_dev;  /* 背光设备 */
/* Backlight level curve */
struct mutex bl_curve_mutex;
u8 bl_curve[FB_BACKLIGHT_LEVELS];
#endif
......
struct fb_ops *fbops; /* 帧缓冲操作函数集 */
struct device *device; /* 父设备 */
struct device *dev; /* 当前 fb 设备 */
int class_flag; /* 私有 sysfs 标志 */
......
char __iomem *screen_base; /* 虚拟内存基地址(屏幕显存) */
unsigned long screen_size; /* 虚拟内存大小(屏幕显存大小) */
void *pseudo_palette; /* 伪 16 位调色板 */
......
};

其中最重要成员有:var,fix,fbops(LCD设备的操作集合),screen_base(显存基地址),screen_size(显存大小),pseudo_palette。

var结构体变量指的是显示设备的可变参数:

struct fb_var_screeninfo {
__u32 xres;/* visible resolution*//*定义屏幕一行有多少个像素点 */
__u32 yres;                       /*定义屏幕一列由多少个像素点 */__u32 bits_per_pixel;             /*每像素位数(多少BPP),单位为字节 */__u32 pixclock; /* pixel clock in ps (pico seconds) */ /*像素时钟(皮秒) *//* 行切换,从同步到绘图之间的延迟即HFPD(有效数据之后无效的像素的个数) ,对应于LCD数据手册的Hsyn的front-porch*/
__u32 left_margin; /* time from sync to picture */  /*行切换,从绘图到同步之间的延迟即HBPD(Hsyn脉冲下降沿之后的无效像素的个数) ,对应于LCD数据手册的Hsyn的back-porch*/
__u32 right_margin; /* time from picture to sync */  /*帧切换,从同步到绘图之间的延迟即VFPD(有效数据之后还要经历的无效行数(之后是下一帧数据)) ,对应于LCD数据手册的Vsyn的front-porch*/
__u32 upper_margin; /* time from sync to picture */ /*帧切换,从绘图到同步之间的延迟即VBPD(Vsyn脉冲下降沿之后还要经历的无效行数) ,对应于LCD数据手册的Vsyn的back-porch */
__u32 lower_margin;  /*水平同步的长度即HSPW(Hsyn信号的脉冲宽度),对应于LCD数据手册的Hsyn的pulse Width */
__u32 hsync_len;  /* length of horizontal sync*//*垂直同步的长度即VSPW(Vsyn信号的脉冲宽度),对应于LCD数据手册的Vsyn的pulse Width */
__u32 vsync_len;  /* length of vertical sync*/    __u32 sync;   /* see FB_SYNC_**/            /* 查看宏FB_SYNC_*/__u32 vmode;  /* see FB_VMODE_**/         /*  查看宏FB_VMODE_ */....
}

这些参数都是可以在设备树中进行修改的,具体的参数是多少要根据LCD的数据手册来进行修改,LCD的驱动程序会从设备树中读取这些参数。

fix结构体变量指的是不变参数,用户不可进行修改的参数,比如屏幕缓冲区的地址。

struct fb_fix_screeninfo { unsigned long smem_start; /* Start of frame buffer mem physical address) */__u32 smem_len; /*fb缓冲的长度,等于max_xres*max_yres*max_bpp/8  */unsigned long mmio_start; /* Start of Memory Mapped I/O*/  /* 内存映射的I/O的开始位置 */__u32 mmio_len; /* 内存映射的I/O的长度 */....
}

var变量是驱动程序从LCD设备的设备树节点中取得,fix变量中的显存基址和显存大小由驱动程序设置。

LCD设备在Linux内核中一般被组织成一个标准的platform设备,其驱动也是一个平台设备驱动,当总线将设备和驱动匹配起来以后,probe函数会被调用,平台设备驱动的重点就是probe函数。

LCD驱动的probe函数需要完成几件事:

一、申请一个fb_info结构体,设置好其成员变量。

二、初始化SoC的LCD控制器,其实就是配置控制器的各寄存器。

三、调用register_framebuffer函数向Linux内核注册初始化好的fb_info。

各SoC厂商在编写Framebuffer设备驱动的时候,往往会对Linux内核中的fb_info结构体进行二次封装,将SoC的LCD控制器的寄存器地址信息,LCD的时钟信息,fb_info封装在一起。NXP将封装后的结构体称之为:mxsfb_info

下面来看看LCD驱动中的一些重点内容:

static int mxsfb_probe(struct platform_device* pdev)
{struct resource *res;struct mxsfb_info *host;struct fb_info *fb_info;/*从设备树中提取LCD控制器寄存器地址信息*/res = platform_get_resource(pdev, IORESOURCE_MEM, 0);/*为二次封装的Framebuffer结构体分配内存*/host = devm_kzalloc(&pdev->dev, sizeof(struct mxsfb_info),GFP_KERNEL);/*给fb_info分配内存空间*/fb_info = framebuffer_alloc(sizeof(struct fb_info), &pdev->dev);/*物理地址映射成虚拟地址,此后可以通过base的值访问到LCD控制器的所有寄存器*/host->base = devm_ioremap_resource(&pdev->dev, res);/*通过LCD设备的设备树节点中的内容去填充fb_info结构体,主要就是设置上述的重点参数*/ret = mxsfb_init_fbinfo(host);/*配置LCD控制器*/mxsfb_set_par(fb_info);mxsfb_enable_controller(fb_info);/*向Linux内核注册*/ret = register_framebuffer(fb_info);.....}

在mxsfb_init_fbinfo函数对fb_info进行初始化的时候,其中LCD的操作函数集如下:

static struct fb_ops mxsfb_ops = {
.owner = THIS_MODULE,
.fb_check_var = mxsfb_check_var,
.fb_set_par = mxsfb_set_par,
.fb_setcolreg = mxsfb_setcolreg,
.fb_ioctl = mxsfb_ioctl,
.fb_blank = mxsfb_blank,
.fb_pan_display = mxsfb_pan_display,
.fb_mmap = mxsfb_mmap,
.fb_fillrect = cfb_fillrect,
.fb_copyarea = cfb_copyarea,
.fb_imageblit = cfb_imageblit,
};

另外,mxsfb_init_fbinfo 函数通过调用 mxsfb_init_fbinfo_dt 函数从设备树中获取到 fb_info需要的各参数信息然后对fb_info进行填充mxsfb_init_fbinfo函数会调用 mxsfb_map_videomem 函数申请 LCD 的帧缓冲内存(也就是显存)。这些函数都在mxsfb.c文件中。

注意:

        SoC厂商提供的Linux内核一般都默认开启了LCD驱动,没开启的自己配置内核来开启,也就是说LCD驱动一般都是写好的,我们要做的就是改设备树信息。

下面来看看LCD设备树信息,来明确要修改哪些信息。

首先是LCD的引脚信息:

一般自己设计的板子,LCD引脚信息会和原厂评估版一样,几乎不用修改。

屏幕参数信息,这个需要按照自己的LCD屏幕重点修改。

其中bits-per-pixel属性根据具体LCD来设置,RGB565那么一个像素16位,RGB888则为24位。

LCD像素时钟需要自己计算,下面贴出一个计算公式:

注意这里计算的是显示一帧的时间,60帧还需要乘以60。计算像素时钟需要的这些参数,也就是设备树LCD参数信息,查询设备手册可以获得。

参考资料:《正点原子Linux设备驱动开发手册》

Linux驱动之LCD驱动相关推荐

  1. 嵌入式Linux下彩色LCD驱动的设计与实现

    嵌入式Linux下彩色LCD驱动的设计与实现 转载 摘要:本文介绍了如何在嵌入在开发彩色LCD显示驱动的方法,并对Linux中的显示驱动程序结构和框架作一介绍. 长期以来,在常见的掌上电脑(PDA)等 ...

  2. Linux驱动之LCD驱动编写

    在Linux驱动之内核自带的S3C2440的LCD驱动分析这篇博客中已经分析了编写LCD驱动的步骤,接下来就按照这个步骤来字尝试字节编写LCD驱动.用的LCD屏幕为tft屏,每个像素点为16bit.对 ...

  3. android lcd驱动框架,LCD驱动及Framebuffer相关(转载)

    LCD驱动及Framebuffer相关 (2012-11-20 17:04) 标签:&nBSP; lcd驱动  framebuffer  io内存  分类: Android驱动模块相关 内容提 ...

  4. linux驱动之LCD驱动框架

    软件框架: lcd框架其实与i2c/spi及其他驱动框架大同小异,都是由一个底层的platform驱动和一个较上层的抽象驱动组成.前者一般由厂商编写,而后者是内核框架提供的. 核心层 \linux-i ...

  5. STM32MP157 Linux系统移植开发篇14:Linux内核RGB LCD驱动移植

    本文章为<STM32MP157 Linux系统移植开发篇>系列中的一篇,笔者使用的开发平台为华清远见FS-MP1A开发板(STM32MP157开发板).stm32mp157是ARM双核,2 ...

  6. Linux LCD 驱动实验

    目录 Linux 下LCD 驱动简析 1 Framebuffer 设备 LCD 驱动简析 硬件原理图分析 LCD 驱动程序编写 运行测试 LCD 屏幕基本测试 设置LCD 作为终端控制台 LCD 背光 ...

  7. linux驱动篇-LCD

    前言 在嵌入式行业,有很多从业者.我们工作的主旋律是拿开源代码,拿厂家代码,完成产品的功能,提升产品的性能,进而解决各种各样的问题.或者是维护一个模块或方向,一搞就是好几年. 时间长了,中年润发现我们 ...

  8. Linux下LCD驱动的详解

    看了不少人写的LCD驱动解释,看之前很懵逼,看之后还是很懵逼.都是放一大堆内核代码,我当时就想吐槽,能写就写,写不明白放一大堆代码是啥意思.后来,实在没办法,只能去看内核代码,结果,真香,原来别人放一 ...

  9. TQ2440平台上LCD驱动的移植

    参考: http://liu1227787871.blog.163.com/blog/static/205363197201242393031250/ http://blog.csdn.net/cum ...

最新文章

  1. 程序员眼中的英文单词是这样的
  2. 【译】Deep Learning with Knowledge Graphs
  3. PLS-00215:字符串长度限制在范围
  4. 会话Cookie及session的关系(Cookie Session)
  5. leaf 叶子(张量)
  6. Hadoop系列之DistributedCache用法
  7. MongoDB 覆盖索引查询
  8. PHP怎么计算百分比?PHP计算百分比的写法
  9. 小米手机测试代码电池测试代码
  10. IP/TCP/UDP报文解析(1)IP报文
  11. 正则表达式提取HTML中IMG标签的SRC地址
  12. 百度云个人服务器搭建
  13. 网站建设的基本步骤有哪些
  14. 双向链表的结点增删细节(p->next->prior = s是啥意思,p->next->prior究竟代表下一个结点的prior指针还是p本身)
  15. logiscope系列-使用说明书
  16. 数组和链表数据结构描述,各自的时间复杂度
  17. java e_java中E表示什么意思
  18. 高性能MySQL(一) 如何做到高扩展性
  19. codeforces1119B. Alyona and a Narrow Fridge 贪心
  20. 刷新率属于计算机的显示性能指标吗,显示器性能指标(菜鸟必看)

热门文章

  1. GDUT_排位赛题解报告_第5场_C. 积木
  2. 亡灵序曲-The Dawn
  3. 摄影后期技术:包围曝光
  4. 轩辕实验室丨欧盟EVITA项目预研 第一章(二)
  5. 面向对象的SQL语句——JPQL
  6. MFC实现三维图像绘制(3)直线光栅化
  7. 概率论与数理统计——偏度和峰度
  8. linux scp 【全新思路解决】出现Permission denied问题
  9. 9、中本聪的继任者——加文·安德烈森
  10. 联合双边滤波-Joint Bilateral Filter