framebuffer 子系统分析

来源:互联网 发布:程序员入门必看的书籍 编辑:程序博客网 时间:2024/05/16 15:52

一、常见结构体分析

1、fb_info

[cpp] view plain copy
print?
  1. struct fb_info {  
  2.     int node;  
  3.     int flags;  
  4.     struct mutex lock;      /* 调用open/release/ioctl时的锁 */  
  5.     struct mutex mm_lock;       /* fb_mmap和smem_*的锁 */  
  6.     struct fb_var_screeninfo var;   /* 当前LCD的可变参数 */  
  7.     struct fb_fix_screeninfo fix;   /* 当前LCD的固定参数 */  
  8.     struct fb_monspecs monspecs;    /* 当前LCD标准 */  
  9.     struct work_struct queue;   /* 帧缓冲工作队列 */  
  10.     struct fb_pixmap pixmap;    /* 图像硬件mapper */  
  11.     struct fb_pixmap sprite;    /* 光标硬件mapper */  
  12.     struct fb_cmap cmap;        /* 当前LCD的颜色表 */  
  13.     struct list_head modelist;      /* mode list */  
  14.     struct fb_videomode *mode;  /* 当前的video模式 */  
  15.   
  16. #ifdef CONFIG_FB_BACKLIGHT  
  17.     /* 对应的背光设备,在framebuffer之前注册及其之后注销 */  
  18.     struct backlight_device *bl_dev;  
  19.   
  20.     /* 背光等级调整 */  
  21.     struct mutex bl_curve_mutex;      
  22.     u8 bl_curve[FB_BACKLIGHT_LEVELS];  
  23. #endif  
  24. #ifdef CONFIG_FB_DEFERRED_IO  
  25.     struct delayed_work deferred_work;  
  26.     struct fb_deferred_io *fbdefio;  
  27. #endif  
  28.   
  29.     struct fb_ops *fbops;           /* 帧缓冲底层操作函数接口 */  
  30.     struct device *device;      /* 父设备 */  
  31.     struct device *dev;     /* fb设备*/  
  32.     int class_flag;                    /* 私有sysfs标志 */  
  33. #ifdef CONFIG_FB_TILEBLITTING  
  34.     struct fb_tile_ops *tileops;    /* Tile Blitting */  
  35. #endif  
  36.     char __iomem *screen_base;  /* 虚拟基地址即framebuffer起始虚拟地址 */  
  37.     unsigned long screen_size;  /* 显存大小 */   
  38.     void *pseudo_palette;       /* 伪16色颜色表 */   
  39. #define FBINFO_STATE_RUNNING    0  
  40. #define FBINFO_STATE_SUSPENDED  1  
  41.     u32 state;          /* Hardware state i.e suspend */  
  42.     void *fbcon_par;                /* fbcon use-only private area */  
  43.     /* 私有数据 */  
  44.     void *par;  
  45.     /* we need the PCI or similiar aperture base/size not 
  46.        smem_start/size as smem_start may just be an object 
  47.        allocated inside the aperture so may not actually overlap */  
  48.     struct apertures_struct {  
  49.         unsigned int count;  
  50.         struct aperture {  
  51.             resource_size_t base;  
  52.             resource_size_t size;  
  53.         } ranges[0];  
  54.     } *apertures;  
  55. };  
帧缓冲设备中最关键的数据结构就是fb_info,其中记录了设备的全部信息,包括设备的设置参数、状态以及操作函数指针,每一个帧缓冲设备必须对应一个fb_info结构体。

2、fb_var_screeninfo 和 fb_fix_screeninfo

[cpp] view plain copy
print?
  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.     __u32 bits_per_pixel;       /* 每个像素点占用的位数 */  
  10.     __u32 grayscale;        /* 非0时指灰度值 */  
  11.   
  12.     struct fb_bitfield red;     /* fb内存的RGB位域 */  
  13.     struct fb_bitfield green;  
  14.     struct fb_bitfield blue;  
  15.     struct fb_bitfield transp;  /* 透明度 */     
  16.   
  17.     __u32 nonstd;           /* 非0时代指非标准像素格式 */  
  18.   
  19.     __u32 activate;         /* see FB_ACTIVATE_* */  
  20.   
  21.     __u32 height;           /* 高度 mm */  
  22.     __u32 width;            /* 宽度 mm */  
  23.   
  24.     __u32 accel_flags;      /* (OBSOLETE) see fb_info.flags */  
  25.   
  26.     /* 时序: 除pixel以外,其他的都以像素时钟为单位 */  
  27.     __u32 pixclock;         /* 像素时钟(皮秒) */  
  28.     __u32 left_margin;      /* 行前肩:从行同步信号到有效数据开始的时钟数 */  
  29.     __u32 right_margin;     /* 行后肩:从有效数据末尾到行同步信号的时钟数 */  
  30.     __u32 upper_margin;     /* 帧前肩:从帧同步信号到有效行开始的行数 */  
  31.     __u32 lower_margin;             /* 帧后肩:从有效行末尾到帧同步信号的行数 */  
  32.     __u32 hsync_len;        /* 行同步信号占用的时钟数 */  
  33.     __u32 vsync_len;        /* 帧同步信号占用的行数 */  
  34.     __u32 sync;         /* see FB_SYNC_*        */  
  35.     __u32 vmode;            /* see FB_VMODE_*       */  
  36.     __u32 rotate;           /* 旋转角度 */  
  37.     __u32 reserved[5];      /* 保留备用 */  
  38. };  

[cpp] view plain copy
print?
  1. struct fb_fix_screeninfo {  
  2.     char id[16];            /* 标识符 */  
  3.     unsigned long smem_start;   /* framebuffer的物理起始地址 */  
  4.     __u32 smem_len;         /* framebuffer的长度 */  
  5.     __u32 type;         /* see FB_TYPE_*        */  
  6.     __u32 type_aux;         /* 隔行扫描参数 */  
  7.     __u32 visual;           /* see FB_VISUAL_*      */   
  8.     __u16 xpanstep;         /* zero if no hardware panning  */  
  9.     __u16 ypanstep;         /* zero if no hardware panning  */  
  10.     __u16 ywrapstep;        /* zero if no hardware ywrap    */  
  11.     __u32 line_length;      /* 一行的字节数 */  
  12.     unsigned long mmio_start;   /* 内存映射I/O的物理起始地址 */  
  13.     __u32 mmio_len;         /* 内存映射I/O的长度 */  
  14.     __u32 accel;              
  15.     __u16 reserved[3];      /* 保留备用 */  
  16. };  
这两个结构体分别记录了显示器可以修改和不可修改的信息,这些数据成员需要在驱动程序中初始化。其中fix.visual代表显示器使用的色彩模式,Linux中支持的色彩模式如下:

[cpp] view plain copy
print?
  1. #define FB_VISUAL_MONO01        0   /* 黑白. 1=Black 0=White */  
  2. #define FB_VISUAL_MONO10        1   /* 黑白. 1=White 0=Black */  
  3. #define FB_VISUAL_TRUECOLOR     2   /* 真彩色,由红绿蓝三基色构成*/  
  4. #define FB_VISUAL_PSEUDOCOLOR       3   /* 伪彩色,采用索引颜色 */  
  5. #define FB_VISUAL_DIRECTCOLOR       4   /* 查表显示 */  
  6. #define FB_VISUAL_STATIC_PSEUDOCOLOR    5   /* 只读的伪彩色 */  

fb_bitfield结构体描述每一个像素在显示缓冲区中的组织方式。

[cpp] view plain copy
print?
  1. struct fb_bitfield {  
  2.     __u32 offset;           /* 位域偏移 */  
  3.     __u32 length;           /* 位域长度 */  
  4.     __u32 msb_right;        /* != 0 : 最高有效位在右边 */   
  5. };  

3、fb_ops

