允执 引商刻羽,杂以流徵

LCD相关(一)

2013年10月左右,开始调试手机LCD的驱动。由于采用的是MTK和高通成熟的解决方案,在软件架构的实现上,两个平台做了大量的接口优化工作,留给驱动工程师的工作,只剩下在bootloader和内核中添加屏的驱动文件,控制好上下电时序,根据提供好的接口函数设置LCD驱动IC的相关寄存器,设置屏的分辨率、图像数据的格式、帧率、前后沿参数、平台的CLK(MTK平台)、LCD的驱动方式(video mode 还是 command mode)、通信总线的类别(dsi,dpi/rgb,dbi/mcu)等,控制好睡眠唤醒的机制等。

虽然经历了从Android 4.0(Icecream),Android 4.2 (Jellybean),Android 4.4(kitkat),Android 5.0(lollipod)软件版本的更迭,linux kernel也从3.0 更新到3.2,但对LCD的调试一直是这样工作画面:

  • 关注LCD VDD 2.8v, IOVCC 1.8v 或者 AVDD,AVEE两种上电驱动的方式
  • dsi接口的lane 数目,各lane的BB端的接口是否和屏FPC的接口一致
  • 背光的驱动方式–屏输出CABC还是平台pwm
  • reset管脚的定义,on-ceil,in-ceil项目同时关注下TP相关管脚的定义

最后吐个槽,LCD的调试工作比较关键,直接影响该项目的进度,所以基本上从项目开始到结束,过程中一直会遇到的各种问题,随机异常,保持耐心和细心是调试非常重要的。另外,相关问题尽早和驱动IC的技术支持,平台的技术支持一起讨论,会很有益于问题的迅速解决。毕竟这个模块的涉及的知识点比较多,单个的个体很难了解所有技术点,协作是非常重要和有效的。

上面的内容作为引子,下面介绍一些关于LCD的基础知识和linux kernel的驱动内容(高通平台),最后一部分计划补充下android下的显示系统的软件流程和架构

LCD基础知识

  1. LCD:Liquid Crystal Display的简称。显示的原理是液晶分子(一种有机化合物,分子形状为长棒状,长度大约10nm)在不同的电流的作用下会进行有规律的旋转,从而将透过的光进行一些折射,进而在彩色偏光片等结构作用下显示出丰富的色彩画面。很多液晶分子构成一个像素,而很多像素又构成了完整图像。液晶显示器有无源矩阵(又称被动矩阵或者单纯矩阵)和有源矩阵(又称主动矩阵)两种驱动方式。前者在封入液晶材料的玻璃基板上纵横布置电极,其交叉点作为像素,构成无源矩阵;后者在封入液晶材料的玻璃基板上纵横布置薄膜三极管或者二极管等有源元件,尤其控制一个像素,构成有源矩阵。液晶显示器按驱动方式分为静态驱动,简单矩阵驱动和主动矩阵驱动。其中,简单矩阵又可细分扭转相列型(TN)和超转向列(STN)两种,而主动矩阵驱动则以TFT为主。一般的,LCD有如下技术参数:a.可视面积;b.可视角度; c.点距;d.色彩对;e.对比度;f.亮度值;g.响应时间.

  2. TFT ( Thin Film Transistor 薄膜晶体管) ,是有源矩阵类型液晶显示器(AM-LCD)中的一种,TFT在液晶的背部设置特殊光管,可以“主动的”对屏幕上的各个独立的象素进行控制,这也就是所谓 的主动矩阵TFT(aCTive matrix TFT)的来历,这样可以大大的提高反应时间,一般TFT的反映时间比较快约80ms,而STN则为200ms如果要提高就会有闪烁现象发生。而且由于 TFT是主动式矩阵LCD可让液晶的排列方式具有记忆性,不会在电流消失后马上恢复原状。TFT还改善了STN 会闪烁(水波纹)-模糊的现象,有效的提高了播放动态画面的能力。和STN相比TFT有出色的色彩饱和度、还原能力和更高的对比度,但是缺点就是比较耗电,而且成本也比较高。

  3. 液晶显示器为了能显示任意的图像,其电极由m*n个点组成点矩阵型。由这种点矩阵画面来显示图像,特别是动画,需要大量的图像数据。为此,需要在图像的输出端和接收端之间,有输入端将图像数据按时间轴分解,变换为时序信号,并使之成为可传送的形式。与此同时,后者接受此时序信号,并按先后顺序将其以平面图像的形式,在显示屏上进行再布置。一般称该操作为“扫描”。扫描方式有点“点顺序扫描”,“线顺序扫描”和“面顺序扫描”等。像液晶显示器等这类平板显示器,由于图像信号的写入能力很强,一般采用线顺序扫描,而CRT及多晶硅(poly-si)TFT LCD等,一般采用“点顺序扫描”。

  4. 液晶显示器多采用交流驱动的方式,及将即将极性正负变换的电压加到液晶上。这是因为,液晶在直流电压的长时间作用下会引起电气分解等,造成材料变质,寿命降低。而交流电压作用下,液晶材料不会变质,从而保证寿命。为了采用交流电压驱动,要求施加在液晶上电压的极性每帧发生反转。尽管整个画面同时实现极性反转既简单又方便,但由于容易产生闪烁及亮度沿画面的倾斜等,实际上并不采用。称这种方法为帧反转驱动法。为了减少帧反转驱动法对画面质量产生的种种不利影响,一般是采用个像素的机型反转有少许位相差的驱动方式,其代表有:每一水平线有少许位相差的方式(称为H线反转驱动法);每一垂直线极性反转有少许相位差的方式(称为V线反转驱动法);每一像素交互性有少许相位差的方式(称其为H/V线反转驱动法,或像素反转驱动法)等。而且,在公用电极上的供电,还有供给直流电压的方式和每一扫描线电平翻转,即供给交流电压之分。

  5. 所谓帧是指全体删线按顺序从上至下扫描时,完成一个画面显示所用的时间。从人眼的响应性考虑,一般希望帧频在60HZ以上。

  6. 交叉噪声(cross-talk) 例如在黑色背景中显示白色四角形方块时会显著出现。这种由信号线、公用电极之间的寄生电容及数据线、像素电极之间的寄生电容等造成的。作为客服交叉噪声的对策,一般可采用可消除寄生电容的H/V线驱方法。

  7. 液晶显示屏有透射型,放射型和半透射半反射型之分。利用发自屏面型的入射光的液晶显示器称为投射性;液晶显示器中不带背光源,而是利用周围光源进行显示的称为反射型;两者并用的称为半透射半反射型。

  8. 液晶显示器还可以根据由电气信号引起的液晶分子曲线变化的方式来分类,称为动作模式。液晶显示器的动作模式有多种,例如TN模式,STN模式,IPS模式,VA模式(MVA,ASV,PVA)模式和OCB模式等。

(1) TN液晶屏 在显示屏的液晶物质中,指向矢沿与玻璃基板表面平行的相同方向均匀排列。这种相同的取向使用过设置在基板表面上的聚酰亚胺分子薄膜进行单方向摩擦,即进行取向处理来实现的。而且,两块基板表面取向方向反平行方向布置。但是,实际应用的被称为扭曲向列(twisted nematic, TN)方式的显示屏中,上述布置得两块基板中的一块要绕其法线做90°旋转,即两块基板表面的取向方向互相垂直。TN型驱动液晶,是LCD中最基本的,其他LCD都以TN型改进而得。他只能将入射光旋转90°,视角只有30°,色彩单一,对比度低,用于电子表和电子计算器

(2) STN 型驱动液晶,可将入射光旋转180°至270°,也改善了视角。它通过搭配彩色滤光片,将单色矩阵的任意像素分成3个子像素成红绿蓝,再经由三色按比例调和,显示出全彩模式的色彩。

(3) TN与STN都采用场电压驱动方式,如果显示尺寸加大,中心部分对电极变化的反应时间就会变长,显示器的速度跟不上,为了解决这个问题,主动矩阵驱动TFT被提出。他通过液晶管显示信号开启或者关闭液晶分子的电压,从而避免了显示器对电厂效应的依靠。

(4) OELD. OLED (Organic Light Emitting Display)即有机发光显示器,在手机LCD上属于新崛起的种类,被称誉为”梦幻显示器”.OLED显示技术与传统的LCD显示方式不同,无需背光灯,采用非常薄的有机材料涂层和玻璃基板,当有电流通过时,这些有机材料就会发光。而且OLED显示屏幕可以做得更轻更薄,可视角度更大,并且能够显著节省电能。目前已经有相关成熟的屏上市,应该属于未来几年甚至更长时间的主流手机屏幕的选择。

显示原理

