一:基础知识
Kernel 通过input 子系统与Android交互,每当我们点击屏幕或抬起都会产生中断,
每当kernel收到中断会通过i2c总线读取TP控制器产生的坐标数据,kernel就会通过input系统上报给android层, android层会完成相应的动作。
1. 硬件管脚:
SCL0: IIC 时钟引脚
SDA0:IIC数据引脚
RST: 复位引脚
EINT: IIC 中断引脚,触摸事件通过IIC 贯穿到系统
2. TP 增加驱动原理
TMK 增加驱动到静态数组 tpd_driver_list 数组中
static struct tpd_driver_t tpd_device_driver = {
.tpd_device_name = "FT5x0x",
.tpd_local_init = tpd_local_init,
};
module_init(tpd_driver_init)--->tpd_driver_add(&tpd_device_driver)
kernel-3.18/drivers/input/touchscreen/mediatek/mtk_tpd.c TP 设备加载、卸载和平台总线注册
运行 tpd_probe
static int tpd_probe(struct platform_device *pdev)
{
...
/* 全局数组tpd_driver_lsit[i]中的tp驱动依次进行如下操作 ,遍历整个数组
执行tp驱动中的tpd_local_init()接口,此接口主要是对tpd_i2c_driver进行i2c
总线的注册,匹配成功后执行tpd_i2c_driver中的probe ,这个probe比较重要,
其中系统会跟TP进行一次i2c通信,如果成功则说明找到了这个驱动,根据
此,可以兼容多款不同IC的TP设备* /
for (i = 1; i < TP_DRV_MAX_COUNT; i++) {
/* add tpd driver into list */
if (tpd_driver_list[i].tpd_device_name != NULL) {
//运行驱动中i2c_add_driver(&tpd_i2c_driver) -->tpd_probe 读取成功则全局 tpd_load_status设置为1 ,这可以兼容不同TP
tpd_driver_list[i].tpd_local_init();
/* msleep(1); */
if (tpd_load_status == 1) { 如果上面的i2c总线注册成功,则将tpd_load_status置位
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]; //并将g_tpd_drv指向这个驱动
break;
}
}
}
...
if(input_register_device(tpd->dev)) //向输入子系统注册输入设备
...
}
二:从零添加新TP
1. 修改kernel-3.18/arch/arm/configs/hys6737m_35_m0_debug_defconfig
kernel-3.18/arch/arm/configs/hys6737m_35_m0_defconfig
-CONFIG_TOUCHSCREEN_MTK_GT1151=y
+CONFIG_TOUCHSCREEN_MTK_FT6X36=y //打开指定的tp,关闭其他的
2. 修改 device/teksun/hys6737m_35_m0/ProjectConfig.mk
+CUSTOM_KERNEL_TOUCHPANEL = ft6x36 //修改为指定tp
3. 添加驱动代码,把ft6x36放到 kernel-3.18/drivers/input/touchscreen/mediatek/ 中
对TP功能进行修改,分辨率,等。
有dts 的需要修改kernel-3.18/arch/arm/boot/dts/hys6737m_35_m0.dts
- tpd-resolution = <720 1280>;
- use-tpd-button = <0>;
- tpd-key-num = <3>;
- tpd-key-local= <139 172 158 0>;
- tpd-key-dim-local = <90 883 100 40 230 883 100 40 370 883 100 40 0 0 0 0>;
+ tpd-resolution = <480 854>;
+ use-tpd-button = <1>;
+ tpd-key-num = <2>;
+ tpd-key-local= <139 158 0 0>;
+ tpd-key-dim-local = <160 2100 100 40 570 2100 100 40 0 0 0 0 0 0 0 0>;
4. kernel-3.18/drivers/input/touchscreen/mediatek/Kconfig 添加:
+config TOUCHSCREEN_MTK_FT6X36
+ bool "FT6X36 for Mediatek package"
+ default n
+ help
+ Say Y here if you have FT6X36 touch panel.
+
+ If unsure, say N.
+
+ To compile this dirver as a module, choose M here: the
+ module will be called.
+
5. 在 kernel-3.18\drivers\input\touchscreen\mediatek\Makefile 添加:
+obj-$(CONFIG_TOUCHSCREEN_MTK_FT6X36) += ft6x36/
三:TP兼容
不同ic的tp模组做兼容
在 /kernel-3.18/arch/arm/configs/hys6737m_35_m0_debug_defconfig
kernel-3.18/arch/arm/configs/hys6737m_35_m0_defconfig 配置要增加的IC驱动,
如 CONFIG_TOUCHSCREEN_MTK_FT6X36=y CONFIG_TOUCHSCREEN_MTK_ICN8711=y
TP进行一次i2c通信,成功则说明找到了这个驱动
相同ic的tp模组做兼容
通过线距兼容2种gsl1680TP ,原理是不同的屏长 ,线距 不一样,i2c通信 2次同的数据不一样
dts .在dws 配置
Slave Device Channel Device Address
CAP_TOUCH I2C_CHANNEL_1 0x38
(codegen.dws编译生成)
./out/target/product/hys6737m_35_m0/obj/KERNEL_OBJ/arch/arm/boot/dts/cust.dtsi
&i2c1 { //在那路I2上挂载设备
#address-cells = <1>;
#size-cells = <0>;
cap_touch@38 {
compatible = "mediatek,cap_touch"; //设备配备Ic驱动 重要
reg = <0x38>; //可以随便配置
status = "okay";
};
}
为了兼容其他IP 一般在probe 强制转换成自己的device address 如
敦太tp
if(i2c_client->addr != 0x38)
{
i2c_client->addr = 0x38;
TPD_DMESG("set i2c_client->addr = 0x%x\n",i2c_client->addr);
}
ICN8711 TP
#define ICN85XX_NORMAL_IIC_ADDR (0x90>>1)
i2c_client = client;
i2c_client->addr=ICN85XX_NORMAL_IIC_ADDR;
TP IC 地址 7为地址 软件合成八位 ,最后一位表示读下位
1. 思立微的tp:gsl915 0x40
2. 汇顶的tp: GT5668 0x5d (0xba>>1)
3. 敦太tp: FT6X36 0x38 (0x70>>1)
4. ICN8711: 0x48 (0x90>>1)
四:TP附加功能
ps功能:贴脸灭屏
#define TPD_PROXIMITY
#ifdef TPD_PROXIMITY
#include "alsps.h"
#endif
#ifdef TPD_PROXIMITY
{
obj_ps.polling = 1; //0--interrupt mode;1--polling mode;
obj_ps.sensor_operate = tpd_ps_operate;
if ((err = hwmsen_attach(ID_PROXIMITY, &obj_ps)))
{
TPD_DEBUG("hwmsen attach fail, return:%d.", err);
}
}
#endif
手势唤醒
TPD_SLIDE_WAKEUP
虚拟按键
dts修改:
#define KEY_BACK 158 /* AC Back */
#define KEY_HOME 172 /* AC Home */
#define KEY_MENU 139 /* Menu */
&touch {
tpd-resolution = <480 854>; //tp分辨率
use-tpd-button = <1>; //tp虚拟按键使能
tpd-key-num = <3>; //tp虚拟按键个数
tpd-key-local=
tpd-key-dim-local = <80 1000 100 40 240 1000 100 40 400 1000 100 40 0 0 0 0>; //3个虚拟按键参数(第4个为0)4*4(x,y,weith,height)
tpd-max-touch-num = <5>; //5点触控
tpd-filter-enable = <1>; //tp过滤器使能
tpd-filter-pixel-density = <124>; //tp过滤器像素密度
tpd-filter-pixel-density = <124>; //tp过滤器像素密度
tpd-filter-custom-prameters = <0 0 0 0 0 0 0 0 0 0 0 0>;
tpd-filter-custom-speed = <0 0 0>;
pinctrl-names = "default", "state_eint_as_int", "state_eint_output0", "state_eint_output1", 、//TP GPIO
"state_rst_output0", "state_rst_output1";
pinctrl-0 = <&CTP_pins_default>;
pinctrl-1 = <&CTP_pins_eint_as_int>;
pinctrl-2 = <&CTP_pins_eint_output0>;
pinctrl-3 = <&CTP_pins_eint_output1>;
pinctrl-4 = <&CTP_pins_rst_output0>;
pinctrl-5 = <&CTP_pins_rst_output1>;
status = "okay";
};
驱动中修改
#define TPD_RES_X 480
#define TPD_RES_Y 854
#define TPD_HAVE_BUTTON // if have virtual key,need define the MACRO
#define TPD_KEY_COUNT 3 // 4
#define TPD_BUTTON_HEIGH (60) //100
#define TPD_KEYS {KEY_MENU, KEY_HOMEPAGE, KEY_BACK}
#define TPD_KEYS_DIM {{90,1000,80,TPD_BUTTON_HEIGH},{240,1000,80,TPD_BUTTON_HEIGH},{400,1000,80,TPD_BUTTON_HEIGH}}
tp翻转180度
./kernel-3.18/drivers/input/touchscreen/mediatek/ft6x36/focaltech_core.c
#define CONFIG_TPD_ROTATE_180
可以按下面修改
#if defined(CONFIG_TPD_ROTATE_90) || defined(CONFIG_TPD_ROTATE_270) || defined(CONFIG_TPD_ROTATE_180)
static void tpd_swap_xy(int *x, int *y)
{
int temp = 0; temp = *x; *x = *y; *y = temp;
}
static void tpd_rotate_90(int *x, int *y)
{
*x = TPD_RES_X1 + 1 - *x;
*x = (*x * TPD_RES_Y1) / TPD_RES_X1;
*y = (*y * TPD_RES_X1) / TPD_RES_Y1;
tpd_swap_xy(x, y);
}
static void tpd_rotate_180(int *x, int *y)
{
*y = TPD_RES_Y1 + 1 - *y;
*x = TPD_RES_X1 + 1 - *x;
}
static void tpd_rotate_270(int *x, int *y)
{
*y = TPD_RES_Y1 + 1 - *y;
*x = (*x * TPD_RES_Y1) / TPD_RES_X1;
*y = (*y * TPD_RES_X1) / TPD_RES_Y1;
tpd_swap_xy(x, y);
}
static void tpd_down(int x, int y, int p, int id)
{
#if defined(CONFIG_TPD_ROTATE_90)
tpd_rotate_90(&x, &y);
#elif defined(CONFIG_TPD_ROTATE_270)
tpd_rotate_270(&x, &y);
#elif defined(CONFIG_TPD_ROTATE_180)
tpd_rotate_180(&x, &y);
#endif
input_report_abs(tpd->dev, ABS_MT_TRACKING_ID, id);
printk("%s x:%d y:%d p:%d\n", __func__, x, y, p);
input_report_key(tpd->dev, BTN_TOUCH, 1);
input_report_abs(tpd->dev, ABS_MT_TOUCH_MAJOR, 1);
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);
}
}
static void tpd_up(int x, int y)
{
#if defined(CONFIG_TPD_ROTATE_90)
tpd_rotate_90(&x, &y);
#elif defined(CONFIG_TPD_ROTATE_270)
tpd_rotate_270(&x, &y);
#elif defined(CONFIG_TPD_ROTATE_180)
tpd_rotate_180(&x, &y);
#endif
printk("%s x:%d y:%d\n", __func__, x, y);
input_report_key(tpd->dev, BTN_TOUCH, 0);
input_mt_sync(tpd->dev);
}
打开ESD
#define FT_ESD_PROTECT
五:TP调试方法
TP .一般修改是I2c地址,上电压,复位时序。中断过程,上报过程
1 检查硬件
用万用表测量6个引脚的电压:
正常工作电压 休眠电压
INT 1.8V 0V
RST 1.8V 1.8V
VDD 2.8V 2.8V
SDA 1.8V 1.8V
SCL 1.8V 1.8V
GND 0V 0V
通过[万用表]查看中断脚有无中断 - 实测可以
通过[万用表]查看TP的GND是否与主板的GND导通
通过[示波器]查看sda有无数据波形
2 通过i2驱动名字 查找设备节点
static struct i2c_driver tpd_i2c_driver = {
.driver = {
.name = "fts",
}
cat /sys/bus/i2c/devices/i2c-1/1-0038/name
cat /sys/devices/bus.2/11008000.I2C1/i2c-1/1-0038/name
ls -l /sys/bus/i2c/drivers
是否有fts文件夹
3. 开启 log 查看 tp型号 。函数是否有调用
4. 查看tp报点 /dev/input/event2 //司机生成的节点
2.1 驱动中有打印的话:
cat /proc/kmsg | grep "tpd"
2.2 可以直接从input设备节点/dev/input/event?读取
getevent -i
add device 3: /dev/input/event2
bus: 0000
vendor 0000
product 0000
version 0000
name: "mtk-tpd"
location: ""
id: ""
version: 1.0.1
events:
KEY (0001): 008b 009e 00ac 014a //虚拟按键
ABS (0003): 0000 : value 0, min 0, max 480, fuzz 0, flat 0, resolution 48
0001 : value 0, min 0, max 854, fuzz 0, flat 0, resolution 85
0018 : value 0, min 0, max 255, fuzz 0, flat 0, resolution 0
0030 : value 0, min 0, max 100, fuzz 0, flat 0, resolution 0
0031 : value 0, min 0, max 100, fuzz 0, flat 0, resolution 0
0035 : value 0, min 0, max 480, fuzz 0, flat 0, resolution 0
0036 : value 0, min 0, max 854, fuzz 0, flat 0, resolution 0
0039 : value 0, min 0, max 10, fuzz 0, flat 0, resolution 0
getevent -t /dev/input/event2 (event?,用[getevent -i] 查看)
-- 查看到的是原始数据,看不出坐标点,只能看出有无上报
5. 查看TP虚拟坐标
cat /sys/board_properties/virtualkeys.mtk-tpd
0x01:139:90:1000:80:60:0x01:172:240:1000:80:60:0x01:158:400:1000:80:60
六:案例分析
案例一: tp虚拟按键无功能 - dts中配置有误
现象:
平台:
排查过程:
修改:
案例二: tp无上报 - gpio 引脚 ,电压引脚错误 i2c地址 - 八位地址与七位地址 - dws写7位地址
现象:
平台:
排查过程:
修改:
案例三: tp开机 休眠唤醒 重启 - 修改休眠唤醒的 tpd_suspend 或者 关防静电的宏
现象:
平台:
排查过程:
修改:
案例四: TP 有功能 上报点不对
现象:
平台:
排查过程:
修改: FAR支持 ,修改固件
案例五: TP 有功能 有无点现象
现象:
平台:
排查过程:
修改: 修改DMA传 。固件初始应FIFO传输 ,MTK FIFO传只能连续传16个字节,大于要用DMA传
案例六: TP 虚拟按键无功能
现象: 开始 一批虚拟按键有功能,后一批TP无虚拟按键
平台:MT6737m
排查过程:
修改: TP虚拟按键块和LCD的地连在一起。贴高温胶纸防止短接。
七:TP流程分析