第六章--LCD驱动移植


6.1 认识LCD相关硬件原理
    LCD显示屏相关参数,如何设置参数,如何根据型号编写驱动
    6.1.1 概述
        0)    显示汉字,字符,图形
            低压,低功耗,体积小,重量轻,超薄
        1)  根据物理结构:扭曲向列型(TN-LCD),超扭曲向列型(STN-LCD),双层超扭曲向列型(DSTN-LCD)
                          薄膜晶体管型(TFT-LCD)
                          前三种显示原理相同,只是液晶分子扭曲角度不同,
                          TFT-LCD采用完全不同的显示方式
        2)  常用参数    
                    1]PPI(Pixel Per Inch)每平方英寸像素数目,PPI与显示密度,拟真度,显示效果正相关,目前市场TFT都是100PPI
                    2]分辨率 :VGA ,SVGA,UXGA SXGA+,SXVGA+为1400x1050
                              XGA:1280x1024
                              Quad-VGA:1280x960
                    3]BPP(Bit Per Pixel) 每个像素使用多少位表示颜色,例如黑白色只用1bit
                                         4阶灰度2bit(2BPP)表示一个点,对于256色要用8bit(8BPP)表示一个点
        3)  显示原理
                    内存显示完整图像,采用CRT显示器概念,一幅画像称为一帧,一帧由多行排列组成,每行由多个像素组成,每个像素色彩由若干位数据表示,单色显示器每个像素用1位即1BPP
                            256色显示器每个像素使用8位表示即8BPP
                    显示器从屏幕左上方开始一行一行取得单个像素数据并显示,显示到最右时,跳下一行知道现实所有重新调到左上方即Z字形扫描
                    同时使用帧扫描和行扫描信号
    6.1.2 控制器:
                  1.控制时序和信号,从而驱动LCD。
                  2.用户只需通过读写LCD控制器的一些列寄存器完成配置。
                  3.用户需要显示的内容都是LCD控制器从帧缓冲区读取,然后发送到LCD控制器进而显示在屏幕
                  4.新的处理器都集成了LCD控制器,如S3C2440等
                  5.S3C2440的LCD控制器由一个逻辑单元组成,它把LCD图像数据从系统内存的buffer传到外部LCD驱动器。LCD控制器使用基于时间的像素都懂算法和帧速率控制思想,支持单色,2-bit per pixel(4级灰度)或者
                    4-bit-pixel(16级灰度)屏,并可与256色(8BPP)和4096色(12BPP)彩色STN-LCD连接
                  6.LCD控制器还支持1BPP,2BPP,4BPP,8BPP的调色板TFT彩色屏,并支持64K色(16BPP)和16M(24BPP)非调色板真彩色显示,根据编程满足不同需求例如单向像素数,数据线宽度,接口时序,刷新速率等
    6.1.3 LCD控制器方块图
                ****************插入图像*******************

                 第六章--LCD驱动移植_第1张图片
                1.根据工作原理LCD控制器接口时序分为STN和TFT两种,根据实际需要对控制器进行不同设置产生不同时序
                2.LCD控制器中控制信号有VFRAME,VLINE,VCLK和VM等
                3.S3C2440作为视频数据的数据端口,是VD[23:0].
                4.LCD控制器由REGBANK,LCDCDMA,VIDPRCS,TIMEGEN和LPC3600等组成
                5.REGBANK:17个可编程寄存器组和一块256x16调色板内存组成,配置LCD控制器
                6.LCDCDMA:专用DMA,自动把内存中视频数据传到LCD驱动器,在CPU不干预情况下显示在LCD屏。
                7.VIDPRCS:接收LCDCDMA的数据,并转换为合适的数据格式,例如4/8位扫描,4位双扫显示模式,然后通过数据端口VD[23:0]传送数据到LCD驱动器
                8.TIMEGEN:1]可编程逻辑组成,支持不同LCD驱动器接口时序和速率需求
                          2]可产生VFRAME,VLINE,VCLK和VM等时钟信号
            
                9.数据流描述
                        LCDCDMA中存在FIFO存储器。如FIFO空或部分空,LCDCDMA请求从存储器取得数据,(每个突发请求,连续读4个字(16bytes),在总线传输中,不匀速总线控制权交给另一个总线)用突发的存储传输模式取得数据
                        传输请求被存储控制器总线仲裁器接收后,产生连续4个字数据传输control系统内存到内部的FIFO(12个FIFOL和16个FIFOH组成的28个字),
                        S3C2440用2个FIFO支持双扫显示模式,如单扫模式,只有一个FIFO会用到
                        
    6.1.4 控制器操作(STN和TFT两种)
                    视频数据在内存中存储方式:
                        RGB三色组成单个像素色彩。也就是三基色
                    1.24BPP显示使用24位表示一个像素点,每种颜色8比特,LCD控制器从内存获得某个像素的24位颜色值,然后通过VD[23:0]数据线发送LCD驱动器,像素值与VD[23:0]引脚的对应关系
                    ******************************插入图片像素值与VD映射关系***********************

                    第六章--LCD驱动移植_第2张图片
                    2.16BPP
                     3.8BPP
                    4.256色调色板
    6.1.5 LCD控制寄存器
                    17个控制寄存器,包括LCDCON1-LCDCOON5,LCDSADDR1-LCDSADDR3等
