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

  • 3
    点赞
  • 41
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
mtk平台lcd驱动框架详解可以从Mtkfb.c文件开始解释。在该文件中,我们可以看到定义了一个名为mtkfb_driver的结构体变量,该变量是一个platform_driver结构体类型,其中包含了一些成员函数的指针,如probe、remove、suspend、resume和shutdown等。这些函数是用来处理与MTK平台上的LCD显示相关的操作。例如,当系统探测到MTK平台上的LCD设备时,probe函数会被调用来初始化LCD驱动;当系统要移除LCD设备时,remove函数会被调用来卸载LCD驱动。 除了上述的成员函数指针外,mtkfb_driver结构体变量还包含了一些其他成员,如name、pm和bus等。其中,name成员指定了驱动的名称,pm成员用于指定与电源管理相关的操作函数,而bus成员则指定了驱动所属的总线类型。 需要注意的是,以上只是mtk平台上lcd驱动框架概述,具体实现细节可能因不同的平台而有所不同。此外,本文可能存在错误或不够深入,请参考相关资料以获取更详细的信息。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [MTK平台LCD驱动框架详解(一)](https://blog.csdn.net/xuan_h/article/details/38519975)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

零意@

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

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

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

打赏作者

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

抵扣说明:

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

余额充值