[cpp] view plain copy
print?
  1. struct fb_ops {  
  2.     /* 打开/释放 */  
  3.     struct module *owner;  
  4.     int (*fb_open)(struct fb_info *info, int user);  
  5.     int (*fb_release)(struct fb_info *info, int user);  
  6.   
  7.     /* 下面两个函数是非线性布局的/常规内存映射无法工作的缓冲设备需要的接口 */  
  8.     ssize_t (*fb_read)(struct fb_info *info, char __user *buf,  
  9.                size_t count, loff_t *ppos);  
  10.     ssize_t (*fb_write)(struct fb_info *info, const char __user *buf,  
  11.                 size_t count, loff_t *ppos);  
  12.   
  13.     /* 检测可变参数并调整到支持的值 */  
  14.     int (*fb_check_var)(struct fb_var_screeninfo *var, struct fb_info *info);  
  15.   
  16.     /* 根据info->var设置video模式 */  
  17.     int (*fb_set_par)(struct fb_info *info);  
  18.   
  19.     /* 设置颜色寄存器 */  
  20.     int (*fb_setcolreg)(unsigned regno, unsigned red, unsigned green,  
  21.                 unsigned blue, unsigned transp, struct fb_info *info);  
  22.   
  23.     /* 批量设置颜色寄存器 */  
  24.     int (*fb_setcmap)(struct fb_cmap *cmap, struct fb_info *info);  
  25.   
  26.     /* 清屏 */  
  27.     int (*fb_blank)(int blank, struct fb_info *info);  
  28.   
  29.     /* pan display */  
  30.     int (*fb_pan_display)(struct fb_var_screeninfo *var, struct fb_info *info);  
  31.   
  32.     /* 绘制一个矩形 */  
  33.     void (*fb_fillrect) (struct fb_info *info, const struct fb_fillrect *rect);  
  34.     /* 拷贝数据 */  
  35.     void (*fb_copyarea) (struct fb_info *info, const struct fb_copyarea *region);  
  36.     /* 绘制一幅图像 */  
  37.     void (*fb_imageblit) (struct fb_info *info, const struct fb_image *image);  
  38.   
  39.     /* 绘制光标 */  
  40.     int (*fb_cursor) (struct fb_info *info, struct fb_cursor *cursor);  
  41.   
  42.     /* 旋转显示 */  
  43.     void (*fb_rotate)(struct fb_info *info, int angle);  
  44.   
  45.     /* 等待blit空闲(可选) */  
  46.     int (*fb_sync)(struct fb_info *info);  
  47.   
  48.     /* ioctl函数(可选) */  
  49.     int (*fb_ioctl)(struct fb_info *info, unsigned int cmd,  
  50.             unsigned long arg);  
  51.   
  52.     /* 32位的compat ioctl(可选) */  
  53.     int (*fb_compat_ioctl)(struct fb_info *info, unsigned cmd,  
  54.             unsigned long arg);  
  55.   
  56.     /* fb特定的mmap */  
  57.     int (*fb_mmap)(struct fb_info *info, struct vm_area_struct *vma);  
  58.   
  59.     /* 根据var得到显示器的功能信息 */  
  60.     void (*fb_get_caps)(struct fb_info *info, struct fb_blit_caps *caps,  
  61.                 struct fb_var_screeninfo *var);  
  62.   
  63.     /* 销毁fb */  
  64.     void (*fb_destroy)(struct fb_info *info);  
  65. };  

fb_ops是驱动编写人员应该实现的底层函数接口。

4、tccfb_info

[cpp] view plain copy
print?
  1. struct tccfb_info {  
  2.     struct fb_info      *fb;  // fbi结构体  
  3.     struct device       *dev;  
  4.   
  5.     //struct tccfb_mach_info *mach_info;  
  6.   
  7.     /* raw memory addresses */  
  8.     dma_addr_t      map_dma;    /* physical */  
  9.     u_char *        map_cpu;    /* virtual */  
  10.     u_int           map_size;  
  11.   
  12.     /* addresses of pieces placed in raw buffer */  
  13.     u_char *        screen_cpu; /* virtual address of buffer */  
  14.     dma_addr_t      screen_dma; /* physical address of buffer */  
  15.   
  16.     u_int           imgch;  
  17.   
  18.     struct tccfb_platform_data *pdata;  
  19. #ifdef CONFIG_HAS_EARLYSUSPEND  
  20.     struct early_suspend early_suspend;  
  21.     struct early_suspend earlier_suspend;  
  22. #endif  
  23. };  

二、framebuffer注册流程分析

[cpp] view plain copy
print?
  1. static struct platform_driver tccfb_driver = {  // 底层函数接口  
  2.     .probe      = tccfb_probe,  
  3.     .remove     = tccfb_remove,  
  4.     .suspend    = tccfb_suspend,  
  5.     .shutdown   = tccfb_shutdown,  
  6.     .resume     = tccfb_resume,  
  7.     .driver     = {  
  8.         .name   = "tccxxx-lcd",  
  9.         .owner  = THIS_MODULE,  
  10.     },  
  11. };  
  12.   
  13. static int __init tccfb_init(void)  
  14. {  
  15.     printk(KERN_INFO " %s (built %s %s)\n", __func__, __DATE__, __TIME__);  
  16.   
  17.     fb_power_state = 1;  
  18.   
  19.     tca_fb_init();   // 初始化控制器  
  20.   
  21. #ifdef TCC_VIDEO_DISPLAY_BY_VSYNC_INT   // 初始化锁  
  22.     spin_lock_init(&vsync_lock) ;  
  23.     spin_lock_init(&vsync_lockDisp ) ;  
  24. #endif  
  25.   
  26.     return platform_driver_register(&tccfb_driver);  
  27. }  
  28.   
  29. static void __exit tccfb_cleanup(void)  
  30. {  
  31.     tca_fb_cleanup();  // 注销控制器  
  32.     platform_driver_unregister(&tccfb_driver);  
  33. }  
  34.   
  35. module_init(tccfb_init);  
  36. module_exit(tccfb_cleanup);  
其中
[cpp] view plain copy
print?
  1. int tca_fb_init(void)  // 该函数主要完成LCD控制器时钟和DDI_CACHE的初始化  
  2. {  
  3.     struct lcd_panel *lcd_info;  
  4.     pmap_t pmap_fb_video;  
  5.   
  6.     printk(KERN_INFO " tcc92xx %s (built %s %s)\n", __func__, __DATE__, __TIME__);  
  7.   
  8.     pmap_get_info("fb_video", &pmap_fb_video);  
  9.   
  10. #ifdef TCC_LCDC1_USE  // 获取控制器地址  
  11.     pLCDC = (volatile PLCDC)tcc_p2v(HwLCDC1_BASE);  
  12. #ifdef CONFIG_ARCH_TCC92XX  
  13.     pLCDC_FB_CH = (volatile PLCDC_CHANNEL)tcc_p2v(pLCDC->LI2C);  
  14. #else  
  15.     pLCDC_FB_CH = (volatile PLCDC_CHANNEL)tcc_p2v(HwLCDC1_CH_BASE(2));  
  16. #endif//  
  17.     Fb_Lcdc_num = 1;  
  18. #else  
  19.     pLCDC = (volatile PLCDC)tcc_p2v(HwLCDC0_BASE);  
  20. #ifdef CONFIG_ARCH_TCC92XX  
  21.     pLCDC_FB_CH = (volatile PLCDC_CHANNEL)tcc_p2v(HwLCDC0_CH_BASE(0));  
  22. #else  
  23.     pLCDC_FB_CH = (volatile PLCDC_CHANNEL)tcc_p2v(HwLCDC0_CH_BASE(2));  
  24. #endif//  
  25.     Fb_Lcdc_num = 0;  
  26. #endif//    TCC_LCDC1_USE  
  27.   
  28.     tca92xxfb_clock_init();  // 初始化时钟  
  29.     tca92xxfb_clock_set(PWR_CMD_ON);  // 打开时钟  
  30.   
  31.     tcc_ddi_cache_setting();  // 设置DDI_CACHE  
  32.   
  33.     TCC_OUTPUT_LCDC_Init();  // 初始化控制器  
  34.   
  35.     init_waitqueue_head(&lcdc_struct.waitq);  
  36.     lcdc_struct.state = 1;  
  37.   
  38.     #ifdef CONFIG_FB_M2M_COPY  
  39.     lcd_info = tccfb_get_panel();  
  40.   
  41.     if(pmap_fb_video.size == 0)  
  42.     {  
  43.         Gmap_cpu  = dma_alloc_writecombine(0, lcd_info->xres * lcd_info->yres * 4 , &Gmap_dma, GFP_KERNEL);  
  44.     }  
  45.     else  
  46.     {  
  47.         unsigned int fb_size = lcd_info->xres * lcd_info->yres * 4;  
  48.         Gmap_dma =  pmap_fb_video.base + (fb_size * 2);  
  49.         Gmap_dma = PAGE_ALIGN(Gmap_dma);  
  50.         Gmap_cpu = ioremap_nocache(Gmap_dma, fb_size);  
  51.     }  
  52.     #endif//  
  53.   
  54.     printk(" %s LCDC:%d  end \n", __func__, Fb_Lcdc_num);  
  55.   
  56.     return 0;  
  57. }  
  58. EXPORT_SYMBOL(tca_fb_init);  
  59.   
  60. void tca_fb_cleanup(void)  // 该函数也是完成对时钟的设置  
  61. {  
  62.     dprintk(" %s LCDC:%d \n", __func__, Fb_Lcdc_num);  
  63.     tca92xxfb_clock_delete();  
  64. }  
  65. EXPORT_SYMBOL(tca_fb_cleanup);  
在板级初始化程序中有对TCC_FB设备的初始化
[cpp] view plain copy
print?
  1. #if defined(CONFIG_FB_TCC)  
  2. /*---------------------------------------------------------------------- 
  3.  * Device     : LCD Frame Buffer resource 
  4.  * Description:  
  5.  *----------------------------------------------------------------------*/  
  6.   
  7. static u64 tcc_device_lcd_dmamask = 0xffffffffUL;  
  8.   
  9. struct platform_device tcc_lcd_device = {  
  10.     .name     = "tccxxx-lcd",  
  11.     .id       = -1,  
  12.     .dev      = {  
  13.         .dma_mask           = &tcc_device_lcd_dmamask,  
  14. //      .coherent_dma_mask  = 0xffffffffUL  
  15.     }  
  16. };  
  17. #endif  

然后在下面的函数中注册设备

[cpp] view plain copy
print?
  1. int __init m801_88_init_panel(void)  
  2. {  
  3.     int ret;  
  4.     if (!machine_is_m801_88())  
  5.         return 0;  
  6.     printk("%s LCD panel type %d\n", __func__, tcc_panel_id);  
  7.   
  8.     switch (tcc_panel_id) {           
  9.         #ifdef CONFIG_LCD_AT070TN93  
  10.         case PANEL_ID_AT070TN93:  
  11.             platform_device_register(&at070tn93_lcd);  // 注册lcd panel设备  
  12.             break;  
  13.         #endif  
  14.       
  15.         default:  
  16.             pr_err("Not supported LCD panel type %d\n", tcc_panel_id);  
  17.             return -EINVAL;  
  18.     }  
  19.   
  20.     ret = platform_device_register(&tcc_lcd_device);  // 注册fb设备  
  21.     if (ret)  
  22.         return ret;  
  23.   
  24.     platform_device_register(&m801_88_backlight);  // 注册背光控制设备  
  25.     ret = platform_driver_register(&m801_88_backlight_driver);  // 注册背光控制驱动  
  26.     if (ret)  
  27.         return ret;  
  28.   
  29.     return 0;  
  30. }  
  31. device_initcall(m801_88_init_panel);  
1、另外讲下lcd panel的注册流程

[cpp] view plain copy
print?
  1. static struct lcd_platform_data lcd_pdata = {  // panel的几个控制引脚  
  2.     .power_on   = GPIO_LCD_ON,  
  3.     .display_on = GPIO_LCD_DISPLAY,  
  4.     .bl_on      = GPIO_LCD_BL,  
  5.     .reset      = GPIO_LCD_RESET,  
  6. };  
  7.   
  8. #ifdef CONFIG_LCD_AT070TN93  
  9. static struct platform_device at070tn93_lcd = {  
  10.     .name   = "at070tn93_lcd",  
  11.     .dev    = {  
  12.         .platform_data  = &lcd_pdata,  
  13.     },  
  14. };  
  15. #endif//CONFIG_LCD_AT070TN93  
[cpp] view plain copy
print?
  1. static struct lcd_panel at070tn93_panel = {  // panel的参数  
  2.     .name       = "AT070TN93",  
  3.     .manufacturer   = "INNOLUX",  
  4.     .id     = PANEL_ID_AT070TN93,  
  5.     .xres       = 1024,  
  6.     .yres       = 600,  
  7.     .width      = 136,  
  8.     .height     = 3,  
  9.     .bpp        = 18,  
  10.     .clk_freq   = 500000,  
  11.     .clk_div    = 1,  
  12.     .bus_width  = 18,  
  13.     .lpw        = 320,  
  14.     .lpc        = 1024,  
  15.     .lswc       = 24,  
  16.     .lewc       = 160,  
  17.     .vdb        = 0,  
  18.     .vdf        = 10,  
  19.     .fpw1       = 3,  
  20.     .flc1       = 600,  
  21.     .fswc1      = 0,  
  22.     .fewc1      = 22,  
  23.     .fpw2       = 3,  
  24.     .flc2       = 600,  
  25.     .fswc2      = 0,  
  26.     .fewc2      = 22,  
  27.     .sync_invert    = IV_INVERT_EN | IH_INVERT_EN,  
  28.     .init       = at070tn93_panel_init,  
  29.     .set_power  = at070tn93_set_power,  
  30.     .set_backlight_level = at070tn93_set_backlight_level,  
  31. };  
  32.   
  33. static int at070tn93_probe(struct platform_device *pdev)  
  34. {  
  35.     printk("%s : %d\n", __func__, 0);  
  36.   
  37.     mutex_init(&panel_lock);  
  38.     lcd_pwr_state = 1;  
  39.   
  40.     at070tn93_panel.dev = &pdev->dev;  
  41.       
  42.     tccfb_register_panel(&at070tn93_panel);  // 注册panel  
  43.     return 0;  
  44. }  
  45.   
  46. static int at070tn93_remove(struct platform_device *pdev)  
  47. {  
  48.     return 0;  
  49. }  
  50.   
  51. static struct platform_driver at070tn93_lcd = {  
  52.     .probe  = at070tn93_probe,  
  53.     .remove = at070tn93_remove,  
  54.     .driver = {  
  55.         .name   = "at070tn93_lcd",  
  56.         .owner  = THIS_MODULE,  
  57.     },  
  58. };  
  59.   
  60. static __init int at070tn93_init(void)  
  61. {  
  62.     return platform_driver_register(&at070tn93_lcd);  // 注册panel驱动  
  63. }  
  64.   
  65. static __exit void at070tn93_exit(void)  
  66. {  
  67.     platform_driver_unregister(&at070tn93_lcd);  
  68. }  
  69.   
  70. subsys_initcall(at070tn93_init);  
  71. module_exit(at070tn93_exit);  
[cpp] view plain copy
print?
  1. int tccfb_register_panel(struct lcd_panel *panel)  
  2. {  
  3.     dprintk(" %s  name:%s \n", __func__, panel->name);  
  4.   
  5.     lcd_panel = panel;  // 赋值给全局变量  
  6.     return 1;  
  7. }  
  8. EXPORT_SYMBOL(tccfb_register_panel);  

2、另外讲下背光控制设备的注册流程

