MTK TouchPanel 驱动框架

前言

简单追了下 MTK TouchPanel 驱动的框架

框架

在这里插入图片描述

平台流程

【mtk touchpanel 驱动流程】:
//////////////////////////////////////////////////////////////
// Mtk_tpd.c (kernel-3.18\drivers\input\touchscreen\mediatek)
late_initcall(tpd_probe_init);
tpd_probe_init(void)
    ////////////////////////////////////////////////////////////////
    // Mtk_tpd.c (kernel-3.18\drivers\input\touchscreen\mediatek)
    // 创建一个单线程工作队列,启动工作线程
    tpd_device_init();
        // 创建单线程工作队列
        tpd_init_workqueue = create_singlethread_workqueue("mtk-tpd");
        // 初始化工作线程
        INIT_WORK(&tpd_init_work, tpd_init_work_callback);
        // 启动工作线程
        res = queue_work(tpd_init_workqueue, &tpd_init_work);
                //////////////////////////////////////////////////////////////////
                // Mtk_tpd.c (kernel-3.18\drivers\input\touchscreen\mediatek)
                tpd_init_work_callback(struct work_struct *work)
                    /////////////////////////////////////////////////////////////////   
                    // 注册 platform driver 设备    
                    //   static struct platform_driver tpd_driver = {
                    //        .remove = tpd_remove,
                    //        .shutdown = NULL,
                    //        .probe = tpd_probe,
                    //        .driver = {
                    //                .name = TPD_DEVICE,
                    //                .pm = &tpd_pm_ops,
                    //                .owner = THIS_MODULE,
                    //                .of_match_table = touch_of_match,
                    //                      /////////////////////////////////////////////////////
                    //                      //  struct of_device_id touch_of_match[] = {
                    //                      //      { .compatible = "mediatek,mt6570-touch", },
                    //                      //      { .compatible = "mediatek,mt6735-touch", },
                    //                      //      { .compatible = "mediatek,mt6580-touch", },
                    //                      //      { .compatible = "mediatek,mt8173-touch", },
                    //                      //      { .compatible = "mediatek,mt6755-touch", },
                    //                      //      { .compatible = "mediatek,mt6757-touch", },
                    //                      //      { .compatible = "mediatek,mt6797-touch", },
                    //                      //      { .compatible = "mediatek,mt8163-touch", },
                    //                      //      { .compatible = "mediatek,mt8127-touch", },
                    //                      //      { .compatible = "mediatek,mt2701-touch", },
                    //                      //      { .compatible = "mediatek,mt7623-touch", },
                    //                      //      {},
                    //                      //  };
                    //        },
                    //    };
                    /////////////////////////////////////////////////////////////////
                    //  dts 相关设置
                    //      touch: touch {
                    //          compatible = "mediatek,mt6755-touch";
                    //          // VTOUCH-supply = <&mt_pmic_vgp1_ldo_reg>; 
                    //      };
                    //      &touch {
                    //          /////////////////////////////////////////////////////////
                    //          // 上报点分辨率
                    //          tpd-resolution = <1080 1920>;
                    //          /////////////////////////////////////////////////////////
                    //          // 虚拟按键
                    //          use-tpd-button = <0>;
                    //          tpd-key-num = <3>;
                    //          tpd-key-local= <139 172 158 0>;
                    //          tpd-key-dim-local = <90 883 100 40 230 883 100 40 370 883 100 40 0 0 0 0>;
                    //          tpd-max-touch-num = <5>;
                    //          //////////////////////////////////////////////////////////
                    //          // 过滤设置
                    //          tpd-filter-enable = <1>;
                    //          tpd-filter-pixel-density = <146>;
                    //          tpd-filter-custom-prameters = <0 0 0 0 0 0 0 0 0 0 0 0>;
                    //          tpd-filter-custom-speed = <0 0 0>;
                    //          ///////////////////////////////////////////////////////////
                    //          // 引脚设置
                    //          pinctrl-names = "default", "state_eint_as_int", "state_eint_output0", "state_eint_output1",
                    //              "state_rst_output0", "state_rst_output1";
                    //          pinctrl-0 = <&ctp_pins_default>;
                    //          pinctrl-1 = <&ctp_pins_eint_as_int>;
                    //          pinctrl-2 = <&ctp_pins_eint_output0>;
                    //          pinctrl-3 = <&ctp_pins_eint_output1>;
                    //          pinctrl-4 = <&ctp_pins_rst_output0>;
                    //          pinctrl-5 = <&ctp_pins_rst_output1>;
                    //          status = "okay";
                    //      };
                    platform_driver_register(&tpd_driver)
        
        
