概述
一:步骤分析:
在上一节LCD层次分析中,得出写个LCD驱动入口函数,需要以下4步:
-
1) 分配一个fb_info结构体: framebuffer_alloc(); 2) 设置fb_info 3) 设置硬件相关的操作 4) 使能LCD,并注册fb_info: register_framebuffer()
具体步骤如下:
在驱动init入口函数中:
1)分配一个fb_info结构体
2)设置fb_info
2.1)设置固定的参数fb_info-> fix
2.2) 设置可变的参数fb_info-> var
2.3) 设置操作函数fb_info-> fbops
2.4) 设置fb_info 其它的成员
3)设置硬件相关的操作
3.1)配置LCD引脚
3.2)根据LCD手册设置LCD控制器
3.3)分配显存(framebuffer),把地址告诉LCD控制器和fb_info
4)开启LCD,并注册fb_info: register_framebuffer()
4.1) 直接在init函数中开启LCD(后面讲到电源管理,再来优化)
控制LCDCON5允许PWREN信号,
然后控制LCDCON1输出PWREN信号,
输出GPB0高电平来开背光,
4.2) 注册fb_info
二: 分配,设置fb_info结构体
具体操作
1)分配一个fb_info结构体
2)设置fb_info
2.1)设置固定的参数fb_info-> fix
2.2) 设置可变的参数fb_info-> var
2.3) 设置操作函数fb_info-> fbops
2.4) 设置fb_info 其它的成员
相关API:
1.分配一个fb_info结构体
struct fb_info *framebuffer_alloc(size_t size, struct device *dev); //申请一个fb_info结构体,
//size:额外的内存,
//*dev:指针, 这里填0,表示这个申请的结构体里没有内容
2.fb_info结构体如下:
struct fb_info {
... ...
struct fb_var_screeninfo var; //可变的参数
struct fb_fix_screeninfo fix; //固定的参数
... ...
struct fb_ops *fbops; //操作函数
... ...
char __iomem *screen_base; //显存虚拟起始地址
unsigned long screen_size; //显存虚拟地址长度
void *pseudo_palette;
//假的16色调色板,里面存放了16色的数据,可以通过8bpp数据来找到调色板里面的16色颜色索引值,模拟出16色颜色来,节省内存,不需要的话就指向一个不用的数组即可
... ...
};
3.固定的参数fb_info-> fix 结构体如下:
struct fb_fix_screeninfo {
char id[16]; //id名字
unsigned long smem_start; //framebuffer物理起始地址
__u32 smem_len; //framebuffer长度,字节为单位
__u32 type; //lcd类型,默认值0即可
__u32 type_aux; //附加类型,为0
__u32 visual; //画面设置,常用参数如下
// FB_VISUAL_MONO01 0 单色,0:白色,1:黑色
// FB_VISUAL_MONO10 1 单色,1:白色,0:黑色
// FB_VISUAL_TRUECOLOR 2 真彩(TFT:真彩)
// FB_VISUAL_PSEUDOCOLOR 3 伪彩
// FB_VISUAL_DIRECTCOLOR 4 直彩
__u16 xpanstep; /*如果没有硬件panning就赋值为0 */
__u16 ypanstep; /*如果没有硬件panning就赋值为0 */
__u16 ywrapstep; /*如果没有硬件ywrap就赋值为0 */
__u32 line_length; /*一行的字节数 ,例:(RGB565)240*320,那么这里就等于240*16/8 */
/*以下成员都可以不需要*/
unsigned long mmio_start; /*内存映射IO的起始地址,用于应用层直接访问寄存器,可以不需要*/
__u32 mmio_len; /* 内存映射IO的长度,可以不需要*/
__u32 accel;
__u16 reserved[3];
};
4.可变的参数fb_info-> var 结构体如下:
structfb_var_screeninfo{
__u32xres; /*可见屏幕一行有多少个像素点*/
__u32 yres; /*可见屏幕一列有多少个像素点*/
__u32 xres_virtual; /*虚拟屏幕一行有多少个像素点 */
__u32 yres_virtual; /*虚拟屏幕一列有多少个像素点*/
__u32 xoffset; /*虚拟到可见屏幕之间的行偏移,若可见和虚拟的分辨率一样,就直接设为0*/
__u32 yoffset; /*虚拟到可见屏幕之间的列偏移*/
__u32 bits_per_pixel; /*每个像素的位数即BPP,比如:RGB565则填入16*/
__u32 grayscale; /*非0时,指的是灰度,真彩直接填0即可*/
struct fb_bitfield red; //fb缓存的R位域, fb_bitfield结构体成员如下:
//__u32 offset; 区域偏移值,比如RGB565中的R,就在第11位
//__u32 length; 区域长度,比如RGB565的R,共有5位
//__u32 msb_right; msb_right ==0,表示数据左边最大, msb_right!=0,表示数据右边最大
struct fb_bitfield green; /*fb缓存的G位域*/
struct fb_bitfield blue; /*fb缓存的B位域*/
/*以下参数都可以不填,默认为0*/
struct fb_bitfield transp; /*透明度,不需要填0即可*/
__u32nonstd; /* != 0表示非标准像素格式*/
__u32 activate; /*设为0即可*/
__u32height; /*外设高度(单位mm),一般不需要填*/
__u32width; /*外设宽度(单位mm),一般不需要填*/
__u32 accel_flags; /*过时的参数,不需要填*/
/* 除了pixclock本身外,其他的都以像素时钟为 单位*/
__u32pixclock; /*像素时钟(皮秒)*/
__u32 left_margin; /*行切换,从同步到绘图之间的延迟*/
__u32right_margin; /*行切换,从绘图到同步之间的延迟*/
__u32upper_margin; /*帧切换,从同步到绘图之间的延迟*/
__u32lower_margin; /*帧切换,从绘图到同步之间的延迟*/
__u32hsync_len; /*水平同步的长度*/
__u32 vsync_len; /*垂直同步的长度*/
__u32 sync;
__u32 vmode;
__u32 rotate;
__u32reserved[5]; /*保留*/
}
5.操作函数fb_info-> fbops 结构体写法如下:
static struct fb_ops s3c_lcdfb_ops = {
.owner = THIS_MODULE,
.fb_setcolreg = my_lcdfb_setcolreg,//设置调色板fb_info-> pseudo_palette,自己构造该函数
.fb_fillrect = cfb_fillrect, //填充矩形,用/drivers/video/ cfbfillrect.c里的函数即可
.fb_copyarea = cfb_copyarea, //复制数据, 用/drivers/video/cfbcopyarea.c里的函数即可
.fb_imageblit = cfb_imageblit, //绘画图形, 用/drivers/video/imageblit.c里的函数即可
};
具体代码如下:
static int lcd_init(void)
{
/*1.分配一个fb_info结构体:framebuffer_alloc*/
s3c_lcd_info = framebuffer_alloc(0, NULL); /*申请一个fb_info结构体,size:额外的内存,这里为0,表示不需要,*dev:指针, 这里填NULL,表示这个申请的结构体里没有内容*/
/*2.设置fb_info*/
/*2.1设置固定参数fd_info->fix*/
strcpy(s3c_lcd_info->fix.id,"mylcd"); //id名字,将mylcd字符串复制到fix.id数组
s3c_lcd_info->fix.smem_len= 480*272*2; //显存farmebuffer长度
s3c_lcd_info->fix.type = FB_TYPE_PACKED_PIXELS; //lcd类型,就取默认值
s3c_lcd_info->fix.visual = FB_VISUAL_TRUECOLOR; //lcd颜色,黑白还是彩色
s3c_lcd_info->fix.line_length = 480*2; //一行的长度
/*2.2设置可变参数fd_info->var*/
s3c_lcd_info->var.xres = 480; //行分辨率 480
s3c_lcd_info->var.yres = 272; //列分辨率 272
s3c_lcd_info->var.xres_virtual = 480;
s3c_lcd_info->var.yres_virtual = 272;
s3c_lcd_info->var.bits_per_pixel = 16; //每个像素的位数即BPP,比如:RGB565则填入16
/*设置RGB的位域:565*/
s3c_lcd_info->var.red.offset = 11;
s3c_lcd_info->var.red.length = 5;
s3c_lcd_info->var.green.offset = 5;
s3c_lcd_info->var.green.length = 6;
s3c_lcd_info->var.blue.offset = 0;
s3c_lcd_info->var.blue.length = 5;
s3c_lcd_info->var.activate = FB_ACTIVATE_NOW;
/*2.3设置操作函数fd_info->fbops*/
s3c_lcd_info->fbops = &s3c2440_ops;
/*2.4其他设置*/
s3c_lcd_info->screen_size = 480*272*16/8; //显存的大小
//s3c_lcd_info->screen_base = ; //显存的虚拟地址
s3c_lcd_info->pseudo_palette = pseudo_palette; //假调色板
/*3.硬件相关操作*/
转载自https://www.cnblogs.com/lifexy/p/7604011.html
最后
以上就是羞涩黄豆为你收集整理的LCD驱动--二 写lcd驱动 1.分配,设置fb_info (转载)的全部内容,希望文章能够帮你解决LCD驱动--二 写lcd驱动 1.分配,设置fb_info (转载)所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复