解决了2440液晶LCD在内核linux2.6.26.3上的一个问题

    来自于: http://hi.baidu.com/excellentderek/blog/item/b1b460009eebb280e950cdca.html
由于项目需要,原来的2410升级了一下,改用s3c2440。这几天挺累的,1个礼拜画完了1块2440的6层板。2440其实还不错,就是停产了有点让人不放心。
本来移植好的全套内核和驱动这次不得已需要重新改一下。
这次用几乎是最新的2.6.26.3了,一切都很顺利。但是在LCD方面却遇到一个很诡异的问题。网上也找不到比较有用的信息,最后终于把问题解决了。现在最一下总结。
本来在2410的时候LCD驱动几乎没有问题,很顺利。买的NEC的640*480的液晶屏,用RGB565的方式接到ARM上,买好液晶屏的当天,我焊好后,按照数据手册设定好时序参数就OK了。
现在调的是用的utu2440的核心版做的(先期减少风险和投入所以用核心版)。这次其实对那些模式和寄存器很熟悉了,只不过2.6.26新内核换了平台参数声明
static struct s3c2410fb_display smdk2440_lcd_cfg __initdata = {

     .lcdcon5     = S3C2410_LCDCON5_FRM565 |
               S3C2410_LCDCON5_INVVLINE |
               S3C2410_LCDCON5_INVVFRAME |            
               S3C2410_LCDCON5_PWREN |
               S3C2410_LCDCON5_HWSWP,

     .type         = S3C2410_LCDCON1_TFT,

     .width         = 640,
     .height         = 480,

     .pixclock     = 40000,  
     .xres         = 640,
     .yres         = 480,
     .bpp         = 16,
     .left_margin     = 17,
     .right_margin     = 49,
     .hsync_len     = 97,
     .upper_margin     = 32,
     .lower_margin     = 13,
     .vsync_len     = 3,
};
变 成了xxx_margin,其实换汤不换药的,看看s3c2410_fb.c驱动就知道对应得时序参数了。然后是pixclock,这个照道理是 picosecond单位的。2440和2410都是HCLK=100M的,所以用原来2410上的就行了。或者看液晶屏手册要求像素是25.175M, 设置成39721(1/25.175MHZ,注意数量级单位)。

启动2440却发现情况不对,LCD要不就是黑屏,怎么调情况要么是偏的,都不理想。
用示波器看同步信号,发现HSYNC和VSYNC的极性和要求是相反的。这就奇怪了,应为已经在参数中加了
S3C2410_LCDCON5_INVVLINE 和   S3C2410_LCDCON5_INVVFRAME 来反向同步信号了,为什么还是极性不对。
后来发现去掉参数也是不对的,极性仍然相反。我很疑惑,我还以为芯片有BUG,怎么极性都改不过来。我开始真的没办法,还用了片74hc04反相器来反向这两个同步信号,但是结果发现效果并不好,还是图像偏掉。

于 是我很奇怪搜网上的资料,但是并没有得到太多结果。不过我看了很多厂家都在卖2440的板子,而且都配LCD屏,别人怎么就是好的呢。我有把问题定位到了 软件上。正好有utu2440的定制系统,弄了个厂家定制好的uboot进去,号称是由logo显示的,用示波器测了一下,惊奇的发现同步信号极性是正确 的,这就说明芯片本身没有问题。
然后用uboot的md命令dump关键的寄存器值。得到了结果:
4d000000: 04e80079 0577c241 017b1f0f 0000005f     y...A.w...{._...
4d000010: 00014b09 19800000 0005dc00 00000320     .K.......... ...
4d000020: 00000000 00000000 00000000 0000a5a5     ................
4d000030: 0ba5da65 000a5a5f 00000d6b 0eb7b5ed     e..._Z..k.......
4d000040: 00007dbe 0007ebdf 07fdfbfe 00000000     .}..............
4d000050: 00000000 00000000 00000003 00000003     ................
4d000060: 00000f82 ffffffff 00000006 00000000     ................
4d000070: 00000000 00000000 00000000 00000000     ................


GPCCON: 0xaaaaaaaa
GPCUP:   0x0000ffff
GPDCON: 0xaaaaaaaa
GPDUP:   0x0000ffff
CLOCKCON: 0007fff0

LCDCON1: 04e80079
100111010000000000001111001
ENVID + 16 bpp for TFT +TFT LCD panel
MMODE = 0
CLKVAL = 0

LCDCON2: 0577c241
101011101111100001001000001
VSPW = 000001 =1
VFPD = 00001001 = 9
LINEVAL = 0111011111 = 479
VBPD = 5

LCDCON3:017b1f0f
101111 01100011111 00001111
HFPD = 00001111 = 15
HOZVAL = 01100011111   =799
HBPD = 47

LCDCON4: 0000005f    
HSPW = 95
MVAL =0

LCDCON5:00014b09
10100 101100001001
HWSWP = 1
BSWP = 0
ENLEND = 0
PWREN = 1
INVLEND = 0
INVPWREN = 0
INVVDEN = 0
INVVD = 0
INVVFRAME = 1
INVVLINE = 1
INVVCLK = 0
FRM565 = 1
BPP24BL = 0

LCDSADDR1: 19800000
11001100 000000000000000000000

LCDSADDR2: 0005dc00

LCDSADDR3: 00000320    
1100100000
OFFSIZE =0
PAGEWIDTH = 800

REDLUT:00000000
GREENLUT:00000000
BLUELUT:00000000
DITHMODE:0

TPAL: 0
LCDINTPND:0
LCDSRCPND:0x03
LCDINTMSK:0x03 (MASKED)


TCONSEL:00000f82
1111 1000 0010
LPC_EN = 0 disable
RES_SEL = 1 (240*320)
MODE_SEL = 0 = sync mode
CPV_SEL = 0
LCC_EN = 0

之 后,我又阅读了s3c2410_fb.c的驱动,基本上LCDCON1-5寄存器都没问题。我就怀疑是TCONSEL寄存器,2440手册第435页,实 际上S3C2410_LPCSEL。这个东西是专门针对三星的液晶出的控制寄存器。驱动中似乎没有处理过这个。于是在驱动力加了段代码,
val = 0x0f82;
writel(val,regs + S3C2410_LPCSEL);

结果问题就迎刃而解。

今天我又看了一下,平台数据里面应该是设置这个值的。那么驱动就不用修改了。    
.lpcsel         = ((0xCE6) & ~7) | 1<<4,
直接把这个值重新设定一下

你可能感兴趣的:(c,linux,struct,三星,平台)