6.2 LCD参数设置
        根据LCD屏正确设置对应的LCD寄存器参数
        1]设置VFRAME,VLINE(根据液晶屏尺寸和显示木事设置),他们对应LCDCON2寄存器的HOZVAL和LINEVAL值
              HOZVAL=(水平尺寸/VD数据位)-1
              彩色液晶屏,水平尺寸=3x水平像素点数
              VD数据位=BBP数(不分单双扫描)
              LINVAL=垂直尺寸-1(单扫描)
              LINVAL=垂直尺寸/2-1(双扫描)
         2]设置VCLK:直接由系统总线(AHB)工作频率HCLK直接分频得到
              VCLK=HCLK/((CLKVAL+1)*2)
         3]帧速率:即VSYNC信号频率。帧速率与VSYNC,VBPD,VFPD,LINEVAL,HSYNC,HBPD,HFPD,HOZVAL和CLKVAL的域有关
              他们是LCDCON1/2/3/4。大多数LCD驱动器需要他们合适的帧速率。
              帧速率公式:
              Frame Rate = 1/[{(VSPW+1)+(VPBD+1)+(LINEVAL+1)+(VFPD+1)}*{(HSPW+1)+(HBPD+1)+(HFPD+1)+HOZVAL+1}*{2*(CLKVAL+1)/HCLK}]
               VSPW,VBPD,VFPD,HSPW,HBPD,HFPD参考LCD屏幕手册

6.3 内核LCD驱动机制
        Linux提供的驱动:帧缓冲(FrameBufer)设备驱动程序。实际工作只需在显示缓存中填写要显示的数据,屏幕即可显示
                        驱动得到显示缓存的地址,即可操作它
    6.3.1 FrameBufer概述
            1. 从Linux2.2.x提供的驱动程序接口
            2. 把显示设备抽象为帧缓冲区设备,为图像设备提供抽象化处理,代表了一些视频设备。
            3.允许APP通过定义明确界面访问图像硬件设备。软件无序了解任何硬件底层驱动内容
            4.FB允许app在图形模式下直接对显示缓冲区读写和IO控制等
            5.通过专门的设备结点对相应的设备进行访问,如/dev/fb0,app可将其视为显示内存的引用,将其映射到进程地址空间后,就可读写,读写可反映到具体的LCD设备
            6.FB驱动支持控制台的字符显示。linux2.4种与FB控制台相关的在fbcon和其他相关目录。linux2.6放在drivers/video/console中,涵盖各种格式显示缓冲的字符输出,字体定义文件,简化FB控制台驱动程序移植
    6.3.2 FB设备驱动结构
          FB设备驱动基于两个文件 linux/include/linux/fb.h和 linux/drivers/video/fbdev/core/fbmem.c 其中fb.h定义FB驱动所需的几乎所有结构体,
          包括struct fb_info,struct fb_var_screeninfo 和struct fb_fix_screeninfo。
            1.struct fb_info
                1]记录帧缓冲全部信息,包括设置参数、状态、操作函数指针等
                2]每个帧缓冲设备都由一个struct fb_info描述,所有参数都是面向特定设备,工程师就是填写这些数值。
                3]fb_info也是FB相关结构唯一在内核空间可见的,用户可通过ioctl()操作设备,这个结构体就是用于支持ioctl()的这些操作的
            2.fb_var_screeninfo:
                1]记录帧缓冲设备和指定显示模式的可修改信息。
                2]包括显示屏分辨率,像素比特数,一些时序变量。
                3]变量xres定义一行所占像素数目,yres定义一列所占像素数目,bits_per_pixel定义每个像素所需位数
                4]参数都可通过应用程序设置
                5]通过fb_opt实现
            3. fb_fix_screeninfo:
                1]定义硬件不可变属性,显示缓冲区映射地址的定义
                2]缓冲区不应该被APP改变
                
            4. fbmem.c linux/drivers/video/fbdev/core/fbmem.c
                1]是FB设备驱动关键,为上层应用提供系统调用,为下层特定硬件驱动提供编程接口
                2]底层硬件驱动乣用到这里的接口来向系统内核注册它们自己。
                3]fbmem.c为所有支持FB的设备驱动提供通用接口,避免重复的工作
                4]用户只需针对fbmem.c提供的底层驱动接口函数分别实现即可,也就是fb.h中的structfb_ops函数指针组
                5]fbmem.c实现register_framebuffer和unregister_framebuffer,提供给下层FB驱动的接口。底层设备驱动所要做的事情就是填充fb_info结构并想系统注册或注销
                
                
