Contribute
Register

[Guide] ASUS ZenBook Pro Duo 15 OLED UX582 OpenCore

@gvkt For the Luna brightness problem, make sure you have the same setting here:
Screen Shot 2021-12-12 at 4.53.31 AM.png
 
@shiecldk
Now that I have fixed the multi-touch for our laptops, I am struggling with converting the trackpad from polling to GPIO interrupt as its APIC interrupt number (5F) is higher than what MacOS can handle. But none of the GPIO pinning numbers work following the guide in

Can you tell me the first number of the InterruptSpecifiers for each of the three touch devices on your laptop (which will show if they are low enough to be in APIC mode or are polling instead of interrupt mode) or gpioPin number which will show instead if they are GPIO pinned. IORegistryExplorer will show this for the ETPD, TPL0, etc.

There seems to be quite a battery hit from leaving it in polling mode vs disabling it so need to get into interrupt mode.
 
@gkvt Is this the information you need? Let me know. Maybe @atrslb knows better than me on this part since he got the SSDT for ELAN trackpad? And @gkvt, do you find the touch device sometime stop responding? This seems to be happening quite often with our trackpad due to some VoodooI2C bug.
Screen Shot 2021-12-20 at 7.27.07 AM.png
Screen Shot 2021-12-20 at 7.27.15 AM.png
Screen Shot 2021-12-20 at 7.28.13 AM.png
Screen Shot 2021-12-20 at 7.28.23 AM.png


Also, I found the recent Luna.app breaks the brightness FN keys although brightness adjustment works on the menu UI.
Screen Shot 2021-12-20 at 7.34.34 AM.png
 
Last edited:
@shiecldk Thanks. Basically, the Zenbook Pro I have uses ETPD and TPL0 with same interrupts. The ETPD make is different but they are wired the same. The TPLx are within MacOS APIC range so they work without polling OOB.

The ETPD with interrupt 5F is out of range for MacOS APIC so, it is working in polling mode (like yours as shown by IORegistry) and this reduces battery time 10-20%. I have not had any issues with the ETPD in polling mode other than battery life. My touchpad is by Goodix not Elan.

So, I have been trying to get it to work via GPIO interrupts as recommended by VoodooI2C. But unsuccessful. It should be one of the following:

1. A problem specific to Goodix in sending interrupts. This is unlikely. As it works in Windows with that interrupt. If it is this problem, then your Elan should be able to work in GPIO interrupt mode.
2. A problem in the VoodooI2CCannonLakeH GPIO controller for the 10th generation CPUs. There are translation tables to convert from APIC interrupt numbers to GPIO. Both of our laptops will have problems with GPIO interrupts if this is the case. I am trying to find if anybody with the 10th generation H CPUs have been able to get GPIO interrupts working.
3. A BIOS problem that locks the corresponding GPIO interrupt for APIC and so unavailable for GPIO. I am going to try a Linux distro to see if this is the problem.

If you have some time, try using the GPIO pinning guide I linked above for your laptop. I can help you with what needs to be done if you have problems following that since we likely have similar DSDT for ETPD. The GPIO interrupts to try will be the same for both of our laptops translating 5F to 0x57, 0xD7 or 0xF7 so you don’t need to do that calculation. If you post the DSDT section for ETPD, I can tell you what SSDT patch and possible rewrite string you need to try a GPIO interrupt. This part works for me fine, just that it doesn’t get any interrupts. Also have instrumented debug kexts to output what is happening.

If it works for you then it is a Goodix problem and I may be out of luck. If it doesn’t, then it is a VoodooGPIO or BIOS problem. Would be useful to know to explore further.
 
@gvkt This is the related DSDT code of my UX582. Let me know if it helps. I will try the GPIO interrupt this weekend. I do find the battery life is relatively short comparing to other hackintosh laptops I built. It would be great to solve this. If you know what SSDT I could apply, I can try it today or tomorrow. Thanks again.


