LCD 原理和移植总结【转】

转自:http://blog.chinaunix.net/uid-22915173-id-329617.html

Framebuffer:是linux的framebuffer驱动在内存开辟的一块显存,存放一帧图像数据
IPU:是mx51的图像处理单元,里面包含DMA控制器和DI显示接口等。
LCDDriver:是一块和LCD屏幕整合在一起的驱动芯 片,接收IPU传过来的数据和时序信号,转化为有规律的LCD驱动电压。

一幅图像的显示过程是这样的:用户打开/dev/fbx设备,使用mmap()系统调用映射framebuffer内存空间到用户空间,用户直接用 memcpy()复制图像数据到framebuffer,DMA探测到framebuffer数据发生变动,启动DMA传输图像数据到IPUI,PU再根 据framebuffer驱动设置的处理模式对像素数据进行一系列处理,比如framebuffer使用了overlay framebuffer那就启动overlay处理单元混合两个framebuffer的数据,另外IPU还会packing像素数据,比如 framebuffer里像素格式为RGB565,IPU会把他packing成RGB666的格式,以配合LCD模块的接口。IPU处理完数据后,送到 DI,在DI时序模块产生的时序信号同步下,一起输出到LCD驱动芯片。

移植LCD驱动的第一步,是确保IPU输出给LCD Driver的时序、数据、供电信号是对的。
时序信号一般是根据LCD的datasheet上的参数,填写fb_videomode这个结构体:

struct fb_videomode {
        const char *name;        /* optional */
        u32 refresh;                /* optional */
        u32 xres;                // x分辨率
        u32 yres;                // y分辨率
        u32 pixclock;                // 像素时钟频率,即每个时钟周期显示一个像素点
        u32 left_margin;        // 行扫描开始脉冲到一行像素数据开始输出的延迟 hsync<==>DEN
        u32 right_margin;        // 一行像素数据输出完毕到下一行的行扫描开始脉冲间的延迟 DEN <==>hsync
        u32 upper_margin;        // 帧扫描开始脉冲到第一行像素数据开始输出的延迟 vsync<==>DEN(1st line)
        u32 lower_margin;        // 最后一行像素数据输出结束到下一帧的那帧扫描开始脉冲间的延迟DEN(last line)<==>vsync
        u32 hsync_len; // 行扫描脉冲宽度,单位为pixclock
        u32 vsync_len; // 帧扫描脉冲宽度,单位为line
        u32 sync; // 各同步信号的极性定义,如hsync、vsync、DEN的极性等。
        u32 vmode; // 显示模式,逐行还是隔行扫描
        u32 flag; // 一般为0
};

这个结构体定义完之后,对于一般的LCD,在连线正确的情况下,系统启动后应该就出来图像了,此时图像可能是上下跳动或者左右有偏移,这就需要再调整一下 fb_videomode中left/right/upper/lower margin参数。如果上电后没有图像,则首先用示波器检测hsync, vsync,DEN,pclk等波形是否正确,使用双踪示波器通过hsync、vsync与DEN的比对查看left/right/upper /lower margin是否合适。如果这些信号都没有问题,那么说明LCD需要通过spi总线发送命令对其进行初始化。初始化代码一般由LCD厂商提供,不过很多厂 商提供的初始化代码都有问题,会导致LCD白屏或者其他不正常的现象。

TFT LCD的原理

图2. TFT LCD截面图

TFT LCD主要由两个透明电极,中间的液晶分子和一个有色玻璃组成。在没有通电的情况下,液晶分子呈无规则排列,背光无法透过液晶层。当有外加电场时,液晶分 子顺着电场的方向有序排列,背光可以通过,并且由于有色玻璃的滤光,呈现红,绿,蓝色调,不过,背光的透过率只有10%,这是LCD的一个缺点。

以上是一个像素中的一个RGB分量的产生过程。接下来看看如何整合这个基本单元,组成一个LCD屏幕。

图3. LCD平面图