/////////////////////////////////////////////////////////////////////////
// Mtk_tpd.c (kernel-3.18\drivers\input\touchscreen\mediatek)
tpd_probe(struct platform_device *pdev)
    /////////////////////////////////////////////////////////
    // 1. 注册杂项设备
    //      static struct miscdevice tpd_misc_device = {
    //          .minor = MISC_DYNAMIC_MINOR,
    //          .name = "touch",
    //          .fops = &tpd_fops,
    //              /////////////////////////////////////////////////////
    //              //  static const struct file_operations tpd_fops = {
    //              //  //  .owner = THIS_MODULE, 
    //              //      .open = tpd_misc_open,
    //              //      .release = tpd_misc_release,
    //              //      .unlocked_ioctl = tpd_unlocked_ioctl,
    //              //  #ifdef CONFIG_COMPAT
    //              //      .compat_ioctl = tpd_compat_ioctl,
    //              //  #endif
    //              //  };
    //      };
    misc_register(&tpd_misc_device)
    /////////////////////////////////////////////////////////////
    // 2.【获得 dts 相关引脚配置 pinctrl】
    tpd_get_gpio_info(pdev);
            pinctrl1 = devm_pinctrl_get(&pdev->dev);
            pins_default = pinctrl_lookup_state(pinctrl1, "default");
            eint_as_int = pinctrl_lookup_state(pinctrl1, "state_eint_as_int");
            eint_output0 = pinctrl_lookup_state(pinctrl1, "state_eint_output0");
            eint_output1 = pinctrl_lookup_state(pinctrl1, "state_eint_output1");
            rst_output0 = pinctrl_lookup_state(pinctrl1, "state_rst_output0");
            rst_output1 = pinctrl_lookup_state(pinctrl1, "state_rst_output1");
            
    ////////////////////////////////////////////////////////////////
    // 3. 分配 mtk 封装的 tp 数据结构
    tpd = kmalloc(sizeof(struct tpd_device), GFP_KERNEL);     
    ////////////////////////////////////////////////////////////////
    // 4. 分配分配输入子系统
    tpd->dev = input_allocate_device();    
    
    ///////////////////////////////////////////////////////////////
    // 5. 处理 touch panel 报点旋转
    if (0 == strncmp(CONFIG_MTK_LCM_PHYSICAL_ROTATION, "90", 2)
		|| 0 == strncmp(CONFIG_MTK_LCM_PHYSICAL_ROTATION, "270", 3))
        TPD_RES_Y = DISP_GetScreenWidth();
		TPD_RES_X = DISP_GetScreenHeight();
    
    ///////////////////////////////////////////////////////////////
    // 6. 相关报点参数设置
    tpd_mode = TPD_MODE_NORMAL;
	tpd_mode_axis = 0;
	tpd_mode_min = TPD_RES_Y / 2;
	tpd_mode_max = TPD_RES_Y;
	tpd_mode_keypad_tolerance = TPD_RES_X * TPD_RES_X / 1600;
    
    //////////////////////////////////////////////////////////////
    // 7. 设置输入设备 TP 上报事件类型
    set_bit(EV_ABS, tpd->dev->evbit);
	set_bit(EV_KEY, tpd->dev->evbit);
	set_bit(ABS_X, tpd->dev->absbit);
	set_bit(ABS_Y, tpd->dev->absbit);
	set_bit(ABS_PRESSURE, tpd->dev->absbit);
    
    //////////////////////////////////////////////////////////////////
    // 8.【调用第三方驱动注册的的 init 函数】
    for (i = 1; i < TP_DRV_MAX_COUNT; i++)
        if (tpd_driver_list[i].tpd_device_name != NULL) {
            //////////////////////////////////////////////////////////
            // 主要注册 i2c 设备驱动,设置 tp 虚拟按键属性
			tpd_driver_list[i].tpd_local_init();
                    /////////////////////////////////////////////////////////////////////
                    // Focaltech_core.c (kernel-3.18\drivers\input\touchscreen\mediatek\focaltech_touch_ft3427)
                    tpd_local_init(void)
                        ///////////////////////////////////
                        // 初始化 TP 使用的 reglator:上电 2.8v
                        fts_power_init() 
                                tpd->tpd_dev->of_node = of_find_compatible_node(NULL, NULL, "mediatek,mt6755-touch");
                                if (tpd->tpd_dev->of_node)
                                    tpd->reg = regulator_get(tpd->tpd_dev, "vtouch");
                                    retval = regulator_set_voltage(tpd->reg, 2800000, 2800000);
                        ///////////////////////////////////
                        // 注册 i2c device
                        i2c_add_driver(&tpd_i2c_driver) 
                        //////////////////////////////////
                        // 设置 tp 设置
                        if (tpd_dts_data.use_tpd_button)
                            tpd_button_setting(tpd_dts_data.tpd_key_num, tpd_dts_data.tpd_key_local, tpd_dts_data.tpd_key_dim_local);
                                    tpd_keycnt = keycnt;
                                    memcpy(tpd_keys, keys, keycnt * 4);
                                    memcpy(tpd_keys_dim, keys_dim, keycnt * 4 * 4);
                    
            ///////////////////////////////////////////////////////// 
            // tpd_load_status 是在具体 TP 驱动中的 probe 函数中设置的
            // 【TP 初始化成功后,会设置此位】
			if (tpd_load_status == 1) 		
                ////////////////////////////////////////////////////
                // 【设置当前使用的 tp 】
				g_tpd_drv = &tpd_driver_list[i];				
			
		}
    /////////////////////////////////////////////////////////////
    // 9. 如果没有注册 tp 驱动,则调用默认的 R 电阻屏驱动
    if (g_tpd_drv == NULL) {
		if (tpd_driver_list[0].tpd_device_name != NULL) {
			g_tpd_drv = &tpd_driver_list[0];
			// touch_type:0: r-touch, 1: C-touch 
			touch_type = 0;
			g_tpd_drv->tpd_local_init();		
		}
	}
    
    ////////////////////////////////////////////////////////////////////////
    // 10. 调用当前使用的 tp 驱动的 resume() 函数
    touch_resume_workqueue = create_singlethread_workqueue("touch_resume");
	INIT_WORK(&touch_resume_work, touch_resume_workqueue_callback);
				// Mtk_tpd.c (kernel-3.18\drivers\input\touchscreen\mediatek)
                touch_resume_workqueue_callback(struct work_struct *work)
                	g_tpd_drv->resume(NULL);

	///////////////////////////////////////////////////////////////////////////////
	// 11. 注册内核通知链,监听 fb_notifier,应该会在相应的屏的驱动里面进行通知调用 
    //      【在这里进行 TP 的唤醒和休眠操作】
	tpd_fb_notifier.notifier_call = tpd_fb_notifier_callback;
									tpd_fb_notifier_callback(struct notifier_block *self, unsigned long event, void *data)
                                    // 参数:谁调用谁传
                                            /////////////////////////////////////////////////
                                            // 直接传个指针过来了。。。
                                            evdata = data;
                                            blank = *(int *)evdata->data;
                                            //////////////////////////////////////////////////
                                            // 进行 TP 的唤醒,休眠操作
                                            switch (blank)
                                                case FB_BLANK_UNBLANK:
                                                    if (g_tpd_drv && tpd_suspend_flag)
                                                        err = queue_work(touch_resume_workqueue, &touch_resume_work);                                                                           
                                                case FB_BLANK_POWERDOWN:
                                                    if (g_tpd_drv && !tpd_suspend_flag)
                                                        ////////////////////////////////////////////////////
                                                        // 取消唤醒工作队列
                                                        err = cancel_work_sync(&touch_resume_work);
                                                        ///////////////////////////////////////////////////
                                                        // 调用第三方驱动的 suspend 挂起函数
                                                        g_tpd_drv->suspend(NULL);

	//////////////////////////////////////////
    // 注册通知链
    fb_register_client(&tpd_fb_notifier)
    
    //////////////////////////////////////////////////////////////
    // 设置输入设备 TP 上报事件
    input_set_abs_params(tpd->dev, ABS_X, 0, TPD_RES_X, 0, 0);
	input_set_abs_params(tpd->dev, ABS_Y, 0, TPD_RES_Y, 0, 0);
	input_abs_set_res(tpd->dev, ABS_X, TPD_RES_X);
	input_abs_set_res(tpd->dev, ABS_Y, TPD_RES_Y);
	input_set_abs_params(tpd->dev, ABS_PRESSURE, 0, 255, 0, 0);
	input_set_abs_params(tpd->dev, ABS_MT_TRACKING_ID, 0, 10, 0, 0);
    
    /////////////////////////////////////////////////////////////
    // 注册输入设备
    input_register_device(tpd->dev)
    tpd_register_flag = 1;
    
    if (g_tpd_drv->tpd_have_button)
        tpd_button_init();    
        
    if (g_tpd_drv->attrs.num)
		tpd_create_attributes(&pdev->dev, &g_tpd_drv->attrs);    

