今天要讨论的LCD驱动,首先分析fbmem.c LCD核心层,通过分析代码可知,在核心层里已经有 主设备号、file_operations、register_chrdev.然而这些只是抽象出的核心层,可以参考Atmel_fb.c来写出硬件相关的东西。在LCD驱动硬件相关的东西里面,有很大部分是寄存器相关的一些设置。
LCD驱动程序:
假设打开的文件主设备号为:29,次设备号为:0
应用程序: open("/dev/fb0" ...) 主设备号: 29, 次设备号: 0
------------------------------------------------------------
kernel:
fb_open
int fbidx = iminor(inode); // 得到设备节点的次设备号。
//struct fb_info *info == registered_fb[fbidx];
struct fb_info *info == registered_fb[0]; // 假设次设备号为0
应用程序: read()
-------------------------------------------------------------
kernel:
fb_read
//int fbidx = iminor(inode);
int 0 = iminor(inode);
struct fb_info *info = registered_fb[fbidx];
//src = (u32 __iomem *) (info->screen_base + p); // screen_base显存基地址
if (info->fbops->fb_read) // 如果有读函数
return info->fbops->fb_read(info, buf, count, ppos);
src = (u32 __iomem *) (info->screen_base + p); // 如果没有读函数
dst = buffer;
*dst++ = fb_readl(src++);
copy_to_user(buf, buffer, c)
---------------------------------------------------------------
综上,read和open都依赖于fb_info结构体,而fb_info结构体又依赖于regiseted_fb以次设备号为下标得到。
registered_fb[fbidx]数组在哪里被设置?
register_framebuffer (向核心层注册硬件设备的信息如,s3c2410fb.c、Atmel_fb.c等)
怎么写LCD驱动程序?
1,分配一个fb_info结构体 fbinfo = framebuffer_alloc(sizeof(struct s3c2410fb_info), &pdev->dev)
2,设置
3,注册 register_framebuffer
4,硬件相关的操作 ioctrl FBIOGET_VSCREENINFO(可变的屏幕信息)其中的V即为Var
if (!fb)
return -ENODEV;
switch (cmd) {
case FBIOGET_VSCREENINFO:
return copy_to_user(argp, &info->var,
sizeof(var)) ? -EFAULT : 0;
struct fb_info {
int node;
int flags;
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 */
struct fb_var_screeninfo { /* 可变参数 */
__u32 xres; /* visible resolution */
__u32 yres;
__u32 xres_virtual; /* virtual resolution */
__u32 yres_virtual;
__u32 xoffset; /* offset from virtual to visible */
__u32 yoffset; /* resolution */
__u32 bits_per_pixel; /* guess what */
__u32 grayscale; /* != 0 Graylevels instead of colors */
struct fb_fix_screeninfo { /* 固定参数 */
char id[16]; /* identification string eg "TT Builtin" */
unsigned long smem_start; /* Start of frame buffer mem */
/* (physical address) */
__u32 smem_len; /* Length of frame buffer mem */
__u32 type; /* see FB_TYPE_* */
__u32 type_aux; /* Interleave for interleaved Planes */
__u32 visual; /* see 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; /* length of a line in bytes */
unsigned long mmio_start; /* Start of Memory Mapped I/O */
/* (physical address) */
__u32 mmio_len; /* Length of Memory Mapped I/O */
__u32 accel; /* Indicate to driver which */
/* specific chip/card we have */
__u16 reserved[3]; /* Reserved for future compatibility */
};
struct fb_var_screeninfo {
__u32 xres; /* visible resolution */
__u32 yres;
__u32 xres_virtual; /* virtual resolution 虚拟分辨率*/
__u32 yres_virtual;
__u32 xoffset; /* offset from virtual to visible */
__u32 yoffset; /* resolution */
__u32 bits_per_pixel; /* guess what 每个相素用多少个位 */
__u32 grayscale; /* != 0 Graylevels instead of colors */
struct fb_bitfield red; /* bitfield in fb mem if true color, 红 */
struct fb_bitfield green; /* else only length is significant 绿*/
struct fb_bitfield blue; /* 蓝 */
struct fb_bitfield transp; /* transparency 透明色 */
__u32 nonstd; /* != 0 Non standard pixel format */
__u32 activate; /* see FB_ACTIVATE_* */
__u32 height; /* height of picture in mm */
__u32 width; /* width of picture in mm */
__u32 accel_flags; /* (OBSOLETE) see fb_info.flags */
/* Timing: All values in pixclocks, except pixclock (of course) */
__u32 pixclock; /* pixel clock in ps (pico seconds) */
__u32 left_margin; /* time from sync to picture */
__u32 right_margin; /* time from picture to sync */
__u32 upper_margin; /* time from sync to picture */
__u32 lower_margin;
__u32 hsync_len; /* length of horizontal sync */
__u32 vsync_len; /* length of vertical sync */
__u32 sync; /* see FB_SYNC_* */
__u32 vmode; /* see FB_VMODE_* */
__u32 rotate; /* angle we rotate counter clockwise */
__u32 reserved[5]; /* Reserved for future compatibility */
};
测试:
1,make menuconfig去掉原来的驱动程序,以避免对新的驱动程序有影响,去掉的是 S3C2410 LCD framebuffer support编译成模块,因为还要调用里面的cfbcopyarea.ko,cfbfillrect.ko,cfbimgblt.ko。
2,make uImage
make modules
3,使用新的uImage启动开发板。
4,insmod cfbcopyarea.ko
insmod cfbfillrect.ko
insmod cfbimgblt.ko
insmod lcd.ko
echo hello > /dev/tty1 //可以在LCD上显示hello
cat lcd.ko > /dev/fb0 // 花屏
5,另一种测试方法:修改/etc/inittab增加一行
tty1::askfirst:-/bin/sh
用新内核重启
insmod cfbcopyarea.ko
insmod cfbfillrect.ko
insmod cfbimgblt.ko
insmod lcd.ko
insmod buttons.ko