編寫前的準備
可以參考的代碼:
drivers\video\fbdev\s3c2410fb.c
基本思路
在init函數中:
- 配置設定fb_info
- 設定fb_info
- 設定var參數
- 設定fix參數
- 設定fbops參數
- 注冊fb_info
在exit函數中:
- 解除安裝fb_info
- 清空fb_info
相關函數
framebuffer_alloc,include/linux/fb.h
/**
* framebuffer_alloc - creates a new frame buffer info structure
*
* @size: size of driver private data, can be zero
* @dev: pointer to the device for this fb, this can be NULL
*
* Creates a new frame buffer info structure. Also reserves @size bytes
* for driver private data (info->par). info->par (if any) will be
* aligned to sizeof(long).
*
* Returns the new structure, or NULL if an error occurred.
*
*/
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); /*這個size是額外的配置設定的記憶體*/
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
}
dma_alloc_writecombine
register_framebuffer
注冊framebuffer
源碼
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/fb.h>
struct fb_info *myfb_info;
static struct fb_ops myfb_ops = {
.owner = THIS_MODULE,
.fb_fillrect = cfb_fillrect,
.fb_copyarea = cfb_copyarea,
.fb_imageblit = cfb_imageblit,
};
static int lcd_drv_init(void)
{
int ret;
dma_ddr_t phy_addr;
/* 1. crate */
myfb_info = framebuffer_alloc(0, NULL);
if(!fb_info)
return -ENOMEN;
/* 2. set */
/* 2.1 var resolution color formate */
myfb_info->var.xres = 1024;
myfb_info->var.yres = 600;
myfb_info->var.bits_per_pixel = 16; /* rgb565 */
myfb_info->var.red.offset = 11;
myfb_info->var.red.length = 5;
myfb_info->var.green.offset = 5;
myfb_info->var.green.length = 6;
myfb_info->var.blue.offset = 0;
myfb_info->var.blue.length = 5;
/* 2.2 fix */
myfb_info->fix.smem_len= myfb_info->var.xres * myfb_info->var.yres * myfb_info->var.bits_per_pixel / 8;
if(myfb_info->var.bits_per_pixel == 24) {
myfb_info->fix.smem_len= myfb_info->var.xres * myfb_info->var.yres * 4;
}
myfb_info->fix.type = FB_TYPE_PACKED_PIXELS;
myfb_info->fix.visual = FB_VISUAL_TRUECOLOR;
myfb_info->screen_base = dma_alloc_writecombine(NULL, myfb_info->fix.smem_len,
&phy_addr, GFP_KERNEL); /* virtual address */
myfb_info->fix.smem_start = phy_addr; /* physicsal address */
/* 2.3 fops */
myfb_info->fbops = &myfb_ops;
/* 3. register */
ret = register_framebuffer(myfb_info);
/* 4. hardware opeation */
return 0;
}
static void lcd_drv_exit(void)
{
unregister_framebuffer(myfb_info);
dma_free_writecombine(NULL, PAGE_ALIGN(myfb_info->fix.smem_len),
myfb_info->screen_base, myfb_info->fix.smem_start);
framebuffer_release(myfb_info);
}
module_init(lcd_drv_init);
module_exit(lcd_drv_exit);
MODULE_AUTHOR("chen");
MODULE_DESCRIPTION("Framebuffer driver for the linux");
MODULE_LICENSE("GPL");