LCD驱动程序(一)

LCD显示原理:

在JZ2440上,想要让LCD显示,需要几个部分1、LCD硬件 2、开发板上的LCD控制器 3、SDRAM内存存放数据FramBuffer 4、可能还需要一个调色板(实际上是一块内存,里面数据可以组成各种颜色)

显示原理:在开发板上操作LCD控制器,使得开发板向SDRAM内存里去除数据发送通过LCD数据引脚发送到LCD屏上。

 

具体硬件操作步骤:

1、LCD引脚的连接,根据LCD原理图配置引脚

2、根据LCD控制器手册设置LCD控制器

3、分配显存,并把地址告诉LCD控制器

需要调色板的情况:LCD数据线少,比如16位数据线无法显示完全部的颜色组成,只能当做一个索引作用,指向调色板上正真的地址颜色空间

 

LCD液晶屏显示原理:

     可以想象一下LCD后面有一个电子枪,电子枪的作用就是将从FramBuffer内存里获取到的颜色,一个一个的打到LCD屏幕上,怎么打?顺序为:

以液晶屏左上角开始,从左往右开始,一个一个颜色点打上去,打到后面没有地方的时候,又开始换行又从左往右打;就比如你打开一个记事本按住某个字符符号不懂,

它会不断的在记事本上输出字母,当到边界是开始换行输出。直到输出完为止。当然LCD液晶屏上空间有限,打的速率非常快的,是你感觉是图像是突然就出现到你

前面来一样。

------------------------------------------------------------------------------------------------------------------------------------

LCD驱动程序的框架

满足字符设备驱动程序的框架

1、应用程序通过open、read、write等函数进入内核进而调用dri_open、dri_read、dir_write等函数,通过设备好找到LCD驱动的注册id,进而

进入到到驱动函数的File_operation结构体函数,对硬件进行操作,主要框架如图所示。

 


LCD驱动程序

假设
app: open("/dev/fb0", ...) 主设备号: 29, 次设备号: 0
--------------------------------------------------------------
kernel:
fb_open
int fbidx = iminor(inode);
struct fb_info *info = = registered_fb[0];

app: read()
---------------------------------------------------------------
kernel:
fb_read
int fbidx = iminor(inode);
struct fb_info *info = registered_fb[fbidx];
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)

问1. registered_fb在哪里被设置?
答1. register_framebuffer

怎么写LCD驱动程序?
1. 分配一个fb_info结构体: framebuffer_alloc
2. 设置
3. 注册: register_framebuffer
4. 硬件相关的操作

----------------------------------------------------------------------------------------------------------------

对LCD初始化:主入口函数要做的事情

1. 分配一个fb_info结构体: framebuffer_alloc

struct fb_info {   

........

struct fb_var_screeninfo var; /* Current var  可变参数*/
struct fb_fix_screeninfo fix; /* Current fix 固定参数*/

........

}

/* 1. 分配一个fb_info */
s3c_lcd = framebuffer_alloc(0, NULL);

2. 设置

/* 2. 设置 */
/* 2.1 设置固定的参数 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) */
__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 */
};

strcpy(s3c_lcd->fix.id, "mylcd");
s3c_lcd->fix.smem_len = 240*320*16/8;
s3c_lcd->fix.type = FB_TYPE_PACKED_PIXELS;
s3c_lcd->fix.visual = FB_VISUAL_TRUECOLOR; /* TFT */
s3c_lcd->fix.line_length = 240*2;


/* 2.2 设置可变的参数Current var */

             

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

s3c_lcd->var.xres = 240;
s3c_lcd->var.yres = 320;
s3c_lcd->var.xres_virtual = 240;
s3c_lcd->var.yres_virtual = 320;
s3c_lcd->var.bits_per_pixel = 16;

 

/* RGB:565 */
s3c_lcd->var.red.offset = 11;
s3c_lcd->var.red.length = 5;

s3c_lcd->var.green.offset = 5;
s3c_lcd->var.green.length = 6;

s3c_lcd->var.blue.offset = 0;
s3c_lcd->var.blue.length = 5;

s3c_lcd->var.activate = FB_ACTIVATE_NOW;


/* 2.3 设置操作函数 */

s3c_lcd->fbops              = &s3c_lcdfb_ops;
/* 2.4 其他的设置 */

s3c_lcd->screen_size   = 240*324*16/8;

 3. 硬件相关的操作 

/* 3.1 配置GPIO用于LCD */
/* 3.2 根据LCD手册设置LCD控制器, 比如VCLK的频率等 */
/* 3.3 分配显存(framebuffer), 并把地址告诉LCD控制器 */


4. 注册: register_framebuffer

 

/* 4. 注册 */
register_framebuffer(s3c_lcd);

 

 

剩余的对s3c_lcdfb_ops的配置以及硬件配置查看LCD驱动(二)

posted @ 2017-02-12 15:28  我有一壶酒  阅读(536)  评论(0编辑  收藏  举报