LCD为液晶显示屏,本身不发光,需要背光源。其由TFT基板与CF(彩膜)基板贴合而成,内充液晶。通过TFT基板提供电场来控制液晶旋转的角度,从而起到控制液晶穿透率的作用。彩膜上印刷有RGB三种颜色色块,背光源的光线透过透明的TFT基板,透过液晶分子,然后透过CF基板。受各个色块下液晶分子的穿透率不同的影响,色块发出不同亮暗的红绿蓝三色,可混合成显示所需的颜色。 而OLED为有机发光二极管,属于自发光器件,不需要背光源;构造为在TFT基板上蒸镀在通电下可以自发光的RGB三色有机膜层。通过TFT基板控制电流大小,即可控制RGB有机膜层的发光亮暗,从而混合出显示所需的颜色。 目前市场主流的显示技术还是为TFT-LCD技术,OLED作为新一代的显示技术,在工艺良率、大尺寸、高PPI、使用寿命、制作成本等方面还需要进一步提升,但其在低功耗、高色域、宽视角、可弯曲、更薄更轻、可透明方面有显著的优势。

色彩基础知识

色彩的三要素

色彩的三要素是指色相(H,hues),饱和度(纯度,S, saturation),明度(B, brightness)

color

H=色相决定是什么颜色 S=纯度决定颜色浓淡 B=明度决定照射在颜色上的白光有多亮

明度:指色彩的明暗程度,也称深浅度。无彩色系中,白色明度最高,黑色最低。有彩色系中,黄色明度最高,紫色明度最低。任何一个有彩色,当它掺入白色时,明度增高;当它掺入黑色时,明度降低。同时其纯度也相应降低。

色调:是指通过色彩的明度和饱和度综合表现色彩状态的概念。

小知识:

RGB颜色三者都是0为黑色而255是白色 为什么要这样定义呢?

有两种产生颜色的方法:一种是做加色法(additive),另一种是做减色法(Subtractive)。

加色法是光源合成光线的原理。显示屏是一个光源,本身可以发出红、绿、蓝三种颜色的光线。通过调节红、绿、蓝三种颜色的强度,来合成其它。 减色法是物体表面反射光线的原理。一些物体可以反射所有波长的光线,比如白纸,所以我们看到画纸是白色的;而像用来画画的颜料只能反射一部分波长的光线,红色的颜料反射红色的光线,其余光线被颜料吸收了(减去了),所以我们只看到红色。

加色法:有红、绿、蓝三个光源叠加,我们在photoshop里设置(0,0,0)就相当于告诉显示屏把这个像素点红、绿、蓝三盏灯都熄灭,然后我们在屏幕上就看到了一个黑点。而(255,255,255)就相当于让三盏灯亮度达到最大,于是中心就呈现了一个白斑。

减色法正好相反。本来画纸可以反射所有颜色,然后我们用画笔涂上一种颜料,这种颜料只反射其中一种颜色,其它颜色的光线都被它吸收了。因为粉色颜料吸收除粉色以外所有光线,青色颜料吸收除青色以外所有光线,黄色颜料吸收除黄色以外所有光线,所以在三种颜料的叠加区域所有颜色都被吸收了,我们只能看到黑色。(插一句,夏天穿黑衣服吸热就是由于黑衣服比白衣服能吸收更多的光能,能量多了温度就上升了)

gamma

色彩校正中的gamma 值是什么 Gamma是用来描述显示设备的‘非线性’程度的专有名词. Gamma是一个非常好用的用来校正画面明暗程度的数学工具。其实它也是唯一正确的用来校正画面明暗程度的工具.

一个典型的完整图像处理系统主要包括摄像采集部件、存储传输部件和显示输出部件。这三个部分中都可以引入Gamma的概念。按照国际组织ITU的标准如sRGB,常见的摄像部件中Gamma处理过程称为Gamma预校正,推荐值为1/2.2=0.4545…,而显示部件中Gamma推荐值为2.2。两者相抵最终呈现给观察者的系统Gamma则等于1。

macbeth色彩表

记忆色彩调节

使用不同的参考图片或者色块来调节记忆色彩

在进行记忆色彩调节之前,请先完成白平衡的调节

按照如下子模块顺序调节,每个模块按H,S,B进行调节