Code:
Scope (_SB.PCI0.LPCB)
    {
        Device (PS2K)
        {
            Name (_HID, EisaId ("ATK3001"))  // _HID: Hardware ID
            Name (_CID, EisaId ("PNP030B"))  // _CID: Compatible ID
            Method (_STA, 0, NotSerialized)  // _STA: Status
            {
                If ((IOST & 0x0400))
                {
                    Return (0x0F)
                }
                Else
                {
                    Return (Zero)
                }
            }

            Name (_CRS, ResourceTemplate ()  // _CRS: Current Resource Settings
            {
                IO (Decode16,
                    0x0060,             // Range Minimum
                    0x0060,             // Range Maximum
                    0x00,               // Alignment
                    0x01,               // Length
                    )
                IO (Decode16,
                    0x0064,             // Range Minimum
                    0x0064,             // Range Maximum
                    0x00,               // Alignment
                    0x01,               // Length
                    )
                IRQNoFlags ()
                    {1}
            })
            Name (_PRS, ResourceTemplate ()  // _PRS: Possible Resource Settings
            {
                StartDependentFn (0x00, 0x00)
                {
                    IO (Decode16,
                        0x0060,             // Range Minimum
                        0x0060,             // Range Maximum
                        0x00,               // Alignment
                        0x01,               // Length
                        )
                    IO (Decode16,
                        0x0064,             // Range Minimum
                        0x0064,             // Range Maximum
                        0x00,               // Alignment
                        0x01,               // Length
                        )
                    IRQNoFlags ()
                        {1}
                }
                EndDependentFn ()
            })
        }
    }

    If (CondRefOf (\_SB.PCI0.CNVW))
    {
        Scope (_SB.PCI0.CNVW)
        {
            Method (_PRW, 0, NotSerialized)  // _PRW: Power Resources for Wake
            {
                Return (GPRW) /* External reference */
                0x6D
                0x04
            }

            Method (_DSW, 3, NotSerialized)  // _DSW: Device Sleep Wake
            {
            }
        }
    }

    Scope (_SB.PCI0.I2C1)
    {
        Device (ETPD)
        {
            Name (SBFB, ResourceTemplate ()
            {
                I2cSerialBusV2 (0x004C, ControllerInitiated, 0x00061A80,
                    AddressingMode7Bit, "\\_SB.PCI0.I2C1",
                    0x00, ResourceConsumer, _Y38, Exclusive,
                    )
            })
            Name (SBFI, ResourceTemplate ()
            {
                Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive, ,, )
                {
                    0x0000005F,
                }
            })
            CreateWordField (SBFB, \_SB.PCI0.I2C1.ETPD._Y38._ADR, BADR)  // _ADR: Address
            Name (_ADR, One)  // _ADR: Address
            Name (ETPH, Package (0x04)
            {
                "ELAN1200",
                "ELAN1300",
                "ELAN1406",
                "ASUE1406"
            })
            Name (FTPH, Package (0x0C)
            {
                "FTE1001",
                "FTE1200",
                "FTE1200",
                "FTE1300",
                "FTE1300",
                "FTE1201",
                "FTE1200",
                "FTE1200",
                "FTE1201",
                "FTE1201",
                "FTE1200",
                "FTE1200"
            })
            Method (_HID, 0, NotSerialized)  // _HID: Hardware ID
            {
                If ((TPDI & 0x04))
                {
                    BADR = 0x15
                    Return (DerefOf (ETPH [TPHI]))
                }

                If ((TPDI & 0x10))
                {
                    BADR = 0x15
                    Return (DerefOf (FTPH [TPHI]))
                }

                Return ("ELAN1000")
            }

            Name (_CID, "PNP0C50" /* HID Protocol Device (I2C bus) */)  // _CID: Compatible ID
            Name (_UID, One)  // _UID: Unique ID
            Name (_S0W, 0x03)  // _S0W: S0 Device Wake State
            Method (_DSM, 4, NotSerialized)  // _DSM: Device-Specific Method
            {
                If ((Arg0 == ToUUID ("3cdff6f7-4267-4555-ad05-b30a3d8938de") /* HID I2C Device */))
                {
                    If ((Arg2 == Zero))
                    {
                        If ((Arg1 == One))
                        {
                            Return (Buffer (One)
                            {
                                 0x03                                             // .
                            })
                        }
                        Else
                        {
                            Return (Buffer (One)
                            {
                                 0x00                                             // .
                            })
                        }
                    }

                    If ((Arg2 == One))
                    {
                        Return (One)
                    }
                }
                Else
                {
                    Return (Buffer (One)
                    {
                         0x00                                             // .
                    })
                }
            }

            Method (_STA, 0, NotSerialized)  // _STA: Status
            {
                If (((TPIF != One) || (DSYN && One)))
                {
                    Return (Zero)
                }

                Return (0x0F)
            }

            Method (_CRS, 0, NotSerialized)  // _CRS: Current Resource Settings
            {
                Return (ConcatenateResTemplate (SBFB, SBFI))
            }
        }
    }

    Scope (_SB.PCI0.I2C1)
    {
        Device (ALED)
        {
            Name (_ADR, One)  // _ADR: Address
            Method (_HID, 0, NotSerialized)  // _HID: Hardware ID
            {
                Return ("ALED0217")
            }

            Name (_CID, "PNP0C50" /* HID Protocol Device (I2C bus) */)  // _CID: Compatible ID
            Name (_UID, One)  // _UID: Unique ID
            Name (_S0W, 0x03)  // _S0W: S0 Device Wake State
            Method (_DSM, 4, NotSerialized)  // _DSM: Device-Specific Method
            {
                If ((Arg0 == ToUUID ("3cdff6f7-4267-4555-ad05-b30a3d8938de") /* HID I2C Device */))
                {
                    If ((Arg2 == Zero))
                    {
                        If ((Arg1 == One))
                        {
                            Return (Buffer (One)
                            {
                                 0x03                                             // .
                            })
                        }
                        Else
                        {
                            Return (Buffer (One)
                            {
                                 0x00                                             // .
                            })
                        }
                    }

                    If ((Arg2 == One))
                    {
                        Return (One)
                    }
                }
                Else
                {
                    Return (Buffer (One)
                    {
                         0x00                                             // .
                    })
                }
            }

            Method (_STA, 0, NotSerialized)  // _STA: Status
            {
                Return (0x0F)
            }

            Method (_CRS, 0, Serialized)  // _CRS: Current Resource Settings
            {
                Name (SBFI, ResourceTemplate ()
                {
                    I2cSerialBusV2 (0x0029, ControllerInitiated, 0x00061A80,
                        AddressingMode7Bit, "\\_SB.PCI0.I2C1",
                        0x00, ResourceConsumer, , Exclusive,
                        )
                    Interrupt (ResourceConsumer, Level, ActiveLow, Exclusive, ,, )
                    {
                        0x0000003F,
                    }
                })
                Return (SBFI) /* \_SB_.PCI0.I2C1.ALED._CRS.SBFI */
            }
        }
    }

    Scope (_SB.PCI0.I2C2)
    {
        Device (TPL0)
        {
            Name (_CID, "PNP0C50" /* HID Protocol Device (I2C bus) */)  // _CID: Compatible ID
            Name (_UID, One)  // _UID: Unique ID
            Name (_S0W, 0x03)  // _S0W: S0 Device Wake State
            Name (SADR, Buffer (One)
            {
                 0x10                                             // .
            })
            Name (HIDS, Package (0x01)
            {
                "ELAN9008"
            })
            Name (HIDA, Buffer (One)
            {
                 0x01                                             // .
            })
            Method (_HID, 0, NotSerialized)  // _HID: Hardware ID
            {
                Return (DerefOf (HIDS [TPLI]))
            }

            Method (_DSM, 4, NotSerialized)  // _DSM: Device-Specific Method
            {
                If ((Arg0 == ToUUID ("3cdff6f7-4267-4555-ad05-b30a3d8938de") /* HID I2C Device */))
                {
                    If ((Arg2 == Zero))
                    {
                        If ((Arg1 == One))
                        {
                            Return (Buffer (One)
                            {
                                 0x03                                             // .
                            })
                        }
                        Else
                        {
                            Return (Buffer (One)
                            {
                                 0x00                                             // .
                            })
                        }
                    }

                    If ((Arg2 == One))
                    {
                        Return (DerefOf (HIDA [TPLI]))
                    }
                }
                Else
                {
                    Return (Buffer (One)
                    {
                         0x00                                             // .
                    })
                }
            }

            Method (_STA, 0, NotSerialized)  // _STA: Status
            {
                If ((TPLP == Zero))
                {
                    Return (Zero)
                }

                Return (0x0F)
            }

            Method (_CRS, 0, NotSerialized)  // _CRS: Current Resource Settings
            {
                Name (SBFI, ResourceTemplate ()
                {
                    I2cSerialBusV2 (0x0010, ControllerInitiated, 0x00061A80,
                        AddressingMode7Bit, "\\_SB.PCI0.I2C2",
                        0x00, ResourceConsumer, _Y39, Exclusive,
                        )
                    Interrupt (ResourceConsumer, Level, ActiveLow, Exclusive, ,, )
                    {
                        0x0000001B,
                    }
                })
                CreateWordField (SBFI, \_SB.PCI0.I2C2.TPL0._CRS._Y39._ADR, ADR1)  // _ADR: Address
                ADR1 = DerefOf (SADR [TPLI])
                Return (SBFI) /* \_SB_.PCI0.I2C2.TPL0._CRS.SBFI */
            }
        }
    }

    Scope (_SB.PCI0.I2C3)
    {
        Device (TPL1)
        {
            Name (_CID, "PNP0C50" /* HID Protocol Device (I2C bus) */)  // _CID: Compatible ID
            Name (_UID, One)  // _UID: Unique ID
            Name (_S0W, 0x03)  // _S0W: S0 Device Wake State
            Name (SADR, Buffer (One)
            {
                 0x10                                             // .
            })
            Name (HIDS, Package (0x01)
            {
                "ELAN9009"
            })
            Name (HIDA, Buffer (One)
            {
                 0x01                                             // .
            })
            Method (_HID, 0, NotSerialized)  // _HID: Hardware ID
            {
                Return (DerefOf (HIDS [MTLI]))
            }

            Method (_DSM, 4, NotSerialized)  // _DSM: Device-Specific Method
            {
                If ((Arg0 == ToUUID ("3cdff6f7-4267-4555-ad05-b30a3d8938de") /* HID I2C Device */))
                {
                    If ((Arg2 == Zero))
                    {
                        If ((Arg1 == One))
                        {
                            Return (Buffer (One)
                            {
                                 0x03                                             // .
                            })
                        }
                        Else
                        {
                            Return (Buffer (One)
                            {
                                 0x00                                             // .
                            })
                        }
                    }

                    If ((Arg2 == One))
                    {
                        Return (DerefOf (HIDA [MTLI]))
                    }
                }
                Else
                {
                    Return (Buffer (One)
                    {
                         0x00                                             // .
                    })
                }
            }

            Method (_STA, 0, NotSerialized)  // _STA: Status
            {
                If ((MTLP == Zero))
                {
                    Return (Zero)
                }

                Return (0x0F)
            }

            Method (_CRS, 0, NotSerialized)  // _CRS: Current Resource Settings
            {
                Name (SBFI, ResourceTemplate ()
                {
                    I2cSerialBusV2 (0x0010, ControllerInitiated, 0x00061A80,
                        AddressingMode7Bit, "\\_SB.PCI0.I2C3",
                        0x00, ResourceConsumer, _Y3A, Exclusive,
                        )
                    Interrupt (ResourceConsumer, Level, ActiveLow, Exclusive, ,, )
                    {
                        0x0000001C,
                    }
                })
                CreateWordField (SBFI, \_SB.PCI0.I2C3.TPL1._CRS._Y3A._ADR, ADR1)  // _ADR: Address
                ADR1 = DerefOf (SADR [MTLI])
                Return (SBFI) /* \_SB_.PCI0.I2C3.TPL1._CRS.SBFI */
            }
        }
    }
 
