歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

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 結構
 
  1. struct fb_info {  
  2.     int node;  
  3.     int flags;  
  4.     struct mutex lock;      /* Lock for open/release/ioctl funcs */  
  5.     struct mutex mm_lock;       /* Lock for fb_mmap and smem_* fields */  
  6.     struct fb_var_screeninfo var;   /* Current var */  
  7.     struct fb_fix_screeninfo fix;   /* Current fix */  
  8.     struct fb_monspecs monspecs;    /* Current Monitor specs */  
  9.     struct work_struct queue;   /* Framebuffer event queue */  
  10.     struct fb_pixmap pixmap;    /* Image hardware mapper */  
  11.     struct fb_pixmap sprite;    /* Cursor hardware mapper */  
  12.     struct fb_cmap cmap;        /* Current cmap */  
  13.     struct list_head modelist;      /* mode list */  
  14.     struct fb_videomode *mode;  /* current mode */  
  15.   
  16. #ifdef CONFIG_FB_BACKLIGHT   
  17.     /* assigned backlight device */  
  18.     /* set before framebuffer registration,  
  19.        remove after unregister */  
  20.     struct backlight_device *bl_dev;  
  21.   
  22.     /* Backlight level curve */  
  23.     struct mutex bl_curve_mutex;      
  24.     u8 bl_curve[FB_BACKLIGHT_LEVELS];  
  25. #endif   
  26. #ifdef CONFIG_FB_DEFERRED_IO   
  27.     struct delayed_work deferred_work;  
  28.     struct fb_deferred_io *fbdefio;  
  29. #endif   
  30.   
  31.     struct fb_ops *fbops;  
  32.     struct device *device;      /* This is the parent */  
  33.     struct device *dev;     /* This is this fb device */     
  34.     int class_flag;                    /* private sysfs flags */  
  35. #ifdef CONFIG_FB_TILEBLITTING   
  36.     struct fb_tile_ops *tileops;    /* Tile Blitting */  
  37. #endif   
  38.     char __iomem *screen_base;  /* Virtual address */  
  39.     unsigned long screen_size;  /* Amount of ioremapped VRAM or 0 */   
  40.     void *pseudo_palette;       /* Fake palette of 16 colors */   
  41. #define FBINFO_STATE_RUNNING    0   
  42. #define FBINFO_STATE_SUSPENDED  1   
  43.     u32 state;          /* Hardware state i.e suspend */  
  44.     void *fbcon_par;                /* fbcon use-only private area */  
  45.     /* From here on everything is device dependent */  
  46.     void *par;  
  47.     /* we need the PCI or similiar aperture base/size not 
  48.        smem_start/size as smem_start may just be an object 
  49.        allocated inside the aperture so may not actually overlap */  
  50.     resource_size_t aperture_base;  
  51.     resource_size_t aperture_size;  
  52. };  
    這個結構是frambuffer驅動的基本數據結構,裡面包含了幀緩存設備的所有信息,每一個注冊成frambuffer接口的設備都應該聲明並初始化這樣一個結構。register_framebuffer 函數的參數就是這樣一個結構,fb_info在mini2440lcd驅動中是在s3c24xxfb_probe函數中分配並初始化的。其中struct fb_var_screeninfo結構包含了lcd顯示中可以改變的信息,結構如下:
 
  1. struct fb_var_screeninfo {  
  2.     __u32 xres;         /* 視口水平分辨率      */  
  3.     __u32 yres;  
  4.     __u32 xres_virtual;     /* 虛擬屏幕水平分辨率        */  
  5.     __u32 yres_virtual;  
  6.     __u32 xoffset;          /* 視口與虛擬屏幕水平分辨率偏移 */  
  7.     __u32 yoffset;            
  8.   
  9.   
  10.     __u32 bits_per_pixel;       /* 像素的位數            */  
  11.     __u32 grayscale;        /* 灰度標志,如果為1代表是灰度 */  
  12.   
  13.   
  14.     struct fb_bitfield red;     /* 如果是真彩色,這個是顏色位,如果不是那麼只有結構的大小重要,其他表示的信息無關緊要 */  
  15.     struct fb_bitfield green;     
  16.     struct fb_bitfield blue;  
  17.     struct fb_bitfield transp;  /* 透明度      */    
  18.   
  19.   
  20.     __u32 nonstd;           /* 非標准顏色表示標志位 */  
  21.     __u32 activate;         /* 參照 FB_ACTIVATE_*     */  
  22.     __u32 height;           /* 在內存地址空間的長度    */  
  23.     __u32 width;            /* 在內存地址空間的寬度     */  
  24.   
  25.   
  26.     __u32 accel_flags;      /* (不用了) 參照 fb_info.flags */  
  27.   
  28.   
  29.     /* 時序: 以下所有的值單位都是pixclock, 當然除了pixclock */  
  30.     __u32 pixclock;         /* 每秒像素值 */  
  31.     __u32 left_margin;      /* 從sync信號到顯示真正的像素的時鐘個數 */  
  32.     __u32 right_margin;     /* 從真正顯示像素到sync信號的時鐘個數  */  
  33.     __u32 upper_margin;     /* 上面兩個是針對列像素的,這個針對行的   */  
  34.     __u32 lower_margin;  
  35.     __u32 hsync_len;        /* 水平sync信號的長度  */  
  36.     __u32 vsync_len;        /* 垂直sync信號的長度  */  
  37.     __u32 sync;         /* 參照 FB_SYNC_*     */  
  38.     __u32 vmode;            /* 參照 FB_VMODE_*        */  
  39.     __u32 rotate;           /* angle we rotate counter clockwise */   
  40.     __u32 reserved[5];      /* 保留 */  
  41. };  
