您的位置:首页 > 其它

mini210开发板H43电阻屏驱动程序

2014-04-10 16:54 387 查看
把代码粘上来,肯定能用,照着裸机改的,我刚刚试过的

#include <linux/module.h>
#include <linux/kernel.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/workqueue.h>
#include <linux/wait.h>
#include <linux/platform_device.h>
#include <linux/clk.h>

#include <asm/io.h>
#include <asm/uaccess.h>
#include <asm/div64.h>

#include <asm/mach/map.h>

#include <plat/fb.h>
static int s3c_lcdfb_setcolreg(unsigned int regno, unsigned int red,
unsigned int green, unsigned int blue,
unsigned int transp, struct fb_info *info);

static struct fb_ops s3c_lcdfb_ops = {
.owner		= THIS_MODULE,
.fb_setcolreg	= s3c_lcdfb_setcolreg,
.fb_fillrect	= cfb_fillrect,
.fb_copyarea	= cfb_copyarea,
.fb_imageblit	= cfb_imageblit,
};

static struct fb_info *s3c_lcd;
struct clk *lcd_clk;
static u32 pseudo_palette[16];
/*mini210 lcd regs*/
static volatile unsigned long *gPF0CON;
static volatile unsigned long *gPF1CON;
static volatile unsigned long *gPF2CON;
static volatile unsigned long *gPF3CON;

static volatile unsigned long *gPD0CON;
static volatile unsigned long *gPD0DAT;

static volatile unsigned long *cLK_SRC1;
static volatile unsigned long *cLK_DIV1;
static volatile unsigned long *dISPLAY_CONTROL;

static volatile unsigned long *vIDCON0;
static volatile unsigned long *vIDCON1;
static volatile unsigned long *vIDTCON2;
static volatile unsigned long *wINCON0;
static volatile unsigned long *wINCON2;
static volatile unsigned long *sHADOWCON;
static volatile unsigned long *vIDOSD0A;
static volatile unsigned long *vIDOSD0B;
static volatile unsigned long *vIDOSD0C;

static volatile unsigned long *vIDW00ADD0B0;
static volatile unsigned long *vIDW00ADD1B0;

static volatile unsigned long *vIDTCON0;
static volatile unsigned long *vIDTCON1;

static volatile unsigned long *clk_gate_block;

#define HSPW 			(0)
#define HBPD			(40 - 1)
#define HFPD 			(5 - 1)
#define VSPW			(0)
#define VBPD 			(8 - 1)
#define VFPD 			(8 - 1)
// FB地址
//#define FB_ADDR			(0x23000000)
#define ROW				(272)
#define COL				(480)
#define HOZVAL			(COL-1)
#define LINEVAL			(ROW-1)

