LCD动程序分析_第1页
LCD动程序分析_第2页
LCD动程序分析_第3页
已阅读5页,还剩27页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、*/*2007618*文件在/kernel/include/asm-arm/arch-s3c2410/bitfield.h中:#ifndef_ASSEMBLY_#defineUData(Data)(unsignedlong)(Data)#else#defineUData(Data)(Data)#endif例:UData(5);=5/* MACRO:Fld* Purpose* ThemacroFldencodesabitfield,givenitssizeanditsshiftvalue* withrespecttobit0.* Note* Amoreintuitivewaytoencodebi

2、tfieldswouldhavebeentousetheir* mask.However,extractingsizeandshiftvalueinformationfromabit* fieldsmaskiscumbersomeandmightbreaktheassembler(255-character* line-sizelimit).InputSizeSizeSizeofthebitfield,innumberofbits.ShftShiftvalueofthebitfieldwithrespecttobit0.OutputFldEncodedbitfield.*/#defineFld

3、(Size,Shft)(Size)16)例:FSize(0x20005);=2#defineFShft(Field)(Field)&OxOOOOFFFF)例:FShft(0x20005);=5/* MACRO:FInsrt* Purpose* ThemacroFinsrtinsertsavalueintoabitfieldbyshiftingthe* formerappropriately.*Input* ValueBit-fieldvalue.* FieldEncodedbitfield(usingthemacroFid).* Output* FlnsrtBit-fieldvalueposi

4、tionedappropriately.*/(UData(Value)FShft(Field)例:Finsrt(0x3,0x20005);=0x3max_xres*fbi-max_yres*fbi-max_bpp/en+PAGE_SIZE);fbi-map_cpu=consistent_alloc(GFP_KERNEL,fbi-map_size,&fbi-map_dma);if(fbi-map_cpu)fbi-screen_cpu=fbi-map_cpu+PAGE_SIZE;fbi-screen_dma=fbi-map_dma+PAGE_SIZE;fbi-fb.fix.smem_start=f

5、bi-screen_dma;在/kernel/include/asm-arm/proc-armo/page.h文件中:/*PAGE_SHIFTdeterminesthepagesize.Thisisconfigurable.*/#ifdefined(CONFIG_PAGESIZE_16)hereisnotinterruptcontextsafe.*Notethatthisdoes*not*zerotheallocatedarea!*/void*consistent_alloc(intgfp,size_tsize,dma_addr_t*dma_handle)这里首先计算出需要视频缓冲区的大小(L

6、CD屏的宽度*LCI屏的高度*每像素的位数/每字节的位数)en二240*320*16/8=0x25800=150K(9.375个PAGEPAGE_SHIFT=14PAGE_SIZE=1map_dma);最后得到:framebuffer(物理地址)I丨11map_dma|16K|分配了|1screen_dma=176K|共11个|160K=10个PAGEPAGE|160K|可以容下所需的150K视频缓冲区大小(16K)|.|*/*2007619*在/kernel/drivers/video/s3c2410fb.c文件中的s3c2410fb_activate_var函数中:unsignedlong

7、VideoPhysicalTemp=fbi-screen_dma;这里已经得到了framebuffer在内存中的起始地址为VideoPhysicalTemp,地址数据位为A30:0。new_regs.lcdcon1=fbi-reg.lcdcon1&LCD1_ENVID;new_regs.lcdcon2=(fbi-reg.lcdcon2&LCD2_LINEVAL_MSK)|LCD2_LINEVAL(var-yres-1);/*TFTLCDonly!*/new_regs.lcdcon3=(fbi-reg.lcdcon3&LCD3_HOZVAL_MSK)|LCD3_HOZVAL(var-xres-1

8、);new_regscdcon4二fbi-regcdcon4;new_regscdcon5=fbi-regcdcon5;LCDCON1首先需要禁止视频输出才能进行寄存器的设置,然后对LCDCON2LCDCON进行设置,主要是增加LINEVAL和HOZVAL这两个显示尺寸的参数。LCDCON4LCDCON按原来配置设置。LCDBANK29:21为系统内存中视频缓冲区在系统存储器内的段地址的A30:22LCDBASEU20:0为LCDframebuffer的起始地址的A21:1LCDBASEL20:0为LCDframebuffer的结束地址的A21:10FFSIZE21:11为某一行的第一个半字与

