LCD驱动及Framebuffer相关 (2012-11-20 17:04)

标签:&nBSP; lcd驱动  framebuffer  io内存  分类: Android驱动模块相关

内容提要:

1. android display相关的名词

2. 调试LCD驱动需要注意的步骤

3. 关于帧缓冲区及I/O内存

------------------------------------------------------------------------------------------

1.名词解释

GPU:Graphic Processing Unit (图形处理器)

OpenGL:Open Graphic Library 定义了一个跨编程语言、跨平台的编程接口的规格,不同厂商会有不同的实现方法,它主要用于三维图象(二维的亦可)绘制。

SurfaceFlinger:Android中负责Surface之间叠加、混合操作的动态库

Skia:Android中的2D图形库

libagl:Android中通过软件方法实现的一套OpenGL动态库

libhgl:为区别libagl,自定义的一种叫法。特指GPU厂商提供的硬件实现的OpenGL

composition:特指SurfaceFlinger对各个Surface之间的叠加、混合操作

render:特指使用OpenGL动态库进行3D渲染

copybit:Android使用2D引擎来加速图形操作(主要是Surface之间的composition操作)的一种技术,对应着一个或几个动态库。

pmem:Android特有驱动,从linux内核中reserve物理连续内存,可以为2d、3d引擎、vpu等设备分配物理连续内存。

Android在启动后,会在运行时根据配置文件加载OpenGL(libagl & libhgl)的实现,如果有libhgl实现,默认使用libhgl实现,否则使用libagl实现。

OpenGL在Android中两个作用:

1. 用于Surface的composition操作。

SurfaceFlinger会调用到OpenGL中,通过libagl或者libhgl做Surface的组合、叠加操作。

2. 用于图形图像的渲染

Android Framework会对OpenGL实现进行Java层次的简单封装,在java应用程序中对OpenGL的调用最终会调用到libagl或者libhgl中去。

很多第三方游戏、3D图库、某些Launcher会使用OpenGL实现比较炫丽UI的特效。

Copybit在Android中的作用

Copybit在Android中主要用于Surface的composition操作。

Skia在Android中的作用

Skia是Android的2D图形库,用于绘制文字、几何图形、图像等。

Skia的设备后端:Raster、OpenGL、PDF

(以上这段是网上摘的)

------------------------------------------------------------------------------------------

LCD调光方式有:

一线脉冲计数调光

PWM调光

调试LCD需要注意的:

SCLK

SDA

CS

RESET

上面这几路线是发命令和参数用的,所以首先要调通,这几路OK后屏应该亮或花屏

PCLK

HSYNC

VSYNC

DE

这几路是刷数据用的,屏亮后显示不正常就调这几路的参数

320x480的,参数为:

PCLK    10MHz

HSYNC    30KHz(行刷新)

VSYNC    60Hz(列刷新,即一屏)

SCLK    70KHz

DE    30KHz(Data enable RGB写数据时用到)

CS    spi写命令或参数时用,往屏上刷数据时用不到

常见的问题:

---

lk亮屏了,但是白屏,查下极性,看是不是反了

极性: lcdc侧的Pclk,Hsync,Vsync,DE是高有效,那么panel driver的

这些信号也应该是高有效,在往寄存器写参数时要核对下

---

要注意这些东西,HFP,HBP,VFP,VBP 即通常所讲的前沿,后沿

屏幕图像左右抖动,不用说,肯定是HFP/HBP不对

前沿后沿就是给hsync,vsync往屏幕刷数据提供时间,可以看你的LCD IC SPEC了解

调试步骤(这段是网上摘的):

1)调试lcd背光,背光主要分为PMIC自带的和单独的DCDC,如果为PMIC自带的背光,一般平台厂商已经做好,

直接调用接口即可,如果为单独的DCDC驱动,则需要用GPIO控制DCDC的EN端

2)确认lcd的模拟电,io电是否正常

3)根据lcd的分辨率,RGB/CPU/mipi等不同的接口,配置控制寄存器接口

4)根据lcd spec配置PCLK的频率,配置PCLK,VSYNC,HSYNC,DE等控制线的极性

5)使用示波器测试所有clk的波形,确认频率,极性是否符合要求

6)使用示波器测试data线,看是否有数据输出,bpp的设置是否正确

7)如果lcd需要初始化,配置spi的接口,一般分为cpu自带的spi控制器,和gpio模拟的spi。

8)根据lcd spec中的初始化代码进行lcd的初始化

9)用示波器测量lcd的spi clk及数据线,确认是否正常输出

10)正常情况下,此时lcd应该可以点亮。如果没有点亮,按照上述步骤1到9,逐项进行检查测试,重点检查第

5项,clk的极性

11)如果lcd点亮,但是花屏。则需要先确认数据格式是否正确,然后确认fb里的数据是否正常,有以下几种方