[cpp] view plain copy
print?
  1. static void m801_88_brightness_set(struct led_classdev *led_cdev, enum led_brightness value)  
  2. {  
  3.     struct lcd_panel *lcd_panel = tccfb_get_panel();  // 获取全局的panel  
  4.   
  5.     if (lcd_panel->set_backlight_level)  
  6.         lcd_panel->set_backlight_level(lcd_panel, value);  // 调用panel的函数实现背光控制  
  7. }  
  8.   
  9. static struct led_classdev m801_88_backlight_led = {  
  10.     .name       = "lcd-backlight",  
  11.     .brightness = DEFAULT_BACKLIGHT_BRIGHTNESS,  
  12.     .brightness_set = m801_88_brightness_set,  
  13. };  
  14.   
  15. #define M801_88_GPIO_LCD_RESET      TCC_GPC(29)  
  16. #define M801_88_GPIO_LCD_ON         TCC_GPG(2)  
  17. #define M801_88_GPIO_LCD_BL         TCC_GPA(4)  
  18. static int m801_88_backlight_probe(struct platform_device *pdev)  
  19. {  
  20.     tcc_gpio_config(M801_88_GPIO_LCD_ON, GPIO_FN(0));   //gpio_d 21  //初始化IO  
  21.     tcc_gpio_config(M801_88_GPIO_LCD_BL, GPIO_FN(0));   //gpio a 4  
  22.     tcc_gpio_config(M801_88_GPIO_LCD_RESET, GPIO_FN(0));    //gpio c 28  
  23.   
  24.     gpio_request(M801_88_GPIO_LCD_ON,       "lcd_on");  
  25.     gpio_request(M801_88_GPIO_LCD_BL,       "lcd_bl");  
  26.     gpio_request(M801_88_GPIO_LCD_RESET,    "lcd_reset");  
  27.       
  28.     return led_classdev_register(&pdev->dev, &m801_88_backlight_led);  // 注册led_classdev  
  29. }  
  30.   
  31. static int m801_88_backlight_remove(struct platform_device *pdev)  
  32. {  
  33.     led_classdev_unregister(&m801_88_backlight_led);  
  34.     return 0;  
  35. }  
  36.   
  37. static struct platform_driver m801_88_backlight_driver = {  // 驱动  
  38.     .probe  = m801_88_backlight_probe,  
  39.     .remove = m801_88_backlight_remove,  
  40.     .driver = {  
  41.         .name   = "m801_88-backlight",  
  42.         .owner  = THIS_MODULE,  
  43.     },  
  44. };  
  45.   
  46. static struct platform_device m801_88_backlight = {  // 设备  
  47.     .name = "m801_88-backlight",  
  48. };  

回到主题

当fb的设备和驱动匹配在一起之后便执行tccfb_probe函数

[cpp] view plain copy
print?
  1. static int __init tccfb_probe(struct platform_device *pdev)  
  2. {  
  3.     struct tccfb_info *info;  
  4.     struct fb_info *fbinfo;  
  5.     int ret;  
  6.     int plane = 0;  
  7.     unsigned int screen_width, screen_height;  
  8.   
  9.     if (!lcd_panel) { // 是否已经注册panel  
  10.         pr_err("tccfb: no LCD panel data\n");  
  11.         return -EINVAL;  
  12.     }  
  13.     pr_info("LCD panel is %s %s %d x %d\n", lcd_panel->manufacturer, lcd_panel->name,  
  14.         lcd_panel->xres, lcd_panel->yres);  
  15.   
  16.         screen_width      = lcd_panel->xres;  // 设置分辨率  
  17.         screen_height     = lcd_panel->yres;  
  18.   
  19. #if defined(CONFIG_TCC_HDMI_UI_SIZE_1280_720)  // 是否定义HDMI开机显示UI  
  20.         if(tcc_display_data.resolution == 1)  
  21.         {  
  22.             screen_width      = 720;  
  23.             screen_height     = 576;  
  24.         }  
  25.         else if(tcc_display_data.resolution == 2)  
  26.         {  
  27.             screen_width      = 800;  
  28.             screen_height     = 480;  
  29.         }  
  30. #endif  
  31.   
  32.     printk("%s, screen_width=%d, screen_height=%d\n", __func__, screen_width, screen_height);  
  33.   
  34.     pmap_get_info("fb_video", &pmap_fb_video);  
  35.   
  36. #if defined(CONFIG_TCC_EXCLUSIVE_UI_LAYER)  
  37.     pmap_get_info("exclusive_viqe", &pmap_eui_viqe);  
  38. #endif  
  39.   
  40.     for (plane = 0; plane < CONFIG_FB_TCC_DEVS; plane++)  
  41.     {  
  42.         fbinfo = framebuffer_alloc(sizeof(struct tccfb_info), &pdev->dev);  // 申请fbi 下面开始填充结构体  
  43.         info = fbinfo->par;  
  44.         info->fb = fbinfo;  
  45.         //platform_set_drvdata(pdev, fbinfo);  
  46.   
  47.         strcpy(fbinfo->fix.id, tccfb_driver_name);  
  48.   
  49.         fbinfo->fix.type     = FB_TYPE_PACKED_PIXELS;  
  50.         fbinfo->fix.type_aux     = 0;  
  51.         fbinfo->fix.xpanstep     = 0;  
  52.         fbinfo->fix.ypanstep     = 1;  
  53.         fbinfo->fix.ywrapstep        = 0;  
  54.         fbinfo->fix.accel        = FB_ACCEL_NONE;  
  55.   
  56.         fbinfo->var.nonstd       = 0;  // 标准像素格式  
  57.         fbinfo->var.activate     = FB_ACTIVATE_NOW;  
  58.   
  59.         fbinfo->var.accel_flags      = 0;  
  60.         fbinfo->var.vmode        = FB_VMODE_NONINTERLACED;  
  61.   
  62.         fbinfo->fbops            = &tccfb_ops;  // 注册操作函数  
  63.         fbinfo->flags            = FBINFO_FLAG_DEFAULT;  
  64.   
  65.         fbinfo->var.xres     = screen_width;  
  66.         fbinfo->var.xres_virtual = fbinfo->var.xres;  
  67.         fbinfo->var.yres     = screen_height;  
  68.   
  69. #ifdef TCC_FB_DOUBLE  
  70.         fbinfo->var.yres_virtual = fbinfo->var.yres * 2;  
  71. #else  
  72.         fbinfo->var.yres_virtual = fbinfo->var.yres;  
  73. #endif//  
  74.         fbinfo->var.bits_per_pixel   = default_scn_depth[plane];  // 设置每个像素占用的位数  都是16位  
  75.         fbinfo->fix.line_length  = fbinfo->var.xres * fbinfo->var.bits_per_pixel/8;  // 计算一行的大小  
  76.   
  77.         tccfb_check_var(&fbinfo->var, fbinfo);  // 检测参数  
  78.   
  79.         // the memory size that LCD should occupy  
  80.         fbinfo->fix.smem_len = fbinfo->var.xres * fbinfo->var.yres_virtual * SCREEN_DEPTH_MAX / 8;  // 计算缓冲区大小  
  81.   
  82.         info->imgch = plane;  // 通道  
  83.   
  84.         /* Initialize video memory */  
  85.         ret = tccfb_map_video_memory(info, plane);  // 申请缓冲区内存空间  
  86.         if (ret) {  
  87.             dprintk( KERN_ERR "Failed to allocate video RAM: %d\n", ret);  
  88.             ret = -ENOMEM;  
  89.         }  
  90.   
  91.         ret = register_framebuffer(fbinfo);  // 注册fbi  
  92.         if (ret < 0) {  
  93.             dprintk(KERN_ERR "Failed to register framebuffer device: %d\n", ret);  
  94.             goto free_video_memory;  
  95.         }  
  96.   
  97. //      fbinfo->var.reserved[0] = 0x54445055;  
  98.   
  99.         tccfb_set_par(fbinfo);  // 设置参数  
  100.   
  101.         if (plane == 0) // 判断是否顶层  
  102.             if (fb_prepare_logo(fbinfo, FB_ROTATE_UR)) {  // 准备logo  
  103.             /* Start display and show logo on boot */  
  104.             fb_set_cmap(&fbinfo->cmap, fbinfo);  // 设置颜色表  
  105.   
  106.             dprintk("fb_show_logo\n");  
  107.             fb_show_logo(fbinfo, FB_ROTATE_UR);  // 显示logo  
  108.         }  
  109.         printk(KERN_INFO "fb%d: %s frame buffer device\n",  fbinfo->node, fbinfo->fix.id);  
  110.     }  
  111.   
  112.     tcc_lcd_interrupt_reg(TRUE);  // 设置中断寄存器  
  113.   
  114. #ifdef CONFIG_HAS_EARLYSUSPEND  // 电源相关的函数  
  115.     info->early_suspend.suspend = tcc_fb_early_suspend;  
  116.     info->early_suspend.resume   = tcc_fb_late_resume;  
  117.     info->early_suspend.level    = EARLY_SUSPEND_LEVEL_STOP_DRAWING;  
  118.     register_early_suspend(&info->early_suspend);  
  119.   
  120.     info->earlier_suspend.suspend = tcc_fb_earlier_suspend;  
  121.     info->earlier_suspend.resume     = tcc_fb_later_resume;  
  122.     info->earlier_suspend.level  = EARLY_SUSPEND_LEVEL_BLANK_SCREEN;  
  123.     register_early_suspend(&info->earlier_suspend);  
  124. #endif  
  125.   
  126.     return 0;  
  127.   
  128. free_video_memory:  
  129.     tccfb_unmap_video_memory(info);  
  130.     dprintk("TCC92xx fb init failed.\n");  
  131.     return ret;  
  132. }  

