移植tiny210 的lcd驱动
来源:互联网 发布:mac如何截取视频 编辑:程序博客网 时间:2024/06/05 16:52
lcd驱动:
RGB 接口, 写一个lcd驱动,我的建议就是有空必须认认真真的看完 210的lcd 控制器的datasheet。
tiny210的lcd控制器支持很多复杂的功能,比如overlay , color-key等,我们这里不去关心。
一个lcd驱动简单来说就是软件框架和硬件数据传输。
软件框架:
参考fbmem.c 这部分网上资料很多。
硬件数据传输:
参考s5pv210 的lcd 控制器手册:
我们只需要根据 手册配置完相关寄存器实现下图的传输就好了。
附上lcd驱动的代码:
<strong>#include <linux/kernel.h>#include <linux/module.h>#include <linux/platform_device.h>#include <linux/dma-mapping.h>#include <linux/slab.h>#include <linux/init.h>#include <linux/clk.h>#include <linux/fb.h>#include <linux/io.h>#include <linux/uaccess.h>#include <linux/interrupt.h>#include <linux/pm_runtime.h>#include <mach/map.h>#include <plat/regs-fb-v4.h>#include <plat/fb.h>#include <plat/gpio-cfg.h>#include <linux/gpio.h>#include <mach/regs-clock.h>#include <mach/regs-gpio.h>#include <linux/regulator/consumer.h>static u32 pseudo_palette[16];static volatile unsigned int *vidw00add0b0; // Window 2’s buffer start address register, buffer 0. static volatile unsigned int *vidw00add1b0; // window 2’s buffer end address register, buffer 0static volatile unsigned int *vidw00add2; // win dow 2’s buffer size register.static volatile unsigned int *gpd0con; static volatile unsigned int *gpd0dat; static volatile unsigned int *gpf0con; static volatile unsigned int *gpf1con; static volatile unsigned int *gpf2con; static volatile unsigned int *gpf3con; static volatile unsigned int *display_control; static volatile unsigned int *vidosd0a; static volatile unsigned int *vidosd0b; static volatile unsigned int *vidosd0c; static volatile unsigned int *wincon0 ;static volatile unsigned int *vidcon0 ;static volatile unsigned int *vidcon1 ; static volatile unsigned int *vidtcon0 ; static volatile unsigned int *vidtcon1 ; static volatile unsigned int *vidtcon2 ; static volatile unsigned int *shadowcon ; static struct fb_info*s5p_lcd_info;static struct clk *lcd_clk ;static unsigned int chan_to_field(unsigned int chan, struct fb_bitfield *bf){chan &= 0xffff; chan >>= 16 - bf->length; return chan << bf->offset; }static int s3cfb_setcolreg(unsigned int regno, unsigned int red, unsigned int green, unsigned int blue, unsigned int transp, struct fb_info *info){ unsigned int val; printk("neo: s3cfb_setcolreg \n" ); 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 struct fb_ops s5pfb_ops = {.owner = THIS_MODULE,.fb_fillrect = cfb_fillrect,.fb_copyarea = cfb_copyarea,.fb_imageblit = cfb_imageblit,.fb_setcolreg = s3cfb_setcolreg,};static int __init s5p_fb_init(void){/* 分配一个fb_info */s5p_lcd_info = framebuffer_alloc(0, NULL); // size 是指 info 之外的大小/* 设置 fb_info */strcpy(s5p_lcd_info->fix.id, "s5pv210_lcd");s5p_lcd_info->fix.smem_len = 800*480*4;s5p_lcd_info->fix.type = FB_TYPE_PACKED_PIXELS;s5p_lcd_info->fix.visual = FB_VISUAL_TRUECOLOR;s5p_lcd_info->fix.line_length = 800*4;/* var */s5p_lcd_info->var.xres = 800;s5p_lcd_info->var.yres = 480;s5p_lcd_info->var.xres_virtual = 800;s5p_lcd_info->var.yres_virtual = 480;s5p_lcd_info->var.bits_per_pixel = 32;s5p_lcd_info->var.red.offset = 16;s5p_lcd_info->var.red.length = 8;s5p_lcd_info->var.green.offset = 8;s5p_lcd_info->var.green.length = 8;s5p_lcd_info->var.blue.offset = 0;s5p_lcd_info->var.blue.length = 8;s5p_lcd_info->var.activate = FB_ACTIVATE_NOW;s5p_lcd_info->screen_size = 800*480*4;s5p_lcd_info->pseudo_palette = pseudo_palette;s5p_lcd_info->fbops = &s5pfb_ops; /* 使能时钟 */ 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); /* 映射lcd控制器的寄存器 */display_control = ioremap(0xe0107008, 4);gpd0con = ioremap(0xE02000A0, 4);gpd0dat = ioremap(0xE02000A4, 4);gpf0con = ioremap(0xE0200120, 4);gpf1con = ioremap(0xE0200140, 4);gpf2con = ioremap(0xE0200160, 4);gpf3con = ioremap(0xE0200180, 4); vidcon0 = ioremap(0xF8000000, 4); vidcon1 = ioremap(0xF8000004, 4); vidtcon0 = ioremap(0xF8000010, 4); vidtcon1 = ioremap(0xF8000014, 4); vidtcon2 = ioremap(0xF8000018, 4); wincon0 = ioremap(0xF8000020, 4); vidosd0a = ioremap(0xF8000040, 4);vidosd0b = ioremap(0xF8000044, 4);vidosd0c = ioremap(0xF8000048, 4); vidw00add0b0 = ioremap(0xF80000A0, 4);vidw00add1b0 = ioremap(0xF80000D0, 4);shadowcon = ioremap(0xF8000034, 4); /* config gpio */*gpf0con = 0x22222222;*gpf1con = 0x22222222;*gpf2con = 0x22222222;*gpf3con = 0x22222222;/* 打开背光 */*gpd0con &= ~(0xf<<4); *gpd0con |= 1<<4; *gpd0dat |= 1<<1;// 10: RGB=FIMD I80=FIMD ITU=FIMD*display_control = 2<<0;/* lcd 控制器初始化 和 设置 */ // 设置vclk 频率 // 一帧频率设为 65 hz // 那么一个像素的频率为 (65* ( 80 + 36 + 10 + 480 ) *( 22 +15+ 8 + 800)) = 33284550 hz // hclk = 166750000hz vclk = 33284550hz div = 5+1 = 6 *vidcon0 |= (0<<16)|(0<<5)|(1<<4)|(0<<2)|(5<<6);// 设置 时钟 极性 *vidcon1 |= (0<<7)|(1<<6)|(1<<5)|(0<<4); // 设置video timing 即前后左右间距 设置lcd 的分辨率*vidtcon0 |= (0<<24)|(14<<16)|(21<<8)|(7<<0) ; *vidtcon1 |= (0<<24)|(35<<16)|(209<<8)|(9<<0) ;*vidtcon2 |= (799<<0)|(479<<11); *wincon0 &= ~(0xf << 2);*wincon0 |= (1 << 15)|(0xb << 2);// 设置window position(0 0)(799 499)*vidosd0a = (0<<11) |(0<<0);*vidosd0b = (799<<11) |(479<<0);*vidosd0c = 800*480;s5p_lcd_info->screen_base = dma_alloc_writecombine(NULL,PAGE_ALIGN(s5p_lcd_info->fix.smem_len),(dma_addr_t *)&(s5p_lcd_info->fix.smem_start), GFP_KERNEL); // 把 framebuffer 地址告诉lcd 控制器*vidw00add0b0 = (unsigned int)s5p_lcd_info->fix.smem_start; // 放的是物理地址*vidw00add1b0 = (unsigned int)s5p_lcd_info->fix.smem_start + s5p_lcd_info->fix.smem_len;// 打开输出信号总开关 打开window 0 窗口0 *vidcon0 |= (1<<0)|(1<<1); *wincon0 |= (1<<0);*shadowcon |= (1<<0);/* 4. 注册 fb_info */ register_framebuffer(s5p_lcd_info); #if defined(CONFIG_LOGO)if (fb_prepare_logo( s5p_lcd_info, FB_ROTATE_UR)) {printk("Start display and show logo\n");/* Start display and show logo on boot */fb_set_cmap(&s5p_lcd_info->cmap, s5p_lcd_info);fb_show_logo(s5p_lcd_info, FB_ROTATE_UR);}#endifprintk("neo: lcd_init\n");return 0;}static void __exit s5p_fb_cleanup(void){unregister_framebuffer(s5p_lcd_info);dma_free_writecombine(NULL, s5p_lcd_info->fix.smem_len, s5p_lcd_info->screen_base,s5p_lcd_info->fix.smem_start);iounmap(vidw00add0b0);iounmap(vidw00add1b0);iounmap(vidw00add2);iounmap(gpd0con);iounmap(gpd0dat);iounmap(gpf0con);iounmap(gpf1con);iounmap(gpf2con);iounmap(gpf3con);iounmap(display_control);iounmap(vidosd0a);iounmap(vidosd0b);iounmap(vidosd0c); iounmap(shadowcon); iounmap(wincon0); iounmap(vidtcon2); iounmap(vidtcon1); iounmap(vidtcon0); iounmap(vidcon1); iounmap(vidcon0); framebuffer_release(s5p_lcd_info);}module_init(s5p_fb_init);module_exit(s5p_fb_cleanup);MODULE_LICENSE("GPL");</strong>
测试:
1. cat lcd.ko > /dev/fb0 // 花屏
2. 在内核启动时可以看到linux内核自带的小企鹅的图片。
3. 测试程序:
显示英文,中文,宋体汉字,以及图片。
参考韦老师的第一期项目视频。
我写在了另一篇博客里。
0 0
- 移植tiny210 的lcd驱动
- 移植 tiny210 的按键驱动
- 移植tiny210的 触摸屏驱动
- LCD驱动的移植
- SylixOS的LCD驱动移植
- tiny210触摸屏驱动移植问题
- LCD驱动移植笔记
- 移植LCD驱动
- 6410 LCD驱动移植
- 6410 LCD驱动移植
- LCD驱动移植
- LCD 背光驱动移植
- OK6410 LCD驱动移植
- LCD驱动移植
- Wince LCD驱动移植
- wince lcd驱动移植
- s5pv210 LCD驱动移植
- AM1808 LCD驱动移植
- 远程软件升级(http协议)
- combiner操作
- Ubuntu12.04下Android4.0.4源码的下载及其编译过程
- Java NIO 系列教程
- 两元店经典台词
- 移植tiny210 的lcd驱动
- 递归求平均数代码
- 【C语言天天练(十七)】字符/字符串输出函数fputc、fputs、putc、putchar和puts
- GetMemory错误讲解(指针练习)
- TabHost实现底部导航示例
- 仿360悬浮窗,WindowManager的使用(有可运行Demo)
- js验证数字
- 分区表索引实践案例
- 黑马程序员——02几个例子说明equals与"=="的区别