Natalie2-uo&&Alex2 Project LCD Backlight模块代码架构及Bug修改简介。
LCD显示模块部分在外部采用一颗Sharp LCDC芯片,其代号为Goliath2(LR388G9/LR388G7, G7/G9基本上没有区别,可以认为是一个)。
Goliath2作为显示控制芯片有两个作用:
1. 控制主屏(480*854)显示。
2. 控制副屏显示,Natalie2-uo和Alex2只是外屏大小不一样,控制接口都一样。
3. 对主屏显示图像进行防偷窥图层混合,然后将合成的图片输出到主屏上。
其中第2个功能是当时杜辉负责的.
主屏工作时主屏图像数据通路:
图像数据由MDP从framebuffer中取出经过旋转或缩放等一系统处理,在通过MSM7227的MDDI Host接口送到Goliath2的MDDI Client端,Goliath2接收到以后由它的前处理器1送到VRAM里去。后处理器TG0在从VRAM里取数据,经由CUSTOM BLOCK模块,然后通过LVDS接口输出到LCD 面板上显示。
主屏初始化接口:
Goliath2的上电要参考文档Gokuh_Power_Sequence_Application_Note_ver01.pdf。按照它指定的上电顺序和对应的电路接口进行控制。
初始化指令是由Goliath2的前处理器0(Pre-processor0)的EBI2总线接口写入。最佳寄存器设置要参考文档Gokuh_LCD_Application_Note_ver10e.pdf。之所以要用EBI2总线写入而不用MDDI写入是因为有一个指令是不能通过MDDI数据包写入Register的方式来访问Goliath2. 另外,副屏的初始化指令、副屏正常工作时图像数据、防偷窥(Veil View)功能的图像数据写入都是通过这组EBI2总线接口写到前处理器0里的。所以当系统进出休眠或开启Veil view功能时会跟其它使用EBI2总线的模块有冲突和竞争。需要特别处理加入保护和互斥机机制。
LCD面板上面的LCD驱动芯片需要由Goliath2的IIC接口向它写入面板初始化指令。Goliath2 IIC 初始化参考文档为Gokuh_I2C_Application_Note_ver01.pdf。
主屏进出休眠控制:
进休眠时Goliath2有专门的流程说明, 也可以直接断电,然后在出休眠时重新初始化。目前Natalie2使用的是第二种做法。两种做法主要是进休眠时耗电问题,按SHARP说进休眠时如果按它的说明进入Suspend状态而不是断电,则会产生很少的耗电,而事实上进休眠时设置Suspend状态和断电状态都会造成约0.1mA的耗电。后来直接采用进休眠后断电,出休眠后重新初始化。
背光芯片控制:
背光芯片采用SSC的模式控制,芯片接收脉冲个数来调整内部电流输出。硬件上支持32级背光亮度。这个软件实现上不难,但是要注意背光级别调整时不要下电,否则会产生强烈的闪烁。还有就是在GPIO口拉脉冲个数的时候需要加以保护,不要切走CPU。
Android framebuffer代码构成
网络上也有很多这方面的说明,写的也很详细,如下摘了一段:
*************************************************************************
Android display SW架构分析
下面简单介绍一下上图中的各个Layer:
*蓝色部分-用户空间应用程序
应用程序层,其中包括Android应用程序以及框架和系统运行库,和底层相关的是系统运行库,而其中和显示相关的就是Android的Surface Manager, 它负责对显示子系统的管理,并且为多个应用程序提供了2D和3D图层的无缝融合。
*黑色部分-HAL层,在2.2.1部分会有介绍
*红色部分-Linux kernel层
Linux kernel,其中和显示部分相关的就是Linux的FrameBuffer,它是Linux系统中的显示部分驱动程序接口。Linux工作在保护模式下,User空间的应用程序无法直接调用显卡的驱动程序来直接画屏,FrameBuffer机制模仿显卡的功能,将显卡硬件结构抽象掉,可以通过 Framebuffer的读写直接对显存进行操作。用户可以将Framebuffer看成是显示内存的一个映像,将其映射到进程地址空间之后,就可以直接进行读写操作,而写操作可以立即反应在屏幕上。这种操作是抽象的,统一的。用户不必关心物理显存的位置、换页机制等等具体细节。这些都是由 Framebuffer设备驱动来完成的。
*绿色部分-HW驱动层
该部分可以看作高通显卡的驱动程序,和高通显示部分硬件相关以及外围LCD相关的驱动都被定义在这边,比如上述的显卡的一些特性都是在这边被初始化的,同样MDP和MDDI相关的驱动也都定义在这里
这里的User Space就是与应用程序相关的上层部分(参考上图中的蓝色部分),其中与Kernel空间交互的部分称之为HAL-HW Abstraction Layer。
HAL其实就是用户空间的驱动程序。如果想要将 Android 在某硬件平台上执行,基本上完成这些驱动程序就行了。其内定义了 Android 对各硬件装置例如显示芯片、声音、数字相机、GPS、GSM 等等的需求。
HAL存在的几个原因:
1、 并不是所有的硬件设备都有标准的linux kernel的接口。
2、 Kernel driver涉及到GPL的版权。某些设备制造商并不原因公开硬件驱动,所以才去HAL方式绕过GPL。
3、 针对某些硬件,Android有一些特殊的需求。
在display部分,HAL的实现code在copybit.c中,应用程序直接操作这些接口即可,具体的接口如下:
struct copybit_context_t *ctx = malloc(sizeof(struct copybit_context_t));
memset(ctx, 0, sizeof(*ctx));
ctx->device.common.tag = HARDWARE_DEVICE_TAG;
ctx->device.common.version = 0;
ctx->device.common.module = module;
ctx->device.common.close = close_copybit;
ctx->device.set_parameter = set_parameter_copybit;//设置参数
ctx->device.get = get;
ctx->device.blit = blit_copybit;//传送显示数据
ctx->device.stretch = stretch_copybit;
ctx->mAlpha = MDP_ALPHA_NOP;
ctx->mFlags = 0;
ctx->mFD = open("/dev/graphics/fb0", O_RDWR, 0);//打开设备
这里的Kernel空间(与Display相关)是Linux平台下的FB设备(参考上图中的红色部分)。下面介绍一下FB设备。
Fb即FrameBuffer的简称。framebuffer 是一种能够提取图形的硬件设备,是用户进入图形界面很好的接口。有了framebuffer,用户的应用程序不需要对底层驱动有深入了解就能够做出很好的图形。对于用户而言,它和/dev 下面的其他设备没有什么区别,用户可以把
framebuffer 看成一块内存,既可以向这块内存中写入数据,也可以从这块内存中读取数据。它允许上层应用程序在图形模式下直接对显示缓冲区进行读写操作。这种操作是抽象的,统一的。用户不必关心物理显存的位置、换页机制等等具体细节。这些都是由Framebuffer设备驱动来完成的。
从用户的角度看,帧缓冲设备和其他位于/dev下面的设备类似,它是一个字符设备,通常主设备号是29,次设备号定义帧缓冲的个数。
在LINUX系统中,设备被当作文件来处理,所有的文件包括设备文件,Linux都提供了统一的操作函数接口。上面的结构体就是Linux为FB设备提供的操作函数接口。
1)、读写(read/write)接口,即读写屏幕缓冲区(应用程序不一定会调用该接口)
2)、映射(map)操作(用户空间不能直接访问显存物理空间,需map成虚拟地址后才可以)
由于Linux工作在保护模式,每个应用程序都有自己的虚拟地址空间,在应用程序中是不能直接访问物理缓冲区地址的。为此,Linux在文件操作 file_operations结构中提供了mmap函数,可将文件的内容映射到用户空间。对于帧缓冲设备,则可通过映射操作,可将屏幕缓冲区的物理地址映射到用户空间的一段虚拟地址中,之后用户就可以通过读写这段虚拟地址访问屏幕缓冲区,在屏幕上绘图了。实际上,使用帧缓冲设备的应用程序都是通过映射操作来显示图形的。由于映射操作都是由内核来完成,下面我们将看到,帧缓冲驱动留给开发人员的工作并不多
3)、I/O控制:对于帧缓冲设备,对设备文件的ioctl操作可读取/设置显示设备及屏幕的参数,如分辨率,显示颜色数,屏幕大小等等。ioctl的操作是由底层的驱动程序来完成
Note:上述部分请参考文件fbmem.c。
*************************************************************************
********************************************************