您的位置:首页 > 运维架构 > Linux

linux ------ framebuffer 驱动

2014-03-06 16:18 302 查看
framebuffer 设备即帧缓冲设备(简写fb)提供了显示接口的抽象描述。他同时代表着显示接口的存储区,应用程序通过定义好的函数访问,不需要知道底层的任何操作。 Framebuffer 驱动使用的设备节点,通常位于/dev 目录,如/dev/fb*.从用户角度看,fb 设备和其他/dev 下面的设备类似:普通的字符设备,主设备号29,次设备号定义fb 的索引。通常,使用如下方式(前面的数字表示次设备号)0 = /dev/fb0
第一个fb 设备,1 = /dev/fb1 第二个fb 设备,fb 也是一种普通的内存设备,可以读写其内容。例如,屏幕抓屏:cp /dev/fb0 myfile,fb 虽然可以像内存设备(/dev/mem)一样,对其read,write,seek 以及mmap。但区别在于fb 使用的不是整个内存区,而是显存部分。通过ioctl 可以读取或设定fb 设备参数,很重要的一点,颜色表(cmap)也要通过Ioctl 设定。你可以获取设备一些不变的信息,如设备名,屏幕的组织(平面,象素,...)对应内存区的长度和起始地址。也可以获取能够改变的信息,例如位深,颜色格式,时序等。如果你改变这些值,驱动程序将对值进行优化,以满足设备特性。framebuffer是LCD控制器相关的驱动,CPU可以通过寻址的方式访问LCD控制器,所以framebuffer一般是platform
driver,所以用platform driver的架构来编写framebuffer驱动。

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

一. 重要数据结构

1. 帧缓冲区描述符 fb_info

struct fb_info
{

atomic_t count;

int node;

int flags;

struct mutex lock; /* Lock for open/release/ioctl funcs */

struct mutex mm_lock; /* Lock for fb_mmap and smem_* fields */

struct fb_var_screeninfo var; /* Current var */ //缓冲区可变参数

struct fb_fix_screeninfo fix; /* Current fix */ //缓冲区固定参数

struct fb_monspecs monspecs; /* Current Monitor specs */ //当前显示器

struct work_struct queue; /* Framebuffer event queue */ //事件工作队列

struct fb_pixmap pixmap; /* Image hardware mapper */ //图像硬件映射

struct fb_pixmap sprite; /* Cursor hardware mapper */ //光标硬件映射

struct fb_cmap cmap; /* Current cmap */

struct list_head modelist; /* mode list */
//视频模式链表

struct fb_videomode *mode; /* current mode */ //当前视频模式

#ifdef CONFIG_FB_BACKLIGHT //支持背光的参数

struct backlight_device *bl_dev;

struct mutex bl_curve_mutex;

u8 bl_curve[FB_BACKLIGHT_LEVELS];

#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; /* This is the parent */ //父设备

struct device *dev; /* This is this fb device */ //FB设备

int class_flag; /* private sysfs flags */

#ifdef CONFIG_FB_TILEBLITTING

struct fb_tile_ops *tileops; /* Tile Blitting */

#endif

char __iomem *screen_base; /* Virtual address */

unsigned long screen_size; /* Amount of ioremapped VRAM or 0 */

void *pseudo_palette; /* Fake palette of 16 colors */

#define FBINFO_STATE_RUNNING 0

#define FBINFO_STATE_SUSPENDED 1

u32 state; /* Hardware state i.e suspend */

void *fbcon_par; /* fbcon use-only private area */

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]; /* 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行的字节数

unsigned long mmio_start; /* Start of Memory Mapped I/O*///内存IO映射的开始地址

/* (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. 可变参数描述符

struct fb_var_screeninfo {

__u32 xres; /* visible resolution */ //可见解析度,分辨率的X轴宽度

__u32 yres; //可见解析度,分辨率的Y轴宽度

__u32 xres_virtual; /* virtual resolution */ //虚拟解析度X轴宽度

__u32 yres_virtual; //虚拟解析度Y轴宽度

__u32 xoffset; /* offset from virtual to visible */ //虚拟与可见解析度之间X轴偏移

__u32 yoffset; /* resolution */ //虚拟与可见解析度之间Y轴偏移

__u32 bits_per_pixel; /* guess what */ //每像素点的位数

__u32 grayscale; /* 0 = color, 1 = grayscale, */ //灰度级别,0表示彩色

/* >1 = FOURCC */

struct fb_bitfield red; /* bitfield in fb mem if true color, */ //RGB位域的红色

struct fb_bitfield green; /* else only length is significant */ //RGB位域的绿色

struct fb_bitfield blue; //RGB位域的蓝色

struct fb_bitfield transp; /* transparency */ //透明色

__u32 nonstd; /* != 0 Non standard pixel format */ //如果该值不为0,非标准像素格式

__u32 activate; /* see FB_ACTIVATE_* */

__u32 height; /* height of picture in mm */ //图像在屏幕中的高度

__u32 width; /* width of picture in mm */ //图像在屏幕中的宽度

__u32 accel_flags; /* (OBSOLETE) see fb_info.flags */

__u32 pixclock; /* pixel clock in ps (pico seconds) */ //像点时钟

__u32 left_margin; /*time from sync to picture*///行切换时,显示与同步间的延时左边空隙

__u32 right_margin; /*time from picture to sync*///行切换时,显示与同步间的延时右边空隙

__u32 upper_margin;/*time from sync to picture*///帧切换时,显示与同步间的延时上边空隙

__u32 lower_margin; //帧切换时,显示与同步间的延时上边空隙

__u32 hsync_len; /* length of horizontal sync */ //行同步长度

__u32 vsync_len; /* length of vertical sync */ //帧同步长度

__u32 sync; /* see FB_SYNC_* */

__u32 vmode; /* see FB_VMODE_* */

__u32 rotate; /* angle we rotate counter clockwise */ //顺时针旋转角度

__u32 colorspace; /* colorspace for FOURCC-based modes *///颜色空间

__u32 reserved[5]; /* Reserved for future compatibility */

};

5. 调色板描述符

struct fb_cmap {

__u32 start; /* First entry */ //第一个颜色入口

__u32 len; /* Number of entries */ //颜色总数

__u16 *red; /* Red values */ //RGB红色值

__u16 *green; //RGB红绿值

__u16 *blue; //RGB红蓝值

__u16 *transp; /* transparency, can be NULL */ //透明度值

};

二. 主要函数

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 <linux/fb.h>

#include <linux/device.h>

#include <linux/platform_device.h>

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);
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: