您的位置:首页 > 其它

mini2440驱动分析之LCD

2013-09-05 20:42 507 查看



[日期:2011-10-04]来源:Linux社区 作者:yaozhenguo2006
四. frambuffer驱动模型fb_ops各函数的实现

由s3c2410fb_ops结构可以看出,mini2440lcd驱动主要实现了下面几个函数:

s3c2410fb_check_var

s3c2410fb_set_par

s3c2410fb_blank

s3c2410fb_setcolreg

cfb_fillrect

cfb_copyarea

cfb_imageblit

其中最重要的是s3c2410fb_set_par,这个函数根据fbinfo的值初始化了底层的lcd控制器,重点分析这个函数。他由fb_set_var调用,对应则frambufer核心ioctl中的FBIOPUT_VSCREENINFO命令。其他的函数也是为了完成lcd的相关功能而编写的,与具体实现的功能有关。s3c2410fb_set_par函数定义如下:

static int s3c2410fb_set_par(struct fb_info *info)
{
struct fb_var_screeninfo *var = &info->var;

switch (var->bits_per_pixel) {
case 32:
case 16:
case 12:
info->fix.visual = FB_VISUAL_TRUECOLOR;
break;
case 1:
info->fix.visual = FB_VISUAL_MONO01;
break;
default:
info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
break;
}

info->fix.line_length = (var->xres_virtual * var->bits_per_pixel) / 8;
/* activate this new configuration */
s3c2410fb_activate_var(info);
return 0;
}

可以看出,这个函数除了根据fbinfo的像素位来赋值fix.visual外,主要是调用了s3c2410fb_activate_var函数:

static void s3c2410fb_activate_var(struct fb_info *info)
{
struct s3c2410fb_info *fbi = info->par;
void __iomem *regs = fbi->io;
int type = fbi->regs.lcdcon1 & S3C2410_LCDCON1_TFT;
struct fb_var_screeninfo *var = &info->var;
int clkdiv;

clkdiv = DIV_ROUND_UP(s3c2410fb_calc_pixclk(fbi, var->pixclock), 2);

dprintk("%s: var->xres = %d\n", __func__, var->xres);
dprintk("%s: var->yres = %d\n", __func__, var->yres);
dprintk("%s: var->bpp = %d\n", __func__, var->bits_per_pixel);

if (type == S3C2410_LCDCON1_TFT) {
//判断lcd型号,我们的lcd是TFT型lcd,所以下面语句执行
s3c2410fb_calculate_tft_lcd_regs(info, &fbi->regs);
//这个函数主要的功能就是将info中的lcd配置相关的值赋值给s3c2410fb_info结构的regs成员
//这个regs是一个s3c2410fb_hw结构,这个结构就是定义了5个lcd控制寄存器lcdcon1~5
--clkdiv;
if (clkdiv < 0)
clkdiv = 0;
} else {
//如果是STN型的lcd,那么执行下面的函数。因为s3c2440的lcd控制器由有几个专门用于控制STN型lcd的寄存器,所以要单独设置
s3c2410fb_calculate_stn_lcd_regs(info, &fbi->regs);
if (clkdiv < 2)
clkdiv = 2;
}

fbi->regs.lcdcon1 |= S3C2410_LCDCON1_CLKVAL(clkdiv);
/* write new registers */
dprintk("new register set:\n");
dprintk("lcdcon[1] = 0x%08lx\n", fbi->regs.lcdcon1);
dprintk("lcdcon[2] = 0x%08lx\n", fbi->regs.lcdcon2);
dprintk("lcdcon[3] = 0x%08lx\n", fbi->regs.lcdcon3);
dprintk("lcdcon[4] = 0x%08lx\n", fbi->regs.lcdcon4);
dprintk("lcdcon[5] = 0x%08lx\n", fbi->regs.lcdcon5);

writel(fbi->regs.lcdcon1 & ~S3C2410_LCDCON1_ENVID,
regs + S3C2410_LCDCON1);
writel(fbi->regs.lcdcon2, regs + S3C2410_LCDCON2);
writel(fbi->regs.lcdcon3, regs + S3C2410_LCDCON3);
writel(fbi->regs.lcdcon4, regs + S3C2410_LCDCON4);
writel(fbi->regs.lcdcon5, regs + S3C2410_LCDCON5);
//将配置值写入五个寄存器
/* set lcd address pointers */
s3c2410fb_set_lcdaddr(info);
//设置显存地址寄存器,设置为我们分配的那块内存,设置之后,lcd控制器就会在这块内存取数据送往lcd显示

fbi->regs.lcdcon1 |= S3C2410_LCDCON1_ENVID,
//打开视频显示,这样lcd就可以正确显示了
writel(fbi->regs.lcdcon1, regs + S3C2410_LCDCON1);
}

五. 总结

mini2440lcd驱动分别涉及到了platform和frambuffer核心,利用这两个核心实现其功能。刚开始分析这个驱动的时候,总是感觉很乱没有重点。我想这个主要是和自己对frambuffer和lcd显示还不熟悉的原因。看了几天过后才逐渐有点眉目。最让人迷惑的就是如何设置lcd控制器的寄存器问题。我以前认为这个应该在probe函数中设置,一般来说这个函数检测设备状态,初始化设备,然后设备就绪,应用程序就可以操作了。但是在s3c2410fb_probe中只是设置了相关的GPIO接口寄存器,根本没有设置lcd控制寄存器。后来发现是在s3c2410fb_set_par函数中设置的。这个函数对应用户空间ioctl的FBIOPUT_VSCREENINFO。也就是说应用程序必须调用ioctl(fd,FBIOPUT_VSCREENINFO,struct
fb_var_screeninfo *var)才能设置正确的lcd状态,但是这个命令有一个参数是fb_var_screeninfo结构,也就意味这应用程序必须填充这样一个结构,才可以调用ioctl。这样一来内核初始化的默认配置信息就没用了。唯一的办法是先调用ioctl(fd,FBIOGET_VSCREENINFO,struct fb_var_screeninfo *var)获得这个结构,然后修改之后在调用ioctl(fd,FBIOPUT_VSCREENINFO,struct fb_var_screeninfo
*var)将修改的值写入。我在MiniGUI的源码中验证了这个推论,在MiniGUI的fbcon图形引擎中的FB_SetVideoMode函数中,有如下的调用

if ( ioctl(console_fd, FBIOGET_VSCREENINFO, &vinfo) < 0 ) {
GAL_SetError("NEWGAL>FBCON: Couldn't get console pixel format\n");
FB_VideoQuit(this);
return(-1);
}

然后就是设置finfo中需要改变的值,最后有下面的代码来设置lcd控制寄存器器

if ( ioctl(console_fd, FBIOPUT_VSCREENINFO, &vinfo) < 0 ) {
vinfo.yres_virtual = height;
if ( ioctl(console_fd, FBIOPUT_VSCREENINFO, &vinfo) < 0 ) {
GAL_SetError("NEWGAL>FBCON: Couldn't set console screen info");
return(NULL);
}
}

关于lcd驱动还有好多知识要学,比如mmap操作。mmap是一般lcd应用程序运行的模式,他将显存映射到用户空间,提高系统的性能。因为自己只是为了熟悉一下这个驱动,所以没有深入看下去。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: