mini2440驱动分析之LCD

发布时间:2016-12-8 8:19:17 编辑:www.fx114.net 分享查询网我要评论
本篇文章主要介绍了"mini2440驱动分析之LCD",主要涉及到mini2440驱动分析之LCD方面的内容,对于mini2440驱动分析之LCD感兴趣的同学可以参考一下。

[日期: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应用程序运行的模式,他将显存映射到用户空间,提高系统的性能。因为自己只是为了熟悉一下这个驱动,所以没有深入看下去。

上一篇:poj1014-Dividing
下一篇:1362 循环左移字符串

相关文章

相关评论