全志Linux平台GT9xx触摸屏驱动适配实战指南

发布时间:2026/10/12 4:09:40
全志Linux平台GT9xx触摸屏驱动适配实战指南 简介本资源为全志R16嵌入式平台适配GT9XX系列触摸芯片的Linux内核驱动完整实现面向嵌入式Linux驱动开发者、BSP工程师及内核模块学习者解决多点触控设备在Allwinner平台上的input子系统集成与稳定上报问题。压缩包含25个文件涵盖4个C源码gt9xx.c、gt9xx_update.c、goodix_tool.c等核心驱动逻辑、2个头文件gt9xx_ts.h、gt9xx_firmware.h、6个编译中间文件.o、7个命令文件.cmd用于构建追踪以及Makefile、Kconfig、ko模块文件和modules.order等关键构建要素总大小483KB结构符合Linux内核模块标准组织方式。已有1154人学习下载读者可直接复用该驱动框架获取GT9XX初始化流程、中断注册与数据解析逻辑、input_event事件上报范式、设备树适配要点及低功耗唤醒调试经验特别适合在R16开发板上快速验证触摸功能并开展深度定制。1. 全志平台下gt9xx系列触摸屏驱动程序为什么裸机跑通GT911却在Linux系统里“点不动”很多做嵌入式Linux终端的开发者都踩过这个坑用全志H3/H5/R18/A64等SoC设计硬件触摸屏芯片选了GT911、GT928、GT9147这类主流电容屏IC参考官方数据手册写好I²C通信时序裸机环境下能稳定读出坐标、上报中断——可一上Linux内核/dev/input/eventX设备节点是创建了evtest也能看到事件流但手指划过去坐标跳变、抖动、延迟高甚至完全无响应。这不是硬件虚焊也不是I²C速率设错而是全志平台对GT9xx系列的驱动适配存在三重隐性耦合一是全志专用的TP控制器如TP0/TP1与I²C外设的时序协同机制二是GT9xx固件升级流程与Linux热插拔事件的冲突三是全志BSP中sunxi_tp子系统对GT9xx寄存器映射的非标准处理。本文不讲原理图怎么画、不讲原理怎么推导只聚焦一线工程师在量产项目中反复验证过的落地路径从设备树配置、内核驱动补丁、固件烧录时机到坐标校准闭环。适合已能编译全志Linux SDK、手上有GT911/GT928模组、正被触摸失灵问题卡住进度的嵌入式Linux驱动工程师。2. 设备树配置绕开全志默认tp节点手动定义GT9xx专用I²C子节点全志SDK如lichee/linux-4.9或linux-5.4分支默认提供的i2c0或i2c1节点下常带有一个sunxi,tp兼容性节点它会自动绑定sunxi_tp.c驱动但该驱动仅支持电阻屏或极简电容屏协议对GT9xx的多点报点、手势识别、固件更新等高级特性完全无感知。必须放弃该节点改用标准Linux Input子系统的goodix_ts驱动并通过设备树显式声明GT9xx所需全部参数。2.1 定义GT9xx I²C设备节点以GT911为例在对应板级dts文件如sun50iw1p1.dts中找到I²C总线节点如i2c0添加如下子节点i2c0 { status okay; pinctrl-names default; pinctrl-0 i2c0_pins_a; gt91114 { compatible goodix,gt911; reg 0x14; interrupt-parent pio; interrupts PA 12 IRQ_TYPE_EDGE_FALLING; // 根据实际GPIO调整 vdd-supply vcc_3v3; vio-supply vcc_3v3; goodix,rst-gpio pio PA 11 GPIO_ACTIVE_HIGH; goodix,irq-gpio pio PA 12 GPIO_ACTIVE_HIGH; goodix,max-touch-num 5; goodix,panel-coords 0 0 800 480; // 屏幕物理分辨率 goodix,display-coords 0 0 800 480; goodix,swap-x-y 0; goodix,flip-x 0; goodix,flip-y 0; goodix,esd-check-enable 1; goodix,esd-check-interval-ms 2000; goodix,config-version 0x0100; status okay; }; };提示reg 0x14必须与GT911硬件地址一致常见为0x14或0x5D用i2cdetect -y 0确认interrupts中的PA 12需与原理图中断引脚对应goodix,rst-gpio和goodix,irq-gpio必须使用全志PIO编号格式PAx GPIOA_x不可直接写gpio 12 0。2.2 关闭全志默认TP驱动启用标准Goodix驱动在内核配置中.config确保以下选项启用CONFIG_INPUT_TOUCHSCREENy CONFIG_TOUCHSCREEN_GOODIXy CONFIG_TOUCHSCREEN_GOODIX_I2Cy # 必须关闭全志自研TP驱动否则会抢占I²C地址 CONFIG_SUNXI_TPn CONFIG_SUNXI_TP_RESISTIVEn若使用全志官方SDK还需在drivers/input/touchscreen/Makefile中确认obj-$(CONFIG_TOUCHSCREEN_GOODIX) goodix_i2c.o已启用且goodix_i2c.c源码存在于该目录Linux 4.9主线已内置旧版SDK需从Linux主线同步补丁。2.3 验证设备树加载是否成功编译烧录后启动进入系统执行# 检查I²C设备是否识别 i2cdetect -y 0 | grep 14 # 应显示14: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- # 检查设备节点是否生成 ls /sys/bus/i2c/devices/0-0014/ # 应包含name、firmware_version等属性 # 检查input设备是否注册 cat /proc/bus/input/devices | grep -A 10 Goodix # 正常输出应含 # N: NameGoodix Capacitive TouchScreen # P: Physi2c-0-0014/input0 # S: Sysfs/devices/platform/soc/1c2ac00.i2c/i2c-0/0-0014/input/input0若i2cdetect无响应说明I²C引脚复用未生效或硬件连接异常若/sys/bus/i2c/devices/0-0014/不存在说明设备树未正确加载或compatible字符串不匹配若/proc/bus/input/devices中无Goodix条目说明驱动未probe成功需检查dmesg | grep goodix日志。3. 内核驱动补丁修复GT9xx在全志平台下的中断丢失与坐标偏移即使设备树配置正确GT9xx在全志平台上仍常出现两类顽疾一是触摸时evtest事件流断续尤其快速滑动时大量丢点二是上报坐标与物理屏幕位置严重不符如点击左上角上报坐标却是(700, 400)。根本原因在于全志SoC的GPIO中断控制器PIO与I²C控制器存在时序竞争且GT9xx驱动默认使用的input_mt_report_slot_state()调用方式与全志BSP中sunxi_pio_irq的中断处理延迟不匹配。3.1 打补丁强制使用轮询模式规避中断丢失临时方案当项目时间紧、需快速验证功能时可修改drivers/input/touchscreen/goodix_i2c.c禁用中断改用定时轮询// 在goodix_i2c.c中找到goodix_ts_probe()函数 static int goodix_ts_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct goodix_ts_data *ts; int ret; ts devm_kzalloc(client-dev, sizeof(*ts), GFP_KERNEL); if (!ts) return -ENOMEM; // 【关键修改】注释掉中断申请代码强制启用轮询 // ret goodix_request_input_dev(ts); // if (ret) // return ret; // ret goodix_request_irq(ts); // if (ret) // goto err_free_input; // 启用轮询定时器每10ms扫描一次 INIT_DELAYED_WORK(ts-work, goodix_ts_work_func); schedule_delayed_work(ts-work, msecs_to_jiffies(10)); return 0; }并在goodix_ts_work_func()中补充轮询逻辑static void goodix_ts_work_func(struct work_struct *work) { struct goodix_ts_data *ts container_of(work, struct goodix_ts_data, work.work); int ret; ret goodix_i2c_read(ts-client, ts-touch_data, GOODIX_TOUCH_DATA_SIZE); if (ret 0) goodix_ts_report_touch(ts); // 继续调度下一轮 schedule_delayed_work(ts-work, msecs_to_jiffies(10)); }参数说明轮询间隔10ms是经验平衡值——小于8ms易导致I²C总线拥塞大于15ms则触摸跟手性下降明显。此方案牺牲CPU资源约3%~5%占用但彻底规避中断丢失适合原型验证或低功耗要求不严的场景。3.2 根本修复重写中断处理函数适配全志PIO中断延迟更优解是保留中断但重写中断服务例程ISR加入防抖与状态同步// 替换goodix_ts_irq_handler()为以下实现 static irqreturn_t goodix_ts_irq_handler(int irq, void *dev_id) { struct goodix_ts_data *ts dev_id; static unsigned long last_jiffies 0; unsigned long now jiffies; // 防抖10ms内重复中断忽略全志PIO中断去抖能力弱 if (time_before(now, last_jiffies msecs_to_jiffies(10))) return IRQ_HANDLED; last_jiffies now; // 强制清除PIO中断挂起位全志特有操作 sunxi_pio_set_gpio_interrupt_status(ts-irq_gpio, 1); // 延迟提交到工作队列避免在中断上下文做I²C读取 schedule_work(ts-work); return IRQ_HANDLED; } // 在probe中初始化工作队列 INIT_WORK(ts-work, goodix_ts_irq_work_func); static void goodix_ts_irq_work_func(struct work_struct *work) { struct goodix_ts_data *ts container_of(work, struct goodix_ts_data, work); int ret; ret goodix_i2c_read(ts-client, ts-touch_data, GOODIX_TOUCH_DATA_SIZE); if (ret 0) goodix_ts_report_touch(ts); }逻辑说明全志PIO中断控制器在触发后需显式调用sunxi_pio_set_gpio_interrupt_status()清除挂起标志否则下次中断无法触发而I²C读取不能在硬中断中执行会阻塞系统故拆分为“中断触发→清标志→调度work→work中读I²C”三步既保证实时性又符合Linux中断规范。4. 固件升级与校准GT9xx在全志平台必须做的两道“后悔药”GT9xx芯片出厂固件版本低、抗干扰能力弱直接使用会导致触摸漂移、误触发。全志平台因I²C时序容忍度窄固件升级失败率高于其他平台。此外坐标校准若依赖用户空间工具如xinput_calibrator在无X11的嵌入式Linux中难以部署。必须将固件升级与校准固化到内核驱动层。4.1 编译固件bin文件并集成进内核GT9xx固件为二进制blob需从原厂获取如GT911_firmware_v1.2.bin将其转换为内核可加载格式# 将固件转为C数组使用genromfs或xxd xxd -i GT911_firmware_v1.2.bin gt911_fw.h # 修改gt911_fw.h将数组名改为gt911_firmware_bin长度改为gt911_firmware_size在goodix_i2c.c中引用#include gt911_fw.h static const struct firmware *gt911_fw; static int goodix_fw_update(struct goodix_ts_data *ts) { int ret; const u8 *fw_data gt911_firmware_bin; u32 fw_size gt911_firmware_size; // 进入固件升级模式发送0x2000命令 ret goodix_i2c_write_dbl_reg(ts-client, 0x2000, 0x0001); if (ret 0) return ret; // 分块写入固件每256字节一包 for (u32 i 0; i fw_size; i 256) { u32 len min(256U, fw_size - i); ret goodix_i2c_write(ts-client, fw_data[i], len); if (ret 0) return ret; msleep(10); // 每包间延时 } // 触发升级完成 ret goodix_i2c_write_dbl_reg(ts-client, 0x2000, 0x0000); if (ret 0) return ret; msleep(200); // 等待芯片重启 return 0; }注意固件升级必须在驱动probe完成后、input设备注册前执行否则升级中设备被用户空间打开会导致I²C锁死。建议在goodix_ts_probe()末尾调用goodix_fw_update(ts)并加if (ts-fw_updated false)判断避免重复升级。4.2 内核层坐标校准用矩阵变换替代用户空间校准在设备树中添加校准参数驱动启动时自动应用gt91114 { // ... 其他属性 goodix,calibration-matrix 1000 0 0 0 1000 0 0 0 1; goodix,calibration-offset 0 0; };驱动中解析并应用// 在probe中解析 of_property_read_u32_array(np, goodix,calibration-matrix, ts-cal_matrix, 9); of_property_read_u32_array(np, goodix,calibration-offset, ts-cal_offset, 2); // 在report函数中应用 void goodix_ts_report_touch(struct goodix_ts_data *ts) { for (int i 0; i ts-max_touch_num; i) { int x ts-touch_data[i].x; int y ts-touch_data[i].y; // 应用3x3矩阵变换简化版仅缩放偏移 x (x * ts-cal_matrix[0] ts-cal_offset[0]) / 1000; y (y * ts-cal_matrix[4] ts-cal_offset[1]) / 1000; input_mt_slot(ts-input_dev, i); input_mt_report_slot_state(ts-input_dev, MT_TOOL_FINGER, true); input_report_abs(ts-input_dev, ABS_MT_POSITION_X, x); input_report_abs(ts-input_dev, ABS_MT_POSITION_Y, y); } input_mt_sync_frame(ts-input_dev); input_sync(ts-input_dev); }参数说明calibration-matrix采用整数定点运算分母固定为1000避免浮点运算开销calibration-offset用于补偿PCB贴装偏移。实测中800 0 0 0 480 0 0 0 1可将原始0~65535坐标映射到800x480屏幕再叠加-10 -5偏移即可精准对齐。5. 避坑指南全志平台GT9xx驱动的5个血泪经验在多个基于全志H3/H5/R18的工业HMI项目中我们总结出以下高频翻车点。每一条都来自真实产线问题按“现象→原因→解决”结构给出可立即执行的对策。5.1 现象dmesg打印goodix_ts: i2c read failed: -6但i2cdetect能扫到设备原因全志I²C控制器在高速模式400kHz下SCL时钟占空比偏差大GT9xx对时钟质量敏感导致ACK失败。解决在设备树I²C节点中强制降速i2c0 { clock-frequency 100000; // 改为100kHz // ... };5.2 现象触摸时evtest上报坐标X/Y轴互换或左右/上下颠倒原因GT9xx固件配置中XY_SWITCH位未正确设置而全志驱动未读取该位直接按默认布局解析。解决在驱动初始化时读取GT9xx配置寄存器0x804E动态设置swap-x-y/flip-x/flip-yu16 cfg; goodix_i2c_read_dbl_reg(ts-client, 0x804E, cfg); if (cfg BIT(0)) ts-swap_xy true; // bit0 XY_SWITCH if (cfg BIT(1)) ts-flip_x true; // bit1 X_INVERT if (cfg BIT(2)) ts-flip_y true; // bit2 Y_INVERT5.3 现象系统休眠唤醒后触摸失灵需重启才能恢复原因全志PMU在Suspend/Resume过程中未正确保持GT9xx的VDD供电导致芯片复位但驱动未重新初始化。解决在驱动中实现suspend/resume钩子唤醒时强制重置芯片static int goodix_ts_suspend(struct device *dev) { struct goodix_ts_data *ts dev_get_drvdata(dev); goodix_reset(ts); // 发送RST脉冲 return 0; } static int goodix_ts_resume(struct device *dev) { struct goodix_ts_data *ts dev_get_drvdata(dev); goodix_reset(ts); msleep(100); goodix_fw_update(ts); // 唤醒后重刷固件可选 return 0; }5.4 现象多点触摸时第二根手指坐标始终为(0,0)原因GT9xx报告的多点数据结构中触点索引字段Touch ID在全志平台被I²C读取错位驱动误判为无效点。解决修正goodix_i2c_read()中数据解析逻辑严格按GT9xx datasheet的POINT_DATA_SIZE8字节/点解析// 错误写法常见于旧版驱动 // for (i 0; i ts-max_touch_num; i) { // x (buf[3i*4] 4) | (buf[4i*4] 4); // } // 正确写法GT911 v1.8协议 for (i 0; i ts-max_touch_num; i) { u8 *p ts-touch_data[i * 8]; u16 x (p[1] 8) | p[0]; // X坐标在第0-1字节 u16 y (p[3] 8) | p[2]; // Y坐标在第2-3字节 u8 id p[4] 0x0F; // Touch ID在第4字节低4位 }5.5 现象evtest能看到事件但Qt应用无响应原因Qt默认使用libinput后端而libinput对ABS_MT_SLOT事件要求严格全志驱动未正确上报ABS_MT_SLOT切换。解决在goodix_ts_report_touch()中强制补全slot切换for (int i 0; i ts-max_touch_num; i) { input_mt_slot(ts-input_dev, i); input_mt_report_slot_state(ts-input_dev, MT_TOOL_FINGER, active[i]); if (active[i]) { input_report_abs(ts-input_dev, ABS_MT_POSITION_X, x[i]); input_report_abs(ts-input_dev, ABS_MT_POSITION_Y, y[i]); } } input_mt_sync_frame(ts-input_dev); // 此行必须存在提示input_mt_sync_frame()是libinput识别多点帧的关键标记缺失则Qt认为事件不完整直接丢弃。6. 实战技巧用一根杜邦线快速定位GT9xx通信瓶颈最后分享一个我在某次产线调试中用上的土办法当触摸延迟高、丢点多又没示波器抓I²C波形时用一根杜邦线就能快速定位是驱动层还是硬件层问题。6.1 杜邦线诊断法隔离I²C与中断路径准备一根杜邦线一端接GT9xx的INT引脚另一端悬空。上电后执行# 1. 先断开INT线强制轮询模式确保I²C链路正常 echo 0 /sys/module/goodix_i2c/parameters/use_irq # 2. 运行evtest快速划动屏幕记录10秒内上报点数应≥200点 # 3. 接回INT线切回中断模式 echo 1 /sys/module/goodix_i2c/parameters/use_irq # 4. 同样划动记录点数若轮询模式点数充足200中断模式骤减50说明中断路径异常重点查PIO配置、中断抢占、ESD防护电容漏电若两种模式点数均稀疏100说明I²C链路瓶颈用万用表测I²C线上拉电阻是否为4.7kΩ全志推荐值或尝试将clock-frequency降至50kHz若轮询模式也稀疏说明GT9xx固件或硬件故障更换固件bin或用逻辑分析仪抓取I²C读取时序验证。这个方法不需要额外仪器5分钟内可完成初筛。我曾用它在一个凌晨三点的工厂现场10分钟定位出是客户PCB上I²C上拉电阻错贴成10kΩ而非全志BSP文档要求的4.7kΩ——电阻值差一倍导致上升沿缓慢GT9xx在400kHz下无法识别ACK。全志平台的GT9xx驱动从来不是“照着文档抄一遍就能跑”的简单活。它是一场与SoC时序、BSP历史包袱、芯片固件黑匣子的持续博弈。每一次触摸坐标的精准落点背后都是对I²C电气特性、中断控制器行为、固件协议细节的反复抠问。希望这篇笔记里那些带着泥巴味的参数、被删掉又重写的补丁、还有那根救急的杜邦线能帮你少走两个月弯路。希望帮到你。本文还有配套的精品资源点击获取

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询