Mtk touch panel驱动/TP驱动详解
1、
1.1、 MTKTouch 驱动的组成
Mtk Touch driver 驱动包括:Mtkplatform 虚拟平台设备驱动、Module touch IC 驱动、Inputsubsystem。
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 driverinit\n");
if(platform_driver_register(&tpd_driver)!=0){
TPD_DMESG("unable to register touch paneldriver.\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,
#ifndefCONFIG_HAS_EARLYSUSPEND
.suspend =NULL,
.resume = NULL,
#endif
.driver = {
.name = TPD_DEVICE,
},
};
根据platform bus mathc的规则:driver_name和device_name相同就会调用platform_drive的probe函数。这里牵扯到Linux的设备模型知识,需要了解的人可以看下Linux platformbus。
#defineTPD_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__);
//if(g_tpd_drv == NULL||tpd_load_status ==0)
if((tpd=(struct tpd_device*)kmalloc(sizeof(struct tpd_device),GFP_KERNEL))==NULL) return -ENOMEM;//分配一个Mtktpd_device
memset(tpd,0, sizeof(struct tpd_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;
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++)
{
if(tpd_driver_list[i].tpd_device_name !=NULL)//这里是在遍历mtk的tpd_driver_list里面的所有的驱动,判断名字是否为NULL,每一个moduletouch IC 驱动都会添加到这个静态数组里面
{
tpd_driver_list[i].tpd_local_init();
//msleep(1);
if(tpd_load_status ==1) {//这里我们会判断我们所遍历的每一个moduleIC驱动的初始化函数。成功的话就会将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;
}
}
}
。。。。。。。。。。。。。。
。。。。。。。。。。。。。。
#ifdefCONFIG_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;
#if0
if(touch_type ==0)
{
g_tpd_drv->tpd_local_init();
}
#endif
if(g_tpd_drv->tpd_have_button)
{
tpd_button_init();
}
return0;
}
1.3、 Ft6306module driver
Ft6306是敦泰的Touch IC ,这个里面,我们可以进行IC的上电、设置中断、UpdateFW等动作。
Ft6306中首先执行的代码是:
static int __init tpd_driver_init(void) {
printk("MediaTek FT5206 touch panel driverinit\n");
i2c_register_board_info(0, &ft5206_i2c_tpd,1);
if(tpd_driver_add(&tpd_device_driver) <0)
TPD_DMESG("add FT5206 driverfailed\n");
return0;
}
module_init(tpd_driver_init);
tpd_driver_init函数会注册一个I2CTouch设备、调用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++)
{
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
}
}
return0;
}
上面会将我们的每一个注册的Moudle IC touch驱动进行添加到tpd_driver_list数组中。添加进去后,我们就会调用tpd_local_init函数进行touch IC的初始化。
1.3.1、Module tpd_local_init函数
static int tpd_local_init(void)
{
inti;
TPD_DMESG("Focaltech FT5206 I2C TouchscreenDriver (Built %s @ %s)\n", __DATE__, __TIME__);
if(i2c_add_driver(&tpd_i2c_driver)!=0)
{
TPD_DMESG("unable to add i2cdriver.\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等、UpdateFW、IC提供的控制 touch 的interface等。
tpd_probe函数定义如下:
static int __devinit tpd_probe(struct i2c_client *client, conststruct i2c_device_id *id)
{
int retval =TPD_OK;
chardata;
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 kernelthread: %d\n", retval);
}
上面创建的线程,我们会进行申请中断、读取坐标,上报坐位给上层使用。(这部分最重要的东西作者你居然就这样一句话给跳过了,无语无语,从上边跟到这里不就是为了最后这部分代码里实现的内容。然后再去网上找发现关于这部分的资料还真少,这里我整理了一下这边导师做的归纳之后奉献出来)
二:中断处理流程
注册中断后,每次触摸到TP就会产生硬件中断,调用到中断处理函数tpd_eint_interrupt_handler
从中断处理函数tpd_eint_interrupt_handler()分析下TP的触摸事件处理流程
static voidtpd_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); //每一次操作结束后的同步,不论是多点还是单点值,
图2:touch 的电路图,我们上电的就是VGP4。
Mtk touch panel驱动/TP驱动详解相关推荐
- MTK 驱动(64)---Mtk touch panel驱动/TP驱动详解
Mtk touch panel驱动/TP驱动详解 TP还算是比LCM好理解的多. 在启动过程中,先注册/mediatek/custom/command/kernel/touchpanel目录下的具体驱 ...
- STM32L475 SPI驱动LCD ST7789V2详解
概述 最近在学习正点原子潘多拉开发板,在此结合原子哥的代码, 对SPI驱动LCD做一个详细介绍. TFTLCD 和 SPI TFTLCD介绍 TFT-LCD 即薄膜晶体管液晶显示器.其英文全称为:Th ...
- 9、Windows驱动开发技术详解笔记(5) 基本语法回顾
5.在驱动中获取系统时间 1)获取启动毫秒数 在ring3 我们可以通过一个GetTickCount 函数来获得自系统启动开始的毫秒数,在ring0也有一个与之对应的KeQueryTickCount ...
- 15、Windows驱动开发技术详解笔记(11) 基本概念
9.Windows驱动程序的入口函数规定为_DriverEntry@8,所以用C++编写时要用extern. 驱动程序中,不能使用编译器运行时函数,甚至C语言中的malloc,C++的new函数都不能 ...
- 《Windows驱动开发技术详解》学习笔记
Abstract 如果推荐 Windows 驱动开发的入门书,我强烈推荐<Windows驱动开发技术详解>.但是由于成书的时间较早,该书中提到的很多工具和环境都已不可用或找不到,而本文 ...
- linux驱动之总线详解
linux驱动 第一章 linux驱动之设备与驱动 第二章 linux驱动之设备树与GPIO子系统 linux驱动之总线详解 linux驱动 一.总线bus 1.bus在linux中文件结构 2.bu ...
- c语言windows驱动编程入门,Windows驱动开发技术详解 PDF扫描版[175MB]
Windows驱动开发技术详解由浅入深.循序渐进地介绍了windows驱动程序的开发方法与调试技巧.本书共分23章,内容涵盖了windows操作系统的基本原理.nt驱动程序与wdm驱动程序的构造.驱动 ...
- 激光二极管驱动电路图大全(六款激光二极管驱动电路设计原理图详解) - 全文
激光二极管驱动电路图大全(六款激光二极管驱动电路设计原理图详解) - 全文 来源:网络整理 作者:2018年03月01日 14:36 1 分享 订阅 关键词:驱动电路激光二极管 激光二极管驱动电路图( ...
- 驱动开发函数详解之Wdm
驱动开发函数详解之Wdm 前言 IRP(I/O Request Package) == 输入输出请求包 上层应用程序需要访问底层输入输出设备时,发出I/O请求,系统会把这些请求转化为IRP数据,不同的 ...
- linux小红帽系统装打印机驱动,Linux系统详解 第三篇:红帽RHEL的安装
Linux系统详解 第二篇:红帽RHEL的安装 前言: 本系列文章取材广泛,有来自于互联网的,有来自教科书的,有来自自己的笔记的,也有来自自己对Linux的经验积累的.此系列的文章都是经过长时间的整理 ...
最新文章
- Spring常见问题
- MySQL之单表查询、多表查询(一)
- IntelliJ中的远程调试Wildfly应用程序
- 在MSF中怎么区分易混淆的工作项类型:Bug、风险和问题(我个人的理解)
- python注销代码_django用户注册、登录、注销和用户扩展的示例
- python回归分析预测模型_在Python中如何使用Keras模型对分类、回归进行预测
- windows环境下 安装gcc
- Java写播放器好写吗_java写mp3播放器
- python画超长图-python—networkx:求图的平均路径长度并画出直方图
- 一道面试题引发的pythonic
- java 元胞自动机_元胞自动机 Java实现
- dorado java_[Java教程]dorado 7 使用总结
- tomcat之servlet容器
- kali linux 2020.4 自带浏览器英文改中文
- 练习使用firewalld的masquerade和nat功能
- Markdown|书单
- 微信又因夜间模式上热搜,我们又成为了谣言的传播者
- 我能等待。。。。。。
- 发布一个JINI服务
- IAR for ARM系列教程(三)_菜单(Ⅰ)