TouchDisplay2でタッチが効かなくなる件

 TouchDisplay2でタッチが効かなくなる問題は、どうも、起動後にrebootした後はダメになる感じ。

 ドライバのロードメッセージを見てみる。

 正常なときはこう。

fd@pi3b:~ $ dmesg | grep Goodix
[   10.358666] Goodix-TS 10-005d: supply VDDIO not found, using dummy regulator
[   10.447665] Goodix-TS 10-005d: ID 911, version: 1060
[   10.465138] input: 10-005d Goodix Capacitive TouchScreen as /devices/platform/soc/3f205000.i2c/i2c-11/i2c-10/10-005d/input/input0

 rebootしたときはこれ。

fd@pi3b:~ $ dmesg | grep Goodix
[    7.563941] Goodix-TS 10-005d: supply VDDIO not found, using dummy regulator
[    7.627625] Goodix-TS 10-005d: Error reading 1 bytes from 0x8140: -5
[    7.651622] Goodix-TS 10-005d: Error reading 1 bytes from 0x8140: -5
[    7.675364] Goodix-TS 10-005d: I2C communication failure: -5
[    7.676273] Goodix-TS 10-005d: probe with driver Goodix-TS failed with error -5

 ドライバが、I2Cの先にあるタッチデバイスを探したのだけど、失敗してエラーを出している。

 これは、毎回完全に電源抜いて入れ直す(コールドブートする)必要があるようだ。

 この動きの違いはこれだろうな...

Touch Display 2買ってみた -1-|kinneko|pixivFANBOX
https://kinneko.fanbox.cc/posts/10708996

 ウォームブートのときには、この電源が通電しっぱなしなので、DSIのマイコンがリセットされない。Goodix-TSはDSIコントローラー配下にあるので、こちらも当然リセットされない。

 つまり、再起動前のI2Cの設定が残ってしまっていて、マイコン側は新規の接続を受け付けなくなっている。

 Touch Display 2のタッチ部はGoodix GT911互換コントローラ(I2C接続、通常 bus 10 / address 0x5d)を使っていて、このチップは電源投入直後のリセットシーケンス(RST + INT ピン制御)を要求するそうだ。再起動時はRaspi側のGPIO/I2Cがリセットされず、Goodix側が古い状態のまま応答しなくなる。goodix_tsドライバは起動時にI2Cに応答がないと「probe failed -5」で諦めるので、その後ロードされても復帰できない。

 本来は、ハード的にはDSIマイコンのコントローラーのファームでデバイスが接続したときにはリセットすべき感じかな。もしくは、dtbでリセットするか。それとも、デバイスドライバ側でリセット処理を入れるか。

 もっとも、GoodixのリセットピンがRaspi側から見えるように外に出ているわけではないので、Raspi側からの制御は難しいかも。少なくともdtsを書き換えたくらいだと無理そう。

 純正プロダクトなのに、なんてお粗末な設計なんだろうなぁ... しかも、採用されているGoodixはAPI互換のクローン品らしい。

 調べてみると、タッチが効かなくなるという事例は純正7インチTouch Display 2の時からたくさんある感じ。対処したというメッセージもあるけど、その後もあいかわらずダメという反応も多い。

Touch-functionality of Touch Display 2 stops working after reboot - Raspberry Pi Forums
https://forums.raspberrypi.com/viewtopic.php?t=389937

 waveshare品でも同じ問題がある感じ。こちらはなんでかわからないけど、解決されないままCloseしている。

RPI 5 - Goodix capacitive touchscreen not working on latest Kernel · Issue #6456 · raspberrypi/linux
https://github.com/raspberrypi/linux/issues/6456

 最近改良がされているdtbの設定でも、リセットパラメータはない。

linux/arch/arm/boot/dts/overlays/README at 4421ed134f9f03351a4a26293a29f009b8fff725 · raspberrypi/linux
https://github.com/raspberrypi/linux/blob/4421ed134f9f03351a4a26293a29f009b8fff725/arch/arm/boot/dts/overlays/README#L5600-L5612

 正常時はinputデバイスが見えている。

fd@pi3b:~ $ cat /proc/bus/input/devices | grep -A5 "oodix"
N: Name="10-005d Goodix Capacitive TouchScreen"
P: Phys=input/ts
S: Sysfs=/devices/platform/soc/3f205000.i2c/i2c-11/i2c-10/10-005d/input/input0
U: Uniq=
H: Handlers=kbd mouse0 event0
B: PROP=2

 とりあえず、ワークアラウンドで対応してみる。

fd@pi3b:~ $ vi goodix_recover.sh
#!/usr/bin/env bash
# /usr/local/bin/goodix_recover.sh (rev2)

 set -u

BUS="${BUS:-10}"
ADDR_HEX="${ADDR_HEX:-0x5d}"     # 0x5d
DEV_NAME="${BUS}-005d"           # 10-005d
I2C_DEV_DIR="/sys/bus/i2c/devices"
I2C_BUS_DIR="${I2C_DEV_DIR}/i2c-${BUS}"
I2C_NEW="${I2C_BUS_DIR}/new_device"
I2C_DEL="${I2C_DEV_DIR}/delete_device"
DRV_DIR="/sys/bus/i2c/drivers/goodix"
PLAT_DRV="/sys/bus/platform/drivers/i2c-bcm2835"
PLAT_DEV="$(ls -d /sys/bus/platform/devices/*i2c* 2>/dev/null | head -n1)"
log(){ echo "[goodix_recover] $*"; }
has_input(){ grep -A5 -i "Goodix Capacitive TouchScreen" /proc/bus/input/devices 2>/dev/null | grep -q "Handlers="; }
has_node(){ [[ -e "${I2C_DEV_DIR}/${DEV_NAME}" ]]; }
unbind_goodix(){
[[ -e "${DRV_DIR}/unbind" ]] || return 0
echo "${DEV_NAME}" > "${DRV_DIR}/unbind" 2>/dev/null || true
}
bind_goodix(){
[[ -e "${DRV_DIR}/bind"   ]] || return 0
echo "${DEV_NAME}" > "${DRV_DIR}/bind"   2>/dev/null || true
}
delete_node(){
[[ -w "${I2C_DEL}" ]] || return 0
echo "${DEV_NAME}" > "${I2C_DEL}" 2>/dev/null || true
}
create_node(){
[[ -w "${I2C_NEW}" ]] || return 0
echo "goodix ${ADDR_HEX}" > "${I2C_NEW}" 2>/dev/null || true
}
rebind_i2c_controller(){
[[ -n "${PLAT_DEV}" && -e "${PLAT_DRV}/unbind" && -e "${PLAT_DRV}/bind" ]] || return 0
echo "$(basename "${PLAT_DEV}")" > "${PLAT_DRV}/unbind" 2>/dev/null || true

 sleep 0.2

echo "$(basename "${PLAT_DEV}")" > "${PLAT_DRV}/bind"  2>/dev/null || true

 sleep 0.3

}
reload_mod(){
modprobe -r goodix_ts 2>/dev/null || true

 sleep 0.2

modprobe goodix_ts 2>/dev/null || true
}
main(){
if has_input; then
log "already present (input). nothing to do."

 exit 0

 fi

log "step1: reload mod + unbind/bind client"

 reload_mod

 unbind_goodix

if has_node; then delete_node; fi

 create_node

 bind_goodix

 sleep 0.5

if has_input; then log "recovered (step1)"; exit 0; fi

 log "step2: rebind I2C controller, then recreate"

 rebind_i2c_controller

 reload_mod

 unbind_goodix

if has_node; then delete_node; fi

 create_node

 bind_goodix

 sleep 0.8

if has_input; then log "recovered (step2)"; exit 0; fi
if command -v vcgencmd >/dev/null 2>&1; then

 log "step3: display power cycle"

vcgencmd display_power 0 >/dev/null 2>&1 || true

 sleep 0.3

vcgencmd display_power 1 >/dev/null 2>&1 || true

 sleep 0.5

 reload_mod

 unbind_goodix; if has_node; then delete_node; fi

 create_node; bind_goodix

 sleep 0.5

if has_input; then log "recovered (step3)"; exit 0; fi

 fi

 log "recovery failed. cold boot may be required."

 exit 1

}

 main "$@"

fd@pi3b:~ $ chmod +x goodix_recover.sh

 再起動して効果を確認。

fd@pi3b:~ $ sudo reboot
fd@pi3b:~ $ cat /proc/bus/input/devices | grep -A5 "oodix"
fd@pi3b:~ $ sudo ./goodix_recover.sh
[goodix_recover] step1: reload mod + unbind/bind client
[goodix_recover] recovered (step1)

 実行後は、一応見えるようになっている。

fd@pi3b:~ $ cat /proc/bus/input/devices | grep -A5 "oodix"
N: Name="10-005d Goodix Capacitive TouchScreen"
P: Phys=input/ts
S: Sysfs=/devices/platform/soc/3f205000.i2c/i2c-11/i2c-10/10-005d/input/input2
U: Uniq=
H: Handlers=kbd mouse0 event2
B: PROP=2

 正常時は何もしない。

fd@pi3b:~ $ sudo ./goodix_recover.sh
[goodix_recover] already present (input). nothing to do.

 systemdで起動するように設定すると、起動順序のバランスが悪いので、起動中にロックしてしまう。面倒なので、rc.localで起動することにする。

fd@pi3b:~ $ vi /etc/rc.local
#!/bin/sh -e

起動をブロックしないよう遅延してバックグラウンド実行

( sleep 5; /home/fd/goodix_recover.sh >> /var/log/goodix_recover.log 2>&1 ) &

 exit 0

 rebootのとき。

fd@pi3b:~ $ cat /var/log/goodix_recover.log
[goodix_recover] step1: reload mod + unbind/bind client
[goodix_recover] recovered (step1)

 コールドブートのとき。

fd@pi3b:~ $ cat /var/log/goodix_recover.log
[goodix_recover] already present (input). nothing to do.

 ログがたまると面倒なので、あとでログはloggerに渡すように変更しておく。

fd@pi3b:~ $ sudo rm /var/log/goodix_recover.log
fd@pi3b:~ $ sudo vi /etc/rc.local
#!/bin/sh -e

起動をブロックしないよう遅延してバックグラウンド実行

(

 sleep 5

/home/fd/goodix_recover.sh 2>&1 | /usr/bin/logger -t goodix_recover
) &

 exit 0

 再起動してみる。

fd@pi3b:~ $ sudo reboot

 動作はしている。

fd@pi3b:~ $ sudo journalctl -t goodix_recover -b | cat
Oct 30 16:58:30 pi3b goodix_recover[629]: [goodix_recover] step1: reload mod + unbind/bind client
Oct 30 16:58:31 pi3b goodix_recover[629]: [goodix_recover] recovered (step1)

 デバイスは見えている。

fd@pi3b:~ $ grep -A5 -i "Goodix Capacitive TouchScreen" /proc/bus/input/devices
N: Name="10-005d Goodix Capacitive TouchScreen"
P: Phys=input/ts
S: Sysfs=/devices/platform/soc/3f205000.i2c/i2c-11/i2c-10/10-005d/input/input2
U: Uniq=
H: Handlers=kbd mouse0 event2
B: PROP=2

 これで解決という感じか。

 100円投げ銭  https://kinneko.booth.pm/items/1963720


オリジナル投稿:
TouchDisplay2でタッチが効かなくなる件|kinneko|pixivFANBOX
https://kinneko.fanbox.cc/posts/10816996