您的位置首页>企业动态>

你了解过linux framebuffer 驱动?

导读 大家好,我是极客范的本期栏目编辑小友,现在为大家讲解你了解过linux framebuffer 驱动?问题。帧缓冲设备(fb)提供显示界面的抽象描述。

大家好,我是极客范的本期栏目编辑小友,现在为大家讲解你了解过linux framebuffer 驱动?问题。

帧缓冲设备(fb)提供显示界面的抽象描述。同时,它代表显示界面的存储区域,应用程序可以通过定义的函数访问它,而不需要知道任何底层操作。Framebuffer驱动程序使用的设备节点通常位于/dev目录中,例如/dev/fb*。从用户的角度来看,fb设备与/dev下的其他设备类似:普通字符设备、主设备号29和次设备号定义fb的索引。一般采用以下方法(前面的数字表示子器件编号):0=/dev/fb0第一fb器件,1=/dev/fb1第二fb器件,fb也是普通的存储器件,可以读写其内容。例如,屏幕截图:cp /dev/fb0 myfile,fb可以像存储设备一样读取、写入、查找和mmap它(/dev/mem)。但不同的是,fb并不使用整个存储区域,而是视频存储部分。fb设备的参数可以通过ioctl读取或设置,最重要的是颜色表(cmap)也要通过Ioctl设置。您可以获得一些关于设备的不变信息,例如设备名称、屏幕的组织(平面、像素,),相应存储区的长度和起始地址。您还可以获得可以更改的信息,如位深度、颜色格式、时间顺序等。如果您更改这些值,驱动程序将优化这些值以满足设备特性。帧缓冲区是与LCD控制器相关的驱动,CPU可以通过寻址访问LCD控制器,所以帧缓冲区一般是平台驱动,所以帧缓冲区驱动是用平台驱动的框架编写的。

当我们要写一个FB设备驱动的时候,比较好的方法是注册平台设备,然后把FB设备注册、IO映射操作、硬件初始化等操作放在探针里,这样整体结构就清晰了。

一、重要数据结构

1.帧缓冲区描述符fb_info

