目录
- 前言
- 一、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从地址进行右移一位,即去掉最后一位读写位。具体可看下图:
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 中,注意修改格式。
到这里触摸屏已经能正常使用了,另外遇到问题的话可以在评论区讨论一下。