evidence · 8.5 KiB
Committed at docs/evidence/touch-probe.txt. This is what grounds the requirements
that cite it.
The GT9895 binds to the backported goodix_berlin driver.
Captured on hardware 2026-09-20, extracted from docs/evidence/panel-probe.txt.
Device tree declares, in nix/dts/k230-tdisplay.dts:
touchscreen@5d {
compatible = "goodix,gt9895", "goodix,gt9916";
reg = <0x5d>;
reset-gpios = <&gpio0_ports 24 GPIO_ACTIVE_LOW>;
interrupt-parent = <&gpio0_ports>;
interrupts = <23 IRQ_TYPE_EDGE_FALLING>;
};
Kernel log:
[ 1.495480] goodix-berlin-i2c 1-005d: supply avdd not found, using dummy regulator
[ 1.495631] goodix-berlin-i2c 1-005d: supply iovdd not found, using dummy regulator
[ 1.652309] input: Goodix Berlin Capacitive TouchScreen as \
/devices/platform/soc/91408000.i2c/i2c-1/1-005d/input/input0
Resulting input device:
$ cat /proc/bus/input/devices
I: Bus=0018 Vendor=0000 Product=0000 Version=0000
N: Name="Goodix Berlin Capacitive TouchScreen"
P: Phys=input/ts
S: Sysfs=/devices/platform/soc/91408000.i2c/i2c-1/1-005d/input/input0
H: Handlers=mouse0 event0
B: PROP=2
B: EV=b
B: ABS=261800000000003
$ ls -l /dev/input/
crw-rw---- 1 root input 13, 64 event0
crw-rw---- 1 root input 13, 32 mouse0
WHAT THIS SETTLES
Task 4.1 asked which driver can drive this part, by experiment rather than
assumption. The answer is the v6.12 goodix_berlin backport, reached through
the "goodix,gt9916" fallback compatible.
It binds at address 0x5d on i2c-1 and registers an input device with
PROP=2 (INPUT_PROP_DIRECT, i.e. a touchscreen rather than a trackpad) and a
multitouch ABS bitmap. The driver reads its register layout off the part at
runtime from the IC-info blob at 0x10070 -- see gt9895-touch.md -- and
neither goodix_berlin_read_version() nor goodix_berlin_get_ic_info() logged
a failure, so the GT9895 answers the Berlin protocol.
Task 4.1b therefore resolves to NEITHER of its two branches. No gt9895_data
chip entry is added, because the driver has no chip table to add one to. No
port of LilyGO's RT-Smart gt9895.c is needed, because the backport works.
The only change required was the fallback compatible in the device tree.
STILL UNPROVEN
That it binds is not that it tracks. Task 4.3 requires an evtest transcript
of a deliberate drag, to show coordinates follow the finger and that the axes
are neither swapped nor mirrored on a portrait panel. Not yet captured.
The two "dummy regulator" lines mean avdd and iovdd are not described in the
device tree. The panel works, so they are evidently supplied in hardware,
but the device tree does not model them.
=====================================================================
2026-09-21 UPDATE: it binds, but it does not report
=====================================================================
Two evtest runs, 22s and 40s, with a finger dragged across the panel:
39 lines of output each time, all of it evtest's capability dump, and
ZERO "Event:" lines. No touch events at all.
The interrupt is wired and requested:
$ cat /proc/interrupts
87: 4 gpio-k230 23 Edge goodix-berlin
Four interrupts since boot. A 40-second drag would produce thousands.
So the line is correct, the driver claimed it, and the controller is not
asserting it when the panel is touched.
WHAT THIS CORRECTS
Task 4.1 was marked done on the evidence that the backported
goodix_berlin driver binds at 0x5d and registers an input device with
INPUT_PROP_DIRECT. That is still true and is literally what 4.1 asked for
("record whether it binds"). But it was reported here as "the GT9895
answers the Berlin protocol", and that claim is not supported: binding
proves the driver matched a compatible string and created a device node,
not that the controller is talking.
This is the same error made twice elsewhere in this project on the same
day -- treating a successful DSI write as proof the panel received it
(it only proves the controller's FIFO drained), and treating a faithful
transcription as proof it came from live code (it was dead code). The
pattern is accepting a proxy for the thing itself.
WHAT IS ACTUALLY UNKNOWN
- Whether the GT9895 needs a firmware or configuration upload that the
backported driver does not perform for this part. goodix_berlin reads
its register layout from the IC-info blob at 0x10070 at runtime; if
that read is returning something plausible-but-wrong the driver would
initialise without error and then never see data.
- Whether the IRQ polarity is right. Ours is IRQ_TYPE_EDGE_FALLING from
the reference board's touch controller, not from any GT9895 source.
- Whether the four interrupts seen are init-time or spurious.
NEXT STEP
Read back the controller over i2c directly -- i2cget on bus 1 address
0x5d -- and compare against what goodix_berlin expects. i2c-tools is in
the image. That distinguishes "the part is not responding" from "the
driver is misreading a part that is".
=====================================================================
i2c probe: the controller is alive and answering
=====================================================================
$ i2cdetect -y -r 1
50: -- -- -- -- -- -- -- -- -- -- -- -- -- UU -- -- (0x5d, claimed)
$ i2ctransfer -f -y 1 w4@0x5d 0x00 0x01 0x00 0x70 r16 # IC info, 0x10070
0xad 0x00 0x01 0x00 0x00 0x00 0x22 0xfc 0x0b 0x65 0x02 0x01 0x00 0x01 0x00 0x00
$ i2ctransfer -f -y 1 w4@0x5d 0x00 0x01 0x00 0x00 r8 # 0x10000
0xaa 0xaa 0xaa 0xaa 0xaa 0xaa 0xaa 0xaa
Real data, not 0xff (dead bus) and not 0x00. The GT9895 is present,
powered, and responding to 32-bit-addressed reads -- the Goodix Berlin
access pattern.
So the earlier framing of the problem was wrong in an instructive way.
"The panel does not answer" was true of the DISPLAY's DCS reads; the
TOUCH controller answers fine. These are different parts on different
buses and they were briefly conflated.
WHAT THIS LEAVES
The controller is alive on i2c and never asserts its interrupt (4 counts
since boot on IRQ 87, where a 40s drag would give thousands). That is a
driver-initialisation mismatch, not absent or broken hardware:
goodix_berlin derives every register address at runtime from the IC-info
blob above, so if a GT9895's layout differs from the GT9916 the driver
was written for, it will initialise without error, compute wrong
addresses, and then wait forever for data that is being written
somewhere else.
That is precisely branch two of task 4.1b -- "port LilyGO's RT-Smart
gt9895.c" -- and the i2c evidence now supports choosing it, where before
the choice rested on the driver merely having bound.
CONCRETE NEXT STEP
Decode the IC-info blob by hand against goodix_berlin_get_ic_info() and
check whether the addresses it derives are plausible. The first bytes
(0xad 0x00 0x01 0x00 ...) are a length and version header in the Berlin
format; if the length field does not match what the driver expects, the
parse silently produces garbage. LilyGO's gt9895.c in
repo/canmv_k230/src/rtsmart/ is the reference for what the layout should
be for this exact part.
=====================================================================
2026-09-21 RESOLVED (pending a boot): wrong interrupt trigger type
=====================================================================
The concrete next step above was taken. Both of its premises turned out
to be false and the answer was somewhere else.
The IC-info blob parses CORRECTLY. Length 0xad = 173 is exactly
2 + 16 + 10 + 4 + 25 + 114 + 2, where 114 is sizeof the driver's misc
struct and 25 is the five variable-length parameter arrays with counts
summing to 10. The decoded version fields are all in range. The parse
cannot be producing garbage.
LILYGO's RT-Smart gt9895.c has NO init sequence, NO config upload and
NO firmware upload -- it opens i2c and polls 90 bytes from 0x00010308,
which is the Berlin layout byte for byte (8-byte header, count in byte
2 low nibble, ten 8-byte points, 2-byte checksum). There is nothing for
a port to add.
The bug is the device tree. `IRQ_TYPE_EDGE_FALLING` was cloned from the
reference board's edt-ft5306 at k230-canmv-v3-lcd.dts:66. A Goodix
Berlin part holds INT low until the host clears the status byte, so it
wants IRQ_TYPE_LEVEL_LOW. caveman99/k230-linux runs this same driver on
this same board on this same kernel with LEVEL_LOW and working
multitouch; its /proc/interrupts line says "Level" where ours says
"Edge".
Also missing: touchscreen-size-x/y, without which the driver advertises
a 65536-unit axis for a 1024x2400 sensor.
Full decode, citations and the confirming sources are in
docs/evidence/gt9895-port.md. The fix is DTB-only.