新闻中心

EEPW首页>嵌入式系统>设计应用> AM335x(TQ335x)学习笔记——触摸屏驱动编写

AM335x(TQ335x)学习笔记——触摸屏驱动编写

作者: 时间:2016-11-28 来源:网络 收藏
前面几篇文章已经通过配置DTS的方式完成了多个驱动的移植,接下来我们解决TQ335x的触摸驱动问题。由于种种原因,TQ335x的触摸屏驱动是以模块方式提供的,且Linux官方内核中也没有带该触摸屏的驱动源码,单纯的配置DTS是无法完成TQ335x的触摸驱动移植工作的,因此,本文参考内核中原有的pixcir_i2c_ts驱动编写TQ335x的触摸屏(TN92)驱动。

在之前移植TQ210时,我已经编写过TQ210的触摸屏驱动,我的TQ335x还是使用的TQ210的屏,因此,难度不是很大。这里需要说明一点,在TQ210驱动移植时对多点触摸协议的理解还不够深入,当时编写的驱动单点触摸是可以正常使用的,但是多点触摸不对(这次编写TQ335x的触摸驱动是才意识到的)。但是编写的TQ210驱动多点触摸实际上使用的多点触摸的A协议,但是用错了一些地方,本文基于TQ335x的重新编写的触摸驱动是按照多点触摸B协议编写,使用tslib测试正常,文章末尾有效果图。

本文引用地址://m.amcfsurvey.com/article/201611/322822.htm

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. 1.GT811检测到触摸时会拉低中断引脚,因此,GPIO1_27需要配置为下降沿触发。
  2. 2.GT811的RESET脚为低电平有效,因此,上电时需要拉低RESET引脚。
  3. 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节点内添加引脚配置信息,具体内容如下:

  1. gt811_ts_pins:gt811_ts_pins{
  2. pinctrl-single,pins=<
  3. 0x68(PIN_INPUT_PULLUP|MUX_MODE7)
  4. 0x6c(PIN_INPUT_PULLUP|MUX_MODE7)
  5. >;
  6. };
Step3. 在i2c1节点内添加GT811设备信息

GT811的设备节点内需要提供以下信息,i2c设备地址、pinmux配置、中断信息、屏幕大小等,具体如下(这里就不细说了,有什么不清楚的可以留言讨论)。

  1. gt811_ts@5d{
  2. compatible="gt811,gt811_ts";
  3. pinctrl-names="default";
  4. pinctrl-0=<>811_ts_pins>;
  5. reg=<0x5d>;
  6. interrupt-parent=<&gpio1>;
  7. interrupts=<272>;
  8. gpios=<&gpio1260>;
  9. touchscreen-size-x=<800>;
  10. touchscreen-size-y=<480>;
  11. touchscreen-swap=<1>;
  12. touchscreen-revert-x=<1>;
  13. touchscreen-revert-y=<1>;
  14. };
至此,DTS的配置工作就完成了,下面就是GT811的驱动编写。
(3)驱动编写

驱动编写根之前TQ210相比,没有多少变化,都是采用的新式I2C设备驱动架构,重要的区别在于支持了多点触摸,驱动的详细分析我就不多说了,具体可以参考韦东山老师的视频教程(绝对物有所值)。下面是GT811的多点触摸驱动源码。从GT811设备节点中获取坐标信息的部分我直接贴出来了,完整的代码还是请到资源里下载,还是有点贵哈,不过这个驱动可以直接拿去使用了,不需要任何修改。下面是不完整的代码,可以打印出触摸点坐标,该代码已经把本驱动的核心的部分都写出来了。其实很多朋友不需要下载源码就可以补充完善这个驱动了,而且我真心的希望阅读本文的朋友不需要下载源码就能自己写出触摸驱动。

  1. #include
  2. #include
  3. #include
  4. #include
  5. #include
  6. #include
  7. #include
  8. #include
  9. #include
  10. #include
  11. #include
  12. structgt811_ts_platdata
  13. {
  14. u32size_x;
  15. u32size_y;
  16. u32size_p;
  17. u32swap;
  18. u32revert_x;
  19. u32revert_y;
  20. u32reset_pin;
  21. u32interrupt_pin;
  22. u32ponits_max;
  23. structi2c_client*client;
  24. structinput_dev*input;
  25. structwork_structwork;
  26. };
  27. staticconststructof_device_idgt811_ts_of_match[]={
  28. {.compatible="gt811,gt811_ts",.data=NULL},
  29. {}
  30. };
  31. staticinti2c_write_bytes(structi2c_client*client,uint8_t*data,intlen){
  32. structi2c_msgmsg;
  33. msg.flags=!I2C_M_RD;
  34. msg.addr=client->addr;
  35. msg.len=len;
  36. msg.buf=data;
  37. returni2c_transfer(client->adapter,&msg,1);
  38. }
  39. staticinti2c_read_bytes(structi2c_client*client,uint8_t*buf,intlen){
  40. structi2c_msgmsgs[2];
  41. msgs[0].flags=!I2C_M_RD;
  42. msgs[0].addr=client->addr;
  43. msgs[0].len=2;
  44. msgs[0].buf=&buf[0];
  45. msgs[1].flags=I2C_M_RD;
  46. msgs[1].addr=client->addr;
  47. msgs[1].len=len-2;
  48. msgs[1].buf=&buf[2];
  49. returni2c_transfer(client->adapter,msgs,2);
  50. }
  51. staticvoidgt811_ts_handler(structwork_struct*work)
  52. {
  53. structgt811_ts_platdata*pdata=container_of(work,structgt811_ts_platdata,work);
  54. structdevice*dev=&pdata->client->dev;
  55. uint8_tbuffer[36]={0x07,0x21,0};
  56. uint8_tcount,index,flags,position;
  57. intx,y;
  58. buffer[0]=0x0f;
  59. buffer[1]=0xff;
  60. if(i2c_write_bytes(pdata->client,buffer,2)<0){
  61. dev_err(dev,"Failedtowritewakeupmessage.");
  62. gotoreenable_irq;
  63. }
  64. buffer[0]=0x07;
  65. buffer[1]=0x21;
  66. if(i2c_read_bytes(pdata->client,buffer,sizeof(buffer))<0){
  67. dev_err(dev,"Failedtoreadtouchmessage.");
  68. gotoreenable_irq;
  69. }
  70. buffer[0]=0x80;
  71. buffer[1]=0x00;
  72. if(i2c_write_bytes(pdata->client,buffer,2)<0){
  73. dev_err(dev,"Failedtowritesleepmessage.");
  74. gotoreenable_irq;
  75. }
  76. buffer[25]=buffer[19];
  77. buffer[19]=0;
  78. flags=buffer[2]&0x1f;
  79. while(flags){
  80. if(!(flags&0x1)){
  81. continue;
  82. }
  83. if(index<3){
  84. position=4+index*5;
  85. }
  86. else{
  87. position=25+(index-3)*5;
  88. }
  89. x=(buffer[position]<<8)|buffer[position+1];
  90. y=(buffer[position+2]<<8)|buffer[position+3];
  91. if(pdata->swap){
  92. swap(x,y);
  93. }
  94. if(pdata->revert_x){
  95. x=pdata->size_x-x;
  96. }
  97. if(pdata->revert_y){
  98. y=pdata->size_y-y;
  99. }
  100. printk("point:(x:%03d,y:%03d)",x,y);
  101. }
  102. //组织检测出来的触摸点信息上报到输入子系统节点即可
  103. reenable_irq:
  104. enable_irq(pdata->client->irq);
  105. }
  106. staticirqreturn_tgt811_ts_isr(intirq,void*dev_id)
  107. {
  108. structgt811_ts_platdata*pdata=(structgt811_ts_platdata*)dev_id;
  109. disable_irq_nosync(pdata->client->irq);
  110. schedule_work(&pdata->work);
  111. returnIRQ_HANDLED;
  112. }
  113. staticintgt811_ts_initilize(structi2c_client*client)
  114. {
  115. structdevice*dev=&client->dev;
  116. structgt811_ts_platdata*pdata=(structgt811_ts_platdata*)i2c_get_clientdata(client);
  117. intstatus=0,count=0;
  118. uint8_tversion[4]={0x7,0x17,0};
  119. uint8_tconfig[]={
  120. 0x06,0xA2,
  121. 0x12,0x10,0x0E,0x0C,0x0A,0x08,0x06,0x04,0x02,0x00,0xE2,0x53,0xD2,0x53,0xC2,0x53,
  122. 0xB2,0x53,0xA2,0x53,0x92,0x53,0x82,0x53,0x72,0x53,0x62,0x53,0x52,0x53,0x42,0x53,
  123. 0x32,0x53,0x22,0x53,0x12,0x53,0x02,0x53,0xF2,0x53,0x0F,0x13,0x40,0x40,0x40,0x10,
  124. 0x10,0x10,0x0F,0x0F,0x0A,0x35,0x25,0x0C,0x03,0x00,0x05,0x20,0x03,0xE0,0x01,0x00,
  125. 0x00,0x34,0x2C,0x36,0x2E,0x00,0x00,0x03,0x19,0x03,0x08,0x00,0x00,0x00,0x00,0x00,
  126. 0x14,0x10,0xEC,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0D,0x40,
  127. 0x30,0x3C,0x28,0x00,0x00,0x00,0x00,0xC0,0x12,0x01
  128. };
  129. config[62]=480>>8;
  130. config[61]=480&0xff;
  131. config[64]=800>>8;
  132. config[63]=800&0xff;
  133. if(!gpio_is_valid(pdata->reset_pin)){
  134. dev_err(dev,"Theresetpinnumberisinvalid.");
  135. return-EINVAL;
  136. }
  137. count=3;
  138. while(count--){
  139. gpio_direction_output(pdata->reset_pin,0);
  140. msleep(10);
  141. gpio_direction_output(pdata->reset_pin,1);
  142. msleep(100);
  143. if(i2c_read_bytes(client,version,sizeof(version))<0){
  144. dev_err(dev,"FailedtogettheversionofGT811,tryagain...");
  145. status=-ENODEV;
  146. }
  147. else{
  148. dev_info(dev,"Gt811detected,version(%04x)...",(version[2]<<8)|version[3]);
  149. status=0;
  150. break;
  151. }
  152. }

  153. 上一页 1 2 下一页

评论


技术专区

关闭