Linux的LCD驱动源码分析及移植
理解LCD屏幕的驱动原理与调试过程,示例的驱动IC为GC9308,展示整个屏幕的驱动过程。

理解LCD屏幕的驱动原理与调试过程,⽰例的驱动IC为GC9308,展⽰整个屏幕的驱动过程。
起因最近拿到了⼀个⽐较新的驱动 IC 的 LCD 了,此前 K210 上⾯使⽤的都是 ST7789V ILI9342C SH1106 这类驱动 IC 的屏幕模块。
这次来了⼀个 GC9308 ,我想我需要认识⼀下屏幕驱动的整体架构,也就是拿起数据⼿册当作学习教材来学了,实际上学完以后,懂了以后都不难,重点在如何总结这些屏幕的驱动逻辑,以此打下往后的屏幕驱动理解基础。
我需要读懂图像的⼆进制定义、还有传输⽅式,我找了⼀本中⽂的屏幕数据⼿册来读,了解⼀下相关的流程和细节本⽂我只会交待软件层⾯的理解,硬件⽅⾯的定义和特性我⽆法给出准确的解释,姑不会提及。
屏幕的发展历程让我们看⼀下这个⼤哥的故事,就很好的说明了这段 LCD MCU 发展的历史。
记得在很早的时候,那时候还都是FSTN的显⽰屏满天飞的时候(也是⼩弟刚刚毕业开始作⼿机的时候)。
LCD的驱动电路有很多是两⽚芯⽚的,⼀⽚LCDC,⼀⽚LCD Driver,⼀般的LCDC⾥⾯有⼀个display的buffer。
LCDDriver是电路驱动液晶显⽰部分的电路,没有什么好讲的。
更早的时候,LCD上就⼀⽚LCDDriver就⾏了,程序员需要控制两个(H,V)场扫描信号,⽽且程序员希望在某个坐标显⽰,都需要编程控制驱动电路来实现,后来发现显⽰屏越来越⼤,⽽MCU以及程序员没有这个能⼒和精⼒来对LCD进⾏这类的同步控制,于是LCDC就诞⽣出来承担起这些个功能。
后来加上了buffer,就是说程序员可以把⼤批的显⽰内容以显⽰矩阵(display matrix)的形式写到buffer⾥,让LCDC来读取buffer⾥的数据再由LCDDriver显⽰到显⽰屏上。
后来这个buffer越来越⼤,除了显⽰矩阵以外还放很多命令,所以也不能⽼把它笼统的叫buffer啊,所以就对放显⽰矩阵的存储空间有了⼀个专⽤的名字叫做GRAM。
LCD12864驱动源代码

