您的位置:首页 > 运维架构 > Linux

Linux监控系统开发详解(四)--- framebuffer驱动分析

2015-01-30 20:26 344 查看
Framebuffer驱动



为什么要用frambuffer

如果我们的系统要用GUI(图形界面接口),比如minigui,MicroWindows.这时LCD设备驱动程序就应该编写成frambuffer接口,而不是编写成仅仅操作底层的LCD控制器接口。

什么是frambuffer设备

frambuffer设备层是对图像设备的一种抽象,它代表了视频硬件的帧缓存,使得应用程序通过定义好的接口就可以访问硬件。所以应用程序不需要考虑底层的(寄存器级)的操作。应用程序对设备文件的访问一般在/dev 目录,如 /dev/fb*.Framebuffer机制模仿显卡的功能,将显卡硬件结构抽象掉,可以通过Framebuffer的读写直接对显存进行操作。用户可以将 Framebuffer看成是显示内存的一个映像,将其映射到进程地址空间之后,就可以直接进行读写操作,而写操作可以立即反应在屏幕上。这种操作是抽象
的,统一的,用户不必关心物理显存的位置、换页机制等等具体细节,这些都是由Framebuffer设备驱动来完成的,但Framebuffer本身不具备任何运算数据的能力,就只好比是一个暂时存放水的水池,CPU将运算后的结果放到这个水池,水池再将结果流到显示器,中间不会对数据做处理,应用程序也可以直接读写这个水池的内容。在嵌入式系统中一般没有专门的显存,而仅仅是从RAM(SDRAM)空间中分配一段显示缓冲区,典型结构如下图所示:



一块LCD屏不但需要LCD驱动器,还需要有相应的LCD控制器。通常LCD驱动器会以COF/COG的形式与LCD玻璃基板***在一起,而LCD控制器则由外部电路来实现。许多MCU内部直接集成了LCD控制器,通过LCD控制器可以方便地控制STN和TFT屏。

3.6.3 linux frambuffer 驱动源码分析

linux中frambuffer接口的所有功能实现都包括在下面两个文件中:

1) linux/include/linux/fb.h

2)linux/drivers/video/fbmem.c

下面详细分析这两个文件:

3.6.3.1 fb.h


所有frambuffer重要的结构体都定义在这个文件中。下面逐个分析他们:

1) fb_var_screeninfo

这个结构用来描述一个显卡可以被设置的特性,在fb_var_screeninfo结构体里有我们设备需要的,比如分辨率等信息。

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]; /* 保留 */

};

2) fb_fix_screeninfon

这个结构体定义了一些显示设备的特性,这些特性当设备的工作模式确定之后就不能改变了。例如:frambuffer 内存的起始地址。这个地址是根据模式的不同而不同。一旦你用了某种模式,你就不要在想去改变他的起始地址了。在这种情况下,你可以获得显示设备的内存 区域地址,但是你不能更改他。

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; /* 每行的长度,单位字节 */

1. unsigned long mmio_start; /* I/O 内存的开始地址 */

2. /* (物理地址) */

3. __u32 mmio_len; /* I/O内存的长度 */

4. __u32 accel; /* 对驱动程序的标示:是哪个设备*/

5. __u16 reserved[3]; /* 保留 */

6. };

3) fb_cmap

调色板信息,这个结构是设备依赖的。应用程序可以通过ioctls的FBIOGETCMAP和FBIOPUTCMAP命令来获得和设置这个结构。

struct fb_cmap {

1. __u32 start; /* First entry */

2. __u32 len; /* Number of entries */

3. __u16 *red; /* Red values */

4. __u16 *green;

5. __u16 *blue;

6. __u16 *transp; /* transparency, can be NULL */

7. };

4)fb_info

这个结构代表了一个显示设备的当前状态。他仅对内核可见。除了fb_info结构,内核还有一个fb_ops结构,定义了一些驱动必须的操作函数。

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. };

5)struct fb_ops

应用程序可以通过ioctl()系统调用来操作LCD硬件,这些操作需要fb_ops中的函数的支持。

/*

*Frame buffer operations

*

*LOCKING NOTE: those functions must _ALL_ be called with the

console

*semaphore held, this is the only suitablelocking mechanism we

have

*in 2.6. Some may be called at interrupt time at this point though.

*

*The exception to this is the debug related hooks. Putting the fb

*into a debug state (e.g. flipping to the kernel console) and restoring

*it must be done in a lock-free manner, so low level drivers should

*keep track of the initial console (if applicable) and may need to

*perform direct, unlocked hardware writesin these hooks.

*/

