Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

State of fan readings/curves #114

Closed
yjmd2222 opened this issue Jun 21, 2024 · 17 comments
Closed

State of fan readings/curves #114

yjmd2222 opened this issue Jun 21, 2024 · 17 comments

Comments

@yjmd2222
Copy link

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
Copy link
Author

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
Copy link

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
Copy link
Author

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

@yjmd2222
Copy link
Author

yjmd2222 commented Jul 3, 2024

@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
Copy link

HolzMichel commented Jul 4, 2024

@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
Copy link
Author

yjmd2222 commented Jul 4, 2024

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.

@HolzMichel
Copy link

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
Copy link
Author

yjmd2222 commented Jul 9, 2024

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
Copy link
Author

AsusSMC/AsusSMC/AsusSMC.cpp

Lines 545 to 550 in 39c8abe

for (uint32_t i = 0, count = arrsize(FTA1); i < count; i++) {
if (FTA1[i] == avgtemp) {
idx = i;
break;
}
}

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
Copy link
Author

yjmd2222 commented Jul 10, 2024

AsusSMC/AsusSMC/AsusSMC.hpp

Lines 114 to 115 in 39c8abe

static constexpr uint32_t FTA1[] = { 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 0xFF };
static constexpr uint32_t FTA2[] = { 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 160, 185, 205, 225, 245, 250, 255 };

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
Copy link
Author

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

@yjmd2222
Copy link
Author

yjmd2222 commented Jul 13, 2024

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
Copy link
Author

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
Copy link

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
Copy link

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
Copy link
Author

yjmd2222 commented Aug 6, 2024

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.

  • The original experimental fan mod uses timer loop of 1 second to read and set the fan speed selected from the calculation of the temperatures.
  • It can be optimized for better fan mod experience.
  • There is EC fan mode for max spin, auto, and manual speed.
  • To use with 1 second is long compared to ACPIPoller.kext (I think 0.1 s), so the EC fan auto mode keeps overriding the speed set by AsusSMC, making the fan jump from time to time.
  • Setting EC fan mode to manual will prevent the above issue, but it needs to be reset at some point before booting other OS. Or 1 second period can be decreased so that the jumps smooth out quickly.
  • If woken from hibernation, the fan mod needs to be reinitialized: see Resume from hibernation turns off battery threshold at 80 percent #103
  • The SSDT and the kext attached handle everything for older laptops except the alledged hibernation problem which I cannot get to work.
  • HolzMichel's script and SSDT mod fan from a different approach by modding the fan temperature table.
  • Newer laptops have different numbers of parameters in ACPI methods, so cannot use the kext and the SSDTs right away.
  • And some hacks don't report min/max possible fan speeds for iStat menus or MacsFanControl to work. They are closed-source projects to my knowledge so don't know how hacks can add the reporting.

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

@yjmd2222 yjmd2222 closed this as completed Aug 6, 2024
@yjmd2222
Copy link
Author

yjmd2222 commented Aug 7, 2024

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants