Mtk Ft6306 touch 驱动

http://blog.youkuaiyun.com/sunweizhong1024/article/details/8572121

1、    MTk Touch 驱动程序

1.1、    MTK Touch 驱动的组成
Mtk  Touch  driver 驱动包括:Mtk platform 虚拟平台设备驱动、Module touch IC 驱动、Input subsystem。
Mtk platform 设备驱动是mtk为了兼容多个touch IC 驱动而设计出来的虚拟驱动,它会去遍历每一个touch  IC 驱动,直到其中一个初始化成功。
Linux input_subsystem是linux 的输入子系统,我们的输入设备都要通过这个子系统进行上报事件以及设置事件的类型。
 
图1 MTk Touch 架构图
1.2、    Platform 驱动
Platfiorm 驱动主要是负责mtk虚拟touch 平台的驱动的注册,执行probe函数遍历每一个具体的touch IC 驱动。
    Kernel/touchpanel/src/mtk_tpd.c
Platform 设备moudle_init 函数:

static int __init tpd_device_init(void) {
            printk("MediaTek touch panel driver init\n");
            if(platform_driver_register(&tpd_driver)!=0) {
        TPD_DMESG("unable to register touch panel driver.\n");
        return -1;
        }   
        return 0;

}
module_init(tpd_device_init)
上面的moduel_init首先加载的函数tpd_device_init 函数中调用platform_driver_register进行注册一个mtk_touch_driver 平台驱动。
其中注册的平台驱动tpd_driver定义如下:
static struct platform_driver tpd_driver = {
    .remove     = tpd_remove,
    .shutdown   = NULL,
    .probe      = tpd_probe,
    #ifndef CONFIG_HAS_EARLYSUSPEND
    .suspend    = NULL,
    .resume     = NULL,
    #endif
    .driver     = {
        .name = TPD_DEVICE,
    },
};

根据platform bus mathc的规则:driver_name 和device_name相同就会调用platform_drive 的probe函数。这里牵扯到Linux的设备模型知识,需要了解的人可以看下Linux platform bus。
#define TPD_DEVICE            "mtk-tpd"
Platform device 注册:retval = platform_device_register(&mtk_tpd_dev);
mtk_tpd_dev的定义如下:
static struct platform_device mtk_tpd_dev = {
    .name = "mtk-tpd",
    .id   = -1,
};
/mediatek/platform/mt6589/kernel/core/mt_devs.c
上面这个路径是mtk的板极支持的文件,很多板极的注册和初始化的动作都是放在上面的C文件里面的。
根据我上面所说的platform bus的match 规则,设备名字和驱动名字相同。进而就会调用
1.2.1、Platform 驱动入口probe函数
static int tpd_probe(struct platform_device *pdev) {
        int  touch_type = 1; // 0:R-touch, 1: Cap-touch
        int i=0;
      TPD_DMESG("enter %s, %d\n", __FUNCTION__, __LINE__); 
      /* Select R-Touch */
     // if(g_tpd_drv == NULL||tpd_load_status == 0) 
    if((tpd=(struct tpd_device*)kmalloc(sizeof(struct tpd_device), GFP_KERNEL))==NULL) return -ENOMEM;//分配一个Mtk tpd_device
    memset(tpd, 0, sizeof(struct tpd_device));

    /* allocate input device */
    if((tpd->dev=input_allocate_device())==NULL) { kfree(tpd); return -ENOMEM; }
  //上面是分配一个input 设备
    TPD_RES_X = simple_strtoul(LCM_WIDTH, NULL, 0);
    TPD_RES_Y = simple_strtoul(LCM_HEIGHT, NULL, 0);
  
    printk("mtk_tpd: TPD_RES_X = %d, TPD_RES_Y = %d\n", TPD_RES_X, TPD_RES_Y);
  
    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;
    /* struct input_dev dev initialization and registration */
    tpd->dev->name = TPD_DEVICE;
    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);
    set_bit(BTN_TOUCH, tpd->dev->keybit);
set_bit(INPUT_PROP_DIRECT, tpd->dev->propbit);
//上面都是input 设备事件类型的设置
#if 1    
  for(i = 1; i < TP_DRV_MAX_COUNT; i++)
    {
            /* add tpd driver into list */
        if(tpd_driver_list[i].tpd_device_name != NULL)//这里是在遍历mtk的tpd_driver_list里面的所有的驱动,判断名字是否为NULL,每一个module touch IC 驱动都会添加到这个静态数组里面
        {
            tpd_driver_list[i].tpd_local_init();
            //msleep(1);
            if(tpd_load_status ==1) {//这里我们会判断我们所遍历的每一个module IC 驱动的初始化函数。成功的话就会将tpd_load_status至1,所以我们就是通过这个值判断哪一个驱动的
                TPD_DMESG("[mtk-tpd]tpd_probe, tpd_driver_name=%s\n", tpd_driver_list[i].tpd_device_name);
                g_tpd_drv = &tpd_driver_list[i];
                break;
            }
        }    
  }