Last edited:
The DSDT for ETPD is same as mine. As in the guide, you have to introduce a GPIO interrupt configuration for SBFG definition inside the ETPD scope as below (the compiled SSDT attached)
DefinitionBlock ("", "SSDT", 2, "hack", "GPIO", 0x00000000)
{
External (_SB_.PCI0.I2C1.ETPD, DeviceObj)

Scope (\_SB.PCI0.I2C1.ETPD)
{
Name (SBFG, ResourceTemplate ()
{
GpioInt (Level, ActiveLow, ExclusiveAndWake, PullDefault, 0x0000,
"\\_SB.PCI0.GPI0", 0x00, ResourceConsumer, ,
)
{ // Pin list Try 0x57, 0xD7, 0xF7
0x0057
}
})
}
}
Change the pin number above to try all 3 and see if any of them work.

And have a rewrite rule to change in _CRS
Return (ConcatenateResTemplate (SBFB, SBFI))
to
Return (ConcatenateResTemplate (SBFB, SBFG))
the easiest was to find the smallest byte sequence corresponding to SBFB,SBFI which is not found anywhere else in the DSDT. So have the following ACPI patch
Screen Shot 2021-12-21 at 10.34.35 PM.png

If this patch and SSDT is working, your IORegistry entry for ETPD will no longer show the InterruptSpecifiers property but show gpioPin (the pin number you have in the SSDT) and a gpioIRQ with the hardware number pin type used.

