Skip to content

Commit

Permalink
Remove 0RPM mode for gen8 devices (#737)
Browse files Browse the repository at this point in the history
* Remove 0RPM mode for gen8 devices

* Fix power mode feature toggle.

* Clean up
  • Loading branch information
BartoszCichecki authored May 25, 2023
1 parent 475c0bf commit 204a5be
Show file tree
Hide file tree
Showing 9 changed files with 118 additions and 70 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ public async Task<GodModeState> GetStateAsync()
if (Log.Instance.IsTraceEnabled)
Log.Instance.Trace($"Loading state from store...");

return LoadStateFromStore(store, defaultState);
return await LoadStateFromStoreAsync(store, defaultState).ConfigureAwait(false);
}

public Task SetStateAsync(GodModeState state)
Expand Down Expand Up @@ -106,6 +106,14 @@ public Task SetStateAsync(GodModeState state)

public abstract Task ApplyStateAsync();

public Task<FanTable> GetDefaultFanTableAsync()
{
var fanTable = new FanTable(new ushort[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 });
return Task.FromResult(fanTable);
}

public abstract Task<FanTable> GetMinimumFanTableAsync();

public abstract Task<Dictionary<PowerModeState, GodModeDefaults>> GetDefaultsInOtherPowerModesAsync();

public abstract Task RestoreDefaultsInOtherPowerModeAsync(PowerModeState state);
Expand All @@ -132,9 +140,16 @@ public Task SetStateAsync(GodModeState state)
throw new InvalidOperationException($"Preset with ID {activePresetId} not found.");
}

protected async Task<bool> IsValidFanTableAsync(FanTable fanTable)
{
var minimumFanTable = await GetMinimumFanTableAsync().ConfigureAwait(false);
var minimum = minimumFanTable.GetTable();
return fanTable.GetTable().Where((t, i) => t < minimum[i] || t > 10u).IsEmpty();
}

private bool IsValidStore(GodModeSettings.GodModeSettingsStore store) => store.Presets.Any() && store.Presets.ContainsKey(store.ActivePresetId);

private GodModeState LoadStateFromStore(GodModeSettings.GodModeSettingsStore store, GodModePreset defaultState)
private async Task<GodModeState> LoadStateFromStoreAsync(GodModeSettings.GodModeSettingsStore store, GodModePreset defaultState)
{
var states = new Dictionary<Guid, GodModePreset>();

Expand All @@ -157,7 +172,7 @@ private GodModeState LoadStateFromStore(GodModeSettings.GodModeSettingsStore sto
preset.GPUTotalProcessingPowerTargetOnAcOffsetFromBaseline,
preset.MinValueOffset,
preset.MaxValueOffset),
FanTableInfo = GetFanTableInfo(preset, defaultState.FanTableInfo?.Data),
FanTableInfo = await GetFanTableInfoAsync(preset, defaultState.FanTableInfo?.Data).ConfigureAwait(false),
FanFullSpeed = preset.FanFullSpeed,
MinValueOffset = preset.MinValueOffset ?? defaultState.MinValueOffset,
MaxValueOffset = preset.MaxValueOffset ?? defaultState.MaxValueOffset
Expand Down Expand Up @@ -210,7 +225,7 @@ private GodModeState LoadStateFromStore(GodModeSettings.GodModeSettingsStore sto
return null;
}

private FanTableInfo? GetFanTableInfo(GodModeSettings.GodModeSettingsStore.Preset preset, FanTableData[]? fanTableData)
private async Task<FanTableInfo?> GetFanTableInfoAsync(GodModeSettings.GodModeSettingsStore.Preset preset, FanTableData[]? fanTableData)
{
if (Log.Instance.IsTraceEnabled)
Log.Instance.Trace($"Getting fan table info...");
Expand All @@ -225,17 +240,17 @@ private GodModeState LoadStateFromStore(GodModeSettings.GodModeSettingsStore sto
if (Log.Instance.IsTraceEnabled)
Log.Instance.Trace($"Fan table data retrieved: {fanTableData}");

var fanTable = preset.FanTable ?? FanTable.Default;
var fanTable = preset.FanTable ?? await GetDefaultFanTableAsync().ConfigureAwait(false);

if (Log.Instance.IsTraceEnabled)
Log.Instance.Trace($"Fan table retrieved: {fanTable}");

if (!fanTable.IsValid())
if (!await IsValidFanTableAsync(fanTable).ConfigureAwait(false))
{
if (Log.Instance.IsTraceEnabled)
Log.Instance.Trace($"Fan table invalid, replacing with default...");

fanTable = FanTable.Default;
fanTable = await GetDefaultFanTableAsync().ConfigureAwait(false);
}

return new FanTableInfo(fanTableData, fanTable);
Expand Down
12 changes: 12 additions & 0 deletions LenovoLegionToolkit.Lib/Controllers/GodMode/GodModeController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,18 @@ public async Task ApplyStateAsync()
await controller.ApplyStateAsync().ConfigureAwait(false);
}

public async Task<FanTable> GetDefaultFanTableAsync()
{
var controller = await GetControllerAsync().ConfigureAwait(false);
return await controller.GetDefaultFanTableAsync().ConfigureAwait(false);
}

public async Task<FanTable> GetMinimumFanTableAsync()
{
var controller = await GetControllerAsync().ConfigureAwait(false);
return await controller.GetMinimumFanTableAsync().ConfigureAwait(false);
}

public async Task<Dictionary<PowerModeState, GodModeDefaults>> GetDefaultsInOtherPowerModesAsync()
{
var controller = await GetControllerAsync().ConfigureAwait(false);
Expand Down
62 changes: 37 additions & 25 deletions LenovoLegionToolkit.Lib/Controllers/GodMode/GodModeControllerV1.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ public override async Task ApplyStateAsync()
var gpuPowerBoost = preset.GPUPowerBoost;
var gpuConfigurableTgp = preset.GPUConfigurableTGP;
var gpuTemperatureLimit = preset.GPUTemperatureLimit;
var fanTable = preset.FanTable ?? FanTable.Default;
var fanTable = preset.FanTable ?? await GetDefaultFanTableAsync().ConfigureAwait(false);
var fanFullSpeed = preset.FanFullSpeed ?? false;

if (cpuLongTermPowerLimit is not null)
Expand Down Expand Up @@ -233,12 +233,12 @@ public override async Task ApplyStateAsync()
if (Log.Instance.IsTraceEnabled)
Log.Instance.Trace($"Applying Fan Table {fanTable}...");

if (!fanTable.IsValid())
if (!await IsValidFanTableAsync(fanTable).ConfigureAwait(false))
{
if (Log.Instance.IsTraceEnabled)
Log.Instance.Trace($"Fan table invalid, replacing with default...");

fanTable = FanTable.Default;
fanTable = await GetDefaultFanTableAsync().ConfigureAwait(false);
}

await SetFanTable(fanTable).ConfigureAwait(false);
Expand All @@ -255,6 +255,12 @@ public override async Task ApplyStateAsync()
Log.Instance.Trace($"State applied.");
}

public override Task<FanTable> GetMinimumFanTableAsync()
{
var fanTable = new FanTable(new ushort[] { 0, 0, 0, 0, 0, 0, 0, 1, 3, 5 });
return Task.FromResult(fanTable);
}

public override async Task<Dictionary<PowerModeState, GodModeDefaults>> GetDefaultsInOtherPowerModesAsync()
{
try
Expand Down Expand Up @@ -465,7 +471,7 @@ protected override async Task<GodModePreset> GetDefaultStateAsync()
GPUPowerBoost = await GetGPUPowerBoost().OrNull().ConfigureAwait(false),
GPUConfigurableTGP = await GetGPUConfigurableTGPAsync().OrNull().ConfigureAwait(false),
GPUTemperatureLimit = await GetGPUTemperatureLimitAsync().OrNull().ConfigureAwait(false),
FanTableInfo = fanTableData is null ? null : new FanTableInfo(fanTableData, FanTable.Default),
FanTableInfo = fanTableData is null ? null : new FanTableInfo(fanTableData, await GetDefaultFanTableAsync().ConfigureAwait(false)),
FanFullSpeed = await GetFanFullSpeedAsync().ConfigureAwait(false),
MinValueOffset = 0,
MaxValueOffset = 0
Expand Down Expand Up @@ -823,27 +829,33 @@ protected static Task SetFanFullSpeedAsync(bool enabled) => WMI.CallAsync("root\

#region Default values

private static Task<IEnumerable<(PowerModeState powerMode, GodModeDefaults defaults)>> GetDefaultValuesInDifferentModeAsync() => WMI.ReadAsync("root\\WMI",
$"SELECT * FROM LENOVO_DEFAULT_VALUE_IN_DIFFERENT_MODE_DATA ",
pdc =>
{
var mode = Convert.ToInt32(pdc["mode"].Value) - 1;

return ((PowerModeState)mode, new GodModeDefaults
{
CPULongTermPowerLimit = Convert.ToInt32(pdc["DefaultLongTermPowerlimit"].Value),
CPUShortTermPowerLimit = Convert.ToInt32(pdc["DefaultShortTermPowerlimit"].Value),
CPUPeakPowerLimit = Convert.ToInt32(pdc["DefaultPeakPowerLimit"].Value),
CPUCrossLoadingPowerLimit = Convert.ToInt32(pdc["DefaultCpuCrossLoading"].Value),
APUsPPTPowerLimit = Convert.ToInt32(pdc["DefaultAPUsPPTPowerLimit"].Value),
CPUTemperatureLimit = Convert.ToInt32(pdc["DefaultTemperatueControl"].Value),
GPUPowerBoost = Convert.ToInt32(pdc["Default_PPAB_Powerlimit"].Value),
GPUConfigurableTGP = Convert.ToInt32(pdc["Default_cTGP_Powerlimit"].Value),
GPUTemperatureLimit = Convert.ToInt32(pdc["DefaultTemperatueLimit"].Value),
FanTable = FanTable.Default,
FanFullSpeed = false
});
});
private async Task<IEnumerable<(PowerModeState powerMode, GodModeDefaults defaults)>> GetDefaultValuesInDifferentModeAsync()
{
var defaultFanTableAsync = await GetDefaultFanTableAsync().ConfigureAwait(false);

var result = await WMI.ReadAsync("root\\WMI",
$"SELECT * FROM LENOVO_DEFAULT_VALUE_IN_DIFFERENT_MODE_DATA ",
pdc =>
{
var mode = (PowerModeState)Convert.ToInt32(pdc["mode"].Value) - 1;

return (mode, new GodModeDefaults
{
CPULongTermPowerLimit = Convert.ToInt32(pdc["DefaultLongTermPowerlimit"].Value),
CPUShortTermPowerLimit = Convert.ToInt32(pdc["DefaultShortTermPowerlimit"].Value),
CPUPeakPowerLimit = Convert.ToInt32(pdc["DefaultPeakPowerLimit"].Value),
CPUCrossLoadingPowerLimit = Convert.ToInt32(pdc["DefaultCpuCrossLoading"].Value),
APUsPPTPowerLimit = Convert.ToInt32(pdc["DefaultAPUsPPTPowerLimit"].Value),
CPUTemperatureLimit = Convert.ToInt32(pdc["DefaultTemperatueControl"].Value),
GPUPowerBoost = Convert.ToInt32(pdc["Default_PPAB_Powerlimit"].Value),
GPUConfigurableTGP = Convert.ToInt32(pdc["Default_cTGP_Powerlimit"].Value),
GPUTemperatureLimit = Convert.ToInt32(pdc["DefaultTemperatueLimit"].Value),
FanTable = defaultFanTableAsync,
FanFullSpeed = false
});
}).ConfigureAwait(false);
return result;
}

#endregion

Expand Down
16 changes: 11 additions & 5 deletions LenovoLegionToolkit.Lib/Controllers/GodMode/GodModeControllerV2.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ public override async Task ApplyStateAsync()
{ TuneId.GPUTotalProcessingPowerTargetOnAcOffsetFromBaseline, preset.GPUTotalProcessingPowerTargetOnAcOffsetFromBaseline },
};

var fanTable = preset.FanTable ?? FanTable.Default;
var fanTable = preset.FanTable ?? await GetDefaultFanTableAsync().ConfigureAwait(false);
var fanFullSpeed = preset.FanFullSpeed ?? false;

foreach (var (id, value) in settings)
Expand Down Expand Up @@ -113,12 +113,12 @@ public override async Task ApplyStateAsync()
if (Log.Instance.IsTraceEnabled)
Log.Instance.Trace($"Applying Fan Table {fanTable}...");

if (!fanTable.IsValid())
if (!await IsValidFanTableAsync(fanTable).ConfigureAwait(false))
{
if (Log.Instance.IsTraceEnabled)
Log.Instance.Trace($"Fan table invalid, replacing with default...");

fanTable = FanTable.Default;
fanTable = await GetDefaultFanTableAsync().ConfigureAwait(false);
}

await SetFanTable(fanTable).ConfigureAwait(false);
Expand All @@ -135,6 +135,12 @@ public override async Task ApplyStateAsync()
Log.Instance.Trace($"State applied.");
}

public override Task<FanTable> GetMinimumFanTableAsync()
{
var fanTable = new FanTable(new ushort[] { 1, 1, 1, 1, 1, 1, 1, 1, 3, 5 });
return Task.FromResult(fanTable);
}

public override async Task<Dictionary<PowerModeState, GodModeDefaults>> GetDefaultsInOtherPowerModesAsync()
{
try
Expand All @@ -161,7 +167,7 @@ public override async Task<Dictionary<PowerModeState, GodModeDefaults>> GetDefau
GPUConfigurableTGP = GetDefaultTuneIdValueInPowerMode(allCapabilityData, TuneId.GPUConfigurableTGP, powerMode),
GPUTemperatureLimit = GetDefaultTuneIdValueInPowerMode(allCapabilityData, TuneId.GPUTemperatureLimit, powerMode),
GPUTotalProcessingPowerTargetOnAcOffsetFromBaseline = GetDefaultTuneIdValueInPowerMode(allCapabilityData, TuneId.GPUTotalProcessingPowerTargetOnAcOffsetFromBaseline, powerMode),
FanTable = FanTable.Default,
FanTable = await GetDefaultFanTableAsync().ConfigureAwait(false),
FanFullSpeed = false
};

Expand Down Expand Up @@ -234,7 +240,7 @@ protected override async Task<GodModePreset> GetDefaultStateAsync()
GPUConfigurableTGP = stepperValues.GetValueOrNull(TuneId.GPUConfigurableTGP),
GPUTemperatureLimit = stepperValues.GetValueOrNull(TuneId.GPUTemperatureLimit),
GPUTotalProcessingPowerTargetOnAcOffsetFromBaseline = stepperValues.GetValueOrNull(TuneId.GPUTotalProcessingPowerTargetOnAcOffsetFromBaseline),
FanTableInfo = fanTableData is null ? null : new FanTableInfo(fanTableData, FanTable.Default),
FanTableInfo = fanTableData is null ? null : new FanTableInfo(fanTableData, await GetDefaultFanTableAsync().ConfigureAwait(false)),
FanFullSpeed = await GetFanFullSpeedAsync().ConfigureAwait(false)
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ public interface IGodModeController
Task<GodModeState> GetStateAsync();
Task SetStateAsync(GodModeState state);
Task ApplyStateAsync();
Task<FanTable> GetDefaultFanTableAsync();
Task<FanTable> GetMinimumFanTableAsync();
Task<Dictionary<PowerModeState, GodModeDefaults>> GetDefaultsInOtherPowerModesAsync();
Task RestoreDefaultsInOtherPowerModeAsync(PowerModeState state);
}
13 changes: 0 additions & 13 deletions LenovoLegionToolkit.Lib/Structs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -78,9 +78,6 @@ public override string ToString() =>

public readonly struct FanTable
{
public static readonly FanTable Minimum = new(new ushort[] { 0, 0, 0, 0, 0, 0, 0, 1, 3, 5 });
public static readonly FanTable Default = new(new ushort[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 });

// ReSharper disable AutoPropertyCanBeMadeGetOnly.Global
// ReSharper disable MemberCanBePrivate.Global

Expand All @@ -106,10 +103,6 @@ public FanTable(ushort[] fanTable)
if (fanTable.Length != 10)
throw new ArgumentException("Length must be 10.", nameof(fanTable));

var minimum = Minimum.GetTable();
for (var i = 0; i < fanTable.Length; i++)
fanTable[i] = Math.Clamp(fanTable[i], minimum[i], (ushort)10u);

FSTM = 1;
FSID = 0;
FSTL = 0;
Expand All @@ -127,12 +120,6 @@ public FanTable(ushort[] fanTable)

public ushort[] GetTable() => new[] { FSS0, FSS1, FSS2, FSS3, FSS4, FSS5, FSS6, FSS7, FSS8, FSS9 };

public bool IsValid()
{
var minimum = Minimum.GetTable();
return GetTable().Where((t, i) => t < minimum[i] || t > 10u).IsEmpty();
}

public byte[] GetBytes()
{
using var ms = new MemoryStream(new byte[64]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public class PowerModeControl : AbstractComboBoxFeatureCardControl<PowerModeStat
private readonly PowerModeListener _powerModeListener = IoCContainer.Resolve<PowerModeListener>();
private readonly PowerPlanListener _powerPlanListener = IoCContainer.Resolve<PowerPlanListener>();

private readonly ThrottleFirstDispatcher _throttleDispatcher = new(TimeSpan.FromSeconds(1), nameof(PowerModeControl));
private readonly ThrottleLastDispatcher _throttleDispatcher = new(TimeSpan.FromSeconds(1), nameof(PowerModeControl));

private readonly Button _configButton = new()
{
Expand Down
19 changes: 12 additions & 7 deletions LenovoLegionToolkit.WPF/Controls/FanCurveControl.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ public partial class FanCurveControl
private readonly InfoTooltip _customToolTip = new();

private FanTableData[]? _tableData;
private FanTable? _minimumFanTable;

public FanCurveControl()
{
Expand All @@ -39,7 +40,7 @@ protected override Size ArrangeOverride(Size arrangeBounds)
return size;
}

public void SetFanTableInfo(FanTableInfo fanTableInfo)
public void SetFanTableInfo(FanTableInfo fanTableInfo, FanTable minimumFanTable)
{
_sliders.Clear();
_slidersGrid.Children.Clear();
Expand All @@ -55,6 +56,7 @@ public void SetFanTableInfo(FanTableInfo fanTableInfo)
}

_tableData = fanTableInfo.Data;
_minimumFanTable = minimumFanTable;

Dispatcher.InvokeAsync(DrawGraph, DispatcherPriority.Render);
}
Expand Down Expand Up @@ -126,13 +128,16 @@ private void Slider_OnValueChanged(object sender, RoutedPropertyChangedEventArgs
if (currentSlider is { IsKeyboardFocusWithin: false, IsMouseCaptureWithin: false })
return;

var index = (int)currentSlider.Tag;
var minimum = FanTable.Minimum.GetTable();

if (currentSlider.Value < minimum[index])
if (_minimumFanTable.HasValue)
{
currentSlider.Value = minimum[index];
return;
var index = (int)currentSlider.Tag;
var minimum = _minimumFanTable.Value.GetTable();

if (currentSlider.Value < minimum[index])
{
currentSlider.Value = minimum[index];
return;
}
}

VerifyValues(currentSlider);
Expand Down
Loading

0 comments on commit 204a5be

Please sign in to comment.