Mtk Ft6306 touch 驅動

Linux Tt6306 Touch 驅動
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


發佈了18 篇原創文章 · 獲贊 11 · 訪問量 37萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章