操作函数接口如下

[cpp] view plain copy
print?
  1. static struct fb_ops tccfb_ops = {  
  2.     .owner          = THIS_MODULE,  
  3.     .fb_check_var   = tccfb_check_var,  
  4.     .fb_set_par     = tccfb_set_par,  
  5.     .fb_blank       = tccfb_blank,  
  6.     .fb_setcolreg   = tccfb_setcolreg,  
  7.     .fb_fillrect    = cfb_fillrect,  
  8.     .fb_copyarea    = cfb_copyarea,  
  9.     .fb_imageblit   = cfb_imageblit,  
  10.     .fb_ioctl       = tccfb_ioctl,  
  11.     .fb_pan_display = tccfb_pan_display,  
  12. };  

检测参数的函数如下

[cpp] view plain copy
print?
  1. static int tccfb_check_var(struct fb_var_screeninfo *var,  
  2.                    struct fb_info *info)  
  3. {  
  4.     /* 判断bpp是否越界 */  
  5.     if (var->bits_per_pixel > 32)  
  6.         var->bits_per_pixel = 32;  
  7.     else if (var->bits_per_pixel < 16)  
  8.         var->bits_per_pixel = 16;  
  9.   
  10.     /* 设置r/g/b的位置和偏移 */  
  11.     if (var->bits_per_pixel == 16) {  
  12.         var->red.offset  = 11;  
  13.         var->green.offset    = 5;  
  14.         var->blue.offset = 0;  
  15.         var->red.length  = 5;  
  16.         var->green.length    = 6;  
  17.         var->blue.length = 5;  
  18.         var->transp.length   = 0;  
  19.     } else if (var->bits_per_pixel == 32) {  
  20.         var->red.offset  = 16;  
  21.         var->green.offset    = 8;  
  22.         var->blue.offset = 0;  
  23.         var->transp.offset   = 24;  
  24.         var->red.length  = 8;  
  25.         var->green.length    = 8;  
  26.         var->blue.length = 8;  
  27.         var->transp.length   = 8;  
  28.     } else {  
  29.         var->red.length  = var->bits_per_pixel;  
  30.         var->red.offset  = 0;  
  31.         var->green.length    = var->bits_per_pixel;  
  32.         var->green.offset    = 0;  
  33.         var->blue.length = var->bits_per_pixel;  
  34.         var->blue.offset = 0;  
  35.         var->transp.length   = 0;  
  36.     }  
  37.     if (var->yres_virtual < var->yoffset + var->yres)  // 判断yres_virtual是否越界  
  38.         var->yres_virtual = var->yoffset + var->yres;  
  39.   
  40.     return 0;  
  41. }  

申请缓冲区内存空间函数如下

[cpp] view plain copy
print?
  1. static int __init tccfb_map_video_memory(struct tccfb_info *fbi, int plane)  
  2. {  
  3.     fbi->map_size = PAGE_ALIGN(fbi->fb->fix.smem_len + PAGE_SIZE);  // 内存对齐  
  4.   
  5.     if(FB_VIDEO_MEM_SIZE == 0)  
  6.     {  
  7.   
  8.         fbi->map_cpu  = dma_alloc_writecombine(fbi->dev, fbi->map_size,  
  9.                                &fbi->map_dma, GFP_KERNEL);  
  10.         printk("map_video_memory (fbi=%p) kenel memoy, dma:0x%x map_size:%08x\n", fbi,fbi->map_dma, fbi->map_size);  
  11.   
  12.     }  
  13.     else  
  14.     {  
  15.         fbi->map_dma =  FB_VIDEO_MEM_BASE;  // dma起始地址  
  16.         fbi->map_cpu = ioremap_nocache(fbi->map_dma, fbi->map_size);  // 申请内存空间,得到起始虚拟地址  
  17.         printk("map_video_memory (fbi=%p) used map memoy,map dma:0x%x size:%08x\n", fbi, fbi->map_dma ,fbi->map_size);  
  18.     }  
  19.   
  20.     fbi->map_size = fbi->fb->fix.smem_len;  
  21.   
  22.     if (fbi->map_cpu) {  // 申请是否成功  
  23.         /* prevent initial garbage on screen */  
  24.         dprintk("map_video_memory: clear %p:%08x\n", fbi->map_cpu, fbi->map_size);  
  25.   
  26.         memset(fbi->map_cpu, 0x00, fbi->map_size);  // 初始化空间  
  27.   
  28.         fbi->screen_dma      = fbi->map_dma;  // 赋值物理起始地址  
  29.         fbi->fb->screen_base  = fbi->map_cpu;  // 赋值虚拟起始地址  
  30.         fbi->fb->fix.smem_start  = fbi->screen_dma;  // 赋值物理起始地址  
  31.   
  32.         // Set the LCD frame buffer start address  
  33.         switch (plane)  // 不同panel  
  34.         {  
  35.             case 2: // IMG2  
  36.                 fb_mem_vaddr[plane] = fbi->map_cpu;  
  37.                 fb_mem_size [plane] = fbi->map_size;  
  38.                 break;  
  39.             case 1: // IMG1  
  40.                 fb_mem_vaddr[plane] = fbi->map_cpu;  
  41.                 fb_mem_size [plane] = fbi->map_size;  
  42.                 break;  
  43.             case 0: // IMG0  
  44.                 fb_mem_vaddr[plane] = fbi->map_cpu;    
  45.                 fb_mem_size [plane] = fbi->map_size;  
  46.                 break;  
  47.         }  
  48.         dprintk("map_video_memory: dma=%08x cpu=%p size=%08x\n",  
  49.             fbi->map_dma, fbi->map_cpu, fbi->fb->fix.smem_len);  
  50.     }  
  51.   
  52.     return fbi->map_cpu ? 0 : -ENOMEM;  
  53. }  
设置参数函数如下
[cpp] view plain copy
print?
  1. static int tccfb_set_par(struct fb_info *info)  
  2. {  
  3.     struct tccfb_info *fbi = info->par;  
  4.     struct fb_var_screeninfo *var = &info->var;  
  5.   
  6.     sprintk("- tccfb_set_par pwr:%d  output:%d \n",fb_power_state, Output_SelectMode);  
  7.   
  8.     if (var->bits_per_pixel == 16)  // 设置显示器色彩模式  
  9.         fbi->fb->fix.visual = FB_VISUAL_TRUECOLOR;  
  10.     else if (var->bits_per_pixel == 32)  
  11.         fbi->fb->fix.visual = FB_VISUAL_TRUECOLOR;  
  12.     else  
  13.         fbi->fb->fix.visual = FB_VISUAL_PSEUDOCOLOR;  
  14.   
  15.     fbi->fb->fix.line_length = (var->xres*var->bits_per_pixel)/8;  
  16.   
  17.     #ifndef CONFIG_TCC_OUTPUT_STARTER  
  18.     /* activate this new configuration */  
  19.     if( fb_power_state && Output_SelectMode != TCC_OUTPUT_COMPONENT )  
  20.         tccfb_activate_var(fbi, var);  
  21.     #endif  
  22.   
  23.     return 0;  
  24. }  
[cpp] view plain copy
print?
  1. static void tccfb_activate_var(struct tccfb_info *fbi,  struct fb_var_screeninfo *var)  
  2. {  
  3.     unsigned int imgch = 0;  
  4.   
  5.     sprintk("%s node:0x%x TCC_DEVS:%d \n", __func__, fbi->fb->node, CONFIG_FB_TCC_DEVS);  
  6.   
  7.     if((0 <= fbi->fb->node) && (fbi->fb->node < CONFIG_FB_TCC_DEVS))  
  8.         imgch = fbi->fb->node;  
  9.     else  
  10.         return;  
  11.   
  12.     tca_fb_activate_var(fbi, var);  
  13. }  
[cpp] view plain copy
print?
  1. void tca_fb_activate_var(struct tccfb_info *fbi,  struct fb_var_screeninfo *var)  
  2. {  
  3.     unsigned int imgch, bpp_value,tmp_value, base_addr;  
  4.     unsigned int regl, lcd_width, lcd_height, img_width, img_height;  
  5.   
  6.     #define IMG_AOPT            2  
  7.       
  8.     unsigned int alpha_type = 0, alpha_blending_en = 0;  
  9.     unsigned int chromaR, chromaG, chromaB, chroma_en;  
  10.   
  11.     imgch = fbi->fb->node;  // 通道  
  12.     if(fbi->fb->var.bits_per_pixel == 32)  
  13.     {  
  14.         chroma_en = 0;  
  15.         alpha_type = 1;  
  16.         alpha_blending_en = 1;  
  17.         bpp_value = 0x000C; //RGB888  
  18.     }  
  19.     else if(fbi->fb->var.bits_per_pixel == 16)  // 判断像素点深度并设置相关属性  
  20.     {  
  21.         chroma_en = 1;  
  22.         alpha_type = 0;  
  23.         alpha_blending_en = 0;  
  24.         bpp_value = 0x000A; //RGB565  
  25.     }  
  26.     else    {  
  27.         printk("%s:fb%d Not Supported BPP!\n", __FUNCTION__, fbi->fb->node);  
  28.         return;  
  29.     }  
  30.   
  31.     chromaR = chromaG = chromaB = 0;  
  32.   
  33.     sprintk("%s: fb%d Supported BPP!\n", __FUNCTION__, fbi->fb->node);  
  34.     // 计算缓冲区空间末尾地址  
  35.     base_addr = fbi->map_dma + fbi->fb->var.xres * var->yoffset * (fbi->fb->var.bits_per_pixel/8);  
  36.     if(fbi->fb->var.yoffset > fbi->fb->var.yres) {  
  37.         base_addr = PAGE_ALIGN(base_addr);  
  38.     }  
  39.   
  40.     sprintk("%s: fb%d Baddr:0x%x Naddr:0x%x!\n", __FUNCTION__, fbi->fb->node, base_addr, pLCDC_FB_CH->LIBA0);  
  41.   
  42.     regl = pLCDC->LDS; // get LCD size 获取寄存器值  
  43.   
  44.     lcd_width = (regl & 0xFFFF);  
  45.     lcd_height = ((regl>>16) & 0xFFFF);  
  46.     img_width = fbi->fb->var.xres;  
  47.     img_height = fbi->fb->var.yres;  
  48.   
  49.     if(img_width > lcd_width)      
  50.         img_width = lcd_width;  
  51.       
  52.     if(img_height > lcd_height)    
  53.         img_height = lcd_height;  
  54.     /* 写新的寄存器值 */  
  55.     switch(imgch)  
  56.     {  
  57.         case 0:  
  58.             // default framebuffer   
  59.             tmp_value = pLCDC_FB_CH->LIC;  
  60.             pLCDC_FB_CH->LIC = (tmp_value & 0xFFFFFFE0) | (bpp_value & 0x0000001F);  
  61.             pLCDC_FB_CH->LIO = fbi->fb->var.xres * (fbi->fb->var.bits_per_pixel/8);  
  62.             pLCDC_FB_CH->LIS = (img_height<< 16) | (img_width); //Size  
  63.             pLCDC_FB_CH->LIP = 0; // position  
  64.             #ifdef CONFIG_FB_M2M_COPY  
  65.             if(!tccxxx_overlay_use()) {  
  66.                 pLCDC_FB_CH->LIBA0   = Gmap_dma;  
  67.             }  
  68.             else  
  69.             #endif//CONFIG_FB_M2M_COPY  
  70.             {  
  71.                 pLCDC_FB_CH->LIBA0   = base_addr;                  
  72.             }  
  73.   
  74.             #ifdef CONFIG_ARCH_TCC92XX  
  75.             pLCDC_FB_CH->LIC |= (HwLIC_IEN);    //  image enable  
  76.             #else  
  77.             pLCDC_FB_CH->LIC |= (HwLIC_IEN | HwLCT_RU);    //  image enable  
  78.             #endif//    CONFIG_ARCH_TCC92XX  
  79.   
  80.             // overlay 加己  
  81.             BITCSET (pLCDC->LI2C,    0x1<< 30,  (alpha_blending_en)    << 30); // alpha enable  
  82.             BITCSET (pLCDC->LI2C, 0x3<< 25,    (IMG_AOPT)  << 25); // alpha opt  
  83.             BITCSET (pLCDC->LI2C, 0x1<< 24,    (alpha_type)  << 24); // alpha select    
  84.   
  85.             BITCSET (pLCDC->LI2C, 0x1<< 29,    (chroma_en)  << 29); // chroma-keying  
  86.               
  87.             BITCSET (pLCDC->LI2KR, 0xff <<  0, (chromaR)  <<  0); // key  
  88.             BITCSET (pLCDC->LI2KR, 0xff << 16, (0xF8)  << 16); // keymask  
  89.             BITCSET (pLCDC->LI2KG, 0xff <<  0, (chromaG)  <<  0); // key  
  90.             BITCSET (pLCDC->LI2KG, 0xff << 16, (0xFC)  << 16); // keymask  
  91.             BITCSET (pLCDC->LI2KB, 0xff <<  0, (chromaB)  <<  0); // key  
  92.             BITCSET (pLCDC->LI2KB, 0xff << 16, (0xF8)  << 16); // keymask  
  93.   
  94.             tmp_value = pLCDC->LI2C;  
  95.             pLCDC->LI2C = (tmp_value & 0xFFFFFFE0) | (bpp_value & 0x0000001F);  
  96.             pLCDC->LI2O = fbi->fb->var.xres * (fbi->fb->var.bits_per_pixel/8);  
  97.   
  98.             #ifdef CONFIG_FB_TCC_USE_VSYNC_INTERRUPT  
  99.             tca_fb_vsync_activate(var, fbi);  // 设置场同步中断  
  100.             #else  
  101.             msleep(16);  
  102.             #endif  
  103.               
  104.             break;  
  105.   
  106.         case 1:  
  107.             tmp_value = pLCDC->LI1C;  
  108.             pLCDC->LI1C = (tmp_value & 0xFFFFFFE0) | (bpp_value & 0x0000001F);  
  109.             pLCDC->LI1O = fbi->fb->var.xres * (fbi->fb->var.bits_per_pixel/8);  
  110.             pLCDC->LI1S  = (img_height<< 16) | (img_width); //Size  
  111.             pLCDC->LI1BA0 = base_addr;  
  112.             #ifdef CONFIG_ARCH_TCC92XX  
  113.             pLCDC->LI1C |= (HwLIC_IEN);  
  114.             #else  
  115.             pLCDC->LI1C |= (HwLIC_IEN | HwLCT_RU);  
  116.             #endif//  
  117.             break;  
  118.   
  119.         case 2:  
  120.             tmp_value = pLCDC->LI0C;  
  121.             pLCDC->LI0C = (tmp_value & 0xFFFFFFE0) | (bpp_value & 0x0000001F);  
  122.             pLCDC->LI0O = fbi->fb->var.xres * (fbi->fb->var.bits_per_pixel/8);  
  123.             pLCDC->LI0S  = (img_height<< 16) | (img_width); //Size  
  124.             pLCDC->LI0BA0 = base_addr;  
  125.             #ifdef CONFIG_ARCH_TCC92XX  
  126.             pLCDC->LI0C |= (HwLIC_IEN);  
  127.             #else  
  128.             pLCDC->LI0C |= (HwLIC_IEN | HwLCT_RU);  
  129.             #endif//              
  130.             break;  
  131.     }  
  132.   
  133.     return;  
  134.       
  135. }  
  136. EXPORT_SYMBOL(tca_fb_activate_var);  

