目录

  • 前言
  • 一、defconfig打开GT9xx配置
  • 二、配置设备树dts
  • 三、中断GPIO申请失败
  • 四、gt9271驱动注册失败
  • 五、触摸屏可以触摸,但是x轴数据反了
  • 五、遇到的问题



前言


带触摸屏的设备并不少见,现在市面上常见的有电容式触摸屏,很少见电阻触摸屏;电容触摸屏通讯接口一般有两种:I2C和USB;便利的话还是USB,USB做为热插拔设备即插即用;驱动上也不用怎么调试,唯一的缺点可能是让人感觉不太稳定的样子;I2C的方式,这需要调试驱动,并且不支持热插拔;

调试:

一、defconfig打开GT9xx配置

  SDK里面包含有GT9xx的驱动,只需要在kernel的config打开该配置即可:

CONFIG_TOUCHSCREEN_GT9XX=y

二、配置设备树dts

首先需要确定硬件是接在哪一组I2C上;gt9271的I2C地址可以通过规格书或者咨询供应商;在驱动上填写的I2C从设备地址需要右移一位(address>>1);

  那问题来了,为什么I2C从设备地址需要右移一位呢?

  其实,I2C地址主要由7bit的二进制数值组成,最低位是读写标志位,0表示写,1表示读;datasheet给出的都是8bit的I2C地址(带读写位),驱动里往往是使用实际的设备地址(不带读写位),所以在编程时需要对I2C从地址进行右移一位,即去掉最后一位读写位。具体可看下图:

android 11 USB触摸屏协议_linux


  GT9271的I2C地址是0x28,所以在驱动dts中要填的I2C从设备地址右移一位后是0x14,dts配置如下:

&i2c1 {
	status = "okay";
	gt9xx: gt9xx@14 {
		status = "okay";
		compatible = "goodix,gt9xx";
		pinctrl-names = "default";
		pinctrl-0 = <&tp_gpio>;
		reg = <0x14>;
		reset-gpio = <&gpio0 RK_PB6 GPIO_ACTIVE_HIGH>;
		irq-gpio = <&gpio0 RK_PB5 IRQ_TYPE_LEVEL_LOW>;
	};
};
 
&pinctrl {
	touch {
		tp_gpio: tp-gpio {
			rockchip,pins =
				<0 RK_PB6 RK_FUNC_GPIO &pcfg_pull_up>,
				<0 RK_PB5 RK_FUNC_GPIO &pcfg_pull_none>;
		};
	};
};

三、中断GPIO申请失败

编译kernel并烧录,发现并没有加载gt9xx的驱动,尝试加打印信息,也没有打印出来;
后面查明原因是中断Label的name错误,驱动中写的如下:

ts->irq_pin = of_get_named_gpio_flags(np, "touch-gpio", 0, (enum of_gpio_flags *)(&ts->irq_flags));
ts->rst_pin = of_get_named_gpio_flags(np, "reset-gpio", 0, &rst_flags);

可以看到中断Label的name为touch-gpio,所以导致驱动在申请该gpio资源时申请不到;然后再设备树dts配置成touch-gpio = <&gpio0 RK_PB5 IRQ_TYPE_LEVEL_LOW>;即可;

四、gt9271驱动注册失败

1.报以下问题1

goodix_ts_probe() start
Goodix-TS 2-0014: no max-x defined
Goodix-TS: probe of 2-0014 failed with error -22

解决:再gt9xx驱动中搜索“no max-x defined”的关键句;发现设备树中没有配置tp-size属性,根据代码的理解是选择触摸屏芯片的型号(若代码中没有对应的芯片型号,可以自己添加):

if (of_property_read_u32(np, "tp-size", &val)) {
    	dev_err(&client->dev, "no max-x defined\n");
    	return -EINVAL;
    }

	if (val == 89) {
		m89or101 = TRUE;
		gtp_change_x2y = TRUE;
		gtp_x_reverse = FALSE;
		gtp_y_reverse = TRUE;
	} else if (val == 101) {
		m89or101 = FALSE;
		gtp_change_x2y = TRUE;
		gtp_x_reverse = TRUE;
		gtp_y_reverse = FALSE;
	} else if (val == 911) {
		m89or101 = FALSE;
		bgt911 = TRUE;
		gtp_change_x2y = TRUE;
		gtp_x_reverse = FALSE;
		gtp_y_reverse = TRUE;
	} else if
	...
	} else if (val == 9271) {
		m89or101 = FALSE;
		bgt9271 = TRUE;
		gtp_change_x2y = FALSE;
		gtp_x_reverse = TRUE;
		gtp_y_reverse = TRUE;
	}

在设备树dts中添加即可:tp-size = <9271>;

2.报以下问题2

goodix_ts_probe() start
Goodix-TS 2-0014: 2-0014 supply tp not found, using dummy regulator
Goodix-TS 2-0014: Linked as a consumer to regulator.0
Goodix-TS 2-0014: no max-x defined
Goodix-TS 2-0014: Dropping the link to regulator.0
Goodix-TS: probe of 2-0014 failed with error -22

解决:继续搜索“no max-x defined”,查看代码理解意思:

if (of_property_read_u32(np, "max-x", &val)) {
    dev_err(&client->dev, "no max-x defined\n");
    return -EINVAL;
}
//ts->abs_x_max = val;
	
if (of_property_read_u32(np, "max-y", &val)) {
    dev_err(&client->dev, "no max-y defined\n");
    return -EINVAL;
}
//ts->abs_y_max = val;

设备树中也没有配置这两个属性:
  max-x = <800>;
  max-y = <1280>;

五、触摸屏可以触摸,但是x轴数据反了

gt9xx.c驱动里面有调整X轴和Y轴数据方向代码,只需要修改下驱动即可;

m89or101 = FALSE;
bgt9271 = TRUE;
gtp_change_x2y = FALSE;    ===>X轴和Y轴数据交换
gtp_x_reverse = TRUE;      ===>X轴数据反转
gtp_y_reverse = TRUE;      ===>XY轴数据反转

如果上面配置修改没有起作用,看下代码哪里做了判断,修改如下即可触摸正常:

//if (!bgt911 && !bgt970) {
		if (gtp_x_reverse)
			x = ts->abs_x_max - x;
		if (gtp_y_reverse)
			y = ts->abs_y_max - y;
//	}

五、遇到的问题

1.驱动没有获取设备树中的X轴和Y轴的像素最大值,在传入gtp_touch_down触摸按下函数中的ts->abs_x_max/ts->abs_y_max值打印出来的不是设备树中获取到的max-x和max-y的值,所以查找问题后发现:

if (of_property_read_u32(np, "max-x", &val)) {
    dev_err(&client->dev, "no max-x defined\n");
    return -EINVAL;
}
//ts->abs_x_max = val;
	
if (of_property_read_u32(np, "max-y", &val)) {
    dev_err(&client->dev, "no max-y defined\n");
    return -EINVAL;
}
//ts->abs_y_max = val;

以上存在两个问题:是驱动将节点属性max-x和max-y获取到后存在了&val这个地址里面,没有存放在结构体中,所以需要将该值重新存放

of_property_read_u32(np, "max-x", &ts->abs_x_max)

编译时可能会出错,因为在gt9xx.h文件中查看goodix_ts_data结构体时发现:

u16 abs_x_max;
u16 abs_y_max;

因此为避免数据类型不同,可修改为如下:

if (of_property_read_u32(np, "max-x", &val)) {
    dev_err(&client->dev, "no max-x defined\n");
    return -EINVAL;
}
ts->abs_x_max = val;
//ts->abs_x_max = val;
	
if (of_property_read_u32(np, "max-y", &val)) {
    dev_err(&client->dev, "no max-y defined\n");
    return -EINVAL;
}
ts->abs_y_max = val;
//ts->abs_y_max = val;

2.还是出现在触摸按下函数gtp_touch_down(struct goodix_ts_data* ts,s32 id,s32 x,s32 y,s32 w)传进来的参数x和y,在按下屏幕四个顶点时打印到x和y的坐标最大值不是从max-x和max-y获取到的最大值,此时需要考虑的是触摸屏配置信息表是否正确的问题(太多就不赘述了,直接上修改):

static s32 gtp_init_panel(struct goodix_ts_data *ts)
{
    s32 ret = -1;
#if GTP_DRIVER_SEND_CFG
    s32 i = 0;
    u8 check_sum = 0;
    u8 opr_buf[16] = {0};
    u8 sensor_id = 0;
	
	u8 cfg_info_group1[] = CTP_CFG_GROUP1;
    u8 cfg_info_group2[] = CTP_CFG_GROUP2;
    u8 cfg_info_group3[] = CTP_CFG_GROUP3;
    u8 cfg_info_group4[] = CTP_CFG_GROUP4;
    u8 cfg_info_group5[] = CTP_CFG_GROUP5;
    u8 cfg_info_group6[] = CTP_CFG_GROUP6;
//	u8 *send_cfg_buf[] = {gtp_dat_10_1, cfg_info_group2,
    u8 *send_cfg_buf[] = {cfg_info_group1, cfg_info_group2, 
						  cfg_info_group3, cfg_info_group4, 
						  cfg_info_group5, cfg_info_group6};
//    u8 cfg_info_len[] = { CFG_GROUP_LEN(gtp_dat_10_1),
    u8 cfg_info_len[] = { CFG_GROUP_LEN(cfg_info_group1),
                          CFG_GROUP_LEN(cfg_info_group2),
                          CFG_GROUP_LEN(cfg_info_group3),
                          CFG_GROUP_LEN(cfg_info_group4),
                          CFG_GROUP_LEN(cfg_info_group5),
                          CFG_GROUP_LEN(cfg_info_group6)};
    
    GTP_INFO("  <%s>_%d \n", __func__, __LINE__);

    GTP_DEBUG_FUNC();
    GTP_DEBUG("Config Groups\' Lengths: %d, %d, %d, %d, %d, %d", 
        cfg_info_len[0], cfg_info_len[1], cfg_info_len[2], cfg_info_len[3],
        cfg_info_len[4], cfg_info_len[5]);
    
    ...

对应的触摸屏的配置信息需要添加到gt9xx.h文件的#define CTP_CFG_GROUP1 中,注意修改格式。

到这里触摸屏已经能正常使用了,另外遇到问题的话可以在评论区讨论一下。