mini2440驱动分析之LCD
mini2440驱动分析之LCD
mini2440集成了lcd控制器的接口,板子上接的lcd硬件是统宝240*320,TFT型lcd。lcd驱动对应的文件为s3c2410fb.c。要读懂这个驱动必须了解linux platform子系统的知识。因为这个驱动是以platform驱动的形式注册到内核。而且还需要frambuffer驱动的知识,因为这个驱动还是frambuffer接口的。lcd驱动在模块初始化的时候,调用platform注册函数将自己注册到内核,利用linux设备模型核心的机制调用platform_bus总线的match函数找到相应的设备,然后由linux设备模型核心调用s3c2410fb.c中的s3c2410fb_probe ,进行硬件相关初始化,并初始化frambuffer结构。然后注册到frambuffer核心。lcd的功能实现通过frambuffer核心来完成。s3c2410fb.c的功能实现都是配合frambuffer核心的。下面详细分析lcd驱动的实现。程序基本结构
1.模块初始化-->向platform核心注册自己
2.实现linux设备模型必须的probe函数-->向frambuffer核心注册自己(最重要)
resume函数-->系统在由挂起恢复的时候调用
suspand-->系统在挂起的时候调用
remove--> 驱动程序注销自己的时候调用
3.frambuffer驱动模型fb_ops各函数的实现-->实现fb驱动的ioctl命令需要的函数
4.其他函数-->由2.3.中的函数调用,帮助其实现功能。
一. 相关数据结构1. struct fb_info 结构
- struct fb_info {
- int node;
- int flags;
- struct mutex lock; /* Lock for open/release/ioctl funcs */
- struct mutex mm_lock; /* Lock for fb_mmap and smem_* fields */
- struct fb_var_screeninfo var; /* Current var */
- struct fb_fix_screeninfo fix; /* Current fix */
- struct fb_monspecs monspecs; /* Current Monitor specs */
- struct work_struct queue; /* Framebuffer event queue */
- struct fb_pixmap pixmap; /* Image hardware mapper */
- struct fb_pixmap sprite; /* Cursor hardware mapper */
- struct fb_cmap cmap; /* Current cmap */
- struct list_head modelist; /* mode list */
- struct fb_videomode *mode; /* current mode */
- #ifdef CONFIG_FB_BACKLIGHT
- /* assigned backlight device */
- /* set before framebuffer registration,
- remove after unregister */
- struct backlight_device *bl_dev;
- /* Backlight level curve */
- struct mutex bl_curve_mutex;
- u8 bl_curve[FB_BACKLIGHT_LEVELS];
- #endif
- #ifdef CONFIG_FB_DEFERRED_IO
- struct delayed_work deferred_work;
- struct fb_deferred_io *fbdefio;
- #endif
- struct fb_ops *fbops;
- struct device *device; /* This is the parent */
- struct device *dev; /* This is this fb device */
- int class_flag; /* private sysfs flags */
- #ifdef CONFIG_FB_TILEBLITTING
- struct fb_tile_ops *tileops; /* Tile Blitting */
- #endif
- char __iomem *screen_base; /* Virtual address */
- unsigned long screen_size; /* Amount of ioremapped VRAM or 0 */
- void *pseudo_palette; /* Fake palette of 16 colors */
- #define FBINFO_STATE_RUNNING 0
- #define FBINFO_STATE_SUSPENDED 1
- u32 state; /* Hardware state i.e suspend */
- void *fbcon_par; /* fbcon use-only private area */
- /* From here on everything is device dependent */
- void *par;
- /* we need the PCI or similiar aperture base/size not
- smem_start/size as smem_start may just be an object
- allocated inside the aperture so may not actually overlap */
- resource_size_t aperture_base;
- resource_size_t aperture_size;
- };
- struct fb_var_screeninfo {
- __u32 xres; /* 视口水平分辨率 */
- __u32 yres;
- __u32 xres_virtual; /* 虚拟屏幕水平分辨率 */
- __u32 yres_virtual;
- __u32 xoffset; /* 视口与虚拟屏幕水平分辨率偏移 */
- __u32 yoffset;
- __u32 bits_per_pixel; /* 像素的位数 */
- __u32 grayscale; /* 灰度标志,如果为1代表是灰度 */
- struct fb_bitfield red; /* 如果是真彩色,这个是颜色位,如果不是那么只有结构的大小重要,其他表示的信息无关紧要 */
- struct fb_bitfield green;
- struct fb_bitfield blue;
- struct fb_bitfield transp; /* 透明度 */
- __u32 nonstd; /* 非标准颜色表示标志位 */
- __u32 activate; /* 参照 FB_ACTIVATE_* */
- __u32 height; /* 在内存地址空间的长度 */
- __u32 width; /* 在内存地址空间的宽度 */
- __u32 accel_flags; /* (不用了) 参照 fb_info.flags */
- /* 时序: 以下所有的值单位都是pixclock, 当然除了pixclock */
- __u32 pixclock; /* 每秒像素值 */
- __u32 left_margin; /* 从sync信号到显示真正的像素的时钟个数 */
- __u32 right_margin; /* 从真正显示像素到sync信号的时钟个数 */
- __u32 upper_margin; /* 上面两个是针对列像素的,这个针对行的 */
- __u32 lower_margin;
- __u32 hsync_len; /* 水平sync信号的长度 */
- __u32 vsync_len; /* 垂直sync信号的长度 */
- __u32 sync; /* 参照 FB_SYNC_* */
- __u32 vmode; /* 参照 FB_VMODE_* */
- __u32 rotate; /* angle we rotate counter clockwise */
- __u32 reserved[5]; /* 保留 */
- };
- struct fb_fix_screeninfo {
- char id[16]; /* 身份表示符,例如 "TT Builtin" */
- unsigned long smem_start; /* frame buffer内存的开始地址 */
- /* (物理地址) */
- __u32 smem_len; /* frame buffer内存地址的长度 */
- __u32 type; /* 参照 FB_TYPE_* */
- __u32 type_aux; /* Interleave for interleaved Planes */
- __u32 visual; /* 参照 FB_VISUAL_* */
- __u16 xpanstep; /* zero if no hardware panning */
- __u16 ypanstep; /* zero if no hardware panning */
- __u16 ywrapstep; /* zero if no hardware ywrap */
- __u32 line_length; /* 每行的长度,单位字节 */
- unsigned long mmio_start; /* I/O 内存的开始地址 */
- /* (物理地址) */
- __u32 mmio_len; /* I/O内存的长度 */
- __u32 accel; /* 对驱动程序的标示:是哪个设备*/
- __u16 reserved[3]; /* 保留 */
- };
- struct s3c2410fb_info {
- struct device *dev;
- struct clk *clk;
- struct resource *mem; //io内存物理地址也就是寄存器的地址
- void __iomem *io; //用ioremap映射的io虚拟地址
- void __iomem *irq_base; //中断控制器寄存器对应的虚拟地址
- enum s3c_drv_type drv_type;
- struct s3c2410fb_hw regs;
- unsigned long clk_rate;
- unsigned int palette_ready;
- #ifdef CONFIG_CPU_FREQ
- struct notifier_block freq_transition;
- #endif
- /* keep these registers in case we need to re-write palette */
- u32 palette_buffer[256];
- u32 pseudo_pal[16];
- };
2. static struct fb_ops 结构
在mini2440lcd驱动中,fb_ops的初始化代码如下:
- static struct fb_ops s3c2410fb_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,
- };
s3c2410fb_check_var 和s3c2410fb_set_par会由fb_set_var调用,对应Ioctl的FBIOPUT_VSCREENINFO命令
s3c2410fb_blank ,对应ioctl的FBIOBLANK命令,其他几个函数也是类似。
3. struct s3c2410fb_mach_info 结构- struct s3c2410fb_mach_info {
- struct s3c2410fb_display *displays; /* attached diplays info */
- unsigned num_displays; /* number of defined displays */
- unsigned default_display;
- /* GPIOs */
- unsigned long gpcup;
- unsigned long gpcup_mask;
- unsigned long gpccon;
- unsigned long gpccon_mask;
- unsigned long gpdup;
- unsigned long gpdup_mask;
- unsigned long gpdcon;
- unsigned long gpdcon_mask;
- /* lpc3600 control register */
- unsigned long lpcsel;
- };
- static struct s3c2410fb_mach_info mini2440_fb_info __initdata = {
- .displays = &mini2440_lcd_cfg,
- .num_displays = 1,
- .default_display = 0,
- .gpccon = 0xaa955699,
- .gpccon_mask = 0xffc003cc,
- .gpcup = 0x0000ffff,
- .gpcup_mask = 0xffffffff,
- .gpdcon = 0xaa95aaa1,
- .gpdcon_mask = 0xffc0fff0,
- .gpdup = 0x0000faff,
- .gpdup_mask = 0xffffffff,
- .lpcsel = 0xf82,
- };
4. s3c2410fb_display 结构
- struct s3c2410fb_display {
- /* LCD type */
- unsigned type;
- /* Screen size */
- unsigned short width;
- unsigned short height;
- /* Screen info */
- unsigned short xres;
- unsigned short yres;
- unsigned short bpp;
- unsigned pixclock; /* pixclock in picoseconds */
- unsigned short left_margin; /* value in pixels (TFT) or HCLKs (STN) */
- unsigned short right_margin; /* value in pixels (TFT) or HCLKs (STN) */
- unsigned short hsync_len; /* value in pixels (TFT) or HCLKs (STN) */
- unsigned short upper_margin; /* value in lines (TFT) or 0 (STN) */
- unsigned short lower_margin; /* value in lines (TFT) or 0 (STN) */
- unsigned short vsync_len; /* value in lines (TFT) or 0 (STN) */
- /* lcd configuration registers */
- unsigned long lcdcon5;
- };
- static struct s3c2410fb_display mini2440_lcd_cfg __initdata = {
- #if !defined (LCD_CON5)
- .lcdcon5 = S3C2410_LCDCON5_FRM565 |
- S3C2410_LCDCON5_INVVLINE |
- S3C2410_LCDCON5_INVVFRAME |
- S3C2410_LCDCON5_PWREN |
- S3C2410_LCDCON5_HWSWP,
- #else
- .lcdcon5 = LCD_CON5,
- #endif
- .type = S3C2410_LCDCON1_TFT,
- .width = LCD_WIDTH,
- .height = LCD_HEIGHT,
- .pixclock = LCD_PIXCLOCK,
- .xres = LCD_WIDTH,
- .yres = LCD_HEIGHT,
- .bpp = 16,
- .left_margin = LCD_LEFT_MARGIN + 1,
- .right_margin = LCD_RIGHT_MARGIN + 1,
- .hsync_len = LCD_HSYNC_LEN + 1,
- .upper_margin = LCD_UPPER_MARGIN + 1,
- .lower_margin = LCD_LOWER_MARGIN + 1,
- .vsync_len = LCD_VSYNC_LEN + 1,
- };
|
评论暂时关闭