这个图比上面多出来的是2种长条和一种MOS晶体管。这3个东西的作用是在一定的时序下给各显示电极充电。横向的长条和LCD驱动芯片的Gate Driver连接的,用于打开各行的MOSFET。纵向的长条和LCD驱动芯片的Source Driver连接,代表RGB数据。整个过程大致是这样的:首先第一行的Gate线产生一个充电脉冲,使第一行的MOS管导通,同时Source线那边经 过数模转换后的RGB电压也已经就绪,于是通过MOS管对显示电极充电,每个pixel clock充电一个像素,即3根Source线完成充电。对于320x480的屏,一共有480根Gate线,320x3=960根Source线,则经 过320个pclk后,第一行充电完成,显示出相应的画面。然后,第二行的Gate线产生一个充电脉冲,一次类推,直到最后一行,又从第一行开 始.....

图4. LCD基本结构

图4. LCD传输分解

图5. LCD基本单元图

图6. LCD阵列图

图7. LCD信号图

图8. LCD整体框图

LCD点屏步骤:
1.参考LCD datasheet修改fb_videomode结构体的参数。
2.配置GPIO,点亮LCD背光。
3.参考LCD datasheet看这个LCD是否需要spi总线发送命令进行初始化,一般厂商给datasheet时也会给一份初始化代码,不过有些参数是错误的,需 要调整,发送不正确的命令会导致LCD白屏。
4.用示波器测试从LCD控制器出来的Hsync, Vsync, DE, PCLK是否正确,用万用表测量Vio, Vci是否正常。
5.有的LCD Driver需要LCD控制器发出一个CS片选使能信号。
6.用万用表测量LCD的栅压是否正常,一般为9.2V。
7.如果上述步骤后还出不来,再检查LCD初始化命令是否正确,spi时序是否符合。

图像异常处理:
1.驱动问题
上下抖动,左右没对齐:调整left/right/upper/lower margin值
2.LCD初始化命令问题
有纹波:调整VDD/AVDD/VGL/VGH电压
色彩失真:看LCD的RGB模式设置和LCD控制器出来的RGB模式是否一致

本次点屏过程:
0. 非常感谢张同学和梁同学在本次点屏中所作的关键性工作。
1. 在mx51_kernel的mxcfb_epson_vga.c的fb_videomode结构体中修改了时序参数,上电,LCD无任何反应
2. 张同学在mx51_3stack_gpio.c中通过配置GPIO NANDF_CS6 打开了LCD背光灯,LCD产生白屏闪动现象,并在mxcfb_epson_vga.c的lcd_init()中加入了ilitek提供的初始化命令。
3. 梁同学在mx51_3stack_gpio.c中通过配置MX51_PIN_DI1_D1_CS ,使其一直拉低,提供了LCD Driver芯片的片选使能,并测量出upper margin和lower margin时序有偏移,经过调整此2值,消除了IPU error。
4. 去掉3条冗余的LCD初始化命令,LCD点亮。
5. 对于本次调屏,以上步骤都是必要的,也是充分的

kernel 文件修改:
1.driver/video/mxc/mxcfb_epson_vga.c
(1).static struct fb_videomode video_modes[] 改为:

  1. static struct fb_videomode video_modes[] = {
  2.         {
  3.                 /* 320x480 @ 60 Hz */
  4.                 "Elite-HVGA", 60, 320, 480, 86566, 20, 40, 5, 1, 10, 2,
  5.                 FB_SYNC_CLK_LAT_FALL,
  6.                 FB_VMODE_NONINTERLACED,
  7.                 0,},
  8. };

复制代码

