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");
相关文章推荐
- 根据端口号查询进程pid,netstat -nptl
- 我们究竟该如何获取桌面句柄???
- xcode修改product name
- 毕业四年
- Linux网络编程socket错误分析
- android中使用proguard
- Objective-C 类的基础程序
- C++总结
- Layout---Linear Layout和Relative Layout
- Log4j标准配置
- Teradata 学习笔记5
- NGUI之UIRoot
- [物理学与PDEs]第2章第1节 理想流体力学方程组 1.4 一维理想流体力学方程组
- QDir的mkdir和mkpath区别
- 求职信教程大全——10篇文章让你写出优秀的求职信
- 动态规划之多段图(下)
- c#学习笔记之阶乘遇到问题
- ios KVC机制的使用
- winpcap局域网抓包工具http
- MongoDB中级---->关联多表查询