一,TP驱动代码的组成
MTK平台TP驱动主要包括两处文件:
1,kernel-3.18\drivers\input\touchscreen\mediatek\mtk_tpd.c
平台设备驱动,主要为了兼容多个不同的TP驱动IC,它会去遍历每一个编译并添加进 tpd_driver_list 中的IC驱动,直到其中一个初始化成功。
2,kernel-3.18\drivers\input\touchscreen\mediatek\XXX
XXX文件为具体的TP驱动文件,如:汇鼎,思立微,敦泰 等等,一般由IC厂提供,然后移植到各平台的代码中(移植方法后面会讲到),主要实现了对IC的上电和初始化,注册输入设备,获取并上报数据等。
二,mtk_tpd.c分析
首先在装载入口函数 tpd_device_init 中创建了一个工作队列,调用 tpd_init_work_callback 函数,用于注册平台总线。
static struct platform_driver tpd_driver = {
.remove = tpd_remove,
.shutdown = NULL,
.probe = tpd_probe,
.driver = {
.name = TPD_DEVICE,
.pm = &tpd_pm_ops,
.owner = THIS_MODULE,
.of_match_table = touch_of_match, //匹配设备树
},
};
/* called when loaded into kernel */
static void tpd_init_work_callback(struct work_struct *work)
{
TPD_DEBUG("MediaTek touch panel driver init\n");
if (platform_driver_register(&tpd_driver) != 0) //注册平台总线驱动tpd_driver
TPD_DMESG("unable to register touch panel driver.\n");
}
int tpd_device_init(void)
{
int res = 0;
//创建并初始化一个工作队列,调用tpd_init_workqueue回调函数
tpd_init_workqueue = create_singlethread_workqueue("mtk-tpd");
INIT_WORK(&tpd_init_work, tpd_init_work_callback);
res = queue_work(tpd_init_workqueue, &tpd_init_work); //将设备入队
if (!res)
pr_err("tpd : touch device init failed res:%d\n", res);
return 0;
}
EXPORT_SYMBOL(tpd_device_init);
与设备树中的device匹配成功后,调用 tpd_probe 方法
static const struct file_operations tpd_fops = {
/* .owner = THIS_MODULE, */
.open = tpd_misc_open, //tp杂类设备open
.release = tpd_misc_release,//tp杂类设备注销
.unlocked_ioctl = tpd_unlocked_ioctl,//使用ioctl操作tpd杂类设备
#ifdef CONFIG_COMPAT
.compat_ioctl = tpd_compat_ioctl,//调用tpd_unlocked_ioctl中的TPD_GET_FILTER_PARA命令
#endif
};
static struct miscdevice tpd_misc_device = {
.minor = MISC_DYNAMIC_MINOR, //次设备号
.name = "touch", //设备名称
.fops = &tpd_fops, //杂类设备操作集合
};
/* touch panel probe */
static int tpd_probe(struct platform_device *pdev)
{
int touch_type = 1; /* 0:R-touch, 1: Cap-touch */ //选择电阻屏或电容屏
int i = 0;
#ifndef CONFIG_CUSTOM_LCM_X
#ifdef CONFIG_LCM_WIDTH
unsigned long tpd_res_x = 0, tpd_res_y = 0;
int ret = 0;
#endif
#endif
TPD_DMESG("enter %s, %d\n", __func__, __LINE__);
if (misc_register(&tpd_misc_device)) //把tpd作为misc杂类设备进行注册,其实就是一个封装过的字符设备
pr_err("mtk_tpd: tpd_misc_device register failed\n");
tpd_get_gpio_info(pdev); //获取gpio配置信息
tpd = kmalloc(sizeof(struct tpd_device), GFP_KERNEL); //分配一个mtk_tpd_device
if (tpd == NULL)
return -ENOMEM;
memset(tpd, 0, sizeof(struct tpd_device));
/* allocate input device */
tpd