RehabMan
Moderator
- Joined
- May 2, 2012
- Messages
- 181,058
- Motherboard
- Intel DH67BL
- CPU
- i7-2600K
- Graphics
- HD 3000
- Mac
- Mobile Phone
One thing that has always bugged me about HP laptops is the noisy fan. First of all, it runs when it doesn't need to (IMHO) and it runs faster than it needs to for the given temperatures. Although the ideal solution would be to find a different fan, or use a resistor to reduce the voltage going to the fan (thus reducing it's speed overall), at this point I didn't want to attempt that.
Instead, I've been reading various forums for a solution and a pretty good one has been developed for the Windows side of things. And fortunately, I was able to follow all the information about the ProBook's EC such that I could develop a solution on OS X. My solution should work on both Lion and ML, although I've only tested it on ML (Edit: Now tested on Lion too. Works fine!). I do however expect that it will require more testing, so I hope some of you will want to help with that. In particular, I've only tried this on my i3-2310 HD3000 system. I don't have a system with a faster CPU nor do I have one with dedicated graphics.
Let's start with how the current fan control works in the current DSDT. The current code resides in the TCPU method in the SMCD device (name FAN00000). This device is bound to ACPISensors.kext, which registers the ACPI sensor with FakeSMC. The purpose of this method is to report the CPU temperature so HWMonitor can display it. But our version does a bit more -- it controls the CPU fan as well. What the method does is write to an offset within the EC that has some control over what the fan is doing. This is the byte at offset 0x2F (known as FTGC in the DSDT). Normally this byte is set at 0xFF, which is "automatic mode" for the fan. If you write a value other than 0xFF it indicates the speed. 0x00 is the fastest. 0x80 is the slowest. The fan can only be controlled in steps. We all wish the slowest speed was a little slower, unfortunately there is nothing we can do about that.
You might notice that there is no speed for off. That is because 0xFF represents off when the current CPU temperature is 31C or lower. So unless your laptop idles at less than 31C, you will never see the fan go off in automatic mode. Of course, unless the ambient temperature is very low, seeing the fan off in normal use is fairly rare. But it is possible to control it directly...
The trick depends on the fact that if you write to the EC offset normally reserved for reading CPU temperature, you can trick the EC into thinking that the current CPU temperature is 31C (or lower). The temperature can be written here by writing 1 to offset 0x22 (CRZN), then the fake temperature to offset 0x26 (TEMP). If we simultaneously write 0xFF to the fan control, the fan will turn off. Of course, now the EC is unable to respond to temperature variations automatically, so we need code to run to constantly monitor temperature and modify the fan speed appropriately. To reset the EC, you write zero to TEMP (after selecting zone 1 with CRZN, of course). So even after locking in a temperature it is possible to reset the EC back to normal operation. This is important because the setting of the fake temperature at TEMP survives reboots and power cycles!
In addition, you don't want the fan to be constantly turning on one second, then turning off the next, so whatever logic we have in place must buffer changes to the fan speed, to avoid annoying an unnecessary fan speed changes. My solution uses a couple of techniques to accomplish this. First, it doesn't respond to instant temperature fluctuations. Instead it calculates a moving average (current running over 16 samples, collected a second apart) and responds to changes in the average. Second of all, it delays any change in fan speed by a variable time depending on how "far" the current desired fan speed is from the currently set fan speed. Right now this varies between 20 seconds, and 3 seconds, depending on how far the temperature runs. I would say it is extremely lazy about changing fan speed right now. Maybe too lazy. You can try it and give feedback.
Since my code tricks the EC into believing that the laptop is arbitrarily cool, the current method of letting HWMonitor cause the fan control method to execute is not adequate because there are bunch of scenarios where HWMonitor is not running. Consider the case where you run HWMonitor, causing a "fake" temperature to be set, and the fan to be turned off, then you, logout, restart into BIOS, restart into Chimera, restart and boot another OS like Windows. In all those cases, the fan will be left off, the EC will think the laptop is cool, and the fan would never turn on.
In order to handle some of these scenarios I had to develop a bit more software in addition to the new DSDT patch:
- A Chimera module to be run when Chimera starts up. This module is called Fanreset.dylib and it resets the EC to factory settings when Chimera starts. This handles the case you boot some other OS, or just sit at the Chimera screen for a while.
- A Kernel Extension (kext) to call the fan control method in the DSDT to get proper fan control when logged out. This also means you do not need to run HWMonitor to get fan control (HWMonitor is back to just displaying information -- not controlling the fan). This new kernel extension is called ACPIPoller.kext and its purpose is to simply call APCI methods every second. It uses a list of methods called out in the Info.plist and simply attaches to our SMCD device and calls the FCPU method (the FCPU method contains the heart of my new fan control logic)
Note: there is no solution to resetting into BIOS. I recommend always booting into Chimera after running OS X with this fan control software active, then restarting into BIOS (Ctrl+Alt+Del). Alternatively, you can use the EC reset procedure detailed later.
How to install:
- First, repatch your DSDT using my patches available here: https://github.com/RehabMan/HP-ProBook-4x30s-DSDT-Patch
(see the wiki for instructions)
The difference between this patch and a normal patch is that instead of using 04_FanPatch.txt, use 04_FanExperimental.txt. If you are using the Makefile, you can use 'make allexp' to make both the normal patch (all_exp.txt, all1080_exp.txt). Then patch your DSDT using Auto Patcher. You can probably also use the 04_FanExperimental.txt to patch an existing DSDT you already have. I have not tried that, but I think it will work. After patching, copy the result to /Extra/dsdt.aml like normal.
- Second, download and install Fanreset.dylib. It is available here: https://github.com/RehabMan/HP-ProBook-4x30s-Fan-Reset
(see downloads section for binary)
Just copy the binary to /Extra/modules/Fanreset.dylib. You will likely have to make the directory /Extra/modules with 'mkdir /Extra/modules'
- Third, download and install ACPIPoller.kext. It is available here: https://github.com/RehabMan/OS-X-ACPI-Poller
(see downloads section for binary)
You can install using Kext Wizard just like you would install any kext.
Note: Make sure you uncheck the BIOS option "Fan always on with AC power"
After all that, reboot, and you should see the fan off at temperatures up to 40C. If you look at the code in the 04_FanExperimental.txt, you will see a table that correlates fan speeds to CPU temperatures. It is here you can tweak things if you want:
The first byte of each pair in the buffer is the high temperature threshold for the given fan speed that follows. So, for temps up to 40C, the fan is set to automatic (0xFF or 255) and since we are faking the temperature at 31C, the fan will be off. Certainly you could try running at higher temps before turning the fan on, but it might help to run the way I have it and see how your laptop behaves.
If you think things are not working correctly, it might be wise to turn your laptop off and let it cool. Obviously what we are doing here is pretty sketchy and I'm not going to take any responsibility for you burning your laptop up or otherwise damaging it due to overheating. If you think that your EC is not getting reset (via the Chimera Fanreset module), you can reset the EC to default behavior by turning the laptop off, disconnecting AC power, removing the battery, pressing the power button for 30-secs, then putting everything back together and restarting.
In addition, you might want to monitor temperatures and the operation of this fan control DSDT software. For that I have built a special version of HWMonitor, which I have attached to this post. It displays some debugging information from the FCPU method as well as some additional temperatures.
Credits:
http://forum.notebookreview.com/hp-...ays-help-dsdt-editing-nhc-acpi-module-15.html
(in particular poster tkg2 with super useful information!!!)
http://www.computerbase.de/forum/showthread.php?t=1070494
(german)
http://translate.google.com/transla...ase.de/forum/showthread.php?t=1070494&act=url
(english google translate of german site above)
Instead, I've been reading various forums for a solution and a pretty good one has been developed for the Windows side of things. And fortunately, I was able to follow all the information about the ProBook's EC such that I could develop a solution on OS X. My solution should work on both Lion and ML, although I've only tested it on ML (Edit: Now tested on Lion too. Works fine!). I do however expect that it will require more testing, so I hope some of you will want to help with that. In particular, I've only tried this on my i3-2310 HD3000 system. I don't have a system with a faster CPU nor do I have one with dedicated graphics.
Let's start with how the current fan control works in the current DSDT. The current code resides in the TCPU method in the SMCD device (name FAN00000). This device is bound to ACPISensors.kext, which registers the ACPI sensor with FakeSMC. The purpose of this method is to report the CPU temperature so HWMonitor can display it. But our version does a bit more -- it controls the CPU fan as well. What the method does is write to an offset within the EC that has some control over what the fan is doing. This is the byte at offset 0x2F (known as FTGC in the DSDT). Normally this byte is set at 0xFF, which is "automatic mode" for the fan. If you write a value other than 0xFF it indicates the speed. 0x00 is the fastest. 0x80 is the slowest. The fan can only be controlled in steps. We all wish the slowest speed was a little slower, unfortunately there is nothing we can do about that.
You might notice that there is no speed for off. That is because 0xFF represents off when the current CPU temperature is 31C or lower. So unless your laptop idles at less than 31C, you will never see the fan go off in automatic mode. Of course, unless the ambient temperature is very low, seeing the fan off in normal use is fairly rare. But it is possible to control it directly...
The trick depends on the fact that if you write to the EC offset normally reserved for reading CPU temperature, you can trick the EC into thinking that the current CPU temperature is 31C (or lower). The temperature can be written here by writing 1 to offset 0x22 (CRZN), then the fake temperature to offset 0x26 (TEMP). If we simultaneously write 0xFF to the fan control, the fan will turn off. Of course, now the EC is unable to respond to temperature variations automatically, so we need code to run to constantly monitor temperature and modify the fan speed appropriately. To reset the EC, you write zero to TEMP (after selecting zone 1 with CRZN, of course). So even after locking in a temperature it is possible to reset the EC back to normal operation. This is important because the setting of the fake temperature at TEMP survives reboots and power cycles!
In addition, you don't want the fan to be constantly turning on one second, then turning off the next, so whatever logic we have in place must buffer changes to the fan speed, to avoid annoying an unnecessary fan speed changes. My solution uses a couple of techniques to accomplish this. First, it doesn't respond to instant temperature fluctuations. Instead it calculates a moving average (current running over 16 samples, collected a second apart) and responds to changes in the average. Second of all, it delays any change in fan speed by a variable time depending on how "far" the current desired fan speed is from the currently set fan speed. Right now this varies between 20 seconds, and 3 seconds, depending on how far the temperature runs. I would say it is extremely lazy about changing fan speed right now. Maybe too lazy. You can try it and give feedback.
Since my code tricks the EC into believing that the laptop is arbitrarily cool, the current method of letting HWMonitor cause the fan control method to execute is not adequate because there are bunch of scenarios where HWMonitor is not running. Consider the case where you run HWMonitor, causing a "fake" temperature to be set, and the fan to be turned off, then you, logout, restart into BIOS, restart into Chimera, restart and boot another OS like Windows. In all those cases, the fan will be left off, the EC will think the laptop is cool, and the fan would never turn on.
In order to handle some of these scenarios I had to develop a bit more software in addition to the new DSDT patch:
- A Chimera module to be run when Chimera starts up. This module is called Fanreset.dylib and it resets the EC to factory settings when Chimera starts. This handles the case you boot some other OS, or just sit at the Chimera screen for a while.
- A Kernel Extension (kext) to call the fan control method in the DSDT to get proper fan control when logged out. This also means you do not need to run HWMonitor to get fan control (HWMonitor is back to just displaying information -- not controlling the fan). This new kernel extension is called ACPIPoller.kext and its purpose is to simply call APCI methods every second. It uses a list of methods called out in the Info.plist and simply attaches to our SMCD device and calls the FCPU method (the FCPU method contains the heart of my new fan control logic)
Note: there is no solution to resetting into BIOS. I recommend always booting into Chimera after running OS X with this fan control software active, then restarting into BIOS (Ctrl+Alt+Del). Alternatively, you can use the EC reset procedure detailed later.
How to install:
- First, repatch your DSDT using my patches available here: https://github.com/RehabMan/HP-ProBook-4x30s-DSDT-Patch
(see the wiki for instructions)
The difference between this patch and a normal patch is that instead of using 04_FanPatch.txt, use 04_FanExperimental.txt. If you are using the Makefile, you can use 'make allexp' to make both the normal patch (all_exp.txt, all1080_exp.txt). Then patch your DSDT using Auto Patcher. You can probably also use the 04_FanExperimental.txt to patch an existing DSDT you already have. I have not tried that, but I think it will work. After patching, copy the result to /Extra/dsdt.aml like normal.
- Second, download and install Fanreset.dylib. It is available here: https://github.com/RehabMan/HP-ProBook-4x30s-Fan-Reset
(see downloads section for binary)
Just copy the binary to /Extra/modules/Fanreset.dylib. You will likely have to make the directory /Extra/modules with 'mkdir /Extra/modules'
- Third, download and install ACPIPoller.kext. It is available here: https://github.com/RehabMan/OS-X-ACPI-Poller
(see downloads section for binary)
You can install using Kext Wizard just like you would install any kext.
Note: Make sure you uncheck the BIOS option "Fan always on with AC power"
After all that, reboot, and you should see the fan off at temperatures up to 40C. If you look at the code in the 04_FanExperimental.txt, you will see a table that correlates fan speeds to CPU temperatures. It is here you can tweak things if you want:
Code:
// Fan Control Table (pairs of temp, fan control byte)\n
Name (FTAB, Buffer ()\n
{\n
40, 255, // 255 is off (really auto, but at low temp it is off)\n
45, 128, // 128 is slowest speed\n
50, 82,\n
55, 74,\n
60, 59,\n
70, 49,\n
0xFF, 0 // last entry must be 0xFF, 0 is max fan speed\n
})\n
The first byte of each pair in the buffer is the high temperature threshold for the given fan speed that follows. So, for temps up to 40C, the fan is set to automatic (0xFF or 255) and since we are faking the temperature at 31C, the fan will be off. Certainly you could try running at higher temps before turning the fan on, but it might help to run the way I have it and see how your laptop behaves.
If you think things are not working correctly, it might be wise to turn your laptop off and let it cool. Obviously what we are doing here is pretty sketchy and I'm not going to take any responsibility for you burning your laptop up or otherwise damaging it due to overheating. If you think that your EC is not getting reset (via the Chimera Fanreset module), you can reset the EC to default behavior by turning the laptop off, disconnecting AC power, removing the battery, pressing the power button for 30-secs, then putting everything back together and restarting.
In addition, you might want to monitor temperatures and the operation of this fan control DSDT software. For that I have built a special version of HWMonitor, which I have attached to this post. It displays some debugging information from the FCPU method as well as some additional temperatures.
Credits:
http://forum.notebookreview.com/hp-...ays-help-dsdt-editing-nhc-acpi-module-15.html
(in particular poster tkg2 with super useful information!!!)
http://www.computerbase.de/forum/showthread.php?t=1070494
(german)
http://translate.google.com/transla...ase.de/forum/showthread.php?t=1070494&act=url
(english google translate of german site above)