Appendix · reference

Goodix GT911 touchscreen

PineTab2 capacitive touch controller on i2c1; shared Goodix driver, bench pending.

Identity

PartGoodix GT911
RoleCapacitive multitouch controller for the PineTab2 panel
Bus / addressPineTab2 i2c1 addr 0x5d; FreeBSD iicbus uses shifted address 0xba internally
GPIO / IRQIRQ GPIO0_B0, falling edge; reset GPIO0_C2
SuppliesAVDD28 = vcc3v3_pmu, VDDIO = vcca1v8_pmu
DTS compatiblegoodix,gt911

Status — ◐ partial

The PinePhone Pro Goodix driver is now generalized for the PineTab2 GT911 instance. It matches both goodix,gt917s and goodix,gt911, selects the correct I2C address during reset, and uses the model’s matching configuration block: GT917S stays on 0x8050 / 240 bytes, while GT911 uses the GT9x 0x8047 / 186-byte block.

This is still hardware-pending. The expected first PineTab2 evidence is that goodix0 probes at 0x5d, reports chip ID 911, exposes dev.goodix.0.config_addr=32839 (0x8047), and registers an evdev touchscreen. Real coordinate orientation waits until the internal DSI panel path is active; before that, the touch controller can still be proved over I2C and evdev.

Driver Notes

src/sys/dev/iicbus/goodix.c c
1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause
3 *
4 * Copyright (c) 2026 Josh Adams
5 *
6 * Goodix GT9xx Touchscreen Driver
7 *
8 * Multitouch I2C touchscreen controller for PinePhone Pro and PineTab2.
9 * Reports touch events via evdev MT Protocol B.
10 */
11
12 #include <sys/param.h>
13 #include <sys/systm.h>
14 #include <sys/bus.h>
15 #include <sys/callout.h>
16 #include <sys/kernel.h>
17 #include <sys/taskqueue.h>
18 #include <sys/module.h>
19 #include <sys/endian.h>
20 #include <sys/gpio.h>
21 #include <sys/rman.h>
22 #include <sys/sysctl.h>
23 #include <machine/bus.h>
24 #include <machine/resource.h>
25
26 #include <dev/iicbus/iicbus.h>
27 #include <dev/iicbus/iiconf.h>
28
29 #include <dev/evdev/evdev.h>
30 #include <dev/evdev/input.h>
31
32 #include <dev/gpio/gpiobusvar.h>
33
34 #include <dev/ofw/ofw_bus.h>
35 #include <dev/ofw/ofw_bus_subr.h>
36
37 /* Goodix registers (16-bit big-endian addresses) */
38 #define GOODIX_REG_ID 0x8140
39 #define GOODIX_GT1X_REG_CONFIG 0x8050
40 #define GOODIX_GT9X_REG_CONFIG 0x8047
41 #define GOODIX_REG_STATUS 0x814E
42 #define GOODIX_CONFIG_GT911_LEN 186
43 #define GOODIX_CONFIG_GT9X_LEN 240
44
45 /* Touch contact: 8 bytes per point */
46 #define GOODIX_CONTACT_SIZE 8
47 #define GOODIX_MAX_CONTACTS 10
48
49 enum goodix_model_id {
50 GOODIX_MODEL_GT917S = 1,
51 GOODIX_MODEL_GT911,
52 };
53
54 struct goodix_model {
55 enum goodix_model_id id;
56 const char *desc;
57 const char *evdev_name;
58 uint16_t product;
59 uint16_t config_addr;
60 uint16_t config_len;
61 uint16_t fallback_x;
62 uint16_t fallback_y;
63 uint8_t fallback_touches;
64 };
65
66 static const struct goodix_model goodix_models[] = {
67 {
68 .id = GOODIX_MODEL_GT917S,
69 .desc = "Goodix GT917S Touchscreen",
70 .evdev_name = "Goodix GT917S Touchscreen",
71 .product = 0x9170,
72 .config_addr = GOODIX_GT1X_REG_CONFIG,
73 .config_len = GOODIX_CONFIG_GT9X_LEN,
74 .fallback_x = 720,
75 .fallback_y = 1440,
76 .fallback_touches = 5,
77 },
78 {
79 .id = GOODIX_MODEL_GT911,
80 .desc = "Goodix GT911 Touchscreen",
81 .evdev_name = "Goodix GT911 Touchscreen",
82 .product = 0x0911,
83 .config_addr = GOODIX_GT9X_REG_CONFIG,
84 .config_len = GOODIX_CONFIG_GT911_LEN,
85 .fallback_x = 1280,
86 .fallback_y = 800,
87 .fallback_touches = 5,
88 },
89 };
90
91 static const struct ofw_compat_data goodix_compat[] = {
92 { "goodix,gt917s", GOODIX_MODEL_GT917S },
93 { "goodix,gt911", GOODIX_MODEL_GT911 },
94 { NULL, 0 },
95 };
96
97 struct goodix_softc {
98 device_t sc_dev;
99 const struct goodix_model *sc_model;
100 uint16_t sc_addr; /* I2C address (shifted) */
101 uint16_t sc_addr7;
102 gpio_pin_t sc_rst_pin;
103 gpio_pin_t sc_int_pin;
104 struct evdev_dev *sc_evdev;
105 struct resource *sc_irq_res;
106 void *sc_irq_hdl;
107 struct callout sc_poll_callout;
108 struct task sc_poll_task;
109 uint16_t sc_max_x;
110 uint16_t sc_max_y;
111 uint16_t sc_dt_max_x;
112 uint16_t sc_dt_max_y;
113 uint16_t sc_version;
114 uint16_t sc_config_addr;
115 uint16_t sc_config_len;
116 uint8_t sc_max_touch;
117 uint8_t sc_polling;
118 char sc_chip_id[5];
119 uint8_t sc_contact_buf[GOODIX_MAX_CONTACTS * GOODIX_CONTACT_SIZE];
120 /* Track which slots are active for release detection */
121 uint16_t sc_active_slots;
122 };
123
124 static const struct goodix_model *
125 goodix_model_by_id(enum goodix_model_id id)
126 {
127 int i;
128
129 for (i = 0; i < nitems(goodix_models); i++) {
130 if (goodix_models[i].id == id)
131 return (&goodix_models[i]);
132 }
133
134 return (NULL);
135 }
136
137 static const struct goodix_model *
138 goodix_model_for_dev(device_t dev)
139 {
140 const struct ofw_compat_data *compat;
141
142 compat = ofw_bus_search_compatible(dev, goodix_compat);
143 if (compat->ocd_data == 0)
144 return (NULL);
145
146 return (goodix_model_by_id((enum goodix_model_id)compat->ocd_data));
147 }
148
149 static uint16_t
150 goodix_addr_7bit(struct goodix_softc *sc)
151 {
152
153 if (sc->sc_addr > 0x7f)
154 return (sc->sc_addr >> 1);
155
156 return (sc->sc_addr);
157 }
158
159 static uint16_t
160 goodix_fallback_x(struct goodix_softc *sc)
161 {
162
163 if (sc->sc_dt_max_x != 0)
164 return (sc->sc_dt_max_x);
165
166 return (sc->sc_model->fallback_x);
167 }
168
169 static uint16_t
170 goodix_fallback_y(struct goodix_softc *sc)
171 {
172
173 if (sc->sc_dt_max_y != 0)
174 return (sc->sc_dt_max_y);
175
176 return (sc->sc_model->fallback_y);
177 }
178
179 static void
180 goodix_read_size_prop(phandle_t node, const char *name, uint16_t *val)
181 {
182 uint32_t tmp;
183
184 if (OF_getencprop(node, name, &tmp, sizeof(tmp)) > 0 &&
185 tmp <= 0xffff)
186 *val = tmp;
187 }
188
189 static int
190 goodix_read(struct goodix_softc *sc, uint16_t reg, uint8_t *buf, uint16_t len)
191 {
192 uint8_t reg_buf[2];
193 struct iic_msg msgs[2];
194
195 reg_buf[0] = reg >> 8;
196 reg_buf[1] = reg & 0xFF;
197
198 msgs[0].slave = sc->sc_addr;
199 msgs[0].flags = IIC_M_WR;
200 msgs[0].len = 2;
201 msgs[0].buf = reg_buf;
202
203 msgs[1].slave = sc->sc_addr;
204 msgs[1].flags = IIC_M_RD;
205 msgs[1].len = len;
206 msgs[1].buf = buf;
207
208 return (iicbus_transfer(sc->sc_dev, msgs, 2));
209 }
210
211 static int
212 goodix_write_u8(struct goodix_softc *sc, uint16_t reg, uint8_t val)
213 {
214 uint8_t buf[3];
215 struct iic_msg msg;
216
217 buf[0] = reg >> 8;
218 buf[1] = reg & 0xFF;
219 buf[2] = val;
220
221 msg.slave = sc->sc_addr;
222 msg.flags = IIC_M_WR;
223 msg.len = 3;
224 msg.buf = buf;
225
226 return (iicbus_transfer(sc->sc_dev, &msg, 1));
227 }
228
229 static int
230 goodix_reset(struct goodix_softc *sc)
231 {
232 uint16_t addr7;
233 bool int_high;
234 int error;
235
236 if (sc->sc_rst_pin == NULL || sc->sc_int_pin == NULL)
237 return (0); /* No GPIOs, skip reset */
238
239 addr7 = goodix_addr_7bit(sc);
240 if (addr7 != 0x14 && addr7 != 0x5d) {
241 device_printf(sc->sc_dev,
242 "unsupported reset address select for I2C addr 0x%02x\n",
243 addr7);
244 return (EINVAL);
245 }
246 int_high = (addr7 == 0x14);
247
248 /* Drive RST low */
249 gpio_pin_setflags(sc->sc_rst_pin, GPIO_PIN_OUTPUT);
250 gpio_pin_set_active(sc->sc_rst_pin, false);
251 DELAY(20000); /* 20ms */
252
253 /* HIGH selects 0x14; LOW selects 0x5d. */
254 gpio_pin_setflags(sc->sc_int_pin, GPIO_PIN_OUTPUT);
255 gpio_pin_set_active(sc->sc_int_pin, int_high);
256 DELAY(100); /* 100us */
257
258 /* Release RST */
259 gpio_pin_set_active(sc->sc_rst_pin, true);
260 DELAY(6000); /* 6ms */
261
262 /* INT sync: drive low 50ms, then set as input */
263 gpio_pin_set_active(sc->sc_int_pin, false);
264 DELAY(50000); /* 50ms */
265
266 error = gpio_pin_setflags(sc->sc_int_pin, GPIO_PIN_INPUT);
267
268 DELAY(50000); /* 50ms settle */
269 return (error);
270 }
271
272 static int
273 goodix_read_version(struct goodix_softc *sc)
274 {
275 uint8_t buf[6];
276 int error;
277
278 error = goodix_read(sc, GOODIX_REG_ID, buf, 6);
279 if (error)
280 return (error);
281
282 memcpy(sc->sc_chip_id, buf, 4);
283 sc->sc_chip_id[4] = '\0';
284 sc->sc_version = le16dec(&buf[4]);
285
286 device_printf(sc->sc_dev, "Goodix chip ID: %c%c%c%c version: %02x%02x\n",
287 buf[0], buf[1], buf[2], buf[3], buf[5], buf[4]);
288 return (0);
289 }
290
291 static int
292 goodix_read_config(struct goodix_softc *sc)
293 {
294 uint8_t cfg[GOODIX_CONFIG_GT9X_LEN];
295 int error;
296
297 error = goodix_read(sc, sc->sc_model->config_addr, cfg,
298 sc->sc_model->config_len);
299 if (error) {
300 device_printf(sc->sc_dev,
301 "Failed to read config at 0x%04x len %u: %d; using fallback geometry\n",
302 sc->sc_model->config_addr, sc->sc_model->config_len, error);
303 sc->sc_max_x = goodix_fallback_x(sc);
304 sc->sc_max_y = goodix_fallback_y(sc);
305 sc->sc_max_touch = sc->sc_model->fallback_touches;
306 return (0);
307 }
308
309 sc->sc_max_x = le16dec(&cfg[1]);
310 sc->sc_max_y = le16dec(&cfg[3]);
311 sc->sc_max_touch = cfg[5] & 0x0F;
312
313 if (sc->sc_max_x == 0)
314 sc->sc_max_x = goodix_fallback_x(sc);
315 if (sc->sc_max_y == 0)
316 sc->sc_max_y = goodix_fallback_y(sc);
317 if (sc->sc_max_touch == 0)
318 sc->sc_max_touch = sc->sc_model->fallback_touches;
319 else if (sc->sc_max_touch > GOODIX_MAX_CONTACTS)
320 sc->sc_max_touch = GOODIX_MAX_CONTACTS;
321
322 device_printf(sc->sc_dev, "Resolution: %dx%d, max touches: %d\n",
323 sc->sc_max_x, sc->sc_max_y, sc->sc_max_touch);
324 return (0);
325 }
326
327 static void goodix_poll(void *arg);
328
329 static void
330 goodix_intr(void *arg)
331 {
332 struct goodix_softc *sc = arg;
333 uint8_t header[1 + GOODIX_CONTACT_SIZE]; /* status + first contact */
334 uint8_t touch_count;
335 uint16_t new_active = 0;
336 int error, i;
337
338 /* Read status byte + first contact */
339 error = goodix_read(sc, GOODIX_REG_STATUS, header, sizeof(header));
340 if (error)
341 goto clear;
342
343 /* Bit 7 = buffer ready */
344 if (!(header[0] & 0x80))
345 goto clear;
346
347 touch_count = header[0] & 0x0F;
348 if (touch_count > sc->sc_max_touch)
349 touch_count = sc->sc_max_touch;
350
351 /* Read remaining contacts if more than 1 */
352 if (touch_count > 1) {
353 error = goodix_read(sc,
354 GOODIX_REG_STATUS + 1 + GOODIX_CONTACT_SIZE,
355 sc->sc_contact_buf,
356 (touch_count - 1) * GOODIX_CONTACT_SIZE);
357 if (error)
358 goto clear;
359 }
360
361 /* Process each touch point */
362 for (i = 0; i < touch_count; i++) {
363 uint8_t *contact;
364 uint8_t id;
365 uint16_t x, y, w;
366
367 if (i == 0)
368 contact = &header[1];
369 else
370 contact = &sc->sc_contact_buf[(i - 1) * GOODIX_CONTACT_SIZE];
371
372 id = contact[0] & 0x0F;
373 x = le16dec(&contact[1]);
374 y = le16dec(&contact[3]);
375 w = le16dec(&contact[5]);
376
377 if (id >= sc->sc_max_touch)
378 continue;
379
380 new_active |= (1 << id);
381
382 evdev_push_abs(sc->sc_evdev, ABS_MT_SLOT, id);
383 evdev_push_abs(sc->sc_evdev, ABS_MT_TRACKING_ID, id);
384 evdev_push_abs(sc->sc_evdev, ABS_MT_POSITION_X, x);
385 evdev_push_abs(sc->sc_evdev, ABS_MT_POSITION_Y, y);
386 evdev_push_abs(sc->sc_evdev, ABS_MT_TOUCH_MAJOR, w);
387 }
388
389 /* Release slots that are no longer active */
390 for (i = 0; i < sc->sc_max_touch; i++) {
391 if ((sc->sc_active_slots & (1 << i)) &&
392 !(new_active & (1 << i))) {
393 evdev_push_abs(sc->sc_evdev, ABS_MT_SLOT, i);
394 evdev_push_abs(sc->sc_evdev, ABS_MT_TRACKING_ID, -1);
395 }
396 }
397 sc->sc_active_slots = new_active;
398
399 /* Report single-touch ABS_X/Y from first contact for libinput */
400 if (touch_count > 0) {
401 evdev_push_abs(sc->sc_evdev, ABS_X,
402 le16dec(&header[1 + 1]));
403 evdev_push_abs(sc->sc_evdev, ABS_Y,
404 le16dec(&header[1 + 3]));
405 }
406
407 evdev_push_key(sc->sc_evdev, BTN_TOUCH, touch_count > 0);
408 evdev_sync(sc->sc_evdev);
409
410 clear:
411 /* Clear status, required by Goodix protocol. */
412 goodix_write_u8(sc, GOODIX_REG_STATUS, 0);
413
414 /* Re-arm polling timer if in polling mode */
415 if (sc->sc_polling)
416 callout_reset(&sc->sc_poll_callout, hz / 100,
417 goodix_poll, sc);
418 }
419
420 static void
421 goodix_poll_task(void *arg, int pending)
422 {
423 struct goodix_softc *sc = arg;
424
425 goodix_intr(sc);
426 }
427
428 static void
429 goodix_poll(void *arg)
430 {
431 struct goodix_softc *sc = arg;
432
433 /*
434 * Callout runs in softclock context where sleeping is prohibited.
435 * Defer the actual I2C work to a taskqueue thread.
436 */
437 taskqueue_enqueue(taskqueue_thread, &sc->sc_poll_task);
438 }
439
440 static int
441 goodix_probe(device_t dev)
442 {
443 const struct goodix_model *model;
444
445 if (!ofw_bus_status_okay(dev))
446 return (ENXIO);
447 model = goodix_model_for_dev(dev);
448 if (model == NULL)
449 return (ENXIO);
450
451 device_set_desc(dev, model->desc);
452 return (BUS_PROBE_DEFAULT);
453 }
454
455 static int
456 goodix_attach(device_t dev)
457 {
458 struct goodix_softc *sc;
459 struct sysctl_ctx_list *ctx;
460 struct sysctl_oid_list *tree;
461 phandle_t node;
462 int error, rid;
463
464 sc = device_get_softc(dev);
465 sc->sc_dev = dev;
466 sc->sc_model = goodix_model_for_dev(dev);
467 if (sc->sc_model == NULL)
468 return (ENXIO);
469 sc->sc_addr = iicbus_get_addr(dev);
470 sc->sc_addr7 = goodix_addr_7bit(sc);
471 sc->sc_config_addr = sc->sc_model->config_addr;
472 sc->sc_config_len = sc->sc_model->config_len;
473
474 /* Get GPIOs from device tree */
475 node = ofw_bus_get_node(dev);
476 goodix_read_size_prop(node, "touchscreen-size-x", &sc->sc_dt_max_x);
477 goodix_read_size_prop(node, "touchscreen-size-y", &sc->sc_dt_max_y);
478
479 if (bootverbose)
480 device_printf(dev, "OFW node: 0x%x\n", node);
481
482 error = gpio_pin_get_by_ofw_property(dev, node, "reset-gpios",
483 &sc->sc_rst_pin);
484 if (error)
485 device_printf(dev, "No reset GPIO: %d\n", error);
486
487 error = gpio_pin_get_by_ofw_property(dev, node, "irq-gpios",
488 &sc->sc_int_pin);
489 if (error)
490 device_printf(dev, "No IRQ GPIO: %d\n", error);
491
492 /* Reset the controller */
493 error = goodix_reset(sc);
494 if (error)
495 device_printf(dev, "Reset failed: %d (continuing)\n", error);
496
497 /* Read chip ID and version */
498 error = goodix_read_version(sc);
499 if (error) {
500 device_printf(dev, "Failed to read version: %d\n", error);
501 return (error);
502 }
503
504 /* Read config (resolution, max touches) */
505 error = goodix_read_config(sc);
506 if (error)
507 return (error);
508
509 /* Create evdev device */
510 sc->sc_evdev = evdev_alloc();
511 evdev_set_name(sc->sc_evdev, sc->sc_model->evdev_name);
512 evdev_set_phys(sc->sc_evdev, device_get_nameunit(dev));
513 evdev_set_id(sc->sc_evdev, BUS_I2C, 0x0416, sc->sc_model->product,
514 0x0001);
515
516 evdev_support_event(sc->sc_evdev, EV_SYN);
517 evdev_support_event(sc->sc_evdev, EV_ABS);
518 evdev_support_event(sc->sc_evdev, EV_KEY);
519
520 evdev_support_abs(sc->sc_evdev, ABS_MT_SLOT,
521 0, sc->sc_max_touch - 1, 0, 0, 0);
522 evdev_support_abs(sc->sc_evdev, ABS_MT_TRACKING_ID,
523 -1, 65535, 0, 0, 0);
524 evdev_support_abs(sc->sc_evdev, ABS_MT_POSITION_X,
525 0, sc->sc_max_x, 0, 0, 0);
526 evdev_support_abs(sc->sc_evdev, ABS_MT_POSITION_Y,
527 0, sc->sc_max_y, 0, 0, 0);
528 evdev_support_abs(sc->sc_evdev, ABS_MT_TOUCH_MAJOR,
529 0, 255, 0, 0, 0);
530
531 /* Single-touch axes, required for libinput touchscreen classification. */
532 evdev_support_abs(sc->sc_evdev, ABS_X,
533 0, sc->sc_max_x, 0, 0, 0);
534 evdev_support_abs(sc->sc_evdev, ABS_Y,
535 0, sc->sc_max_y, 0, 0, 0);
536
537 evdev_support_key(sc->sc_evdev, BTN_TOUCH);
538 evdev_support_prop(sc->sc_evdev, INPUT_PROP_DIRECT);
539
540 error = evdev_register(sc->sc_evdev);
541 if (error) {
542 device_printf(dev, "evdev register failed: %d\n", error);
543 evdev_free(sc->sc_evdev);
544 return (error);
545 }
546
547 /*
548 * Setup interrupt. ofw_iicbus_attach already populated our
549 * resource list with the IRQ derived from the FDT `interrupts`
550 * property mapped through the gpio3 PIC. The matching kernel-side
551 * fix is patches/.../rk_i2c.c.patch. Without that, rk_i2c's
552 * device class (which lacks bus_* method passthroughs) blackholes
553 * the alloc and we silently fall back to polling.
554 */
555 rid = 0;
556 sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
557 RF_ACTIVE);
558 if (sc->sc_irq_res != NULL) {
559 if (sc->sc_int_pin != NULL)
560 gpio_pin_setflags(sc->sc_int_pin, GPIO_PIN_INPUT);
561 error = bus_setup_intr(dev, sc->sc_irq_res,
562 INTR_TYPE_MISC | INTR_MPSAFE,
563 NULL, goodix_intr, sc, &sc->sc_irq_hdl);
564 if (error) {
565 device_printf(dev,
566 "bus_setup_intr failed: %d\n", error);
567 bus_release_resource(dev, SYS_RES_IRQ, rid,
568 sc->sc_irq_res);
569 sc->sc_irq_res = NULL;
570 } else {
571 device_printf(dev,
572 "IRQ mode enabled (irq %ju)\n",
573 (uintmax_t)rman_get_start(sc->sc_irq_res));
574 }
575 } else {
576 device_printf(dev,
577 "bus_alloc_resource_any(SYS_RES_IRQ) returned NULL "
578 "- check rk_i2c.c.patch is applied\n");
579 }
580
581 if (sc->sc_irq_res == NULL) {
582 /*
583 * No IRQ available, fall back to polling mode.
584 * Poll every 10ms (100 Hz) for responsive touch.
585 */
586 device_printf(dev, "Using polling mode (no IRQ)\n");
587 callout_init(&sc->sc_poll_callout, 1);
588 TASK_INIT(&sc->sc_poll_task, 0, goodix_poll_task, sc);
589 sc->sc_polling = 1;
590 callout_reset(&sc->sc_poll_callout, hz / 100,
591 goodix_poll, sc);
592 }
593
594 ctx = device_get_sysctl_ctx(dev);
595 tree = SYSCTL_CHILDREN(device_get_sysctl_tree(dev));
596 SYSCTL_ADD_STRING(ctx, tree, OID_AUTO, "chip_id",
597 CTLFLAG_RD | CTLFLAG_MPSAFE, sc->sc_chip_id, 0,
598 "Goodix chip ID string");
599 SYSCTL_ADD_U16(ctx, tree, OID_AUTO, "version",
600 CTLFLAG_RD | CTLFLAG_MPSAFE, &sc->sc_version, 0,
601 "Goodix firmware version");
602 SYSCTL_ADD_U16(ctx, tree, OID_AUTO, "i2c_addr_7bit",
603 CTLFLAG_RD | CTLFLAG_MPSAFE, &sc->sc_addr7, 0,
604 "7-bit I2C address selected by reset sequence");
605 SYSCTL_ADD_U16(ctx, tree, OID_AUTO, "config_addr",
606 CTLFLAG_RD | CTLFLAG_MPSAFE, &sc->sc_config_addr, 0,
607 "Goodix config register address");
608 SYSCTL_ADD_U16(ctx, tree, OID_AUTO, "config_len",
609 CTLFLAG_RD | CTLFLAG_MPSAFE, &sc->sc_config_len, 0,
610 "Goodix config register length");
611 SYSCTL_ADD_U16(ctx, tree, OID_AUTO, "max_x",
612 CTLFLAG_RD | CTLFLAG_MPSAFE, &sc->sc_max_x, 0,
613 "Touchscreen X coordinate maximum");
614 SYSCTL_ADD_U16(ctx, tree, OID_AUTO, "max_y",
615 CTLFLAG_RD | CTLFLAG_MPSAFE, &sc->sc_max_y, 0,
616 "Touchscreen Y coordinate maximum");
617 SYSCTL_ADD_U8(ctx, tree, OID_AUTO, "max_touch",
618 CTLFLAG_RD | CTLFLAG_MPSAFE, &sc->sc_max_touch, 0,
619 "Maximum touch contacts");
620 SYSCTL_ADD_U8(ctx, tree, OID_AUTO, "polling",
621 CTLFLAG_RD | CTLFLAG_MPSAFE, &sc->sc_polling, 0,
622 "Polling fallback active");
623
624 device_printf(dev, "Goodix touchscreen attached\n");
625 return (0);
626 }
627
628 static int
629 goodix_detach(device_t dev)
630 {
631 struct goodix_softc *sc = device_get_softc(dev);
632
633 if (sc->sc_irq_hdl != NULL)
634 bus_teardown_intr(dev, sc->sc_irq_res, sc->sc_irq_hdl);
635 if (sc->sc_irq_res != NULL)
636 bus_release_resource(dev, SYS_RES_IRQ, 0, sc->sc_irq_res);
637 if (sc->sc_polling) {
638 callout_drain(&sc->sc_poll_callout);
639 taskqueue_drain(taskqueue_thread, &sc->sc_poll_task);
640 }
641 if (sc->sc_evdev != NULL)
642 evdev_free(sc->sc_evdev);
643 return (0);
644 }
645
646 static device_method_t goodix_methods[] = {
647 DEVMETHOD(device_probe, goodix_probe),
648 DEVMETHOD(device_attach, goodix_attach),
649 DEVMETHOD(device_detach, goodix_detach),
650 DEVMETHOD_END
651 };
652
653 static driver_t goodix_driver = {
654 "goodix",
655 goodix_methods,
656 sizeof(struct goodix_softc),
657 };
658
659 DRIVER_MODULE(goodix, iicbus, goodix_driver, NULL, NULL);
660 MODULE_DEPEND(goodix, iicbus, IICBUS_MINVER, IICBUS_PREFVER, IICBUS_MAXVER);
661 MODULE_DEPEND(goodix, evdev, 1, 1, 1);
662 MODULE_VERSION(goodix, 1);
663 IICBUS_FDT_PNP_INFO(goodix_compat);
664

The address-select behavior matters for PineTab2. The Goodix reset sequence samples INT while reset is deasserted: INT high selects the 0x14 address used by the PinePhone Pro, while INT low selects the 0x5d address used by PineTab2.

The driver now exposes first-boot receipt sysctls:

Bring-Up Predicate

After booting the PineTab2 kernel:

dmesg | grep -i goodix
sysctl dev.goodix.0
libinput list-devices

Expected first-pass evidence:

  1. goodix0 attaches as a Goodix GT911 Touchscreen.
  2. chip_id is 911 or another GT9xx-compatible ID from the same controller family.
  3. i2c_addr_7bit is 93 (0x5d).
  4. config_addr is 32839 (0x8047) and config_len is 186.
  5. polling is 0 if the GPIO IRQ path works; 1 is acceptable for first I2C proof but should be fixed before touch becomes user-facing.

Open Work