MTK 驱动(63)---MTK TP驱动移植

时间:2024-03-17 07:32:46

MTK TP驱动移植

 

对于MTK TP驱动移植一般分为六部分:

1、硬件IO口配置;

2、TP驱动移植;

3、I2C通信;

4、中断触发;

5、数据上报;

6、虚拟按键;

 

硬件电路:

MTK 驱动(63)---MTK TP驱动移植


1、GPIO配置

打开 vendor\mediatek\proprietary\scripts\DrvGen.exe 

选择 cendor\mediatek\proprietary\bootable\bootloader\lk\target\ $ (project) \dct\dct\codegen.dws 配置文件

配置EINT7_CTP引脚、CTP_RST复位引脚

MTK 驱动(63)---MTK TP驱动移植

 

2、TP驱动移植(以ft5x16为例)

在vendor\mediatek\proprietary\custom\touch目录下创建ft5x16,将供应商提供的驱动驱动资料拷贝到该目录下;

MTK 驱动(63)---MTK TP驱动移植

修改配置文件:device\mediateksample\k62v1_64_bsp\ProjectConfig.mk下的CUSTOM_KERNEL_TOUCHPANEL其值由改为ft5x16,表明对应ft5x16子目录;

打开ft5x16.c文件,修改一下:

[cpp] view plain copy

  1. static struct i2c_board_info __initdata ft5x16_i2c_tpd={ I2C_BOARD_INFO("ft5x16", (0x70>>1))}; //"ft5x16"为设备名 ,设备地址为高7位  
  2.   
  3. static struct tpd_driver_t tpd_device_driver = {  
  4.     .tpd_device_name = "FT5x16",  
  5.     .tpd_local_init = tpd_local_init,   
  6.     .suspend = tpd_suspend,  
  7.     .resume = tpd_resume,  
  8. #ifdef TPD_HAVE_BUTTON    
  9.     .tpd_have_button = 1,  
  10. #else  
  11.     .tpd_have_button = 0,  
  12. #endif        
  13. };  
  14.   
  15. /* called when loaded into kernel */  
  16. static int __init tpd_driver_init(void) {  
  17.     printk("MediaTek FT5x16 touch panel driver init\n");  
  18.     /* 注册板级设备信息 */  
  19.     i2c_register_board_info(IIC_PORT, &ft5x16_i2c_tpd, 1);  //IIC_PORT表示i2c控制器号,由电路原理图可知TP设备连接到i2c控制器0,ft5x16_i2c_tpd为i2c设备结构,1表示该i2c_board_info个数  
  20.     if(tpd_driver_add(&tpd_device_driver) < 0)  
  21.         printk("add FT5x16 driver failed\n");  
  22.     return 0;  
  23. }  
  24. </span>  

重新编译:./mk n k && ./mk bootimage 

 

3、I2C通信

新驱动编译进内核,启动内核后,我们怎样验证i2c接口能够正常通信呢?

系统启动后通过串口或adb shell进入系统命令行窗口,查询/sys/bus/i2c/devices目录下是否有0-0038信息,查询/sys/bus/i2c/drivers目录下是否存在‘ft5x16’设备名;先保证i2c能够正常通信;

 

4、中断触发

中断注册函数:mt_eint_registration(CUST_EINT_TOUCH_PANEL_NUM, CUST_EINT_TOUCH_PANEL_TYPE, tpd_eint_interrupt_handler, 1);

//tpd_eint_interrupt_handler函数为中断回调函数

 

5、数据上报

当触摸屏产生中断的时候就会调用到该接口;然后在中断处理函数中唤醒运行在子线程中的等待队列,再通过子线程获取TP数据并上报到系统;

 

[cpp] view plain copy

  1. static DECLARE_WAIT_QUEUE_HEAD(waiter);  //初始化等待队列  
  2.   
  3. thread = kthread_run(touch_event_handler, 0, TPD_DEVICE);  //新建线程  
  4.   
  5. static int touch_event_handler(void *unused)  
  6. {   
  7.     ......  
  8.     do  
  9.     {  
  10.         mt_eint_unmask(CUST_EINT_TOUCH_PANEL_NUM);   
  11.         set_current_state(TASK_INTERRUPTIBLE);   
  12.         wait_event_interruptible(waiter,tpd_flag!=0);  //等待队列进入休眠,等待唤醒  
  13.         tpd_flag = 0;  
  14.         set_current_state(TASK_RUNNING);  
  15.         ......  
  16.         if (tpd_touchinfo(&cinfo, &pinfo))   //获取TP数据  
  17.         {  
  18.             //TPD_DEBUG("point_num = %d\n",point_num);  
  19.             TPD_DEBUG_SET_TIME;  
  20.             if(point_num >0)   
  21.             {  
  22.                 for(i =0; i<point_num; i++)//only support 3 point  
  23.                 {             
  24.                     cinfo.x[i] = cinfo.x[i];  
  25.                     cinfo.y[i] = cinfo.y[i];  
  26.                       
  27.                     tpd_down(cinfo.x[i], cinfo.y[i], cinfo.id[i]); //上报按下数据  
  28.                     printk(KERN_DEBUG"----calibration----- X:%4d, Y:%4d, P:%4d \n", cinfo.x[i], cinfo.y[i], cinfo.id[i]);  
  29.                 }  
  30.                 input_sync(tpd->dev);  
  31.             }  
  32.             else    
  33.             {  
  34.                 tpd_up(cinfo.x[0], cinfo.y[0]);   //上报弹起数据  
  35.                 //TPD_DEBUG("release --->\n");   
  36.                 //input_mt_sync(tpd->dev);  
  37.                 input_sync(tpd->dev);  
  38.             }  
  39.         }  
  40.     ......  
  41.   
  42.     }while(!kthread_should_stop());  
  43.   
  44.     return 0;  
  45. }  

TP数据可以通过打印的方式进行查看,也可以**‘系统设置’中‘开发者选项’的‘指针位置’,现在触摸操作在LCD的轨迹,也可以在packages\apps\Launcher2\src\com\android\launcher2\Launcher.java的onCreate方法最后添加Settings.System.putInt(this.getContentResolver(),Settings.System.POINTER_LOCATION, 1); 在Launcher中开启‘指针位置’功能(需要mm Launcher模块并重新打包和烧录system.img文件);

 

注:如果TP获取到的数据比较乱的时候建议通过打开‘指针位置’功能进行查看,排除TP固件分辨与LCD没对应等问题;

6、虚拟按键

[cpp] view plain copy

  1. static struct tpd_driver_t tpd_device_driver = {  
  2.     .tpd_device_name = "FT5x16",  
  3.     .tpd_local_init = tpd_local_init,   
  4.     .suspend = tpd_suspend,  
  5.     .resume = tpd_resume,  
  6. #ifdef TPD_HAVE_BUTTON    
  7.     .tpd_have_button = 1,  
  8. #else  
  9.     .tpd_have_button = 0,  
  10. #endif        
  11. };  

从tpd_driver_t结构可知tpd_have_button成员为虚拟按键标志位;由宏TPD_HAVA_BUTTON开关决定的,宏定义在tpd_custom_fts.h中;

 

在tpd_custom_fts.h中定义了一系列关于虚拟按键的宏:

#define TPD_HAVE_BUTTON  //虚拟按键开关
#define TPD_BUTTON_WIDTH    (200)  //按键宽度
#define TPD_BUTTON_HEIGH    (100)  //按键高度
#define TPD_KEY_COUNT             3       //按键个数
#define TPD_KEYS                        {KEY_MENU, KEY_HOMEPAGE, KEY_BACK}  //按键对应的功能
#define TPD_KEYS_DIM              {{80,900,TPD_BUTTON_WIDTH,TPD_BUTTON_HEIGH}, {240,900,TPD_BUTTON_WIDTH,TPD_BUTTON_HEIGH}, {400,900,TPD_BUTTON_WIDTH,TPD_BUTTON_HEIGH}}  //按键对应位置

