MTK平臺TP驅動框架分析

MTK TP驅動移植調試一般分爲五步:

1、硬件IO口配置;

2、TP驅動移植;

3、I2C通信;

4、中斷觸發;

5、數據上報;

MTK Touch 驅動的組成:

Mtk Touch driver 驅動包括:Mtkplatform 虛擬平臺設備驅動、Module touch IC 驅動、Inputsubsystem。

Mtk platform 設備驅動是mtk爲了兼容多個touch IC驅動而設計出來的虛擬驅動,它會去遍歷每一個touch IC驅動,直到其中一個初始化成功。

Linux input_subsystem是linux的輸入子系統,我們的輸入設備都要通過這個子系統進行上報事件以及設置事件的類型。

一、在LINUX啓動過程中,先註冊kernel-4.4/drivers/input/touchscreen/mediatek/目錄下的具體驅動(如msg2238_ilitek),在驅動tpd_driver_init函數裏調用tpd_driver_add(&tpd_device_driver)

把該tp驅動加入到一個靜態數組tpd_driver_list[i]中。 在kernel-4.4/drivers/input/touchscreen/mediatek/mtk_tpd.c中moduel_init首先加載的函數tpd_device_init 函數中

調用tpd_init_work_callback --> 然後platform_driver_register(&tpd_driver)註冊一個mtk_touch_driver平臺驅動driver --> mtk_touch_driver函數

的.of_match_table = touch_of_match的compatible = "mediatek,mt6739-touch"與在mt6739.dts註冊的設備device touch: touch compatible = “mediatek,mt6739-touch”;相同,就執行tpd_probe函數。

根據platform bus match的規則:driver_name 和device_name相同就會調用platform_driver 的probe函數。(這裏牽扯到Linux的設備模型知識,需要了解的人可以看下Linux platform bus。)

在tpd_probe函數中,調用tpd_get_gpio_info(pdev)函數解析dts參數,調用input_allocate_device()分配一個輸入設備,設置input 設備事件類型,

執行if(tpd_driver_list[i].tpd_device_name != NULL)//這裏是在遍歷mtk的tpd_driver_list裏面的所有的驅動,判斷名字是否爲NULL,每一個module touch IC 驅動都會添加到這個靜態數組裏面。

tpd_driver_list[i].tpd_local_init(); if(tpd_load_status ==1) {//這裏我們會判斷我們所遍歷的每一個module IC 驅動的初始化函數tpd_local_init(),該函數會註冊i2c驅動i2c_add_
driver(&tpd_i2c_driver),註冊成功會跟註冊的device匹配,匹配通過(name一致)然後probe成功的話就會將tpd_load_status變量置1,

所以我們就是通過這個值tpd_load_status判斷使用哪一個驅動的。然後調用g_tpd_drv = &tpd_driver_list[i]去執行具體的TP ic驅動。

具體TP ic驅動裏面,主要進行IC的上電、申請中斷號註冊中斷處理函數、Update FW等動作。

例如分析msg2238驅動:從mtk_tpd.c中匹配到具體的TP ic驅動之後,首先執行ilitek_drv_mtk.c中tpd_driver_init --> 執行i2c_register_board_info(I2C_BUS_ID, &i2c_tpd, 1);註冊i2c設備,

–> 執行tpd_driver_add(&tpd_device_driver)註冊驅動–> 執行tpd_local_init --> 執行i2c_add_driver(&tpd_i2c_driver)函數,其實就是將這個驅動添加到上面說的靜態數組tpd_driver_lis裏面,

–> 設備&i2c_tpd device的name:TP_IC_NAME和驅動tpd_i2c_driver的name:TP_IC_NAME一致,根據i2c驅動與設備匹配原則,就執行tpd_device_driver裏面的tpd_probe函數。

–> MsDrvInterfaceTouchDeviceSetIicDataRate(g_I2cClient, 100000); 設置i2c速率 --> ret = regulator_set_voltage(g_ReguVdd, 2800000, 2800000)上電

–> 然後執行MsDrvInterfaceTouchDeviceProbe函數(ilitek_drv_main.c) --> 然後執行DrvTouchDeviceRegisterFingerTouchInterruptHandler();(ilitek_drv_main.c)

–> 申請中斷request_threaded_irq (ilitek_drv_main.c)–> 註冊中斷處理函數_DrvFingerTouchInterruptHandler,(ilitek_drv_main.c)註冊中斷後,每次觸摸到TP就會產生硬件中斷,

調用到中斷處理函數_DrvFingerTouchInterruptHandler。–> 註冊完中斷後執行INIT_WORK(&_gFingerTouchWork, _DrvFingerTouchDoWork);初始化觸摸工作隊列_DrvFingerTouchDoWork;

---------檢測到有中斷到來時-----------

–> 執行_DrvHandleFingerTouch(); --> 執行_DrvSelfHandleFingerTouch();然後調用rc = IicReadData(SLAVE_I2C_ID_DWI2C, &pPacket[0], nReportPacketLength);讀取tp寄存器的數據:,

–> 並且通過input輸入子系統上報數據到安卓層,_DrvSelfHandleFingerTouch有執行iic讀取數據的操作:rc = IicReadData(SLAVE_I2C_ID_DWI2C, &pPacket[0], nReportPacketLength

二:中斷處理流程()

註冊中斷後,每次觸摸到TP就會產生硬件中斷,調用到中斷處理函數_DrvFingerTouchInterruptHandler,從中斷處理函數_DrvFingerTouchInterruptHandler,分析下TP的觸摸事件處理流程:

如果有觸摸動作,產生中斷( if (_gInterruptFlag == 1),然後disable_irq_nosync(_gIrq);//禁止中斷,無需進行同步,防止死鎖 --> 啓動工作隊列schedule_work(&_gFingerTouchWork);

–> _DrvFingerTouchDoWork --> 執行_DrvHandleFingerTouch(); --> 執行_DrvSelfHandleFingerTouch();然後調用rc = IicReadData(SLAVE_I2C_ID_DWI2C, &pPacket[0], nReportPacketLength);

讀取TP對應寄存器的數據。–> 調用input_report_key 上報虛擬按鍵信息,input_report_abs 上報相對座標信息 ,每次上報完都要調用input_sync(g_InputDevice);每個點上報後都需要同步

表示上報數據完成 -->調用DrvFingerTouchPressed(tInfo.tPoint[i].nX, tInfo.tPoint[i].nY, 1, i);收集手指按壓TP的數據信息,

調用DrvFingerTouchReleased收集釋放的動作信息(其中涉及多點觸摸協議(可百度瞭解),分A類和B類);

下面是Ft6xxx(敦泰的Touch IC)的一箇中斷處理流程,供參考:
二:中斷處理流程

註冊中斷後,每次觸摸到TP就會產生硬件中斷,調用到中斷處理函數tpd_eint_interrupt_handler
從中斷處理函數tpd_eint_interrupt_handler()分析下TP的觸摸事件處理流程

static void tpd_eint_interrupt_handler(void)
{
TPD_DEBUG_PRINT_INT;
tpd_flag = 1;
//喚醒內核進程touch_event_handler中的等待隊列
wake_up_interruptible(&waiter);
}

static int touch_event_handler(void *unused)
{
//設置Task 的狀態爲可中斷的等待狀態
set_current_state(TASK_INTERRUPTIBLE);
//滿足tpd_flag!=0 就喚醒隊列
wait_event_interruptible(waiter,tpd_flag!=0);
tpd_flag = 0; //改變條件
//設置Task 的狀態爲執行態
set_current_state(TASK_RUNNING);

//touchinfo 函數獲取手指觸摸TP的信息,譬如按下的手指數目,每個點的座標
if (tpd_touchinfo(&cinfo, &pinfo))

//tpd_down 上報按下的座標信息
tpd_down(cinfo.Point[i].X, cinfo.Point[i].Y, i);
input_report_key(tpd->dev, BTN_TOUCH, 1);
input_report_abs(tpd->dev, ABS_MT_TOUCH_MAJOR, 20);
input_report_abs(tpd->dev, ABS_MT_POSITION_X, x);
input_report_abs(tpd->dev, ABS_MT_POSITION_Y, y);
//tpd_up 上報離開的信息
tpd_up(map_x, map_y, 0);
input_mt_sync //單點同步,每個點上報後都需要同步
input_sync(tpd->dev); //每一次操作結束後的同步,不論是多點還是單點值,

這裏面,我們看到幾個新函數
tpd_calibrate,tpd_down,tpd_up
主要是通過傳入座標值,對TOUCH的down和up值做處理。
void tpd_down(int raw_x, int raw_y, int x, int y, int p) {
if(tpd && tpd->dev && tpd_register_flag1) {
input_report_abs(tpd->dev, ABS_PRESSURE, p/PRESSURE_FACTOR);
input_report_key(tpd->dev, BTN_TOUCH, 1);
input_report_abs(tpd->dev, ABS_MT_TOUCH_MAJOR, p/PRESSURE_FACTOR);
input_report_abs(tpd->dev, ABS_MT_WIDTH_MAJOR, p/PRESSURE_FACTOR);
input_report_abs(tpd->dev, ABS_MT_POSITION_X, x);
input_report_abs(tpd->dev, ABS_MT_POSITION_Y, y);
input_mt_sync(tpd->dev);
TPD_DEBUG(“D[M M M]\n”, x, y, p);
TPD_EM_PRINT(raw_x, raw_y, x, y, p, 1);
}
}
void tpd_up(int raw_x, int raw_y, int x, int y, int p) {
if(tpd && tpd->dev && tpd_register_flag
1) {
input_report_abs(tpd->dev, ABS_PRESSURE, 0);
input_report_key(tpd->dev, BTN_TOUCH, 0);
input_report_abs(tpd->dev, ABS_MT_TOUCH_MAJOR, 0);
input_report_abs(tpd->dev, ABS_MT_WIDTH_MAJOR, 0);
input_report_abs(tpd->dev, ABS_MT_POSITION_X, x);
input_report_abs(tpd->dev, ABS_MT_POSITION_Y, y);
input_mt_sync(tpd->dev);
TPD_DEBUG(“U[M M M]\n”, x, y, 0);
TPD_EM_PRINT(raw_x, raw_y, x, y, p, 0);
}
}
這裏面主要通過驅動linux的輸入設備驅動函數input_report_abs, input_report_key把linux輸入設備的座標和輸入設備事件提交到linux內核裏面去。

其他:虛擬按鍵在dts配置,在ilitek_drv_common.h中有對應定義:
#ifdef CONFIG_TP_HAVE_KEY
#define TOUCH_KEY_MENU (139) //229
#define TOUCH_KEY_HOME (172) //102
#define TOUCH_KEY_BACK (158)
#define TOUCH_KEY_SEARCH (217)

#define MAX_KEY_NUM (4)
#endif //CONFIG_TP_HAVE_KEY
相關的一些宏控:
打開固件自動升級:CONFIG_UPDATE_FIRMWARE_BY_SW_ID=y
打開TP手勢喚醒:CONFIG_ENABLE_GESTURE_WAKEUP=y

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章