码迷,mamicode.com
首页 > 其他好文 > 详细

展讯sc7731 LCD驱动简明笔记之二

时间:2016-01-03 18:06:36      阅读:1416      评论:0      收藏:0      [点我收藏+]

标签:

此篇笔记基于sc7731 - android 5.1,对lcd的framebuffer做一个简明笔记。
一共分为两大部分:第一部分,关于LCD的硬件方面的;第二部分,关于lcd核心处理(framebuffer)部分的。

第一部分,LCD硬件相关的

一、液晶
液晶是一种高分子有机材料。当给它加上直流电场后,原本有序的分子排列被打乱,一部分液晶变得不透明,颜色加深,便因此显示出字符和图形。
液晶的光电效应:干涉、散射、衍射、旋光、吸收等。

二、LCD种类
1. 构造: 使用两块玻璃板夹着一块液晶:一块玻璃板上设置薄膜晶体管(TFT);另一块玻璃板上放置彩色滤光片
----当改变TFT上的电信号和电压时,会改变液晶内部分子的转动流向,根据光学原理,从而控制每个像素点是否显示。
2. 种类
(1) STN : Super Twisted Nematic
在传统单色STN液晶显示器上加一彩色滤光片,并将单色显示矩阵中的每一像素分成三个子像素,分别通过彩色滤光片显示红、绿、蓝三基色,就可显示出彩色画面。
其功耗小、极度省电、可显示65536种色彩,一般功能机上或者低配智能机上不二选择。

(2) UFB: Ultra Fine Bright
三星手机的专用彩色显示屏技术。在设计上UFB采用了特别的光栅设计,可减少像素间距,以获得更佳的图像质量。
减小像素间距,以获得更佳的图像质量;可显示65536种色彩,能够达到128×160像素的分辨率;对比度是STN液晶显示屏的两倍;耗电量低于TFT。

(3) TFD: Thin Film Diode
是TFT和STN的折中,有着比STN更好的亮度和色彩饱和度,却又比TFT更省电。为LCD上每一个像素都配备了一颗单独的二极管来作为控制源。
高画质、超低功耗、小型化、动态影像的显示能力以及快速的反应时间。采用图像处理技术可以显示相当于26万色的图像。

(4) TFT: Thin Film Transistor
每个液晶像素点都是由集成在像素点后面的薄膜晶体管来驱动,具有高响应度、高亮度、高对比度等优点。
是各类笔记本电脑和台式机上的主流显示设备,中高端彩屏手机中分65536 色、16 万色,1600万色三种。

(5) OLED: Organic Light-Emitting Diode
OLED显示器很薄很轻,因为它不使用背光。
该类LCD广泛用于各种嵌入式设备。并且可实现高度可携带、折叠的显示技术。

三、LCD技术参数
从技术参数开始,驱动软件就必须要开始关注了。从这里开始,驱动软件要开始对lcd硬件相关部分进行描述和处理。怎么描述? 一个C语言的结构体足以。
(1) 可视面积
(2) 可视角度
(3) 点距
(4) 色彩度
(5) 对比值
(6) 亮度值
(7) 响应时间

四、LCD时序图
LCD 显示出一副图片,是从上到下、从左到右刷出来的。其显示过程,通过以下时序图进行描述。
技术分享


外部引脚信号(通过示波器可量到的)
VSYNC: 帧同步信号,表示扫描1帧的开始,一帧也就是LCD显示的一个画面 --- 竖直方向。
HSYNC: 行同步信号,表示扫描1行的开始。 --- 水平方向。
VDEN: 数据使能信号。
VD[23:0]: LCD像素数据输出端口。
VCLK: 像素时钟信号。

寄存器参数
VSPW: 帧同步信号的脉宽,单位为1行(Line)的时间。 --- vsync_len
HSPW: 行同步信号的脉宽,单位为1VCLK的时间。 ---hsync_len

VFPD: 帧同步信号的前肩,单位为1行(Line)的时间。就是一帧图像结束后,在下一帧图像开始信号之前的无效行数。 ---lower_margin
VBPD: 帧同步信号的后肩,单位为1行(Line)的时间。就是一帧图像开始时,帧同步信号无效的行数。 ---upper_margin

