Touchscreen Issue Resolved

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:

  1. The GPIO interrupt pin should be ActiveHigh instead of ActiveLow
  2. 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)
  3. 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:

  1. 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.
  2. 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) and GNUM (0x02050009) , which are 0x80 and 0x81 when calculated, respectively). I wrote 0x80 and 0x81 to replace the placeholders.
  3. Removing the separate ResourceTemplate 's and merged them together in _CRS instead of using ConcatenateResTemplate . (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
2 Likes

Hello,
I just installed Linux Mint 19.2. Bios 0.23 is also installed. How do I proceed to make the touchscreen to work? I copied the acpi_override file in the /boot directory. In what file do I add the “initrd /acpi_override” line? Is it in the /etc/default/grub
file? If so, where in that file? Thank you for your help, it is much appreciated!

1 Like

@joshwiththegoodhair - by any chance are you able to assist @Wondow here please?

Unfortunately, with 0.23, it’s impossible to get the touch screen to work - even with the /acpi_override cpio image. That cpio override only works for < 0.23.

2 Likes

Thought so, but wanted someone who knows to say it not me. Do you know if there is or will be any solution yet to downgrading bios to 0.22? Thanks

@PeterCxy - Based on the past, GPD typically only releases only a few BIOS updates for a product. How much effort is it to rebuild the CPIO image? Is it something you could help me understand so that I could build it?

2 Likes

That is very sad. I bought this device to run it with Linux, and with touch screen. I should have waited before upgrading to 0.23… But given the number of bugs reported by other users on previous versions, I installed it. I usually never update bios… It is impossible, or it is impossible yet to make the touch screen to work with Linux?

Not much, you can do it totally yourself by following the very helpful ArchWiki article on DSDT and my Reddit post / git log on GitHub to modify the new DSDT. I just haven’t had time to do it yet due to a bunch of University stuff. I haven’t even upgraded to 0.23 myself.

However I’d probably just go with patching the kernel instead when I have time to build the package. I don’t really want to bother with keeping things up to date with whatever GPD decides to screw up in their buggy ACPI.

1 Like

It is possible. It’s just that I haven’t had time to update the ACPI override or package my patched kernel yet. I’m just a random final year university student that has to be able to graduate before doing any side project. If you know how to apply kernel patches OR how to modify ACPI table according to my GitHub logs, you can totally do it yourself.

This is exactly why I wrote up the kernel patch and submitted to LKML – so that nobody need to care about what BIOS version they are on and apply the “corresponding” fix, and so that I would not have to bother with keeping things up-to-date with every single BIOS update and write warnings about what BIOS version the fix is compatible with.

2 Likes

Thanks for the info. I will try to rebuild!

@PeterCxy - I’ve filled the Arch guide alongside a diff of 0.23’s dsl and the dsdt.dsl in your repo. I’m pretty confident I’ve made the three changes suggested in your Reddit post (add _DSD function, ActiveLow to ActiveHigh, remove two function bodies for touchscreen ACPI power reset). On a visual diff, they’re identical outside some minor hex differences (which I think are related to BIOS version change).

I’m able to compile the amr file and build the cpio image successfully. But - as soon as I try to bump the OEM revision (as suggested by the Arch guide and confirmed by your dsl’s revision number), I receive 200+ errors from the compiler. The revision provided by the decompile is identical to the one in your dsl and if I attempt to use your override, it also fails.

Any suggestions?

Diff between your repo’s dsdt.dsl and UNPATCHED 0.23 dump:

3c3
<  * AML/ASL+ Disassembler version 20190703 (64-bit version)
---
>  * AML/ASL+ Disassembler version 20190816 (64-bit version)
8c8
<  * Disassembly of dsdt2.dat, Fri Aug 23 10:04:39 2019
---
>  * Disassembly of ./dsdt-23-orig.dat, Tue Sep 10 22:59:48 2019
14c14
<  *     Checksum         0xAC
---
>  *     Checksum         0xA1
21c21
< DefinitionBlock ("", "DSDT", 2, "ALASKA", "A M I ", 0x01072020)
---
> DefinitionBlock ("", "DSDT", 2, "ALASKA", "A M I ", 0x01072009)
260c260
<     Name (PPIM, 0x8CA71F98)
---
>     Name (PPIM, 0x8CA5CF98)
273c273
<     OperationRegion (GNVS, SystemMemory, 0x8CA6C000, 0x0793)
---
>     OperationRegion (GNVS, SystemMemory, 0x8CA57000, 0x0793)
11137c11137
<     Name (PNVB, 0x8CA71018)
---
>     Name (PNVB, 0x8CA5C018)
17194c17194
<                 GpioInt (Edge, ActiveHigh, Exclusive, PullDefault, 0x0000,
---
>                 GpioInt (Edge, ActiveLow, Exclusive, PullDefault, 0x0000,
17227,17236d17226
<             Name (_DSD,  Package ()
<             {
<                 ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
<                 Package ()
<                 {
<                     Package (2) {"irq-gpios", Package() {^TCSE, 0, 0, 0 }},
<                     Package (2) {"reset-gpios", Package() {^TCSE, 1, 0, 0 }},
<                 }
<             })
< 
17243a17234,17237
>                 SGOV (0x02050009, Zero)
>                 Sleep (0x23)
>                 SGOV (0x02050009, One)
>                 Sleep (0x78)
17247a17242
>                 SGOV (0x02050009, Zero)

Diff between your repo’s dsdt.dsl and the 0.23’s PATCHED dsl (with your touchscreen changes):

3c3
<  * AML/ASL+ Disassembler version 20190703 (64-bit version)
---
>  * AML/ASL+ Disassembler version 20190816 (64-bit version)
8c8
<  * Disassembly of dsdt2.dat, Fri Aug 23 10:04:39 2019
---
>  * Disassembly of ./dsdt-23.dat, Tue Sep 10 21:56:36 2019
14c14
<  *     Checksum         0xAC
---
>  *     Checksum         0xA1
21c21
< DefinitionBlock ("", "DSDT", 2, "ALASKA", "A M I ", 0x01072020)
---
> DefinitionBlock ("", "DSDT", 2, "ALASKA", "A M I ", 0x01072009)
260c260
<     Name (PPIM, 0x8CA71F98)
---
>     Name (PPIM, 0x8CA5CF98)
273c273
<     OperationRegion (GNVS, SystemMemory, 0x8CA6C000, 0x0793)
---
>     OperationRegion (GNVS, SystemMemory, 0x8CA57000, 0x0793)
11137c11137
<     Name (PNVB, 0x8CA71018)
---
>     Name (PNVB, 0x8CA5C018)

Are you sure those are errors not warnings? Because I know there are a huge bunch of warnings but no fatal error. Just ignore those warnings. GPD didn’t care and you don’t need to either.

and you have to keep the last value in DefinitionBlock unchanged because otherwise it won’t override.

Ah, so I don’t need to do this OEM version increase?

If I don’t do that increase, it does compile and the updated CPIO image seems to load, but no touchscreen. I was assuming the OEM version increase was needed to “override” the BIOS DSDT.

You need to, what I was saying is that you can just keep using MY value (not the stock one), which is already incremented to like 10 beyond the official version. But I don’t think changing that number would cause any failure in compilation though. Can you try with my version value?

This is the compiler error after just changing the revision from 0x01072009 to your dsl’s increment value of 0x01072020. Nothing else was changed and it compiled (with warnings) when the revision was 0x01072009. It’s just very strange.

This tarball has the unaltered 0.23 .dat dump, the unaltered decompiled dsl as well as the “patched” dsl (with default/decompiled 0x01072009 revision) if you want to take a look.

you need to look at the very first error. Looking at the end shows nothing because everything valuable has been pushed up.

1 Like

I’m an idiot. I think it was some sort of weird encoding issue. I was using vim to edit that revision value, but decided to just give emacs a try and sure enough, it compiled. And touchscreen is working in 0.23.

Sorry for roping you in! I now know how to recompile this for future versions so that you won’t have to spend any time on it. Since the end result of this exercise is a release binary (not code), I’m not quite sure how (or if) I can PR you this binary for your Github repo, but I think it might be helpful to future linux users to include it :slight_smile:

For now, this is the working override cpio for the 0.23 BIOS if anyone needs it. (@wondow)

1 Like

I’m not sure if I’ll be even maintaining the repo anymore. I might just point them here. I think I’ll be mainly releasing prebuilt kernel binary and trying to get that patch mainlined.

2 Likes

Thank you very much! Well, It is almost sure that there will be a 0.24, since 0.23 has battery and performance problems. Anyways, I will gladly install this override. So if I come back to my original question, I understand that I have to copy acpi_override file in the /boot directory. In what file do I add the “initrd /acpi_override” line? Is it in the /etc/default/grub
file? If so, where in that file? Thank you for your help, it is much appreciated!

1 Like