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");
- LCD驱动程序(1)初步编写LCD驱动程序
- Linux LCD 驱动程序的编写
- Linux LCD 驱动程序的编写
- 嵌入式驱动编写-LCD驱动程序
- LCD设备驱动程序1
- LCD设备驱动程序1 .
- LCD 驱动程序
- Lcd驱动程序
- lcd驱动程序
- LCD驱动程序
- LCD驱动程序二(程序设计)
- WinCE(s3c2410)的LCD驱动程序编写指南(续)
- (转)WinCE(s3c2410)的LCD驱动程序编写指南
- LCD驱动程序——代码编写(二)
- LCD驱动程序——代码编写(二)
- LCD驱动程序——代码编写(二)
- LCD驱动程序——代码编写(二)
- WinCE的LCD驱动程序编写指南
- SSL/TLS握手过程
- Java8 DateTime与1582历法问题
- vue数据交互
- 出现importError: No module named certifi,如何解决
- 使用FEC改善UDP(RTP)音视频传输效果
- LCD驱动程序(1)初步编写LCD驱动程序
- 智能指针的用法
- 对.NET同步、异步、阻塞、非阻塞的理解。
- Scala 的 val与var
- 数组指针的用法,用处。
- 20170305 第一次学习总结
- Python生成随机数的方法
- 全景图 HelloPanorama 的使用
- androidstudio如何打渠道包,一个项目包含多个版本 如何选择一个版本打包