hieplpvip / AsusSMC

A VirtualSMC plugin provides native macOS support for ALS, keyboard backlight and Fn keys on Asus laptops
MIT License
171 stars 22 forks source link

State of fan readings/curves #114

Closed yjmd2222 closed 1 month ago

yjmd2222 commented 3 months ago

The most recent commits include some things about fan readings. Anybody knows anything about them? I think hiep tried to see if setting fan curve works directly via WMI/EC in the "experimental fan code," but have no idea on the current status. ACPIPoller introduces a third-party module to always poll on the fan to measure the current/cumulative fan/temperature, so I guess it uses up a lot of resources, hence not used in the OC branch of the Zenbook repo. The fan readings are not published as are. Had to use SMCSuperIO.kext and the corresponding properties for "generic" device kindly provided by BrandTime for the actual readings by iStat menus and Macs Fan Control. But even so the min/max rpms are invalid (65345 something). Anyone would like to share their experience or information?

yjmd2222 commented 3 months ago

Interesting findings here: https://www.hackintosh-forum.de/forum/thread/58108-asus-notebook-fan-control-acpi-schreiben-in-ec-ram/ and the issue link in it. There's a temperature table in the EC RAM which is picked up by the fan mechanism to spin at certain levels at the corresponding temperatures.

@HolzMichel, I'm guessing you are the one that started the thread above. Have you had any more progress other than updating this table with ACPIDebug? And I'm not trying to be offensive, but parts of your offsets and the SSDT are probably wrong, as hexadecimal numbering does not go from 9 to 10. It should be ..., 0x539, 0x53a, 0x53b,...

HolzMichel commented 3 months ago

Hello @yjmd2222 , yes this is an excel auto fill issue, in my real implementation it is correct of course…. I have been using this method for more than a year now and it works very well. I have two Automator scripts, one runs on startup and sets the „silent“ fan curve. The other one has a small GUI and let’s me select different modes: silent, full speed, stock and so on.

If it is beneficial for you I can upload what I did here.

yjmd2222 commented 3 months ago

Hello. It'd be great to see your scripts. Not only me but all others could benefit from them.

yjmd2222 commented 3 months ago