(2).static void lcd_init(void)改为:

  1. static void lcd_init(void)
  2. {
  3.         u16 i;
  4. const u16 cmd[] = {
  5.           0x11,
  6.           0xD0, param(0x07), param(0x41), param(0x0F),
  7.           0xD1, param(0x00), param(0x3E), param(0x1F),
  8.           0xD2, param(0x01), param(0x10),
  9.           0xC0, param(0x00), param(0x3B), param(0x00), param(0x02),
  10.                 param(0x11),
  11.           0xC5, param(0x02),
  12. //          0xC6, param(0x1B),
  13.           0xC6, param(0x02),
  14.           0xC8, param(0x66), param(0x66), param(0x66), param(0x66),
  15.                 param(0x0E), param(0x1E), param(0x66), param(0x66),
  16.                 param(0x77), param(0x66), param(0x0F), param(0x0F),
  17.           0x36, param(0x0A),    // set_address_mode, RGB order
  18.           0x3A, param(0x66),        // 0x60: RGB=666; 0x50: RGB=565; 0x10: RGB=111
  19.           0xB4, param(0x11),
  20.           0x29,
  21.           0x2C
  22. };
  23.         if (lcd_spi) {
  24.                 spi_write(lcd_spi, (const u8 *)cmd, ARRAY_SIZE(cmd));
  25.         } else {
  26.                 for (i = 0; i < sizeof(cmd) / 2; i++)
  27.                 {
  28.                         ipu_disp_direct_write(DIRECT_ASYNC1, cmd[i], 0);
  29.                 }
  30.                 msleep(1);
  31.                 ipu_uninit_channel(DIRECT_ASYNC1);
  32.         }
  33. }

复制代码

2.arch/arm/mach-mx51/mx51_3stack.c

  1. static struct mxc_lcd_platform_data lcd_data = {
  2.         .core_reg = "VIOHI",
  3.         .io_reg = "SW4",
  4.         .reset = lcd_reset,
  5. };

复制代码

改 为

  1. static struct mxc_lcd_platform_data lcd_data = {
  2.         .core_reg = "VSD",
  3.         .io_reg = "SW4",
  4.         .reset = lcd_reset,
  5. };

复制代码

3.arch/arm/mach-mx51/mx51_3stack_gpio.c
void gpio_lcd_active(void)修改为:

    1. void gpio_lcd_active(void)
    2. {
    3.         mxc_request_iomux(MX51_PIN_NANDF_CS6, IOMUX_CONFIG_ALT3);
    4.         mxc_set_gpio_direction(MX51_PIN_NANDF_CS6, 0);
    5.         mxc_set_gpio_dataout(MX51_PIN_NANDF_CS6, 1);
    6.         mxc_request_iomux(MX51_PIN_DI1_D1_CS, IOMUX_CONFIG_ALT4);
    7.         mxc_set_gpio_direction(MX51_PIN_DI1_D1_CS, 0);
    8.         mxc_set_gpio_dataout(MX51_PIN_DI1_D1_CS, 0);
    9.        
    10.         mxc_request_iomux(MX51_PIN_DI_GP2, IOMUX_CONFIG_ALT0);
    11.         mxc_request_iomux(MX51_PIN_DI_GP3, IOMUX_CONFIG_ALT0);
    12. }
时间: 2024-09-23 12:06:51

LCD 原理和移植总结【转】的相关文章

FL2440 Linux kernel + yaffs2根文件移植过程(一)

本文全过程为自己亲自试验,成功移植了一个最基本功能的Kernel.根文件系统,现在将这个一耗时.耗精力 的过程写下来,希望对遇到相同问题的朋友们有所帮助! 平台:飞凌FL2440             windows xp sp2             vmware 6.5.build-203739              ubuntu 9.10              交叉编译器: 4.3.2              内核:linux-2.6.28.7.tar.bz2        

嵌入式Linux支持LCD console【转】

转自:http://blog.sina.com.cn/s/blog_664c545f0100v9zl.html 转载:http://www.mculee.cn/post/48.html     [1]LCD 驱动基础知识 Linux- 2.6.32.2 内核已经支持S3C2440 的LCD 控制器驱动,但在此我们先介绍一下关于2440 LCD 控制器以及驱动相关的LCD 的一些基础知识.注意:在此我们只讨论 TFT LCD,也就是真彩屏.LCD 驱动中最关键的就是时钟频率(Clock frequ

安卓修炼之路必要要知道的要求和建议

