struct fb_fix_screeninfo {
____char id[16];____________/* identification string eg "TT Builtin" */
____unsigned long smem_start;___/* Start of frame buffer mem */
____________________/* (physical address) */
______u32 smem_len;_________/* Length of frame buffer mem */
______u32 type;_________/* see FB_TYPE_*________*/
______u32 type_aux;_________/* Interleave for interleaved Planes */
______u32 visual;___________/* see FB_VISUAL_*______*/
______u16 xpanstep;_________/* zero if no hardware panning */
______u16 ypanstep;_________/* zero if no hardware panning */
______u16 ywrapstep;________/* zero if no hardware ywrap */
______u32 line_length;______/* length of a line in bytes */
____unsigned long mmio_start;___/* Start of Memory Mapped I/O */
____________________/* (physical address) */
______u32 mmio_len;_________/* Length of Memory Mapped I/O */
______u32 accel;____________/* Indicate to driver which_*/
____________________/* specific chip/card we have__*/
______u16 capabilities;_____/* see FB_CAP_*_________*/
______u16 reserved[2];______/* Reserved for future compatibility */
};
struct fb_info {
......
____struct fb_var_screeninfo var;___/* Current var */
____struct fb_fix_screeninfo fix;___/* Current fix */
......
____struct fb_ops *fbops;
......
____char __iomem *screen_base;__/* Virtual address */
____unsigned long screen_size;__/* Amount of ioremapped VRAM or 0 */
____void *pseudo_palette;_______/* Fake palette of 16 colors */
......
}
/*******************************************************************/
static u32 pseudo_palette[16];
static struct fb_ops s3c_lcdfb_ops = {
.owner = THIS_MODULE,
.fb_setcolreg = s3c_lcdfb_setcolreg, /*调色板的操作函数*/
.fb_fillrect = cfb_fillrect,
.fb_copyarea = cfb_copyarea,
.fb_imageblit = cfb_imageblit,
};
/* from pxafb.c */
static inline unsigned int chan_to_field(unsigned int chan, struct fb_bitfield *bf)
{
chan &= 0xffff;
chan >>= 16 - bf->length;
return chan << bf->offset;
}
static int s3c_lcdfb_setcolreg(unsigned int regno, unsigned int red,
unsigned int green, unsigned int blue,
unsigned int transp, struct fb_info *info)
{
unsigned int val;
if (regno > 16)
return 1;
/* 用red,green,blue三原色构造出val */
val = chan_to_field(red, &info->var.red);
val |= chan_to_field(green, &info->var.green);
val |= chan_to_field(blue, &info->var.blue);
//((u32 *)(info->pseudo_palette))[regno] = val;
pseudo_palette[regno] = val;
return 0;
}
static int lcd_init(void)
{
/* 1. 分配一个fb_info */
s3c_lcd = framebuffer_alloc(0, NULL);
/* 2. 设置 fb_info */
......
/* MINI2440的LCD位宽是24,但是2440里会分配4字节即32位(浪费1字节) */
s3c_lcd->fix.smem_len = 320*240*32/8;
......
/* 2.3 设置操作函数 */
s3c_lcd->fbops = &s3c_lcdfb_ops;
/* 2.4 其他的设置 */
s3c_lcd->pseudo_palette = pseudo_palette;
//s3c_lcd->screen_base = ; /* 显存的虚拟地址 */
s3c_lcd->screen_size = 320*240*32/8;
......
/* 3. 硬件相关的操作 */
......
/* 3.3 分配显存(framebuffer), 并把地址告诉LCD控制器 */
s3c_lcd->screen_base = dma_alloc_writecombine(NULL, s3c_lcd->fix.smem_len, &s3c_lcd->fix.smem_start, GFP_KERNEL);
lcd_regs->lcdsaddr1 = (s3c_lcd->fix.smem_start >> 1) & ~(3<<30);
lcd_regs->lcdsaddr2 = ((s3c_lcd->fix.smem_start + s3c_lcd->fix.smem_len) >> 1) & 0x1fffff;
lcd_regs->lcdsaddr3 = (320*32/16); /* 一行的长度(单位: 2字节) */
/* 启动LCD */
lcd_regs->lcdcon1 |= (1<<0); /* 使能LCD控制器 */
lcd_regs->lcdcon5 |= (1<<3); /* 使能LCD本身: LCD_PWREN */
// *gpbdat |= 1; /* MINI2440的背光电路也是通过LCD_PWREN来控制的, 不需要单独的背光引脚 */
/* 4. 注册fb_info */
register_framebuffer(s3c_lcd);
return 0;
}
static void lcd_exit(void)
{
unregister_framebuffer(s3c_lcd);
lcd_regs->lcdcon1 &= ~(1<<0); /* 关闭LCD控制器 */
lcd_regs->lcdcon1 &= ~(1<<3); /* 关闭LCD本身 */
// *gpbdat &= ~1; /* 关闭背光 */
dma_free_writecombine(NULL, s3c_lcd->fix.smem_len, s3c_lcd->screen_base, s3c_lcd->fix.smem_start);
......
framebuffer_release(s3c_lcd);
}
总结:
1、framebuffer的使用。
2、DMA空间的申请使用。(dma_alloc_writecombine)
3、调色板的使用。