9、前一行最后一个半字之间的距离(单位:半字数,即2个字节)PAGEWIDTH10:0为显示存储区的可见帧宽度(单位:半字数,即2个字节)new_regscdsaddr1=LCDADDR_BANK(unsignedIong)VideoPhysicalTemp22)|LCDADDR_BASEU(unsignedIong)VideoPhysicalTemp1);new_regs.lcdsaddr2=LCDADDR_BASEL(unsignedIong)VideoPhysicalTemp+(var-xres*2*(varyres)1);这里LCDADDR_BASEL计算方法为用framebuffer在内

10、存中的起始地址VideoPhysicalTemp,加上framebuffer的大小(LCD屏的宽度*LCD屏的高度*每像素的位数/每字节的位数),得到framebuffer在内存中的结束地址,然后右移1位。new_regs.lcdsaddr3=LCDADDR_OFFSET(0)|(LCDADDR_PAGE(var-xres);这里PAGEWIDT的计算方法为:LCD屏的宽度*每像素的位数/16位(半字)。问题:以上这些操作是否已经对DMA控制器进行了设置?我认为这里将framebuffer在内存中的起始地址为VideoPhysicalTemp变换后载入LCDADDR1LCDADDR2LCDAD

11、DR中就已经完成了对LCDCDM控制器的源数据的基地址设置,当打开LCDCON1|=LCD1_ENVID后就可以由LCDCDM控制器自动从framebuffer中传数据到LCD屏幕了。在/kernel/drivers/video/s3c2410fb.c文件中的xxx_stnnfo结构体初始化中:lcdcon5:LCD5_FRM565|LCD5_INVVLINE|LCD5_INVVFRAME|LCD5_HWSWP|LCD5_PWREN,INVVCLK,INVLINE,INVFRAME,INVVD:通过前面的时序图,我们知道,CPU勺LCD空制器输出的时序默认是正脉冲,而LCD需要VSYNCVFR

12、AM)VLINE(HSYNC均为负脉冲,因此INVLINE和INVFRAME必须设为“1”,即选择反相输出。INVVDEN,INVPWRENINVLEND的功能同前面的类似。PWREN为LCD电源使能控制。在CPULC控制器的输出信号中,有一个电源使能管脚LCD_PWREN用来做为LCD屏电源的开关信其中LCD5_HWSW一项,设置了LCD从内存中显示数据时,经过了半字交换。16BPPDisplay(BSWP=0,HWSWP=0)D31:16D15:0000HP1P2004HP3P4008HP5P6(BSWP=0,HWSWP=1)D31:16D15:0000HP2P1004HP4P3008HP

13、6P5像素显示顺序如下:P1P2P3P4P5.例如:内存地址的数据为:0x11223344(32位)系统存储器采用Big-Endian(大端模式)存储格式,地址数据格式如下:D31:16D15:00001020300H0x110x220x330x44(0x1122)(0x3344)04H.08H.则首先显示0x3344的数据到第一个像素,然后再显示0x1122到第二个像素。系统存储器采用Little-Endian(小端模式)存储格式,地址数据格式如下:D31:16D15:00302010000H0x110x220x330x44(0x1122)(0x3344)04H.08H.0x1122到则首先

14、显示0x3344的数据到第一个像素,然后再显示第二个像素。*在/kernel/arch/arm/mm/consistent.c文件中的consistent_alloc函数中:void*consistent_alloc(intgfp,size_tsize,dma_addr_t*dma_handle)virt=page_address(page);*dma_handle=virt_to_bus(virt);ret=_ioremap(virt_to_phys(virt),size,0);这里调用该函数来分配一段内存空间有两个返回值,一个返回值返回给了ret指针,另一个返回值返回给了dma_handl

15、e指针。virt_to_bus和virt_to_phys函数的调用可以参考下面的分析。经过分析这两个函数作用一样,都是将virt这个虚拟地址转换为物理地址。所以返回给指针dma_handle的是所分配内存的起始地址(物理地址)。_ioremap函数的调用也可以参考下面的说明,该函数也返回所分配内存的起始地址(虚拟地址),不过是经过I/O内存映射的,把物理地址转换为了虚拟地址。这样一来就很清楚了,返回的framebuffer的物理地址给了扌旨针dma_handle,也就是fbi-map_dma,至Ufbi-screen_dma,再至,最后至U了指针VideoPhysicalTemp,这样写入到L

16、CDADDRLCDADDR寄存器中的framebuffer的地址其实都是物理地址。而返回的framebuffer的虚拟地址给了指针ret,也就是fbi-map_cpu,至Ufbi-screen_cpu,最后至U了display-screen_base(见/kernel/drivers/video/s3c2410fb.c文件中的s3c2410fb_set_var函数)。在/kernel/drivers/video/fbmem.c文件中:/* register_framebuffer-registersaframebufferdevice* fb_info:framebufferinfostruc

17、ture* Registersaframebufferdevicefbnfo.*Returnsnegativeerrnoonerror,orzeroforsuccess.*/intregister_framebuffer(structfbnfo*fbnfo)/*device* unregister_framebuffer-releasesaframebuffer* fb_info:framebufferinfostructureUnregistersaframebufferdevicefb_info.* Returnsnegativeerrnoonerror,orzeroforsuccess.

18、*/intunregister_framebuffer(structfbnfo*fbnfo)staticintfb_open(structinode*inode,structfile*file)staticintfb_release(structinode*inode,structfile*file)staticssize_tfb_read(structfile*file,char*buf,size_tcount,loff_t*ppos)staticssize_tfb_write(structfile*file,constchar*buf,size_tcount,loff_t*ppos)sta

19、ticintfb_ioctl(structinode*inode,structfile*file,unsignedintcmd,unsignedlongarg)staticintfb_mmap(structfile*file,structvm_area_struct*vma)在该文件中包含了所有驱动LCD的函数。在fb_read和fb_write这两个函数中,都对framebuffer进行了操作。fb_read函数中:char*base_addr;base_addr=info-disp-screen_base;count-=copy_to_user(buf,base_addr+p,count)

20、;fb_write函数中:char*base_addr;base_addr=info-disp-screen_base;count-=copy_from_user(base_addr+p,buf,count);所读写的framebuffer的基地址就是disp-screen_base,也就是fbi-screen_cpu所指的framebuffer的虚拟地址。从而得到:framebuffer(虚拟地址)|.|11map_cpu|16K|分配了|1screen_cpu=display-screen_base176K|共11个|160K=10个PAGEPAGE|160K|可以容下所需的150K视频缓

21、冲区大小(16K)|III.|其中display-screen_base结构在/kernel/include/video/fbcon.h文件中定义。得出结论,在分配framebuffer时一共返回两个指针,虽然是同一块内存空间,但一个返回的是实际的物理地址,另一个返回的是经过地址转换的虚拟地址。在设置LCD控制器中framebuffer起始地址寄存器时,用的是所分配内存的物理地址;而当要对framebuffer进行读写操作时,用的是同一块内存的物理地址所转换后的虚拟地址。由此可以知道,内核在对每个I/O地址进行读写操作时用的都是经过转换的虚拟地址。在/kernel/include/asm-ar

22、m/arch-s3c2410/memory.h文件中:/*Pageoffset:3GB*/#definePAGE_OFFSET(OxcOOOOOOOUL)#definePHYS_OFFSET(0x30000000UL)/* Wetakeadvantageofthefactthatphysicalandvirtualaddresscanbethe* saem.ThuNUMAodeishandlingthelargeholesthatmightexistbetween虚拟地址转为物理地址宏:_virt_to_phys(x)=(x)-(PAGE_OFFSET-PHYS_OFFSET)=(x)-PAG

23、E_OFFSET|卜PHYS_OFFSET物理地址转为虚拟地址宏:_phys_to_virt(x)=(x)+(PAGE_OFFSET-PHYS_OFFSET)=(x)+PAGE_OFFSET-PHYS_OFFSET内核虚拟地址和实际物理地址仅仅是相差一个偏移量(PAGE_OFFS)T可以很方便的将其转化为物理内存地址,同时内核也提供了virt_to_phys()函数将内核虚拟空间中的物理影射区地址转化为物理地址。/* VirtualviewDMAviewmemoryaddresstranslations* virt_to_bus:Usedtotranslatethevirtualaddress

24、toan* addresssuitabletobepassedtoset_dma_addr* bus_to_virt:UsedtoconvertanaddressforDMAoperations* toanaddressthatthekernelcanuse.*/#definevirttobusisamacro#definebustovirtisamacro#define_virt_to_bus(x)_virt_to_phys(x)#define_bus_to_virt(x)_phys_to_virt(x)这里注意:_virt_to_bus(x)就等于_virt_to_phys(x)在/ker

25、nel/include/asm-arm/memory.h文件中:/* Theseare*only*validonthekerneldirectmappedRAMmemory.*/staticinlineunsignedlongvirt_to_phys(volatilevoid*x)return_virt_to_phys(unsignedIong)(x);/* VirtualDMAviewmemoryaddresstranslationsAgain,theseare*only*validonthekerneldirectmaRAM*memory.*/#definevirt_to_bus(x)(_

26、virt_to_bus(unsignedlong)(x)由上面的分析可知:virt_to_bus(x)和virt_to_phys(volatilevoid*x)这两个函数调用的都是_virt_to_phys(x)即(x)-PAGE_OFFSET+PHYS_OFFSET)所以这两个调用都是将虚拟地址转换为了物理地址。在/kernel/arch/arm/mm/ioremap.c文件中:/* Remapanarbitraryphysicaladdressspaceintothekernelvirtual* addressspace.Neededwhenthekernelwantstoaccesshi

27、ghaddresses* directly.* NOTE!Weneedtoallownon-page-alignedmappingstoo:wewillobviously* havetoconvertthemintoanoffsetinapage-alignedmapping,butthe* callershouldntneedtoknowthatsmalldetail.* flagsaretheextraL_PTE_flagsthatyouwanttospecifyforthis* mapping.Seeinclude/asm-arm/proc-armv/pgtable.hformorein

28、formation.*/void*_ioremap(unsignedlongphys_addr,size_tsize,unsignedlongflags)ioremap函数的作用是将physicaladdress以及busaddress映射为kernel的virtualadrress。ioremap的作用是把I/O内存地址(物理地址)映射到虚拟地址空间,使用之前需要分配I/O内存区域。但是,ioremap函数的内部实现并不是简单的(10的物理地址)-0x10000000+0xE4000000。所以,得到的虚拟地址可能是不同的。因为linux用的是页面映射机制,CPU不能按物理地址来访问存储空间

29、,而必须使用虚拟地址,所以必须反向的从物理地址出发找到一片虚存空间并建立起映射。/*2007622在/kernel/drivers/video/fbmem.c文件中:staticstructfile_operationsfb_fops=owner:THIS_MODULE,read:fb_read,write:fb_write,ioctl:fb_ioctl,mmap:fb_mmap,open:fb_open,release:fb_release,#ifdefHAVE_ARCH_FB_UNMAPPED_AREAget_unmapped_area:get_fb_unmapped_area,#endi

30、f;这个结构中定义了对LCD所分配的framebuffer进行读写操作,以及一些内存映射之类的函数,这些源函数都在该文件中。/* register_framebuffer-registersaframebufferdevice* fb_info:framebufferinfostructure* Registersaframebufferdevicefbnfo.* Returnsnegativeerrnoonerror,orzeroforsuccess.*/intregister_framebuffer(structfbnfo*fbnfo)这个是对LCD的framebuffer设备进行注册时调

31、用到的注册函数,该函数在/kernel/drivers/video/s3c2410fb.c文件的s3c2410fb_init函数里的最后部分被调用。fb_info-devfs_handle=devfs_register(devfs_handle,name_buf,DEVFS_FL_DEFAULT,FB_MAJOR,i,S_IFCHR|S_IRUGO|SWUGO,&fb_fops,NULL);在注册函数的最后部分,将前面的fb_fops结构里的各个驱动函数的入口点传入到devfs_register()设备注册函数中。*/*2007626上面这个devfs_register函数(原型在/kerne

32、l/fs/devfs/base.c文件中)执行前,在fbmemnit函数中调用了函数:devfs_handle=devfs_mk_dir(NULL,fb,NULL);在/kernel/fs/devfs/base.c在/kernel/fs/devfs/base.c文件中:* devfs_mk_dir-Createadirectoryinthedevfsnamespace* dir:Thehandletotheparentdevfsdirectoryentry.Ifthisis%NULLthe* newnameisrelativetotherootofthedevfs.* name:Thename

33、oftheentry.* info:Anarbitrarypointerwhichwillbeassociatedwiththeentry.* Useofthisfunctionisoptional.Thedevfs_register()function* willautomaticallycreateintermediatedirectoriesasneeded.Thisfunction* isprovidedforefficiencyreasons,asitprovidesahandletoadirectory.* Returnsahandlewhichmaylaterbeusedinac

34、alltodevfs_unregister().* Onfailure%NULLisreturned.*/devfs_handle_tdevfs_mk_dir(devfs_handle_tdir,constchar*name,void*info)这个devfs_mk_dir函数会在设备文件系统中创建一个名为fb的目录,并返回一个带有devfs设备文件系统目录结构的数据结构变量devfs_handle。然后把这个数据结构作为下一步调用devfs_register函数时的参数,该参数在调用设备文件系统注册清除函数devfs_unregister时也要作为参数传入。/* devfs_register-Registeradeviceentry.* dir:Thehandletotheparentdevfsdirectoryentry.Ifthisis%NULLthe* newnameisrelativetotherootofthedevfs.* name:Thenameo

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论