fb_fix_screeninfo包含了lcd顯示中不可改變的信息,結構如下:
  1. struct fb_fix_screeninfo {  
  2.     char id[16];            /* 身份表示符,例如 "TT Builtin" */  
  3.     unsigned long smem_start;   /* frame buffer內存的開始地址 */  
  4.                     /* (物理地址) */  
  5.     __u32 smem_len;         /* frame buffer內存地址的長度 */  
  6.     __u32 type;         /* 參照 FB_TYPE_*     */  
  7.     __u32 type_aux;         /* Interleave for interleaved Planes */  
  8.     __u32 visual;           /* 參照 FB_VISUAL_*       */   
  9.     __u16 xpanstep;         /* zero if no hardware panning  */  
  10.     __u16 ypanstep;         /* zero if no hardware panning  */  
  11.     __u16 ywrapstep;        /* zero if no hardware ywrap    */  
  12.     __u32 line_length;      /* 每行的長度,單位字節    */  
  13.     unsigned long mmio_start;   /* I/O 內存的開始地址   */  
  14.                     /* (物理地址) */  
  15.     __u32 mmio_len;         /* I/O內存的長度  */  
  16.     __u32 accel;            /* 對驅動程序的標示:是哪個設備*/  
  17.     __u16 reserved[3];      /* 保留 */  
  18. };  
其中倒數第三個成員par是設備自定義數據結構。在mini2440lcd驅動中為s3c2410fb_info,結構如下:
  1. struct s3c2410fb_info {  
  2.     struct device       *dev;  
  3.     struct clk      *clk;  
  4.   
  5.     struct resource     *mem; //io內存物理地址也就是寄存器的地址   
  6.     void __iomem        *io;  //用ioremap映射的io虛擬地址   
  7.     void __iomem        *irq_base; //中斷控制器寄存器對應的虛擬地址   
  8.   
  9.     enum s3c_drv_type   drv_type;  
  10.     struct s3c2410fb_hw regs;  
  11.   
  12.     unsigned long       clk_rate;  
  13.     unsigned int        palette_ready;  
  14.   
  15. #ifdef CONFIG_CPU_FREQ   
  16.     struct notifier_block   freq_transition;  
  17. #endif   
  18.   
  19.     /* keep these registers in case we need to re-write palette */  
  20.     u32         palette_buffer[256];  
  21.     u32         pseudo_pal[16];  
  22. };  
這個結構是和硬件相關的,包括寄存器的物理地址,虛擬地址和調色板的一些信息。這個結構也是在s3c24xxfb_probe中分配並初始化。
  2. static struct fb_ops 結構
  在mini2440lcd驅動中,fb_ops的初始化代碼如下:  
  1. static struct fb_ops s3c2410fb_ops = {  
  2.     .owner      = THIS_MODULE,  
  3.     .fb_check_var   = s3c2410fb_check_var,  
  4.     .fb_set_par = s3c2410fb_set_par,  
  5.     .fb_blank   = s3c2410fb_blank,  
  6.     .fb_setcolreg   = s3c2410fb_setcolreg,  
  7.     .fb_fillrect    = cfb_fillrect,  
  8.     .fb_copyarea    = cfb_copyarea,  
  9.     .fb_imageblit   = cfb_imageblit,  
  10. };  
這些函數是驅動程序必須實現的,他們實現的功能對應frambuffer核心的Ioctl系統調用,當應用程序調用ioctl系統調用的時候,他們會被直接或間接的調用。其中:

s3c2410fb_check_var 和s3c2410fb_set_par會由fb_set_var調用,對應Ioctl的FBIOPUT_VSCREENINFO命令

s3c2410fb_blank ,對應ioctl的FBIOBLANK命令,其他幾個函數也是類似。

  3. struct s3c2410fb_mach_info 結構
  1. struct s3c2410fb_mach_info {  
  2.     struct s3c2410fb_display *displays; /* attached diplays info */  
  3.     unsigned num_displays;          /* number of defined displays */  
  4.     unsigned default_display;  
  5.     /* GPIOs */  
  6.     unsigned long   gpcup;  
  7.     unsigned long   gpcup_mask;  
  8.     unsigned long   gpccon;  
  9.     unsigned long   gpccon_mask;  
  10.     unsigned long   gpdup;  
  11.     unsigned long   gpdup_mask;  
  12.     unsigned long   gpdcon;  
  13.     unsigned long   gpdcon_mask;  
  14.   
  15.     /* lpc3600 control register */  
  16.     unsigned long   lpcsel;  
  17. };  
