Linux LCD驱动

摘自:http://blog.csdn.net/xinyuwuxian/article/details/10083051

LCD 硬件原理 

利用液晶制成的显示器称为 LCD,依据驱动方式可分为静态驱动、简单矩阵驱动以及主动矩阵驱动 3 种。其中,简单矩阵型又可再细分扭转向列型(TN)和超扭
转式向列型(STN)两种,而主动矩阵型则以薄膜式晶体管型(TFT)为主流。表18.1 列出了 TN、STN 和 TFT 显示器的区别。


TN 型液晶显示技术是 LCD 中最基本的,其他种类的 LCD 都以 TN 型为基础改进而得。TN 型 LCD 显示质量很差,色彩单一,对比度低,反映速度很慢,故主要用于简单的数字符与文字的显示,如电子表及电子计算器等。 

STN LCD 的显示原理与 TN 类似,区别在于 TN 型的液晶分子将入射光旋转 90°,而 STN 则可将入射光旋转 180°~270°。STN 改善了 TN 视角狭小的缺点,并提高了对比度,显示品质较 TN 高。 STN 搭配彩色滤光片,将单色显示矩阵的任一像素分成 3 个子像素,分别透过彩色滤光片显示红、绿、蓝三原色,再经由三原色按比例调和,显示出逼近全彩模式的色彩。STN 显示的画面色彩对比度仍较小,反应速度也较慢,可以作为一般的操作显示接口。 随后出现的 DSTN 通过双扫描方式来显示,显示效果相对 STN 而言有了较大幅度的提高。DSTN 的反应速度可达到 100ms,但是在电场反复改变电压的过程中,每一像素的恢复过程较慢。因此,当在屏幕画面快速变化时,会产生“拖尾”现象。 

TN 与 STN 型液晶显示器都是使用场电压驱动方式,如果显示尺寸加大,中心部位对电极变化的反应时间就会拉长,显示器的速度跟不上。为了解决这个问题,主动式矩阵驱动被提出,主动式 TFT 型的液晶显示器的结构较为复杂,它包括背光管、导光板、偏光板、滤光板、玻璃基板、配向膜、液晶材料和薄膜式晶体管等。 

在 TFT 型 LCD 中,晶体管矩阵依显示信号开启或关闭液晶分子的电压,使液晶分子轴转向而成“亮”或“暗”的对比,避免了显示器对电场效应的依靠。因此,TFT LCD 的显示质量较 TN/STN 更佳,画面显示对比度可达 150:1以上,反应速度逼近 30ms甚至更快,适用于 PDA、笔记本电脑、数码相机、MP4 等。 

一块 LCD 屏显示图像不但需要 LCD 驱动器,还需要有相应的 LCD 控制器。通常 LCD 驱动器会以 COF/COG 的形式与 LCD 玻璃基板制作在一起,而 LCD 控制器则由外部电路来实现。许多 MCU 内部直接集成了 LCD 控制器,通过 LCD控制器可以方便地控制 STN 和 TFT 屏。 

TFT 屏是目前嵌入式系统应用的主流,图 18.1 给出了 TFT 屏的典型时序。时序图中的 VCLK、HSYNC 和 VSYNC 分别为像素时钟信号(用于锁存图像数据的像素
时钟)、行同步信号和帧同步信号,VDEN 为数据有效标志信号,VD 为图像的数据信号。

作为帧同步信号的 VSYNC,每发出一个脉冲,都意味着新的一屏图像数据开始发送。而作为行同步信号的 HSYNC,每发出一个脉冲都表明新的一行图像资料开始发送。在帧同步以及行同步的头尾都必须留有回扫时间。这样的时序安排起源于 CRT显示器电子枪偏转所需要的时间,但后来成为实际上的工业标准,因此 TFT 屏也包含了回扫时间。 

下图给出了 LCD 控制器中应该设置的 TFT 屏的参数,其中的上边界和下边界即为帧切换的回扫时间,左边界和右边界即为行切换的回扫时间,水平同步和垂直同步分别是行和帧同步本身需要的时间。xres 和 yres 则分别是屏幕的水平和垂直分辨率,常见的嵌入式设备的 LCD 分辨率主要为 320*240、640*480 等。 


帧缓冲 

帧缓冲的概念 

帧缓冲(framebuffer)是 Linux 系统为显示设备提供的一个接口,它将显示缓冲区抽象,屏蔽图像硬件的底层差异,允许上层应用程序在图形模式下直接对显示缓冲区进行读写操作。用户不必关心物理显示缓冲区的具体位置及存放方式,这些都由帧缓冲设备驱动本身来完成。对于帧缓冲设备而言,只要在显示缓冲区中与显示点对应的区域写入颜色值,对应的颜色会自动在屏幕上显示。

帧缓冲设备为标准字符设备,主设备号为 29,对应于/dev/fb%d 设备文件。帧缓冲驱动的应用非常广泛,在 Linux 的桌面系统中,Xwindow 服务器就是利用帧缓冲进行窗口的绘制。嵌入式系统中的 Qt/Embedded 等图形用户界面环境也基于帧缓冲而设计。另外,通过帧缓冲可支持汉字点阵的显示,因此帧缓冲也成为 Linux 汉化的可行方案。 

显示缓冲区与显示点 

在帧缓冲设备中,对屏幕显示点的操作通过读写显示缓冲区来完成,在不同的色彩模式下,显示缓冲区和屏幕上的显示点有不同的对应关系,表 18.2~表 18.4 分别给出了 16 级灰度、8 位色和 16 位情况下显示缓冲区与显示点的对应关系。




Linux 帧缓冲相关数据结构与函数 

1.fb_info 结构体 

帧缓冲设备最关键的一个数据结构体是 fb_info 结构体(为了便于记忆,我们把它简称为“FBI”),FBI 中包括了关于帧缓冲设备属性和操作的完整描述,这个结构体的定义如代码清单所示。

  1. 1  struct fb_info   
  2. 2  {   
  3. 3     int node;   
  4. 4     int flags;   
  5. 5     struct fb_var_screeninfo var; /*可变参数 */   
  6. 6     struct fb_fix_screeninfo fix; /*固定参数 */   
  7. 7     struct fb_monspecs monspecs; /*显示器标准 */   
  8. 8     struct work_struct queue; /* 帧缓冲事件队列 */   
  9. 9     struct fb_pixmap pixmap; /* 图像硬件 mapper */   
  10. 10    struct fb_pixmap sprite; /* 光标硬件 mapper */   
  11. 11    struct fb_cmap cmap; /* 目前的颜色表*/   
  12. 12    struct list_head modelist;    
  13. 13    struct fb_videomode *mode; /* 目前的 video 模式 */   
  14. 14   
  15. 15    #ifdef CONFIG_FB_BACKLIGHT   
  16. 16       struct mutex bl_mutex;   
  17. 17       /*  对应的背光设备  */   
  18. 18       struct backlight_device *bl_dev;   
  19. 19       /* 背光调整 */   
  20. 20       u8 bl_curve[FB_BACKLIGHT_LEVELS];   
  21. 21     #endif   
  22. 22    
  23. 23     struct fb_ops *fbops; /* fb_ops,帧缓冲操作 */   
  24. 24     struct device *device;   
  25. 25     struct class_device *class_device; /   
  26. 26     int class_flag; /* 私有 sysfs 标志 */   
  27. 27     #ifdef CONFIG_FB_TILEBLITTING   
  28. 28         struct fb_tile_ops *tileops; /* 图块 Blitting */   
  29. 29     #endif   
  30. 30     char _ _iomem *screen_base; /* 虚拟基地址 */   
  31. 31     unsigned long screen_size; /* ioremapped 的虚拟内存大小 */   
  32. 32     void *pseudo_palette; /* 伪 16 色颜色表 */   
  33. 33     #define FBINFO_STATE_RUNNING 0   
  34. 34     #define FBINFO_STATE_SUSPENDED         1   
  35. 35     u32 state; /* 硬件状态,如挂起 */   
  36. 36     void *fbcon_par;   
  37. 37     void *par;   
  38. 38 };  
FBI 中记录了帧缓冲设备的全部信息,包括设备的设置参数、状态以及操作函数指针。每一个帧缓冲设备都必须对应一个 FBI。 

2.fb_ops 结构体 

