LCD驱动程序(1)初步编写LCD驱动程序

来源:互联网 发布:易语言大漠模块源码 编辑:程序博客网 时间:2024/06/05 09:43

先参考内核里面自带的驱动程序,我们只是参考它的头文件而已


 /*1.分配一个fb_info结构体*/
 30     s5p_lcd=framebuffer_alloc(sizeof(struct s5p_lcd), &pdev->dev);
 31     //这里为什么需要一个大小,内核里面有个经常有个取巧的办法,分配一个结构体
    ,本来这个结构体只有这么大,它会额外分配一部分空间给你,然后你原本那个大小的
    里面有个私有指针,指向它。你可以往里面存一些你觉得有意义的数据


不信的话我们可以看一下framebuffer_alloc的源代码

struct fb_info *framebuffer_alloc(size_t size, struct device *dev)

{
#define BYTES_PER_LONG (BITS_PER_LONG/8)
#define PADDING (BYTES_PER_LONG - (sizeof(struct fb_info) % BYTES_PER_LONG))
int fb_info_size = sizeof(struct fb_info);
struct fb_info *info;
char *p;


if (size)
fb_info_size += PADDING;


p = kzalloc(fb_info_size + size, GFP_KERNEL);//看这里  fb_info_size还要加一个size。


if (!p)
return NULL;


info = (struct fb_info *) p;


if (size)
info->par = p + fb_info_size; //par指向额外分配的一段空间


info->device = dev;


#ifdef CONFIG_FB_BACKLIGHT
mutex_init(&info->bl_curve_mutex);
#endif


return info;
#undef PADDING
#undef BYTES_PER_LONG
}



在我们驱动程序中要设置fb_info这个结构体,我们来看看这个结构体中有什么东西

struct fb_info {
atomic_t count;
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;注意这里还有个fops操作函数
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 similar aperture base/size not
  smem_start/size as smem_start may just be an object
  allocated inside the aperture so may not actually overlap */
struct apertures_struct {
unsigned int count;
struct aperture {
resource_size_t base;
resource_size_t size;
} ranges[0];
} *apertures;
};



我们前面说了固定参数

struct fb_fix_screeninfo fix;/* Current fix */     //这里的意思是固定的参数

我们来看看这个结构体里面有什么东西

struct fb_fix_screeninfo {
char id[16]; /* identification string eg "TT Builtin" */         //名字 
unsigned long smem_start;/* Start of frame buffer mem */
/* (physical address) *///framebuffer的起始地址,我们一开始的时候没分配显存,还不知道,所以放到后面去
__u32 smem_len;/* Length of frame buffer mem */ //显存的长度,这个我们可以算出来的
__u32 type; /* see FB_TYPE_* *///这里说 看看这个宏 我们来看看这个宏里面有什么

#define FB_TYPE_PACKED_PIXELS0 /* Packed Pixels*/
#define FB_TYPE_PLANES 1/* Non interleaved planes */
#define FB_TYPE_INTERLEAVED_PLANES 2/* Interleaved planes */
#define FB_TYPE_TEXT 3/* Text/attributes */
#define FB_TYPE_VGA_PLANES 4/* EGA/VGA planes */
 

如果看不懂就用默认值,默认值都是0


__u32 type_aux;/* Interleave for interleaved Planes *


__u32 visual; /* see FB_VISUAL_* */                   //我们来看看这个宏

#define FB_VISUAL_MONO010 /* Monochr. 1=Black 0=White */
#define FB_VISUAL_MONO10 1/* Monochr. 1=White 0=Black */
#define FB_VISUAL_TRUECOLOR 2/* True color */
#define FB_VISUAL_PSEUDOCOLOR 3/* Pseudo color (like atari) */
#define FB_VISUAL_DIRECTCOLOR 4/* Direct color */
#define FB_VISUAL_STATIC_PSEUDOCOLOR 5/* Pseudo color readonly */

第一行表示单色,1表示黑,0表示白

第二行表示单色,1表示白,0表示黑

第三行表示真彩色 TFT屏是真彩色

  

                
__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 *///x方向的分辨率
__u32 yres; //y方向的分辨率
__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 */ //灰度值,我们不需要这个东西,因为我们前面设置了bpp


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
struct fb_bitfield transp;/* transparency *///透明色,我们没有透明度 struct fb_bitfield {
__u32 offset; /* beginning of bitfield */
__u32 length; /* length of bitfield */
__u32 msb_right;/* != 0 : Most significant bit is */ 
/* right */ 
};
第一个是从哪一位开始,第二个是长度,第三个是  最重要的一位,如果最重要的一位在最右边 那么这里应该设置为不等于0;



__u32 nonstd; /* != 0 Non standard pixel format */ //非标准,但是我们是标准的


__u32 activate;/* see FB_ACTIVATE_* *///我们看这个宏

#define FB_ACTIVATE_NOW0 /* set values immediately (or vbl)*/
#define FB_ACTIVATE_NXTOPEN 1/* activate on next open */
#define FB_ACTIVATE_TEST 2/* don't set, round up impossible */
#define FB_ACTIVATE_MASK       15
/* values */
#define FB_ACTIVATE_VBL       16/* activate values on next vbl  */
#define FB_CHANGE_CMAP_VBL     32 /* change colormap on vbl*/
#define FB_ACTIVATE_ALL       64/* change all VCs on this fb */
#define FB_ACTIVATE_FORCE     128 /* force apply even when no change*/
#define FB_ACTIVATE_INV_MODE  256       /* invalidate videomode */


看不懂就先用默认值


__u32 height; /* height of picture in mm    */ //高度 应该是这个LCD的物理尺寸,以毫米为单位
__u32 width; /* width of picture in mm     */ //宽度 应该是这个LCD的物理尺寸,以毫米为单位

不写,写了也没什么用户


__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 */
};



下面我们来设置我们的fops

我们看其他的驱动程序,会发现一个共同点

static struct fb_ops tiny_lcdfb_ops = {
.owner = THIS_MODULE,

.fb_fillrect = cfb_fillrect, //这一个是什么意思呢,从英文名字可以看出是填充矩形的意思。
.fb_copyarea = cfb_copyarea, //拷贝一个区域
.fb_imageblit = cfb_imageblit,
}; 这几个fops基本上在每个lcd驱动上都会出现,共用的


所以我们也来参照一下

很明显是对显存的一些操作。



经过上面这些操作,我们驱动程序变成这样的

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/err.h>
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/mm.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/fb.h>
#include <linux/init.h>
#include <linux/dma-mapping.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/clk.h>
#include <linux/cpufreq.h>
#include <asm/io.h>
#include <asm/div64.h>
#include <asm/mach/map.h>
#include <mach/regs-lcd.h>
#include <mach/regs-gpio.h>
#include <mach/fb.h>




static struct fb_info *s5p_info;


static struct fb_ops s5p_lcdfb_ops = {
.owner = THIS_MODULE,
//.fb_setcolreg= tiny_lcdfb_setcolreg,
.fb_fillrect = cfb_fillrect,
.fb_copyarea = cfb_copyarea,
.fb_imageblit = cfb_imageblit,
};


static int lcd_init(void)
{
int res;
/*1.分配一个fb_info结构体*/
s5p_info=framebuffer_alloc(0,NULL);
if (!s5p_info)
{
printk("framebuffer_alloc error");
return -ENOMEM;
}




//这里为什么需要一个大小,内核里面有个经常有个取巧的办法,分配一个结构体,本来这个结构体只有这么大,它会额外分配一部分空间给你,然后你原本那个大小的里面有个私有指针,指向它。你可以往里面存一些你觉得有意义的数据。
//但是这里我们不需要额外的那段空间,所以这里写为0,后面写为NULL


/*2.设置*/


/*2.1设置固定的参数*/


/*2.1.1名字*/
strcpy(s5p_info->fix.id,"ghlcd");
/*2.1.2 设置显存的长度*/
/*这里需要我们去看LCD的手册*/
s5p_info->fix.len=800*480*4;
/*2.1.3 type*/
s5p_info->fix.type=FB_TYPE_PACKED_PIXELS;
/*2.1.4  visual*/
s5p_info->fix.visual=VISUAL_TRUECOLOR;
/*2.1.5 一行的长度单位是字节*/
s5p_info->fix.line_length=800*4;
/*2.2设置可变的参数*/
/*2.2.1 x方向的分辨率*/
s5p_info->var.xres=800;
/*2.2.2 y方向的分辨率*/
s5p_info->var.yres=480;
/*2.2.3  x方向的虚拟分辨率*/
s5p_info->var.xres_virtual=800;
/*2.2.4  y方向的虚拟分辨率*/
s5p_info->var.yres_virtual=480;
/*2.2.5 每个像素用多少位*/
s5p_info->var.bits_per_pixel=32;
/*2.2.6 红色从那一位开始*/
//RGB 8:8:8
s5p_info->var.red.offset = 16;
/*2.2.7 长度*/
s5p_info->var.red.length =8;

s5p_info>var.green.offset= 8;
s5p_info->var.green.length = 8;


s5p_info->var.blue.offset  = 0;
s5p_info->var.blue.length  = 8;


/*2.2.8 activate */
s5p_info->var.activate = FB_ACTIVATE_NOW;
/*2.3设置fops操作函数*/
s5p_info->fbfops=&s5p_lcdfb_ops;
/*2.4其他的设置*/
//tiny_lcd->screen_base = ; /*显存的虚拟起始地址*/
s5p_info->screen_size = 800*480*4;
s5p_info->pseudo_palette = pseudo_pal; //这个是假的调色板


/*3.硬件相关的操作*/
/*3.1配置相应的GPIO为LCD管脚*/
/*3.2根据LCD手册设置LCD控制器,让它可以发出正确的信号*/
/*3.3分配framebuffer,并把物理地址告诉LCD控制器*/
//s5p_info->var.smem_start=xxxxx;
/*4.注册*/
res = register_framebuffer(s5p_info);
if (ret < 0) {
printk(KERN_ERR "Failed to register framebuffer device: %d\n",ret);
return ENOMEM;
}
return 0;


}


static void lcd_exit(void)
{

}


module_init(lcd_init);
module_exit(lcd_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("EIGHT");





0 0
原创粉丝点击