#define LeftTopX     0
#define LeftTopY     0
#define RightBotX   479
#define RightBotY   271
/* 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 void regs_remap(void)
{
gPF0CON= ioremap(0xE0200120, 4);
gPF1CON= ioremap(0xE0200140, 4);
gPF2CON= ioremap(0xE0200160, 4);
gPF3CON= ioremap(0xE0200180, 4);

gPD0CON= ioremap(0xE02000A0, 4);
gPD0DAT= ioremap(0xE02000A4, 4);

cLK_SRC1= ioremap(0xe0100204, 4);
cLK_DIV1= ioremap(0xe0100304, 4);
dISPLAY_CONTROL= ioremap(0xe0107008, 4);

vIDCON0= ioremap(0xF8000000, 4);
vIDCON1= ioremap(0xF8000004, 4);
vIDTCON2= ioremap(0xF8000018, 4);
wINCON0= ioremap(0xF8000020, 4);
wINCON2= ioremap(0xF8000028, 4);
sHADOWCON= ioremap(0xF8000034, 4);
vIDOSD0A= ioremap(0xF8000040, 4);
vIDOSD0B= ioremap(0xF8000044, 4);
vIDOSD0C= ioremap(0xF8000048, 4);

vIDW00ADD0B0= ioremap(0xF80000A0, 4);
vIDW00ADD1B0= ioremap(0xF80000D0, 4);

vIDTCON0= ioremap(0xF8000010, 4);
vIDTCON1= ioremap(0xF8000014, 4);

//clk_gate_block= ioremap(0xE0100480, 4);
}
static void regs_unremap(void)
{
//iounmap(clk_gate_block);

iounmap(gPF0CON);
iounmap(gPF1CON);
iounmap(gPF2CON);
iounmap(gPF3CON);

iounmap(gPD0CON);
iounmap(gPD0DAT);

iounmap(cLK_SRC1);
iounmap(cLK_DIV1);
iounmap(dISPLAY_CONTROL);

iounmap(vIDCON0);
iounmap(vIDCON1);
iounmap(vIDTCON2);
iounmap(wINCON0);
iounmap(wINCON2);
iounmap(sHADOWCON);
iounmap(vIDOSD0A);
iounmap(vIDOSD0B);
iounmap(vIDOSD0C);

iounmap(vIDW00ADD0B0 );
iounmap(vIDW00ADD1B0);

iounmap(vIDTCON0);
iounmap(vIDTCON1);

}
static void lcd_hadinit(void)
{
// 配置引脚用于LCD功能
*gPF0CON = 0x22222222;
*gPF1CON = 0x22222222;
*gPF2CON = 0x22222222;
*gPF3CON = 0x22222222;
// 打开背光
*gPD0CON &= ~(0xf<<4);
*gPD0CON |= (1<<4);
printk("close backlight\n");
*gPD0DAT |= (1<<1);
// 10: RGB=FIMD I80=FIMD ITU=FIMD
*dISPLAY_CONTROL = 2<<0;
// bit[26~28]:使用RGB接口
// bit[18]:RGB 并行
// bit[2]:选择时钟源为HCLK_DSYS=166MHz
*vIDCON0 &= ~( (3<<26)|(1<<18)|(1<<2) );
// bit[1]:使能lcd控制器
// bit[0]:当前帧结束后使能lcd控制器
*vIDCON0 |= ( (1<<0)|(1<<1) );
// bit[6]:选择需要分频
// bit[6~13]:分频系数为15,即VCLK = 166M/(14+1) = 11M
*vIDCON0 |= 14<<6 | 1<<4;
// H43-HSD043I9W1.pdf(p13) 时序图:VSYNC和HSYNC都是低脉冲
// s5pv210芯片手册(p1207) 时序图:VSYNC和HSYNC都是高脉冲有效,所以需要反转
*vIDCON1 |= 1<<5 | 1<<6;
// 设置时序
*vIDTCON0 = VBPD<<16 | VFPD<<8 | VSPW<<0;
*vIDTCON1 = HBPD<<16 | HFPD<<8 | HSPW<<0;
// 设置长宽
*vIDTCON2 = (LINEVAL << 11) | (HOZVAL << 0);
// 设置windows1	// bit[0]:使能
// bit[2~5]:24bpp

// 设置windows1的上下左右
*vIDOSD0A = (LeftTopX<<11) | (LeftTopY << 0);
*vIDOSD0B = (RightBotX<<11) | (RightBotY << 0);
*vIDOSD0C = (LINEVAL + 1) * (HOZVAL + 1);

}
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)
{

printk("mini210000000  lcd init \n");
/* 1. 分配一个fb_info */
s3c_lcd = framebuffer_alloc(0, NULL);

/* 2. 设置 */
/* 2.1 设置固定的参数 */
strcpy(s3c_lcd->fix.id, "mylcd");
s3c_lcd->fix.smem_len = 480*272*32/8;        /* TQ2440的LCD位宽是24,但是2440里会分配4字节即32位(浪费1字节) */
s3c_lcd->fix.type     = FB_TYPE_PACKED_PIXELS;
s3c_lcd->fix.visual   = FB_VISUAL_TRUECOLOR; /* TFT */
s3c_lcd->fix.line_length = 480*4;

/* 2.2 设置可变的参数 */
s3c_lcd->var.xres           = 480;
s3c_lcd->var.yres           = 272;
s3c_lcd->var.xres_virtual   = 480;
s3c_lcd->var.yres_virtual   = 272;
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    = 8;

s3c_lcd->var.activate       = FB_ACTIVATE_NOW;

/* 2.3 设置操作函数 */
s3c_lcd->fbops              = &s3c_lcdfb_ops;