這個結構包括一個s3c2410fb_display結構體,其他的域是GPIO寄存器的信息。mini2440lcd驅動中定義並初始化了這樣一個結構體:
  1. static struct s3c2410fb_mach_info mini2440_fb_info __initdata = {  
  2.     .displays   = &mini2440_lcd_cfg,  
  3.     .num_displays   = 1,  
  4.     .default_display = 0,  
  5.   
  6.     .gpccon =       0xaa955699,  
  7.     .gpccon_mask =  0xffc003cc,  
  8.     .gpcup =        0x0000ffff,  
  9.     .gpcup_mask =   0xffffffff,  
  10.   
  11.     .gpdcon =       0xaa95aaa1,  
  12.     .gpdcon_mask =  0xffc0fff0,  
  13.     .gpdup =        0x0000faff,  
  14.     .gpdup_mask =   0xffffffff,  
  15.   
  16.     .lpcsel     = 0xf82,  
  17. };  
這裡初始化了結構中的所有成員,s3c2410fb_display結構初始化成mini2440_lcd_cfg,這個結構的初始化是在/arch/arm/mach-s3c2440/mach-mini2440.c這個文件中。這裡設置了s3c2440 lcd控制器對應的GPIO寄存器的初始值,在s3c2410fb_init_registers函數中將這些值寫到相應的寄存器中。
  4. s3c2410fb_display 結構
  1. struct s3c2410fb_display {  
  2.     /* LCD type */  
  3.     unsigned type;  
  4.   
  5.     /* Screen size */  
  6.     unsigned short width;  
  7.     unsigned short height;  
  8.   
  9.     /* Screen info */  
  10.     unsigned short xres;  
  11.     unsigned short yres;  
  12.     unsigned short bpp;  
  13.   
  14.     unsigned pixclock;      /* pixclock in picoseconds */  
  15.     unsigned short left_margin;  /* value in pixels (TFT) or HCLKs (STN) */  
  16.     unsigned short right_margin; /* value in pixels (TFT) or HCLKs (STN) */  
  17.     unsigned short hsync_len;    /* value in pixels (TFT) or HCLKs (STN) */  
  18.     unsigned short upper_margin;    /* value in lines (TFT) or 0 (STN) */  
  19.     unsigned short lower_margin;    /* value in lines (TFT) or 0 (STN) */  
  20.     unsigned short vsync_len;   /* value in lines (TFT) or 0 (STN) */  
  21.   
  22.     /* lcd configuration registers */  
  23.     unsigned long   lcdcon5;  
  24. };  
這個結構體非常重要,他包括了一個lcd顯示的所有必須的配置信息。程序就是用這個結構體初始化fb_info結構中的fb_var_screeninfo相關成員的。最後這些值都會寫進lcd控制器的相應寄存器中。如上分析,這個結構在mini2440lcd驅動中被初始化成了mini2440_lcd_cfg,他定義在/arch/arm/mach-s3c2440/mach-mini2440.c,如下所示:
  1. static struct s3c2410fb_display mini2440_lcd_cfg __initdata = {  
  2.   
  3. #if !defined (LCD_CON5)   
  4.     .lcdcon5    = S3C2410_LCDCON5_FRM565 |  
  5.               S3C2410_LCDCON5_INVVLINE |  
  6.               S3C2410_LCDCON5_INVVFRAME |  
  7.               S3C2410_LCDCON5_PWREN |  
  8.               S3C2410_LCDCON5_HWSWP,  
  9. #else   
  10.     .lcdcon5    = LCD_CON5,  
  11. #endif   
  12.     .type       = S3C2410_LCDCON1_TFT,  
  13.     .width      = LCD_WIDTH,  
  14.     .height     = LCD_HEIGHT,  
  15.     .pixclock   = LCD_PIXCLOCK,  
  16.     .xres       = LCD_WIDTH,  
  17.     .yres       = LCD_HEIGHT,  
  18.     .bpp        = 16,  
  19.     .left_margin    = LCD_LEFT_MARGIN + 1,  
  20.     .right_margin   = LCD_RIGHT_MARGIN + 1,  
  21.     .hsync_len  = LCD_HSYNC_LEN + 1,  
  22.     .upper_margin   = LCD_UPPER_MARGIN + 1,  
  23.     .lower_margin   = LCD_LOWER_MARGIN + 1,  
  24.     .vsync_len  = LCD_VSYNC_LEN + 1,  
  25. };  
Copyright © Linux教程網 All Rights Reserved