前面几篇文章现现已过装备DTS的方法完结了多个驱动的移植,接下来咱们处理TQ335x的接触驱动问题。由于种种原因,TQ335x的接触屏驱动是以模块方法供给的,且Linux官方内核中也没有带该接触屏的驱动源码,单纯的装备DTS是无法完结TQ335x的接触驱动移植作业的,因而,本文参阅内核华夏有的pixcir_i2c_ts驱动编写TQ335x的接触屏(TN92)驱动。
在之前移植TQ210时,我现已编写过TQ210的接触屏驱动,我的TQ335x仍是运用的TQ210的屏,因而,难度不是很大。这儿需求阐明一点,在TQ210驱动移植时对多点接触协议的了解还不行深化,其时编写的驱动单点接触是能够正常运用的,可是多点接触不对(这次编写TQ335x的接触驱动是才意识到的)。可是编写的TQ210驱动多点接触实际上运用的多点接触的A协议,可是用错了一些当地,本文根据TQ335x的从头编写的接触驱动是依照多点接触B协议编写,运用tslib测验正常,文章结尾有用果图。
TN92接触屏运用的触控芯片是GT811,下面咱们来剖析下接触屏驱动的编写。
(1) 查看原理图
从接触屏原理图中能够看到,GT811与开发板相连的引脚有四条,分别是SDA、SDL、INT和RESET。其间,I2C_SDA和I2C_SDL是衔接到AM335x的I2C1端口上的,用来与SoC通讯;INT引脚是衔接在GPIO1的27号引脚上的,在检测到接触时GT811通过该引脚向SoC建议中止请求;RESET引脚接到SoC的GPIO1的26号引脚上的,是用来接纳SoC复位操作,关于本文,SoC便是AM335x。
其间,GT811与SoC的管脚衔接信息能够从底板原理图中找到,SDA和SCL的我就不往外贴了,INT和RESET的衔接联系如下:
YP衔接到了GT811的RESET脚上,然后通过短路帽与GPIO1_26链接,YM衔接到GT811的INT脚上,通过短路帽与GPIO1_27链接,因而,需求将GPIO1_27装备为终端输入引脚,GPIO1_26装备为输出引脚。此外,查看GT811的芯片手册可获得INT和RESET的操作信息:
- 1.GT811检测到接触时会拉低中止引脚,因而,GPIO1_27需求装备为下降沿触发。
- 2.GT811的RESET脚为低电平有用,因而,上电时需求拉低RESET引脚。
- 3.GT811的RESET引脚自带上拉,因而,运用GPIO1_26将GT811的RESET拉低复位后切换为悬浮输入太即可。
了解这些信息后咱们就能够开端剖析驱动结构了。
(2) DTS装备Platform信息
通过前面的剖析,咱们知道需求装备AM335x的四条引脚才能使GT811正常作业。其间,GT811通过I2C接口衔接到AM335x的I2C1上,因而,需求装备AM335x的I2C1的两条引脚为I2C功用;GPIO1_27需求装备为中止输入、下降沿触发,中止号也能够确认下来了,便是GPIO1的27号角(内核能将引脚转换为中止号);最终便是RESET脚,驱动初始化GT811时需求操作RESET引脚,且GT811为拉低复位,故可将GPIO1的26角设为输出电平状况。通过前面几篇文章的学习,咱们知道DTS能够装备pinmux,然后剖析内核自带的DTS文件能够,DTS也能够将衔接信息传递给内核。通过剖析及参阅,我最TQ335x.dts文件做了如下修正:
Step1. 查看I2C引脚的pinmux装备
查找i2c1能够找到i2c1节点,该节点的pinctrl-0只想的phandler对i2c1的两个引脚进行了相关的装备,因而,不需任何修正。
Step2. 装备INT和RESET引脚
在am33xx_pinmux节点内增加引脚装备信息,详细内容如下:
- gt811_ts_pins:gt811_ts_pins{
- pinctrl-single,pins=<
- 0x68(PIN_INPUT_PULLUP|MUX_MODE7)
- 0x6c(PIN_INPUT_PULLUP|MUX_MODE7)
- >;
- };
Step3. 在i2c1节点内增加GT811设备信息
GT811的设备节点内需求供给以下信息,i2c设备地址、pinmux装备、中止信息、屏幕巨细等,详细如下(这儿就不细说了,有什么不清楚的能够留言评论)。
- gt811_ts@5d{
- compatible=”gt811,gt811_ts”;
- pinctrl-names=”default”;
- pinctrl-0=<>811_ts_pins>;
- reg=<0x5d>;
- interrupt-parent=<&gpio1>;
- interrupts=<272>;
- gpios=<&gpio1260>;
- touchscreen-size-x=<800>;
- touchscreen-size-y=<480>;
- touchscreen-swap=<1>;
- touchscreen-revert-x=<1>;
- touchscreen-revert-y=<1>;
- };
至此,DTS的装备作业就完结了,下面便是GT811的驱动编写。
(3)驱动编写
驱动编写根之前TQ210比较,没有多少改变,都是选用的新式I2C设备驱动架构,重要的差异在于支撑了多点接触,驱动的详细剖析我就不多说了,详细能够参阅韦东山教师的视频教程(肯定物有所值)。下面是GT811的多点接触驱动源码。从GT811设备节点中获取坐标信息的部分我直接贴出来了,完好的代码仍是请到资源里下载,仍是有点贵哈,不过这个驱动能够直接拿去运用了,不需求任何修正。下面是不完好的代码,能够打印出接触点坐标,该代码现已把本驱动的中心的部分都写出来了。其实许多朋友不需求下载源码就能够弥补完善这个驱动了,并且我诚心的期望阅览本文的朋友不需求下载源码就能自己写出接触驱动。
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- structgt811_ts_platdata
- {
- u32size_x;
- u32size_y;
- u32size_p;
- u32swap;
- u32revert_x;
- u32revert_y;
- u32reset_pin;
- u32interrupt_pin;
- u32ponits_max;
- structi2c_client*client;
- structinput_dev*input;
- structwork_structwork;
- };
- staticconststructof_device_idgt811_ts_of_match[]={
- {.compatible=”gt811,gt811_ts”,.data=NULL},
- {}
- };
- staticinti2c_write_bytes(structi2c_client*client,uint8_t*data,intlen){
- structi2c_msgmsg;
- msg.flags=!I2C_M_RD;
- msg.addr=client->addr;
- msg.len=len;
- msg.buf=data;
- returni2c_transfer(client->adapter,&msg,1);
- }
- staticinti2c_read_bytes(structi2c_client*client,uint8_t*buf,intlen){
- structi2c_msgmsgs[2];
- msgs[0].flags=!I2C_M_RD;
- msgs[0].addr=client->addr;
- msgs[0].len=2;
- msgs[0].buf=&buf[0];
- msgs[1].flags=I2C_M_RD;
- msgs[1].addr=client->addr;
- msgs[1].len=len-2;
- msgs[1].buf=&buf[2];
- returni2c_transfer(client->adapter,msgs,2);
- }
- staticvoidgt811_ts_handler(structwork_struct*work)
- {
- structgt811_ts_platdata*pdata=container_of(work,structgt811_ts_platdata,work);
- structdevice*dev=&pdata->client->dev;
- uint8_tbuffer[36]={0x07,0x21,0};
- uint8_tcount,index,flags,position;
- intx,y;
- buffer[0]=0x0f;
- buffer[1]=0xff;
- if(i2c_write_bytes(pdata->client,buffer,2)<0){
- dev_err(dev,”Failedtowritewakeupmessage.”);
- gotoreenable_irq;
- }
- buffer[0]=0x07;
- buffer[1]=0x21;
- if(i2c_read_bytes(pdata->client,buffer,sizeof(buffer))<0){
- dev_err(dev,”Failedtoreadtouchmessage.”);
- gotoreenable_irq;
- }
- buffer[0]=0x80;
- buffer[1]=0x00;
- if(i2c_write_bytes(pdata->client,buffer,2)<0){
- dev_err(dev,”Failedtowritesleepmessage.”);
- gotoreenable_irq;
- }
- buffer[25]=buffer[19];
- buffer[19]=0;
- flags=buffer[2]&0x1f;
- while(flags){
- if(!(flags&0x1)){
- continue;
- }
- if(index<3){
- position=4+index*5;
- }
- else{
- position=25+(index-3)*5;
- }
- x=(buffer[position]<<8)|buffer[position+1];
- y=(buffer[position+2]<<8)|buffer[position+3];
- if(pdata->swap){
- swap(x,y);
- }
- if(pdata->revert_x){
- x=pdata->size_x-x;
- }
- if(pdata->revert_y){
- y=pdata->size_y-y;
- }
- printk(“point:(x:%03d,y:%03d)”,x,y);
- }
- //安排检测出来的接触点信息上签到输入子系统节点即可
- reenable_irq:
- enable_irq(pdata->client->irq);
- }
- staticirqreturn_tgt811_ts_isr(intirq,void*dev_id)
- {
- structgt811_ts_platdata*pdata=(structgt811_ts_platdata*)dev_id;
- disable_irq_nosync(pdata->client->irq);
- schedule_work(&pdata->work);
- returnIRQ_HANDLED;
- }
- staticintgt811_ts_initilize(structi2c_client*client)
- {
- structdevice*dev=&client->dev;
- structgt811_ts_platdata*pdata=(structgt811_ts_platdata*)i2c_get_clientdata(client);
- intstatus=0,count=0;
- uint8_tversion[4]={0x7,0x17,0};
- uint8_tconfig[]={
- 0x06,0xA2,
- 0x12,0x10,0x0E,0x0C,0x0A,0x08,0x06,0x04,0x02,0x00,0xE2,0x53,0xD2,0x53,0xC2,0x53,
- 0xB2,0x53,0xA2,0x53,0x92,0x53,0x82,0x53,0x72,0x53,0x62,0x53,0x52,0x53,0x42,0x53,
- 0x32,0x53,0x22,0x53,0x12,0x53,0x02,0x53,0xF2,0x53,0x0F,0x13,0x40,0x40,0x40,0x10,
- 0x10,0x10,0x0F,0x0F,0x0A,0x35,0x25,0x0C,0x03,0x00,0x05,0x20,0x03,0xE0,0x01,0x00,
- 0x00,0x34,0x2C,0x36,0x2E,0x00,0x00,0x03,0x19,0x03,0x08,0x00,0x00,0x00,0x00,0x00,
- 0x14,0x10,0xEC,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0D,0x40,
- 0x30,0x3C,0x28,0x00,0x00,0x00,0x00,0xC0,0x12,0x01
- };
- config[62]=480>>8;
- config[61]=480&0xff;
- config[64]=800>>8;
- config[63]=800&0xff;
- if(!gpio_is_valid(pdata->reset_pin)){
- dev_err(dev,”Theresetpinnumberisinvalid.”);
- return-EINVAL;
- }
- count=3;
- while(count–){
- gpio_direction_output(pdata->reset_pin,0);
- msleep(10);
- gpio_direction_output(pdata->reset_pin,1);
- msleep(100);
- if(i2c_read_bytes(client,version,sizeof(version))<0){
- dev_err(dev,”FailedtogettheversionofGT811,tryagain…”);
- status=-ENODEV;
- }
- else{
- dev_info(dev,”Gt811detected,version(%04x)…”,(version[2]<<8)|version[3]);
- status=0;
- break;
- }
- }
-