Conversation
|
Hi, with the data from the comments in #352 , I added a commit to simplify the use for the models LZCN and NZCN :
Example:
$ sensors legion_hwmon-isa-0000
legion_hwmon-isa-0000
Adapter: ISA adapter
Fan 1: 1400 RPM (max = 10000 RPM)
Fan 2: 1400 RPM (max = 10000 RPM)
CPU Temperature: +42.0°C
GPU Temperature: +35.0°C
IC Temperature: +0.0°C
pwm1: N/A (mode = pwm)Edit : There is a WMI Method that can return the selected fan curve from the internal fan tables, but I cant make it work, maybe someone knows how, keep getting ACPI Error 4100:fwts dsl struct WMIFanTableReadLoq { // FACT table
u16 FNIM;
u16 FNID;
u32 FNLE;
u16 FNS0;
u16 FNS1;
u16 FNS2;
u16 FNS3;
u16 FNS4;
u16 FNS5;
u16 FNS6;
u16 FNS7;
u16 FNS8;
u16 FNS9;
u32 SEID;
u32 STLE;
u16 SST0;
u16 SST1;
u16 SST2;
u16 SST3;
u16 SST4;
u16 SST5;
u16 SST6;
u16 SST7;
u16 SST8;
u16 SST9;
u8 SOU1;
u8 SOU2;
u16 CFMS;
u8 SOU3;
u8 SOU4;
u16 CFIS;
u16 FSSP;
u16 MST1;
u16 MST2;
u16 MSTP;
} __packed;
static ssize_t wmi_read_fancurve_idx(const struct model_config *model,
struct fancurve *fancurve)
{
u8 buffer[10];
int err;
u8 input[2] = { 0x09, 0x0 };
struct acpi_buffer in_buf = {
.length = sizeof(input),
.pointer = input,
};
err = wmi_exec_ints("87FB2A6D-D802-48E7-9208-4576C5F5C8D8", 0,
0xa7, &in_buf, buffer, sizeof(buffer));
if (!err) {
struct WMIFanTableReadLoq *fantable =
(struct WMIFanTableReadLoq *)&buffer[0];
fancurve->current_point_i = 0;
fancurve->size = fantable->FNLE;
fancurve->fan_speed_unit = FAN_SPEED_UNIT_RPM_HUNDRED;
fancurve->points[0].speed1 = fantable->FNS0;
fancurve->points[1].speed1 = fantable->FNS1;
fancurve->points[2].speed1 = fantable->FNS2;
fancurve->points[3].speed1 = fantable->FNS3;
fancurve->points[4].speed1 = fantable->FNS4;
fancurve->points[5].speed1 = fantable->FNS5;
fancurve->points[6].speed1 = fantable->FNS6;
fancurve->points[7].speed1 = fantable->FNS7;
fancurve->points[8].speed1 = fantable->FNS8;
fancurve->points[9].speed1 = fantable->FNS9;
print_hex_dump(KERN_DEBUG, "legion_laptop fan table idx wmi buffer",
DUMP_PREFIX_ADDRESS, 16, 1, buffer, sizeof(buffer),
true);
}
return err;
}``
</details> |
|
In Vantage App when the Custom Mode is selected, there is a drop down control to the right that says "Resets" and gives the options of powermodes : "Quiet, Balanced, Performance". It means that when in Custom Mode/balanced-performance 255 it can use any of the default fancurves from "Quiet, Balanced, Performance" modes. This last commit does that.
|
|
This is needed to make the 15IRX10 model to work, could be added to the whitelist after this is merged |
Add an issue with the info required / model / dmidecode as others, and also add the info that I asked on #352 to see If this PR can work for your model. |
- Offsets for reading CPU,GPU groups LZCN, NZCN, R3CN models. - Adds function wmi_write_fancurve_defaults to call WMI method SFAN to trigger the selection of fan curve. - Expose function wmi_write_fancurve_defaults as an entry in hwmon path 'auto_points_defaults' to select default fancurve from other powermodes when in custom mode. Only for tested models. - Adds compatibility for R3CN model. - Use of last range of fan curve rpm's. Vantage App limited it, LegionSpace allows it.
24779e5 to
b09f4ec
Compare
|
Works as expected |
|
missing some fixes diff --git a/kernel_module/legion-laptop.c b/kernel_module/legion-laptop.c
index f57b8af..683f219 100644
--- a/kernel_module/legion-laptop.c
+++ b/kernel_module/legion-laptop.c
@@ -2454,7 +2454,7 @@ static ssize_t fancurve_print_seqfile(const struct fancurve *fancurve,
const struct fancurve_point *point = &fancurve->points[i];
fancurve_get_speed_pwm(fancurve, i, 0, &speed_pwm1);
- fancurve_get_speed_pwm(fancurve, i, 0, &speed_pwm2);
+ fancurve_get_speed_pwm(fancurve, i, 1, &speed_pwm2);
seq_printf(
s,
diff --git a/python/legion_linux/legion_linux/legion.py b/python/legion_linux/legion_linux/legion.py
index df551cb..d63660a 100755
--- a/python/legion_linux/legion_linux/legion.py
+++ b/python/legion_linux/legion_linux/legion.py
@@ -872,10 +872,10 @@ class FanCurveIO(Feature):
return self._read_file(file_path)
def get_fan_1_speed_rpm(self, point_id):
- return round(self.get_fan_1_speed_pwm(point_id)/255.0*self.get_fan_1_max_rpm(), ndigits=2)
+ return round(((self.get_fan_1_speed_pwm(point_id) * self.get_fan_1_max_rpm() + (100 * 255) - 1) // (100 * 255)) * 100 , ndigits=2)
def get_fan_2_speed_rpm(self, point_id):
- return round(self.get_fan_2_speed_pwm(point_id)/255.0*self.get_fan_2_max_rpm(), ndigits=2)
+ return round(((self.get_fan_2_speed_pwm(point_id) * self.get_fan_2_max_rpm() + (100 * 255) - 1) // (100 * 255)) * 100 , ndigits=2)
def get_lower_cpu_temperature(self, point_id):
point_id = self._validate_point_id(point_id)
also we are missing the GPU and IC temps |
- User can query its current value, 0 if is not set. - When powermode changes Fn+q or via sysfs is reset to 0.
This reads the FNT* table configuraton that is used by the SFAN Method, provides values for: - CPU RPM's, Max Temps - GPU RPM's, Max Temps - IC Max Temps - others The temps not necessarily match the ones used, the tables that are used for temps are in FI* that only SFAN can access. The RPM's should match.
# in Custom Powermode
$ echo "balanced-performance" > /sys/firmware/acpi/platform_profile
$ sudo cat /sys/kernel/debug/legion/fancurve | tail -n 30
# First part what it reads from EC, shows what is running currently after changing mode from Balanced mode.
# Second part what it read from the WMI call that extracts the configuration of the FNT table for the current powermode, that is "balanced-powermode" (255)
u(speed_of_unit)|speed1[u]|speed2[u]|speed1[pwm]|speed2[pwm]|acceleration|deceleration|cpu_min_temp|cpu_max_temp|gpu_min_temp|gpu_max_temp|ic_min_temp|ic_max_temp
3 14 14 35 35 0 0 0 60 0 0 0 0
3 39 39 99 99 0 0 58 84 0 0 0 0
3 39 39 99 99 0 0 70 97 0 0 0 0
3 39 39 99 99 0 0 70 97 0 0 0 0
3 39 39 99 99 0 0 70 97 0 0 0 0
3 39 39 99 99 0 0 70 97 0 0 0 0
3 39 39 99 99 0 0 70 97 0 0 0 0
3 39 39 99 99 0 0 70 97 0 0 0 0
3 39 39 99 99 0 0 70 99 0 0 0 0
3 39 39 99 99 0 0 94 100 0 0 0 0
=====================
Current fan curve in hardware (WMI; might be empty)
Fan curve current point id: 0
Fan curve points size: 10
u(speed_of_unit)|speed1[u]|speed2[u]|speed1[pwm]|speed2[pwm]|acceleration|deceleration|cpu_min_temp|cpu_max_temp|gpu_min_temp|gpu_max_temp|ic_min_temp|ic_max_temp
3 14 14 35 35 0 0 0 60 0 48 0 42
3 17 17 43 43 0 0 0 70 0 60 0 63
3 19 19 48 48 0 0 0 73 0 66 0 74
3 22 22 56 56 0 0 0 77 0 70 0 76
3 25 25 63 63 0 0 0 79 0 74 0 78
3 27 27 68 68 0 0 0 82 0 77 0 80
3 29 29 73 73 0 0 0 85 0 81 0 90
3 31 31 79 79 0 0 0 92 0 85 0 95
3 35 35 89 89 0 0 0 97 0 89 0 105
3 39 39 99 99 0 0 0 100 0 100 0 120
# I want to use the rpms of quiet mode,
$ cat /path/to/hwmon/auto_points_default
0
# Is not set
$ echo 1 > /path/to/hwmon/auto_points_default
$ cat /path/to/hwmon/auto_points_default
1
# Now is set
# Checking if it was applied on EC .
$ sudo cat /sys/kernel/debug/legion/fancurve | tail -n 30
u(speed_of_unit)|speed1[u]|speed2[u]|speed1[pwm]|speed2[pwm]|acceleration|deceleration|cpu_min_temp|cpu_max_temp|gpu_min_temp|gpu_max_temp|ic_min_temp|ic_max_temp
3 0 0 0 0 0 0 0 70 0 0 0 0
3 14 14 35 35 0 0 68 86 0 0 0 0
3 17 17 43 43 0 0 84 92 0 0 0 0
3 19 19 48 48 0 0 84 92 0 0 0 0
3 22 22 56 56 0 0 84 92 0 0 0 0
3 25 25 63 63 0 0 84 92 0 0 0 0
3 29 29 73 73 0 0 84 92 0 0 0 0
3 31 31 79 79 0 0 84 92 0 0 0 0
3 35 35 89 89 0 0 88 99 0 0 0 0
3 39 39 99 99 0 0 94 100 0 0 0 0
=====================
Current fan curve in hardware (WMI; might be empty)
Fan curve current point id: 0
Fan curve points size: 10
u(speed_of_unit)|speed1[u]|speed2[u]|speed1[pwm]|speed2[pwm]|acceleration|deceleration|cpu_min_temp|cpu_max_temp|gpu_min_temp|gpu_max_temp|ic_min_temp|ic_max_temp
3 0 0 0 0 0 0 0 70 0 48 0 42
3 14 14 35 35 0 0 0 74 0 55 0 63
3 17 17 43 43 0 0 0 78 0 58 0 65
3 19 19 48 48 0 0 0 82 0 60 0 68
3 22 22 56 56 0 0 0 86 0 78 0 76
3 25 25 63 63 0 0 0 89 0 80 0 77
3 29 29 73 73 0 0 0 92 0 83 0 87
3 31 31 79 79 0 0 0 95 0 85 0 97
3 35 35 89 89 0 0 0 99 0 87 0 105
3 39 39 99 99 0 0 0 100 0 100 0 120
# looking at the sensor
legion_hwmon-isa-0000
Adapter: ISA adapter
Fan 1: 0 RPM (max = 10000 RPM)
Fan 2: 0 RPM (max = 10000 RPM)
CPU Temperature: +44.0°C
GPU Temperature: +35.0°C
IC Temperature: +0.0°C
pwm1: N/A (mode = pwm)
# Now I want to apply a "curve" to those rpm's as in the Vantage App .
$ cat /path/to/hwmon/fancurve_indices
1,2,3,4,5,6,7,8,9,10
$ echo "2,2,3,3,3,4,5,7,8,9" > /path/to/hwmon/fancurve_indices
$ cat /path/to/hwmon/fancurve_indices
2,2,3,3,3,4,5,7,8,9
$ sudo cat /sys/kernel/debug/legion/fancurve | tail -n 30
# first part what is running in the ec
# second part, you still see the original config of the fan table
# so you can choose again what indice to use, if you want to change the curve
u(speed_of_unit)|speed1[u]|speed2[u]|speed1[pwm]|speed2[pwm]|acceleration|deceleration|cpu_min_temp|cpu_max_temp|gpu_min_temp|gpu_max_temp|ic_min_temp|ic_max_temp
3 14 14 35 35 0 0 0 70 0 0 0 0
3 14 14 35 35 0 0 68 86 0 0 0 0
3 17 17 43 43 0 0 84 92 0 0 0 0
3 17 17 43 43 0 0 84 92 0 0 0 0
3 17 17 43 43 0 0 84 92 0 0 0 0
3 19 19 48 48 0 0 84 92 0 0 0 0
3 22 22 56 56 0 0 84 92 0 0 0 0
3 29 29 73 73 0 0 84 92 0 0 0 0
3 31 31 79 79 0 0 88 99 0 0 0 0
3 35 35 89 89 0 0 94 100 0 0 0 0
=====================
Current fan curve in hardware (WMI; might be empty)
Fan curve current point id: 0
Fan curve points size: 10
u(speed_of_unit)|speed1[u]|speed2[u]|speed1[pwm]|speed2[pwm]|acceleration|deceleration|cpu_min_temp|cpu_max_temp|gpu_min_temp|gpu_max_temp|ic_min_temp|ic_max_temp
3 0 0 0 0 0 0 0 70 0 48 0 42
3 14 14 35 35 0 0 0 74 0 55 0 63
3 17 17 43 43 0 0 0 78 0 58 0 65
3 19 19 48 48 0 0 0 82 0 60 0 68
3 22 22 56 56 0 0 0 86 0 78 0 76
3 25 25 63 63 0 0 0 89 0 80 0 77
3 29 29 73 73 0 0 0 92 0 83 0 87
3 31 31 79 79 0 0 0 95 0 85 0 97
3 35 35 89 89 0 0 0 99 0 87 0 105
3 39 39 99 99 0 0 0 100 0 100 0 120
# sensor
legion_hwmon-isa-0000
Adapter: ISA adapter
Fan 1: 1400 RPM (max = 10000 RPM)
Fan 2: 1400 RPM (max = 10000 RPM)
CPU Temperature: +44.0°C
GPU Temperature: +35.0°C
IC Temperature: +0.0°C
pwm1: N/A (mode = pwm) |
Expose in hwmon sysfs fancurve_indices, returns the current indices of the fan table that is used by the bios. Also allows to be modified when in Custom powermode (255) Read cat /path/to/hwmon/fancurve_indices 1,2,3,4,5,6,7,8,9,10 Write echo "2,2,3,4,5,6,7,8,9,10" > /path/to/hwmon/fancurve_indices It will use the rpm's from indice 2 in indice 1, similar to what the Vantage App does. Values allowed from 1 to 10. It takes in consideration the /path/to/hwmon/auto_points_defaults. example: If you are in custom mode "balanced-performance" (255), and you set to use the default fancurve of quiet powermode : echo 1 > /path/to/hwmon/auto_points_defaults cat /path/to/hwmon/fancurve_indices 1,2,3,4,5,6,7,8,9,10 echo "1,2,3,4,4,4,7,8,9" > /path/to/hwmon/fancurve_indices will create a curve with the rpm's of quiet powermode.
7423a00 to
2382893
Compare
|
changing to draft, I will create small PR's for each part |
Hi me again :), tldr of this PR :
Now the details :
When using the Lenovo Vantage Application when setting the custom mode and modifying its levels (points) :
It can be queried with the following powershell script :
FanTable : {2, 2, 3, 4, 5, 6, 7, 8 ,9 ,9} FanTableSize : 10 SensorTable : {2, 2, 3, 4, 5, 6 ,7, 8, 9 ,9} SensorTableSize : 10 ReturnValue : TrueIn this output the value 2 is repeated because I changed the first point of the fancurve to the same level as the second point (1400, 1400). This method is implemented now in function
wmi_read_fancurve_idx. FanId and SensorId parameters doesnt make any difference.There are many Fan Curves defined and can be queried with the following powershell :
This output is just one example, In Windows it shows 15 I assume it gets only the Fan Table specific for the laptop model, In the ACPI DSDT there are 4 Tables of 15 each one. Also the temps here are not used there are other tables with temps selected also by the thermal mode, dgpu and PRID logic.
We dont care too much about the Fan Curves predefined, maybe as a reference, however Vantage app doesnt use the 10th one that has the highest temp 120 for the IC sensor (the index doesnt start at 0 as C arrays it starts at 1), you can see in the output of
Get_Fan_Tableuses index 9 for the 10th position. This can be a warning when changing those values.The WMI call that the Vantage App uses
LENOVO_FAN_METHOD.Fan_Set_Tablerelated to the ACPI/DSDT SFAN Method only works with the indices mapping, doesnt set directly RPM's it obtains them from its internal tables. This method is implemented inwmi_write_fancurve_idx.The function
wmi_read/write_fancurve_idxcan be used as new feature on the variables exposed by the driver in hwmon or acpi/firmware (maybe) and also on the python client, if someone wants to develop it.Besides the modes Quiet (1), Balanced (2), Performance (3) and Custom (255) there is a Extreme Mode (224).
So following the DSDT code as a guide of how to obtain the rpm's, I replaced the old
ec_read/write_fancurve_loqto reset the index mapping to an ordered list (1-10) that represent the speed RPM's that are being passed as arguments (via cmd line, legion.py, legion_gui.py), sets the correct values on the offsets on the 3 groups (cpu, gpu, ic), and activates a flag to tell the device/ec to use the new values.Note:
echo "balanced" > /sys/firmware/acpi/platform_profile, the values are reset to the bios/dsdt defaults and the 3 sets of custom values are not changed, so when queryingcat /sys/kernel/debug/legion/fancurveit will appear the custom values but not the current ones, I think that when changing powermodes also we have to callwmi_write_fancurve_idxso we reset the indices, and the acpi/dsdt set the default speeds and temps of the current powermode.Test Output of Fancurve (Custom Mode, modes set in Vantage App):
Changing the CPU and GPU fans
output of fancurve