MTK平台TP驱动框架分析

本文详细介绍了MTKTP驱动的移植与调试过程,包括硬件IO口配置、I2C通信、中断触发及数据上报等关键步骤。深入剖析了MTKTouch驱动组成及其在Linux环境下的工作原理,涵盖Mtkplatform设备驱动、ModuletouchIC驱动和Inputsubsystem的运作机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

<think>嗯,用户想了解MTK平台手机TP驱动的加载流程。首先,我得回忆一下MTK平台的整体架构。MTK的Android系统驱动通常在内核层,TP驱动应该属于Input子系统的一部分。用户可能是在开发或调试触摸屏时遇到了问题,需要了解驱动加载的各个阶段,以便排查故障或者进行定制开发。 首先,TP驱动的加载流程应该从内核启动开始,系统初始化时会加载各种驱动模块。MTK平台可能使用设备树(DTS)来描述硬件信息,所以驱动会和设备树中的节点匹配。接下来,驱动初始化的步骤可能包括probe函数,这里会配置GPIO、中断、注册输入设备等。 然后需要考虑用户空间的部分,比如HAL层和Android框架的交互,可能涉及配置文件如IDC(Input Device Configuration)和触摸固件的加载。另外,固件更新和校准流程也可能是驱动加载的一部分。 用户可能还关心调试方法,比如如何通过日志或工具检查驱动是否正常加载。需要分阶段讲解,从内核到用户空间,再到应用层,确保流程清晰。同时,结合之前的引用内容,用户提到启动流程分析对bringup有帮助,所以应该强调各个阶段的关键节点和可能的问题点。 需要注意的是,用户可能实际遇到的问题比如驱动加载失败、触摸无响应,所以在讲解流程时,可以指出常见的失败原因,比如设备树配置错误、中断冲突、电源管理问题等。此外,TP驱动的兼容性和不同型号的适配也可能影响加载流程,可能需要提及如何根据具体硬件调整驱动参数。 最后,生成相关问题时要围绕流程的深入分析、调试技巧、优化方法以及常见问题处理,帮助用户进一步探索解决方案。确保回答结构清晰,步骤明确,并引用相关的技术点,比如设备树、内核模块、HAL层等,以增强专业性。</think>### MTK平台TP驱动加载流程详解 MTK平台触摸屏(TP驱动加载流程可分为**内核驱动初始化**、**硬件抽象层交互**和**Android框架适配**三个阶段,以下是关键步骤分析: --- #### 一、内核驱动初始化阶段 1. **设备树(DTS)匹配** MTK平台使用设备树描述TP硬件参数(I2C地址、GPIO引脚、中断号等),驱动通过`compatible`属性与设备树节点匹配。例如: ```c &i2c3 { touchscreen@5d { compatible = "mediatek,ft6336"; reg = <0x5d>; interrupt-parent = <&pio>; interrupts = <135 IRQ_TYPE_EDGE_FALLING>; }; }; ``` 2. **驱动Probe函数** 匹配成功后执行`probe()`函数完成以下操作: - 初始化I2C通信协议 - 配置GPIO中断(如`request_threaded_irq()`) - 注册输入设备:`input_register_device()` - 创建sysfs调试节点(如`/sys/class/touchscreen/`) - 加载固件(部分TP需要独立固件文件) 3. **电源管理初始化** 通过`dev_pm_ops`结构体实现休眠/唤醒时的电源状态切换,例如关闭扫描频率进入低功耗模式。 --- #### 二、硬件抽象层交互(HAL层) 1. **Input子系统上报事件** 驱动通过`input_event()`上报坐标数据到`/dev/input/eventX`节点,事件类型包括: - `ABS_MT_POSITION_X/Y`(坐标) - `ABS_MT_TRACKING_ID`(多点触控ID) - `SYN_REPORT`(同步信号) 2. **IDC配置文件解析** Android系统通过`/vendor/usr/idc/`目录下的`.idc`文件定义设备属性,例如: ```ini touch.deviceType = touchScreen touch.orientationAware = 1 touch.filter.level = 2 ``` 3. **固件更新机制** 部分TP芯片需要运行时更新固件,通过`request_firmware()`从`/vendor/firmware/`加载`.bin`文件。 --- #### 三、Android框架适配 1. **InputReader处理数据流** `InputReader`线程从内核读取原始事件,进行坐标校准(通过`/system/usr/calibration`文件)和手势识别。 2. **SurfaceFlinger坐标映射** 根据屏幕旋转状态转换坐标系,例如将硬件坐标(1080x2400)转换为逻辑坐标(2400x1080)用于横屏显示。 3. **Vendor HIDL接口** MTK平台通过`vendor.mediatek.hardware.input@1.0`服务提供厂商定制功能,如手套模式灵敏度调节。 --- #### 典型问题排查点 1. **I2C通信失败** 使用`i2cdetect`工具检测设备地址是否响应[^1] 2. **中断未触发** 检查`/proc/interrupts`中TP中断计数是否增加 3. **坐标漂移** 验证`calibration`文件或重新执行`ts_calibrate` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

常怀安

您的打赏将是我继续创作的动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值