ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

全志Linux平台GT9xx触摸屏驱动适配:从I2C设备树到坐标上报全解析

全志Linux平台GT9xx触摸屏驱动适配:从I2C设备树到坐标上报全解析 简介全志平台下 GT9XX 系列触摸屏驱动程序的完整工程面向嵌入式 Linux 驱动开发者用于在全志 R16 等 SoC 上适配和调试汇顶 GT9XX 触摸芯片涉及 input 子系统的注册与事件上报、I2C/SPI 通信、中断处理和电源管理等关键环节。压缩包为 rar 格式共 25 个文件、约 483KB包含 4 个 C 源码、2 个头文件、6 个 .o 编译目标、1 个 .ko 内核模块以及 Makefile、Kconfig 等构建配置适合直接分析或集成到内核源码。目前已有 1150 人学习具备一定参考价值。通过该资源可以快速掌握全志平台触摸屏驱动的初始化流程、触控数据解析和上报机制还能借助 goodix_tool 进行调试与固件升级为二次开发和产品移植提供了简洁的起点。 前阵子在一款全志H3的Linux板子上调触摸屏客户给的屏是GT9xx系的电容触摸屏就是汇顶那一大家子GT911、GT9147、GT9271这些。说实话全志平台本身在和平板类方案里覆盖面很广H3、V3s、A33、A20这些芯片配合GT9xx触控方案几乎是量产标配组合。这个适配过程踩了不少坑把驱动从内核态到设备树捋清楚了今天整理出来给正在全志Linux平台上折腾GT9xx的朋友做个参考。这篇内容适合三类人来读一是刚接触嵌入式Linux驱动、想搞懂输入子系统怎么跟具体触摸IC对上号的初学者二是手里有全志开发板、正被触摸屏“点了没反应”或者“坐标满天飞”折磨的量产工程师三是想搞明白I2C触摸屏驱动从设备树配置到上报坐标这条完整链路准备自己移植驱动的进阶玩家。我会把内核配置、设备树节点、驱动探测流程、常见故障排查全部拆开讲尽量说人话。1. 项目背景与整体思路1.1 为什么全志平台和GT9xx这么“搭”先聊点背景。全志的SoC在消费电子和智能硬件里之所以常见是因为成本控制好、BSPBoard Support Package比较完整H3这类芯片甚至被大量用在数播、掌机、智能家居中控屏上。这类产品几乎必然带一个触摸屏而GT9xx系列触摸屏控制IC在国产屏里出货量非常大价格便宜、性能稳定、支持多点触控和手势两者搭配可以说是天作之合。但“搭”不意味着“开箱即用”。全志的官方BSP里虽然带了gt9xx的驱动但内核版本不同、芯片平台不同驱动代码差异很大。有的平台用的还是老式的input设备注册方式有的已经切到devicetree platform_driver的结构还有的直接用主线的goodix驱动。你在A33上能跑的方案搬到H3上可能要改设备树再搬到V3s上可能连compatible都要重新对一遍。提示拿到一个新的全志方案别急着改代码先在板子上确认你的GT9xx具体型号、I2C地址、复位脚和中断脚分别接到了哪个GPIO这些信息决定了后面设备树怎么写也决定了驱动能不能探测成功。1.2 驱动适配的技术路线选择GT9xx的驱动适配有三条路我分别列一下方便你根据手上的内核版本做选择第一条路是用全志BSP自带的gt9xx专用驱动。这类驱动通常放在drivers/input/touchscreen/gt9xx/目录下特点是全志自己封装了I2C读写函数、固件下载接口还支持通过config字节来配置坐标翻转和分辨率。缺点是代码风格陈旧、API接口跟新内核5.x以后完全不兼容如果内核太新编译会报一堆错。第二条路是用主线内核自带的goodix.c驱动。从内核4.x开始主线里已经包含了汇顶GT911/GT912等型号的支持compatible通常是goodix,gt911。这条路的优点是代码干净、维护活跃而且完全基于设备树配置移植起来非常顺手。缺点是如果屏是定制固件可能需要额外处理配置表。第三条路是自己写一个精简的I2C驱动。说实话GT9xx的数据手册并不算复杂读取触摸坐标的核心寄存器就那么几个如果你只需要基础的单点或两点触摸完全可以自己实现。但我不建议一上来就自己写除非你是为了学习输入子系统否则能用现成驱动就别重复造轮子。从我的实际经验来看如果内核是5.4以上直接选主线goodix驱动最省心如果是全志BSP自带的3.10或4.9老内核那就用全志自己的gt9xx驱动。本篇文章主要围绕主线驱动和设备树配置来展开老内核的思路也能参考只是接口名不同。2. 驱动工作的核心原理解析2.1 GT9xx硬件特性和I2C通信要点GT9xx是一颗电容触摸控制IC它内部集成了电容感应通道、ADC采样、数字信号处理和坐标计算模块。主机通过I2C接口读取到的不是原始电容值而是已经算好的触摸点坐标、触摸轮廓大小等信息。这个设计大大简化了主控端的软件工作驱动只需要定时或中断触发读数据就行。GT9xx的I2C地址不是固定的常见有0x5D、0x14、0x28、0x29等具体取决于芯片的配置和外围电路INT引脚和RST引脚的上下拉关系会影响地址选择。这也是新手最容易卡住的地方你用i2cdetect扫描不到设备不一定是你接线错了很可能是地址没对上。注意如果你用i2cdetect扫描I2C总线0x28、0x29、0x5C、0x5D这些地址都试一下。我在一块板子上就遇到过设备树里写0x5D死活没反应后来发现屏的空闲地址是0x14改完马上就能读到数据。通信时序方面GT9xx支持标准I2C速率100kHz和快速模式400kHz在全志平台上我建议刚开始调试时把I2C时钟控制在100kHz尤其是屏线比较长或者排线质量一般的时候高速模式容易产生误码。等确认稳定之后再考虑拉到400kHz提升响应速度。2.2 内核驱动框架用“快递柜”理解输入子系统要理解GT9xx驱动在Linux里是怎么工作的可以先看一个生活化的类比。input子系统就像一个快递柜触摸屏驱动是“快递员”把“我在这儿摸了一下”这个信息装进一个标准包裹即input_event结构体投递到快递柜input_dev设备用户空间的应用程序去快递柜取件就能知道触摸事件。GT9xx驱动在这个体系里的职责有三块第一初始化硬件包括复位、配置、开中断第二在触摸中断触发时通过I2C读取坐标数据第三把读到的坐标封装成ABS_MT_POSITION_X、ABS_MT_POSITION_Y等事件通过input_report_abs和input_sync上报给内核。多点触控用的是Type B协议核心是按slot来区分触摸点。每个触摸点有一个独立的ABS_MT_SLOT每个slot维护自己的tracking id。比如你的屏支持5点触摸那就有5个slot每个slot里轮流上报对应的坐标。Type B的好处是内核能判断哪些触摸点是同一个手指在连续滑动从而做更好的手势识别。驱动探测成功后你会在系统里看到一个类似/dev/input/event1的设备节点。这个节点就是用户空间的入口应用层直接open它循环readinput_event结构体就能拿到触摸数据。EV测试工具evtest也是这么干的所以驱动调好了用evtest能立刻看到报点信息。3. 实操从内核配置到设备树适配3.1 内核配置打开对应的触摸驱动开关以主线内核为例先把配置项打开。你要确保内核开启了I2C子系统、GPIO中断、以及gt9xx对应的触摸驱动。一般执行make menuconfig在路径Device Drivers - Input device support - Touchscreens - Goodix touchscreen下勾选即可对应的配置项是CONFIG_TOUCHSCREEN_GOODIX。全志老BSP内核可能选项名字不同有的在Device Drivers - Input device support - Touchscreens - GT9XX based I2C touchscreen配置项为CONFIG_TOUCHSCREEN_GT9XX。如果找不到可以到drivers/input/touchscreen目录下翻一下Makefile和Kconfig看看有哪些源文件再用grep搜索GT9XX或GT9xx关键字。实操心得我习惯直接把驱动编成模块m这样调试时反复insmod、rmmod不用重新烧整个内核省不少时间。等驱动稳定后再改成内建y避免启动时加载顺序的问题。3.2 设备树节点和关键参数逐项拆解设备树是驱动与硬件连接的“接线图”。我在全志H3平台上的设备树节点长这样你可以直接参考i2c0 { status okay; clock-frequency 100000; gt911: touchscreen5d { compatible goodix,gt911; reg 0x5d; interrupt-parent pio; interrupts PA 21 IRQ_TYPE_EDGE_FALLING; irq-gpios pio PA 21 GPIO_ACTIVE_HIGH; reset-gpios pio PA 20 GPIO_ACTIVE_HIGH; touchscreen-size-x 1024; touchscreen-size-y 600; touchscreen-inverted-x; touchscreen-inverted-y; }; };下面逐项解释关键参数为什么这么配。compatible这一项决定了驱动用哪个of_match_table来匹配。主线驱动认的是goodix,gt911。如果你的板子用的是GT9147可以写成goodix,gt9147GT9271写成goodix,gt9271。驱动会根据不同的型号走不同的初始化流程。reg必须和实际I2C地址一致。这里有个关键点reg在设备树里是7位地址也就是屏蔽掉读写位之后的地址。如果芯片手册说8位地址是0xBA那它对应的7位地址就是0x5D0xBA 1。很多新手直接把8位地址写进设备树导致I2C探测失败这是一个非常高发的错误。interrupts和irq-gpios是中断脚配置。全志用interrupt-parent pio表示中断控制器的父节点是PIOGPIO控制器PA 21是“PA组第21号引脚”。触发方式我用的是IRQ_TYPE_EDGE_FALLING下降沿触发这是因为GT9xx在检测到触摸时会拉低INT脚通知主控下降沿触发最合适。touchscreen-size-x和touchscreen-size-y是屏的分辨率必须跟屏幕实际物理分辨率对应。注意这个值不是屏幕像素值而是GT9xx控制器内部坐标的最大值。如果你想支持更高的坐标精度可以在驱动初始化时写入配置表修改但一般用屏幕物理分辨率就好。touchscreen-inverted-x和touchscreen-inverted-y是坐标翻转。电容屏不像电阻屏需要“四点校准”它的每个触摸点坐标是相对固定的但如果你把屏接反了或者屏本身的坐标方向和面板方向不一致就需要用这两个属性把坐标轴翻转过来。实际调试时先用evtest观察触摸点和手指位置的关系再决定要不要翻。3.3 编译、烧录和验证驱动是否生效设备树改完编译设备树二进制文件DTS编译成DTB关掉老的gt9xx驱动或者确保compatible不冲突然后重新编译内核或模块。启动后用以下几条命令验证# 查看I2C总线上是否有对应设备 i2cdetect -y 0 # 查看input设备注册情况 cat /proc/bus/input/devices # 查看内核日志确认驱动初始化信息 dmesg | grep -i goodix # 实时查看触摸事件 evtest /dev/input/event1正常情况你会看到i2cdetect扫描出0x5d位置的设备dmesg里出现类似goodix-ts的初始化成功日志evtest里能实时看到触摸点坐标。如果这几步都能走通驱动适配就算成功了80%剩下的就是性能和稳定性的细节打磨。4. 故障排查解决五种高频问题4.1 触摸完全无响应设备没在I2C总线上现身这是最常见的故障通常是地址不对或者复位时序不对。先用i2cdetect -y 0扫描看有没有设备挂在总线上。如果没有首先检查GPIO复用配置全志芯片的引脚功能非常灵活默认情况下PA21不一定复用成GPIO输入功能可能需要设置pinctrl属性。另一个常见原因是上电时序不对GT9xx要求先上电再拉高复位脚延时至少10ms后才开始I2C通信有些板子的复位电路RC常数太大会导致芯片还没准备好就去读。排查技巧用一个很简单的User LED脚当GPIO来模拟手动复位——拉低复位脚50ms再拉高隔100ms再去i2cdetect。如果手动复位后能扫到设备说明驱动里的复位时序有问题优先改等待时间。4.2 能识别设备但点击没反应如果i2cdetect能看到设备、dmesg也没有报错但触摸没反应多半是中断没触发或者input设备没按预期工作。先用cat /proc/interrupts | grep gpio看一下中断计数有没有在手指触摸时增加。如果计数不动检查设备树里的interrupts属性、GPIO是否被其他驱动占用、中断号是否算错。如果中断有触发但evtest没数据重点查驱动读坐标寄存器的流程是否正常可以在驱动里加dev_info打印每次中断读到的原始数据。4.3 坐标乱飞、光标自己抖这个在热搜词里对应“ubuntu触摸屏鼠标乱飞”但在全志Linux板子上也经常出现。坐标乱飞的原因主要有三个一是电源纹波太大触摸IC的参考电压不稳定导致误报二是I2C总线受到干扰读回来的数据是错的三是软件没有做好滤波把噪声点当成有效触摸上报了。我的处理经验是先用示波器看触摸屏排线的电源和I2C波形确认硬件层面是否有毛刺。软件层面可以在驱动里增加一个简单的“邻近点过滤”逻辑即本次报点的坐标和上一次报点的坐标距离超过某个阈值比如屏幕对角线长度的30%就认为是无效点直接丢弃。这样做对误报的抑制效果非常明显。4.4 检测到触摸但是响应延迟明显延迟问题通常出在中断处理或I2C读取速度上。GT9xx在每次触摸事件后会连续上报多帧坐标数据。如果驱动用轮询方式读坐标或者中断处理里做了太多延时操作响应自然慢。优化方向是确认中断触发方式是边沿触发而不是电平触发同时把I2C频率从100kHz调到400kHz并在中断回调里用disable_irq把中断关掉读完数据再重新开。这里有个容易被忽略的点如果驱动在中断上下文里调用了i2c_transfer要注意I2C控制器本身是否支持原子操作。全志的一些I2C控制器驱动在CONFIG_PREEMPT_RT实时内核下会要求I2C传输带irq的上下文处理方式搞不好会直接报BUG: scheduling while atomic。遇到这个问题可以考虑把读坐标的操作放到工作队列workqueue里执行。4.5 反转坐标和旋转屏的问题最后说说屏幕旋转时坐标怎么处理。大多数全志方案用的是横屏屏但有的产品做成竖屏或者屏本身安装方向旋转了180度。电容屏没有“校准”概念只能在设备树里做坐标变换。坐标翻转有四种组合touchscreen-inverted-x、touchscreen-inverted-y以及两个属性组合起来实现180度旋转。如果屏幕旋转90度那就不只是翻转而是X、Y轴互换这时你不能只靠设备树属性解决要么在驱动里交换坐标轴上报要么在应用层做旋转。我建议驱动里保持原始坐标旋转统一交给应用层处理这样驱动更通用也方便适配不同方向的产品。5. 全志平台GT9xx驱动调试的个人心得跟全志平台和GT9xx打交道这几年最大的感受是——这类老牌国产芯片和触摸IC的组合问题几乎不出在技术方案上而出在“信息断层”上。全志的BSP更新慢、文档分散GT9xx手册也不是随便能拿到最全的版本很多时候得靠对比不同Linux版本驱动源代码、试寄存器地址、看内核日志来逆向推断硬件行为。几个实在的建议第一设备树里尽可能把GPIO、中断、分辨率一次配对减少反复编译内核的时间第二调试阶段一定把内核的CONFIG_INPUT相关调试选项打开日志输出选择dynamic_debug这样能省去反复改代码加打印的麻烦第三手头准备一个逻辑分析仪关键时刻比示波器快得多抓一下I2C波形就知道是芯片没工作还是驱动没读对第四别迷信全志BSP自带的驱动如果内核版本允许优先用主线驱动社区的bug修复和硬件适配覆盖更全面。最后分享一个我在交付量产方案时常用的小技巧在驱动里预留一个sysfs节点允许运行时动态调整坐标翻转和分辨率。这样就算客户换了不同尺寸的屏你也不用重新编译内核直接在应用里通过文件接口写入参数就行。这个思路在项目紧张的时候能救急平时维护多型号产品线也非常实用算是这次适配经历中沉淀下来最值钱的经验之一。本文还有配套的精品资源点击获取
返回列表