驱动实现

  1. LCD驱动的显示原理:作为帧同步信号的vsync,每发出一个脉冲,都意味着新的一副图像数据开始传送。而作为行同步信号的hsync,每发出一个脉冲,都表明新的一行图像资料开始发送。所有LCD显示图像的原理都是从上到下,从左到右的。一幅图像可以看做是一个矩形,有很多排列整齐的点一行一行组成,这些点称之为像素。

  2. 同步信号和前后沿

     VSYNC:帧同步信号
     HSYNC:行同步信号
     VCLK:像素时钟信号
     LEND:行结束信号
    
     VBP:表示一帧图像开始时,帧同步信号以后的无效的行数
     VFP:表示一帧图像结束后,帧同步信号以前的无效的函数
     VSPW:表示垂直同步脉冲的宽度,用行数计算
     HBP:表示从水平同步信号开始后到一行有效数据开始之间的VCLK的个数
     HFP:表示一行的有效数据结束到下一个水平同步信号开始之间的VCLK的个数
     HSPW:表示水平同步信号的宽度,用VCLK计算
    
  3. 帧缓冲:Framebuffer是图像设备的硬件抽象。对开发者而言,framebuffer是一块显示缓存,往显示缓存中写入特定格式的数据就意味着向屏幕输出内容。通过不断地向framebuffer中写入数据,显示控制器就可以自动的从framebuffer中取数据并显示出来。帧缓冲设备对应的设备文件为/dev/fb*,如果系统有多个显示卡,Linux下还可以支持多个帧缓冲设备,最多可带32个,而/dev/fb则为当前缺省的帧缓冲设备,通常指向/dev/fb0。帧缓冲设备为字符设备,主设备号29,次设备号从0到31 。

  4. linux内核使用struct fb_info来描述帧缓冲设备

     struct fb_info
     {
         ...
         struct fb_vat_screeninfo var;/*可变参数*/
         struct fb_fix_screeninfo fix;/*固定参数*/
         ...
         struct fb_ops *fbops;/*帧缓冲操作 */
     };
    

struct fb_var_screeninfo记录了用户可以修改的显示参数,包括屏幕分辨率等

struct fb_fix_screeninfo记录了用户不能修改的显示控制其参数,如显示缓冲的物理地址等

struct fb_ops包含了对控制器进行操作的函数指针

linux内核使用register_framebuffer函数注册一个帧缓冲设备

LCD驱动的撰写

  1. 获取device传递的设备属性,如irq(platform_get_irq),IO资源——即控制器操作的寄存器的物理地址(plafrom_get_resource)
  2. 调用framebuffer_alloc 申请fb_info结构的内存空间
  3. 初始化fb_info->fix, fb_info->var, fb_info->fbops, fb_info->pseudo_palette等结构
  4. 调用 request_mem_region函数,申请使用显示控制器的物理的地址
  5. 调用ioremap函数,将物理地址映射到进程虚拟地址上
  6. 调用register_framebuffer注册帧缓冲设备

android 启动画面

开机过程中第二个画面—-开机android logo

system/core/init.c中main函数包含一个console_init_action的函数,下面是对该函数的分析: 这个函数主要做了两件事件:

A. 初始化控制台。init进程在启动的时候,会解析内核的启动参数(保存在文件/proc/cmdline中)。如果发现内核的启动参数中包含有了一个名称为“androidboot.console”的属性,那么就会将这个属性的值保存在字符数组console中。这样我们就可以通过设备文件/dev/来访问系统的控制台。如果内核的启动参数没有包含名称为“androidboot.console”的属性,那么默认就通过设备文件/dev/console来访问系统的控制台。如果能够成功地打开设备文件/dev/或者/dev/console,那么就说明系统支持访问控制台,因此,全局变量have_console的就会被设置为1。

B. 显示第二个开机画面。显示第二个开机画面是通过调用函数load_565rle_image来实现的。在调用函数load_565rle_image的时候,指定的开机画面文件为INIT_IMAGE_FILE。INIT_IMAGE_FILE是一个宏,定义在system/core/init/init.h文件中,如下所示:

开机过程中第三个画面—-开机动画 由应用程序bootanimation来实现,应用程序bootanimation在启动脚本init.rc中被配置成了一个服务。 应用程序bootanimation的用户和用户组名称分别被设置为graphics。注意, 用来启动应用程序bootanimation的服务是disable的,即init进程在启动的时候,不会主动将应用程序bootanimation启动起来。当SurfaceFlinger服务启动的时候,它会通过修改系统属性ctl.start的值来通知init进程启动应用程序bootanimation,以便可以显示第三个开机画面,而当System进程将系统中的关键服务都启动起来之后,ActivityManagerService服务就会通知SurfaceFlinger服务来修改系统属性ctl.stop的值,以便可以通知init进程停止执行应用程序bootanimation,即停止显示第三个开机画面。接下来我们就分别分析第三个开机画面的显示过程和停止过程。