偶然在一个群中看到有人转发了这篇文章,感觉写得真不错,所以转发下来.向大师学习! (一)成为Android高手必须掌握的8项基本要求 [1] Android操作系统概述 1. Android系统架构.            2. Android利用设计理念.            3. Android 开源知识.            4. Android 参考网站与权威信息.[2] Android SDK及其开发环境搭建            1. Android SDK的版本发布.     

显示器如何正确的摆放

在电脑前工作是一种坐着的生活方式,这就意味着肌肉在工作时没有得到锻炼.这种坐着的生活方式最易让颈和背部受到损伤.如果办公人员工作安排的不合理,情况会更加糟糕. 很重要的一点是:上班族应该安装可调节的显示器.这样的显示器经过调整,能适应每个人不同的生理特征.还可以朝任何方向转动,其高度和显示器曲度也可随意调整. 如果显示器稍微偏左,就会使得左边的颈部肌肉紧绷,而右边的肌肉得到伸展.这种失衡会导致头部右偏.所以,办公室的电脑显示器必须依正中线放置.换句话说,显示器必须直接放在键盘的后边,因为键盘的中

《嵌入式Linux开发实用教程》——导读

前言 嵌入式Linux开发实用教程 2012年11月,当我看到论坛中的同龄大学生在学习嵌入式Linux寸步难行,我就计划将我学习嵌入式Linux的点点滴滴记录下来,从一个学生的角度去写,或许更能让初学者接受.2013年1月,当写完初稿再重新审视的时候,总感觉不尽如意.2013年3月,我联系了我的师弟李强,两人打算以一个全新的思维重新完成这本书. 2013年6月,书稿终于定型. 本书一共有6章,从Linux指令基础到Linux常用软件:从U-Boot移植到Linux移植:从Linux驱动程序设计到

AM335x(TQ335x)学习笔记——LCD驱动移植

TI的LCD控制器驱动是非常完善的,共通的地方已经由驱动封装好了,与按键一样,我们可以通过DTS配置完成LCD的显示.下面,我们来讨论下使用DTS方式配置内核完成LCD驱动的思路. (1)初步分析 由于TQ335x使用的芯片是AM335x,故仍然可以参考am335x-evm.dts.当然,am335x-evmsk.dts.am335x-beagbone.dts都可以.本文以am335x-evm.dts为例.大体上浏览下DTS文件,可以发现两个醒目的节点:一个是panel,一个是backlight

[lcm] MTK平台移植屏幕lcd过程要点

下拉项目和编译 参考吴庆亚添加LCM驱动 编译生成对应数据 为87工模添加lcm节点信息 TP fl10802 LCM himax_852xES 从单屏到多屏兼容 下拉项目和编译 [W5900] $ git clone ssh://172.16.16.15:29418/mtk_repository/MTK6580_WEG_L1_MP6.V2.19 $ git checkout -b MMI_W5900 origin/MMI_W5900 $ git pull $ source build/envs

LCD的移植

移植LCD这个非常的辛苦,希望读者要多加尝试,以至于能够完全理解其中的奥秘. 在嵌入式linux上移植LCD(这里指彩色点阵式LCD)的驱动,通常说来,并不是很困难的事.最简单的方法,就是找到linux中,现有的LCD驱动的参数设置的代码,直接修改参数即可.复杂点的方法,就要添加LCD驱动相关的结构体,设备描述,等.但不管怎么样,LCD的参数设置是最终肯定要面对的问题. 以下,就把LCD的参数设置的方法说明一下. 首先,参数设置设置的是什么?其实就是LCD屏的工作频率,垂直扫描频率,撗向扫描时间

[lcm] Qualcomm平台的显示屏lcd驱动移植步骤

1lk部分 1-1 target_displayc 1-2 oem_panelc 1-3 panel_innont51021b_1200p_videoh 2Kernel 2-1 dsi-panel-boent51012_1200_videodtsi 2-2 msm8953-mdss-panelsdtsi 2-3 msm8953-mtpdtsi 更多相关文章: <高通Qualcomm平台lk(light kernel)启动流程1--aboot_init()之前>: http://blog.csd