您的位置:首页 > 运维架构 > Linux

LCD驱动设计与分析 --GQ2440+LTV350QV_F04 + LINUX2.6.22内核

2012-12-15 16:04 232 查看
LCD使用的是LTV350QV_F04
参数设置见4_th_ok程序中的设置
程序中使用了
.fb_fillrect = cfb_fillrect,
.fb_copyarea = cfb_copyarea,
.fb_imageblit = cfb_imageblit,
三个由驱动模块提供的函数:
所以:
make menuconfig
----->device driver
----> graphic
[M] s3c2410frame buffer suport
make uImage
make modules
把driver/video/cfbfillrect.ko cfbcopyarea.ko cfbimageblit.ko 拷贝到开发板中
insmod cfbfillrect.ko
insmod cfbcopyarea.ko
insmod cfbimgblt.ko
insmod gq2440_lcd.ko
cfbfillrect: unknown relocation: 40
insmod: can't insert 'cfbfillrect.ko': invalid module format
cfbcopyarea: unknown relocation: 40
insmod: can't insert 'cfbcopyarea.ko': invalid module format
cfbimgblt: unknown relocation: 40
insmod: can't insert 'cfbimgblt.ko': invalid module format
解决方法:
修改内核源码:
D:\linux-2.6.22源码分析\linux-2.6.22\include\asm-arm\elf.h
#define R_ARM_NONE 0
#define R_ARM_PC24 1
#define R_ARM_ABS32 2
#define R_ARM_CALL 28
#define R_ARM_JUMP24 29
/*modify 在大约三十行,修改加上下面的宏定义*/
#define R_ARM_V4BX 40
D:\linux-2.6.22源码分析\linux-2.6.22\arch\arm\kernel\module.c
/*modify 大约在109行加上case的下面这条分支*/
case R_ARM_V4BX:
/* Preserve Rm and the condition code. Alter
* other bits to re-code instruction as
* MOV PC,Rm.
*/
*(u32 *)loc &= 0xf000000f;
*(u32 *)loc |= 0x01a0f000;
打上补丁:
diff -urN 没有修改过的内核目录 修改过的内核目录 > xx.patch
重新
make uImage
make modules
============
搞定:
测试:
1 ls /dev/fb0
2 cat xx_file > /dev/fb0
3 修改/etc/inittab:tty1::askfirst:-/bin/sh 通过bin shell程序启动一个虚拟终端,reboot
4 echo helo > /dev/tty1
5 insmod input_btn_drv.ko 通过按键对虚拟终端进行测试
?????????????????????????????????????????????????????????????????????????????????????????????
驱动模块卸载:rmmod gq2440_lcd 提示:Resource temporarily unavailable
google的结果是:要卸载的这个模块(调用了try_module_get函数),
查看源码:fbmem.c中的fb_open 调用过try_module_get
fb_release中也调用了module_put释放了
问题以后再解决吧!估计是
.fb_fillrect = cfb_fillrect,
.fb_copyarea = cfb_copyarea,
.fb_imageblit = cfb_imageblit,
这三个模块的问题
核心LCD设置代码
/* 1 分配一个fb_info结构体*/
s3c_lcd = framebuffer_alloc(0,NULL);
/* 2 设置fb_info结构体 */
/* 2.1 设置固定的参数*/
strcpy(s3c_lcd->fix.id,"sust_lcd");
s3c_lcd->fix.smem_len = 240*320*32/8;
s3c_lcd->fix.type = FB_TYPE_PACKED_PIXELS;
s3c_lcd->fix.visual = FB_VISUAL_TRUECOLOR;
s3c_lcd->fix.line_length = 320*4;

/* 2.2 设置可变的参数*/
s3c_lcd->var.xres = 320;
s3c_lcd->var.yres = 240;
s3c_lcd->var.xres_virtual = 320;
s3c_lcd->var.xres_virtual = 240;
s3c_lcd->var.bits_per_pixel = 32;
/*RGB:565*/
s3c_lcd->var.red.length = 8;
s3c_lcd->var.red.offset = 16;
s3c_lcd->var.green.length = 8;
s3c_lcd->var.green.offset = 8;
s3c_lcd->var.blue.length = 8;
s3c_lcd->var.blue.offset = 0;
s3c_lcd->var.activate = FB_ACTIVATE_NOW;
/* 2.3 设置fb_ops*/
s3c_lcd->fbops = &s3c_fbops;
/* 2.4 设置其它 */
s3c_lcd->pseudo_palette = pseudo_pal;

s3c_lcd->screen_size = 240*320*4;/*显存的大小*/
/* 3 硬件相关的设置*/
/* 3.1 配置引脚用于LCD*/
gpgcon = ioremap(0x56000060,8);
*gpgcon |= 3<<4*2;/*LCD_PWRDN*/
gpccon = ioremap(0x56000020,28) ;
gpcdat = gpccon + 1 ;
gpdcon = gpccon + 4 ;
gpddat = gpccon + 5 ;
*gpccon = 0xAAAAAAAA ;
*gpdcon = 0xAAAAAAAA ;

/* 3.2 根据LCD手册设置LCD控制器 such as:VCLK*/

s3c_lcd_regs = ioremap(0X4D000000,sizeof(struct lcd_regs));
/* CLKVAL[17:8]: TFT: VCLK = HCLK/[(CLKVAL+1)*2] = 10MHz=100MHz /((clkval+1)*2)
* CLKVAL = 4
*/
s3c_lcd_regs->lcdcon1 = (6<<8) | (0x03<<5) |(0x0d<<1) ;
s3c_lcd_regs->lcdcon2 = (9<<24) | (239<<14) | (7<<6) | 2;
s3c_lcd_regs->lcdcon3 = (0<<19) | (319<<8) | 3 ;
s3c_lcd_regs->lcdcon4 = 0x12 ;
s3c_lcd_regs->lcdcon5 = (1<<9) | (1<<8) ;

/* 3.3 分配显存,并把地址告诉LCD控制器*/
/*显存的虚拟地址*/
s3c_lcd->screen_base = dma_alloc_writecombine(NULL,s3c_lcd->fix.smem_len,
/*显存的物理地址*/ &(s3c_lcd->fix.smem_start) ,GFP_KERNEL);
s3c_lcd_regs->lcdsaddr1 = (s3c_lcd->fix.smem_start >>1) & ~(3<<30);
s3c_lcd_regs->lcdsaddr2 = ((s3c_lcd->fix.smem_start + s3c_lcd->fix.smem_len)>>1) & 0x1fffff;
s3c_lcd_regs->lcdsaddr3 = 320*2;/*一行的长度:单位2字节*/
s3c_lcd_regs->lcdcon1 |= (1<<0);/*使能LCD控制器*/
s3c_lcd_regs->lcdcon5 |= (1<<3);/*使能LCD,背光也是通过LCD_PWREN控制*/
/*4 注册fb_info结构体*/
register_framebuffer(s3c_lcd);
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: