msm8953 android8.1平台GT9xx移植
首先向FAE要GT9xx的驱动包
将驱动拷贝到kernel/msm-4.9/drivers/input/touchscreen/gt9xx ,如下:
1、添加驱动编译并去掉gt9xx之外的tp驱动,如下:
kernel/msm-4.9/arch/arm64/configs/GM620S-perf_defconfig
CONFIG_INPUT_JOYSTICK=y
#kangting modify start
-CONFIG_TOUCHSCREEN_MSG28XX=y
+#CONFIG_TOUCHSCREEN_MSG28XX=y
+CONFIG_TOUCHSCREEN_GT9XX=y
+CONFIG_TOUCHSCREEN_GT9XX_TOOL=n
+CONFIG_TOUCHSCREEN_GT9XX_UPDATE=n
#kangting modify end
CONFIG_INPUT_TOUCHSCREEN=y
CONFIG_INPUT_MISC=y
kernel/msm-4.9/arch/arm64/configs/GM620S_defconfig
# CONFIG_INPUT_MOUSE is not set
CONFIG_INPUT_JOYSTICK=y
#kangting modify start
-CONFIG_TOUCHSCREEN_MSG28XX=y
+#CONFIG_TOUCHSCREEN_MSG28XX=y
+CONFIG_TOUCHSCREEN_GT9XX=y
+CONFIG_TOUCHSCREEN_GT9XX_TOOL=n
+CONFIG_TOUCHSCREEN_GT9XX_UPDATE=n
#kangting modify end
CONFIG_INPUT_TOUCHSCREEN=y
CONFIG_INPUT_MISC=y
kernel/msm-4.9/drivers/input/touchscreen/Kconfig
source "drivers/input/touchscreen/synaptics_dsx/Kconfig"
+source "drivers/input/touchscreen/gt9xx/Kconfig"
kernel/msm-4.9/drivers/input/touchscreen/Makefile
obj-$(CONFIG_TOUCHSCREEN_ZFORCE) += zforce_ts.o
obj-$(CONFIG_TOUCHSCREEN_COLIBRI_VF50) += colibri-vf50-ts.o
obj-$(CONFIG_TOUCHSCREEN_ROHM_BU21023) += rohm_bu21023.o
-obj-$(CONFIG_TOUCHSCREEN_MSG28XX) += msg28xx/
+obj-$(CONFIG_INPUT_TOUCHSCREEN) += gt9xx/
kernel/msm-4.9/drivers/input/touchscreen/msg28xx/Makefile
-obj-y += ilitek_drv_main.o
-obj-y += ilitek_drv_mp_test.o
-obj-y += ilitek_drv_qcom.o
-obj-y += ilitek_drv_update.o
+#obj-y += ilitek_drv_main.o
+#obj-y += ilitek_drv_mp_test.o
+#obj-y += ilitek_drv_qcom.o
+#obj-y += ilitek_drv_update.o
kernel/msm-4.9/drivers/input/touchscreen/synaptics_dsx/Kconfig
menuconfig TOUCHSCREEN_SYNAPTICS_DSX
bool "Synaptics DSX touchscreen"
- default y
+ default n
help
Say Y here if you have a Synaptics DSX touchscreen connected
to your system.
kernel/msm-4.9/drivers/input/touchscreen/synaptics_dsx_2.6/Kconfig
menuconfig TOUCHSCREEN_SYNAPTICS_DSX_v26
bool "Synaptics DSX v2.6 touchscreen"
- default y
+ default n
help
Say Y here if you have a Synaptics DSX touchscreen connected
to your system.
2、添加设备树配置
kernel/msm-4.9/arch/arm64/boot/dts/GM620S/msm8953-mtp.dtsi
//kangting modify for TP1
&i2c_3 {
- aaa@qq.com26 {
- compatible = "mstar,msg2xxx";
- reg = <0x26>;
+ aaa@qq.com5d {
+ compatible = "goodix,gt9xx";
+ reg = <0x5d>;
interrupt-parent = <&tlmm>;
interrupts = <65 0x2008>;
- vdd-supply = <&pm8953_l10>; //vdd-supply = <&pmtitanium_l17>; //kangting modify
+ vdd_ana-supply = <&pm8953_l10>; //vdd-supply = <&pmtitanium_l17>; //kangting modify
vcc_i2c-supply = <&pm8953_l6>;
+ /*pinctrl-names = "int-default", "int-output-low","int-output-high", "int-input", "ts_rst_default", "ts_rst_output_high", "ts_rst_output_low", "ts_rst_ouput";
+ pinctrl-0 = <&ts_int_default>;
+ pinctrl-1 = <&ts_int_output_low>;
+ pinctrl-2 = <&ts_int_output_high>;
+ pinctrl-3 = <&ts_int_input>;
+ pinctrl-4 = <&ts_rst_default>;
+ pinctrl-5 = <&ts_rst_output_high>;
+ pinctrl-6 = <&ts_rst_output_low>;
+ pinctrl-7 = <&ts_rst_ouput>;*/
pinctrl-names = "pmx_ts_active","pmx_ts_suspend",
"pmx_ts_release";
pinctrl-0 = <&ts_int_active &ts_reset_active>;
@@ -48,8 +58,27 @@
pinctrl-2 = <&ts_release>;
touch,reset-gpio = <&tlmm 64 0x00>;
touch,irq-gpio = <&tlmm 65 0x2008>;
+ irq-flags = <2>;
+ touchscreen-max-id = <11>;
+ touchscreen-size-x = <320>;
+ touchscreen-size-y = <1280>;
+ touchscreen-max-w = <512>;
+ touchscreen-max-p = <512>;
+ /*touchscreen-key-map = <172>, <158>;*/ /*KEY_HOMEPAGE=172, KEY_BACK=158,KEY_MENU=139*/
+ goodix,slide-wakeup = <0>;
+ goodix,type-a-report = <0>;
+ goodix,driver-send-cfg = <0>;
+ goodix,resume-in-workqueue = <0>;
+ goodix,int-sync = <1>;
+ goodix,swap-x2y = <1>;
+ goodix,esd-protect = <0>;
+ goodix,auto-update-cfg = <0>;
+ goodix,power-off-sleep = <0>;
+ goodix,pen-suppress-finger = <0>;
+ goodix,cfg-group0 = [53 D0 02 00 05 05 F5 D5 21 48 2D 0F 5A 41 0E 05 00 00 32 32 20 00 05 14 14 1A 14 8B 2B 00];
};
};
即如下代码:
//kangting modify for TP1
&i2c_3 {
aaa@qq.com5d {
compatible = "goodix,gt9xx";
reg = <0x5d>;
interrupt-parent = <&tlmm>;
interrupts = <65 0x2008>;
vdd_ana-supply = <&pm8953_l10>; //vdd-supply = <&pmtitanium_l17>; //kangting modify
vcc_i2c-supply = <&pm8953_l6>;
/*pinctrl-names = "int-default", "int-output-low","int-output-high", "int-input", "ts_rst_default", "ts_rst_output_high", "ts_rst_output_low", "ts_rst_ouput";
pinctrl-0 = <&ts_int_default>;
pinctrl-1 = <&ts_int_output_low>;
pinctrl-2 = <&ts_int_output_high>;
pinctrl-3 = <&ts_int_input>;
pinctrl-4 = <&ts_rst_default>;
pinctrl-5 = <&ts_rst_output_high>;
pinctrl-6 = <&ts_rst_output_low>;
pinctrl-7 = <&ts_rst_ouput>;*/
pinctrl-names = "pmx_ts_active","pmx_ts_suspend",
"pmx_ts_release";
pinctrl-0 = <&ts_int_active &ts_reset_active>; //INT和RST使用
pinctrl-1 = <&ts_int_suspend &ts_reset_suspend>;
pinctrl-2 = <&ts_release>;
touch,reset-gpio = <&tlmm 64 0x00>;
touch,irq-gpio = <&tlmm 65 0x2008>;
irq-flags = <2>;
touchscreen-max-id = <11>;
touchscreen-size-x = <320>;
touchscreen-size-y = <1280>;
touchscreen-max-w = <512>;
touchscreen-max-p = <512>;
/*touchscreen-key-map = <172>, <158>;*/ /*KEY_HOMEPAGE=172, KEY_BACK=158,KEY_MENU=139*/
goodix,slide-wakeup = <0>;
goodix,type-a-report = <0>;
goodix,driver-send-cfg = <0>;
goodix,resume-in-workqueue = <0>;
goodix,int-sync = <1>;
goodix,swap-x2y = <1>; //x和Y坐标交换
goodix,esd-protect = <0>; //不用ESD
goodix,auto-update-cfg = <0>;
goodix,power-off-sleep = <0>;
goodix,pen-suppress-finger = <0>;
goodix,cfg-group0 = [53 D0 02 00 05 05 F5 D5 21 48 2D 0F 5A 41 0E 05 00 00 32 32 20 00 05 14 14 1A 14 8B 2B 00];
};
};
kernel/msm-4.9/arch/arm64/boot/dts/GM620S/msm8953-pinctrl.dtsi
/* add pingrp for touchscreen */
pmx_ts_int_active {
ts_int_active: ts_int_active {
mux {
pins = "gpio65";
function = "gpio";
};
config {
pins = "gpio65";
drive-strength = <8>;
bias-pull-up;
};
};
};
pmx_ts_int_suspend {
ts_int_suspend: ts_int_suspend {
mux {
pins = "gpio65";
function = "gpio";
};
config {
pins = "gpio65";
drive-strength = <2>;
bias-pull-down;
};
};
};
pmx_ts_reset_active {
ts_reset_active: ts_reset_active {
mux {
pins = "gpio64";
function = "gpio";
};
config {
pins = "gpio64";
drive-strength = <8>;
bias-pull-up;
};
};
};
pmx_ts_reset_suspend {
ts_reset_suspend: ts_reset_suspend {
mux {
pins = "gpio64";
function = "gpio";
};
config {
pins = "gpio64";
drive-strength = <2>;
bias-pull-down;
};
};
};
pmx_ts_release {
ts_release: ts_release {
mux {
pins = "gpio65", "gpio64";
function = "gpio";
};
config {
pins = "gpio65", "gpio64";
drive-strength = <2>;
bias-pull-down;
};
};
};
3、驱动修改
kernel/msm-4.9/drivers/input/touchscreen/gt9xx/gt9xx.c
3.1 msm8953-pinctrl.dtsi中定义的INT和RST管脚的处理
static int gtp_pinctrl_init(struct goodix_ts_data *ts)函数修改成如下:
static int gtp_pinctrl_init(struct goodix_ts_data *ts)
{
struct goodix_pinctrl *pinctrl = &ts->pinctrl;
pinctrl->pinctrl = devm_pinctrl_get(&ts->client->dev);
if (IS_ERR_OR_NULL(pinctrl->pinctrl)) {
dev_info(&ts->client->dev, "No pinctrl found\n");
pinctrl->pinctrl = NULL;
return 0;
}
pinctrl->gPinCtrlStateActive = pinctrl_lookup_state(pinctrl->pinctrl,
"pmx_ts_active");
if (IS_ERR_OR_NULL(pinctrl->gPinCtrlStateActive)) {
dev_info(&ts->client->dev,
"Failed get pinctrl state:pmx_ts_active\n");
goto exit_pinctrl_init;
}
pinctrl->gPinCtrlStateSuspend = pinctrl_lookup_state(pinctrl->pinctrl,
"pmx_ts_suspend");
if (IS_ERR_OR_NULL(pinctrl->gPinCtrlStateSuspend)) {
dev_info(&ts->client->dev,
"Failed get pinctrl state:gPinCtrlStateSuspend\n");
goto exit_pinctrl_init;
}
pinctrl->gPinCtrlStateRelease = pinctrl_lookup_state(pinctrl->pinctrl,
"pmx_ts_release");
if (IS_ERR_OR_NULL(pinctrl->gPinCtrlStateRelease)) {
dev_info(&ts->client->dev,
"Failed get pinctrl state:gPinCtrlStateRelease\n");
goto exit_pinctrl_init;
}
pinctrl_select_state(pinctrl->pinctrl, pinctrl->gPinCtrlStateActive);//选择INT和RST为活动状态
dev_info(&ts->client->dev, "****%s() Success init pinctrl***\n",__func__);
return 0;
exit_pinctrl_init:
devm_pinctrl_put(pinctrl->pinctrl);
pinctrl->gPinCtrlStateActive = NULL;
pinctrl->gPinCtrlStateSuspend = NULL;
pinctrl->gPinCtrlStateRelease = NULL;
return 0;
}
针对设备树中touch,reset-gpio和touch,irq-gpio的处理
static int gtp_parse_dt(struct device *dev,
struct goodix_ts_platform_data *pdata)
{
int ret;
u32 key_nums;
struct property *prop;
u32 key_map[MAX_KEY_NUMS];
struct device_node *np = dev->of_node;
..........................................
pdata->irq_gpio = of_get_named_gpio(np, "touch,irq-gpio", 0);
dev_info(dev, "pdata->irq_gpio = %d\n", pdata->irq_gpio);
if (!gpio_is_valid(pdata->irq_gpio))
dev_err(dev, "No valid irq gpio");
pdata->rst_gpio = of_get_named_gpio(np, "touch,reset-gpio", 0);
dev_info(dev, "pdata->rst_gpio = %d\n", pdata->rst_gpio);
if (!gpio_is_valid(pdata->rst_gpio))
dev_err(dev, "No valid rst gpio");
return 0;
}
针对设备树种PMIC的LDO的初始化:
static int gtp_power_init(struct goodix_ts_data *ts)
{
int ret;
//vdd_ana就是设备树中的vdd_ana-supply 使用时去掉-supply
ts->vdd_ana = regulator_get(&ts->client->dev, "vdd_ana");
if (IS_ERR(ts->vdd_ana)) {
ts->vdd_ana = NULL;
ret = PTR_ERR(ts->vdd_ana);
dev_info(&ts->client->dev,
"Regulator get failed vdd ret=%d\n", ret);
}
//vcc_i2c就是设备树中的vcc_i2c-supply 使用时去掉-supply
ts->vcc_i2c = regulator_get(&ts->client->dev, "vcc_i2c");
if (IS_ERR(ts->vcc_i2c)) {
ts->vcc_i2c = NULL;
ret = PTR_ERR(ts->vcc_i2c);
dev_info(&ts->client->dev,
"Regulator get failed vcc_i2c ret=%d\n", ret);
}
return 0;
}
3.2 在probe()函数中针对gtp_pinctrl_init和上电需要交换一下位置,方便后续针对休眠和唤醒的处理
static int gtp_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
int ret = -1;
struct goodix_ts_data *ts;
struct goodix_ts_platform_data *pdata;
......................................................
ret = gtp_power_on(ts);
if (ret) {
dev_err(&client->dev, "Failed power on device\n");
ret = -EINVAL;
goto exit_deinit_power;
}
ret = gtp_pinctrl_init(ts);
if (ret < 0) {
/* if define pinctrl must define the following state
* to let int-pin work normally: default, int_output_high,
* int_output_low, int_input
*/
dev_err(&client->dev, "Failed get wanted pinctrl state\n");
goto exit_deinit_power;
}
修改成:
ret = gtp_pinctrl_init(ts);
if (ret < 0) {
/* if define pinctrl must define the following state
* to let int-pin work normally: default, int_output_high,
* int_output_low, int_input
*/
dev_err(&client->dev, "Failed get wanted pinctrl state\n");
goto exit_deinit_power;
}
ret = gtp_power_on(ts);
if (ret) {
dev_err(&client->dev, "Failed power on device\n");
ret = -EINVAL;
goto exit_deinit_power;
}else{
dev_info(&client->dev, "gtp_power_on device ok\n");
}
ret = gtp_request_io_port(ts);
if (ret < 0) {
dev_err(&client->dev, "Failed request IO port\n");
goto exit_power_off;
}
gtp_reset_guitar(ts->client, 20);
.....................................................
3.3 gtp_request_io_port()函数添加INT和RST管脚的初始状态
static int gtp_request_io_port(struct goodix_ts_data *ts)
{
int ret = 0;
//struct goodix_pinctrl *pinctrl_ts = &ts->pinctrl;
dev_info(&ts->client->dev, "ts->pdata->irq_gpio=%d\n", ts->pdata->irq_gpio);
dev_info(&ts->client->dev, "ts->pdata->rst_gpio=%d\n", ts->pdata->rst_gpio);
if (gpio_is_valid(ts->pdata->irq_gpio)) {
ret = gpio_request(ts->pdata->irq_gpio, "goodix_ts_int");
if (ret < 0) {
dev_err(&ts->client->dev,
"Failed to request GPIO:%d, ERRNO:%d\n",
(s32)ts->pdata->irq_gpio, ret);
return -ENODEV;
}
//zhaojr add
gpio_direction_output(ts->pdata->irq_gpio, 1); //中断管脚先输出为高
gpio_set_value(ts->pdata->irq_gpio, 1);
msleep(5);
//end add
gpio_direction_input(ts->pdata->irq_gpio);
dev_info(&ts->client->dev, "Success request irq-gpio\n");
}
if (gpio_is_valid(ts->pdata->rst_gpio)) {
ret = gpio_request(ts->pdata->rst_gpio, "goodix_ts_rst");
if (ret < 0) {
dev_err(&ts->client->dev,
"Failed to request GPIO:%d, ERRNO:%d\n",
(s32)ts->pdata->rst_gpio, ret);
if (gpio_is_valid(ts->pdata->irq_gpio))
gpio_free(ts->pdata->irq_gpio);
return -ENODEV;
}
//gpio_direction_input(ts->pdata->rst_gpio);
ret = gpio_direction_output(ts->pdata->rst_gpio, 1); //复位先输出为高
if(ret){
dev_info(&ts->client->dev, "gpio_direction_output rst_gpio failed\n");
}
gpio_set_value(ts->pdata->rst_gpio, 1);
//pinctrl_select_state(pinctrl_ts->pinctrl, pinctrl_ts->rst_input);
dev_info(&ts->client->dev, "Success request rst-gpio\n");
}
return 0;
}
3.4 gtp_reset_guitar()函数,即RST管脚和INT管脚的处理,这里需要参考TP的上电时序,如下:
void gtp_reset_guitar(struct i2c_client *client, s32 ms)
{
struct goodix_ts_data *ts = i2c_get_clientdata(client);
dev_info(&client->dev, "Guitar reset");
set_bit(PANEL_RESETTING, &ts->flags);
if (!gpio_is_valid(ts->pdata->rst_gpio)) {
dev_warn(&client->dev, "reset failed no valid reset gpio");
return;
}
//gpt_ret=gpio_direction_output(ts->pdata->rst_gpio, 0);
//if(gpt_ret){
// dev_info(&client->dev, "gpio_direction_output rst_gpio failed\n");
//}
gpio_set_value(ts->pdata->rst_gpio, 0); //RST输出为低,进行复位
usleep_range(ms * 1000, ms * 1000 + 100); /* T2: > 10ms */
gtp_int_output(ts, client->addr == 0x14);//client->addr为0x5d
usleep_range(2000, 3000); /* T3: > 100us (2ms)*/
//gpt_ret = gpio_direction_output(ts->pdata->rst_gpio, 1);
//if(gpt_ret){
// dev_info(&client->dev, "gpio_direction_output rst_gpio failed\n");
//}
gpio_set_value(ts->pdata->rst_gpio, 1); //输出为1
//gpio_direction_output(ts->pdata->rst_gpio, 0);
usleep_range(6000, 7000); /* T4: > 5ms */
//gpt_ret = gpio_direction_input(ts->pdata->rst_gpio);//去掉输入,否则TP连接上后有异常
//if(gpt_ret){
// dev_info(&client->dev, "gpio_direction_input rst_gpio failed\n");
//}
gtp_int_sync(ts, 50);
#if GTP_ESD_PROTECT
if (ts->pdata->esd_protect)
gtp_init_ext_watchdog(client);
#endif
clear_bit(PANEL_RESETTING, &ts->flags);
}
gtp_int_sync()函数走IO请求的方式:
void gtp_int_sync(struct goodix_ts_data *ts, s32 ms)
{
if (!ts->pdata->int_sync)
return;
if (gpio_is_valid(ts->pdata->irq_gpio)) {
gpio_direction_output(ts->pdata->irq_gpio, 0);
msleep(ms);
gpio_direction_input(ts->pdata->irq_gpio);
} else {
dev_err(&ts->client->dev, "Failed sync int pin\n");
}
}
gtp_int_output函数走IO请求的方式:
void gtp_int_output(struct goodix_ts_data *ts, int level)
{
if (!ts->pdata->int_sync)
return;
if (level == 0) {
if (gpio_is_valid(ts->pdata->irq_gpio))
gpio_direction_output(ts->pdata->irq_gpio, 0);
else
dev_err(&ts->client->dev,
"Failed set int pin output low\n");
} else {
if (gpio_is_valid(ts->pdata->irq_gpio))
gpio_direction_output(ts->pdata->irq_gpio, 1);
else
dev_err(&ts->client->dev,
"Failed set int pin output high\n");
}
}
3.5 中断的处理,中断申请时使用IRQF_TRIGGER_FALLING | IRQF_ONESHOT
static int gtp_request_irq(struct goodix_ts_data *ts)
{
int ret = -1;
// use irq
if (gpio_is_valid(ts->pdata->irq_gpio) || ts->client->irq > 0) {
if (gpio_is_valid(ts->pdata->irq_gpio))
ts->client->irq = gpio_to_irq(ts->pdata->irq_gpio);
dev_info(&ts->client->dev, "INT num %d, trigger type:%d\n",
ts->client->irq, ts->pdata->irq_flags);
ret = request_threaded_irq(ts->client->irq, NULL,
gtp_irq_handler,
//ts->pdata->irq_flags | IRQF_TRIGGER_FALLING, //IRQF_ONESHOT,
IRQF_TRIGGER_FALLING | IRQF_ONESHOT, //修改成下降沿或电平触发
ts->client->name,
ts);
if (ret < 0) {
dev_err(&ts->client->dev,
"Failed to request irq %d\n", ts->client->irq);
return ret;
}
} else { // use hrtimer
dev_info(&ts->client->dev, "No hardware irq, use hrtimer\n");
hrtimer_init(&ts->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
ts->timer.function = gtp_timer_handler;
hrtimer_start(&ts->timer,
ktime_set(0, (GTP_POLL_TIME + 6) * 1000000),
HRTIMER_MODE_REL);
set_bit(HRTIMER_USED, &ts->flags);
ret = 0;
}
return ret;
}
3.6 以上修改之后,TP就有报点了,但是报点不对,需要进行X和Y坐标的交换之后X坐标反向,如下:
static u8 gtp_get_points(struct goodix_ts_data *ts,
struct goodix_point_t *points,
u8 *key_value)
{
int ret;
int i;
u8 *coor_data = NULL;
u8 finger_state = 0;
u8 touch_num = 0;
.............................
for (i = 0; i < touch_num; i++) {
coor_data = &point_data[i * 8 + 3];
points[i].id = coor_data[0];
points[i].x = coor_data[1] | (coor_data[2] << 8);
points[i].y = coor_data[3] | (coor_data[4] << 8);
points[i].w = coor_data[5] | (coor_data[6] << 8);
/* if pen hover points[].p must set to zero */
points[i].p = coor_data[5] | (coor_data[6] << 8);
//After the exchange of X and Y coordinates, x coordinates will become y coordinates, y coordinates will become x coordinates, and then x or y will reverse, which needs to be carried out
//X = (x of LCD physical resolution (e.g. 320) - Y coordinate of alarm point), and the same is true for y reverse
if (ts->pdata->swap_x2y) //x and y chanage 先进行X和Y坐标交换,交换之前X=320,Y=1280.交换之后X=1280,Y=320,之后再进行X反向
GTP_SWAP(points[i].x, points[i].y);
#if REVERT_X_FLAG
points[i].y = 320-points[i].y; //X坐标反向
#endif
dev_info(&ts->client->dev, "[%d][%d %d %d]\n",
points[i].id, points[i].x, points[i].y, points[i].p);
............................................
以上函数只是将数据读取,并进行换算,以下函数才是输入子系统向上报数据
static void gtp_mt_slot_report(struct goodix_ts_data *ts, u8 touch_num,
struct goodix_point_t *points)
{
int i;
u16 cur_touch = 0;
static u16 pre_touch;
static u8 pre_pen_id;
for (i = 0; i < ts->pdata->max_touch_id; i++) {
if (touch_num && i == points->id) {
input_mt_slot(ts->input_dev, points->id);
if (points->tool_type == GTP_TOOL_PEN) {
input_mt_report_slot_state(ts->input_dev,
MT_TOOL_PEN, true);
pre_pen_id = points->id;
} else {
input_mt_report_slot_state(ts->input_dev,
MT_TOOL_FINGER, true);
}
//dev_err(&ts->client->dev,"points->x=%d,points->y=%d\n",points->x,points->y);
//#if REVERT_X_FLAG
// points[i].y = 320-points[i].y;
//#endif
//开始上报数据
input_report_abs(ts->input_dev, ABS_MT_POSITION_X,
points->x);
input_report_abs(ts->input_dev, ABS_MT_POSITION_Y,
points->y);
input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR,
points->w);
input_report_abs(ts->input_dev, ABS_MT_PRESSURE,
points->p);
cur_touch |= 0x01 << points->id;
points++;
} else if (pre_touch & 0x01 << i) {
input_mt_slot(ts->input_dev, i);
if (pre_pen_id == i) {
input_mt_report_slot_state(ts->input_dev,
MT_TOOL_PEN, false);
/* valid id will < 10, so set id to 0xff to
* indicate a invalid state
*/
pre_pen_id = 0xff;
} else {
input_mt_report_slot_state(ts->input_dev,
MT_TOOL_FINGER, false);
}
}
}
pre_touch = cur_touch;
/* report BTN_TOUCH event */
input_mt_sync_frame(ts->input_dev);
input_sync(ts->input_dev);
}
4、kernel\msm-4.9\drivers\input\touchscreen\gt9xx\gt9xx.h修改
添加:
#define GTP_DEBUG_ON 1
#define GTP_DEBUG_ARRAY_ON 0
#define GTP_DEBUG_FUNC_ON 0
#define REVERT_X_FLAG 1
#define REVERT_Y_FLAG 0
#define READ_FW_X_Y 0
#define GTP_ESD_PROTECT 0
#define GTP_ERROR(fmt,arg...) printk("<<-GTP-ERROR->> "fmt"\n",##arg)
...........................................................
struct goodix_pinctrl {
struct pinctrl *pinctrl;
//struct pinctrl_state *default_sta;
//struct pinctrl_state *int_out_high;
//struct pinctrl_state *int_out_low;
//struct pinctrl_state *int_input;
//struct pinctrl_state *rst_default;
//struct pinctrl_state *rst_out_high;
//struct pinctrl_state *rst_out_low;
//struct pinctrl_state *rst_output;
//struct pinctrl_state *rst_input;
struct pinctrl_state *gPinCtrlStateActive;
struct pinctrl_state *gPinCtrlStateSuspend;
struct pinctrl_state *gPinCtrlStateRelease;
};
.............................................................
/* TODO: define your config for Sensor_ID == 2 here, if needed */
//这个数组要向FAE要
#define CTP_CFG_GROUP2 {\
0x63,0x40,0x01,0x00,0x05,0x05,0x05, \
0x00,0x01,0x08,0x28,0x05,0x46,0x32, \
0x03,0x05,0x00,0x00,0x00,0x00,0x00, \
0x00,0x00,0x1C,0x00,0x0C,0x0E,0x8C, \
0x2E,0x09,0x15,0x17,0xF5,0x0F,0x00, \
0x00,0x00,0x02,0x03,0x2D,0x00,0x01, \
0x00,0x00,0x00,0x03,0x64,0x32,0x00, \
0x00,0x00,0x0F,0x3C,0x94,0xD5,0x02, \
0x07,0x00,0x00,0x04,0x98,0x11,0x00, \
0x7B,0x16,0x00,0x61,0x1E,0x00,0x50, \
0x27,0x00,0x44,0x34,0x00,0x44,0x00, \
0x00,0x00,0x00,0x00,0x00,0x00,0x00, \
0x00,0x00,0x00,0x00,0x00,0x00,0x00, \
0x00,0x00,0x00,0x00,0x00,0x00,0x00, \
0x00,0x00,0x00,0x00,0x00,0x00,0x00, \
0x00,0x00,0x00,0x00,0x00,0x00,0x00, \
0x12,0x10,0x0E,0x0C,0x0A,0x08,0x06, \
0x04,0x02,0xFF,0xFF,0xFF,0xFF,0xFF, \
0x00,0x00,0x00,0x00,0x00,0x00,0x00, \
0x00,0x00,0x00,0x00,0x00,0x00,0x00, \
0x00,0x00,0x2A,0x29,0x28,0x26,0x24, \
0x22,0x21,0x20,0x1F,0x1E,0x1D,0x1C, \
0x18,0x16,0x14,0x13,0x12,0x10,0x0F, \
0x0C,0x0A,0x08,0x06,0x04,0x02,0x00, \
0x00,0x00,0x00,0x00,0x00,0x00,0x00, \
0x00,0x00,0x00,0x00,0x00,0x00,0x00, \
0x00,0x00,0x52,0x01\
}
......................................................
/* STEP_3(optional): Specify your special config info if needed */
#define GTP_DEFAULT_MAX_X 320 /* default coordinate max values */
#define GTP_DEFAULT_MAX_Y 1280
//#define GTP_DEFAULT_MAX_WIDTH 1024
#define GTP_DEFAULT_MAX_WIDTH 320
5、在驱动中添加I2C读单一寄存器的函数
#if READ_FW_X_Y
#define FL_PACK_SIZE 1024
#define GTP_ADDR_LENGTH 2
static int fw_x_max=0,fw_y_max=0;
u8 i2c_opr_buf[GTP_ADDR_LENGTH + FL_PACK_SIZE] = {0};
#endif
......................................
#if READ_FW_X_Y
s32 i2c_read_bytes(struct i2c_client *client, u16 addr, u8 *buf, s32 len)
{
s32 ret = 0;
s32 read_bytes = 0;
s32 retry = 0;
u8 *tx_buf = buf;
while (len > 0)
{
i2c_opr_buf[0] = (u8)(addr >> 8);
i2c_opr_buf[1] = (u8)(addr & 0xFF);
if (len > FL_PACK_SIZE)
{
read_bytes = FL_PACK_SIZE;
}
else
{
read_bytes = len;
}
for (retry = 0; retry < 5; ++retry)
{
//ret = gup_i2c_read(client, i2c_opr_buf, read_bytes + 2); //GTP_ADDR_LENGTH=2
ret = gtp_i2c_read(client, i2c_opr_buf, read_bytes + GTP_ADDR_LENGTH); //GTP_ADDR_LENGTH=2
if (ret == 2)
{
break;
}
}
if (retry >= 5)
{
GTP_ERROR("retry timeout, I2C read 0x%04X %d bytes failed!", addr, read_bytes);
return -1;
}
memcpy(tx_buf, i2c_opr_buf + 2, read_bytes);
addr += read_bytes;
len -= read_bytes;
tx_buf += read_bytes;
}
return 2;
}
s32 i2c_write_bytes(struct i2c_client *client, u16 addr, u8 *buf, s32 len)
{
s32 ret = 0;
s32 write_bytes = 0;
s32 retry = 0;
u8 *tx_buf = buf;
while (len > 0)
{
i2c_opr_buf[0] = (u8)(addr >> 8);
i2c_opr_buf[1] = (u8)(addr & 0xFF);
if (len > FL_PACK_SIZE)
{
write_bytes = FL_PACK_SIZE;
}
else
{
write_bytes = len;
}
memcpy(i2c_opr_buf + 2, tx_buf, write_bytes);
for (retry = 0; retry < 5; ++retry)
{ //GTP_ADDR_LENGTH=2
ret = gup_i2c_write(client, i2c_opr_buf, write_bytes + GTP_ADDR_LENGTH);
if (ret == 1)
{
break;
}
}
if (retry >= 5)
{
GTP_ERROR("retry timeout, I2C write 0x%04X %d bytes failed!", addr, write_bytes);
return -1;
}
addr += write_bytes;
len -= write_bytes;
tx_buf += write_bytes;
}
return 1;
}
#endif
static u8 gtp_get_points(struct goodix_ts_data *ts,
struct goodix_point_t *points,
u8 *key_value)
{
.....................................
#if READ_FW_X_Y
u8 x_opr_buf[2];
u8 y_opr_buf[2];
#endif
.....................................................
//read x_max and y_max
#if READ_FW_X_Y
ret = i2c_read_bytes(ts->client, 0x8049, x_opr_buf, 1);
if (ret < 0)
{
return FAIL;
}
fw_x_max = x_opr_buf[0];
ret = i2c_read_bytes(ts->client, 0x8048, x_opr_buf, 1);
if (ret < 0)
{
return FAIL;
}
fw_x_max = (fw_x_max << 8) |x_opr_buf[0];
ret = i2c_read_bytes(ts->client, 0x804B, y_opr_buf, 1);
if (ret < 0)
{
return FAIL;
}
fw_y_max = y_opr_buf[0];
ret = i2c_read_bytes(ts->client, 0x804A, y_opr_buf, 1);
if (ret < 0)
{
return FAIL;
}
fw_y_max = (fw_y_max << 8) |y_opr_buf[0];
dev_err(&ts->client->dev, "gtp_get_points()::fw_x_max=%d,fw_y_max=%d \n",fw_x_max,fw_y_max);
#endif
下一篇: 推荐一位大牛的2013博客汇总