TPD_KEYS_DIM中的坐标是该按键区域的中心点:

MTK 驱动(63)---MTK TP驱动移植

 

TP驱动简要分析

 

[cpp] view plain copy

  1. static struct tpd_driver_t tpd_device_driver = {  
  2.     .tpd_device_name = FT5x16,  
  3.     .tpd_local_init = tpd_local_init,  //初始化函数  
  4.     .suspend = tpd_suspend,  
  5.     .resume = tpd_resume,  
  6. #ifdef TPD_HAVE_BUTTON  
  7.     .tpd_have_button = 1,  
  8. #else  
  9.     .tpd_have_button = 0,  
  10. #endif        
  11. };  
  12.   
  13. /* called when loaded into kernel */  
  14. static int __init tpd_driver_init(void) {  
  15.     printk("MediaTek FT5x16 touch panel driver init\n");  
  16.     i2c_register_board_info(0, &ft5x16_i2c_tpd, 1);  //注册板级设备信息  
  17.     if(tpd_driver_add(&tpd_device_driver) < 0)  //添加驱动  
  18.         printk("add FT5x16 driver failed\n");  
  19.     return 0;  
  20. }  

MTK自己编写了一套TP框架,通过该框架管理TP设备,tpd_driver_add为框架的接口之一;系统通过tpd_driver_add添加驱动后会回调tpd_local_init函数;

 

[cpp] view plain copy

  1. #ifdef TPD_HAVE_BUTTON  
  2. static int tpd_keys_local[TPD_KEY_COUNT] = TPD_KEYS;   //存放按键功能信息  
  3. static int tpd_keys_dim_local[TPD_KEY_COUNT][4] = TPD_KEYS_DIM;   //存放虚拟按键信息  
  4. #endif  
  5.   
  6. static int tpd_local_init(void)  
  7. {  
  8.     TPD_DMESG("FTS I2C Touchscreen Driver (Built %s @ %s)\n", __DATE__, __TIME__);  
  9.   
  10.     if(i2c_add_driver(&tpd_i2c_driver)!=0)  //注册i2c驱动  
  11.     {  
  12.         TPD_DMESG("FTS unable to add i2c driver.\n");  
  13.         return -1;  
  14.     }  
  15.     if(tpd_load_status == 0)   
  16.     {  
  17.         TPD_DMESG("FTS add error touch panel driver.\n");  
  18.         i2c_del_driver(&tpd_i2c_driver);  
  19.         return -1;  
  20.     }  
  21.   
  22. #ifdef TPD_HAVE_BUTTON      //如果定义虚拟按键,则初始化按键信息  
  23.     tpd_button_setting(TPD_KEY_COUNT, tpd_keys_local, tpd_keys_dim_local);// initialize tpd button data  
  24. #endif     
  25.   
  26. #if (defined(TPD_WARP_START) && defined(TPD_WARP_END))      
  27.     TPD_DO_WARP = 1;  
  28.     memcpy(tpd_wb_start, tpd_wb_start_local, TPD_WARP_CNT*4);  
  29.     memcpy(tpd_wb_end, tpd_wb_start_local, TPD_WARP_CNT*4);  
  30. #endif   
  31.   
  32. #if (defined(TPD_HAVE_CALIBRATION) && !defined(TPD_CUSTOM_CALIBRATION))  
  33.     memcpy(tpd_calmat, tpd_def_calmat_local, 8*4);  
  34.     memcpy(tpd_def_calmat, tpd_def_calmat_local, 8*4);    
  35. #endif    
  36.     TPD_DMESG("end %s, %d\n", __FUNCTION__, __LINE__);    
  37.     tpd_type_cap = 1;  
  38.     return 0;   
  39. }  

向系统注册i2c驱动后,如果找到对应的设备就会调用tpd_probe函数;


 

