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
/* assigned backlight device */
/* set before framebuffer registration,
remove after unregister */
struct backlight_device *bl_dev;
/* Backlight level curve */
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;
struct device *device; /* This is the parent */
struct device *dev; /* This is this fb device */
int class_flag; /* private sysfs flags */
#ifdef CONFIG_FB_TILEBLITTING
struct fb_tile_ops *tileops; /* Tile Blitting */
#endif
union {
char __iomem *screen_base; /* Virtual address */
char *screen_buffer;
};
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 */
/* From here on everything is device dependent */
void *par;
/* we need the PCI or similar aperture base/size not
smem_start/size as smem_start may just be an object
allocated inside the aperture so may not actually overlap */
struct apertures_struct {
unsigned int count;
struct aperture {
resource_size_t base;
resource_size_t size;
} ranges[0];
} *apertures;
bool skip_vt_switch; /* no VT switch on suspend/resume required */
};
registered_fb
中的索引值,注册的时候分配,通过node可以索引fb_info#define FBINFO_MODULE 0x0001 /* Low-level driver is a module */
#define FBINFO_HWACCEL_DISABLED 0x0002
/* When FBINFO_HWACCEL_DISABLED is set:
* Hardware acceleration is turned off. Software implementations
* of required functions (copyarea(), fillrect(), and imageblit())
* takes over; acceleration engine should be in a quiescent state */
/* hints */
#define FBINFO_VIRTFB 0x0004 /* FB is System RAM, not device. */
#define FBINFO_PARTIAL_PAN_OK 0x0040 /* otw use pan only for double-buffering */
#define FBINFO_READS_FAST 0x0080 /* soft-copy faster than rendering */
/* hardware supported ops */
/* semantics: when a bit is set, it indicates that the operation is
* accelerated by hardware.
* required functions will still work even if the bit is not set.
* optional functions may not even exist if the flag bit is not set.
*/
#define FBINFO_HWACCEL_NONE 0x0000
#define FBINFO_HWACCEL_COPYAREA 0x0100 /* required */
#define FBINFO_HWACCEL_FILLRECT 0x0200 /* required */
#define FBINFO_HWACCEL_IMAGEBLIT 0x0400 /* required */
#define FBINFO_HWACCEL_ROTATE 0x0800 /* optional */
#define FBINFO_HWACCEL_XPAN 0x1000 /* optional */
#define FBINFO_HWACCEL_YPAN 0x2000 /* optional */
#define FBINFO_HWACCEL_YWRAP 0x4000 /* optional */
#define FBINFO_MISC_USEREVENT 0x10000 /* event request
from userspace */
#define FBINFO_MISC_TILEBLITTING 0x20000 /* use tile blitting */
/* A driver may set this flag to indicate that it does want a set_par to be
* called every time when fbcon_switch is executed. The advantage is that with
* this flag set you can really be sure that set_par is always called before
* any of the functions dependent on the correct hardware state or altering
* that state, even if you are using some broken X releases. The disadvantage
* is that it introduces unwanted delays to every console switch if set_par
* is slow. It is a good idea to try this flag in the drivers initialization
* code whenever there is a bug report related to switching between X and the
* framebuffer console.
*/
#define FBINFO_MISC_ALWAYS_SETPAR 0x40000
/* where the fb is a firmware driver, and can be replaced with a proper one */
#define FBINFO_MISC_FIRMWARE 0x80000
/*
* Host and GPU endianness differ.
*/
#define FBINFO_FOREIGN_ENDIAN 0x100000
/*
* Big endian math. This is the same flags as above, but with different
* meaning, it is set by the fb subsystem depending FOREIGN_ENDIAN flag
* and host endianness. Drivers should not use this flag.
*/
#define FBINFO_BE_MATH 0x100000
/* report to the VT layer that this fb driver can accept forced console
output like oopses */
#define FBINFO_CAN_FORCE_OUTPUT 0x200000
/* Draws a rectangle */
void (*fb_fillrect) (struct fb_info *info, const struct fb_fillrect *rect);
/* Copy data from area to another */
void (*fb_copyarea) (struct fb_info *info, const struct fb_copyarea *region);
/* Draws a image to the display */
void (*fb_imageblit) (struct fb_info *info, const struct fb_image *image);
#define FBINFO_STATE_RUNNING 0
#define FBINFO_STATE_SUSPENDED 1
19.skip_vt_switch:关于VT switch,是与console切换以及PM相关的,具体
struct fb_info * framebuffer_alloc(size_t size, struct device *dev)
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
}
EXPORT_SYMBOL(framebuffer_alloc);
int register_framebuffer(struct fb_info *fb_info)
static int do_register_framebuffer(struct fb_info *fb_info)
{
int i, ret;
struct fb_event event;
struct fb_videomode mode;
if (fb_check_foreignness(fb_info))
return -ENOSYS;
ret = do_remove_conflicting_framebuffers(fb_info->apertures,
fb_info->fix.id,
fb_is_primary_device(fb_info));
if (ret)
return ret;
if (num_registered_fb == FB_MAX)
return -ENXIO;
num_registered_fb++;
for (i = 0 ; i < FB_MAX; i++)
if (!registered_fb[i])
break;
fb_info->node = i;
atomic_set(&fb_info->count, 1);
mutex_init(&fb_info->lock);
mutex_init(&fb_info->mm_lock);
fb_info->dev = device_create(fb_class, fb_info->device,
MKDEV(FB_MAJOR, i), NULL, "fb%d", i);
if (IS_ERR(fb_info->dev)) {
/* Not fatal */
printk(KERN_WARNING "Unable to create device for framebuffer %d; errno = %ld\n", i, PTR_ERR(fb_info->dev));
fb_info->dev = NULL;
} else
fb_init_device(fb_info);
if (fb_info->pixmap.addr == NULL) {
fb_info->pixmap.addr = kmalloc(FBPIXMAPSIZE, GFP_KERNEL);
if (fb_info->pixmap.addr) {
fb_info->pixmap.size = FBPIXMAPSIZE;
fb_info->pixmap.buf_align = 1;
fb_info->pixmap.scan_align = 1;
fb_info->pixmap.access_align = 32;
fb_info->pixmap.flags = FB_PIXMAP_DEFAULT;
}
}
fb_info->pixmap.offset = 0;
if (!fb_info->pixmap.blit_x)
fb_info->pixmap.blit_x = ~(u32)0;
if (!fb_info->pixmap.blit_y)
fb_info->pixmap.blit_y = ~(u32)0;
if (!fb_info->modelist.prev || !fb_info->modelist.next)
INIT_LIST_HEAD(&fb_info->modelist);
if (fb_info->skip_vt_switch)
pm_vt_switch_required(fb_info->dev, false);
else
pm_vt_switch_required(fb_info->dev, true);
fb_var_to_videomode(&mode, &fb_info->var);
fb_add_videomode(&mode, &fb_info->modelist);
registered_fb[i] = fb_info;
event.info = fb_info;
if (!lockless_register_fb)
console_lock();
if (!lock_fb_info(fb_info)) {
if (!lockless_register_fb)
console_unlock();
return -ENODEV;
}
fb_notifier_call_chain(FB_EVENT_FB_REGISTERED, &event);
unlock_fb_info(fb_info);
if (!lockless_register_fb)
console_unlock();
return 0;
}
作用
注册framebuffer到framebuffer框架下的全局变量registered_fb
中
framebuffer的框架(框架图抄来的)
在framebuffer框架中(fbmem.c),完成了对字符设备的注册,申请了Major=29(
FB_MAJOR
),此设备号从0开始,总共256(实际上只支持32个#define FB_MAX 32 /* sufficient for now */
)的设备数,并提供了f_ops,
ret = register_chrdev(FB_MAJOR, "fb", &fb_fops);
static const struct file_operations fb_fops = {
.owner = THIS_MODULE,
.read = fb_read,
.write = fb_write,
.unlocked_ioctl = fb_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl = fb_compat_ioctl,
#endif
.mmap = fb_mmap,
.open = fb_open,
.release = fb_release,
#ifdef HAVE_ARCH_FB_UNMAPPED_AREA
.get_unmapped_area = get_fb_unmapped_area,
#endif
#ifdef CONFIG_FB_DEFERRED_IO
.fsync = fb_deferred_io_fsync,
#endif
.llseek = default_llseek,
};
registered_fb
数组中,其索引号赋值给fb_info中的node 成员变量fb_info->dev = device_create(fb_class, fb_info->device, MKDEV(FB_MAJOR, i), NULL, "fb%d", i);
fb_init_device
完成),其中xxx包含父节点的目录static struct device_attribute device_attrs[] = {
__ATTR(bits_per_pixel, S_IRUGO|S_IWUSR, show_bpp, store_bpp),
__ATTR(blank, S_IRUGO|S_IWUSR, show_blank, store_blank),
__ATTR(console, S_IRUGO|S_IWUSR, show_console, store_console),
__ATTR(cursor, S_IRUGO|S_IWUSR, show_cursor, store_cursor),
__ATTR(mode, S_IRUGO|S_IWUSR, show_mode, store_mode),
__ATTR(modes, S_IRUGO|S_IWUSR, show_modes, store_modes),
__ATTR(pan, S_IRUGO|S_IWUSR, show_pan, store_pan),
__ATTR(virtual_size, S_IRUGO|S_IWUSR, show_virtual, store_virtual),
__ATTR(name, S_IRUGO, show_name, NULL),
__ATTR(stride, S_IRUGO, show_stride, NULL),
__ATTR(rotate, S_IRUGO|S_IWUSR, show_rotate, store_rotate),
__ATTR(state, S_IRUGO|S_IWUSR, show_fbstate, store_fbstate),
#ifdef CONFIG_FB_BACKLIGHT
__ATTR(bl_curve, S_IRUGO|S_IWUSR, show_bl_curve, store_bl_curve),
#endif
};
4.初始化pixmap的成员变量,具体要干什么未知,后面更新
5.将var的中的屏的参数转换成fb_videomode
,将其mode挂载在modelist
链表中去,当然首次会初始化modelist
INIT_LIST_HEAD(&fb_info->modelist);
6.skip_vt_switch,主要是console在suspend的时候切换console,调用
pm_vt_switch_required(fb_info->dev, false);
完成。设置为1,则不进行切换,当然也要使能对应的CONFIG,CONFIG_VT_CONSOLE_SLEEP
7.通过通知链,将FB_EVENT_FB_REGISTERED
的事件发送出去,通知链的原理是建立一个链表,向其注册回调,通过xxx_notifier_call_chain,将事件发送出去,这个通知链会经常用到,通知一些包括RESUME,SUSPEND,BLANK等事件,具体实现在fb_notify.c
1.fb_info代表的一类显示设备(LCD,OLED等),而显示设备的父节点就是显示控制器,
2.通常显示设备的参数以及显示控制器参数会在deviceTree中描述,对于显示设备来讲,描述的是一些时序,对应到fb_info中var参数,控制器参数一般包括显示控制器的中断号,显存位置等
3.显示控制器作为设备挂在platform device的树中,显示控制器驱动 platform driver 通过匹配某些字段,完成match操作,probe函数中,读取平台参数,包括显示控制器的参数,显示设备的参数,调用注册framebuffer,完成设备节点的创建
4.显示控制器一般会关联硬件加速函数,2D,可以部分重写部分framebuffer框架中的一些绘图函数
5.Framebuffer框架作为简单的显示框架,目前已经切换到DRM框架中,为了适应更复杂的图形计算。目前主流的芯片也都基于其框架写显示部分的驱动。但是早期的芯片例如三星2440,6410 还是会有部分的驱动代码
6.DRM框架也是今后的方向