lenovo-dytc: Implement perfmode

Implement dytc_perfmode, as per https://patchwork.kernel.org/patch/11678983/
This commit is contained in:
Bastien Nocera 2020-08-06 15:47:39 +02:00
parent 953eb716fd
commit ebf9e5b7c8
2 changed files with 64 additions and 3 deletions

View file

@ -8,10 +8,13 @@
*/
#include <gudev/gudev.h>
#include <gio/gio.h>
#include "ppd-driver-lenovo-dytc.h"
#include "ppd-utils.h"
#define LAPMODE_SYSFS_NAME "dytc_lapmode"
#define PERFMODE_SYSFS_NAME "dytc_perfmode"
struct _PpdDriverLenovoDytc
{
@ -57,12 +60,26 @@ sysfs_attr_as_boolean (GUdevDevice *device,
return (g_strcmp0 (contents, "1") == 0);
}
static const char *
profile_to_perfmode_value (PpdProfile profile)
{
switch (profile) {
case PPD_PROFILE_POWER_SAVER:
return "L";
case PPD_PROFILE_BALANCED:
return "M";
case PPD_PROFILE_PERFORMANCE:
return "H";
}
g_assert_not_reached ();
}
static void
update_dytc_state (PpdDriverLenovoDytc *dytc)
{
gboolean new_lapmode;
new_lapmode = sysfs_attr_as_boolean (dytc->device, LAPMODE_SYSFS_NAME);
if (new_lapmode != dytc->lapmode) {
dytc->lapmode = new_lapmode;
@ -93,6 +110,31 @@ uevent_cb (GUdevClient *client,
update_dytc_state (dytc);
}
static gboolean
ppd_driver_lenovo_dytc_activate_profile (PpdDriver *driver,
PpdProfile profile,
GError **error)
{
PpdDriverLenovoDytc *dytc = PPD_DRIVER_LENOVO_DYTC (driver);
g_return_val_if_fail (dytc->client, FALSE);
if (profile == PPD_PROFILE_PERFORMANCE &&
dytc->lapmode) {
g_debug ("Can't switch to performance mode, lapmode is detected");
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "Mode is inhibited");
return FALSE;
}
if (!ppd_utils_write_sysfs (dytc->device, PERFMODE_SYSFS_NAME, profile_to_perfmode_value (profile), error)) {
g_debug ("Failed to write to perfmode: %s", (* error)->message);
return FALSE;
}
g_debug ("Successfully switched to profile %s", ppd_profile_to_str (profile));
return TRUE;
}
static gboolean
ppd_driver_lenovo_dytc_probe (PpdDriver *driver)
{
@ -114,7 +156,8 @@ ppd_driver_lenovo_dytc_probe (PpdDriver *driver)
if (g_strcmp0 (g_udev_device_get_name (dev), "thinkpad_acpi") != 0)
continue;
if (!g_udev_device_get_sysfs_attr (dev, LAPMODE_SYSFS_NAME))
if (!g_udev_device_get_sysfs_attr (dev, LAPMODE_SYSFS_NAME) ||
!g_udev_device_get_sysfs_attr (dev, PERFMODE_SYSFS_NAME))
break;
dytc->device = g_object_ref (dev);
@ -159,6 +202,7 @@ ppd_driver_lenovo_dytc_class_init (PpdDriverLenovoDytcClass *klass)
driver_class = PPD_DRIVER_CLASS(klass);
driver_class->probe = ppd_driver_lenovo_dytc_probe;
driver_class->activate_profile = ppd_driver_lenovo_dytc_activate_profile;
}
static void

View file

@ -386,7 +386,7 @@ class Tests(dbusmock.DBusTestCase):
'''Lenovo DYTC performance driver'''
tp_acpi = self.testbed.add_device('platform', 'thinkpad_acpi', None,
['dytc_lapmode', '0'],
['dytc_lapmode', '0', 'dytc_perfmode', 'H'],
[ 'DEVPATH', '/devices/platform/thinkpad_acpi' ]
)
@ -400,6 +400,9 @@ class Tests(dbusmock.DBusTestCase):
self.assertEqual(profiles[2]['Profile'], 'performance')
self.assertEqual(self.get_dbus_property('ActiveProfile'), 'balanced')
# Verify that perfmode got reset
self.assertEventually(lambda: self.read_sysfs_attr(tp_acpi, 'dytc_perfmode') == b'M')
# lapmode detected, but performance wasn't selected anyway
self.testbed.set_attribute(tp_acpi, 'dytc_lapmode', '1')
self.testbed.uevent(tp_acpi, 'change')
@ -416,15 +419,29 @@ class Tests(dbusmock.DBusTestCase):
# Set performance mode
self.set_dbus_property('ActiveProfile', GLib.Variant.new_string('performance'))
self.assertEqual(self.get_dbus_property('ActiveProfile'), 'performance')
self.assertEventually(lambda: self.read_sysfs_attr(tp_acpi, 'dytc_perfmode') == b'H')
# And turn on lapmode
self.testbed.set_attribute(tp_acpi, 'dytc_lapmode', '1')
self.testbed.uevent(tp_acpi, 'change')
self.assertEventually(lambda: self.have_text_in_log('dytc_lapmode is now on'))
self.assertEventually(lambda: self.read_sysfs_attr(tp_acpi, 'dytc_perfmode') == b'M')
self.assertEqual(self.get_dbus_property('ActiveProfile'), 'balanced')
self.assertEqual(self.get_dbus_property('PerformanceInhibited'), 'lap-detected')
# Turn off lapmode, profile stays balanced
self.testbed.set_attribute(tp_acpi, 'dytc_lapmode', '0')
self.testbed.uevent(tp_acpi, 'change')
self.assertEventually(lambda: self.have_text_in_log('dytc_lapmode is now off'))
self.assertEventually(lambda: self.read_sysfs_attr(tp_acpi, 'dytc_perfmode') == b'M')
# Switch to power-saver mode
self.set_dbus_property('ActiveProfile', GLib.Variant.new_string('power-saver'))
self.assertEqual(self.get_dbus_property('ActiveProfile'), 'power-saver')
self.assertEqual(self.get_dbus_property('PerformanceInhibited'), '')
self.assertEventually(lambda: self.read_sysfs_attr(tp_acpi, 'dytc_perfmode') == b'L')
def test_fake_driver(self):
'''Test that the fake driver works'''