@HolzMichel, please feel free to upload your scripts any time :) Meanwhile, I tried to see if setting the values within the ACPI itself is possible. Ugly and nested usage of ECAV, but the log shows successful writes. I only set the first five bytes though.

    Scope (\_SB.PCI0.LPCB.EC0)
    {
        Device (YJMD)
        {
            Name (_ADR, Zero)  // _ADR: Address
            Method (_INI, 0, NotSerialized)  // _INI: Initialize
            {
                If (ECAV ())
                {
                    \RMDT.P1 ("RMDT debug: EC available")
                    \RMDT.P1 ("RMDT debug: Writing to Fan Temp table")
                    \_SB.PCI0.LPCB.EC0.WRAM (0x0537, 0x3C)
                    \_SB.PCI0.LPCB.EC0.WRAM (0x0538, 0x3E)
                    \_SB.PCI0.LPCB.EC0.WRAM (0x0539, 0x40)
                    \_SB.PCI0.LPCB.EC0.WRAM (0x053A, 0x42)
                    \_SB.PCI0.LPCB.EC0.WRAM (0x053B, 0x44)
                    \RMDT.P1 ("RMDT debug: Reading Fan Temp table")
                    \RMDT.P1 (\_SB.PCI0.LPCB.EC0.RRAM (0x0537))
                    \RMDT.P1 (\_SB.PCI0.LPCB.EC0.RRAM (0x0538))
                    \RMDT.P1 (\_SB.PCI0.LPCB.EC0.RRAM (0x0539))
                    \RMDT.P1 (\_SB.PCI0.LPCB.EC0.RRAM (0x053A))
                    \RMDT.P1 (\_SB.PCI0.LPCB.EC0.RRAM (0x053B))
                    \RMDT.P1 (\_SB.PCI0.LPCB.EC0.RRAM (0x053C))
                    \RMDT.P1 (\_SB.PCI0.LPCB.EC0.RRAM (0x053D))
                    \RMDT.P1 (\_SB.PCI0.LPCB.EC0.RRAM (0x053E))
                }
                Else
                {
                    \RMDT.P1 ("RMDT debug: EC not available")
                }
            }

            Method (_STA, 0, NotSerialized)  // _STA: Status
            {
                If (_OSI ("Darwin"))
                {
                    Return (0x0F)
                }
                Else
                {
                    Return (Zero)
                }
            }
        }

Interestingly, there are two definitions of ECAV object in the ACPI. One in H_EC and the other in EC0. I'm no expert in this area, but I chose EC0.ECAV because it's about writing to and reading the EC RAM if I'm not wrong. Sorry for misinformation if anybody was interested (This is to say the above striked-through writing was wrong, but my SSDT works sorry again). I was thinking I saw LPCB.ECAV and EC0.ECAV, but I mistook H_EC for LPCB. LPCB is the parent object of H_EC or EC0 in Intel. In most ASUS DSDTs, there exist H_EC and H_EC.ECAV (and EC0 and EC0.ECAV). No LPCB.ECAV anywhere. H_EC and EC0 are common ACPI names for embedded controller in Intel boards. To my knowledge, there can only be one embedded controller, and so either H_EC or EC but not both. And in our laptops, the only actual present device name for the embedded controller, EC0. Checking for availability of H_EC via H_EC.ECAV would not have worked because it's not there and because I am probing EC0. And checking availiability of LPCB.ECAV if that was actually present would not fit here because as I said EC RAM (EC0 RAM) is what's important here.

HolzMichel commented 2 months ago

@yjmd2222 your approach also looks promising and should work. If I remember correctly I initially tried to do it via SSDT but I couldn’t get the timing right so that either the system kept overwriting the registers with default values again or it never got set - did not know how to really debug this either. Finally I decided against a deeper dive into ACPI because in newer macOS versions the color banding issue of the iGPU can no longer be addressed by spoofing so the lifetime of this hardware is kind of limited. I did not forget about you, just couldn’t get my hands on the ZenBook yet.

yjmd2222 commented 2 months ago

Before someone mentioned the visual artifacts were fixed with AAPL.GfxYTile set to 1: https://github.com/EETagent/T480-OpenCore-Hackintosh/issues/32#issuecomment-692939634 The revised WEG manual says either spoof to SKL or set AAPL.GfxYTile.

You might want to set that property in DeviceProperties.

Another suggestion is use OCLP and spoof as SKL.

HolzMichel commented 2 months ago

Wow, that’s nice. I did intense research this winter but could not find this. Will give it a try for sure. Maybe I will get hands on the zenbook this weekend.

yjmd2222 commented 2 months ago

AsusSMC-1.4.1-DEBUG.zip Fan mod enabled kext

This probably runs on top of already running EC fan mechanism. hunch:

  1. I set higher temperatures for the lowest speeds in the ACPI and the fan runs intermittently for longer time, which means the kext makes the fan to spin from the temperature table with lower temperatures.
  2. Without ACPI writes, the fan spins every 5 seconds or so for shorter time. This time, EC is making the fan to spin.

I remember ACPIPoller.kext being quieter and not causing intermittent rapid spins. I need to compare the SSDT from the Clover branch and the kext source code.

afilipovich

\_SB.PCI0.LPCB.EC0.WRAM 0x0521 0xc5   # full fan speed, locks register 0x97; .TACH method shows current fan speed
\_SB.PCI0.LPCB.EC0.WRAM 0x0521 0x85   # back to automatic fan speed control
\_SB.PCI0.LPCB.EC0.WRAM 0x0521 0x35   # manual fan control. Fan speed can be controlled by .ST84 call.
\_SB.PCI0.LPCB.EC0.ST84 Arg0 Arg1     # Arg0 - fan id (0x00 for CPU fan). Arg1 - speed 0x00 - 0xff

Maybe set manual speed to 0 in EC mechanism and give only the kext the control

yjmd2222 commented 2 months ago

https://github.com/hieplpvip/AsusSMC/blob/39c8abe41003f6f084e08fd77a3f636a3f8089b9/AsusSMC/AsusSMC.cpp#L545-L550

whereas in ACPI

            Local2 = Match (FTA1, MGE, Local0, MTR, Zero, Zero)

MatchGreaterThanOrEqualTo Local0 which holds average temperature (minimum match). The kext code reads "if exact match." It should actually be

    for (uint32_t i = 0, count = arrsize(FTA1); i < count; i++) {
        if (FTA1[i] >= avgtemp) {
            idx = i;
            break;
        }
    }
yjmd2222 commented 2 months ago

https://github.com/hieplpvip/AsusSMC/blob/39c8abe41003f6f084e08fd77a3f636a3f8089b9/AsusSMC/AsusSMC.hpp#L114-L115

https://osxlatitude.com/forums/topic/10244-how-to-implement-custom-fan-control-on-asus-laptops/

When using 2 it passes Arg0 to ST98 as 0xFF (255) (Oh wait! according to ACPI spec, 255 is max allowed FAN value.)


// Scaling from values as low as 255 RPM to values as high as 5026 RPM (That's great!)
// Scaling that ASUS provided was from 2200 RPM to 2900 RPM (Duh!)
    // Temperatures. 0xFF means if temp is above 52C, let bios take control of things(auto).
    Name(FTA1, Package()
    {
        32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 0xFF,
    })

    // Fan speeds. 255(0xFF) is max/auto, 0(0x00) is for fan off
    Name(FTA2, Package()
    {
        0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 160, 185, 205, 225, 245, 250, 255
    })

Comments don't make sense. To me it reads either
1. At 52 degrees fan spins at 250 out of max 255, but above that temperature the RPM should go down if control is given to EC. So 2200 to 2900 RPM from 52 degrees up, but 255 to 5026 RPM from 52 degrees down?
2. Or some speed units of 250 at 52 degrees and EC default onward? that should not change the upper limit of 2900 RPM. False report from black.dragon74?

Probably 2 is what's going on. I noticed the difference between `ST84` and `ST98`. `ST98` makes fan spin at lower speeds when it receives high values and even 255. `ST84` seems to spin at speeds that scale from minimum 0 to maximum 255.

And `\_SB.PCI0.LPCB.EC0.WRAM 0x0521 0x35   # manual fan control. Fan speed can be controlled by .ST84 call.` this disables intermittent spins. Also seems to disable fan readings from `TACH`.
yjmd2222 commented 2 months ago

AsusSMC-1.4.1-DEBUG.zip 0x521 to 0x35, custom temperature map from 40 to 80.

yjmd2222 commented 2 months ago

SSDT-FanModeReset.aml.zip AsusSMC-1.4.1-DEBUG.zip The SSDT is for resetting Fan mode from manual control to automatic. This is needed if rebooting from macOS to any other OS. Cold boot doesn't matter as in this case EC is reset. Load AsusSMCFanDataProvider.kext before AsusSMC.kext. You can set your own temperatures and speeds in the former kext. Just make sure the numbers of items in the respective arrays match. It is best if someone finds the best temperature and speed sets. boot arg needed: -asussmcfanmod Fork here: https://github.com/yjmd2222/AsusSMC

yjmd2222 commented 2 months ago

SSDT-FanModeReset.aml.zip This updated SSDT checks fan mode before overriding it. Exit if already in automatic mode.

And the kext and the SSDT won't work on newer Zenbooks. Need a check for generation/model. RRAM and WRAM have different numbers of arguments across different models, so that may be an option

HolzMichel commented 1 month ago

I finally found some time to respond to this thread. Here is my SSDT-RMDT where I implemented the different fan curves (silent, cool, stock) and also the other commands mentioned above: SSDT-RMDT.aml.zip

I use ioio to call the methods from within MacOS. Scripts.zip

From there it is quite easy to add e. g. automator tasks that run on startup an automatically set a fan curve or do some quick and dirty gui tools: grafik grafik

HolzMichel commented 1 month ago

Before someone mentioned the visual artifacts were fixed with AAPL.GfxYTile set to 1: EETagent/T480-OpenCore-Hackintosh#32 (comment) The revised WEG manual says either spoof to SKL or set AAPL.GfxYTile.

You might want to set that property in DeviceProperties.

Another suggestion is use OCLP and spoof as SKL.

@yjmd2222 According to this https://github.com/acidanthera/WhateverGreen/blob/master/Manual/FAQ.IntelHD.en.md setting the AAPL,GfxYTile is for "the other way around", they talk about spoofing skylake as kabylake but what I need to do to avoid color banding is spoof my kabylake as a skylake. Feel free to correct me if I got it wrong.

yjmd2222 commented 1 month ago

Thanks for your scripts!

As for colorbanding, the devs say the fixes the AAPL property does is not exclusive to SKL, but I read elsewhere it does not fix the color banding issues unless the display panel is replaced. So I think you might want to use OCLP to upgrade to newer OSes.

I will close this issue because the original question was answered and there was information gain.

@HolzMichel please open a new issue for the color banding problem.

yjmd2222 commented 1 month ago

After rebooting about 10 times, hibernation magically worked.

[ 1203.999436]: AsusSMC       fan: @ (DBG) refreshFan speed 2840
[ 1203.999717]: AsusSMC       fan: @ (DBG) setFanSpeed cpu temp 63
[ 1203.999720]: AsusSMC       fan: @ (DBG) setFanSpeed average temp 57
[ 1205.001078]: AsusSMC       fan: @ (DBG) refreshFan speed 3166
[ 1205.001732]: AsusSMC       fan: @ (DBG) setFanSpeed cpu temp 63
[ 1205.001739]: AsusSMC       fan: @ (DBG) setFanSpeed average temp 58
[ 1206.002461]: AsusSMC       fan: @ (DBG) refreshFan speed 3252
[ 1206.003117]: AsusSMC       fan: @ (DBG) setFanSpeed cpu temp 48
[ 1206.003124]: AsusSMC       fan: @ (DBG) setFanSpeed average temp 58
[ 1207.003592]: AsusSMC       fan: @ (DBG) refreshFan speed 3267
[ 1207.004143]: AsusSMC       fan: @ (DBG) setFanSpeed cpu temp 62
[ 1207.004149]: AsusSMC       fan: @ (DBG) setFanSpeed average temp 58
[ 1208.004351]: AsusSMC       fan: @ (DBG) refreshFan speed 3267
[ 1208.004534]: AsusSMC       fan: @ (DBG) setFanSpeed cpu temp 57
[ 1208.004536]: AsusSMC       fan: @ (DBG) setFanSpeed average temp 58
…
[ 1265.272158]: [ACPI Debug]  [ACPI Debug]  "RRAM (0X0521) result: 0000000000000085"

Fan switches on and off every second or so as if in automatic mode. Fan log shows fan reading is available because it is not in manual mode. ACPIDebug log shows the fan is in fact in automatic mode (0x85).

So hibernation does reset EC. I will see if I can try to make the kext reinitialize fan mod on resume.