开发平台:MINI2440内核版本:linux2.6.261.移植前的说明>从启动信息可以看出没有加载成功LCD驱动io scheduler cfq registereds3c2410-lcd s3c2410-lcd: no platform data for lcd, cannot attachs3c2410-lcd: probe of s3c2410-lcd failed with error -22lp: driver loaded but no devices found>实际上在linux2.6.26将LCD移植到QQ2440时,只需修改两个结构体配置参数即可。这两个结构体分别是:struct s3c2410fb_display和s3c2410fb_mach_info 。修改参数所在文件是arch/arm/mach-s3c2410/mach-smdk2410.c,为什么不是arch/arm/mach-s3c2440/mach-smdk2440.c呢?因为在配置内核时需要选上的mach_type出选smdk2440外还需包含smdk2410,否则编译内核是通不过。既然选上了smdk2410,所以内核编译时所需编译的文件是在arm/mach-s3c2410/mach-smdk2410.c而非arm/mach-s3c2440/mach-smdk2440.c。2.移植参考文件>友善之臂提供了各个驱动都添加好的linux2.6.13内核原码,可以参考它的一些相关参数>相关参数所在文件:arch/arm/mach-s3c2410/mach-sbc2440.c >我的液晶屏是nec240 320的,所以是下面这段代码2.6.24内核将s3c2410fb_mach_info拆成了struct s3c2410fb_display和s3c2410fb_mach_info #if defined(CONFIG_FB_S3C2410_N240320)
static struct s3c2410fb_mach_info sbc2440_lcdcfg __initdata = {
.regs = {
.lcdcon1 = S3C2410_LCDCON1_TFT16BPP | \
S3C2410_LCDCON1_TFT | \
S3C2410_LCDCON1_CLKVAL(0x04),
.lcdcon2 = S3C2410_LCDCON2_VBPD(1) | \
S3C2410_LCDCON2_LINEVAL(319) | \
S3C2410_LCDCON2_VFPD(5) | \
S3C2410_LCDCON2_VSPW(1),
.lcdcon3 = S3C2410_LCDCON3_HBPD(36) | \
S3C2410_LCDCON3_HOZVAL(239) | \
S3C2410_LCDCON3_HFPD(19),
.lcdcon4 = S3C2410_LCDCON4_MVAL(13) | \
S3C2410_LCDCON4_HSPW(5),
.lcdcon5 = S3C2410_LCDCON5_FRM565 |
S3C2410_LCDCON5_INVVLINE |
S3C2410_LCDCON5_INVVFRAME |
S3C2410_LCDCON5_PWREN |
S3C2410_LCDCON5_HWSWP,
},
.lpcsel = 0xf82,
.gpccon = 0xaa955699,
.gpccon_mask = 0xffc003cc,
.gpcup = 0x0000ffff,
.gpcup_mask = 0xffffffff,
.gpdcon = 0xaa95aaa1,
.gpdcon_mask = 0xffc0fff0,
.gpdup = 0x0000faff,
.gpdup_mask = 0xffffffff,
.fixed_syncs = 1,
.width = 240,
.height = 320,
.xres = {
.min = 240,
.max = 240,
.defval = 240,
},
.yres = {
.max = 320,
.min = 320,
.defval = 320,
},
.bpp = {
.min = 16,
.max = 16,
.defval = 16,
},
};
3.参照上面的参考参数修改内核代码>修改文件/linux2.6.26/arch/arm/mach-s3c2410/mach-smdk2410.c#加入头文件#include #添加代码static struct s3c2410fb_display s3c2440_lcd_cfg[] __initdata = { { /* Config for 240x320 LCD */ .lcdcon5 = S3C2410_LCDCON5_FRM565 | S3C2410_LCDCON5_INVVLINE | S3C2410_LCDCON5_INVVFRAME | S3C2410_LCDCON5_PWREN | S3C2410_LCDCON5_HWSWP, .type = S3C2410_LCDCON1_TFT, .width = 320,
.height = 240,
.pixclock = 80000, /* HCLK/(CLKVAL*2) */ .xres = 320,
.yres = 240,
.bpp = 16, .left_margin = 20, .right_margin = 37, .hsync_len = 6, .upper_margin = 2, .lower_margin = 6, .vsync_len = 2, }};static struct s3c2410fb_mach_info s3c2440_fb_info __initdata = { .displays = s3c2440_lcd_cfg, .num_displays = ARRAY_SIZE(s3c2440_lcd_cfg), .default_display = 0, .gpccon = 0xaa955699, .gpccon_mask = 0xffc003cc, .gpcup = 0x0000ffff, .gpcup_mask = 0xffffffff, .gpdcon = 0xaa95aaa1, .gpdcon_mask = 0xffc0fff0, .gpdup = 0x0000faff, .gpdup_mask = 0xffffffff, //.lpcsel = ((0xCE6) & ~7) | 1<<4, 显示不正常
.lpcsel = 0xf82 //.plcsel对于着TCONSEL寄存器
}; #在函数smdk2410_init()中加入s3c24xx_fb_set_platdata(&s3c2440_fb_info);>幕后使者drivers/vidio/s3c2410fb.c:s3c2410fb_calculate_tft_lcd_regs,调用关系:s3c2410fb_ops->s3c2410fb_set_par->s3c2410fb_activate_var->s3c2410fb_calculate_tft_lcd_regsstatic void s3c2410fb_calculate_tft_lcd_regs(const struct fb_info *info,
struct s3c2410fb_hw *regs)
{
const struct s3c2410fb_info *fbi = info->par;
const struct fb_var_screeninfo *var = &info->var; switch (var->bits_per_pixel) {
case 1:
regs->lcdcon1 |= S3C2410_LCDCON1_TFT1BPP;
break;
case 2:
regs->lcdcon1 |= S3C2410_LCDCON1_TFT2BPP;
break;
case 4:
regs->lcdcon1 |= S3C2410_LCDCON1_TFT4BPP;
break;
case 8:
regs->lcdcon1 |= S3C2410_LCDCON1_TFT8BPP;
regs->lcdcon5 |= S3C2410_LCDCON5_BSWP |
S3C2410_LCDCON5_FRM565;
regs->lcdcon5 &= ~S3C2410_LCDCON5_HWSWP;
break;
case 16:
regs->lcdcon1 |= S3C2410_LCDCON1_TFT16BPP;
regs->lcdcon5 &= ~S3C2410_LCDCON5_BSWP;
regs->lcdcon5 |= S3C2410_LCDCON5_HWSWP;
break;
case 32:
regs->lcdcon1 |= S3C2410_LCDCON1_TFT24BPP;
regs->lcdcon5 &= ~(S3C2410_LCDCON5_BSWP |
S3C2410_LCDCON5_HWSWP |
S3C2410_LCDCON5_BPP24BL);
break;
default:
/* invalid pixel depth */
dev_err(fbi->dev, "invalid bpp %d\n",
var->bits_per_pixel);
}
/* update X/Y info */
dprintk("setting vert: up=%d, low=%d, sync=%d\n",
var->upper_margin, var->lower_margin, var->vsync_len); dprintk("setting horz: lft=%d, rt=%d, sync=%d\n",
var->left_margin, var->right_margin, var->hsync_len); regs->lcdcon2 = S3C2410_LCDCON2_LINEVAL(var->yres - 1) |
S3C2410_LCDCON2_VBPD(var->upper_margin - 1) |
S3C2410_LCDCON2_VFPD(var->lower_margin - 1) |
S3C2410_LCDCON2_VSPW(var->vsync_len - 1); regs->lcdcon3 = S3C2410_LCDCON3_HBPD(var->right_margin - 1) |
S3C2410_LCDCON3_HFPD(var->left_margin - 1) |
S3C2410_LCDCON3_HOZVAL(var->xres - 1);regs->lcdcon4 = S3C2410_LCDCON4_HSPW(var->hsync_len - 1);
}regs->lcdcon2 = S3C2410_LCDCON2_LINEVAL(var->yres - 1) |
S3C2410_LCDCON2_VBPD(var->upper_margin - 1) |
S3C2410_LCDCON2_VFPD(var->lower_margin - 1) |
S3C2410_LCDCON2_VSPW(var->vsync_len - 1); regs->lcdcon3 = S3C2410_LCDCON3_HBPD(var->right_margin - 1) |
S3C2410_LCDCON3_HFPD(var->left_margin - 1) |
S3C2410_LCDCON3_HOZVAL(var->xres - 1);regs->lcdcon4 = S3C2410_LCDCON4_HSPW(var->hsync_len - 1);与参考参数比较 .lcdcon2 = S3C2410_LCDCON2_VBPD(1) | \
S3C2410_LCDCON2_LINEVAL(319) | \
S3C2410_LCDCON2_VFPD(5) | \
S3C2410_LCDCON2_VSPW(1),
.lcdcon3 = S3C2410_LCDCON3_HBPD(36) | \
S3C2410_LCDCON3_HOZVAL(239) | \
S3C2410_LCDCON3_HFPD(19),
.lcdcon4 = S3C2410_LCDCON4_MVAL(13) | \
S3C2410_LCDCON4_HSPW(5),这样就可以得到:upper_margin =1+1 =2 lower_margin =5+1 =6 vsync_len =1+1 =2 hsync_len =5+1 =6 right_margin =36+1=37 left_margin =19+1=20HCLK 可以在开发板启动时在串口终端上得到:……………………
CPU S3C2440A (id 0x32440001)
S3C244X: core 400.000 MHz, memory 100.000 MHz, peripheral 50.000 MHz
S3C24XX Clocks, (c) 2004 Simtec Electronics……………………100.000 MHz就是HCLK .pixclock = 1/(HCLK/(CLKVAL*2))=1/(100MHz/(4*2))=8/(100MHz) =80000*10^(-12)s =80000ps(飞秒)4配置内核,启用graphic device里面的frambuffer.并打开boot logo重新编译内核,看看启动信息……io scheduler cfq registeredConsole: switching to colour frame buffer device 30x40fb0: s3c2410fb frame buffer device……同时可以看到LCD上出现了小企鹅,不过出乎意料的是本应该只出现一只小企鹅的,结果出现了两只,且光标下移。以此可断定是参数长宽设置反了。最后作如下修改(红色部分 )static struct s3c2410fb_display s3c2440_lcd_cfg[] __initdata = { { /* Config for 240x320 LCD */ .lcdcon5 = S3C2410_LCDCON5_FRM565 | S3C2410_LCDCON5_INVVLINE | S3C2410_LCDCON5_INVVFRAME | S3C2410_LCDCON5_PWREN | S3C2410_LCDCON5_HWSWP, .type = S3C2410_LCDCON1_TFT, .width = 240
.height = 320
.pixclock = 125000, /* HCLK/(CLKVAL*2) */ .xres = 240
.yres = 320
.bpp = 16, .left_margin = 20, .right_margin = 37, .hsync_len = 6, .upper_margin = 2, .lower_margin = 6, .vsync_len = 2, }};重新编译下载,正常了。注:本人以前的出现在lcd不亮的情况,好像背光的驱动也有问题。但没去管。在arch/arm /mach-s3c2440/mach_smdk2440.c中,lcd初始化函数smdk2440_machine_iniit()中加下这两句就可以了。s3c2410_gpio_cfgpin(S3C2410_GPG4, S3C2410_GPG4_OUTP);
s3c2410_gpio_setpin(S3C2410_GPG4, 1);