通过这个三个开机画面的显示过程分析,我们学习到:

   1. 在内核层,系统屏幕是使用一个称为帧缓冲区的硬件设备来描述的,而用户空间的应用程序可以通过设备文件/dev/fb0或者/dev/graphics/fb0来操作这个硬件设备。实际上,帧缓冲区本身并不是一个真正的硬件,它只不过是对显卡的一个抽象表示,不过,我们通过访帧缓冲区就可以间接地操作显卡内存以及显卡中的其它寄存器。

   2. OpenGL是通过EGL接口来渲染屏幕,而EGL接口是通过ANativeWindow类来间接地渲染屏幕的。我们可以将ANativeWindow类理解成一个Android系统的本地窗口类,即相当于是Windows系统中的窗口句柄概念,它最终是通过文件/dev/fb0或者/dev/graphics/fb0来渲染屏幕的。

   3. init进程在启动的过程中,会将另外一个ueventd进程也启动起来。ueventd进程对应的可执行文件与init进程对应的可执行文件均为/init,不过ueventd进程主要负责处理内核发出的uevent事件,即负责管理系统中的设备文件。

   4. 每当我们设置一个系统属性的时候,init进程都会接收到一个系统属性变化事件。当发生变化的系统属性的名称等于“ctl.start”或者“ctl.stop”,那么实际上是向init进程发出一个启动或者停止服务的命令。

display hardware层分析

从帧缓冲区的使用情景以及硬件抽象层编写规范来介绍Gralloc模块的实现

用户空间的应用程序在使用帧缓冲区之间,首先要加载Gralloc模块,并且获得一个gralloc设备和一个fb设备。有了gralloc设备之后,用户空间中的应用程序就可以申请分配一块图形缓冲区,并且将这块图形缓冲区映射到应用程序的地址空间来,以便可以向里面写入要绘制的画面的内容。最后,用户空间中的应用程序就通过fb设备来将前面已经准备好了的图形缓冲区渲染到帧缓冲区中去,即将图形缓冲区的内容绘制到显示屏中去。相应地,当用户空间中的应用程序不再需要使用一块图形缓冲区的时候,就可以通过gralloc设备来释放它,并且将它从地址空间中解除映射。接下来,我们就按照上述使用情景来分析Gralloc模块的实现。

  1. hardware/libhardware/hardware.c

hw_get_module依次在/system/lib/hw 和 /vendor/lib/hw 查找是否存在 gralloc..so的文件,找到后调用Load函数装载该模块(动态链接库的加载函数是dlopen)。

hardware/libhardware/modules/gralloc/gralloc.cpp hardware/qcom/display/libgralloc/gralloc.c

struct private_module_t HAL_MODULE_INFO_SYM; 这个private_module_t的结构体可以被当成hw_module_t的结构体来用。

gralloc_module_t中得成员函数 lock 和 unlock:

函数lock和unlock分别用来锁定和解锁一个指定的图形缓冲区,这个指定的图形缓冲区同样是使用一个buffer_handle_t句柄来描述。在访问一块图形缓冲区的时候,例如,向一块图形缓冲写入内容的时候,需要将该图形缓冲区锁定,用来避免访问冲突。在锁定一块图形缓冲区的时候,可以指定要锁定的图形绘冲区的位置以及大小,这是通过参数l、t、w和h来指定的,其中,参数l和t指定的是要访问的图形缓冲区的左上角位置,而参数w和h指定的是要访问的图形缓冲区的宽度和长度。锁定之后,就可以获得由参数参数l、t、w和h所圈定的一块缓冲区的起始地址,保存在输出参数vaddr中。另一方面,在访问完成一块图形缓冲区之后,需要解除这块图形缓冲区的锁定。

gralloc_device_open hardware/qcom/display/libgralloc/gpu.c

参考书目

《TFT LCD面板设计与构装技术》(科学出版社,田明波,叶锋等,2010)

点击查看评论
推荐到豆瓣

Blog

Opinion

Project