。。。。。。。。。。。。。。
。。。。。。。。。。。。。。
    #ifdef CONFIG_HAS_EARLYSUSPEND
    MTK_TS_early_suspend_handler.suspend = g_tpd_drv->suspend;
    MTK_TS_early_suspend_handler.resume = g_tpd_drv->resume;
register_early_suspend(&MTK_TS_early_suspend_handler);
//touch 的suspend应该属于eraly_suspend
    #endif          
#endif      
。。。。。。。。。。。。。。。。。。。。。。。。。。。
。。。。。。。。。。。。。。。。。。。。。。。。。。。
    if(input_register_device(tpd->dev))//将我们的touch以Input方式进行注册
        TPD_DMESG("input_register_device failed.(tpd)\n");
    else
            tpd_register_flag = 1;
    /* init R-Touch */
    #if 0
      if(touch_type == 0) 
      {
          g_tpd_drv->tpd_local_init();
      }    
        #endif
    if(g_tpd_drv->tpd_have_button)
    {
        tpd_button_init();
    }

    return 0;
}

1.3、    Ft6306 module driver
Ft6306是敦泰的Touch IC ,这个里面,我们可以进行IC的上电、设置中断、Update FW等动作。
Ft6306中首先执行的代码是:
static int __init tpd_driver_init(void) {
     printk("MediaTek FT5206 touch panel driver init\n");
     i2c_register_board_info(0, &ft5206_i2c_tpd, 1);
         if(tpd_driver_add(&tpd_device_driver) < 0)
             TPD_DMESG("add FT5206 driver failed\n");
     return 0;
 }
module_init(tpd_driver_init);
tpd_driver_init函数会注册一个I2C Touch设备、调用tpd_driver_add添加添加一个驱动,其实就是讲这个驱动添加到上面说的静态数组pd_driver_lis里面。
Tpd_driver_add函数定义如下:
int tpd_driver_add(struct tpd_driver_t *tpd_drv)
{
。。。。。。。。。。。。。。。。。。。。。。。。。
。。。。。。。。。。。。。。。。。。。。。。。。。    
for(i = 1; i < TP_DRV_MAX_COUNT; i++)
    {
        /* add tpd driver into list */
        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;
            #if 0
            if(tpd_drv->tpd_local_init()==0)
            {
                TPD_DMESG("load %s sucessfully\n", tpd_driver_list[i].tpd_device_name);
                g_tpd_drv = &tpd_driver_list[i];
            }
            #endif
            break;
        }
        if(strcmp(tpd_driver_list[i].tpd_device_name, tpd_drv->tpd_device_name) == 0)
        {
            return 1; // driver exist
        }
    }
    
    return 0;
}
上面会将我们的每一个注册的Moudle IC touch驱动进行添加到 tpd_driver_list数组中。添加进去后,我们就会调用tpd_local_init函数进行touch IC 的初始化。


1.3.1、Module tpd_local_init函数
static int tpd_local_init(void)
 {
    int i;
 
  TPD_DMESG("Focaltech FT5206 I2C Touchscreen Driver (Built %s @ %s)\n", __DATE__, __TIME__);
 
 
   if(i2c_add_driver(&tpd_i2c_driver)!=0)
       {
          TPD_DMESG("unable to add i2c driver.\n");
          return -1;
}
。。。。。。
}
/kernel/touchpanel/ft6106/ft5206_drive.c
上面是以I2C的方式注册FT 驱动。记得在前面我们有注册一个I2C 设备。I2C 总线也有一套自己的匹配方式,是通过id_table里面的值进行匹配的,当匹配成功就会调用I2c 驱动的probe函数。
 tpd_i2c_driver定义如下:
static struct i2c_driver tpd_i2c_driver = {
  .driver = {
     .name = TPD_DEVICE,
     .owner = THIS_MODULE,
  },
  .probe = tpd_probe,
  .remove = __devexit_p(tpd_remove),
  .id_table = ft5206_tpd_id,
  .detect = tpd_detect,
//  .address_data = &addr_data,
  .address_list = (const unsigned short*) forces,
 };