HBPD: 行同步信号的后肩,单位为1VCLK的时间。就是水平同步信号开始位置到有效数据开始位置之间有多少个VCLK。 ---right_margin
HFPD: 表示一行的有效数据结束到下一个水平同步信号开始之间的DCLK的个数。---left_margin

LINEVAL: 帧显示尺寸-1,即屏行宽-1,对于800*480分配率的LCD屏,那么LINEVAL=480-1=479,也就是LCD屏显示一帧数据所需要的行的数目.
HOZVAL: 行显示尺寸-1,即屏列宽-1,对于800*480分配率的LCD屏,那么HOZVAL=800-1=799,请记住,是屏列宽,也就是LCD屏显示一行数据所需要的像素(pixel)的数目

说明:
当要显示一副图片时,LCD控制器要先发送一次VSYNC信号;然后会根据图片的组成行数,发送N个 HSYNC 和 VCLK 信号---显然,每一行开始,都会发送HSYNC信号;而每一行内部的每个像素点,都需要一个VCLK信号。

怎么理解VBPD & VFPD & HBPD & HFPD?
可以将LCD的扫描看成是一把电子枪从左上角到右下角的喷射。
当帧同步信号发出来后,它需要一个时间段,有效数据才能从枪里面喷出来。这个有效数据喷出的时间点和帧同步信号发出的时间点,中间有一个时间差值。 ---VBPD
同样的,当一副图片结束后,电子枪可能还需要一段时间才能停止工作,于是在这个有效数据结束的时间点,到电子枪完全停止工作的时间点,中间又是一个时间差值。(当然,电子枪未必会停止工作,它可能会继续发一个帧同步信号,开始刷新下一副图片) ---VFPD

那么水平同步信号也是一样的,每一行的最左端,它有一段时间是没有喷有效数据的;而每一行的最右端,也有一段时间是没有喷有效数据的。于是这里就形成了HBPD 和 HFPD。
如果用肉眼自行看手机屏幕的四边,会发现,手机屏幕的图片,似乎是镶嵌入LCD一样---有一个极细极细的黑边框。而这,就是因为上面四个寄存器参数设置的结果。

第二部分,LCD 驱动软件相关的
何谓帧缓冲?何谓缓冲?
简而言之,缓冲就是一个buffer,一个暂存数据的内存buffer区域;那么帧缓冲,就是一个用户暂存一帧图片的buffer。它不神秘,操作起来非常方便。
当用户需要显示一幅图片时,仅仅需要把该幅图片的具体内容放入该缓冲区即可。操作系统会负责将该幅图片搬运到lcd屏幕上。
framebuffer的概念来源于Linux。在linux中,framebuffer驱动设备被划分为字符设备,设备名: /dev/fbN (N取值范围0~31)