法确认fb里的数据

i)cat /dev/graphics/fb0 > /sdcard/fb0,然后将/sdcard/fb0 >到另一台相同分辨率及相同格式的手机上,看图片显示是否正常

ii)使用irfanview软件显示cat /dev/graphics/fb0出来的raw数据,注意要正确设置分辨率及格式,否则显示花屏

iii)如果adb连接正常,可以使用豌豆莢等软件,查看fb中的数据是否正常

通过以上三种途径,如果确认fb中的数据正常显示,则很可能为lcd初始化代码的问题,或者clk极性的问题,

如果fb数据不正常,则可能为lcd控制寄存器配置不正常导致。

LCD屏的调试注意事项

1. Pix clock是否在规定的范围内。

2. Pclk是否极性正确。上升沿还是下降沿。

3. 变频引起的闪屏问题。可以通过锁定频率来试验是否是变频引起。

要确保每一步都正确,那肯定可以显示出图像来

------------------------------------------------------------------------------------------

framebuffer

我们现在用的是Adreno系列,Adreno是什么?就相当于PC机上的显卡.显卡,也叫GPU,

它的好坏会对手机的多媒体播放和3D游戏性能有着直接的影响.

framebuffer即帧缓冲区,这个帧缓冲区就位于显卡的内部,帧缓冲区是显卡上固化的存储器,其中存放的是当前屏幕的内容.你要做高通平台,那么还会遇到MDP,MDP(Mobile Display Processor), MDP是什么? 比方说你用的data format是RGB666,那么这里的data format输出是多少位是由MDP决定的,MDP1.1/MDP1.2只能输出16或18bpp,而MDP1.3可以输出24bpp.还有图形的旋转等效果,上面说的Copybit进行composition的动作我想底层就是由MDP支持的.我们也可以选择是GPU来composition还是MDP来composition. 那么GPU和MDP是什么关系?GPU是显卡,MDP是图形处理器,后者是锦上添花,去掉无妨,前者去掉那就瞎了.后面分析代码会看到,我们把数据写到MDP就不管了,它内部应该是把数据再调整,然后再写到各个接口(MIPI/LCDC)连接的panel上.这些东西都是SOC,所以你在板子上是看不到的.

显卡对CPU来说是外设,外设会通过I/O接口连接到I/O总线上,I/O总线再连接到CPU. I/O接口包含多个I/O端口.每个连接到I/O总线上的设备都有自己的I/O地址集,通常称为I/O端口(LKD part13 原话).为I/O编程提供统一的方法,但又不牺牲性能,所以设计者们把一组I/O端口(即一地址集)组织成一组专用的寄存器. 这也就是我们通常所说的I/O端口即寄存器的由来. 所以每个外设都是通过读写其寄存器来控制的.

I/O接口是处于一组I/O端口和对应的设备控制器之间的一种硬件电路.它起翻译器的作用,即把I/O端口中的值转换成设备所需要的命令和数据.还可以通过一条IRQ线把这种电路连接到可编程中断控制器上,以使它代表相应的设备发出中断请求.

硬件组织上了解后我们看软件上怎么处理.我们要做的工作是,检测哪些I/O端口已经分配给I/O设备. 通常来讲,I/O设备驱动程序为了探测硬件设备,需要盲目地向某一I/O端口写入数据,但是,如果其他硬件设备已经使用了这个端口,那么系统就会崩溃.所以,linux的设计者们便想出用"资源"来记录分配给每个硬件设备的I/O端口.

资源(resource)被互斥地分配给设备驱动程序,一个资源表示I/O端口地址的一个范围.

我为什么会说I/O呢,因为帧缓冲区就是I/O内存,和I/O有关,抛砖引玉. 关于I/O端口和I/O内存的区别可是有学问的,你知道吗?不知道是哪位大侠创作或整理的文章,粉好,你要是知道这两者的区别,那就不用看了,你要是不知道,那不妨看一看吧.

http://blog.csdn.net/insoonior/article/details/8011192#t0

说到这里我们需要看代码了:

static struct resource msm_fb_resources[] = {

{

.flags  = IORESOURCE_DMA,

}

};

static struct platform_device msm_fb_device = {

.name   = "msm_fb",

.id     = 0,

.num_resources  = ARRAY_SIZE(msm_fb_resources),

.resource       = msm_fb_resources,

.dev    = {

.platform_data = &msm_fb_pdata,

}

};

void __init msm_MSM7627a_allocate_memory_regions(void)

{

addr = alloc_bootmem_align(fb_size, 0x1000);    //这就是framebuffer的物理地址,在framebuffer的驱动中会用到

msm_fb_resources[0].start = __pa(addr);

msm_fb_resources[0].end = msm_fb_resources[0].start + fb_size - 1;

}