[cpp] view plain copy

  1. static const struct i2c_device_id ft5x16_tpd_id[] = {{TPD_NAME,0},{}};  
  2.   
  3. static struct i2c_driver tpd_i2c_driver = {  
  4.     .driver = {  
  5.         .name   = TPD_NAME,  
  6.     },  
  7.     .probe      = tpd_prob,  
  8.     .remove     = __devexit_p(tpd_remove),  
  9.     .id_table   = ft5x16_tpd_id,  
  10.     .detect     = tpd_detect,  
  11. };  
  12.   
  13. static int __devinit tpd_probe(struct i2c_client *client, const struct i2c_device_id *id)  
  14. {      
  15.     int retval = TPD_OK;  
  16.     char data;  
  17.     u8 report_rate=0;  
  18.     int err=0;  
  19.     int reset_count = 0;  
  20.     u8 chip_id,i;  
  21.   
  22. reset_proc:     
  23.     i2c_client = client;  
  24. #ifdef MAIERXUN_TP_COM  
  25.     if(touchpanel_flag){  
  26.         return 0;  
  27.     }  
  28. #endif  
  29.     //复位    
  30.     //power on, need confirm with SA  
  31.     mt_set_gpio_mode(GPIO_CTP_RST_PIN, GPIO_CTP_RST_PIN_M_GPIO);  
  32.     mt_set_gpio_dir(GPIO_CTP_RST_PIN, GPIO_DIR_OUT);  
  33.     mt_set_gpio_out(GPIO_CTP_RST_PIN, GPIO_OUT_ZERO);    
  34.     msleep(5);  
  35.     TPD_DMESG(" fts ic reset\n");  
  36.   
  37.     //打开TP电源  
  38. #ifdef TPD_POWER_SOURCE_CUSTOM  
  39.     hwPowerOn(TPD_POWER_SOURCE_CUSTOM, VOL_3300, "TP");  
  40. #else  
  41.     hwPowerOn(MT65XX_POWER_LDO_VGP2, VOL_3300, "TP");  
  42. #endif  
  43.   
  44.     mt_set_gpio_mode(GPIO_CTP_RST_PIN, GPIO_CTP_RST_PIN_M_GPIO);  
  45.     mt_set_gpio_dir(GPIO_CTP_RST_PIN, GPIO_DIR_OUT);  
  46.     mt_set_gpio_out(GPIO_CTP_RST_PIN, GPIO_OUT_ONE);  
  47.   
  48. #ifdef TPD_CLOSE_POWER_IN_SLEEP    
  49.     hwPowerDown(TPD_POWER_SOURCE,"TP");  
  50.     hwPowerOn(TPD_POWER_SOURCE,VOL_3300,"TP");  
  51.     msleep(100);  
  52.   
  53. #else  /* 结束复位 */  
  54.     mt_set_gpio_mode(GPIO_CTP_RST_PIN, GPIO_CTP_RST_PIN_M_GPIO);  
  55.     mt_set_gpio_dir(GPIO_CTP_RST_PIN, GPIO_DIR_OUT);  
  56.     mt_set_gpio_out(GPIO_CTP_RST_PIN, GPIO_OUT_ZERO);    
  57.     msleep(5);  
  58.     TPD_DMESG(" fts ic reset\n");  
  59.     mt_set_gpio_mode(GPIO_CTP_RST_PIN, GPIO_CTP_RST_PIN_M_GPIO);  
  60.     mt_set_gpio_dir(GPIO_CTP_RST_PIN, GPIO_DIR_OUT);  
  61.     mt_set_gpio_out(GPIO_CTP_RST_PIN, GPIO_OUT_ONE);  
  62. #endif  
  63.   
  64.     /* 初始化中断引脚 */  
  65.     mt_set_gpio_mode(GPIO_CTP_EINT_PIN, GPIO_CTP_EINT_PIN_M_EINT);  
  66.     mt_set_gpio_dir(GPIO_CTP_EINT_PIN, GPIO_DIR_IN);  
  67.     mt_set_gpio_pull_enable(GPIO_CTP_EINT_PIN, GPIO_PULL_ENABLE);  
  68.     mt_set_gpio_pull_select(GPIO_CTP_EINT_PIN, GPIO_PULL_UP);  
  69.   
  70.     /* 中断配置和注册 */  
  71.     mt_eint_set_hw_debounce(CUST_EINT_TOUCH_PANEL_NUM, CUST_EINT_TOUCH_PANEL_DEBOUNCE_CN);  
  72.     mt_eint_registration(CUST_EINT_TOUCH_PANEL_NUM, CUST_EINT_TOUCH_PANEL_TYPE, tpd_eint_interrupt_handler, 1);  //注册中断处理函数,TP产生中断时就会回调tpd_eint_interrupt函数  
  73.     mt_eint_unmask(CUST_EINT_TOUCH_PANEL_NUM);    
  74.   
  75.     msleep(400);  
  76.   
  77.     err=i2c_smbus_read_i2c_block_data(i2c_client, 0x00, 1, &data);  
  78.   
  79.     TPD_DMESG("gao_i2c:err %d,data:%d\n", err,data);  
  80.     if(err< 0 || data!=0)// reg0 data running state is 0; other state is not 0  
  81.     {  
  82.         TPD_DMESG("I2C transfer error, line: %d\n", __LINE__);  
  83. #ifdef TPD_RESET_ISSUE_WORKAROUND  
  84.         if ( reset_count < TPD_MAX_RESET_COUNT )  
  85.         {  
  86.             reset_count++;  
  87.             goto reset_proc;  
  88.         }  
  89. #endif  
  90.         //add at 20150330 by zhu  
  91. #ifdef MAIERXUN_TP_COM  
  92.         touchpanel_flag=false;  
  93. #endif  
  94.         return -1;   
  95.     }  
  96.   
  97.     ......  
  98.   
  99. #ifdef VELOCITY_CUSTOM_FT5206  
  100.     if((err = misc_register(&tpd_misc_device)))  //注册混杂设备驱动  
  101.     {  
  102.         printk("mtk_tpd: tpd_misc_device register failed\n");  
  103.   
  104.     }  
  105. #endif  
  106.   
  107. #ifdef TPD_AUTO_UPGRADE  
  108.     printk("********************Enter CTP Auto Upgrade********************\n");  
  109.     fts_ctpm_auto_upgrade(i2c_client);  
  110. #endif  
  111.     thread = kthread_run(touch_event_handler, 0, TPD_DEVICE);  //创建子线程,通过该子线程获取和上报数据  
  112.     if (IS_ERR(thread))  
  113.     {   
  114.         retval = PTR_ERR(thread);  
  115.         TPD_DMESG(TPD_DEVICE " failed to create kernel thread: %d\n", retval);  
  116.     }  
  117.   
  118.     TPD_DMESG("FTS Touch Panel Device Probe %s\n", (retval < TPD_OK) ? "FAIL" : "PASS");  
  119.   
  120.     /* 初始化TP的P-sensor功能,暂不分析 */  
  121. #ifdef TPD_PROXIMITY  
  122.     struct hwmsen_object obj_ps;  
  123.   
  124.     obj_ps.polling = 0;//interrupt mode  
  125.     obj_ps.sensor_operate = tpd_ps_operate;  
  126.     if((err = hwmsen_attach(ID_PROXIMITY, &obj_ps)))  
  127.     {  
  128.         APS_ERR("proxi_fts attach fail = %d\n", err);  
  129.     }  
  130.     else  
  131.     {  
  132.         APS_ERR("proxi_fts attach ok = %d\n", err);  
  133.     }         
  134. #endif  
  135.       
  136. #ifdef MAIERXUN_TP_COM  
  137.     touchpanel_flag=true;  
  138. #endif  
  139.       
  140.     return 0;  
  141.   
  142. }  