一、Framebuffer测试程序(关键代码)

 1 #include <unistd.h>
 2 #include <stdio.h>
 3 #include <fcntl.h>
 4 #include <linux/fb.h>
 5 #include <sys/mman.h>
 6 
 7 int main()
 8 {
 9     int fbfd = 0;
10     struct fb_var_screeninfo vinfo;
11     struct fb_fix_screeninfo finfo;
12     long int screensize = 0;
13     char *fbp = 0;
14     int x = 0, y = 0;
15     long int location = 0;
16 
17     // 以读写方式打开fb0
18     fbfd = open("/dev/fb0", O_RDWR);
19     if (!fbfd) {
20         printf("Error: cannot open framebuffer device.\n");
21         exit(1);
22     }
23     printf("The framebuffer device was opened successfully.\n");
24 
25     // 获取硬件屏幕信息
26     if (ioctl(fbfd, FBIOGET_FSCREENINFO, &finfo)) {
27         printf("Error reading fixed information.\n");
28         exit(2);
29     }
30 
31     // 获取用户可修改屏幕参数信息
32     if (ioctl(fbfd, FBIOGET_VSCREENINFO, &vinfo)) {
33         printf("Error reading variable information.\n");
34         exit(3);
35     }
36 
37     printf("%dx%d, %dbpp\n", vinfo.xres, vinfo.yres, vinfo.bits_per_pixel );
38 
39     // 计算framebuffer空间大小,也就是可装下一幅图片的大小
40     screensize = vinfo.xres * vinfo.yres * vinfo.bits_per_pixel / 8;
41 
42     //  内存映射,把一块内存区域从内核映射到用户空间,供用户直接操作
43     fbp = (char *)mmap(0, screensize, PROT_READ | PROT_WRITE, MAP_SHARED,
44                        fbfd, 0);
45     if ((int)fbp == -1) {
46         printf("Error: failed to map framebuffer device to memory.\n");
47         exit(4);
48     }
49     printf("The framebuffer device was mapped to memory successfully.\n");
50 
51     x = 100; y = 100; // Where we are going to put the pixel
52 
53     // 绘制矩形, 200x200像素的
54     for ( y = 100; y < 300; y++ )
55         for ( x = 100; x < 300; x++ ) {
56 
57             location = (x+vinfo.xoffset) * (vinfo.bits_per_pixel/8) +
58                        (y+vinfo.yoffset) * finfo.line_length;
59 
60             if ( vinfo.bits_per_pixel == 32 ) {
61                 *(fbp + location) = 100; // Some blue
62                 *(fbp + location + 1) = 15+(x-100)/2; // A little green
63                 *(fbp + location + 2) = 200-(y-100)/5; // A lot of red
64                 *(fbp + location + 3) = 0; // No transparency
65             } else { //assume 16bpp
66                 int b = 10;
67                 int g = (x-100)/6; // A little green
68                 int r = 31-(y-100)/16; // A lot of red
69                 unsigned short int t = r<<11 | g << 5 | b;
70                 *((unsigned short int*)(fbp + location)) = t;
71             }
72 
73         }
74     //解除映射    
75     munmap(fbp, screensize);
76     //设备关闭
77     close(fbfd);
78     return 0;
79 }    

程序来源: http://blog.chinaunix.net/uid-22666248-id-283476.html

二、Framebuffer驱动框架图

技术分享


由图可知,framebuffer没有直接向用户空间提供文件操作接口,而是通过一个调用的关系,让fb_ops帮忙向用户空间提供了文件操作接口。

三、展讯framebuffer关键数据结构

 1 struct fb_info {
 2 
 3     struct fb_var_screeninfo var;    /* Current var */ //LCD 用户可变参数
 4     struct fb_fix_screeninfo fix;    /* Current fix */ //LCD 固定参数
 5 
 6 #ifdef CONFIG_FB_BACKLIGHT
 7     /* assigned backlight device */
 8     /* set before framebuffer registration, 
 9        remove after unregister */
10     struct backlight_device *bl_dev;  //背光设备
11 #endif
12 
13 
14     struct fb_ops *fbops;  //对底层硬件操作函数指针
15 
16     char __iomem *screen_base;    /* Virtual address */
17     unsigned long screen_size;    /* Amount of ioremapped VRAM or 0 */  //LCD I/O映射虚拟内存大小
18 
19     u32 state;            /* Hardware state i.e suspend */  //LCD 挂起或者恢复状态
20 
21 };

说明:
仅仅保留关键字段。位于: include/linux/fb.h

 

 1 struct fb_var_screeninfo {
 2     __u32 xres;            /* visible resolution        */ //可见屏幕一行有多少个像素点
 3     __u32 yres;                                            //可见屏幕一列有多少个像素点
 4     __u32 xres_virtual;        /* virtual resolution        */ //虚拟屏幕一行有多少个像素点
 5     __u32 yres_virtual;
 6     __u32 xoffset;            /* offset from virtual to visible */ //虚拟到可见之间的行偏移
 7     __u32 yoffset;            /* resolution            */
 8 
 9     __u32 bits_per_pixel;        /* guess what            */ //每个像素占的bit,除以8即是字节
10     __u32 grayscale;        /* 0 = color, 1 = grayscale,    */ //非0时,指定的灰度
11                     /* >1 = FOURCC            */
12     struct fb_bitfield red;        /* bitfield in fb mem if true color, */ //R
13     struct fb_bitfield green;    /* else only length is significant */ //G
14     struct fb_bitfield blue;                                          //B
15     struct fb_bitfield transp;    /* transparency            */             //透明度
16 
17     __u32 nonstd;            /* != 0 Non standard pixel format */
18 
19     __u32 activate;            /* see FB_ACTIVATE_*        */
20 
21     __u32 height;            /* height of picture in mm    */
22     __u32 width;            /* width of picture in mm     */
23 
24     __u32 accel_flags;        /* (OBSOLETE) see fb_info.flags */
25 
26     /* Timing: All values in pixclocks, except pixclock (of course) */
27     __u32 pixclock;            /* pixel clock in ps (pico seconds) */ //像素时钟
28     __u32 left_margin;        /* time from sync to picture    */ //行切换,从同步到绘图之间的延迟。也就是上面硬件部分介绍的 HFPD,以下参数意义类推
29     __u32 right_margin;        /* time from picture to sync    */
30     __u32 upper_margin;        /* time from sync to picture    */
31     __u32 lower_margin;
32     __u32 hsync_len;        /* length of horizontal sync    */
33     __u32 vsync_len;        /* length of vertical sync    */
34     __u32 sync;            /* see FB_SYNC_*        */
35     __u32 vmode;            /* see FB_VMODE_*        */
36     __u32 rotate;            /* angle we rotate counter clockwise */
37     __u32 colorspace;        /* colorspace for FOURCC-based modes */
38     __u32 reserved[4];        /* Reserved for future compatibility */
39 };

