天天看點

rk3288 lcd驅動架構編寫編寫前的準備相關函數源碼

編寫前的準備

可以參考的代碼:

drivers\video\fbdev\s3c2410fb.c

基本思路

在init函數中:

  1. 配置設定fb_info
  2. 設定fb_info
    • 設定var參數
    • 設定fix參數
    • 設定fbops參數
  3. 注冊fb_info

在exit函數中:

  1. 解除安裝fb_info
  2. 清空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");

           

繼續閱讀