/* 中断处理函数 */

 

 

[cpp] view plain copy

  1. static void tpd_eint_interrupt_handler(void)  
  2. {  
  3.     //TPD_DEBUG("TPD interrupt has been triggered\n");  
  4.     TPD_DEBUG_PRINT_INT;  
  5.     tpd_flag = 1;   
  6.     wake_up_interruptible(&waiter);  //唤醒等待队列  
  7. }  

中断处理遵循中断上下文的设计原则,使得中断子程序只是简单唤醒等待队列就可以了,没有多余的操作;
 

 

/* 子线程处理函数 */

 

[cpp] view plain copy

  1. static int touch_event_handler(void *unused)  
  2. {   
  3.     struct touch_info cinfo, pinfo;  
  4.     int i=0;  
  5.   
  6.     struct sched_param param = { .sched_priority = RTPM_PRIO_TPD };  
  7.     sched_setscheduler(current, SCHED_RR, ¶m);  
  8.   
  9. #ifdef TPD_PROXIMITY  
  10.     int err;  
  11.     hwm_sensor_data sensor_data;  
  12.     u8 proximity_status;  
  13.   
  14. #endif  
  15.     u8 state;  
  16.   
  17.     do  //进入while循环进行睡眠-等待唤醒的操作  
  18.     {  
  19.         mt_eint_unmask(CUST_EINT_TOUCH_PANEL_NUM);  //中断使能(解除屏蔽)  
  20.         set_current_state(TASK_INTERRUPTIBLE);   
  21.         wait_event_interruptible(waiter,tpd_flag!=0);  //进入睡眠等待唤醒  
  22.   
  23.         tpd_flag = 0;  
  24.   
  25.         set_current_state(TASK_RUNNING);  
  26.         ......  
  27.   
  28. #ifdef TPD_PROXIMITY  //TP的P-sensor功能,暂不分析  
  29.         if (tpd_proximity_flag == 1)  
  30.         {  
  31.             i2c_smbus_read_i2c_block_data(i2c_client, 0xB0, 1, &state);  
  32.             TPD_PROXIMITY_DEBUG("proxi_5206 0xB0 state value is 1131 0x%02X\n", state);  
  33.   
  34.             if(!(state&0x01))  
  35.             {  
  36.                 tpd_enable_ps(1);  
  37.             }  
  38.   
  39.             i2c_smbus_read_i2c_block_data(i2c_client, 0x01, 1, &proximity_status);  
  40.             TPD_PROXIMITY_DEBUG("proxi_5206 0x01 value is 1139 0x%02X\n", proximity_status);  
  41.   
  42.             if (proximity_status == 0xC0)  
  43.             {  
  44.                 tpd_proximity_detect = 0;     
  45.             }  
  46.             else if(proximity_status == 0xE0)  
  47.             {  
  48.                 tpd_proximity_detect = 1;  
  49.             }  
  50.   
  51.             TPD_PROXIMITY_DEBUG("tpd_proximity_detect 1149 = %d\n", tpd_proximity_detect);  
  52.   
  53.             if ((err = tpd_read_ps()))  
  54.             {  
  55.                 TPD_PROXIMITY_DMESG("proxi_5206 read ps data 1156: %d\n", err);   
  56.             }  
  57.             sensor_data.values[0] = tpd_get_ps_value();  
  58.             sensor_data.value_divide = 1;  
  59.             sensor_data.status = SENSOR_STATUS_ACCURACY_MEDIUM;  
  60.             if ((err = hwmsen_get_interrupt_data(ID_PROXIMITY, &sensor_data)))  
  61.             {  
  62.                 TPD_PROXIMITY_DMESG(" proxi_5206 call hwmsen_get_interrupt_data failed= %d\n", err);      
  63.             }  
  64.         }    
  65. #endif  
  66.   
  67.         if (tpd_touchinfo(&cinfo, &pinfo))   //获取TP设备数据,并把数据保存在cinfob buf中  
  68.         {  
  69.             //TPD_DEBUG("point_num = %d\n",point_num);  
  70.             TPD_DEBUG_SET_TIME;  
  71.             if(point_num >0)   
  72.             {  
  73.                 for(i =0; i<point_num; i++)//only support 3 point  
  74.                 {  
  75.                     printk(KERN_DEBUG"X:%4d, Y:%4d, P:%4d \n", cinfo.x[i], cinfo.y[i], cinfo.id[i]);  
  76.                       
  77.                     cinfo.x[i] = cinfo.x[i];  
  78.                     cinfo.y[i] = cinfo.y[i];  
  79.                       
  80.                     tpd_down(cinfo.x[i], cinfo.y[i], cinfo.id[i]);  //按下数据处理  
  81.                     printk(KERN_DEBUG"----calibration----- X:%4d, Y:%4d, P:%4d \n", cinfo.x[i], cinfo.y[i], cinfo.id[i]);  
  82.                 }  
  83.                 input_sync(tpd->dev);  
  84.             }  
  85.             else    
  86.             {  
  87.                 tpd_up(cinfo.x[0], cinfo.y[0]); //弹起数据处理  
  88.                 //TPD_DEBUG("release --->\n");   
  89.                 //input_mt_sync(tpd->dev);  
  90.                 input_sync(tpd->dev);  
  91.             }  
  92.         }  
  93.         ......  
  94.           
  95.     }while(!kthread_should_stop());  
  96.   
  97.     return 0;  
  98. }  

 

 