FBI 的成员变量 fbops 为指向底层操作的函数的指针,这些函数是需要驱动程序开发人员编写的,其定义如代码清单所示。

  1. 1  struct fb_ops   
  2. 2  {   
  3. 3      struct module *owner;   
  4. 4       /* 打开/释放 */   
  5. 5      int(*fb_open)(struct fb_info *info, int user);   
  6. 6      int(*fb_release)(struct fb_info *info, int user);   
  7. 7     
  8. 8      /* 对于非线性布局的/常规内存映射无法工作的帧缓冲设备需要 */   
  9. 9      ssize_t(*fb_read)(struct file *file, char _ _user *buf, size_t count,   
  10. 10        loff_t*ppos);   
  11. 11     ssize_t(*fb_write)(struct file *file, const char _ _user *buf, size_t count,   
  12. 12        loff_t *ppos);   
  13. 13    
  14. 14     /* 检测可变参数,并调整到支持的值*/   
  15. 15          int(*fb_check_var)(struct  fb_var_screeninfo  *var,  struct fb_info *info);   
  16. 16    
  17. 17    /* 根据 info->var 设置 video 模式 */  
  18. 18    int(*fb_set_par)(struct fb_info *info);   
  19. 19    
  20. 20    /* 设置 color 寄存器 */   
  21. 21    int(*fb_setcolreg)(unsigned regno, unsigned red, unsigned green, unsigned   
  22. 22        blue, unsigned transp, struct fb_info *info);   
  23. 23    
  24. 24     /* 批量设置 color 寄存器,设置颜色表 */   
  25. 25     int(*fb_setcmap)(struct fb_cmap *cmap, struct fb_info *info);   
  26. 26    
  27. 27     /*显示空白 */   
  28. 28     int(*fb_blank)(int blank, struct fb_info *info);   
  29. 29    
  30. 30     /* pan 显示 */   
  31. 31        int(*fb_pan_display)(struct  fb_var_screeninfo  *var,  struct fb_info *info);   
  32. 32    
  33. 33     /* 矩形填充 */   
  34. 34          void(*fb_fillrect)(struct  fb_info  *info,  const  struct fb_fillrect *rect);   
  35. 35     /* 数据复制 */   
  36. 36          void(*fb_copyarea)(struct  fb_info  *info,  const  struct fb_copyarea *region);   
  37. 37     /* 图形填充 */   
  38. 38     void(*fb_imageblit)(struct fb_info *info, const struct fb_image *image);   
  39. 39    
  40. 40     /* 绘制光标 */   
  41. 41     int(*fb_cursor)(struct fb_info *info, struct fb_cursor *cursor);   
  42. 42    
  43. 43     /* 旋转显示 */   
  44. 44     void(*fb_rotate)(struct fb_info *info, int angle);   
  45. 45    
  46. 46     /* 等待 blit 空闲 (可选) */   
  47. 47     int(*fb_sync)(struct fb_info *info);   
  48. 48    
  49. 49     /* fb 特定的 ioctl (可选) */   
  50. 50   int(*fb_ioctl)(struct fb_info *info, unsigned int cmd, unsigned long arg);   
  51. 51    
  52. 52   /* 处理 32 位的 compat ioctl (可选) */   
  53. 53      int(*fb_compat_ioctl)(struct  fb_info  *info,  unsigned  cmd, unsigned long arg);   
  54. 54    
  55. 55   /* fb 特定的 mmap */   
  56. 56   int(*fb_mmap)(struct fb_info *info, struct vm_area_struct *vma);   
  57. 57    
  58. 58   /* 保存目前的硬件状态 */   
  59. 59   void(*fb_save_state)(struct fb_info *info);   
  60. 60    
  61. 61   /* 恢复被保存的硬件状态 */   
  62. 62   void(*fb_restore_state)(struct fb_info *info);   
  63. 63 };   

fb_ops 的 fb_check_var()成员函数用于检查可以修改的屏幕参数并调整到合适的值,而 fb_set_par()则使得用户设置的屏幕参数在硬件上有效。

3.fb_var_screeninfo 和 fb_fix_screeninfo 结构体 

FBI 的 fb_var_screeninfo 和 fb_fix_screeninfo 成员也是结构体,fb_var_screeninfo记录用户可修改的显示控制器参数,包括屏幕分辨率和每个像素点的比特数。fb_var_screeninfo 中的 xres 定义屏幕一行有多少个点,yres 定义屏幕一列有多少个点,bits_per_pixel 定义每个点用多少个字节表示。而 fb_fix_screeninfo 中记录用户不能修改的显示控制器的参数,如屏幕缓冲区的物理地址、长度。当对帧缓冲设备进行映射操作的时候,就是从 fb_fix_screeninfo 中取得缓冲区物理地址的。上述数据成员都需要在驱动程序中初始化和设置。
fb_var_screeninfo 和 fb_fix_screeninfo 结构体的定义如代码清单所示。

  1. 1  struct fb_var_screeninfo   
  2. 2  {   
  3. 3     /* 可见解析度   */   
  4. 4     _ _u32 xres;   
  5. 5     _ _u32 yres;   
  6. 6     /* 虚拟解析度    */   
  7. 7     _ _u32 xres_virtual;   
  8. 8     _ _u32 yres_virtual;   
  9. 9     /* 虚拟到可见之间的偏移 */   
  10. 10    _ _u32 xoffset;   
  11. 11    _ _u32 yoffset;   
  12. 12    
  13. 13    _ _u32 bits_per_pixel; /* 每像素位数,BPP */   
  14. 14    _ _u32 grayscale; /非 0 时指灰度 */   
  15. 15    
  16. 16    /* fb 缓存的 R\G\B 位域 */   
  17. 17    struct fb_bitfield red;   
  18. 18    struct fb_bitfield green;   
  19. 19    struct fb_bitfield blue;   
  20. 20    struct fb_bitfield transp; /* 透明度 */   
  21. 21    
  22. 22    _ _u32 nonstd; /* != 0 非标准像素格式 */   
  23. 23    
  24. 24    _ _u32 activate;   
  25. 25    
  26. 26    _ _u32 height; /*高度 */   
  27. 27    _ _u32 width; /*宽度 */   
  28. 28    
  29. 29    _ _u32 accel_flags; /* 看 fb_info.flags */   
  30. 30    
  31. 31    /* 定时: 除了 pixclock 本身外,其他的都以像素时钟为单位 */   
  32. 32    _ _u32 pixclock; /* 像素时钟(皮秒) */   
  33. 33    _ _u32 left_margin; /* 行切换:从同步到绘图之间的延迟    */   
  34. 34    _ _u32 right_margin; /* 行切换:从绘图到同步之间的延迟   */   
  35. 35    _ _u32 upper_margin; /* 帧切换:从同步到绘图之间的延迟  */   
  36. 36    _ _u32 lower_margin; /* 帧切换:从绘图到同步之间的延迟  */   
  37. 37    _ _u32 hsync_len; /* 水平同步的长度     */   
  38. 38    _ _u32 vsync_len; /* 垂直同步的长度     */   
  39. 39    _ _u32 sync;   
  40. 40    _ _u32 vmode;   
  41. 41    _ _u32 rotate; /* 顺时钟旋转的角度 */   
  42. 42    _ _u32 reserved[5]; /* 保留 */   
  43. 43 };   
  1. 1  struct fb_fix_screeninfo   
  2. 2  {   
  3. 3      char id[16]; /* 字符串形式的标识符 */   
  4. 4      unsigned long smem_start; /* fb 缓存的开始位置 */   
  5. 5      _ _u32 smem_len; /* fb 缓存的长度 */   
  6. 6      _ _u32 type; /* FB_TYPE_*        */   
  7. 7      _ _u32 type_aux; /* 分界 */   
  8. 8      _ _u32 visual; /* FB_VISUAL_* */   
  9. 9      _ _u16 xpanstep; /* 如果没有硬件 panning ,赋 0 */   
  10. 10     _ _u16 ypanstep;    
  11. 11     _ _u16 ywrapstep;/   
  12. 12     _ _u32 line_length; /* 1 行的字节数 */   
  13. 13     unsigned long mmio_start; /* 内存映射 I/O 的开始位置 */   
  14. 14     _ _u32 mmio_len; /* 内存映射 I/O 的长度  */   
  15. 15     _ _u32 accel;   
  16. 16     _ _u16 reserved[3]; /* 保留*/   
  17. 17 };   

4.fb_bitfield 结构体 

fb_var_screeninfo 代码清单第 17、18、19 行分别记录 R、G、B 的位域,fb_bitfield 结构体描述每一像素显示缓冲区的组织方式,包含位域偏移、位域长度和 MSB 指示,如代码清单所示。

  1. 1  struct fb_bitfield   
  2. 2  {   
  3. 3      _ _u32 offset; /* 位域偏移    */   
  4. 4      _ _u32 length; /* 位域长度    */  
  5. 5      _ _u32 msb_right; /* MSB */   
  6. 6  };   
5.fb_cmap 结构体 

