JZ2440笔记:LCD驱动程序

vi lcd.c

#include <linux/module.h>
#include <linux/fb.h>
#include <linux/dma-mapping.h>


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;
};

static int s3c_lcdfb_setcolreg(unsigned int regno, unsigned int red, unsigned int green, unsigned int blue, unsigned int transp, struct fb_info * info);

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 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 volatile struct lcd_regs *lcd_regs;
static u32 pseudo_palette[16];


static 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;
	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)
{
	s3c_lcd = framebuffer_alloc(0,NULL);
	
	strcpy(s3c_lcd->fix.id,"mylcd");
	s3c_lcd->fix.smem_len = 480*272*16/8;
	s3c_lcd->fix.type = FB_TYPE_PACKED_PIXELS;
	s3c_lcd->fix.visual = FB_VISUAL_TRUECOLOR;
	s3c_lcd->fix.line_length = 480*2;
	//s3c_lcd->fix.smem_start = ;

	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.bits_per_pixel = 16;
	s3c_lcd->var.red.offset = 11;
	s3c_lcd->var.red.length = 5;
	s3c_lcd->var.green.offset = 5;
	s3c_lcd->var.green.length = 6;
	s3c_lcd->var.blue.offset = 0;
	s3c_lcd->var.blue.length = 5;
	s3c_lcd->var.activate = FB_ACTIVATE_NOW;
	
	s3c_lcd->fbops = &s3c_lcdfb_ops;

	s3c_lcd->pseudo_palette = pseudo_palette;
	//s3c_lcd->screen_base = ;
	s3c_lcd->screen_size = 272*480*16/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);
	*gpbcon |= 1;
	*gpbdat &= 0;
	*gpgcon |= (3<<8);

	lcd_regs = ioremap(0x4d000000,sizeof(struct lcd_regs));
	lcd_regs->lcdcon1 = (4<<8)|(3<<5)|(0x0c<<1);
	lcd_regs->lcdcon2 = (1<<24)|(271<<14)|(1<<6)|(9<<0);
	lcd_regs->lcdcon3 = (1<<19)|(479<<8)|(1<<0);
	lcd_regs->lcdcon4 = 40;
	lcd_regs->lcdcon5 = (1<<11)|(0<<10)|(1<<9)|(1<<8)|(1<<0);
	s3c_lcd->screen_base = dma_alloc_writecombine(NULL,s3c_lcd->fix.smem_len,(dma_addr_t *)&(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 = (480*16/16);

	lcd_regs->lcdcon1 |= (1<<0);
	lcd_regs->lcdcon5 |= (1<<3);
	*gpbdat |= 1;
	register_framebuffer(s3c_lcd);
	return 0;
}

static void lcd_exit(void)
{
	unregister_framebuffer(s3c_lcd);
	lcd_regs->lcdcon1 &= ~(1<<0);
	lcd_regs->lcdcon5 &= ~(1<<3);
	*gpbdat &= ~1;
	dma_free_writecombine(NULL,s3c_lcd->fix.smem_len,s3c_lcd->screen_base,s3c_lcd->fix.smem_start);
	iounmap(lcd_regs);
	iounmap(gpbcon);
	iounmap(gpccon);
	iounmap(gpdcon);
	iounmap(gpgcon);
	framebuffer_release(s3c_lcd);
}


module_init(lcd_init);
module_exit(lcd_exit);
MODULE_LICENSE("GPL");

测试驱动:先去掉uImage里的S3C2410 LCD驱动,

# ls /dev/fb*
ls: /dev/fb*: No such file or directory

# insmod lcd.ko
lcd: Unknown symbol cfb_fillrect
lcd: Unknown symbol cfb_imageblit
lcd: Unknown symbol cfb_copyarea
insmod: cannot insert 'lcd.ko': Unknown symbol in module (-1): No such file or directory

# insmod cfbcopyarea.ko
insmod lcd.ko# insmod cfbimgblt.ko
# insmod cfbfillrect.ko
# insmod lcd.ko
Console: switching to colour frame buffer device 60x34
# insmod lcd.ko
insmod: cannot insert 'lcd.ko': File exists (-1): File exists


# ls /dev/fb*
/dev/fb0
# echo hello > /dev/tty1
# cat lcd.ko > /dev/fb0
 

vi /etc/inittab添加tty1:::askfirst:-/bin/sh,重启后insmod上面的模块和button.ko,就可以在通过按键操作LCD显示。

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值