I've been trying to control the fan of my Lenovo Yoga 910-13IKB laptop (Windows 10) to avoid thermal throttling (I already undervolted the CPU and GPU). To achieve this I need to find a way of modifying the specific registers that control the fan on my laptop's embedded controller.
Using RWEverything
I opened all the ACPI tables on my computer, after extracting the DSDT table I found nothing but 1 register that seemed related to the fan, "CFAN" it is 1 bit long and changing it doesn't have any effect. Seems to be off by default.
After this i started investigating and got into one of the SSDTs where i found this:
Name(OSD1, Package(21)
{
0x04, "CPU Fan Duty Cycle", "RAW", 0x04, "CPU Fan #1 Speed", "RPM",
0x03, "Skin Temp 0", "RAW", 0x03, "Thermistor 1 ", "RAW", 0x03, "Thermistor 2 ",
"RAW", 0x03, "Thermistor 3 ", "RAW", 0x03, "Thermistor 4 ", "RAW"
})
Name(OSD2, Package(24)
{
0x04, "CPU Fan Duty Cycle", "RAW", 0x04, "CPU Fan #1 Speed", "RPM",
0x03, "Skin Temp 0", "RAW", 0x03, "Thermistor 1 ", "RAW", 0x03, "Thermistor 2 ",
"RAW", 0x03, "Thermistor 3 ", "RAW", 0x03, "Thermistor 4 ", "RAW",
0x03, "Thermistor 5 ", "RAW"
})
and a couple lines after i found this:
Method(OSDD, 0, Serialized)
{
If(LEqual(\_SB.PCI0.LPCB.H_EC.ECAV, One))
{
If(LEqual(TSDB, One))
{
Name(OSD2, Package(8)
{
0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000,
0x80000000, 0x80000000
})
Store(\_SB.PCI0.LPCB.H_EC.ECRD(RefOf(\_SB.PCI0.LPCB.H_EC.PENV)), Index(OSD2, Zero))
Store(\_SB.PCI0.LPCB.H_EC.ECRD(RefOf(\_SB.PCI0.LPCB.H_EC.CFSP)), Index(OSD2, One))
Store(\_SB.PCI0.LPCB.H_EC.ECRD(RefOf(\_SB.PCI0.LPCB.H_EC.TSR3)), Index(OSD2, 0x02))
Store(ShiftLeft(\_SB.PCI0.LPCB.H_EC.ECRD(RefOf(\_SB.PCI0.LPCB.H_EC.TER1)), 0x02), Index(OSD2, 0x03))
Store(ShiftLeft(\_SB.PCI0.LPCB.H_EC.ECRD(RefOf(\_SB.PCI0.LPCB.H_EC.TER2)), 0x02), Index(OSD2, 0x04))
Store(ShiftLeft(\_SB.PCI0.LPCB.H_EC.ECRD(RefOf(\_SB.PCI0.LPCB.H_EC.TER3)), 0x02), Index(OSD2, 0x05))
Store(ShiftLeft(\_SB.PCI0.LPCB.H_EC.ECRD(RefOf(\_SB.PCI0.LPCB.H_EC.TER4)), 0x02), Index(OSD2, 0x06))
Store(ShiftLeft(\_SB.PCI0.LPCB.H_EC.ECRD(RefOf(\_SB.PCI0.LPCB.H_EC.TER5)), 0x02), Index(OSD2, 0x07))
Return(OSD2)
}
Name(OSD1, Package(7)
{
0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000,
0x80000000
})
Store(\_SB.PCI0.LPCB.H_EC.ECRD(RefOf(\_SB.PCI0.LPCB.H_EC.PENV)), Index(OSD1, Zero))
Store(\_SB.PCI0.LPCB.H_EC.ECRD(RefOf(\_SB.PCI0.LPCB.H_EC.CFSP)), Index(OSD1, One))
Store(\_SB.PCI0.LPCB.H_EC.ECRD(RefOf(\_SB.PCI0.LPCB.H_EC.TSR3)), Index(OSD1, 0x02))
Store(ShiftLeft(\_SB.PCI0.LPCB.H_EC.ECRD(RefOf(\_SB.PCI0.LPCB.H_EC.TER1)), 0x02), Index(OSD1, 0x03))
Store(ShiftLeft(\_SB.PCI0.LPCB.H_EC.ECRD(RefOf(\_SB.PCI0.LPCB.H_EC.TER2)), 0x02), Index(OSD1, 0x04))
Store(ShiftLeft(\_SB.PCI0.LPCB.H_EC.ECRD(RefOf(\_SB.PCI0.LPCB.H_EC.TER3)), 0x02), Index(OSD1, 0x05))
Store(ShiftLeft(\_SB.PCI0.LPCB.H_EC.ECRD(RefOf(\_SB.PCI0.LPCB.H_EC.TER4)), 0x02), Index(OSD1, 0x06))
Return(OSD1)
}
Return(Package(0){})
}
As you can see, it seems that the fan duty cycle is register \_SB.PCI0.LPCB.H_EC.PENV
and the fan speed is \_SB.PCI0.LPCB.H_EC.CFSP
. However, I looked in every table for the words "PENV" and "CFSP" but couldn't find the numeric address. (No definition anywhere)
So, using RWEverything
I was able to identify a couple of registers that changed in sync with the fan.
(Tried to post an image of the registers but didn't have enough reputation)
I tried modifying all of these registers with no luck.
Maybe there is another way to modify \_SB.PCI0.LPCB.H_EC.PENV
and \_SB.PCI0.LPCB.H_EC.CFSP
through ACPI, or a thrid party driver for the Microsoft ACPI-Compliant Embedded Controller?
Feel free to ask any questions and any help will be greatly appreciated.
User contributions licensed under CC BY-SA 3.0