解决了移植2.6.24内核的LCD驱动移植问题
发布时间:2008-03-27 13:35:26来源:红联作者:ylnyzl
因为项目所要求的是VGA的显示,但是我在移植了2.6.24内核后对LCD的驱动进行修改发现根本无法看到具体效果,于是我就想通过我自己的QQ2440开发板先做一下测试,因为QQ2440开发板我买时带一块3.5英寸的TFT屏,故先于昨天对其进行了2.6.24内核的LCD移植测试,基本上测试我没有查相关的LCD屏的手册,相信那些内容根据《S3C2410 下LCD 驱动程序移植及GUI 程序编写》这篇文章都能看明白具体寄存器的作用,本文重点对2.6.24的LCD差别部分进行说明,以给有同样问题出现的朋友一个捷径,首先,我想说明一下,在编译内核时需要在system type中选中 S3C2410 Machines中选中 SMDK2410/A9M2410,固然友善的QQ2440是s3c2440的ARM,但是不选中上述项就会在编译内核时出现缺少一个函数的错误,这个是2.6.24编译时发现的bug,另外,修改LCD的驱动文件得注意,因为选中了2410选项,需要针对arch/arm/mach-s3c2410/文件下的mach-smdk2410.c进行,不是2440的那个文件夹,开始我一直在2440的那个文件夹下对mach-smdk2440.c修改并让系统打印出信息,发现始终不行,就想是选中了2410的原因了,下边详情:
QQ2440出厂时内核2.6.13原LCD信息如下:
这是在2.6.13内核中的详细配置:[code]static struct s3c2410fb_mach_info sbc2440_lcdcfg __initdata = {
.regs = {
.lcdcon1 = S3C2410_LCDCON1_TFT16BPP | \
S3C2410_LCDCON1_TFT | \
S3C2410_LCDCON1_CLKVAL(0x03),
.lcdcon2 = S3C2410_LCDCON2_VBPD(3) | \
S3C2410_LCDCON2_LINEVAL(239) | \
S3C2410_LCDCON2_VFPD(5) | \
S3C2410_LCDCON2_VSPW(15),
.lcdcon3 = S3C2410_LCDCON3_HBPD(5) | \
S3C2410_LCDCON3_HOZVAL(319) | \
S3C2410_LCDCON3_HFPD(15),
.lcdcon4 = S3C2410_LCDCON4_MVAL(13) | \
S3C2410_LCDCON4_HSPW(8),
.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 = 320,
.height = 240,
.xres = {
.min = 320,
.max = 320,
.defval = 320,
},
.yres = {
.max = 240,
.min = 240,
.defval = 240,
},
.bpp = {
.min = 16,
.max = 16,
.defval = 16,
},
};[/code]而在2.6.24内核中有了重大的数据结构变化,首先他把结构拆成了二部分,一个结构是s3c2410fb_display另一个结构是s3c2410fb_mach_info,所以先根据这二个数据结构进行拆分上述结构[code]static struct s3c2410fb_display smdk2410_lcd_cfg __initdata = {
.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 = 174757,
.xres = 320,
.yres = 240,
.bpp = 16,
.left_margin = 16,
.right_margin = 6,
.hsync_len = 9,
.upper_margin = 4,
.lower_margin = 6,
.vsync_len = 16,
};
static struct s3c2410fb_mach_info smdk2410_fb_info __initdata = {
.displays = &smdk2410_lcd_cfg,
.num_displays = 1,
.default_display = 0,
.gpccon = 0xaa955699,
.gpccon_mask = 0xffc003cc,
.gpcup = 0x0000ffff,
.gpcup_mask = 0xffffffff,
.gpdcon = 0xaa95aaa1,
.gpdcon_mask = 0xffc0fff0,
.gpdup = 0x0000faff,
.gpdup_mask = 0xffffffff,
.lpcsel = 0xf82,
};[/code]2.6.24结构中对寄存器lcdcon1-4全部用函数进行了自动设置,我们只需对lcdcon5进行设置,但是并不说明其他的数据不重要,或者不用设置,重点在这几个数值上
引用:
.left_margin = 16,根据下边的函数S3C2410_LCDCON3_HFPD(var->left_margin - 1)
.right_margin = 6,同上,以此类推
.hsync_len = 9,同上,以此类推
.upper_margin = 4, 同上,以此类推
.lower_margin = 6,同上,以此类推
.vsync_len = 16,同上,以此类推
这些数据的由来是我对比着2.6.24中自动生成lcdcon1-4寄存器值的函数[code]static 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);
}[/code]可以从这个函数中看到对TFT,如果你为STN就看另一个函数,对我们数据结构中的值进行了自动换算,所以我就根据QQ2440板载的2.6.13的相关数据结构(见本文最上边的结构值)进行了换算并赋值,例如S3C2410_LCDCON3_HFPD(var->left_margin - 1)的公式看一下最上边的是S3C2410_LCDCON3_HFPD(15),所以.left_margin = 16,同理,其他的数值以此换算,最后,在smdk2410_init()函数中增加s3c24xx_fb_set_platdata(&smdk2410_fb_info),问题解决了,屏出现了小企鹅。