structfb_info{

atomic_t计数;

int节点;

int标志;

结构互斥锁;

结构互斥锁mm _ lock/*锁定fb_mmap和smem_*字段*/

struct fb _ var _ screeninfo var//缓冲变量参数

struct fb _ fix _ screeninfo fix//缓冲区修复参数

struct fb _ monspecs monspecs//当前显示器

struct work_struct队列;//事件工作队列

struct fb _ pixmap pixmap//映像硬件映射

struct fb _ pixmap sprite//光标硬件映射

struct fb _ cmap cmap

struct list _ head modelist//视频模式链表

struct fb _ videomode *模式;//当前视频模式

# ifdef CONFIG _ FB _背光//支持背光的参数

struct背光_器件* bl _ dev

结构互斥体bl _ curve _ mutex

u8 bl _ curve[FB _背光_电平];

#endif

            #ifdef CONFIG_FB_DEFERRED_IO                    struct delayed_work deferred_work;                    struct fb_deferred_io *fbdefio;            #endif                    struct fb_ops *fbops;      //帧缓冲区操作函数,framebuffer驱动的核心数据结构                    struct device *device;      //父设备                    struct device *dev;      //FB设备                    int class_flag;                                #ifdef CONFIG_FB_TILEBLITTING                    struct fb_TIle_ops *TIleops;                #endif                    char __iomem *screen_base;                     unsigned long screen_size;                     void *pseudo_palette;               #define FBINFO_STATE_RUNNING 0            #define FBINFO_STATE_SUSPENDED 1                    u32 state;                       void *fbcon_par;                                    void *par;                    struct apertures_struct {                            unsigned int count;                            struct aperture {                                     resource_size_t base;                                     resource_size_t size;                             } ranges[0];                    } *apertures;            };

2. 帧缓冲区操作函数表 fb_ops

struct fb_ops {                       struct module *owner;          //模块所有者                       int (*fb_open)(struct fb_info *info, int user);        //FB打开操作                       int (*fb_release)(struct fb_info *info, int user);   //FB释放操作                       ssize_t (*fb_read)(struct fb_info *info, char __user *buf,size_t count, loff_t *ppos);    //FB读操作                       ssize_t (*fb_write)(struct fb_info *info, const char __user *buf,size_t count, loff_t *ppos); //FB写操作                       int (*fb_check_var)(struct fb_var_screeninfo *var, struct fb_info *info);//检查FB可变变量,并调整为可用值                       int (*fb_set_par)(struct fb_info *info);          //设置视频模式                       int (*fb_setcolreg)(unsigned regno, unsigned red, unsigned green,unsigned blue, unsigned transp, struct fb_info *info); //设置颜色寄存器                       int (*fb_setcmap)(struct fb_cmap *cmap, struct fb_info *info); //批量设置颜色寄存器,并设置颜色表                       int (*fb_blank)(int blank, struct fb_info *info);     //空白显示                       int (*fb_pan_display)(struct fb_var_screeninfo *var, struct fb_info *info); //面板显示                       void (*fb_fillrect) (struct fb_info *info, const struct fb_fillrect *rect);              //画矩形                       void (*fb_copyarea) (struct fb_info *info, const struct fb_copyarea *region);//把数据拷贝到另外一个区域                       void (*fb_imageblit) (struct fb_info *info, const struct fb_image *image);//在帧缓冲去中显示一个图片                       int (*fb_cursor) (struct fb_info *info, struct fb_cursor *cursor);                    //绘制光标                       void (*fb_rotate)(struct fb_info *info, int angle);                                              //旋转显示                       int (*fb_sync)(struct fb_info *info);                                                      //等待并同步图像显示完成                       int (*fb_ioctl)(struct fb_info *info, unsigned int cmd,unsigned long arg);//FB的IOCTL操作                       int (*fb_compat_ioctl)(struct fb_info *info, unsigned cmd,unsigned long arg);                           int (*fb_mmap)(struct fb_info *info, struct vm_area_struct *vma);  //FB的内存映射MMAP操作                       void (*fb_get_caps)(struct fb_info *info, struct fb_blit_caps *caps,struct fb_var_screeninfo *var);                       void (*fb_destroy)(struct fb_info *info);                       int (*fb_debug_enter)(struct fb_info *info);                       int (*fb_debug_leave)(struct fb_info *info);              };

3. 固定参数描述符

struct fb_fix_screeninfo {                           char id[16];                                           //FB ID                           unsigned long smem_start;                   //FB缓存开始位置                                                                                                             //物理地址相关                           __u32 smem_len;                                //FB缓存长度                           __u32 type;                                          /* see FB_TYPE_*  */                       //FB类型                           __u32 type_aux;                                 //FB分界                           __u32 visual;                                       /* see FB_VISUAL_*  */                   //FB色彩模式                           __u16 xpanstep;                                   //没有硬件PAN则赋0                           __u16 ypanstep;                                                                        __u16 ywrapstep;                                                          __u32 line_length;                                    //1行的字节数                           unsigned long mmio_start;              //内存IO映射的开始地址                                                                                                                     __u32 mmio_len;                               //IO 长度                           __u32 accel;                                                                                                                                                             __u16 capabilities;                             /* see FB_CAP_*   */                           __u16 reserved[2];                                               };

4. 可变参数描述符

struct fb_var_screeninfo {                          __u32 xres;                              //可见解析度,分辨率的X轴宽度                          __u32 yres;                                                                     //可见解析度,分辨率的Y轴宽度                          __u32 xres_virtual;                  //虚拟解析度X轴宽度                          __u32 yres_virtual;                                                        //虚拟解析度Y轴宽度                          __u32 xoffset;          //虚拟与可见解析度之间X轴偏移                          __u32 yoffset;                                      //虚拟与可见解析度之间Y轴偏移                          __u32 bits_per_pixel;                     //每像素点的位数                          __u32 grayscale;          //灰度级别,0表示彩色                                                                                            struct fb_bitfield red;   //RGB位域的红色                          struct fb_bitfield green;  //RGB位域的绿色                          struct fb_bitfield blue;                                                      //RGB位域的蓝色                          struct fb_bitfield transp;                  //透明色                          __u32 nonstd;      //如果该值不为0,非标准像素格式                          __u32 activate;   /* see FB_ACTIVATE_*  */                          __u32 height;                //图像在屏幕中的高度                          __u32 width;                   //图像在屏幕中的宽度                          __u32 accel_flags;                            __u32 pixclock;     //像点时钟                          __u32 left_margin;  //行切换时,显示与同步间的延时左边空隙                          __u32 right_margin; //行切换时,显示与同步间的延时右边空隙                          __u32 upper_margin;//帧切换时,显示与同步间的延时上边空隙                          __u32 lower_margin;                                             //帧切换时,显示与同步间的延时上边空隙                          __u32 hsync_len;     //行同步长度                          __u32 vsync_len;          //帧同步长度                          __u32 sync;   /* see FB_SYNC_*  */                                                                                    __u32 vmode;   /* see FB_VMODE_*  */                          __u32 rotate;      //顺时针旋转角度                          __u32 colorspace;  //颜色空间                          __u32 reserved[5];                     };

5. 调色板描述符

struct fb_cmap {                           __u32 start;                                                //第一个颜色入口                           __u32 len;                                   //颜色总数                           __u16 *red;                                             //RGB红色值                           __u16 *green;                                                                     //RGB红绿值                           __u16 *blue;                                                                       //RGB红蓝值                           __u16 *transp;           //透明度值                    };

二. 主要函数

1. framebuffer_alloc, 为FB驱动分配内存空间并初始化,这个函数的核心的作用是申请一块空间,并转换为struct fb_info 指针返回,在这个申请过程私有数据空间size并非是必须的,需要的话可以有但并非必须。

struct fb_info *framebuffer_alloc(size_t size, struct device *dev)               {                        #define BYTES_PER_LONG (BITS_PER_LONG/8)                        #define PADDING (BYTES_PER_LONG - (sizeof(struct fb_info) % BYTES_PER_LONG))                        int fb_info_size = sizeof(struct fb_info);                        struct fb_info *info;                        char *p;                        if (size)                               fb_info_size += PADDING;                        p = kzalloc(fb_info_size + size, GFP_KERNEL);                        if (!p)                              return NULL;                        info = (struct fb_info *) p;                        if (size)                               info->par = p + fb_info_size;                        info->device = dev;                        #ifdef CONFIG_FB_BACKLIGHT                                mutex_init(&info->bl_curve_mutex);                        #endif                                 return info;                        #undef PADDING                        #undef BYTES_PER_LONG               }

2. register_framebuffer,向系统注册FB。

int register_framebuffer(struct fb_info *fb_info)                {                      int ret;                      mutex_lock(®istration_lock);                      ret = do_register_framebuffer(fb_info);                      mutex_unlock(®istration_lock);                      return ret;                }

三. 实现framebuffer驱动程序的一个例子的步骤

1. 包含头文件

#include

#include

#include

2. 定义及初始化相关FB参数结构体

struct fb_var_screeninfo dnfb_var__devinitdata = {                             .xres  = 1280,                             .yres  = 1024,                             .xres_virtual = 2048,                             .yres_virtual = 1024,                             .bits_per_pixel = 1,                             .height  = -1,                             .width  = -1,                             .vmode  = FB_VMODE_NONINTERLACED,                      };

static struct fb_fix_screeninfo dnfb_fix__devinitdata = {                              .id  ="Apollo Mono",                              .smem_start = (FRAME_BUFFER_START + IO_BASE),                              .smem_len = FRAME_BUFFER_LEN,                              .type  = FB_TYPE_PACKED_PIXELS,                              .visual  = FB_VISUAL_MONO10,                              .line_length = 256,                      };

3. 定义及实现结构 fb_ops与它的成员函数

static int dnfb_blank(int blank, struct fb_info *info)                      {                             if (blank)                                    out_8(AP_CONTROL_3A, 0x0);                             else                                    out_8(AP_CONTROL_3A, 0x1);                             return 0;                      }

void cfb_fillrect(struct fb_info *p, const struct fb_fillrect *rect)                      {                               unsigned long pat, pat2, fg;                               unsigned long width = rect->width, height = rect->height;                               int bits = BITS_PER_LONG, bytes = bits >> 3;                               u32 bpp = p->var.bits_per_pixel;                               unsigned long __iomem *dst;                               int dst_idx, left;                               if (p->state != FBINFO_STATE_RUNNING)                                      return;                               if (p->fix.visual == FB_VISUAL_TRUECOLOR || p->fix.visual == FB_VISUAL_DIRECTCOLOR )                                      fg = ((u32 *) (p->pseudo_palette))[rect->color];                               else                                      fg = rect->color;                               pat = pixel_to_pat(bpp, fg);                               dst = (unsigned long __iomem *)((unsigned long)p->screen_base & ~(bytes-1));                               dst_idx = ((unsigned long)p->screen_base & (bytes - 1))*8;                               dst_idx += rect->dy*p->fix.line_length*8+rect->dx*bpp;                               left = bits % bpp;                               if (p->fbops->fb_sync)                                       p->fbops->fb_sync(p);                               if (!left) {                                       u32 bswapmask = fb_compute_bswapmask(p);                                       void (*fill_op32)(struct fb_info *p,unsigned long __iomem *dst, int dst_idx,unsigned long pat, unsigned n, int bits,u32 bswapmask) = NULL;

switch (rect->rop) {                                       case ROP_XOR:                                                fill_op32 = bitfill_aligned_rev;                                                break;                                       case ROP_COPY:                                                fill_op32 = bitfill_aligned;                                                break;                                       default:                                                printk( KERN_ERR"cfb_fillrect(): unknown rop, defaulting to ROP_COPY\n");                                                fill_op32 = bitfill_aligned;                                                break;                                        }                                        while (height--) {                                                dst += dst_idx >> (ffs(bits) - 1);                                                dst_idx &= (bits - 1);                                                fill_op32(p, dst, dst_idx, pat, width*bpp, bits, bswapmask);                                                dst_idx += p->fix.line_length*8;                                        }                                } else {                                        int right, r;                                        void (*fill_op)(struct fb_info *p, unsigned long __iomem *dst,int dst_idx, unsigned long pat, int left,int right, unsigned n, int bits) = NULL;                                        right = bpp - left;                                        switch (rect->rop) {                                               case ROP_XOR:                                                        fill_op = bitfill_unaligned_rev;                                                        break;                                               case ROP_COPY:                                                        fill_op = bitfill_unaligned;                                                        break;                                               default:                                                        printk(KERN_ERR"cfb_fillrect(): unknown rop, defaulting to ROP_COPY\n");                                                        fill_op = bitfill_unaligned;                                                        break;                                         }                                         while (height--) {                                                 dst += dst_idx / bits;                                                 dst_idx &= (bits - 1);                                                  r = dst_idx % bpp;                                                  pat2 = le_long_to_cpu(rolx(cpu_to_le_long(pat), r, bpp));                                                  fill_op(p, dst, dst_idx, pat2, left, right,width*bpp, bits);                                                  dst_idx += p->fix.line_length*8;                                         }                                  }                          }

static void dnfb_copyarea(struct fb_info *info, const struct fb_copyarea *area)                          {

}

void cfb_imageblit(struct fb_info *p, const struct fb_image *image)                         {                                u32 fgcolor, bgcolor, start_index, bitstart, pitch_index = 0;                                u32 bpl = sizeof(u32), bpp = p->var.bits_per_pixel;                                u32 width = image->width;                                u32 dx = image->dx, dy = image->dy;                                u8 __iomem *dst1;                                if (p->state != FBINFO_STATE_RUNNING)                                     return;                                bitstart = (dy * p->fix.line_length * 8) + (dx * bpp);                                start_index = bitstart & (32 - 1);                                pitch_index = (p->fix.line_length & (bpl - 1)) * 8;                                bitstart /= 8;                                bitstart &= ~(bpl - 1);                                dst1 = p->screen_base + bitstart;                                if (p->fbops->fb_sync)                                      p->fbops->fb_sync(p);                                if (image->depth == 1) {                                        if (p->fix.visual == FB_VISUAL_TRUECOLOR || p->fix.visual == FB_VISUAL_DIRECTCOLOR) {                                               fgcolor = ((u32*)(p->pseudo_palette))[image->fg_color];                                               bgcolor = ((u32*)(p->pseudo_palette))[image->bg_color];                                        } else {                                               fgcolor = image->fg_color;                                               bgcolor = image->bg_color;                                 }                                  if (32 % bpp == 0 && !start_index && !pitch_index && ((width & (32/bpp-1)) == 0) && bpp >= 8 && bpp <= 32)                                            fast_imageblit(image, p, dst1, fgcolor, bgcolor);                                 else                                         slow_imageblit(image, p, dst1, fgcolor, bgcolor,start_index, pitch_index);                            } else                                     color_imageblit(image, p, dst1, start_index, pitch_index);                      }

static struct fb_ops dn_fb_ops = {                             .owner  = THIS_MODULE,                             .fb_blank = dnfb_blank,                             .fb_fillrect = cfb_fillrect,                             .fb_copyarea = dnfb_copyarea,                             .fb_imageblit = cfb_imageblit,                      };

4. 定义及实现总线驱动结构体及成员函数,如果FB驱动是挂载在platform总线上,则定义platform_driver结构,如果是别的总线,比如PCI总线,在定义pci_driver结构。一般会在总线驱动成员的probe函数中调用FB的函数framebuffer_alloc与register_framebuffer来申请FB设备及注册到系统。

static int __devinit dnfb_probe(struct platform_device *dev)                     {                            struct fb_info *info;                            int err = 0;                            info = framebuffer_alloc(0, &dev->dev);                            if (!info)                                  return -ENOMEM;                            info->fbops = &dn_fb_ops;                            info->fix = dnfb_fix;                            info->var = dnfb_var;                            info->var.red.length = 1;                            info->var.red.offset = 0;                            info->var.green = info->var.blue = info->var.red;                            info->screen_base = (u_char *) info->fix.smem_start;                            err = fb_alloc_cmap(&info->cmap, 2, 0);                            if (err < 0) {                                   framebuffer_release(info);                                   return err;                            }                            err = register_framebuffer(info);                            if (err < 0) {                                   fb_dealloc_cmap(&info->cmap);                                   framebuffer_release(info);                                   return err;                             }                             platform_set_drvdata(dev, info);                             out_8(AP_CONTROL_3A, RESET_CREG);                             out_be16(AP_WRITE_ENABLE, 0x0);                             out_8(AP_CONTROL_0, NORMAL_MODE);                             out_8(AP_CONTROL_1, (AD_BLT | DST_EQ_SRC | NORM_CREG1));                             out_8(AP_CONTROL_2, S_DATA_PLN);                             out_be16(AP_ROP_1, SWAP(0x3));                             return err;                       }

static struct platform_driver dnfb_driver = {                             .probe = dnfb_probe,                             .driver = {                                     .name ="dnfb",                              },                       };                       static struct platform_device dnfb_device = {                              .name ="dnfb",                       };

5. 调用总线驱动注册函数把FB驱动注册到系统。

int __init dnfb_init(void)                     {                           int ret;                           if (!MACH_IS_APOLLO)                                 return -ENODEV;                           if (fb_get_options("dnfb", NULL))                                 return -ENODEV;                           ret = platform_driver_register(&dnfb_driver);                           if (!ret) {                                 ret = platform_device_register(&dnfb_device);                           if (ret)                                 platform_driver_unregister(&dnfb_driver);                           }                           return ret;                     }                     module_init(dnfb_init);

 

郑重声明:本文版权归原作者所有,转载文章仅为传播更多信息之目的,如作者信息标记有误,请第一时间联系我们修改或删除,多谢。