If none of them work (the trackpad is non responsive), it is probably because of the same reason as mine with the pin locked by firmware. See https://www.tonymacx86.com/threads/voodooi2c-help-and-support.243378/post-2297758

I am trying to see if there is a workaround either with a DSDT patch or forcing Voodoo to use that locked interrupt.

To undo, just remove or disable the SSDT and the rewrite patch.
 

Attachments

  • SSDT-ETPD.aml
    134 bytes · Views: 57
Last edited:
@gvkt Thanks. I tested your SSDT-ETPD.aml and OpenCore config.plist patch with all of the pin number you provided (0x57, 0xD7, 0xF7, and even @sqlsec's 0x6D) but none of them get my trackpad work in GPIO mode. However, I do see that in IOReg, the InterruptSpecifiers property becomes gpioPin for all of these pins I tested (attached screenshot).
Screen Shot 2021-12-29 at 5.55.25 AM.png


In addition, I used the ACPI patch, 5342464253424649 -> 5342464253424647 instead. (Not sure why 4253424649 -> 4253424647 didn't work for me; maybe it's an NVRam reset problem?)
Screen Shot 2021-12-29 at 5.34.40 AM.png



I think you could be right; maybe the pin is locked by the firmware but it's odd to see that GPIO interrupt works on @sqlsec's laptop with pin number 0x6D but not on ours since they should be the similar setups/laptops. (They are all ASUS's Intel 10 gen laptops.)

Have the Linux people ever solved this?

Also, not sure if your laptop works the same but for me, the battery life is really too low even after I enabled Low Power Mode in macOS Monterey. Every reboot would also consume about 5% of battery life, and the battery life in light use in total is usually only about 30%-40% as it is in Windows (even after I disabled RTX 3070).
 
Last edited:
Also, do you have the same options in System Preferences>Battery?

Screen Shot 2021-12-29 at 10.13.59 AM.png

Screen Shot 2021-12-29 at 10.16.04 AM.png
 
After much experimenting with recompiled Linux kernel, it appears that we are out of luck with the BIOS/firmware on our machines.

The correct Interrupt to get hardware events is 0x5f. This works on both Windows and Linux OOB as they use their IOAPIC handlers. It corresponds to GPIO pin 74. But the firmware appears to use direct IRQ bypassing the legacy GPIO on these newer machines.

The fact that is pin is locked is not a problem because it is set to operate in GPIO mode and so being locked becomes a non-issue. Because the owner is set as APIC, both Voodoo and Linux pin control refuse to use pin 74 for IRQ. But this check can be bypassed in the code which I did. There have been some machines where bypassing this has enabled GPIO interrupts (for example some Razor Blade and even some Asus laptops). But those had the GPIO and APIC interrupts chained and therefore the interrupt status bit for GPIO was set. I suspect in @sqlsec‘s laptop which is a different model line, ownership in that BIOS was not set and GPIO was chained and hence worked OOB with the correct pin specifier. No such luck in our case.

I doubt ASUS will ever update the software to enable legacy GPIO interrupts for these touch devices and this might be a problem for a lot of newer laptops if they use interrupts beyond the MacOS limit.

For now, I am going to try increasing the polling interval as much as I can before the trackpad becomes hard to use. This should help slightly with power consumption. I am going to check if some APIC events can be handled in DSDT (EVT method) to notify a kext of such events and use it as a workaround (assuming such events are raised despite MacOS limits) to not use polling.

I think there is a bigger problem with the MacOS configuration on this machine for power consumption than trackpad polling. Even with trackpad disabled, the power consumption is very high. The CPU is always running hot very frequently in 60+C even doing nothing and fans keep coming on. I also see the CPU suddenly get very busy slowing down booting and launch of applications. This may have to do with problems with some other device drivers. Only way to know is to turn off specific devices/drivers one at a time and see which may be driving the CPU nuts. The machine on Linux is very power efficient like on Windows.
 
Last edited:
Back
Top