第三方流程

【TouchPanel 初始化流程】:
module_init(tpd_driver_init);
tpd_driver_init(void)
    ///////////////////////////////////////////////////////////////
    // Mtk_tpd.c (kernel-3.18\drivers\input\touchscreen\mediatek)
    // 获得 dts 设备树中与 touch 相关的配置项
    // 保存在 tpd_dts_data 全局变量中
    tpd_get_dts_info();            
            ////////////////////////////////////////////////////////////////
            // 匹配 dts 设备树中的节点
            //      struct of_device_id touch_of_match[] = {
            //          { .compatible = "mediatek,mt6570-touch", },
            //          { .compatible = "mediatek,mt6735-touch", },
            //          { .compatible = "mediatek,mt6580-touch", },
            //          { .compatible = "mediatek,mt8173-touch", },
            //          { .compatible = "mediatek,mt6755-touch", },
            //          { .compatible = "mediatek,mt6757-touch", },
            //          { .compatible = "mediatek,mt6797-touch", },
            //          { .compatible = "mediatek,mt8163-touch", },
            //          { .compatible = "mediatek,mt8127-touch", },
            //          { .compatible = "mediatek,mt2701-touch", },
            //          { .compatible = "mediatek,mt7623-touch", },
            //          {},
            //      };
            /////////////////////////////////////////////////////////////////
            //  dts 相关设置
            //      touch: touch {
            //          compatible = "mediatek,mt6755-touch";
            //          // VTOUCH-supply = <&mt_pmic_vgp1_ldo_reg>; 
            //      };
            //      &touch {
            //          /////////////////////////////////////////////////////////
            //          // 上报点分辨率
            //          tpd-resolution = <1080 1920>;
            //          /////////////////////////////////////////////////////////
            //          // 虚拟按键
            //          use-tpd-button = <0>;
            //          tpd-key-num = <3>;
            //          tpd-key-local= <139 172 158 0>;
            //          tpd-key-dim-local = <90 883 100 40 230 883 100 40 370 883 100 40 0 0 0 0>;
            //          tpd-max-touch-num = <5>;
            //          //////////////////////////////////////////////////////////
            //          // 过滤设置
            //          tpd-filter-enable = <1>;
            //          tpd-filter-pixel-density = <146>;
            //          tpd-filter-custom-prameters = <0 0 0 0 0 0 0 0 0 0 0 0>;
            //          tpd-filter-custom-speed = <0 0 0>;
            //          ///////////////////////////////////////////////////////////
            //          // 引脚设置
            //          pinctrl-names = "default", "state_eint_as_int", "state_eint_output0", "state_eint_output1",
            //              "state_rst_output0", "state_rst_output1";
            //          pinctrl-0 = <&ctp_pins_default>;
            //          pinctrl-1 = <&ctp_pins_eint_as_int>;
            //          pinctrl-2 = <&ctp_pins_eint_output0>;
            //          pinctrl-3 = <&ctp_pins_eint_output1>;
            //          pinctrl-4 = <&ctp_pins_rst_output0>;
            //          pinctrl-5 = <&ctp_pins_rst_output1>;
            //          status = "okay";
            //      };
            node1 = of_find_matching_node(node1, touch_of_match);
            
            /////////////////////////////////////////////////////////////////////////////////////
            // 获得平台中 dts 中的数据,保存在 tpd_dts_data 全局变量中
            if (node1)
                of_property_read_u32(node1, "【tpd-max-touch-num】", &tpd_dts_data.touch_max_num);
                of_property_read_u32(node1, "【use-tpd-button】", &tpd_dts_data.use_tpd_button);
                of_property_read_u32_array(node1, "【tpd-resolution】",	tpd_dts_data.tpd_resolution, ARRAY_SIZE(tpd_dts_data.tpd_resolution));
                if (tpd_dts_data.use_tpd_button)
                    of_property_read_u32(node1, "【tpd-key-num】", &tpd_dts_data.tpd_key_num);
                    of_property_read_u32_array(node1, "【tpd-key-local】",tpd_dts_data.tpd_key_local, ARRAY_SIZE(tpd_dts_data.tpd_key_local));
                    of_property_read_u32_array(node1, "【tpd-key-dim-local】",key_dim_local, ARRAY_SIZE(key_dim_local));
                    of_property_read_u32(node1, "【tpd-filter-enable】", &tpd_dts_data.touch_filter.enable);
                if (tpd_dts_data.touch_filter.enable)
                    of_property_read_u32(node1, "【tpd-filter-pixel-density】",&tpd_dts_data.touch_filter.pixel_density);
                    of_property_read_u32_array(node1, "【tpd-filter-custom-prameters】",(u32 *)tpd_dts_data.touch_filter.W_W, ARRAY_SIZE(tpd_dts_data.touch_filter.W_W));
                    of_property_read_u32_array(node1, "【tpd-filter-custom-speed】",tpd_dts_data.touch_filter.VECLOCITY_THRESHOLD,ARRAY_SIZE(tpd_dts_data.touch_filter.VECLOCITY_THRESHOLD));

    
    //////////////////////////////////////////////////////////////////////////
    // 注册 tpd 驱动
    //      static struct tpd_driver_t tpd_device_driver = {
    //          .tpd_device_name = FTS_DRIVER_NAME,
    //          .tpd_local_init = tpd_local_init,
    //          .suspend = tpd_suspend,
    //          .resume = tpd_resume,
    //          .attrs = {
    //                    .attr = fts_attrs,
    //                    .num = ARRAY_SIZE(fts_attrs),
    //                    },
    //      };
    tpd_driver_add(&tpd_device_driver)
            /////////////////////////////////////////////////////////////////////////////////
            // Mtk_tpd.c (z:\work\e266l_cmcc\kernel-3.18\drivers\input\touchscreen\mediatek)
            tpd_driver_add(struct tpd_driver_t *tpd_drv)
                tpd_drv->tpd_have_button = tpd_dts_data.use_tpd_button;
                ////////////////////////////////////////////////////////////////////////////
                // tpd_driver_list[0]: 默认用来保存电阻屏的驱动
                if (strcmp(tpd_drv->tpd_device_name, "generic") == 0)
                    tpd_driver_list[0].tpd_device_name = tpd_drv->tpd_device_name;
                    tpd_driver_list[0].tpd_local_init = tpd_drv->tpd_local_init;
                    tpd_driver_list[0].suspend = tpd_drv->suspend;
                    tpd_driver_list[0].resume = tpd_drv->resume;
                    tpd_driver_list[0].tpd_have_button = tpd_drv->tpd_have_button;
                
                ////////////////////////////////////////////////////////////////////////////
                // 将要注册的结构体放到 tpd_driver_list[] 全局数组中
                for (i = 1; i < TP_DRV_MAX_COUNT; i++)
                    if (tpd_driver_list[i].tpd_device_name == NULL) {
                        tpd_driver_list[i].tpd_device_name = tpd_drv->tpd_device_name;
                        tpd_driver_list[i].tpd_local_init = tpd_drv->tpd_local_init;
                        tpd_driver_list[i].suspend = tpd_drv->suspend;
                        tpd_driver_list[i].resume = tpd_drv->resume;
                        tpd_driver_list[i].tpd_have_button = tpd_drv->tpd_have_button;
                        tpd_driver_list[i].attrs = tpd_drv->attrs;
                        break;
                    }
            
            