说明:
该结构详细的记录了用户可修改的显示参数。位于include/uapi/linux/fb.h

 

 1 struct fb_fix_screeninfo {
 2     char id[16];            /* identification string eg "TT Builtin" */
 3     unsigned long smem_start;    /* Start of frame buffer mem */ //fb缓存开始位置
 4                     /* (physical address) */
 5     __u32 smem_len;            /* Length of frame buffer mem */
 6     __u32 type;            /* see FB_TYPE_*        */ //fb类型
 7     __u32 type_aux;            /* Interleave for interleaved Planes */
 8     __u32 visual;            /* see FB_VISUAL_*        */ 
 9     __u16 xpanstep;            /* zero if no hardware panning  */
10     __u16 ypanstep;            /* zero if no hardware panning  */
11     __u16 ywrapstep;        /* zero if no hardware ywrap    */
12     __u32 line_length;        /* length of a line in bytes    */
13     unsigned long mmio_start;    /* Start of Memory Mapped I/O   */  //内存I/O映射的开始位置
14                     /* (physical address) */
15     __u32 mmio_len;            /* Length of Memory Mapped I/O  */  //I/O映射的长度
16     __u32 accel;            /* Indicate to driver which    */
17                     /*  specific chip/card we have    */
18     __u16 capabilities;        /* see FB_CAP_*            */
19     __u16 reserved[2];        /* Reserved for future compatibility */
20 };   

说明 :
该结构详细的说明了用户不可更改的参数。位于include/uapi/linux/fb.h

 

 1 struct fb_ops {
 2     /* open/release and usage marking */
 3     struct module *owner;
 4     int (*fb_open)(struct fb_info *info, int user);
 5     int (*fb_release)(struct fb_info *info, int user);
 6 
 7     /* For framebuffers with strange non linear layouts or that do not
 8      * work with normal memory mapped access
 9      */
10     ssize_t (*fb_read)(struct fb_info *info, char __user *buf,
11                size_t count, loff_t *ppos);
12     ssize_t (*fb_write)(struct fb_info *info, const char __user *buf,
13                 size_t count, loff_t *ppos);
14 
15     /* checks var and eventually tweaks it to something supported,
16      * DO NOT MODIFY PAR */
17     int (*fb_check_var)(struct fb_var_screeninfo *var, struct fb_info *info);
18 
19     /* set the video mode according to info->var */
20     int (*fb_set_par)(struct fb_info *info);
21 
22     /* set color register */
23     int (*fb_setcolreg)(unsigned regno, unsigned red, unsigned green,
24                 unsigned blue, unsigned transp, struct fb_info *info);
25 
26     /* set color registers in batch */
27     int (*fb_setcmap)(struct fb_cmap *cmap, struct fb_info *info);
28 
29     /* blank display */
30     int (*fb_blank)(int blank, struct fb_info *info);
31 
32     /* pan display */
33     int (*fb_pan_display)(struct fb_var_screeninfo *var, struct fb_info *info);
34 
35     /* Draws a rectangle */
36     void (*fb_fillrect) (struct fb_info *info, const struct fb_fillrect *rect);
37     /* Copy data from area to another */
38     void (*fb_copyarea) (struct fb_info *info, const struct fb_copyarea *region);
39     /* Draws a image to the display */
40     void (*fb_imageblit) (struct fb_info *info, const struct fb_image *image);
41 
42     /* Draws cursor */
43     int (*fb_cursor) (struct fb_info *info, struct fb_cursor *cursor);
44 
45     /* Rotates the display */
46     void (*fb_rotate)(struct fb_info *info, int angle);
47 
48     /* wait for blit idle, optional */
49     int (*fb_sync)(struct fb_info *info);
50 
51     /* perform fb specific ioctl (optional) */
52     int (*fb_ioctl)(struct fb_info *info, unsigned int cmd,
53             unsigned long arg);
54 
55     /* Handle 32bit compat ioctl (optional) */
56     int (*fb_compat_ioctl)(struct fb_info *info, unsigned cmd,
57             unsigned long arg);
58 
59     /* perform fb specific mmap */
60     int (*fb_mmap)(struct fb_info *info, struct vm_area_struct *vma);
61 
62     /* get capability given var */
63     void (*fb_get_caps)(struct fb_info *info, struct fb_blit_caps *caps,
64                 struct fb_var_screeninfo *var);
65 
66     /* teardown any resources to do with this framebuffer */
67     void (*fb_destroy)(struct fb_info *info);
68 
69     /* called at KDB enter and leave time to prepare the console */
70     int (*fb_debug_enter)(struct fb_info *info);
71     int (*fb_debug_leave)(struct fb_info *info);
72 };

说明:
该结构体详细说明了对底层硬件操作的方法。位于: include/linux/fb.h

 

以上几个结构体是,几乎所有的framebuffer都会有的。针对于展讯的实现方式,它还多了以下两个:

 1  struct sprdfb_device {
 2     struct fb_info    *fb;
 3 
 4     uint16_t        enable;
 5     uint16_t         dev_id; /*main_lcd, sub_lcd*/
 6 
 7     uint32_t         bpp;  /*input bit per pixel*/
 8 
 9     uint16_t        panel_ready; /*panel has been inited by uboot*/
10     uint16_t        panel_if_type; /*panel IF*/
11 
12     union{
13         uint32_t    mcu_timing[MCU_LCD_TIMING_KIND_MAX];
14         uint32_t    rgb_timing[RGB_LCD_TIMING_KIND_MAX];
15     }panel_timing;
16 
17     struct panel_spec    *panel;
18     struct display_ctrl    *ctrl;
19 
20 #ifdef CONFIG_OF
21     struct device *of_dev;
22 #endif
23 
24     uint32_t dpi_clock;
25     struct semaphore   refresh_lock;
26     uint64_t frame_count;
27 
28 #ifdef CONFIG_FB_ESD_SUPPORT
29     struct delayed_work ESD_work;
30 //    struct semaphore   ESD_lock;
31     uint32_t ESD_timeout_val;
32     bool ESD_work_start;
33     /*for debug only*/
34     uint32_t check_esd_time;
35     uint32_t panel_reset_time;
36     uint32_t reset_dsi_time;
37 #ifdef FB_CHECK_ESD_BY_TE_SUPPORT
38     uint32_t esd_te_waiter;
39     wait_queue_head_t  esd_te_queue;
40     uint32_t esd_te_done;
41 #endif
42 #endif
43 
44     uint32_t logo_buffer_addr_v;
45     uint32_t logo_buffer_size;
46 
47 #ifdef CONFIG_HAS_EARLYSUSPEND
48     struct early_suspend    early_suspend;
49 #endif
50 
51     void *priv1;
52 };

说明:
这个是展讯根据自己的平台特点,又封装了一层。如果用面向对象的观点看的话,它继承了 struct fb_info 结构体.

 

 1 struct display_ctrl {
 2     const char    *name;
 3 
 4     int32_t    (*early_init)      (struct sprdfb_device *dev);
 5     int32_t    (*init)          (struct sprdfb_device *dev);
 6     int32_t    (*uninit)          (struct sprdfb_device *dev);
 7 
 8     int32_t     (*refresh)      (struct sprdfb_device *dev);
 9     int32_t     (*logo_proc)      (struct sprdfb_device *dev);
10 
11     int32_t    (*suspend)      (struct sprdfb_device *dev);
12     int32_t     (*resume)      (struct sprdfb_device *dev);
13     int32_t (*update_clk) (struct sprdfb_device *dev);
14 
15 #ifdef CONFIG_FB_ESD_SUPPORT
16     int32_t    (*ESD_check)      (struct sprdfb_device *dev);
17 #endif
18 
19 #ifdef  CONFIG_FB_LCD_OVERLAY_SUPPORT
20     int32_t     (*enable_overlay)     (struct sprdfb_device *dev, struct overlay_info* info, int enable);
21     int32_t    (*display_overlay)    (struct sprdfb_device *dev, struct overlay_display* setting);
22 #endif
23 
24 #ifdef CONFIG_FB_VSYNC_SUPPORT
25     int32_t     (*wait_for_vsync)     (struct sprdfb_device *dev);
26 #endif
27 
28 #ifdef CONFIG_FB_MMAP_CACHED
29     void (*set_vma)(struct vm_area_struct *vma);
30 #endif
31     int32_t    (*is_refresh_done)    (struct sprdfb_device *dev);
32 
33 };

说明:
这个是展讯的LCD主控器硬件操作,该结构体在uboot阶段也使用到了。
注意区别LCD主控制器和LCD显示屏。以上两个数据结构位于: drivers/video/sprdfb/sprdfb.h

 

 四、考察fbmem.c里面实现的 struct file_operations fb_fops 是怎么最终操作到了最底层硬件的。

1. fb_read

 1  static ssize_t
 2 fb_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
 3 {
 4     struct fb_info *info = file_fb_info(file);
 5 
 6     //...
 7     if (info->fbops->fb_read)
 8         return info->fbops->fb_read(info, buf, count, ppos);
 9     //.....
10 }
11 
12 static struct fb_info *file_fb_info(struct file *file)
13 {
14     struct inode *inode = file_inode(file);
15     int fbidx = iminor(inode);
16     struct fb_info *info = registered_fb[fbidx];
17 
18     if (info != file->private_data)
19         info = NULL;
20     return info;
21 }

registered_fb[fbidx] 是一个全局的数组,其原始定义为:

1 struct fb_info *registered_fb[FB_MAX];

它会在 register_framebuffer@fbmem.c 里面使用到,具体的调用:

1 sprdfb_probe -> register_framebuffer -> do_register_framebuffer -> num_registered_fb[]

那么,fb_read 在读取的时候,通过 file_fb_info() 函数获取到num_registered_fb,于是顺利的获取到了展讯的framebuffer了。
而如果展讯framebuffer驱动提供了 fb_read操作函数,也即是if (info->fbops->fb_read) 判断为真的话,那就直接调用展讯提供的fb_read接口了。
而展讯对fbops的初始化如下:

 1 static void setup_fb_info(struct sprdfb_device *dev)
 2 {
 3     struct fb_info *fb = dev->fb;
 4     fb->fbops = &sprdfb_ops;
 5     //....
 6 }
 7 
 8 static struct fb_ops sprdfb_ops = {
 9     .owner = THIS_MODULE,
10     .fb_check_var = sprdfb_check_var,
11     .fb_pan_display = sprdfb_pan_display,
12     .fb_fillrect = cfb_fillrect,
13     .fb_copyarea = cfb_copyarea,
14     .fb_imageblit = cfb_imageblit,
15     .fb_ioctl = sprdfb_ioctl,
16 #ifdef CONFIG_FB_MMAP_CACHED
17     .fb_mmap = sprdfb_mmap,
18 #endif
19 };

似乎很抱歉,并没有为file_operations提供读写函数。这没关系,那就file_operations 层自己实现一把即可。但是放心的是,ioctl/mmap这些,展讯都提供了。

(2016-1-3 over)
(本篇笔记的图片来源于 《Android 深度探索卷一 HAL与驱动开发》,部分内部也是参考了该书。也可以说,是对该书lcd部分学习后的一个笔记)

 

展讯sc7731 LCD驱动简明笔记之二

标签:

原文地址:http://www.cnblogs.com/chineseboy/p/5096724.html

(0)
(1)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!