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

把代码粘上来,肯定能用,照着裸机改的,我刚刚试过的


#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");

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值