您好,欢迎访问三七文档
当前位置:首页 > 商业/管理/HR > 信息化管理 > linux下LCD(framebuffer)驱动分析
/*本文档为s3c2440芯片lcd控制器驱动分析Kernel@2.6.32.2Author@Jwctly_Chen*/linux下framebuffer的驱动架构其实不是特别复杂,如果对其他子系统的架构,如网络驱动,I2C驱动等也有所了解的话.说的简单点,其实就是两个文件,/driver/video/fbmem.c以及s3c2410fb.c.当然,主要的数据结构,比较上层的,如structfb_info,structfb_var_screeninfo,structfb_fix_screeninfo等在/linux/fb.h中定义,而关于平台的一些数据结构则在相关的平台里定义,如/arch/arm/mach-s3c2440/文件夹下的文件mach-s3c2440.c以及/arch/arm/plat-s3cxx/devs.c中定义。fbmem.c中主要定义了与上层应用程序的接口函数:staticconststructfile_operationsfb_fops={.owner=THIS_MODULE,.read=fb_read,.write=fb_write,.unlocked_ioctl=fb_ioctl,#ifdefCONFIG_COMPAT.compat_ioctl=fb_compat_ioctl,#endif.mmap=fb_mmap,.open=fb_open,.release=fb_release,#ifdefHAVE_ARCH_FB_UNMAPPED_AREA.get_unmapped_area=get_fb_unmapped_area,#endif#ifdefCONFIG_FB_DEFERRED_IO.fsync=fb_deferred_io_fsync,#endif};上层应用程序通过这些函数实现对lcd各种参数的控制,修改等,这与以前编写字符设备驱动的模式一样,这些函数都是linux内核已经实现好的,不需要驱动工程师去编写.那驱动工程师的任务是什么呢?获取平台设备的相关信息,并初始化相关的硬件设备,注册中断,开辟帧缓冲内存,注册帧缓冲设备,这就是s3c2440fb.c中的主要内容了.里面有一个重要的数据结构:staticstructfb_opss3c2410fb_ops={.owner=THIS_MODULE,.fb_check_var=s3c2410fb_check_var,.fb_set_par=s3c2410fb_set_par,.fb_blank=s3c2410fb_blank,.fb_setcolreg=s3c2410fb_setcolreg,.fb_fillrect=cfb_fillrect,.fb_copyarea=cfb_copyarea,.fb_imageblit=cfb_imageblit,};这里的函数是真正对底层硬件进行操作的函数了,都是需要驱动工程师根据具体的硬件平台去填写.那么这些底层函数与上层应用程序的接口是怎样对接起来的呢?其实,是通过表征帧缓存设备的数据结构structfb_info来实现的,这个数据结构几乎包括了lcd控制器的所有信息:structfb_info{intnode;intflags;structmutexlock;/*Lockforopen/release/ioctlfuncs*/structmutexmm_lock;/*Lockforfb_mmapandsmem_*fields*/structfb_var_screeninfovar;/*Currentvar*/structfb_fix_screeninfofix;/*Currentfix*/structfb_monspecsmonspecs;/*CurrentMonitorspecs*/structwork_structqueue;/*Framebuffereventqueue*/structfb_pixmappixmap;/*Imagehardwaremapper*/structfb_pixmapsprite;/*Cursorhardwaremapper*/structfb_cmapcmap;/*Currentcmap*/structlist_headmodelist;/*modelist*/structfb_videomode*mode;/*currentmode*/#ifdefCONFIG_FB_BACKLIGHT/*assignedbacklightdevice*//*setbeforeframebufferregistration,removeafterunregister*/structbacklight_device*bl_dev;/*Backlightlevelcurve*/structmutexbl_curve_mutex;u8bl_curve[FB_BACKLIGHT_LEVELS];#endif#ifdefCONFIG_FB_DEFERRED_IOstructdelayed_workdeferred_work;structfb_deferred_io*fbdefio;#endifstructfb_ops*fbops;structdevice*device;/*Thisistheparent*/structdevice*dev;/*Thisisthisfbdevice*/intclass_flag;/*privatesysfsflags*/#ifdefCONFIG_FB_TILEBLITTINGstructfb_tile_ops*tileops;/*TileBlitting*/#endifchar__iomem*screen_base;/*Virtualaddress*/unsignedlongscreen_size;/*AmountofioremappedVRAMor0*/void*pseudo_palette;/*Fakepaletteof16colors*/#defineFBINFO_STATE_RUNNING0#defineFBINFO_STATE_SUSPENDED1u32state;/*Hardwarestatei.esuspend*/void*fbcon_par;/*fbconuse-onlyprivatearea*//*Fromhereoneverythingisdevicedependent*/void*par;/*weneedthePCIorsimiliaraperturebase/sizenotsmem_start/sizeassmem_startmayjustbeanobjectallocatedinsidetheaperturesomaynotactuallyoverlap*/resource_size_taperture_base;resource_size_taperture_size;};其中有几个重要的成员.structfb_var_screeninfovar表示的是lcd屏的可变参数,而structfb_fix_screeninfofix表示的是lcd屏的不变参数.structfb_ops*fbops当然就是上面那个重要结构的指针了.char__iomem*screen_base是申请的帧缓存的首地址(虚拟地址),unsignedlongscreen_size是缓存的大小.还要关注一下void*par这个指针,在初始化中,它用来指向自定义的一个数据结构structs3c2410fb_info,在以下的分析中会见到.structfb_info这个结构是怎样将上层的请求传递到下层的呢?其实就是staticconststructfile_operationsfb_fops结构中的成员函数根据需要调用了structfb_info结构中structfb_ops*fbops成员(不要将两者混淆了)中的相关函数,从而实现对lcd的参数读取、修改等,而structfb_info中包含了lcd屏的相关参数信息.structfb_ops*fbops中的成员函数只是在系统初始化模块时注册到内核中去的,只是存在于内核当中,等待被上层调用而已.整个的架构大致就是这样.用图表示出来就是:以下将从s3c2440的lcd驱动模块(文件s3c2410fb.c)分析开来,以线带面讲解下去,直到上层的用户程序.首先是lcd控制器驱动模块的注册:module_init(s3c2410fb_init);s3c2410fb_init()函数如下:int__inits3c2410fb_init(void){intret=platform_driver_register(&s3c2410fb_driver);if(ret==0)ret=platform_driver_register(&s3c2412fb_driver);returnret;}模块中同时注册了s3c2440和s3c2412两款芯片的lcd控制器驱动程序(几乎相同).structs3c2410fb_driver定义如下:staticstructplatform_drivers3c2410fb_driver={.probe=s3c2410fb_probe,.remove=s3c2410fb_remove,.suspend=s3c2410fb_suspend,.resume=s3c2410fb_resume,.driver={.name=s3c2410-lcd,.owner=THIS_MODULE,},};当注册平台驱动成功时,最终会调用s3c2410fb_probe函数.而这个函数根据具体的芯片类型,将不同参数传入s3c24xxfb_probe函数中,后者主要完成硬件资源的探测初始化,中断注册,开辟帧缓存空间,注册帧缓存设备等工作.下面着重来分析.staticint__inits3c24xxfb_probe(structplatform_device*pdev,enums3c_drv_typedrv_type){structs3c2410fb_info*info;structs3c2410fb_display*display;structfb_info*fbinfo;structs3c2410fb_mach_info*mach_info;structresource*res;intret;intirq;inti;intsize;u32lcdcon1;structs3c2410fb_info*info是在/drivers/video/s3c2410fb.h中定义的一个私有结构体,用来表示lcd控制器的硬件资源,如寄存器,中断号,时钟,临时调色板等.定义如下:structs3c2410fb_info{structdevice*dev;structclk*clk;structresource*mem;void__iomem*io;void__iomem*irq_base;enums3c_drv_typedrv_type;structs3c2410fb_hwregs;unsignedlongclk_rate;unsignedintpalette_ready;#ifdefCONFIG_CPU_FREQstructnotifier_blockfreq_transition;#endif/*keeptheseregistersincaseweneedtore-writepalette*/u32palette_buffer[256];u32pseudo_pal[16];};其中的成员structs3c2410fb_hw定义在arch/arm/mach-s3c2410/include/mach/fb.h中:structs3c2410fb_hw{unsignedlonglcdcon1;unsignedlonglcdcon2;unsignedlonglcdcon3;unsignedlonglcdcon4;unsignedlonglcdcon
本文标题:linux下LCD(framebuffer)驱动分析
链接地址:https://www.777doc.com/doc-3969156 .html