你了解过linux framebuffer 驱动?

网友投稿 371 2022-11-14

你了解过linux framebuffer 驱动?

当我们想编写一个FB设备驱动时,一个比较好的方法是注册platform设备,然后将FB设备的注册,IO映射操作,硬件初始化等操作放在在probe中进行,从而整体上结构清晰。

一. 重要数据结构

1. 帧缓冲区描述符 fb_info

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];                                           /* identification string eg "TT Builtin" *///FB ID                            unsigned long smem_start;            /* Start of frame buffer mem */       //FB缓存开始位置                                                                                           /* (physical address) */                   //物理地址相关                            __u32 smem_len;                             /* Length of frame buffer mem */   //FB缓存长度                            __u32 type;                                          /* see FB_TYPE_*  */                       //FB类型                            __u32 type_aux;                                 /* Interleave for interleaved Planes *///FB分界                            __u32 visual;                                       /* see FB_VISUAL_*  */                   //FB色彩模式                            __u16 xpanstep;                                 /* zero if no hardware panning  */  //没有硬件PAN则赋0                            __u16 ypanstep;                                 /* zero if no hardware panning  */                                        __u16 ywrapstep;                               /* zero if no hardware ywrap    */                            __u32 line_length;                             /* length of a line in bytes    */       //1行的字节数                                                                                           /* (physical address) */                            __u32 mmio_len;                               /* Length of Memory Mapped I/O  *///IO 长度                            __u32 accel;                                        /* Indicate to driver which */                                                                                           /*  specific chip/card we have */                            __u16 capabilities;                             /* see FB_CAP_*   */                            __u16 reserved[2];                             /* Reserved for future compatibility */                   };

4. 可变参数描述符

5. 调色板描述符

二. 主要函数

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

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");                                                 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");                                                         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);

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:微软云计算介绍与实践(实践之三十八)
下一篇:微软云计算介绍与实践(实践之三十七)
相关文章

 发表评论

暂时没有评论,来抢沙发吧~