系统启动并初始化时会通过以下调用,把device 的 resource 加入到resource树中:

# TO tag         FROM line  in file/text

1  1 platform_add_devices  1455  arch/arm/mach-msm/board-qrd7627a.c

2  1 platform_device_register   114  drivers/base/platform.c

3  1 platform_device_add   337  drivers/base/platform.c

4  1 insert_resource   275  drivers/base/platform.c

5  1 insert_resource_conflict   667  conflict = insert_resource_conflict(parent, new);

6  1 __insert_resource   651  conflict = __insert_resource(parent, new);

有了以上的资源后就清楚了:

static int msm_fb_probe(struct platform_device *pdev)

{

fbram_size =

pdev->resource[0].end - pdev->resource[0].start + 1;

fbram_phys = (char *)pdev->resource[0].start;

fbram = __va(fbram_phys);

}

static int msm_fb_register(struct msm_fb_data_type *mfd)

{

struct fb_fix_screeninfo *fix;

struct fb_var_screeninfo *var;    //主要是根据panel的信息初始化这两个数据结构

fbram_offset = PAGE_ALIGN((int)fbram)-(int)fbram;

fbram += fbram_offset;

fbram_phys += fbram_offset;

fbram_size -= fbram_offset;

fbi->screen_base = fbram;

fbi->fix.smem_start = (unsigned long)fbram_phys;

}

smem_start在后面分析mdp_lcdc_update时会用到.

------------------------------------------------------------------------------------------

我们看下数据到framebuffer后是怎么显示到屏幕上的.先从HAL层分析数据的走向,再往上的逻辑待定.

android/hardware/msm7k/libgralloc-qsd8k/ 这是display subsys的HAL层

ioctl(m->framebuffer->fd, FBIOPUT_VSCREENINFO, &m->info)

上层调用这句ioctl把数据推给driver,放到framebuffer里

ioctl(fd, FBIOGET_VSCREENINFO, &info)

上层通过这句可以获知屏幕的大小

ioctl一路调用下来会到

drivers/video/fbmem.c

static long do_fb_ioctl(struct fb_info *info, unsigned int cmd,

unsigned long arg)

case FBIOPUT_VSCREENINFO:

if (copy_from_user(&var, argp, sizeof(var)))

return -EFAULT;

if (!lock_fb_info(info))

return -ENODEV;

console_lock();

info->flags |= FBINFO_MISC_USEREVENT;

ret = fb_set_var(info, &var);    //struct fb_info info, struct fb_var_screeninfo var

info->flags &= ~FBINFO_MISC_USEREVENT;

console_unlock();

unlock_fb_info(info);

if (!ret && copy_to_user(argp, &var, sizeof(var)))

ret = -EFAULT;

break;

int fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var)

fb_pan_display(info, &info->var);

int fb_pan_display(struct fb_info *info, struct fb_var_screeninfo *var)

if ((err = info->fbops->fb_pan_display(var, info)))

return err;

drivers/video/msm/msm_fb.c

static int msm_fb_pan_display(struct fb_var_screeninfo *var,

struct fb_info *info)

if (info->node == 0 && !(mfd->cont_splash_done)) { /* primary */    /* 如果未上电,给panel上电 */

mdp_set_dma_pan_info(info, null, TRUE);

if (msm_fb_blank_sub(FB_BLANK_UNBLANK, info, mfd->op_enable)) {

pr_err("%s: can't turn on display!\n", __func__);

return -EINVAL;

}

}

mdp_dma_pan_update(info);    /* 这句是把数据通过MDP更新到panel */

drivers/video/msm/mdp_dma.c

void mdp_dma_pan_update(struct fb_info *info)

struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;

mfd->dma_fnc(mfd);

drivers/video/msm/mdp.c

static int mdp_probe(struct platform_device *pdev)

case LCDC_PANEL:

mfd->dma_fnc = mdp_lcdc_update;

drivers/video/msm/mdp_dma_lcdc.c

void mdp_lcdc_update(struct msm_fb_data_type *mfd)

struct fb_info *fbi = mfd->fbi;

uint8 *buf;

int bpp;

bpp = fbi->var.bits_per_pixel / 8;

buf = (uint8 *) fbi->fix.smem_start;

buf += calc_fb_offset(mfd, fbi, bpp);

MDP_OUTP(MDP_BASE + dma_base + 0x8, (uint32) buf);    /* 最终会调到这句,上层抛过来的一堆数据存在buf指针指向的区域,然后

把这个地址写到MDP BASE,然后MDP再写到panel上 */

drivers/video/msm/mdp.h

#define MDP_OUTP(addr, data) outpdw((addr), (data))

drivers/video/msm/msm_fb_def.h

#define outpdw(port, val)      writel(val, port)

------------------------------------------------------------------------------------------

