linux2628下6410LCD驱动分析.docx

上传人:b****5 文档编号:7390893 上传时间:2023-01-23 格式:DOCX 页数:27 大小:49.07KB
下载 相关 举报
linux2628下6410LCD驱动分析.docx_第1页
第1页 / 共27页
linux2628下6410LCD驱动分析.docx_第2页
第2页 / 共27页
linux2628下6410LCD驱动分析.docx_第3页
第3页 / 共27页
linux2628下6410LCD驱动分析.docx_第4页
第4页 / 共27页
linux2628下6410LCD驱动分析.docx_第5页
第5页 / 共27页
点击查看更多>>
下载资源
资源描述

linux2628下6410LCD驱动分析.docx

《linux2628下6410LCD驱动分析.docx》由会员分享,可在线阅读,更多相关《linux2628下6410LCD驱动分析.docx(27页珍藏版)》请在冰豆网上搜索。

linux2628下6410LCD驱动分析.docx

linux2628下6410LCD驱动分析

linux2.6.28下6410LCD驱动分析

本文不详细分析lcd的每行代码 ,只是做简单的构架分析,  要详细的分析可以参考

   LCD驱动是用了device和driver架构,首先看arch/arm/mach-s3c6410/mach-smdk6410.c文件,在353行有这样一个数组

staticstructplatform_device*smdk6410_devices[]__initdata={

……………………

&s3c_device_lcd,

……………………

}

我们在进里面了解详情,在arch/arm/palt-s3c64xx/devs.c文件里有s3c_device_lcd变量的定义

staticstructresources3c_lcd_resource[]={

 [0]={

  .start=S3C64XX_PA_LCD,                         //lcd寄存器的起始地址

  .end  =S3C64XX_PA_LCD+SZ_1M-1,    //lcd寄存器的结束地址,

  .flags=IORESOURCE_MEM,

 },

 [1]={

  .start=IRQ_LCD_VSYNC,                        //lcd中断寄存器起始地址,在s3cfb_probe用

  .end  =IRQ_LCD_SYSTEM,

  .flags=IORESOURCE_IRQ,

 }

};

staticu64s3c_device_lcd_dmamask=0xffffffffUL;

structplatform_devices3c_device_lcd={

 .name   ="s3c-lcd",                                              //这个会和driver中的name一样,driver

                                                                             //根据这个进行匹配

 .id   =-1,

 .num_resources  =ARRAY_SIZE(s3c_lcd_resource),

 .resource  =s3c_lcd_resource,

 .dev             ={

  .dma_mask  =&s3c_device_lcd_dmamask,

  .coherent_dma_mask =0xffffffffUL

 }

};

在arch/arm/mach-s3c6410/mach-smdk6410.c文件的

staticvoid__initsmdk6410_machine_init(void)函数中有这么一句话

platform_add_devices(smdk6410_devices,ARRAY_SIZE(smdk6410_devices));

这个就是对device设备进行注册,在注册driver驱动时,会根据name找到相应的device进行匹配,然后会调用probe。

   下面分析driver,在drivers/video/samsung/s3cfb.c文件的最下面有这样的一段代码

staticstructplatform_drivers3cfb_driver={

 .probe  =s3cfb_probe,                      //匹配的话会调用这个函数

 .remove  =s3cfb_remove,

 .suspend =s3cfb_suspend,

 .resume  =s3cfb_resume,

       .driver  ={

  .name ="s3c-lcd",                                 //上面说的,内核会根据这个来找到相应的device

  .owner =THIS_MODULE,

 },

};

int__devinits3cfb_init(void)

{

 returnplatform_driver_register(&s3cfb_driver);//进行drive注册

}

匹配后会掉用s3cfb_probe();

这个函数里面对fbinfo进行初始化,对相关寄存器进行初始化,在6410lcd驱动中,主要要修改的几个文件是:

drivers/video/samsung目录下的s3cfb.c,假设你在配置的时候即用makemenuconfig命令,在里面选择的是480WV,他对应的文件时s3cfb_lte480wv.c,s3cfb_lte480wv.c是和屏参数相关的文件。

还有个要改的文件是s3cfb_fimd4x.c,这个文件主要是涉及寄存器的一些参数的配置。

   主要几个重点:

对构架的分析,理清楚各个文件的关系。

s3cfb.c中的s3cfb_probe主要是在根据s3cfb_fimd4x.c和s3cfb_lte480wv.c文件来初始fbinfo,并且写相关LCD寄存器。

s3cfb_lte480wv.c主要是记录屏的参数,在这里进行修改来满足不同的lcd屏。

s3cfb_fimd4x.c是对寄存器的值进行初始化,比如各个窗口的显示模式、颜色表寄存器的模式、各个窗口的控制寄存器,此文件还包含6410对于lcd的特殊功能,用ioctl来进行实现的。

fbmem.c这个是fb字符设备驱动,每个窗口都是一个字符设备,在s3cfb_probe中通过调用register_buffer进行注册,注意,里面有一个fb_notifier_call_chain,他最终会调用drivers/video/console/fbcon.c中的fbcon_init,里面会有对logo的调用;fbmem.c文件里还有通用的ioctl功能调用,适合所有带lcd控制器的处理器,这个文件时通用的,每个处理器的fbmem都是一样的,做成了和硬件无关。

 

                                                lcd驱动简单构架图 

abc

s3c2410_lcd&framebuffer驱动分析

int__inits3c2410fb_probe(structdevice*dev)

{

   structs3c2410fb_info*info;

   structfb_info     *fbinfo;

   structplatform_device*pdev=to_platform_device(dev);

   structs3c2410fb_hw*mregs;

   intret;

   intirq;

   inti;

   mach_info=dev->platform_data;//获取lcd相关寄存器配置信息

   if(mach_info==NULL){

      dev_err(dev,"noplatformdataforlcd,cannotattach\n");

      return-EINVAL;

   }

   mregs=&mach_info->regs;

   irq=platform_get_irq(pdev,0);

   if(irq<0){

      dev_err(dev,"noirqfordevice\n");

      return-ENOENT;

   }

   fbinfo=framebuffer_alloc(sizeof(structs3c2410fb_info),dev);//分配structfb_info和structs3c2410fb_info结构

   if(!

fbinfo){

      return-ENOMEM;

   }

   info=fbinfo->par;//调用framebuffer_alloc分配内存的时候,其实顺带分配了structs3c2410fb_info结构,紧跟structfb_info结构的后面,fbinfo->par指针处。

   info->fb=fbinfo;

   dev_set_drvdata(dev,fbinfo);

   s3c2410fb_init_registers(info);//lcd相关寄存器配置

   dprintk("devinit\n");

   strcpy(fbinfo->fix.id,driver_name);

   /*配置信息存储起来,以后用到*/

   memcpy(&info->regs,&mach_info->regs,sizeof(info->regs));

   info->mach_info         =dev->platform_data;

   /*以下配置,详细请参考网上资料*/

   fbinfo->fix.type      =FB_TYPE_PACKED_PIXELS;

   fbinfo->fix.type_aux      =0;

   fbinfo->fix.xpanstep      =0;

   fbinfo->fix.ypanstep      =0;

   fbinfo->fix.ywrapstep      =0;

   fbinfo->fix.accel      =FB_ACCEL_NONE;

   fbinfo->var.nonstd      =0;

   fbinfo->var.activate      =FB_ACTIVATE_NOW;

   /*设置分辨率*/

   fbinfo->var.height      =mach_info->height;

   fbinfo->var.width      =mach_info->width;

   fbinfo->var.accel_flags    =0;

   fbinfo->var.vmode      =FB_VMODE_NONINTERLACED;

   fbinfo->fbops         =&s3c2410fb_ops;//重要的fop结构(fb设备本质上是字符设备)

   fbinfo->flags         =FBINFO_FLAG_DEFAULT;

   fbinfo->pseudo_palette     =&info->pseudo_pal;

   fbinfo->var.xres      =mach_info->xres.defval;

   fbinfo->var.xres_virtual   =mach_info->xres.defval;

   fbinfo->var.yres      =mach_info->yres.defval;

   fbinfo->var.yres_virtual   =mach_info->yres.defval;

   fbinfo->var.bits_per_pixel =mach_info->bpp.defval;

   fbinfo->var.upper_margin   =S3C2410_LCDCON2_GET_VBPD(mregs->lcdcon2)+1;

   fbinfo->var.lower_margin   =S3C2410_LCDCON2_GET_VFPD(mregs->lcdcon2)+1;

   fbinfo->var.vsync_len      =S3C2410_LCDCON2_GET_VSPW(mregs->lcdcon2)+1;

   fbinfo->var.left_margin      =S3C2410_LCDCON3_GET_HFPD(mregs->lcdcon3)+1;

   fbinfo->var.right_margin   =S3C2410_LCDCON3_GET_HBPD(mregs->lcdcon3)+1;

   fbinfo->var.hsync_len      =S3C2410_LCDCON4_GET_HSPW(mregs->lcdcon4)+1;

   /*配色板设置(采用5、6、5模式)*/

   fbinfo->var.red.offset     =11;

   fbinfo->var.green.offset   =5;

   fbinfo->var.blue.offset    =0;

   fbinfo->var.transp.offset  =0;

   fbinfo->var.red.length     =5;

   fbinfo->var.green.length   =6;

   fbinfo->var.blue.length    =5;

   fbinfo->var.transp.length  =0;

   /*计算需要申请的framerbuffer大小(以字节为单位)*/

   fbinfo->fix.smem_len       =   mach_info->xres.max*

                        mach_info->yres.max*

                        mach_info->bpp.max/8;

   for(i=0;i<256;i++)

      info->palette_buffer[i]=PALETTE_BUFF_CLEAR;

   if(!

request_mem_region((unsignedlong)S3C24XX_VA_LCD,SZ_1M,"s3c2410-lcd")){

      ret=-EBUSY;

      gotodealloc_fb;

   }

   dprintk("gotLCDregion\n");

   ret=request_irq(irq,s3c2410fb_irq,SA_INTERRUPT,pdev->name,info);

   if(ret){

      dev_err(dev,"cannotgetirq%d-err%d\n",irq,ret);

      ret=-EBUSY;

      gotorelease_mem;

   }

   info->clk=clk_get(NULL,"lcd");

   if(!

info->clk||IS_ERR(info->clk)){

      printk(KERN_ERR"failedtogetlcdclocksource\n");

      ret=-ENOENT;

      gotorelease_irq;

   }

   clk_use(info->clk);

   clk_enable(info->clk);

   dprintk("gotandenabledclock\n");

   msleep

(1);

   /*Initializevideomemory*/

   ret=s3c2410fb_map_video_memory(info);

   if(ret){

      printk(KERN_ERR"FailedtoallocatevideoRAM:

%d\n",ret);

      ret=-ENOMEM;

      gotorelease_clock;

   }

   dprintk("gotvideomemory\n");

   ret=s3c2410fb_init_registers(info);//怎么再次初始化lcd相关寄存器了?

   ret=s3c2410fb_check_var(&fbinfo->var,fbinfo);//注册framebuffer前的一个例行检查

   ret=register_framebuffer(fbinfo);

   if(ret<0){

      printk(KERN_ERR"Failedtoregisterframebufferdevice:

%d\n",ret);

      gotofree_video_memory;

   }

   /*createdevicefiles*/

   device_create_file(dev,&dev_attr_debug);

   printk(KERN_INFO"fb%d:

%sframebufferdevice\n",

      fbinfo->node,fbinfo->fix.id);

   return0;

free_video_memory:

   s3c2410fb_unmap_video_memory(info);

release_clock:

   clk_disable(info->clk);

   clk_unuse(info->clk);

   clk_put(info->clk);

release_irq:

   free_irq(irq,info);

release_mem:

    release_mem_region((unsignedlong)S3C24XX_VA_LCD,S3C24XX_SZ_LCD);

dealloc_fb:

   framebuffer_release(fbinfo);

   returnret;

}

/*

 *s3c2410fb_map_video_memory():

 *   AllocatestheDRAMmemoryfortheframebuffer. Thisbufferis

 *   remappedintoanon-cached,non-buffered,memoryregionto

 *   allowpaletteandpixelwritestooccurwithoutflushingthe

 *   cache. Oncethisareaisremapped,allvirtualmemory

 *   accesstothevideomemoryshouldoccuratthenewregion.

 */

staticint__inits3c2410fb_map_video_memory(structs3c2410fb_info*fbi)

{

   dprintk("map_video_memory(fbi=%p)\n",fbi);

   fbi->map_size=PAGE_ALIGN(fbi->fb->fix.smem_len+PAGE_SIZE);//页对齐

   fbi->map_cpu =dma_alloc_writecombine(fbi->dev,fbi->map_size,

                     &fbi->map_dma,GFP_KERNEL);//目前我只知道用于分配可供dma使用的内存,其中返回地址fbi->map_cpu为虚拟地址,fbi->map_dma为物理地址。

   fbi->map_size=fbi->fb->fix.smem_len;//恢复真实的大小

   if(fbi->map_cpu){

      /*preventinitialgarbageonscreen*/

      dprintk("map_video_memory:

clear%p:

%08x\n",

         fbi->map_cpu,fbi->map_size);

      memset(fbi->map_cpu,0xf0,fbi->map_size);

      fbi->screen_dma      =fbi->map_dma;//物理地址

      fbi->fb->screen_base   =fbi->map_cpu;//虚拟地址

      fbi->fb->fix.smem_start =fbi->screen_dma;//物理地址

      dprintk("map_video_memory:

dma=%08xcpu=%psize=%08x\n",

         fbi->map_dma,fbi->map_cpu,fbi->fb->fix.smem_len);

   }

   returnfbi->map_cpu?

0:

-ENOMEM;

}

staticstructs3c2410fb_mach_infosbc2410_lcdcfg__initdata={

      .fixed_syncs=0,

      .regs={

          .lcdcon1=S3C2410_LCDCON1_TFT16BPP|\

                    S3C2410_LCDCON1_TFT|\

                    S3C2410_LCDCON1_CLKVAL(6),

          .lcdcon2=S3C2410_LCDCON2_VBPD

(2)|\

                    S3C2410_LCDCON2_LINEVAL(319)|\

                    S3C2410_LCDCON2_VFPD(0)|\

                    S3C2410_LCDCON2_

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 高等教育 > 理学

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1