当我们匹配成功后,我们就会调用上面的tpd_probe函数。
1.3.1.1、module I2C probe函数
Tpd_probe函数是touch IC 的核心函数,在里面我们会进行上电、申请中断、设置GPIO等、Update FW、IC提供的控制 touch 的interface等。
tpd_probe函数定义如下:
static int __devinit tpd_probe(struct i2c_client *client, const struct i2c_device_id *id)
 {     
    int retval = TPD_OK;
    char data;
    i2c_client = client;
#if (defined(MT6575)||defined( MT6577) ||defined(CONFIG_ARCH_MT6589))
    //power on, need confirm with SA
    hwPowerOn(TPD_POWER_SOURCE_CUSTOM, VOL_2800, "TP");//这里是在上电,我在porting的过程中就遇到了上电没有成功,后来查看电路才上对Pin脚,下面会有touch 的电路图

    mt_set_gpio_mode(GPIO_CTP_RST_PIN, GPIO_CTP_RST_PIN_M_GPIO);//设置GPIO的工作模式
    mt_set_gpio_dir(GPIO_CTP_RST_PIN, GPIO_DIR_OUT);//将GPIO设置成out方向
    mt_set_gpio_out(GPIO_CTP_RST_PIN, GPIO_OUT_ONE);
    msleep(2);
。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
    }
    else if(data == 0x55)
    {
        sprintf(tpd_chip_name,"%s", "FT5x06");
    }

    tpd_load_status = 1;
    thread = kthread_run(touch_event_handler, 0, TPD_DEVICE);//这里是创建一个线程,我们会执行这个线程
    if (IS_ERR(thread))
    { 
        retval = PTR_ERR(thread);
        TPD_DMESG(TPD_DEVICE " failed to create kernel thread: %d\n", retval);
    }


上面创建的线程,我们会进行申请中断、读取坐标,上报坐位给上层使用。

 图2:touch 的电路图,我们上电的就是VGP4。



                                                        Author:hyde_sun
                                                        2013-2-5
根据提供的文件信息,我们可以确定文件内容涉及的中心知识点为FT6236U触屏驱动程序。FT6236U是来自敦泰科技(Goodix)的一款触控屏幕控制器(Touchscreen Controller),广泛应用于各种移动设备、平板电脑、导航系统以及各种嵌入式系统中。为了详细说明这一知识点,我们将从以下几个方面进行阐述: 1. FT6236U概述 FT6236U是一款高集成度的触控屏幕控制器芯片,支持多点触控功能,适用于电阻式和电容式触摸屏。该控制器提供了高速的响应速度和高精度的触控体验,同时具备低功耗特性,适合便携式电子产品使用。它通常通过I2C(Inter-Integrated Circuit)或SPI(Serial Peripheral Interface)总线与主控制器(如微控制器或应用处理器)通信。 2. FT6236U驱动程序的作用 驱动程序是操作系统和硬件设备之间的桥梁,它允许操作系统控制硬件设备,并向用户提供相应的接口。FT6236U驱动程序的主要作用包括: - 初始化触屏控制器,确保其正常工作。 - 管理触控数据的采集与处理,包括坐标数据的获取与过滤。 - 解析触控手势和多点触控信息,反馈给操作系统进行处理。 - 提供一系列API(Application Programming Interfaces)供应用程序调用,以实现触控功能。 - 适配不同操作系统(如Windows、Linux、Android等),确保FT6236U在各种平台上的兼容性。 3. 驱动开发与调试 驱动开发通常包括几个关键步骤,包括阅读硬件规格书、编程接口定义以及编写相应的驱动代码。对于FT6236U这样的触摸屏控制器,驱动开发可能需要关注以下几个方面: - 设备I/O地址和中断号的配置。 - 通过I2C/SPI等通信协议与控制器建立稳定的通信。 - 实现底层触控数据采集和预处理算法。 - 对于特定的操作系统,需要了解其驱动模型和编程接口,并确保驱动程序符合其驱动架构。 - 驱动程序需要在不同的硬件平台和操作系统版本上进行广泛的测试和调试,以确保其稳定性和兼容性。 4. FT6236U应用案例 FT6236U由于其高性能和低功耗的特点,在众多产品中得到应用。例如: - 智能手机和平板电脑中,实现流畅的手指触控体验。 - 导航系统中,提供精确的触控输入,便于用户操作。 - 各种家用电器和工业控制面板中,用作用户输入界面。 - 在教育、医疗、汽车等行业的设备中,为用户提供交互界面。 5. FT6236U驱动参考资料的重要性和获取方式 如文件标题所示,“FT6236U驱动参考资料.rar”很可能包含FT6236U控制器的技术规格书、数据手册、编程指南、示例代码以及可能的操作系统兼容性说明。这些资料对于开发者来说非常宝贵,因为它们不仅帮助开发者理解硬件的工作原理,也指导开发者如何开发和调试驱动程序。 在获取这些资料时,开发者一般会访问敦泰科技的官方网站,或者直接在FT6236U的购买渠道中寻找。除此之外,还可以通过开源社区、论坛以及专业的电子工程师网站寻找相关的开发文档和讨论。 通过以上几点分析,我们可以了解到FT6236U触屏控制器的重要性和其驱动程序开发的相关知识点。这些内容不仅对于硬件工程师在实际工作中具有指导意义,而且对于所有对触控技术感兴趣的IT专业人士来说,都是值得深入研究的宝贵资料。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值