开发板:aio-rk3288j
SDK版本:rk3288_linux_release_20210304
下载工具:Linux_Upgrade_Tool_v2.1
内核版本:4.4.194
文件系统:buildroot
Ubuntu版本:18.04
交叉编译工具:gcc version 6.3.1 20170404
驱动源码路径:kernel/drivers/input/touchscreen/gt9xx
Kconfig文件添加如下内容
在Makefile里添加编译gt9xx驱动
在内核菜单中去配置gt9xx的驱动,把它编译进内核。打开make menuconfig
路径:
Devrive Drivers ->Input device support -> Touchscreens->Goodix gt9xx support for rockchip
设备树路径:kernel/arch/arm/boot/dts/rk3288-firefly-aio.dts
&i2c4 {
status = "okay";
clock-frequency = <400000>;
gt9xx: goodix-ts@14 {
compatible = "goodix,gt9xx";
reg = <0x14>;
interrupt-parent = <&gpio5>;
interrupts = <19 IRQ_TYPE_EDGE_FALLING>;
touch-gpio = <&gpio5 19 GPIO_ACTIVE_HIGH>;
reset-gpio = <&gpio7 9 GPIO_ACTIVE_LOW>;
pinctrl-names = "default";
pinctrl-0 = <&goodix_touch &goodix_reset>;
max-x = <1024>;
max-y = <600>;
tp-size = <910>;
};
};
&pinctrl {
gt9xx {
goodix_touch: goodix-touch {
rockchip,pins = <5 19 RK_FUNC_GPIO &pcfg_pull_up>;
};
goodix_reset: goodix-reset {
rockchip,pins = <7 9 RK_FUNC_GPIO &pcfg_pull_up>;
};
};
gt9xx.h 文件配置修改
#define DEBUG_SWITCH 1 开启调试开关,打印信息(很重要)
#define GTP_CUSTOM_CFG 1 用来用户自定义设置;
#define GTP_DRIVER_SEND_CFG 1 用来发送CFG文件配置;
group是厂家指定,6个group(0 - 5),该方案配置group3
// TODO: define your config for Sensor_ID == 3 here, if needed
#define CTP_CFG_GROUP3 {\
//厂家提供
0x00,0x00,0x04,0x58,0x02,0x05,0x0C,0x20,0x02,0xC6,0x28,0x0F,0x64,0x50,0x03, \
0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x1A,0x1E,0x14,0x8A,0x29,0x0C, \
0x2A,0x28,0x0F,0x0A,0x00,0x00,0x00,0x81,0x03,0x11,0x00,0x01,0x00,0x00,0x00, \
0x03,0x00,0x00,0x00,0x00,0x00,0x14,0x52,0x94,0xC5,0x02,0x07,0x00,0x00,0x04, \
0xD4,0x17,0x00,0xA6,0x1E,0x00,0x80,0x28,0x00,0x62,0x36,0x00,0x4E,0x47,0x00, \
0x4E,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,0x18,0x16,0x14,0x12,0x10,0x0E,0x0C,0x0A, \
0x08,0x06,0x04,0x02,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, \
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x22,0x21,0x20,0x1F,0x1E,0x1D,0x1C,0x18, \
0x16,0x12,0x10,0x0F,0x0C,0x0A,0x08,0x06,0x04,0x02,0x00,0xFF,0xFF,0xFF,0xFF, \
0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, \
0x00,0x00,0x00,0x00,0xFB,0x01 \
}
Gt9xxx.c源码分析
初始化TP,该函数打印信息判断Sensor id 判断,适配哪个屏幕,即哪个CFG
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_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, cfg_info_group3,
cfg_info_group4, cfg_info_group5, cfg_info_group6};
u8 cfg_info_len[] = { CFG_GROUP_LEN(gtp_dat_10_1),
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__);
if(m89or101){
if (ts->cfg_file_num) {
send_cfg_buf[0] = gtp_dat_8_9_1;
cfg_info_len[0] = CFG_GROUP_LEN(gtp_dat_8_9_1);
} else {
send_cfg_buf[0] = gtp_dat_8_9;
cfg_info_len[0] = CFG_GROUP_LEN(gtp_dat_8_9);
}
}
if (bgt911) {
send_cfg_buf[0] = gtp_dat_gt11;
cfg_info_len[0] = CFG_GROUP_LEN(gtp_dat_gt11);
}
if (bgt970) {
send_cfg_buf[0] = gtp_dat_9_7;
cfg_info_len[0] = CFG_GROUP_LEN(gtp_dat_9_7);
}
if (bgt910) {
send_cfg_buf[0] = gtp_dat_7;
cfg_info_len[0] = CFG_GROUP_LEN(gtp_dat_7);
}
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]);
#if GTP_COMPATIBLE_MODE
if (CHIP_TYPE_GT9F == ts->chip_type)
{
ts->fw_error = 0;
}
else
#endif
{
ret = gtp_i2c_read_dbl_check(ts->client, 0x41E4, opr_buf, 1);
if (SUCCESS == ret)
{
if (opr_buf[0] != 0xBE)
{
ts->fw_error = 1;
GTP_ERROR("Firmware error, no config sent!");
return -1;
}
}
}
if ((!cfg_info_len[1]) && (!cfg_info_len[2]) &&
(!cfg_info_len[3]) && (!cfg_info_len[4]) &&
(!cfg_info_len[5]))
{
sensor_id = 0;
}
else
{
#if GTP_COMPATIBLE_MODE
msleep(50);
#endif
ret = gtp_i2c_read_dbl_check(ts->client, GTP_REG_SENSOR_ID, &sensor_id, 1);
if (SUCCESS == ret)
{
if (sensor_id >= 0x06)
{
GTP_ERROR("Invalid sensor_id(0x%02X), No Config Sent!", sensor_id);
ts->pnl_init_error = 1;
return -1;
}
}
else
{
GTP_ERROR("Failed to get sensor_id, No config sent!");
ts->pnl_init_error = 1;
return -1;
}
GTP_INFO("Sensor_ID: %d", sensor_id);
}
ts->gtp_cfg_len = cfg_info_len[sensor_id];
GTP_INFO("CTP_CONFIG_GROUP%d used, config length: %d", sensor_id + 1, ts->gtp_cfg_len);
if (ts->gtp_cfg_len < GTP_CONFIG_MIN_LENGTH)
{
GTP_ERROR("Config Group%d is INVALID CONFIG GROUP(Len: %d)! NO Config Sent! You need to check you header file CFG_GROUP section!", sensor_id+1, ts->gtp_cfg_len);
ts->pnl_init_error = 1;
return -1;
}
#if GTP_COMPATIBLE_MODE
if (CHIP_TYPE_GT9F == ts->chip_type)
{
ts->fixed_cfg = 0;
}
else
#endif
{
ret = gtp_i2c_read_dbl_check(ts->client, GTP_REG_CONFIG_DATA, &opr_buf[0], 1);
if (ret == SUCCESS)
{
GTP_DEBUG("CFG_GROUP%d Config Version: %d, 0x%02X; IC Config Version: %d, 0x%02X", sensor_id+1,
send_cfg_buf[sensor_id][0], send_cfg_buf[sensor_id][0], opr_buf[0], opr_buf[0]);
if (opr_buf[0] < 90)
{
GTP_INFO(" <%s>_%d \n", __func__, __LINE__);
grp_cfg_version = send_cfg_buf[sensor_id][0]; // backup group config version
send_cfg_buf[sensor_id][0] = 0x00;
ts->fixed_cfg = 0;
}
else // treated as fixed config, not send config
{
GTP_INFO("Ic fixed config with config version(%d, 0x%02X)", opr_buf[0], opr_buf[0]);
ts->fixed_cfg = 1;
gtp_get_info(ts);
return 0;
}
}
else
{
GTP_ERROR("Failed to get ic config version!No config sent!");
return -1;
}
}
memset(&config[GTP_ADDR_LENGTH], 0, GTP_CONFIG_MAX_LENGTH);
memcpy(&config[GTP_ADDR_LENGTH], send_cfg_buf[sensor_id], ts->gtp_cfg_len);
#if GTP_CUSTOM_CFG
config[RESOLUTION_LOC] = (u8)GTP_MAX_WIDTH;
config[RESOLUTION_LOC + 1] = (u8)(GTP_MAX_WIDTH>>8);
config[RESOLUTION_LOC + 2] = (u8)GTP_MAX_HEIGHT;
config[RESOLUTION_LOC + 3] = (u8)(GTP_MAX_HEIGHT>>8);
if (GTP_INT_TRIGGER == 0) //RISING
{
config[TRIGGER_LOC] &= 0xfe;
}
else if (GTP_INT_TRIGGER == 1) //FALLING
{
config[TRIGGER_LOC] |= 0x01;
}
#endif // GTP_CUSTOM_CFG
check_sum = 0;
for (i = GTP_ADDR_LENGTH; i < ts->gtp_cfg_len; i++)
{
check_sum += config[i];
}
config[ts->gtp_cfg_len] = (~check_sum) + 1;
#else // driver not send config
ts->gtp_cfg_len = GTP_CONFIG_MAX_LENGTH;
ret = gtp_i2c_read(ts->client, config, ts->gtp_cfg_len + GTP_ADDR_LENGTH);
if (ret < 0)
{
GTP_ERROR("Read Config Failed, Using Default Resolution & INT Trigger!");
//ts->abs_x_max = GTP_MAX_WIDTH;
//ts->abs_y_max = GTP_MAX_HEIGHT;
ts->int_trigger_type = GTP_INT_TRIGGER;
}
#endif // GTP_DRIVER_SEND_CFG
if ((ts->abs_x_max == 0) && (ts->abs_y_max == 0))
{
ts->abs_x_max = (config[RESOLUTION_LOC + 1] << 8) + config[RESOLUTION_LOC];
ts->abs_y_max = (config[RESOLUTION_LOC + 3] << 8) + config[RESOLUTION_LOC + 2];
ts->int_trigger_type = (config[TRIGGER_LOC]) & 0x03;
GTP_INFO(" <%s>_%d <%d, %d>\n", __func__, __LINE__, ts->abs_x_max, ts->abs_y_max);
}
GTP_INFO(" <%s>_%d \n", __func__, __LINE__);
#if GTP_COMPATIBLE_MODE
if (CHIP_TYPE_GT9F == ts->chip_type)
{
u8 sensor_num = 0;
u8 driver_num = 0;
u8 have_key = 0;
have_key = (config[GTP_REG_HAVE_KEY - GTP_REG_CONFIG_DATA + 2] & 0x01);
if (1 == ts->is_950)
{
driver_num = config[GTP_REG_MATRIX_DRVNUM - GTP_REG_CONFIG_DATA + 2];
sensor_num = config[GTP_REG_MATRIX_SENNUM - GTP_REG_CONFIG_DATA + 2];
if (have_key)
{
driver_num--;
}
ts->bak_ref_len = (driver_num * (sensor_num - 1) + 2) * 2 * 6;
}
else
{
driver_num = (config[CFG_LOC_DRVA_NUM] & 0x1F) + (config[CFG_LOC_DRVB_NUM]&0x1F);
if (have_key)
{
driver_num--;
}
sensor_num = (config[CFG_LOC_SENS_NUM] & 0x0F) + ((config[CFG_LOC_SENS_NUM] >> 4) & 0x0F);
ts->bak_ref_len = (driver_num * (sensor_num - 2) + 2) * 2;
}
GTP_INFO("Drv * Sen: %d * %d(key: %d), X_MAX: %d, Y_MAX: %d, TRIGGER: 0x%02x",
driver_num, sensor_num, have_key, ts->abs_x_max,ts->abs_y_max,ts->int_trigger_type);
return 0;
}
else
#endif
{
#if GTP_DRIVER_SEND_CFG
GTP_INFO(" <%s>_%d \n", __func__, __LINE__);
ret = gtp_send_cfg(ts->client);
if (ret < 0)
{
GTP_ERROR("Send config error.");
}
// set config version to CTP_CFG_GROUP, for resume to send config
config[GTP_ADDR_LENGTH] = grp_cfg_version;
check_sum = 0;
for (i = GTP_ADDR_LENGTH; i < ts->gtp_cfg_len; i++)
{
check_sum += config[i];
}
config[ts->gtp_cfg_len] = (~check_sum) + 1;
#endif
GTP_INFO("X_MAX: %d, Y_MAX: %d, TRIGGER: 0x%02x", ts->abs_x_max,ts->abs_y_max,ts->int_trigger_type);
}
msleep(10);
return 0;
}
查看触摸屏中断次数及驱动加载是否正常
cat /proc/interrupts
Hexdump来查看是否有上报坐标信息。可借助Tslib工具测试触摸屏是否打印正确的坐标信息。
hexdump /dev/input/event1