/* 获取TP数据 */
[cpp] view plain copy

  1. static int tpd_touchinfo(struct touch_info *cinfo, struct touch_info *pinfo)  
  2. {  
  3.     int i = 0;  
  4.     char data[128] = {0};  
  5.     u16 high_byte,low_byte,reg;  
  6.     u8 report_rate =0;  
  7.   
  8.     p_point_num = point_num;  
  9.     if (tpd_halt)  
  10.     {  
  11.         TPD_DMESG( "tpd_touchinfo return ..\n");  
  12.         return false;  
  13.     }  
  14.     mutex_lock(&i2c_access);  
  15.   
  16.   
  17.     reg = 0x00;  
  18.     fts_i2c_Read(i2c_client, &reg, 1, data, 64);  //获取TP数据,一些TP是支持多点触控的,所以有可能就产生多个触点的数据  
  19.     mutex_unlock(&i2c_access);  
  20.   
  21.     /*get the number of the touch points*/  
  22.     point_num= data[2] & 0x0f;  
  23.   
  24.     TPD_DEBUG("point_num =%d\n",point_num);  
  25.   
  26.     /* 根据芯片协议解析数据并存放在cinfo buf中 */  
  27.     for(i = 0; i < point_num; i++)    
  28.     {  
  29.         cinfo->p[i] = data[3+6*i] >> 6; //event flag   
  30.         cinfo->id[i] = data[3+6*i+2]>>4; //touch id  
  31.         /*get the X coordinate, 2 bytes*/  
  32.         high_byte = data[3+6*i];  
  33.         high_byte <<= 8;  
  34.         high_byte &= 0x0f00;  
  35.         low_byte = data[3+6*i + 1];  
  36.         cinfo->x[i] = high_byte |low_byte;  
  37.   
  38.   
  39.         /*get the Y coordinate, 2 bytes*/  
  40.         high_byte = data[3+6*i+2];  
  41.         high_byte <<= 8;  
  42.         high_byte &= 0x0f00;  
  43.         low_byte = data[3+6*i+3];  
  44.         cinfo->y[i] = high_byte |low_byte;  
  45.         }  
  46.   
  47.     }  
  48.     TPD_DEBUG(" cinfo->x[0] = %d, cinfo->y[0] = %d, cinfo->p[0] = %d\n", cinfo->x[0], cinfo->y[0], cinfo->p[0]);    
  49.   
  50.     return true;  
  51. }  


[cpp] view plain copy

  1. static  void tpd_down(int x, int y, int p) {  
  2.   static int tpd_x = 0;  
  3.   static int tpd_y = 0;  
  4.     
  5.   tpd_x = x;  
  6.   tpd_y = y;      
  7.     
  8.         /* 通过输入子系统上报数据 */  
  9.     input_report_key(tpd->dev, BTN_TOUCH, 1);  
  10.     input_report_abs(tpd->dev, ABS_MT_TOUCH_MAJOR, 20);  
  11.     input_report_abs(tpd->dev, ABS_MT_POSITION_X, x);  
  12.     input_report_abs(tpd->dev, ABS_MT_POSITION_Y, y);  
  13.   
  14.     printk(KERN_ERR, "D[%4d %4d %4d] ", x, y, p);  
  15.     /* track id Start 0 */  
  16.     input_report_abs(tpd->dev, ABS_MT_TRACKING_ID, p);   
  17.     input_mt_sync(tpd->dev);  
  18. #ifndef MT6572  
  19.     if (FACTORY_BOOT == get_boot_mode()|| RECOVERY_BOOT == get_boot_mode())  
  20. #endif    
  21.     {     
  22.         tpd_button(x, y, 1); //虚拟按键的处理  
  23.     }  
  24.     TPD_EM_PRINT(x, y, x, y, p-1, 1);  
  25. }  
  26.   
  27. static  void tpd_up(int x, int y) {  
  28.   
  29.     input_report_key(tpd->dev, BTN_TOUCH, 0);  
  30.     input_mt_sync(tpd->dev);  
  31.     TPD_EM_PRINT(x, y, x, y, 0, 0);  
  32.   
  33. #ifndef MT6572  
  34.     if (FACTORY_BOOT == get_boot_mode()|| RECOVERY_BOOT == get_boot_mode())  
  35. #endif  
  36.     {     
  37.         tpd_button(x, y, 0);   
  38.     }              
  39. }  

 