6.4 内核现有LCD驱动源码分析
        内核现有LCD驱动再针对具体型号和硬件资源修改
        6.4.1 主要工作:初始化函数的编写和填充fb_info结构体的主要成员函数
            1.编写初始化函数
                1]编写初始化函数,初始化LCD控制器寄存器,通过写寄存器设置显示模式和颜色数,然后在内存中分配LCD显示缓冲区。linux中可用kmalloc()分配连续空间
                2]缓冲区大小:点阵行数*点阵列数*用于表示一个像素的比特数/8.
                3]缓冲区通常分配在片外SDRAM(容量大),起始地址保存在LCD控制器
                4]本节LCD显示方式:320*240 ,16位彩色,需要分配显示缓冲区:320*240*2 = 150kb
                5]初始化fb_info结构体,填充成员变量,调用register_framebuffer(&fb_info)将fb_info注册入内核
            2.编写成员函数
                1]嵌入式系统只需要实现fb_ops中的 fb_get_fix fb_get_var ,fb_set_var三个函数
                2]应用程序对设备ioctl系统调用时会调用他们
                3]fb_get_fix通过fb_fix_screeninfo获取系统当前状态对成员变量赋值,主要是smem_start,smem_len,最终返给应用程序。
                4]fb_set_var函数传入参数是fb_var_screeninfo,需要对xres,yres和bit_per_pixel赋值
            3.对于/dev/fb 主要操作
                1]读写/dev/fb 等于读写屏幕缓冲区 
                2]映射操作(map):因linux工作在保护模式,每个应用都有自己的虚拟地址空间,应用不能直接访问物理缓冲区地址,故通过mmap()
                  操作file_operations结构,可将文件内容映射到用户空间。帧缓冲设备则可通过映射操作,可将屏幕缓冲区的物理地址映射到用户空间一段虚拟地址之内,之后用户就能通过读写此段虚拟地址访问屏幕缓冲区,在屏幕上绘图
                3]IO控制:帧缓冲设备对设备文件的ioctl操作可读取/设置显示设备及屏幕参数(分辨率,显示颜色数和屏幕大小等)。ioctl由底层硬件驱动完成。
                    一般步骤:1.打开 /dev/fb设备文件;
                             2.用ioctl()取得当前屏幕参数(分辨率,像素比特数)
                             3.根据屏幕参数计算屏幕缓冲区大小
                             4.将屏幕缓冲区映射到用户空间
                             5.映射后可直接读取屏幕缓冲区,进行绘图和显示
        6.4.2 s3c2410fb_init()函数分析
                1.只包含了platform_driver_register()调用,参数&s3c410fb_driver,即向内核注册一个platform设备驱动,该设备是LCD设备
                2.platform两个重要数据结构:platform_device和platform_driver(include/linux/platform_device.h)
                3.LCD驱动(drivers/video/s3c2410fb.c)有platform_driver结构体
                    static struct platform_driver s3c2410fb_driver = {
                        .probe = s3c2410fb_probe, //初始化函数,
                        .remove = s3c2410fb_remove,
                        .suspend = s3c241fb_suspend,
                        .resume = s3c2410fb_resume,
                        .driver = {
                            .name = "s3c2410-lcd", //设备名字,名字一定要和struct platform_device中的name域一致才能把平台驱动和前面定义平台数据联系起来
                            .owner = THIS_MODULE,
                        },        
                    };
        6.4.3 s3c2410fb_probe()函数分析
                1.关键函数
                    s3c2410fb_info:描述整个LCD驱动的结构体,驱动自己定义的设备数据结构,记录s3c2410fb驱动所有信息
                    s3c2410fb_display:定义了LCD规格和时序
                    fb_info:framebuffer的设备数据结构,表示一个显示设备,probe最终填充并向内核注册
                    s3c2410fb_mach_info:描述LCD初始化时所用的值,包含LCD控制器的GPIO,用来设置引脚的功能,和平台有关
                        所在目录:arch/arm/plat-samsung/include/plat/fb-s3c2410.h;
                    Resource:指向设备用到的IO资源,是平台驱动的结构
                    irq:保存中断号。
                    
                2.函数执行步骤
                    1.获得平台数据
                    2.如果mach_info为NULL,则整个驱动程序退出
                    3.查找当前显示屏规格,此规格定义在mach-smdk2440.c文件
                    4.获取设备中断号,中断号也在mach-smdk2440.c文件中定义的硬件所使用到的中断资源
                    5.向内核申请一段sizeof(struct s3c2410fb_info)+size的空间,size:设备私有数据空间,
                    6.fb_info的par指向该私有空间
                    7.设置驱动数据并填充驱动数据
                    8.映射内核资源(IO口,中断号,平台数据不定期传递来的硬件资源地址都是物理地址,内核访问硬件都是虚拟地址,故用相关函数映射物理地址为虚拟地址),映射失败退出程序
                    9.关闭显示器,对fbinfo赋值
                    10.申请中断并打开LCD时钟,使得各个LCD相关引脚输出信号。
                    11.显示内存容量并映射DMA资源,上层应用存储要显示的图像到此内存区,LCD控制器通过DMA从映射内容取出图像
                    12.初始化各个LCD控制寄存器,注册fbinfo,并为该设备创建一个sysfs中的属性
                    13.pdev->dev.platform_data的初始化,内核启动init进程前,会执行smdk2410_map_io函数,次函数中加入s3c24xx_fb_set_platdata(&smdk2410_lcd_platdata)
                       arch/arm/plat-samsung/devs.c 
                     
                     
                3.s3c2410fb_init_registers
                    1.保存本地中断
                    2.修改处理器GPIO工作方式
                    3.初始化LCD控制寄存器
                    4.让处理器的LCD控制器三地址寄存器指向正确位置,也就是LCD缓冲区,参考用户手册
                    5.打开video,因为probe中关闭了
                    
        6.4.4   s3c2410fb_init_remove:移除设备,释放资源(内存空间,中断线等)
                    1.获得fb_info信息
                    2.得到私有数据
                    3.停止LCD控制器
                    4.该函数释放缓冲区,停止时钟
                    5.得到中断线并释放
                    6.释放内存空间
                    7.想内核注销该帧缓冲
                    
                    
6.5 移植内核中的LCD驱动
        不同开发人员设计同一种设备都具备独特性,例如访问硬件资源对应的端口地址,故驱动移植首先要明确驱动的硬件设备连接情况
        然后对驱动源码进行适应具体硬件修改
        
        6.5.1 LCD硬件电路图
              1.LCD的像素同步时钟信号,水平同步信号,垂直同步信号直接连接到LCD的VCLK,VLINE和VFRAME
              2.GPG4作为LCD电源信号直连到LCD_PWREN
                ************插入电路图**********************

            第六章--LCD驱动移植_第3张图片
        6.5.2 修改源码
        6.5.3 配置内核
                1.make menuconfig
                2.devices drivers -> Graphics support-> Support for frame buffer devices
                3.在驱动程序调试阶段最好选中S3C24010 LCD debug messages
                4.增加开机logo,选择bootup logo
                
6.6总结
    分析LCD控制寄存器硬件操作,内核中自带的LCD驱动源程序基础讲述LCD移植,
    内核中FB驱动的体系结构,如何操作LCD控制器
    中断FB数据结构掌握

你可能感兴趣的:(第六章--LCD驱动移植)