3、另外讲下开机logo的显示过程

[cpp] view plain copy
print?
  1. int fb_prepare_logo(struct fb_info *info, int rotate)  
  2. {  
  3.     int depth = fb_get_color_depth(&info->var, &info->fix);  // 获取颜色深度  
  4.     unsigned int yres;  
  5.   
  6.     memset(&fb_logo, 0, sizeof(struct logo_data));  
  7.   
  8.     if (info->flags & FBINFO_MISC_TILEBLITTING ||  
  9.         info->flags & FBINFO_MODULE)  
  10.         return 0;  
  11.   
  12.     if (info->fix.visual == FB_VISUAL_DIRECTCOLOR) {  // 判断色彩模式  我们是真彩色的  
  13.         depth = info->var.blue.length;  
  14.         if (info->var.red.length < depth)  
  15.             depth = info->var.red.length;  
  16.         if (info->var.green.length < depth)  
  17.             depth = info->var.green.length;  
  18.     }  
  19.   
  20.     if (info->fix.visual == FB_VISUAL_STATIC_PSEUDOCOLOR && depth > 4) {  
  21.         /* assume console colormap */  
  22.         depth = 4;  
  23.     }  
  24.   
  25.     /* Return if no suitable logo was found */  
  26.     fb_logo.logo = fb_find_logo(depth);  // 获取logo  
  27.   
  28.     if (!fb_logo.logo) {  
  29.         return 0;  
  30.     }  
  31.   
  32.     if (rotate == FB_ROTATE_UR || rotate == FB_ROTATE_UD)  // 判断是否旋转  
  33.         yres = info->var.yres;  
  34.     else  
  35.         yres = info->var.xres;  
  36.   
  37.     if (fb_logo.logo->height > yres) {  
  38.         fb_logo.logo = NULL;  
  39.         return 0;  
  40.     }  
  41.   
  42.     /* 判断颜色模式 */  
  43.     if (fb_logo.logo->type == LINUX_LOGO_CLUT224)  
  44.         fb_logo.depth = 8;  
  45.     else if (fb_logo.logo->type == LINUX_LOGO_VGA16)  
  46.         fb_logo.depth = 4;  
  47.     else  
  48.         fb_logo.depth = 1;  
  49.   
  50.   
  51.     if (fb_logo.depth > 4 && depth > 4) {  
  52.         switch (info->fix.visual) {  
  53.         case FB_VISUAL_TRUECOLOR:  
  54.             fb_logo.needs_truepalette = 1;  // 真彩色  
  55.             break;  
  56.         case FB_VISUAL_DIRECTCOLOR:  
  57.             fb_logo.needs_directpalette = 1;  
  58.             fb_logo.needs_cmapreset = 1;  
  59.             break;  
  60.         case FB_VISUAL_PSEUDOCOLOR:  
  61.             fb_logo.needs_cmapreset = 1;  
  62.             break;  
  63.         }  
  64.     }  
  65.   
  66.     return fb_prepare_extra_logos(info, fb_logo.logo->height, yres);  // 获取logo高度  
  67. }  
获取logo的函数
[cpp] view plain copy
print?
  1. const struct linux_logo * __init_refok fb_find_logo(int depth)  
  2. {  
  3.     const struct linux_logo *logo = NULL;  
  4.   
  5.     if (nologo)  
  6.         return NULL;  
  7.     ...   
  8.     if (depth >= 8) {  
  9. #ifdef CONFIG_LOGO_LINUX_CLUT224  
  10.         /* Generic Linux logo */  
  11.         logo = &logo_linux_clut224;  
  12. #endif  
  13.     }  
  14.     return logo;  
  15. }  
  16. EXPORT_SYMBOL_GPL(fb_find_logo);  
[cpp] view plain copy
print?
  1. const struct linux_logo logo_linux_clut224 __initconst = {  
  2.     .type       = LINUX_LOGO_CLUT224,  
  3.     .width      = 1024,  
  4.     .height     = 768,  
  5.     .clutsize   = 221,  
  6.     .clut       = logo_linux_clut224_clut,  
  7.     .data       = logo_linux_clut224_data  
  8. };  
设置颜色表
[cpp] view plain copy
print?
  1. int fb_set_cmap(struct fb_cmap *cmap, struct fb_info *info)  
  2. {  
  3.     int i, start, rc = 0;  
  4.     u16 *red, *green, *blue, *transp;  
  5.     u_int hred, hgreen, hblue, htransp = 0xffff;  
  6.   
  7.     red = cmap->red;  
  8.     green = cmap->green;  
  9.     blue = cmap->blue;  
  10.     transp = cmap->transp;  
  11.     start = cmap->start;  
  12.   
  13.     if (start < 0 || (!info->fbops->fb_setcolreg &&  
  14.               !info->fbops->fb_setcmap))  
  15.         return -EINVAL;  
  16.     if (info->fbops->fb_setcmap) {  
  17.         rc = info->fbops->fb_setcmap(cmap, info);  
  18.     } else {  
  19.         for (i = 0; i < cmap->len; i++) {  
  20.             hred = *red++;  
  21.             hgreen = *green++;  
  22.             hblue = *blue++;  
  23.             if (transp)  
  24.                 htransp = *transp++;  
  25.             if (info->fbops->fb_setcolreg(start++,  
  26.                               hred, hgreen, hblue,  
  27.                               htransp, info))  
  28.                 break;  
  29.         }  
  30.     }  
  31.     if (rc == 0)  
  32.         fb_copy_cmap(cmap, &info->cmap);  
  33.   
  34.     return rc;  
  35. }  
显示logo
[cpp] view plain copy
print?
  1. int fb_show_logo(struct fb_info *info, int rotate)  
  2. {  
  3.     int y;  
  4.   
  5.     y = fb_show_logo_line(info, rotate, fb_logo.logo, 0,  // 显示logo  
  6.                   num_online_cpus());  
  7.     y = fb_show_extra_logos(info, y, rotate);  
  8.   
  9.     return y;  
  10. }  
[cpp] view plain copy
print?
  1. static int fb_show_logo_line(struct fb_info *info, int rotate,  
  2.                  const struct linux_logo *logo, int y,  
  3.                  unsigned int n)  
  4. {  
  5.     u32 *palette = NULL, *saved_pseudo_palette = NULL;  
  6.     unsigned char *logo_new = NULL, *logo_rotate = NULL;  
  7.     struct fb_image image;  
  8.   
  9.     /* Return if the frame buffer is not mapped or suspended */  
  10.     if (logo == NULL || info->state != FBINFO_STATE_RUNNING ||  
  11.         info->flags & FBINFO_MODULE)  
  12.         return 0;  
  13.   
  14.     image.depth = 8;  // 设置深度  224色  
  15.     image.data = logo->data;  // 数据  
  16.   
  17.     if (fb_logo.needs_cmapreset)  
  18.         fb_set_logocmap(info, logo);  
  19.   
  20.     if (fb_logo.needs_truepalette ||  
  21.         fb_logo.needs_directpalette) {  
  22.         palette = kmalloc(256 * 4, GFP_KERNEL);  
  23.         if (palette == NULL)  
  24.             return 0;  
  25.   
  26.         if (fb_logo.needs_truepalette)  
  27.             fb_set_logo_truepalette(info, logo, palette);  // 设置调色板  
  28.         else  
  29.             fb_set_logo_directpalette(info, logo, palette);  
  30.   
  31.         saved_pseudo_palette = info->pseudo_palette;  
  32.         info->pseudo_palette = palette;  
  33.     }  
  34.   
  35.     if (fb_logo.depth <= 4) {  
  36.         logo_new = kmalloc(logo->width * logo->height, GFP_KERNEL);  
  37.         if (logo_new == NULL) {  
  38.             kfree(palette);  
  39.             if (saved_pseudo_palette)  
  40.                 info->pseudo_palette = saved_pseudo_palette;  
  41.             return 0;  
  42.         }  
  43.         image.data = logo_new;  
  44.         fb_set_logo(info, logo, logo_new, fb_logo.depth);  
  45.     }  
  46.   
  47.     image.dx = 0;  // 显示logo的起始坐标  
  48.     image.dy = y;  
  49.     image.width = logo->width;  // logo的宽度和高度  
  50.     image.height = logo->height;  
  51.   
  52.     if (rotate) {  
  53.         logo_rotate = kmalloc(logo->width *  
  54.                       logo->height, GFP_KERNEL);  
  55.         if (logo_rotate)  
  56.             fb_rotate_logo(info, logo_rotate, &image, rotate);  
  57.     }  
  58.   
  59.     fb_do_show_logo(info, &image, rotate, n);  
  60.   
  61.     kfree(palette);  
  62.     if (saved_pseudo_palette != NULL)  
  63.         info->pseudo_palette = saved_pseudo_palette;  
  64.     kfree(logo_new);  
  65.     kfree(logo_rotate);  
  66.     return logo->height;  
  67. }  
