欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

msm8953 android8.1平台GT9xx移植

程序员文章站 2022-07-14 15:49:57
...

首先向FAE要GT9xx的驱动包
msm8953 android8.1平台GT9xx移植
将驱动拷贝到kernel/msm-4.9/drivers/input/touchscreen/gt9xx ,如下:
msm8953 android8.1平台GT9xx移植
msm8953 android8.1平台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
相关标签: 高通平台 TP