fb_cmap 结构体记录设备无关的颜色表信息,用户空间可以通过 ioctl()的FBIOGETCMAP 和 FBIOPUTCMAP 命令读取或设定颜色表。

  1. 1  struct fb_cmap   
  2. 2  {   
  3. 3      _ _u32 start; /* 第 1 个元素入口    */   
  4. 4      _ _u32 len; /* 元素数量 */   
  5. 5      /* R、G、B、透明度*/   
  6. 6      _ _u16 *red;   
  7. 7      _ _u16 *green;   
  8. 8      _ _u16 *blue;   
  9. 9      _ _u16 *transp;   
  10. 10 };  

下面代码清单所示为用户空间获取颜色表的例程,若 BPP 为 8 位,则颜色表长度为 256;若 BPP 为 4 位,则颜色表长度为 16;否则,颜色表长度为 0,这是因为,对于 BPP 大于等于 16 的情况,使用颜色表是不划算的。

  1. 1  // 读入颜色表   
  2. 2  if ((vinfo.bits_per_pixel == 8) || (vinfo.bits_per_pixel == 4))   
  3. 3  {   
  4. 4       screencols = (vinfo.bits_per_pixel == 8) ? 256 : 16;//颜色表大小   
  5. 5       int loopc;   
  6. 6       startcmap = new fb_cmap;   
  7. 7       startcmap->start = 0;   
  8. 8       startcmap->len = screencols;   
  9. 9      //分配颜色表的内存   
  10. 10     startcmap->red = (unsigned short int*)malloc(sizeof(unsigned short int)   
  11. 11         *screencols);   
  12. 12     startcmap->green = (unsigned short int*)malloc(sizeof(unsigned short int)   
  13. 13         *screencols);   
  14. 14     startcmap->blue = (unsigned short int*)malloc(sizeof(unsigned short int)   
  15. 15         *screencols);   
  16. 16     startcmap->transp = (unsigned short int*)malloc(sizeof(unsigned short int)   
  17. 17         *screencols);   
  18. 18     //获取颜色表   
  19. 19     ioctl(fd, FBIOGETCMAP, startcmap);   
  20. 20     for (loopc = 0; loopc < screencols; loopc++)   
  21. 21     {   
  22. 22           screenclut[loopc]  =  qRgb(startcmap->red[loopc]  >>  8, startcmap   
  23. 23               ->green[loopc] >> 8, startcmap->blue[loopc] >> 8);  
  24. 24   }   
  25. 25 }   
  26. 26 else   
  27. 27 {   
  28. 28      screencols = 0;   
  29. 29 }   
对于一个 256 色(BPP=8)的 800*600 分辨率的图像而言,若红、绿、蓝分别用一个字节描述,则需要 800*600*3=1440000Byte 的空间,而若使用颜色表,则只需要 800*600*1+256*3= 480768Byte 的空间。 

6.文件操作结构体 

作为一种字符设备,帧缓冲设备的文件操作结构体定义于/linux/drivers/vedio/fbmem.c 文件中,如代码清单所示。

  1. 1  static struct file_operations fb_fops =   
  2. 2  {   
  3. 3      .owner = THIS_MODULE,   
  4. 4      .read = fb_read, //读函数   
  5. 5      .write = fb_write, //写函数   
  6. 6      .ioctl = fb_ioctl, //I/O 控制函数   
  7. 7      #ifdef CONFIG_COMPAT   
  8. 8         .compat_ioctl = fb_compat_ioctl,   
  9. 9      #endif   
  10. 10     .mmap = fb_mmap, //内存映射函数   
  11. 11     .open = fb_open,  //打开函数   
  12. 12     .release = fb_release, //释放函数   
  13. 13     #ifdef HAVE_ARCH_FB_UNMAPPED_AREA   
  14. 14        .get_unmapped_area = get_fb_unmapped_area,   
  15. 15     #endif   
  16. 16 };   
帧缓冲设备驱动的文件操作接口函数已经在 fbmem.c 中被统一实现,一般不需要由驱动工程师再编写。 

7.注册与注销帧缓冲设备 

Linux 内核提供了 register_framebuffer()和 unregister_framebuffer()函数分别注册和注销帧缓冲设备,这两个函数都接受 FBI 指针为参数,原型为: 

int register_framebuffer(struct fb_info *fb_info); 

int unregister_framebuffer(struct fb_info *fb_info); 

对于 register_framebuffer()函数而言,如果注册的帧缓冲设备数超过了 FB_MAX(目前定义为 32),则函数返回-ENXIO,注册成功则返回 0。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值