定义LCD相应寄存器的结构体
struct lcd_regs { unsigned long lcdcon1; unsigned long lcdcon2; unsigned long lcdcon3; unsigned long lcdcon4; unsigned long lcdcon5; unsigned long lcdsaddr1; unsigned long lcdsaddr2; unsigned long lcdsaddr3; unsigned long redlut; unsigned long greenlut; unsigned long bluelut; unsigned long reserved[9]; unsigned long dithmode; unsigned long tpal; unsigned long lcdintpnd; unsigned long lcdsrcpnd; unsigned long lcdintmsk; unsigned long lpcsel; };
定义调色板
u32 pseudo_palette[16];
定义LCD寄存器结构体变量
volatile struct lcd_regs* lcd_regs;
static struct fb_info *s3c_lcd; static volatile unsigned long *gpbcon; static volatile unsigned long *gpbdat; static volatile unsigned long *gpccon; static volatile unsigned long *gpdcon; static volatile unsigned long *gpgcon;
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, }; 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; }
1.分配fb_info结构体
struct fb_info *s3c_lcd = framebuffer_alloc(0, NULL);
strcpy(s3c_lcd->fix.id, "mylcd"); s3c_lcd->fix.smem_len = 480*272*32/8;/* 单位字节 */ s3c_lcd->fix.type = FB_TYPE_PACKED_PIXELS; s3c_lcd->fix.visual = FB_VISUAL_TRUECOLOR; s3c_lcd->fix.line_length = 480*4;/* 单位字节 */
2.2设置可变参数
s3c_lcd->var.xres = 480; s3c_lcd->var.yres = 272; s3c_lcd->var.xres_virtual = 480; s3c_lcd->var.yres_virtual = 272; s3c_lcd->var.bit_per_pixel = 32; /* RGB */ s3c_lcd->var.red.offset = 16; s3c_lcd->var.red.lenght = 8; s3c_lcd->var.green.offset = 8; s3c_lcd->var.green.length = 8; s3c_lcd->var.blue.offset = 0; s3c_lcd->var.blue.length = 8; s3c_lcd->var.activate = FB_ACTIVATE_NOW;
s3c_lcd->fbops = &s3c_lcdfb_ops;
s3c_lcd->pseudo_palette = pseudo_palette; s3c_lcd->screen_size = 480*270*32/8;
gpbcon = ioremap(0x56000010, 8); gpbdat = gpbcon+1; gpccon = ioremap(0x56000020, 4); gpdcon = ioremap(0x56000030, 4); gpgcon = ioremap(0x56000060, 4); *gpccon = 0xaaaaaaaa; *gpdcon = 0xaaaaaaaa; *gpbcon |= (3<<8);/* 使能LCD_PWREN */
lcd_regs = ioremap(0x4D000000, sizeof(struct lcd_regs)); lcd_regs->lcdcon1 = (4<<8) | (3<<5) | (0x0d<<1);/* 设置CLKVAL,VCLK = HCLK / [(CLKVAL+1) x 2], LCD手册P22 (Dclk=9MHz~15MHz) */ /* 垂直方向的时间参数 */ /*VBPD VSYNC之后再过多长时间发出第一行数据*/ /* VFPD 发出最后一行后再过多长时间发出VSYNC */ /* VSPW VSYNC信号的脉冲宽度 */ lcd_regs->lcdcon2 = (1<<24) | (271<<14) | (1<<6) | (9<<0); /* 水平方向的时间参数 */ /* HBPD HSYNC之后再过多长时间才能发出这一行数据 */ /* HFPD 发出一行最后一个像素数据之后,再过多长时间才能发出HSYNC */ lcd_regs->lcdcon3 = (1<<19) | (479<<8) | (1<<0); /* HSPW HSYNC信号的脉冲宽度 */ lcd_regs->lcdcon4 = 40; /* 信号极性、字节序 */ lcd_regs->lcdcon5 = (0<<10) | (1<<9) | (1<<8) | (0<<12) | (0<<1) | (0<<0);
/* s3c_lcd->fix.smem_start为显存的物理地址 */ s3c_lcd->screen_base = dma_alloc_writecombine(NULL, s3c_lcd->fix.smem_len, &s3c_lcd->fix.smem_start, GFP_KERNEL); lcd_regs->lcdaddr1 = (s3c_lcd->fix.smem_start >> 1) & ~(3<<30); lcd_regs->lcdaddr2 = ((s3c_lcd->fix.smem_start + s3c_lcd->fix.smem_len) >> 1) & 0x1fffff; lcd_regs->lcdaddr3 = (480*32/16); /* 一行的长度(单位: 2字节) */
lcd_regs->lcdcon1 |= (1<<0); /* 使能LCD控制器 */ lcd_regs->lcdcon5 |= (1<<3); /* 使能LCD器件: LCD_PWREN */
register_framebuffer(s3c_lcd);/* /dev/fb0 */
5.测试LCD驱动
5.1配置内核,去掉原来的驱动程序
原文地址:http://www.cnblogs.com/zpehome/p/3817702.html