开始显示
[cpp] view plain copy
print?
  1. static void fb_do_show_logo(struct fb_info *info, struct fb_image *image,  
  2.                 int rotate, unsigned int num)  
  3. {  
  4.     unsigned int x;  
  5.   
  6.     if (rotate == FB_ROTATE_UR) {  
  7.         for (x = 0;  
  8.              x < num && image->dx + image->width <= info->var.xres;  
  9.              x++) {  
  10.             info->fbops->fb_imageblit(info, image);  // 调用图像绘制函数显示logo  
  11.             image->dx += image->width + 8;  
  12.         }  
  13.     } else if (rotate == FB_ROTATE_UD) {  
  14.         for (x = 0; x < num && image->dx >= 0; x++) {  
  15.             info->fbops->fb_imageblit(info, image);  
  16.             image->dx -= image->width + 8;  
  17.         }  
  18.     } else if (rotate == FB_ROTATE_CW) {  
  19.         for (x = 0;  
  20.              x < num && image->dy + image->height <= info->var.yres;  
  21.              x++) {  
  22.             info->fbops->fb_imageblit(info, image);  
  23.             image->dy += image->height + 8;  
  24.         }  
  25.     } else if (rotate == FB_ROTATE_CCW) {  
  26.         for (x = 0; x < num && image->dy >= 0; x++) {  
  27.             info->fbops->fb_imageblit(info, image);  
  28.             image->dy -= image->height + 8;  
  29.         }  
  30.     }  
  31. }  
图像绘制函数
[cpp] view plain copy
print?
  1. void cfb_imageblit(struct fb_info *p, const struct fb_image *image)  
  2. {  
  3.     u32 fgcolor, bgcolor, start_index, bitstart, pitch_index = 0;  
  4.     u32 bpl = sizeof(u32), bpp = p->var.bits_per_pixel;  
  5.     u32 width = image->width;  
  6.     u32 dx = image->dx, dy = image->dy;  
  7.     u8 __iomem *dst1;  
  8.   
  9.     if (p->state != FBINFO_STATE_RUNNING)  
  10.         return;  
  11.   
  12.     bitstart = (dy * p->fix.line_length * 8) + (dx * bpp);  // 计算起始点  
  13.     start_index = bitstart & (32 - 1);  
  14.     pitch_index = (p->fix.line_length & (bpl - 1)) * 8;  
  15.   
  16.     bitstart /= 8;  
  17.     bitstart &= ~(bpl - 1);  
  18.     dst1 = p->screen_base + bitstart;  // 计算起始点的虚拟地址  
  19.   
  20.     if (p->fbops->fb_sync)  
  21.         p->fbops->fb_sync(p);  
  22.   
  23.     if (image->depth == 1) {  
  24.         if (p->fix.visual == FB_VISUAL_TRUECOLOR ||  
  25.             p->fix.visual == FB_VISUAL_DIRECTCOLOR) {  
  26.             fgcolor = ((u32*)(p->pseudo_palette))[image->fg_color];  
  27.             bgcolor = ((u32*)(p->pseudo_palette))[image->bg_color];  
  28.         } else {  
  29.             fgcolor = image->fg_color;  
  30.             bgcolor = image->bg_color;  
  31.         }     
  32.           
  33.         if (32 % bpp == 0 && !start_index && !pitch_index &&   
  34.             ((width & (32/bpp-1)) == 0) &&  
  35.             bpp >= 8 && bpp <= 32)              
  36.             fast_imageblit(image, p, dst1, fgcolor, bgcolor);  
  37.         else   
  38.             slow_imageblit(image, p, dst1, fgcolor, bgcolor,  
  39.                     start_index, pitch_index);  
  40.     } else  
  41.         color_imageblit(image, p, dst1, start_index, pitch_index);  
  42. }  
[cpp] view plain copy
print?
  1. static inline void color_imageblit(const struct fb_image *image,   
  2.                    struct fb_info *p, u8 __iomem *dst1,   
  3.                    u32 start_index,  
  4.                    u32 pitch_index)  
  5. {  
  6.     /* Draw the penguin */  
  7.     u32 __iomem *dst, *dst2;  
  8.     u32 color = 0, val, shift;  
  9.     int i, n, bpp = p->var.bits_per_pixel;  
  10.     u32 null_bits = 32 - bpp;  
  11.     u32 *palette = (u32 *) p->pseudo_palette;  
  12.     const u8 *src = image->data;  
  13.     u32 bswapmask = fb_compute_bswapmask(p);  
  14.   
  15.     dst2 = (u32 __iomem *) dst1;  // 起始虚拟地址  
  16.     for (i = image->height; i--; ) {  // 行数  
  17.         n = image->width;  // 列数  
  18.         dst = (u32 __iomem *) dst1;  // 当前虚拟地址  
  19.         shift = 0;  
  20.         val = 0;  
  21.           
  22.         if (start_index) {  
  23.             u32 start_mask = ~fb_shifted_pixels_mask_u32(p,  
  24.                         start_index, bswapmask);  
  25.             val = FB_READL(dst) & start_mask;  
  26.             shift = start_index;  
  27.         }  
  28.         while (n--) {  
  29.             if (p->fix.visual == FB_VISUAL_TRUECOLOR ||  // 真彩色  
  30.                 p->fix.visual == FB_VISUAL_DIRECTCOLOR )  
  31.                 color = palette[*src];  
  32.             else  
  33.                 color = *src;  
  34.             color <<= FB_LEFT_POS(p, bpp);  
  35.             val |= FB_SHIFT_HIGH(p, color, shift ^ bswapmask);  // 合成像素  
  36.             if (shift >= null_bits) {  
  37.                 FB_WRITEL(val, dst++);  // 写到buffer就从LCD上显示出来了  
  38.       
  39.                 val = (shift == null_bits) ? 0 :   
  40.                     FB_SHIFT_LOW(p, color, 32 - shift);  
  41.             }  
  42.             shift += bpp;  
  43.             shift &= (32 - 1);  
  44.             src++;  
  45.         }  
  46.         if (shift) {  
  47.             u32 end_mask = fb_shifted_pixels_mask_u32(p, shift,  
  48.                         bswapmask);  
  49.   
  50.             FB_WRITEL((FB_READL(dst) & end_mask) | val, dst);  
  51.         }  
  52.         dst1 += p->fix.line_length;  // 换行  
  53.         if (pitch_index) {  
  54.             dst2 += p->fix.line_length;  
  55.             dst1 = (u8 __iomem *)((long __force)dst2 & ~(sizeof(u32) - 1));  
  56.   
  57.             start_index += pitch_index;  
  58.             start_index &= 32 - 1;  
  59.         }  
  60.     }  
  61. }  
回到主题

下面我们分析最复杂的函数

...

0 0
原创粉丝点击