framebuffer还有好多方方面面没提到的,网上一搜一大把,就不提了.我只写些自己认为需要整理的东西,算是做个整理吧.

遗留问题:

addr = alloc_bootmem_align(fb_size, 0x1000)分配的内存怎么与帧缓冲区这个IO内存对应上的?

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

  1. Exynos4412 IIC总线驱动开发(一)—— IIC 基础概念及驱动架构分析 (iic驱动框架,i2c驱动框架)...

    转载于 : http://blog.csdn.net/zqixiao_09/article/details/50917655 关于Exynos4412 IIC 裸机开发请看 :Exynos4412 裸 ...

  2. S3C2440 开发板实战(7):字符设备驱动框架+LED驱动

    在学习驱动的时候我遇到了很多问题,所以我的学习路线是这样的: 编写驱动发现.ko文件需要放入开发板的目录中,然后就学习通过nfs创建共享文件,在配置nfs时发现网络没有连接上,所以就学习怎样配置IP地 ...

  3. 基于驱动框架编写驱动代码

    前言:基于上一个博文对 linux驱动的认知的了解,那么现在开始我们正式来进入学习基于驱动框架来编写驱动代码,那么接下来我们先来看看一个最简单的驱动框架代码 一.字符设备驱动框架代码与应用层代码 驱动 ...

  4. linux驱动框架和驱动代码

    一.linux文件系统:         1.什么是文件系统               文件系统是操作系统用于明确存储设备组织文件的方法. 以上说的方法:就是文件管理系统(程序),简称文件系统   ...

  5. 【实战篇】模块化编程之LCD驱动框架详解

    ID:嵌入式云IOT技术圈 作者:杨源鑫 传送门:[架构篇]嵌入式编程中如何给代码的结构分层 废话不多说,理论讲太多没啥感觉,这些条条框框本质就是基于面对对象的设计模式相关的一些理论,设计模式就是前人 ...

  6. Linux驱动框架之framebuffer驱动框架

    1.什么是framebuffer? (1)framebuffer帧缓冲(一屏幕数据)(简称fb)是linux内核中虚拟出的一个设备,framebuffer向应用层提供一个统一标准接口的显示设备.帧缓冲 ...

  7. Linux内核 LCD 驱动程序框架

    Linux 内核 LCD 驱动程序框架 1. framebuffer 简介 1.1 什么是 framebuffer 1.2 framebuffer的作用 2. framebuffer 驱动的框架 3. ...

  8. STM32MP157A驱动开发 | 04 - Linux DRM显示驱动框架

    Linux中主流的显示框架有两种:DRM框架和FB框架. DRM框架:Direct Rendering Module,可以统一管理GPU显示 FB框架:Frame Buffer,不能处理基于3D加速的 ...

  9. Linux uart驱动框架

    Linux uart驱动框架 串口驱动框架包括两部分 struct uart_driver int uart_register_driver(struct uart_driver *uart); vo ...

最新文章

  1. oracle解析xml字符串命名空间,XML命名空间
  2. COM原理及应用之COM特性
  3. “元宇宙” 是什么东西?
  4. 导致自然语言理解的困难的主要因素是什么?
  5. C#如何让Listbox支持多选
  6. python抓取抖音用户画像,摩羯天蝎居然刷得最多?
  7. vB编程VB源码 VB读取EXCEL工作薄某个表中数据 ADODB.Recordset
  8. office visio 替代_5款替代微软Visio的开源免费软件(转)
  9. 利用计算机及时采集检测数据,计算机基础_课件.ppt
  10. python汉化界面_python如何设置中文界面
  11. 未来十年中国经济十大发展趋势
  12. 麻辣江湖服务器正在维护,7月18日例行维护更新公告
  13. 【Ydui.js】------- JavaScript 判断手机终端 例如:移动终端,苹果终端,ipad 终端 等;
  14. 时钟周期 指令周期 MIPS CPI
  15. c语言解二元二次方程组
  16. Spark CASE WHEN 写法案例
  17. java虚拟机之java堆
  18. Android的ADB
  19. 【npm】npm发布测试(beta)版和正式版
  20. java三个技术平台_java三大技术平台是什么

热门文章

  1. 在Angular应用里使用Redux
  2. SAP ABAP里存在Java List这种集合工具类么?CL_OBJECT_COLLECTION了解一下
  3. 另一种使用SAP SAT事务码对通过浏览器启动的应用的性能测量和分析方式
  4. SAP loyalty management点击了公式超链接后的处理逻辑
  5. campaign read in WebUI - Fiori is correct!
  6. where is document CURRENCY field stored
  7. CL_ABAP_COMPILER - get ID - double click on local variable
  8. Enter Further Contact Person error message
  9. why my pricing procedure is not determined in QHD 504
  10. 今日头条Web HTTP请求的白名单