/* 2.4 其他的设置 */
s3c_lcd->pseudo_palette = pseudo_palette;
//s3c_lcd->screen_base  = ;  /* 显存的虚拟地址 */
s3c_lcd->screen_size   = 480*272*32/8;

/* 3. 硬件相关的操作 */
/* 3.1 配置GPIO用于LCD */
regs_remap();
// 配置引脚用于LCD功能
*gPF0CON = 0x22222222;
*gPF1CON = 0x22222222;
*gPF2CON = 0x22222222;
*gPF3CON = 0x22222222;
// 打开背光
*gPD0CON &= ~(0xf<<4);
*gPD0CON |= (1<<4);
printk("close backlight\n");
*gPD0DAT |= (1<<1);
// 10: RGB=FIMD I80=FIMD ITU=FIMD
*dISPLAY_CONTROL = 2<<0;
//   *clk_gate_block&=~((1<<3)|(1<<2));
lcd_clk = clk_get(NULL,"lcd");
if(!lcd_clk||IS_ERR(lcd_clk)){
printk(KERN_INFO"FAILED to get lcd clock source\n");
}
clk_enable(lcd_clk);
// bit[26~28]:使用RGB接口
// bit[18]:RGB 并行
// bit[2]:选择时钟源为HCLK_DSYS=166MHz
*vIDCON0 &= ~( (3<<26)|(1<<18)|(1<<2) );
// bit[1]:使能lcd控制器
// bit[0]:当前帧结束后使能lcd控制器
*vIDCON0 |= ( (1<<0)|(1<<1) );
// bit[6]:选择需要分频
// bit[6~13]:分频系数为15,即VCLK = 166M/(14+1) = 11M
*vIDCON0 |= 14<<6 | 1<<4;
// H43-HSD043I9W1.pdf(p13) 时序图:VSYNC和HSYNC都是低脉冲
// s5pv210芯片手册(p1207) 时序图:VSYNC和HSYNC都是高脉冲有效,所以需要反转
*vIDCON1 |= 1<<5 | 1<<6;
// 设置时序
*vIDTCON0 = VBPD<<16 | VFPD<<8 | VSPW<<0;
*vIDTCON1 = HBPD<<16 | HFPD<<8 | HSPW<<0;
// 设置长宽
*vIDTCON2 = (LINEVAL << 11) | (HOZVAL << 0);

*wINCON0 |= 1<<0;
*wINCON0 &= ~(0xf << 2);
*wINCON0 |= (0xB<<2) | (1<<15);
// 设置windows1的上下左右
*vIDOSD0A = (LeftTopX<<11) | (LeftTopY << 0);
*vIDOSD0B = (RightBotX<<11) | (RightBotY << 0);
*vIDOSD0C = (LINEVAL + 1) * (HOZVAL + 1);
/* 3.3 分配显存(framebuffer), 并把地址告诉LCD控制器 */
s3c_lcd->screen_base = dma_alloc_writecombine(NULL, s3c_lcd->fix.smem_len, (dma_addr_t *)&(s3c_lcd->fix.smem_start), GFP_KERNEL);
// 设置fb的地址
*vIDW00ADD0B0 = s3c_lcd->fix.smem_start;
*vIDW00ADD1B0 = s3c_lcd->fix.smem_start+s3c_lcd->fix.smem_len;
// 使能channel 0传输数据
*sHADOWCON = 0x1;

//s3c_lcd->fix.smem_start = xxx;  /* 显存的物理地址 */
/* 启动LCD */

/* 4. 注册 */

register_framebuffer(s3c_lcd);

return 0;
}

static void lcd_exit(void)
{
unregister_framebuffer(s3c_lcd);
*vIDCON0&=~(1<<1);
*wINCON0 &= ~(1<<0);
//	lcd_regs->lcdcon1 &= ~(1<<0); /* 关闭LCD控制器 */
//	lcd_regs->lcdcon1 &= ~(1<<3); /* 关闭LCD本身 */
//	*gpbdat &= ~1;     /* 关闭背光 */
printk("lcd exit");
dma_free_writecombine(NULL, s3c_lcd->fix.smem_len, s3c_lcd->screen_base, s3c_lcd->fix.smem_start);
regs_unremap();
framebuffer_release(s3c_lcd);
}

module_init(lcd_init);
module_exit(lcd_exit);

MODULE_LICENSE("GPL");
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: