先说明下软件平台:
linux:2.6.35
android: 2.3.4
CPU: 三星S5PV210
显示屏分辨率:1024*768
bug现象:
在玩捕鱼达人游戏的时候屏抖动,有的是在主界面抖,有的是撒网抖动,有的是换网/炮的大小抖动。并且在初步测试中发现还和音频等应用有关,现象飘忽不定。最后紧紧围绕lcd驱动查找原因,经过同事帮忙测试,以及查找原因,已经解决,修改方法如下:
1.使用free run模式
文件:\drivers\video\samsung\s3cfb_fimd6x.c
函数:s3cfb_set_clock
修改方法:S3C_VIDCON0_VCLKEN_NORMAL改为S3C_VIDCON0_VCLKEN_FREERUN
2.修改vclk,使其处于正常状态。之前我们设置的83Mhz已经超过了cpu所允许的66MHz。
datasheet中有写The maximum frequency of VCLK is 66MHz.
文件:\drivers\video\samsung\s3cfb_lcd_info.c
数组:g_s3cfb_lcd_para[]
修改方法:将1024x768分辨率的clk_div改为3,此时vclk=166/3=55Mhz 帧率56hz,接近lcd屏的参考帧率,之前的vclk为80多MHz,帧率也达到了80多Hz,太高了。
注意:
还发现一个bug:我们在s3cfb_set_clock函数里面加了自己指定div的代码,但是并不完善。修改之前是这样的:
#if defined(CONFIG_FB_MSD_LCD)
if (ctrl->lcd->clk_div != 0){
div = ctrl->lcd->clk_div;
}else{
div = (int) (src_clk / vclk);
}
#else
div = src_clk / vclk;
#endif
if (src_clk % vclk)
div++;
if ((src_clk/div) > maxclk)
dev_info(ctrl->dev, "vclk(%d) should be smaller than %d Hz\n",
src_clk/div, maxclk);
既然指定就直接写死,不允许再有类似以下的判断
if (src_clk % vclk)
div++;
所以把这个包到#else里面去了,以绝后患,修改如下:
#if defined(CONFIG_FB_MSD_LCD)
if (ctrl->lcd->clk_div != 0){
div = ctrl->lcd->clk_div;
}else{
div = (int) (src_clk / vclk);
}
#else
div = src_clk / vclk;
if (src_clk % vclk)
div++;
if ((src_clk/div) > maxclk)
dev_info(ctrl->dev, "vclk(%d) should be smaller than %d Hz\n",
src_clk/div, maxclk);
#endif
还有一个极为恼人的是三星代码的bug。开始我div指定为3的是发现其实效果是4,难道是没有减1,仔细看了看设置是有减1操作的。最后加打印消息发现,cfg在设置之前bit[6]就是1,div-1之后只是简单的与了cfg,竟然没有清零!!!
直接在前面cfg初始化的时候加入清零操作。
修改前:
cfg &= ~(S3C_VIDCON0_CLKSEL_MASK | S3C_VIDCON0_CLKVALUP_MASK |
S3C_VIDCON0_VCLKEN_MASK | S3C_VIDCON0_CLKDIR_MASK );
修改后:
cfg &= ~(S3C_VIDCON0_CLKSEL_MASK | S3C_VIDCON0_CLKVALUP_MASK |
S3C_VIDCON0_VCLKEN_MASK | S3C_VIDCON0_CLKDIR_MASK | S3C_VIDCON0_CLKVAL_F(0xFF));
至此修改完毕,进入系统用工具读到0xF800_0000这个寄存器的值应该是0xB7.(修改之前是0x57)
boot中也要改成以上参数。
此BUG的解决完全归功于晓亮同学,当时正值5.1,公司放假三天,我因事回广西,只能拜托他帮忙。
他加班了两天,终于把此问题解决,保证了出货。
特写此文章感谢。