/* 虚拟按键判断和处理函数 */
[cpp] view plain copy

  1. void tpd_button(unsigned int x, unsigned int y, unsigned int down) {  
  2.     int i;  
  3.     if(down) {  
  4.         for(i=0;i<tpd_keycnt;i++)   
  5.         {  
  6.         /* 判断数据是否落在虚拟按键的范围内,数据处理算法实现了以坐标点为中心的虚拟按键 */  
  7.             if(x>=tpd_keys_dim[i][0]-(tpd_keys_dim[i][2]/2) &&  
  8.                x<=tpd_keys_dim[i][0]+(tpd_keys_dim[i][2]/2) &&  
  9.                y>=tpd_keys_dim[i][1]-(tpd_keys_dim[i][3]/2) &&  
  10.                y<=tpd_keys_dim[i][1]+(tpd_keys_dim[i][3]/2) &&  
  11.                !(tpd->btn_state&(1<<i)))      
  12.             {  
  13.                 input_report_key(tpd->kpd, tpd_keys[i], 1);  //上报按键  
  14.                 input_sync(tpd->kpd);  
  15.                 tpd->btn_state|=(1<<i);  
  16.                 TPD_DEBUG("[mtk-tpd] press key %d (%d)\n",i, tpd_keys[i]);  
  17.                 printk("[mtk-tpd] press key %d (%d)\n",i, tpd_keys[i]);  
  18.             }  
  19.         }  
  20.     } else {  
  21.         for(i=0;i<tpd_keycnt;i++) {  
  22.             if(tpd->btn_state&(1<<i)) {  
  23.                 input_report_key(tpd->kpd, tpd_keys[i], 0);  
  24.                 input_sync(tpd->kpd);  
  25.                 TPD_DEBUG("[mtk-tpd] release key %d (%d)\n",i, tpd_keys[i]);  
  26.                 printk("[mtk-tpd] release key %d (%d)\n",i, tpd_keys[i]);  
  27.             }  
  28.         }  
  29.         tpd->btn_state=0;  
  30.     }  
  31. }  
  32. tpd_keys_dim和tpd_keys的数据是通过tpd_button_setting初始化的,可以去看tpd_button_setting()的实现;  

通过简单分析,由此可知MTK的TP驱动的整体框架跟普通TP驱动框架也是大致差不多;

转:https://blog.csdn.net/zhangbijun1230/article/details/80781868?utm_source=blogxgwz3