Chinaunix首页 | 论坛 | 博客
  • 博客访问: 3125042
  • 博文数量: 685
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 5303
  • 用 户 组: 普通用户
  • 注册时间: 2014-04-19 14:17
个人简介

文章分类

全部博文(685)

文章存档

2015年(116)

2014年(569)

分类: Android平台

2014-09-20 14:57:07

原文地址:http://blog.chinaunix.net/uid-26009923-id-3999758.html

MTK6577---touch驱动分析
Resistance screen 电阻屏
Capacitive screen 电容屏
1. 在ProjectConfig.mk中配置touch
mediatek/config/mobitek77_m01_ics2/ProjectConfig.mk
CUSTOM_KERNEL_TOUCHPANEL=mtk_gslX680

2. touch驱动初始化
在mediatek/custom/common/kernel/touchpanel/mtk_gslX680/mtk_gslX680.c中
  1. module_init(tpd_driver_init);
  2. {
  3.     tpd_driver_add
  4.     {    
  5.         i2c_register_board_info(0, &gslX680_i2c_tpd, 1); //注册i2c信息
  6.         //将tpd_device_driver中的函数指针,注册到tpd_driver_list中
  7.         tpd_driver_add(&tpd_device_driver); 
  8.     }
  9. }
在mediatek/custom/common/kernel/touchpanel/src/mtk_tpd.c中
module_init(tpd_device_init);
--> platform_driver_register(&tpd_driver)
-->   tpd_driver->tpd_probe
  1. static int tpd_probe(struct platform_device *pdev)
  2. {
  3.    a. 申请分配内存 tpd_device tpd
  4.     b. 申请分配内存 tpd->dev=input_allocate_device();
  5.     c. set_bit
  6.     d. tpd_driver_list[i].tpd_local_init();
  7.        {
  8.             i2c_add_driver();   //注册i2c设备,并调用probe函数
  9.                 --> tpd_probe(); //注意这个probe是在i2c_add_driver时会被调用
  10.        }
  11.     e. tpd_i2c_probe 被i2c_add_driver调用
  12.        {
  13.             hwPowerOn(MT65XX_POWER_LDO_VGP2, VOL_2800, "TP");
  14.             hwPowerOn(MT65XX_POWER_LDO_VGP, VOL_1800, "TP");
  15.             设置gpio引脚: GPIO_CTP_RST_PIN 与 GPIO_CTP_EINT_PIN
  16.             init_chip   //下载fw,reset, startup_chip等芯片初使化
  17.             注册中断句柄: tpd_eint_interrupt_handler
  18.             启动线程touch_event_handler,等侍wait_event_interruptible(waiter, tpd_flag != 0);
  19.        }
  20.     f. g_tpd_drv = &tpd_driver_list[i]; //:初始化g_tpd_drv
  21. }
3.中断处理流程
当有中断发生时进入中断处理函数,设两个标志,并唤醒等侍队列
  1. void tpd_eint_interrupt_handler(void)
  2. {
  3.     eint_flag = 1;
  4.     tpd_flag=1;
  5.     wake_up_interruptible(&waiter);
  6. }

线程一直在等侍唤醒中,收到信号后,结束等侍,并执行下一条代码
  1. static int touch_event_handler(void *unused)
  2. {
  3.     struct sched_param param = { .sched_priority = RTPM_PRIO_TPD };
  4.     sched_setscheduler(current, SCHED_RR, &param);
  5.     do
  6.     {
  7.         mt65xx_eint_unmask(CUST_EINT_TOUCH_PANEL_NUM);     //一上来先清中断
  8.         set_current_state(TASK_INTERRUPTIBLE);
  9.         wait_event_interruptible(waiter, tpd_flag != 0);   //收到唤醒信号,结束等侍,执行下一条代码
  10.         tpd_flag = 0;                                      //清标志位                
  11.         set_current_state(TASK_RUNNING);                   //设置状态
  12.         eint_flag = 0;                                     //清标志位
  13.         report_data_handle();                              //向上层报告数据
  14.     } while (!kthread_should_stop());
  15.     return 0;
  16. }


touch_event_handler
    --> report_data_handle
  1. static void report_data_handle(void)
  2. {
  3.     1. 从i2c中读取数据,并解析出每个点的(x,y)坐标,可能有多个
  4.     2. record_point(x, y , id);
  5.        tpd_down(id, x_new, y_new, 10);
  6.        {
  7.             input_report_key(tpd->dev, BTN_TOUCH, 1);
                input_report_abs(tpd->dev, ABS_MT_TOUCH_MAJOR, 1);
                input_report_abs(tpd->dev, ABS_MT_POSITION_X, x);
                input_report_abs(tpd->dev, ABS_MT_POSITION_Y, y);
                input_report_abs(tpd->dev, ABS_MT_TRACKING_ID, id);
                input_mt_sync(tpd->dev);      //每一个点都要发送input_mt_sync
  8.        }          
  9.        id_state_flag[id] = 1;
  10.         if(0 == point_num)               //如果当前的finger变为0,就要发送btn_up
            {
                input_report_key(tpd->dev, BTN_TOUCH, 0);   
                input_mt_sync(tpd->dev);
            }
  11.        input_sync(tpd->dev);              //所有点都发送完成后,发送input_sync
  12. }


阅读(1236) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~