Transfer_command(0xa0); /*列扫描顺序:从左到右*/
Transfer_command(0xaf); /*开显示*/
clear_screen();
}
//===============clear all dot martrics=============
Transfer_command(((column>>4)&0x0f)+0x10); //设置列地址的高4 位
Transfer_command(column&0x0f); //设置列地址的低4 位
}
/*=========延时=====================*/
void Delay(int i)
{
char i;
CS_0(); //CS_PIN=0
RS_0(); //CS_PIN=0
for(i=0;i<8;i++)
{
SCLK_0();
if(data1&0x80) DIN_1();
else DIN_0();
SCLK_1();
data1=data1<<=1;
void Initial_Lcd()
{
RST_0(); //reset=0
P2DIR |=RST_PIN | SPI_MOSI_PIN| SPI_CLK_PIN|RS_PIN|CS_PIN ;
Delay(50);
RST_1(); //reset=1
Delay(50);
{
CS_0(); //CS_PIN=0
DM9000驱动移植详解及问题点

OK6410、2.6.36内核移植,dm9000 驱动移植,详细!分类:嵌入式学习Linux学习2012-04-27 00:54 3004人阅读评论(7) 收藏举报interfaceccompressionresourcesstructtable还是先来吐槽:本来我是在上一个星期的周末已经把Linux2.6.34.11 的驱动已经成功的移植到,OK6410 的开发板上的,并且能够启动主机上的NFS 根文件系统,可是我在周一的时候,开始学习LCD 的驱动程序,在修改内核文件的时候,有几处错误修改,将原来自己做的2.6.34.11 的内核源码搞的乱七八糟的,在这里还是自己在修改内核的时候没有提注重注释,并且没有记录下来自己的操作步骤,以至于我没办法,恢复2.6.34 的内核,所以也就只能重新先开始最基础的内核移植了。
这次我选择的是2.6.36.2 的内核,谁知到一开始移植就出现一大堆问题。
在这里我不得不说,飞凌开发人员对内核修改的代码,管理真的是太扯了,自己在注销任何一个设备是没有一点点注释,就把这个设备原有的线性地址分配给其它设备了,让我让我们这些菜鸟干看着一大堆的报错信息顶个什么用,真的是伤不起。
好了不乱扯了,现在开始记录。
我的开发环境是:VMware Ubuntu 10.10 。
OK6410 A版256M+2G 的开发板。
主机系统:XP。
Uboot:飞凌提供的Uboot。
参考内核:飞凌提供的Forlinx 的2.6.36.2 内核操作步骤以下./ 均代表你的内核根目录1、修改./Makefile191 ARCH ?=arm // 指定cpu类型,arm后面不要有空格,要不然编译是会提醒ARCH 不能为一个目录192 CROSS_COMPILE ?=/usr/local/arm/4.2.2-eabi/usr/bin/arm-linux- // 指定交叉编译器的路径,按照你自己的进行指定路径2、先来说说nand flash 的驱动涉及到的文件:MTD 通用nand flash 驱动程序位置:./drivers/mtd/nand/.nand_base.cNAND Flash 的platform 设备信息: ./drivers/mtd/nand/s3c_nand.c有了上面的依赖驱动依赖程序、接下来修改./arch/arm/mach-s3c64xx/mach-smdk6410.c 1) nandflash 驱动,修改方法加载头文件[cpp]view plaincopyprint?1.#include <linux/mtd/mtd.h>2.#include <linux/mtd/partitions.h>3.#include <plat/nand.h> //这些头文件放在./arch/arm/plat-samsung/include/ 下面添加nand 结构体[cpp]view plaincopyprint?1.// add by acanoe first2.extern void s3c64xx_reserve_bootmem(void); //add by acanoe3.4.5.struct mtd_partition ok6410_nand_part[] = {6. {7. .name = "Bootloader",8. .offset = 0,9. .size = (1 * SZ_1M),10. .mask_flags = MTD_CAP_NANDFLASH,11. },12. {13. .name = "Kernel",14. .offset = (1 * SZ_1M),15. .size = (5*SZ_1M) ,16. .mask_flags = MTD_CAP_NANDFLASH,17. },18. {19. .name = "User",20. .offset = (6 * SZ_1M),21. .size = (120*SZ_1M) ,22. },23. {24. .name = "File System",25. .offset = MTDPART_OFS_APPEND,26. .size = MTDPART_SIZ_FULL,27. }28.};29.30.31.static struct s3c2410_nand_set ok6410_nand_sets[] = {32. [0] = {33. .name = "nand",34. .nr_chips = 1,35. .nr_partitions = ARRAY_SIZE(ok6410_nand_part),36. .partitions = ok6410_nand_part,37. },38.};39.40.41.static struct s3c2410_platform_nand ok6410_nand_info = {42. .tacls = 25,43. .twrph0 = 55,44. .twrph1 = 40,45. .nr_sets = ARRAY_SIZE(ok6410_nand_sets),46. .sets = ok6410_nand_sets,47.};48.//add by acanoe first修改 smdk6410_devices[] __initdata = {对照这个结构体将那些进行修改,注意 by acanoe 的语句为修改重点。
MTK详解LCD移植

详解LCD移植1.Make文件设置设置LCDLCD_MODULE = BROADMOBI68_09B_LCM //这个名字可以自己取,但是//这个名字要和\custom\drv\LCD\下的文件夹一致。
//一般可以不用改。
到时直接修改这个文件夹下的代码就行了。
# Based on the LCM solutions (even multiple LCM modules for this project) # SHOULD BE ONE OF THE FOLLOWINGS, based on the LCM# MTKLCM - Mono, 102x64# MTKLCM_COLOR - Color, 120x160, for MT6218_MW001 or MT6205_CEVB# ORDNANCELCM - Mono, 112x64# KLMLCM - Color, 128x128# INFOLCM - Color, 128x128# TOPPOLY_LCM - Color, 128x160, for MT6218B_EVB# SONY_LCMMAIN_LCD_SIZE = 320X480 //查LCD datasheet可以查到分辨率。
# To distinguish the main lcd size.# We can use it to copy the matching resources, such themecomponents.h, Fontres.c, L_xxx.h, etc, to PLUTO_MMI folderSUB_LCD_SIZE = NONE# NONE, 48X64BW, 64X96, 96X64BW, 96X64, 128X128COM_DEFS_FOR_BROADMOBI68_09B_LCM = BROADMOBI68_09B_LCM TFT_MAINLCD //如果//上面的LCD_MOULE设置改了,这个就要跟着该。
LCD驱动代码

1. 驱动代码#include<linux/module.h>#include<linux/kernel.h>#include<linux/fs.h>#include<linux/init.h>#include<linux/delay.h>#include<asm/uaccess.h>#include<asm/irq.h>#include<asm/io.h>#include<linux/device.h>#define DEV_NAME "cdev_leds"#define rGPBCON (*(volatile unsigned *)(base_addr+0))#define rGPBDAT (*(volatile unsigned *)(base_addr+1))#define rGPBUP (*(volatile unsigned *)(base_addr+2))struct class *char_dev_class;static struct class_device *p_class_devs;int major=0;struct file *filp;unsigned int *base_addr=0;#define DEV_SIZE (4)int first_chardev_open(struct inode *inode,struct file *file){printk(KERN_EMERG"open() call\r\n");return 0;}ssize_t first_chardev_read(struct file *file,char __user *buf,ssize_t count,loff_t *f_pos){int retval=0;char led_buffer[DEV_SIZE]={2,2,2,2};printk(KERN_EMERG"read() call\n");led_buffer[0]=!(rGPBDAT&(1<<5));led_buffer[1]=!(rGPBDAT&(1<<6));led_buffer[2]=!(rGPBDAT&(1<<7));led_buffer[3]=!(rGPBDAT&(1<<8));if(*f_pos>=DEV_SIZE)goto out;if(*f_pos+count>DEV_SIZE)count=DEV_SIZE-*f_pos;if(copy_to_user(buf,&led_buffer[0+*f_pos],count)){retval=-EFAULT;goto out;}*f_pos+=count;retval=count;return retval;out:return 0;}ssize_t first_chardev_write(struct file *file,const char __user *buf,size_t count,loff_t *f_pos){char led_buffer[DEV_SIZE]={3,3,3,3};int retval=0;int i=0;printk(KERN_EMERG"write() call\n");if(*f_pos>=DEV_SIZE)goto out;if(*f_pos+count>DEV_SIZE)count=DEV_SIZE-*f_pos;if(copy_from_user((void *)led_buffer[*f_pos],(const void __user *)buf,count)){retval=-EFAULT;goto out;}for(i=0;i<count;i++){if(led_buffer[*f_pos+i]==1)rGPBDAT&=~(1<<(5+*f_pos+i));else if(led_buffer[*f_pos]==0)rGPBDAT|=(1<<(5+*f_pos+i));else{printk("value err!\r\n");goto out;}}*f_pos+=count;retval=count;out:return retval;}int first_chardev_ioctl(struct inode *inode,struct file *file,unsigned int cmd,unsigned long arg){printk(KERN_EMERG"ioctrl() call\n");return 0;}int first_chardev_release(struct inode *inode,struct file *file) {printk(KERN_EMERG"release call\n");return 0;}loff_t first_chardev_llseek(struct file *file,loff_t off,int whence) {loff_t newpos=0;int offset=off;printk(KERN_EMERG"llseek call\n");printk(KERN_EMERG"offset:%d;whence:%d\r\n",offset,whence);switch(whence){case SEEK_SET:newpos=offset;printk(KERN_EMERG"SEEK_SET:newpos:%d\n",newpos);break;case SEEK_CUR:newpos=filp->f_pos+offset;printk(KERN_EMERG"SEEK_CUR:newpos:%d\n",newpos);break;case SEEK_END:newpos=4+offset;printk(KERN_EMERG"SEEK_END:newpos:%d\n",newpos);break;default:return -EINVAL;}if(newpos<0)return -EINVAL;filp->f_pos=newpos;return newpos;}static struct file_operations first_chardev_fops={.owner=THIS_MODULE,.open=first_chardev_open,.release=first_chardev_release,.read=first_chardev_read,.write=first_chardev_write,.llseek=first_chardev_llseek,.ioctl=first_chardev_ioctl,};static int __init s3c24xx_leds_init(void){printk(KERN_EMERG"module init mow!\n");base_addr=(unsigned int *)ioremap(0x56000010,16);rGPBCON&=~(3<<10|3<<12|3<<14|3<<16);rGPBCON|=(3<<10|3<<12|3<14|3<<16);rGPBUP&=~(1<<5|1<<6|1<<7|1<<8);rGPBDAT&=~(1<<5|1<<6|1<<7|1<<8);rGPBDAT|=(1<<5|1<<6|1<<7|1<<8);major=register_chrdev(major,DEV_NAME,&first_chardev_fops);printk(KERN_EMERG"major:%d\n",major);char_dev_class=class_create(THIS_MODULE,"myleds");if(IS_ERR(char_dev_class)){printk("Err,failed in creating class.\n");return 0;}p_class_devs=device_create(char_dev_class,NULL,MKDEV(major,0), NULL,DEV_NAME);printk(DEV_NAME"initialized\n");return 0;}static void __exit s3c24xx_leds_exit(void){unregister_chrdev(major,DEV_NAME);//device_unregister(p_class_devs);device_destroy(char_dev_class,MKDEV(major,0));class_destroy(char_dev_class);iounmap(base_addr);}module_init(s3c24xx_leds_init);module_exit(s3c24xx_leds_exit);MODULE_AUTHOR("XYD");MODULE_VERSION("1.0");MODULE_DESCRIPTION("S3C2440 LED Driver");MODULE_LICENSE("GPL");2.Makefile代码obj-m:=005th_led_cdev.oKDIR:=/lib/modules/$(shell uname -r)/buildall:make -C $(KDIR) M=$(PWD) modules#cp 005th_led_cdev.ko 005th_led_cdev_test/opt/s3c2440/root_nfs/home/#rm -rf *.o *.mod.o *.symvers .*.o *.cmd modules.order *.bak.tmp_versionsclean:make -C $(KDIR) M=$(PWD) cleanrm -rf *.ko *.o *.mod.o *.mod.c *.symvers .*.o *.cmd modules.order *.bak,tmp_versions *~ *.markers3.测试代码#include<stdio.h>#include<stdlib.h>#include<sys/types.h>#include<sys/stat.h>#include<fcntl.h>#include<sys/ioctl.h>#define DEV_NAME "/dev/cdev_leds"int main(int argc,char *argv[]){int fd=0;int ret=0;int i=0;int pos=0;unsigned char recv_buf[10]={2,2,2,2};unsigned char send_buf[10]={0,1,0,1};fd=open(DEV_NAME,O_RDWR);if(fd<0){printf(DEV_NAME"can not open devce!\n");prrror("open:");exit(0);}for(i=0;i<4;i++){ret=write(fd,&send_buf[i],1);printf("ret: %d\n",ret);sleep(1);}pos=lseek(fd,1,SEEK_SET);printf("ret:%d\n",ret);sleep(1);ret=read(fd,&recv_buf[pos],4-pos);printf("%d;%d;%d;%d\n",recv_buf[0],recv_buf[1],recv_buf[2],recv_buf[3]);if(recv_buf[0]==0)printf("led0 off\n");else if(recv_buf[0]==1)printf("led0 on\n");elseprintf("led0 status unnowke\n");if(recv_buf[1]==0)printf("led1 off\n");else if(recv_buf[1]==1)printf("led1 on\n");elseprintf("led1 status unnowke\n");if(recv_buf[2]==0)printf("led2 off\n");else if(recv_buf[2]==1)printf("led2 on\n");elseprintf("led2 status unnowke\n");if(recv_buf[3]==0)printf("led3 off\n");else if(recv_buf[3]==1)printf("led3 on\n");elseprintf("led3 status unnowke\n");sleep(1);ret=lseek(fd,SEEK_CUR);printf("ret:%d\n",ret);sleep(1);ret=lseek(fd,SEEK_END);printf("ret:%d\n",ret);sleep(1);return 0;}。
Linux2.6内核移植系列教程

Linux2.6内核移植系列教程第一:Linux 2.6内核在S3C2440平台上移植此教程适合2.6.38之前的版本,其中2.6.35之前使用同一yaffs补丁包,2.6.36--2.6.28 yaffs文件系统有所改变,2.6.39之后的暂时不支持,源码下载请到:/1.解压linux-2.6.34.tar.bz2源码包#tar jxvf linux-2.6.34.tar.bz22.修改linux-2.6.34/Makefile文件,在makefile中找到以下两条信息并做修改ARCH ? =armCROSS_COMPILE?=/usr/local/arm/4.3.2/bin/arm-linux-注意:交叉编译器的环境变量也需要改为4.3.2#export PATH=/usr/local/arm/4.3.2/bin/:$PATH其中ARCH变量用来决定:配置、编译时读取Linux源码arch目录下哪个体系结构的文件PATH 用来决定交叉编译器版本3.修改机器类型ID号Linux源码中支持多种平台的配置信息,内核会根据bootloader传进来的mach-types决定那份平台的代码起作用,本人手里的板子是仿照三星公司官方给出的demo板改版而来,所以采用arch/arm/mach-s3c2440/mach-smdk2440.c此配置文件,打开此文件,翻到最后,有以下信息:MACHINE_START(S3C2440, "SMDK2440")/* Maintainer: Ben Dooks <ben@> */.phys_io= S3C2410_PA_UART,.io_pg_offst= (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,.boot_params= S3C2410_SDRAM_PA + 0x100,.init_irq= s3c24xx_init_irq,.map_io= smdk2440_map_io,.init_machine= smdk2440_machine_init,.timer= &s3c24xx_timer,MACHINE_ENDMACHINE_START(S3C2440, "SMDK2440")决定了此板子的mach-types,可以在以下文件中找到S3C2440对应的具体数字,"arch/arm/tools/mach-types"文件查找S3C2440,362,这里刚好与我们的bootloader相同,所以不用做修改,直接保存退出即可,如果不同则根据bootloader的内容修改此文件,或根据此文件修改boorloader的内容(在vivi中可通过param show查看,u-boot在Y:\test\u-boot_src\u-boot_edu-2010.06\board\samsung\unsp2440\unsp2440.c文件:gd->bd->bi_arch_number = MACH_TYPE_S3C2440;中决定)。
文档:、linux-308内核I2C触摸屏移植

Linux3.0.8平台搭建移植文档——I2C触摸屏移植1.I2C子系统goodix电容屏采用I2C接口与处理器连接,我们要首先确保linux内核拥有对I2C子系统的支持,下面我们从子系统的配置和电容屏驱动两个方面进行移植修改1)配置I2C子系统支持#make menuconfigDevice Drivers ---><*> I2C support --->[*] Enable compatibility bits for old user-space (NEW)<*> I2C device interface< > I2C bus multiplexing support (NEW)[*] Autoselect pertinent helper modules (NEW)I2C Hardware Bus support --->进入I2C Hardware Bus support选项,选中以下内容:*** I2C system bus drivers (mostly embedded / system-on-chip) ***< > Synopsys DesignWare (NEW)<*> GPIO-based bitbanging I2C< > OpenCores I2C Controller (NEW)< > PCA9564/PCA9665 as platform device (NEW)<*> S3C2410 I2C Driver< > Simtec Generic I2C interface (NEW)...2.GOODIX电容屏移植1)添加goodix电容屏驱动将“goodix_touch.c”文件copy到drivers/input/touchscreen/目录下,并将"goodix_touch.h"、"goodix_queue.h"文件copy到include/linux/目录下,并修改Kconfig文件及Makefile文件支持触摸屏驱动的配置和编译#vi driver/input/touchscreen/Kconfig在config TOUCHSCREEN_TPS6507X选项的后面添加以下内容:config TOUCHSCREEN_GOODIXtristate "GOODIX based touchscreen"depends on I2ChelpIt is a android driver to support Gooidx's touchscreen whose nameis guitar on s5pv210 platform. The touchscreen can support multi-touch not more than two fingers.Say Y here to enable the driver for the touchscreen on theS5V SMDK board.If unsure, say N.To compile this driver as a module, choose M here:the module will be called goodix_touch.ko.#vi driver/input/touchscreen/Makefile在文件最后添加如下内容:obj-$(CONFIG_TOUCHSCREEN_GOODIX) += goodix_touch.o2)添加i2c_board_info资源(电容屏)#vi arch/arm/mach-s5pv210/mach-smdkv210.c在smdkv210_i2c_devs0结构体数组定义中添加以下内容:...{ I2C_BOARD_INFO("24c08", 0x50), }, /* Samsung S524AD0XD1 */ { I2C_BOARD_INFO("wm8580", 0x1b), },{I2C_BOARD_INFO("Goodix-TS", 0x55),.irq = IRQ_EINT(4),},...3)配置电容屏选项#make menuconfigDevice Drivers --->Input device support --->...[*] Touchscreens ---><*> GOODIX based touchscreen4)make将在arch/arm/boot/下生成编译好的可执行程序zImage下载到开发板即可,执行命令“cat /dev/input/event0”,然后用手触摸屏幕会在终端看到输出打印的乱码信息,表示移植成功,如果没有打印信息或没有“/dev/input/event0”这个设备说明移植失败。
lcd驱动分析文档

嵌入式linux中的lcd驅動分析作者:傑洲村的木棉學校:廣東工業大學QQ:568109894在嵌入式linux中,lcd和觸控式螢幕驅動都是字元驅動,採用“檔層-驅動層”的介面方式,本文檔中分析的lcd驅動是針對linux2.6.13內核的,本人用的開發板是qq2440,lcd是三星的LTV3500V(帶觸控式螢幕的),具體分析的文件:是"include/linux/fb.h","drivers/video/s3c2410fb.h","drivers/video/s3c2410fb.c","drivers/video/fbmem.c","/include/asm/arch- s3c2410.fb.h(些標頭檔是針對s3c2440或s3c2410晶片的)",“/home/linux/5/kernel-2.6.13/arch/arm/mach-s3c2410/mach-smdk2410.c"(驅動移植主要就是要修改這個檔,配置一些參數)。
詳細看一下LCD的驅動,實際上,幾乎lcd設備驅動所要做的所有事情就是填充fb_info結構然後向系統註冊或登出它(1)fb.h包含了framebuffer所用到的結構(2)fbmem.c處於Framebuffer設備驅動技術的中心位置.它為上層應用程式提供系統調用也為下一層的特定硬體驅動提供介面;那些底層硬體驅動需要用到這兒的介面來向系統內核註冊它們自己. fbmem.c 為所有支援FrameBuffer的設備驅動提供了通用的介面,避免重復工作.(3)s3c2410fb.c就是特定硬體驅動(針對s3c2410晶片的),fbmem.c就是溝通應用層跟s3c2410fb.c的橋樑FrameBuffer設備驅動基於如下幾個檔:1)include/linux/fb.h2)drivers/video/fbmem.c3)drivers/video/s3c2410fb.c4)drivers/video/s3c2410fb.h5)include/asm/arch-s3c2410/fb.h現在先來分析這兩個檔:1.fb.h 包含了framebuffer 所用到的結構1)fb_fix_screeninfo 描述顯示卡的屬性,並且系統運行時不能被修改 structfb_fix_screeninfo {char id[16];unsigned long smem_start;/* identification string eg "TT Builtin" */ /* Start of frame buffer mem *//* (physical address) */__u32 smem_len;/* Length of frame buffer mem */__u32 type;__u32 type_aux;/* see FB_TYPE_* *//* Interleave for interleaved Planes */__u32 visual;/* see FB_VISUAL_* */ __u16 xpanstep;/* zero if no hardware panning */__u16 ypanstep;__u16 ywrapstep; __u32 line_length;/* zero if no hardware panning */ /* zero if no hardware ywrap */ /* length of a line in bytes */unsigned long mmio_start;/* Start of Memory Mapped I/O *//* (physical address) */__u32 mmio_len; __u32 accel;/* Length of Memory Mapped I/O *//* Indicate to driver which */ /* specific chip/card we have */};__u16 reserved[3];/* Reserved for future compatibility */2)fb_var_screeninfo 這個結構描述了顯示卡的特性struct fb_var_screeninfo {__u32 xres;__u32 yres;__u32 xres_virtual;/* visible resolution/* virtual resolution*/*/__u32 yres_virtual;__u32 xoffset; /* offset from virtual to visible */ __u32 yoffset;/* resolution*/__u32 bits_per_pixel; __u32 grayscale;/* guess what/* != 0 Graylevels instead of colors */*/struct fb_bitfield red; /* bitfield in fb mem if true color, */struct fb_bitfield green; /* else only length is significant */struct fb_bitfield blue;struct fb_bitfield transp; /* transparency */__u32 nonstd; /* != 0 Non standard pixel format */ __u32 activate;/* see FB_ACTIVATE_**/__u32 height; __u32 width;/* height of picture in mm/* width of picture in mm*/*/__u32 accel_flags; /* (OBSOLETE) see fb_info.flags *//* Timing: All values in pixclocks, except pixclock (of course) */__u32 pixclock; /* pixel clock in ps (pico seconds) */__u32 left_margin; /* time from sync to picture */__u32 right_margin; /* time from picture to sync */__u32 upper_margin; /* time from sync to picture */__u32 lower_margin;__u32 hsync_len; /* length of horizontal sync */__u32 vsync_len; /* length of vertical sync*/__u32 sync; /* see FB_SYNC_* */__u32 vmode; /* see FB_VMODE_* */__u32 rotate; /* angle we rotate counter clockwise */__u32 reserved[5]; /* Reserved for future compatibility */};3)fb_cmap描述設備無關的顏色映射資訊。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
Linux的LCD驱动源码分析及移植(三部曲)第一部分:基于ARM9处理器的linux-2.6.32.2操作系统内核移植手记part5.1(LCD驱动源码分析及移植之platform device)1.与LCD控制器硬件相关的寄存器内容请参照三星S3C2440A技术手册中的第15章。
2. LCD Controller的平台设备定义如下(文件位于linux/arch/arm/plat-s3c24xx/devs.c):1./* LCD Controller */2.3.static struct resource s3c_lcd_resource[] = {4. [0] = {5. .start = S3C24XX_PA_LCD,6. .end = S3C24XX_PA_LCD + S3C24XX_SZ_LCD - 1,7. .flags = IORESOURCE_MEM,8. },9. [1] = {10. .start = IRQ_LCD,11. .end = IRQ_LCD,12. .flags = IORESOURCE_IRQ,13. }14.15.};16.17.static u64 s3c_device_lcd_dmamask = 0xffffffffUL;18.19.struct platform_device s3c_device_lcd = {20. .name = "s3c2410-lcd",21. .id = -1,22. .num_resources = ARRAY_SIZE(s3c_lcd_resource),23. .resource = s3c_lcd_resource,24. .dev = {25. .dma_mask = &s3c_device_lcd_dmamask,26. .coherent_dma_mask = 0xffffffffUL27. }28.};29.30.EXPORT_SYMBOL(s3c_device_lcd);平台设备的结构体定义为s3c_device_lcd,该设备在平台总线中的名字取为s3c2410-lcd,该平台设备申请的两个板级资源为以S3C24XX_PA_LCD为起始的IORESOURCE_MEM资源和一个定义为IRQ_LCD的IORESOURCE_IRQ资源。
其中,1.#define S3C24XX_PA_LCD S3C2410_PA_LCD1./* LCD controller */2.#define S3C2410_PA_LCD (0x4D000000)3.#define S3C24XX_SZ_LCD SZ_1M0x4D000000为LCDCON1寄存器的地址。
3. LCD Controller的平台设备的注册如下(文件位于linux/arch/arm/mach-s3c2440/mach-smdk24 40.c):1.static struct platform_device *smdk2440_devices[] __initdata = {2. &s3c_device_usb,3.4. &s3c_device_lcd,5.6. &s3c_device_wdt,7. &s3c_device_i2c0,8. &s3c_device_iis,9. &s3c_device_rtc,10.};以上第4行代码将lcd平台设备注册进内核。
4.在系统初始化时将smdk2440_fb_info结构体添加进平台设备的私有结构中。
具体流程如下:4.11.MACHINE_START(S3C2440, "SMDK2440")2. /* Maintainer: Ben Dooks <ben@> */3. .phys_io = S3C2410_PA_UART,4. .io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,5. .boot_params = S3C2410_SDRAM_PA + 0x100,6.7. .init_irq = s3c24xx_init_irq,8. .map_io = smdk2440_map_io,9. .init_machine = smdk2440_machine_init,10. .timer = &s3c24xx_timer,11.MACHINE_END启动S3C2440机器,系统将通过“.init_machine = smdk2440_machine_init,”调用smdk2440_machine_init()函数。
4.21.static void __init smdk2440_machine_init(void)2.{3. s3c24xx_fb_set_platdata(&smdk2440_fb_info);4. s3c_i2c0_set_platdata(NULL);5.6. platform_add_devices(smdk2440_devices, ARRAY_SIZE(smdk2440_devices));7. smdk_machine_init();8.}在 smdk2440_machine_init函数中,通过“s3c24xx_fb_set_platdata(&smdk2440_fb_info);”将smdk2440_fb_info添加进平台设备的私有结构中。
4.31.void __init s3c24xx_fb_set_platdata(struct s3c2410fb_mach_info *pd)2.{3. struct s3c2410fb_mach_info *npd;4.5. npd = kmalloc(sizeof(*npd), GFP_KERNEL);6.if(npd){7. memcpy(npd, pd, sizeof(*npd));8. s3c_device_lcd.dev.platform_data = npd;9.}else{10. printk(KERN_ERR "no memory for LCD platform data\n");11.}12.}以上代码为smdk2440_fb_info结构的添加过程,其中“s3c_device_lcd.dev.platform_data = npd;”为核心实现部分。
4.41.static struct s3c2410fb_mach_info smdk2440_fb_info __initdata ={2..displays =&smdk2440_lcd_cfg,3..num_displays = 1,4..default_display = 0,5.6.#if 07./* currently setup by downloader */8..gpccon = 0xaa940659,9..gpccon_mask = 0xffffffff,10..gpcup = 0x0000ffff,11..gpcup_mask = 0xffffffff,12..gpdcon = 0xaa84aaa0,13..gpdcon_mask = 0xffffffff,14..gpdup = 0x0000faff,15..gpdup_mask = 0xffffffff,16.#endif17.18.//.lpcsel =((0xCE6)&~7)| 1<<4,19.};以上为smdk2440_fb_info结构体定义。
在此需要注释掉源码中的“.lpcsel = ((0xCE6) & ~7) | 1<<4”!本结构中的关键为“ .displays = &smdk2440_lcd_cfg,”,即LCD的硬件参数,需要根据具体的LCD屏幕来确定,小生使用的是天嵌3.5寸屏幕,所以该结构体的赋值如下:4.51.static struct s3c2410fb_display smdk2440_lcd_cfg __initdata = {2.3. .lcdcon5 = S3C2410_LCDCON5_FRM565 |4. S3C2410_LCDCON5_INVVLINE |5. S3C2410_LCDCON5_INVVFRAME |6. S3C2410_LCDCON5_PWREN |7. S3C2410_LCDCON5_HWSWP,8.9. .type = S3C2410_LCDCON1_TFT,10.11. .width = 320,12. .height = 240,13.14. .pixclock = 80000, /* HCLK 100 MHz, divisor 3 */15. .xres = 320,16. .yres = 240,17. .bpp = 16,18.19. .setclkval = 0x3,20. .left_margin = 28, /* for HFPD*/21. .right_margin = 24, /* for HBPD*/22. .hsync_len = 42, /* for HSPW*/23. .upper_margin = 6, /* for VFPD*/24. .lower_margin = 2, /* for VBPD*/25. .vsync_len = 12, /* for VSPW*/26.27.};以上位LCD屏幕硬件参数。
注:a.本文旨在将与友善之臂开发板配套的的linux-2.6.32.2内核移植到天嵌科技的TQ2440开发板上。
b. 硬件平台:天嵌科技TQ2440开发板(标配)c. 软件平台:linux-2.6.32.2内核源码第二部分:基于ARM9处理器的linux-2.6.32.2操作系统内核移植手记part5.2(LCD驱动源码分析及移植之platform driver)5.LCD驱动模块的注册与注销:注册与注销模块由module_init宏与module_exit宏指定。
6.LCD平台设备驱动s3c2410fb_driver。
该结构定义了LCD驱动程序的名字:"s3c2410-lcd",以及探测函数probe,移除函数remove,电源挂起函数suspend和电源恢复函数resume。
由此可见,真正的探测函数为s3c24xxfb_probe。
第一行用于获取platform device中定义的平台数据(已经在本博客的上一篇文章中提及)。