zoukankan      html  css  js  c++  java
  • sc7731 Android 5.1 LCD驱动简明笔记之二

    此篇笔记基于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 驱动软件相关的
    何谓帧缓冲?何谓缓冲?
    简而言之,缓冲就是一个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.
    ");
    21         exit(1);
    22     }
    23     printf("The framebuffer device was opened successfully.
    ");
    24 
    25     // 获取硬件屏幕信息
    26     if (ioctl(fbfd, FBIOGET_FSCREENINFO, &finfo)) {
    27         printf("Error reading fixed information.
    ");
    28         exit(2);
    29     }
    30 
    31     // 获取用户可修改屏幕参数信息
    32     if (ioctl(fbfd, FBIOGET_VSCREENINFO, &vinfo)) {
    33         printf("Error reading variable information.
    ");
    34         exit(3);
    35     }
    36 
    37     printf("%dx%d, %dbpp
    ", 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.
    ");
    47         exit(4);
    48     }
    49     printf("The framebuffer device was mapped to memory successfully.
    ");
    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没有直接向用户空间提供文件操作接口,而是通过一个调用的关系,让file_operations结构体帮忙向用户空间提供了文件操作接口。

    三、展讯framebuffer关键数据结构

    1、struct fb_info{};

     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

     2、struct fb_var_screeninfo{};

     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

     3、struct fb_fix_screeninfo{};

     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

     4、struct fb_ops{};

     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都会有的。针对于展讯的实现方式,它还多了以下两个:

    5、struct sprdfb_device{};

     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 结构体.

     6、struct display_ctrl{};

     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这些,展讯都提供了。

    (over)

    2016-1-3 


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

  • 相关阅读:
    JDBC
    spring和springmvc的父子容器的关系
    一句话学习
    Java5、java6指的是JDK的版本吗?
    Spring MVC-拦截器
    IDEA 创建项目时没有 maven 选项
    mvn 打包
    什么是线程安全和线程不安全
    SQL修改字段信息
    如何解决跨域问题,以及跨域预检未通过问题
  • 原文地址:https://www.cnblogs.com/chineseboy/p/5096724.html
Copyright © 2011-2022 走看看