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 {
-	mstar@26 {
-		compatible = "mstar,msg2xxx";
-		reg = <0x26>;
+	mstar@5d {
+		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 {
	mstar@5d {
		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
发布了93 篇原创文章 · 获赞 10 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/jinron10/article/details/103879946