×
单片机 > 单片机程序设计 > 详情

《韦东山视频第二期》——LCD驱动

发布时间:2024-05-22 发布时间:
|

一、LCD驱动程序框架分析


app: open("/dev/fb0", ...) 主设备号:29, 次设备号:0


————————————————————————————————————————————————————

kernel:(核心文件/drivers/video/fbmem.c)


fb_open


int fbidx = iminor(inode);

struct fb_info *info;


info = registered_fb[fbidx]; //根据次设备号获得从底层注册的struct fb_info结构体中


file->private_data = info;

if (info->fbops->fb_open) { //调用底层struct fb_info结构体中的fb_open函数

res = info->fbops->fb_open(info,1);

if (res)

module_put(info->fbops->owner);

}


———————————————————————————————————————————————————


app: read()


_____________________________________________________________________________________


kernel:


fb_read


struct inode *inode = file->f_path.dentry->d_inode;

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)


怎么写LCD驱动程序?


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


2.设置


3.注册:register_framebuffer


4.硬件相关的操作


#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

struct lcd_regs {

unsigned long lcdcon1;

unsigned long lcdcon2;

unsigned long lcdcon3;

unsigned long lcdcon4;

unsigned long lcdcon5;

unsigned long lcdsaddr1;

unsigned long lcdsaddr2;

unsigned long lcdsaddr3;

unsigned long redlut;

unsigned long greenlut;

unsigned long bluelut;

unsigned long reserved[9];

unsigned long dithmode;

unsigned long tpal;

unsigned long lcdintpnd;

unsigned long lcdsrcpnd;

unsigned long lcdintmsk;

unsigned long lpcsel;

};

static struct fb_ops* s3c_lcdfb_ops = {

.owner = THIS_MODULE,

// .fb_setcplreg = atmel_lcdfb_setolreg,

.fb_fillrect = cfb_fillrect,

.fb_copyarea = cfb_copyarea,

.fb_imageblit = cfb_imageblit,

};

static struct fb_info* s3c_lcd;

static volatile unsigned long *gpbcon;

static volatile unsigned long *gpbdat;

static volatile unsigned long *gpccon;

static volatile unsigned long *gpdcon;

static volatile unsigned long *gpgcon;

static volatile struct lcd_regs* lcd_regs;

static u32 pseudo_palette[16]; //为了兼容,设置假的调色板

/* from pxafb.c */

static inline unsigned int chan_to_field(unsigned int chan, struct fb_bitfield *bf)

{

chan &= 0xffff;

chan >>= 16 - bf->length;

return chan << bf->offset;

}

static int s3c_lcdfb_setcolreg(unsigned int regno, unsigned int red,

unsigned int green, unsigned int blue,

unsigned int transp, struct fb_info *info)

{

unsigned int val;

if (regno > 16)

return 1;

/* 用red,green,blue三原色构造出val */

val = chan_to_field(red, &info->var.red);

val |= chan_to_field(green, &info->var.green);

val |= chan_to_field(blue, &info->var.blue);

//((u32 *)(info->pseudo_palette))[regno] = val;

pseudo_palette[regno] = val;

return 0;

}

static int lcd_init(void)

{

/* 1. 分配一个fb_info结构体 */

s3c_lcd = framebuffer_alloc(0, NULL);

/* 2. 设置 */

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

strcpy(s3c_lcd->fix.id, "mylcd");

s3c_lcd->fix.smem_len = 320*240*32/8; /* MINI2440的LCD位宽是24,但是2440里会分配4字节即32位(浪费1字节) */

s3c_lcd->fix.type = FB_TYPE_PACKED_PIXELS;

s3c_lcd->fix.visual = FB_VISUAL_TRUECOLOR; /* 真彩色 */

s3c_lcd->fix.line_length = 320 * 4; /* 1行的字节数 */

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

s3c_lcd->var.xres = 320;

s3c_lcd->var.yres = 240;

s3c_lcd->var.xres_virtual = 320;

s3c_lcd->var.yres_virtual = 240;

s3c_lcd->var.bits_per_pixel = 32; /* 每个像素所占的位数 */

/* RGB: 565 */

s3c_lcd->var.red.offset = 16;

s3c_lcd->var.red.length = 8;

s3c_lcd->var.green.offset = 8;

s3c_lcd->var.green.length = 8;

s3c_lcd->var.blue.offset = 0;

s3c_lcd->var.blue.length = 0;

s3c_lcd->var.activate = FB_ACTIVATE_NOW;

/* 2.3 设置操作函数 */

s3c_lcd->fops = &s3c_lcdfb_ops;

/* 2.4 其他设置 */

//s3c_lcd->pseudo_palette =; //

//s3c_lcd->screen_base = ; /* 显存的虚拟地址 */

s3c_lcd->screen_size = 320*240*32/8;

/* 3. 硬件相关的操作 */

/* 3.1 配置GPIO用于LCD */

gpbcon = ioremap(0x56000010, 8);

gpbdat = gpbcon+1;

gpccon = ioremap(0x56000020, 4);

gpdcon = ioremap(0x56000030, 4);

gpgcon = ioremap(0x56000060, 4);

*gpccon = 0xaaaaaaaa; /* GPIO管脚用于VD[7:0],LCDVF[2:0],VM,VFRAME,VLINE,VCLK,LEND */

*gpdcon = 0xaaaaaaaa; /* GPIO管脚用于VD[23:8] */

// *gpbcon &= ~(3); /* GPB0设置为输出引脚 */

// *gpbcon |= 1;

// *gpbdat &= ~1; /* 输出低电平 */

*gpgcon |= (3<<8); /* GPG4用作LCD_PWREN */

/* 3.2 根据LCD手册设置LCD控制器,比如VCLK的频率等 */

lcd_regs = ioremap(0x4D000000, sizeof(struct lcd_regs));

/*

* MINI2440 LCD 3.5英寸 ZQ3506_V0 SPEC.pdf 第11、12页

*

* LCD手册11,12页和2440手册"Figure 15-6. TFT L

[1] [2]
LCD驱动S3C2410程序框架

『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
基于arm的指纹识别门禁系统是如何设计的