1. struct fb_ops {

2. /* open/release and usage marking */

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. /* For framebuffers with strange non linear layouts or that do not

8. * work with normal memory mapped access

9. */

10. ssize_t (*fb_read)(struct fb_info *info, char __user *buf,

11. size_t count, loff_t *ppos);

12. ssize_t (*fb_write)(struct fb_info *info, const char __user *buf,

13. size_t count, loff_t *ppos);

14.

15. /* checks var and eventually tweaks it to something supported,

16. * DO NOT MODIFY PAR */

17. int (*fb_check_var)(struct fb_var_screeninfo *var, struct fb_info *info);

18.

19. /* set the video mode according to info->var */

20. int (*fb_set_par)(struct fb_info *info);

21.

22. /* set color register */

23. int (*fb_setcolreg)(unsigned regno, unsigned red, unsigned green,

24. unsigned blue, unsigned transp, struct fb_info *info);

25.

26. /* set color registers in batch */

27. int (*fb_setcmap)(struct fb_cmap *cmap, struct fb_info *info);

28.

29. /* blank display */

30. int (*fb_blank)(int blank, struct fb_info *info);

31.

32. /* pan display */

33. int (*fb_pan_display)(struct fb_var_screeninfo *var, struct fb_info *info);

34.

35. /* Draws a rectangle */

36. void (*fb_fillrect) (struct fb_info *info, const struct fb_fillrect *rect);

37. /* Copy data from area to another */

38. void (*fb_copyarea) (struct fb_info *info, const struct fb_copyarea *region);

39. /* Draws a image to the display */

40. void (*fb_imageblit) (struct fb_info *info, const struct fb_image *image);

41.

42. /* Draws cursor */

43. int (*fb_cursor) (struct fb_info *info, struct fb_cursor *cursor);

44.

45. /* Rotates the display */

46. void (*fb_rotate)(struct fb_info *info, int angle);

47.

48. /* wait for blit idle, optional */

49. int (*fb_sync)(struct fb_info *info);

50.

51. /* perform fb specific ioctl (optional) */

52. int (*fb_ioctl)(struct fb_info *info, unsigned int cmd,

53. unsigned long arg);

54.

55. /* Handle 32bit compat ioctl (optional) */

56. int (*fb_compat_ioctl)(struct fb_info *info, unsigned cmd,

57. unsigned long arg);

58.

59. /* perform fb specific mmap */

60. int (*fb_mmap)(struct fb_info *info, struct vm_area_struct *vma);

61.

62. /* get capability given var */

63. void (*fb_get_caps)(struct fb_info *info, struct fb_blit_caps *caps,

64. struct fb_var_screeninfo *var);

65.

66. /* teardown any resources to do with this framebuffer */

67. void (*fb_destroy)(struct fb_info *info);

68. };

6)主要结构关系

1. struct fb_info

2. | | fb_var_screeninfo

3. | | fb_fix_screeninfo

4. | | fb_cmap

5. | | modename[40]

6. struct fb_ops ---|--->ops on var

7. | | fb_open

8. | | fb_release

9. | | fb_ioctl

10. | | fb_mmap

11. struct fbgen_hwswitch -|-> detect

12. | | encode_fix

13. | | encode_var

14. | | decode_fix

15. | | decode_var

16. | | get_var

17. | | set_var

18. | | getcolreg

19. | | setcolreg

20. | | pan_display






3.6.3.2fbmem.c

fbmem.c 是frambuffer驱动的核心,他向上给应用程序提供了系统调用接口,向下对特定的硬件提供底层的驱动接口。底层驱动可以通过接口向内核注册自己。fbmem.c提供了frambuffer驱动的所有接口代码,从而避免重复的工作。

1) 全局变量

1. struct fb_info*registered_fb[FB_MAX];

2. int num_registered_fb;

这两个变量用来标识系统中正在使用的fb_info结构,fb_info代表了显示设备当前的状态。所有的fb_info结构体都保存在全局数组中。当一个 新的frambuffer注册到内核,一个新的项就会加入到这个数组中并且 num_registered_fb加一。

1. static struct {

2. const char *name;

3. int (*init)(void);

4. int (*setup)(void);

5. } fb_drivers[] __initdata= { ....};

如果一个frambuffer 驱动模块是静态链接到内核的,那么必须在这个结构中加入新项,如果用动态加载模块的方法,就不用考虑这个结构了。

1. static struct file_operations fb_ops ={

2. owner: THIS_MODULE,

3. read: fb_read,

4. write: fb_write,

5. ioctl: fb_ioctl,

6. mmap: fb_mmap,

7. open: fb_open,

8. release: fb_release

9. };

这是面向应用程序的接口,fbmem.c中实现了这些操作。

2) register_framebuffer(struct fb_info*fb_info) 函数 和 unregister_framebuffer(structfb_info *fb_info)函数。

这个函数是frambuffer设备驱动程序的底层接口。驱动程序用这两个函数向内核注册和注销自己。驱动程序所做的所有底层工作就是填充一个fb_info结构体然后注册自己。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: