Hi,
I’ve been aware that the touchscreen was not working on Linux OS for some time.
PeterCxy has announced a fix to this and it is available here: GitHub - PeterCxy/gpd_p2_max_acpi: Deprecated, use https://github.com/PeterCxy/goodix-p2max-dkms instead
For ease and convenience I’m going to embed the post he has created on reddit below as it is very technical descriptive and helpful and provide a link to the source reddit post.
On the issues of the touch screen of GPD P2 Max under Linux
EDIT : I’ve managed to fix the issue. Here is the fix: GitHub - PeterCxy/gpd_p2_max_acpi: Deprecated, use https://github.com/PeterCxy/goodix-p2max-dkms instead. It’s an issue of the ACPI implementation of the BIOS, not Linux. The fix is in the form of an ACPI override that must be applied through the Linux kernel because we cannot mess with the BIOS itself.
The link contains a brief instruction on how to use the DSDT fix. I have uploaded a prebuilt CPIO image containing the fixed DSDT here in GitHub Releases page Releases · PeterCxy/gpd_p2_max_acpi · GitHub, which you can simply append to your bootloader’s initrd
option to load into your kernel. Something like initrd /acpi_override
(with acpi_override
located in your boot partition)
For those who want a more detailed explanation, I basically changed three things:
- The GPIO interrupt pin should be ActiveHigh instead of ActiveLow
- Added
_DSD
definition for the Linux kernel to handle resets via GPIO instead of using ACPI to handle it (Linux needs _DSD to correctly recognize the GPIO pins) - Removed the original ACPI code that seemed to handle touchscreen resets
To folks at GPD : These fixes are NOT specific to Linux though. The stock DSDT table is just wrong , not “incompatible” with Linux. It’s “incompatible” with everything. Windows works fine only because the Goodix driver in Windows doesn’t care so much about the DSDT device definition. That’s it.
I hope maybe GPD can apply these fixes via a BIOS update so that we won’t need to ask everybody to apply the acpi overrides themselves.
---- Original Post ----
So I’ve received my pre-ordered GPD P2 Max recently. Before this, I have already seen reviews on running Linux on this device, and I knew that the touch screen was not working under Linux distros. I confirmed this when I finished installing Arch Linux on my unit, so I began to try to fix the issue.
At first I thought it’s just not recognized due to a different device identifier or something, just like on GPD Win 2. However it turned out to be not this case. In fact, the kernel module goodix
was able to load successfully by default
[ 10.559385] Goodix-TS i2c-GDIX1002:00: i2c-GDIX1002:00 supply AVDD28 not found, using dummy regulator
[ 10.559404] Goodix-TS i2c-GDIX1002:00: i2c-GDIX1002:00 supply VDDIO not found, using dummy regulator
[ 10.559862] Goodix-TS i2c-GDIX1002:00: ID 928, version: 1060
[ 10.578109] Goodix-TS i2c-GDIX1002:00: Invalid config (0, 0, 0), using defaults
[ 10.578238] input: Goodix Capacitive TouchScreen as /devices/pci0000:00/0000:00:15.2/i2c_designware.2/i2c-8/i2c-GDIX1002:00/input/input13
The same message exists in the dmesg
output of GPD Pocket 1, so there should not be a problem here.
The driver was loaded, and everything shows up in xinput
as Goodix Capacitive TouchScreen, normally it should work just fine. However, when touched, the screen does not generate any interrupt. When looking at /proc/interrupts
, the line corresponding to the goodix touchscreen stayed at 0 no matter how hard I tried to touch it.
At this point I felt very confused. But something happened and made me even more confused – after trying to reboot it for several time, the screen suddenly started working just fine. However, it only worked for that trial, and after another reboot it went back to be not working again. I checked the dmesg
output and everything and it looked literally the same when it started to work, except for the fact that the interrupt numbers are no longer 0.
I was able to get it to work randomly for like 1 out of 50 reboot attempts. After digging into the source code of the driver ( drivers/input/touchscreen/goodix.c
), I realized that the touch panel has a reset sequence that must be done on boot to ensure it is working properly. So I began to think that the problem might be an incorrect reset sequence. And for some other unknown reason, I decided to dump the DSDT table (ACPI) to compare with other GPD products that have a working touchscreen. The section for the touchscreen always contains the identifier GDIX1001
or GDIX1002
so it is easy to locate.
I found that the GPD P2 Max has some additional code in the power state methods
Method (_PS0, 0, Serialized) // _PS0: Power State 0
{
SGOV (0x02050009, Zero)
Sleep (0x23)
SGOV (0x02050009, One)
Sleep (0x78)
}
Method (_PS3, 0, Serialized) // _PS3: Power State 3
{
SGOV (0x02050009, Zero)
}
Guess what, this seems a lot like a reset sequence to me. The 0x02050009
refers to GPIO pin 129 on the south bridge (confirmed through the coreboot source code and the methods named SGOV and GNUM in the same DSDT file). It seems that the ACPI handles the reset sequence on this device, while on the previous devices it did not. I checked the GPIO definitions in the DSDT and they all looked fine to me.
I then started poking around in the DSDT by using the ACPI override feature of the Linux kernel. I mainly tried a few things:
- Messing with the reset sequence in the power state methods. I found a data sheet for the GT928 touchscreen used on GPD P2 Max http://dl.linux-sunxi.org/touchscreen/GT928%20Datashet%20English.pdf and tried to adjust the reset sequence accordingly.
- Removing the GPIO pin number placeholder and directly write the pin number. In the original DSDT, the GPIO pin numbers were placeholders (
0x0000
), and the actual pin number was written later in the init method (GNUM (0x02050008)
andGNUM (0x02050009)
, which are0x80
and0x81
when calculated, respectively). I wrote0x80
and0x81
to replace the placeholders. - Removing the separate
ResourceTemplate
's and merged them together in_CRS
instead of usingConcatenateResTemplate
. (Of course I adjusted other code depending on these accordingly)
And none of these worked. Or maybe some actually could work, but all I have got was those random cases where it worked miraculously and stopped working once again after rebooting. Of course I confirmed my custom DSDT tables were actually taken by the kernel by checking dmesg
output. And I am a noob when it comes to ACPI and DSDT stuff, so maybe it was really a DSDT problem but I was just doing it the wrong way.
I still suspect it can be fixed by a custom DSDT, but I am sort of out of ideas now. Posting here for anyone interested for possibly more ideas. I still could not understand how those random cases worked, though. Maybe it’s also a firmware thing? I hope I could talk to GPD’s tech people directly, because I don’t expect normal customer service to know anything about these – that’s not their job. I just told them Linux is not working and they said they’d be working with Ubuntu or something. Except for that, I have got no valuable information.
The DSDT I dumped from my unit is pasted here: https://fars.ee/CMBu.dsl
Source:
On the issues of the touch screen of GPD P2 Max under Linux from r/GPDPocket