/////////////////////////////////////////////////////////////////////////////////////
// 当在 tpd_common_probe.c 中调用 .tpd_local_init() 函数指针时,会注册一个 i2c device                    
tpd_local_init(void)                    
    ///////////////////////////////////
    // 初始化 TP 使用的 reglator:上电 2.8v
    fts_power_init() 
            tpd->tpd_dev->of_node = of_find_compatible_node(NULL, NULL, "mediatek,mt6755-touch");
            if (tpd->tpd_dev->of_node)
                tpd->reg = regulator_get(tpd->tpd_dev, "vtouch");
                retval = regulator_set_voltage(tpd->reg, 2800000, 2800000);
    ///////////////////////////////////
    // 注册 i2c device
    //      static struct i2c_driver tpd_i2c_driver = {
    //          .driver = {
    //                     .name = FTS_DRIVER_NAME,
    //                     .of_match_table = of_match_ptr(fts_dt_match),
    //                                    ///////////////////////////////////////////////////////
    //                                    // 【兼容原理】:所有的 sensor 都指定匹配此设备节点
    //                                    //            在所进入的 i2c probe() 函数中强制转换 i2c 地址
    //                                    //            这就需要要兼容的多个驱动中需要检测当前初始化的是
    //                                    //            哪颗芯片的
    //                                    // static const struct of_device_id fts_dt_match[] = {
    //                                    //     {.compatible = "mediatek,cap_touch"},
    //                                    //     {},
    //                                    // };
    //                     },
    //          .probe = tpd_probe,
    //          .remove = tpd_remove,
    //          .id_table = fts_tpd_id,
    //          .detect = tpd_i2c_detect,
    //      };
    i2c_add_driver(&tpd_i2c_driver) 
    //////////////////////////////////
    // 设置 tp 设置
    if (tpd_dts_data.use_tpd_button)
        tpd_button_setting(tpd_dts_data.tpd_key_num, tpd_dts_data.tpd_key_local, tpd_dts_data.tpd_key_dim_local);
                tpd_keycnt = keycnt;
                memcpy(tpd_keys, keys, keycnt * 4);
                memcpy(tpd_keys_dim, keys_dim, keycnt * 4 * 4);              
                    
                    
//////////////////////////////////////////////////////////////////////////////////////
// 进入 i2c probe 函数          
tpd_probe(struct i2c_client *client, const struct i2c_device_id *id)

    ///////////////////////////////////////////////////////////////
    // 兼容处理
    if (fts_i2c_client->addr != FTS_I2C_SLAVE_ADDR) 
        fts_i2c_client->addr = FTS_I2C_SLAVE_ADDR;
    
    ///////////////////////////////////////////////////////////////
    // 通过 pinctrl 设置中断引脚
    tpd_gpio_as_int(tpd_int_gpio_number);
        if (pin == 1)
            pinctrl_select_state(pinctrl1, eint_as_int);
    ///////////////////////////////////////////////////////////////
    // 获得 dts 中与中断相关设置,然后申请中断,设置中断处理函数
    //  【TP 中断处理函数】:主要是唤醒 TP 工作队列
    tpd_irq_registration(client);
        ///////////////////////////////////////////////////////////
        // 获得 dts 中相应项
        //      struct of_device_id touch_of_match[] = {
        //          { .compatible = "mediatek,mt6570-touch", },
        //          { .compatible = "mediatek,mt6735-touch", },
        //          { .compatible = "mediatek,mt6580-touch", },
        //          { .compatible = "mediatek,mt8173-touch", },
        //          { .compatible = "mediatek,mt6755-touch", },
        //          { .compatible = "mediatek,mt6757-touch", },
        //          { .compatible = "mediatek,mt6797-touch", },
        //          { .compatible = "mediatek,mt8163-touch", },
        //          { .compatible = "mediatek,mt8127-touch", },
        //          { .compatible = "mediatek,mt2701-touch", },
        //          { .compatible = "mediatek,mt7623-touch", },
        //          {},
        //      };
        node = of_find_matching_node(node, touch_of_match);
        //////////////////////////////////////////////////////////
        // 获得 dts 中与中断相关设置,然后申请中断,设置中断处理函数
        //  【TP 中断处理函数】:主要是唤醒 TP 工作队列
        if (node) 
            of_property_read_u32_array(node, "debounce", ints, ARRAY_SIZE(ints));
            gpio_set_debounce(ints[0], ints[1]);
            ft_touch_irq = irq_of_parse_and_map(node, 0);
            ret = request_irq(ft_touch_irq, tpd_eint_interrupt_handler, IRQF_TRIGGER_FALLING, "TOUCH_PANEL-eint", NULL);
                                            /////////////////////////////////////////////////////////////////////////////////
                                            // 【TP 中断处理函数】:主要是唤醒 TP 工作队列
                                            tpd_eint_interrupt_handler(int irq, void *dev_id)
                                                    ////////////////////////////////////////
                                                    // 设置中断标志
                                                    tpd_flag = 1;
                                                    ////////////////////////////////////////
                                                    // 唤醒睡眠在 waiter 等待队列上的进程
                                                    wake_up_interruptible(&waiter);
    
    ////////////////////////////////////////////////////////////////
    // 关中断,先不能进行中断处理
    fts_irq_disable();
        disable_irq_nosync(ft_touch_irq);
    
    /////////////////////////////////////////////////////////////////
    // 初始化 i2c,只是进行 dma 内存分配用的
    fts_i2c_init();
        fts_i2c_msg_dma_alloct();
            if (NULL == g_dma_buff_va)
                tpd->dev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
                g_dma_buff_va = (u8 *) dma_alloc_coherent(&tpd->dev->dev, DMA_BUFFER_LENGTH, &g_dma_buff_pa, GFP_KERNEL);
        
        
    ///////////////////////////////////////////////////////////////////
    // 返回 chip type, 检查芯片 hid?
    // 【核心】获得更新函数指针
    fts_ctpm_get_upgrade_array();
        ////////////////////////////////////////////////////
        // 奇怪的函数,只是返回固定数组中的值
        fts_get_chip_types();
            struct ft_chip_t ctype[] = FTS_CHIP_TYPE_MAPPING;
            chip_types = ctype[ic_type];
        /////////////////////////////////////////////////////
        // 检查芯片 ?
        fts_ctpm_i2c_hid2std(fts_i2c_client);
            buf[0] = 0xeb;
            buf[1] = 0xaa;
            buf[2] = 0x09;
            bRet = fts_i2c_write(client, buf, 3);
            fts_i2c_read(client, buf, 0, buf, 3);
            if ((0xeb == buf[0]) && (0xaa == buf[1]) && (0x08 == buf[2])) 
        ////////////////////////////////////////////////////////
        // 【核心】获得更新函数指针
        // 对应的函数指针位于:Focaltech_upgrade_ft8006.c (focaltech_touch_ft3427\focaltech_flash)
        memcpy(&fts_updatefun_curr, &fts_updatefun, sizeof(struct fts_upgrade_fun));
            
    ///////////////////////////////////////////////////////////////////////
    // 注册 input 需要上报的,手势 键值
    // 创建 sys 下手势相关的节点 
    fts_gesture_init(tpd->dev, client);
            input_set_capability(input_dev, EV_KEY, KEY_POWER);
            input_set_capability(input_dev, EV_KEY, KEY_GESTURE_U);
            input_set_capability(input_dev, EV_KEY, KEY_GESTURE_UP);
            input_set_capability(input_dev, EV_KEY, KEY_GESTURE_DOWN);
            input_set_capability(input_dev, EV_KEY, KEY_GESTURE_LEFT);
            input_set_capability(input_dev, EV_KEY, KEY_GESTURE_RIGHT);
            input_set_capability(input_dev, EV_KEY, KEY_GESTURE_O);
            input_set_capability(input_dev, EV_KEY, KEY_GESTURE_E);
            input_set_capability(input_dev, EV_KEY, KEY_GESTURE_M);
            input_set_capability(input_dev, EV_KEY, KEY_GESTURE_L);
            input_set_capability(input_dev, EV_KEY, KEY_GESTURE_W);
            input_set_capability(input_dev, EV_KEY, KEY_GESTURE_S);
            input_set_capability(input_dev, EV_KEY, KEY_GESTURE_V);
            input_set_capability(input_dev, EV_KEY, KEY_GESTURE_Z);
            input_set_capability(input_dev, EV_KEY, KEY_GESTURE_C);

            __set_bit(KEY_GESTURE_RIGHT, input_dev->keybit);
            __set_bit(KEY_GESTURE_LEFT, input_dev->keybit);
            __set_bit(KEY_GESTURE_UP, input_dev->keybit);
            __set_bit(KEY_GESTURE_DOWN, input_dev->keybit);
            __set_bit(KEY_GESTURE_U, input_dev->keybit);
            __set_bit(KEY_GESTURE_O, input_dev->keybit);
            __set_bit(KEY_GESTURE_E, input_dev->keybit);
            __set_bit(KEY_GESTURE_M, input_dev->keybit);
            __set_bit(KEY_GESTURE_W, input_dev->keybit);
            __set_bit(KEY_GESTURE_L, input_dev->keybit);
            __set_bit(KEY_GESTURE_S, input_dev->keybit);
            __set_bit(KEY_GESTURE_V, input_dev->keybit);
            __set_bit(KEY_GESTURE_C, input_dev->keybit);
            __set_bit(KEY_GESTURE_Z, input_dev->keybit);
            ///////////////////////////////////////////////
            // 创建 sys 下节点 
            fts_create_gesture_sysfs(client);
            fts_gesture_data.mode = 0;
            fts_gesture_data.active = 0;
            
    ///////////////////////////////////////////////////////////////////////
    // TP 上的距感初始化
    //      设置标志,创建 sys 下节点
    //      注册距感到 hwmsen 中管理,这是老接口
    fts_proximity_init(client);
            ////////////////////////////////////
            // 设置标志,创建 sys 下节点
            fts_proximity_data.detect = 1; 
            err = sysfs_create_group(&client->dev.kobj, &fts_touch_proximity_group);
            /////////////////////////////////////
            // 注册距感,这是老接口
            obj_ps.polling = 0;         // interrupt mode 
            obj_ps.sensor_operate = fts_ps_operate;
            err = hwmsen_attach(ID_PROXIMITY, &obj_ps);
    
    ///////////////////////////////////////////////////////////////////////////
    // 初始化 MTK 封装 input 的,应该用于批量上报的接口 
    input_mt_init_slots(tpd->dev, tpd_dts_data.touch_max_num, INPUT_MT_DIRECT);
    
    ///////////////////////////////////////////////////////////////////////////
    // 通过 pinctrl 复位 TP, 只是复位 rst 引脚
    fts_reset_proc(200);
        tpd_gpio_output(tpd_rst_gpio_number, 0);
        msleep(20);
        tpd_gpio_output(tpd_rst_gpio_number, 1);
    
    //////////////////////////////////////////////////////////////////////////////
    // 通过 i2c 读取寄存器芯片 chip id
    fts_wait_tp_to_valid(client);
            do {
                ret = fts_i2c_read_reg(client, FTS_REG_CHIP_ID, &reg_value);
            }while ((cnt * INTERVAL_READ_REG) < TIMEOUT_READ_REG);
            
    /////////////////////////////////////////////////////////////////////////////////        
    tpd_load_status = 1;
    
    //////////////////////////////////////////////////////////////////////////////
    // 创建 sys 下节点, 用于升级检测什么的
    fts_create_sysfs(client);
        //////////////////////////////////////////////////////////////////////////////
        //  // 【get the fw version、
        //     example:cat fw_version
        //  static DEVICE_ATTR(fts_fw_version, S_IRUGO | S_IWUSR, fts_tpfwver_show, fts_tpfwver_store);
        //  
        //  // 【upgrade from *.i】
        //    example: echo 1 > fw_update
        //  static DEVICE_ATTR(fts_fw_update, S_IRUGO | S_IWUSR, fts_fwupdate_show, fts_fwupdate_store);
        //
        //  // 【read and write register】
        //    read example: echo 88 > rw_reg ---read register 0x88
        //    write example:echo 8807 > rw_reg ---write 0x07 into register 0x88
        //  
        //    note:the number of input must be 2 or 4.if it not enough,please fill in the 0.
        //  static DEVICE_ATTR(fts_rw_reg, S_IRUGO | S_IWUSR, fts_tprwreg_show, fts_tprwreg_store);
        //
        //  //【upgrade from app.bin】
        //     example:echo "*_app.bin" > upgrade_app
        //  static DEVICE_ATTR(fts_upgrade_app, S_IRUGO | S_IWUSR, fts_fwupgradeapp_show, fts_fwupgradeapp_store);
        //  static DEVICE_ATTR(fts_driver_version, S_IRUGO | S_IWUSR, fts_driverversion_show, fts_driverversion_store);
        //  static DEVICE_ATTR(fts_dump_reg, S_IRUGO | S_IWUSR, fts_dumpreg_show, fts_dumpreg_store);
        //  static DEVICE_ATTR(fts_show_log, S_IRUGO | S_IWUSR, fts_show_log_show, fts_show_log_store);
        //  static DEVICE_ATTR(fts_module_config, S_IRUGO | S_IWUSR, fts_module_config_show, fts_module_config_store);
        //  #if FTS_ESDCHECK_EN
        //  static DEVICE_ATTR(fts_esd_check, S_IRUGO | S_IWUSR, fts_esdcheck_show, fts_esdcheck_store);
        //  #endif
        err = sysfs_create_group(&client->dev.kobj, &fts_attribute_group);
        
    //////////////////////////////////////////////////////////////////////////////
    // 初始化一个工作队列,里面通过 input 事件上报触摸事件
    fts_point_report_check_init();
        ///////////////////////////////////////////////////////////
        // 初始化一个工作队列,里面通过 mtk 封装的 input 事件上报触摸事件
        INIT_DELAYED_WORK(&fts_point_report_check_work, fts_point_report_check_func);
                                                fts_point_report_check_func(struct work_struct *work)
                                                    for (finger_count = 0; finger_count < FTS_MAX_POINTS; finger_count++)
                                                         input_mt_slot(fts_input_dev, finger_count);
                                                         input_mt_report_slot_state(fts_input_dev, MT_TOOL_FINGER, false);
                                                    input_report_key(fts_input_dev, BTN_TOUCH, 0);
                                                    input_sync(fts_input_dev);
                                                         
        /////////////////////////////////////////////////////////
        // 创建工作队列
        fts_point_report_check_workqueue = create_workqueue("fts_point_report_check_func_wq");
                               
    ////////////////////////////////////////////////////////////////////////////////
    // 创建 sys 结点, 用于显示当前触摸屏的工作状态: charge / cover / glove
    fts_ex_mode_init(client);
        g_fts_mode_flag.fts_glove_mode_flag = false;
        g_fts_mode_flag.fts_cover_mode_flag = false;
        g_fts_mode_flag.fts_charger_mode_flag = false;
        err = sysfs_create_group(&client->dev.kobj, &fts_touch_mode_group);
    
    ////////////////////////////////////////////////////////////////////////////////
    // 创建 /proc 下的调试节点
    fts_create_apk_debug_channel(client);
    
    ////////////////////////////////////////////////////////////////////////////////
    // TP 的工作线程
    //      设置调度优先级
    //      如果使用虚拟按键的话,先清按键
    //      设置调度策略
    //    循环:
    //        设置当前进程睡眠,等待唤醒
    //        工作线程被唤醒,设置进程状态为运行态
    //        检查手势功能是否使能,
    //        如果手势使能了,那就通过 i2c 读取手势相关寄存器值
    //          根据 gesture_id 转换成要通知应用层的 手势值
    //          通过 uevent 发送给应用层
    //          调用 sysfs_notify() 通知链
    //        解析寄存器,将获得的手势值保存在缓存中
    //        TP 上距感相关数据获取:旧接口,通过 hwsen 上报
    //        通过 mtk 封装的 input 事件上报触摸事件
    //        设置 esd 标志位,表示当前处理中断处理中:interrupt don't add debug message
    //        通过 i2c 读取相关报点值
    //        解析 i2c 读取的寄存器值,获得相应的手势值
    //        读取寄存器成功,开始上报键值
    //             如果有虚拟按键,则通过 input 事件上报:按下松开事件
    //             通过 input 上报触摸和手势按键值
    //        上报完成后,可以进行 esd 复位了,通过 ese 退出中断了
    //      
    thread_tpd = kthread_run(touch_event_handler, 0, TPD_DEVICE);

	/////////////////////////////////////////////////////////////
    // 初始化 esd 工作队列, 切换 esd 线程工作状态
    ///////////////////////////////////////////////////////
    // esd 工作函数:esdcheck_func()
    //      首先检查 lcd 是否复位过,如果复位过,则需要恢复 TP 工作状态
    //           如果 lcd 已经复位了,则需要恢复 TP 状态
    //           恢复 TP  工作状态
    //                轮询通过 i2c 获取芯片 ID
    //                芯片状态恢复,之前是处于:
    //                    1. 手套模式
    //                    2. 恢复模式
    //                    3. 充电模式
    //                通过 i2c 恢复之前的 TP 中的 PSENSOR 状态
    //                通过 i2c 复位手势寄存器
    //                通过 input 系统,上报 resume 之前的所有 TP 手势
    //      然后进行 esd 策略检查:
    //           1. 检查是否在中断中,如果是直接返回
    //           2. 检查电源状态,如果在挂起状态,则不需要做检查
    //           3. 检查是否有 proc_debug 状态,如果有的话,不需要检查 esd
    //           4. 在工厂模式,不需要检查 esd
    //           5. 通过 i2c 获得芯片 ID
    //           6. 如果能获得芯片 ID, 则获得工作状态计数:0x91, 如果没有改变,则需要复位
    //           7. 如果不能获得芯片 ID,则需要进行硬件复位了
    //               pinctrl 控制 TP 的 rst 脚进行复位
    //               恢复 TP 的工作状态
    // 然后启动 esd 检查工作队列
    fts_esdcheck_init();

	///////////////////////////////////////////////////////////
    // 使能 TP 中断    
    fts_irq_enable();
        enable_irq(ft_touch_irq);
        
    ////////////////////////////////////////////////////////////
    // 创建一个工作队列:
    //      先关中断,停 esd 检查工作队列
    //      通过 I2c 更新 TP/LCM 的 固件
    //      恢复中断,启去 esd 检查工作队列
    fts_ctpm_upgrade_init();

	//////////////////////////////////////////////////////
    // 创建一些 sys 节点用于测试
    fts_test_init(client);

杂项

TouchPanel A_B 协议
	Type A: 常按会一直报点 
	Type B: 常按只报一次点,过滤相同点

由于使用了通知链,所以休眠顺序为:屏-->TP
所以会有灭屏后,还会有短时间存在报点的问题,正常现象。

猜你喜欢

转载自blog.csdn.net/wangjun7121/article/details/88236079
MTK