On Sun, Mar 9, 2025 at 4:21 AM Antheas Kapenekakis <lkml@xxxxxxxxxxx> wrote: > > The X1 and X1 mini lineups feature an LED nested within their turbo > button. When turbo takeover is not enabled, the turbo button allows > the device to switch from 18W to 25W TDP. When the device is in the > 25W TDP mode, the LED is turned on. > > However, when we engage turbo takeover, the turbo led remains on its > last state, which might be illuminated and cannot be currently > controlled. Therefore, add the register that controls it under sysfs, > to allow userspace to turn it off once engaging turbo takeover and > then control it as they wish. > > 2024 OneXPlayer devices, other than the X1s, do not have a turbo LED. > However, earlier models do, so this can be extended to them as well > when the register for it is found. > > Signed-off-by: Antheas Kapenekakis <lkml@xxxxxxxxxxx> > --- > drivers/platform/x86/oxpec.c | 84 ++++++++++++++++++++++++++++++++++++ > 1 file changed, 84 insertions(+) > > diff --git a/drivers/platform/x86/oxpec.c b/drivers/platform/x86/oxpec.c > index 9cb024325da5..eb7eafebbd37 100644 > --- a/drivers/platform/x86/oxpec.c > +++ b/drivers/platform/x86/oxpec.c > @@ -106,6 +106,12 @@ static enum oxp_board board; > #define OXP_X1_CHARGE_BYPASS_MASK_ALWAYS (OXP_X1_CHARGE_BYPASS_MASK_S0 | \ > OXP_X1_CHARGE_BYPASS_MASK_S3S5) > > +/* X1 Turbo LED */ > +#define OXP_X1_TURBO_LED_REG 0x57 > + > +#define OXP_X1_TURBO_LED_OFF 0x01 > +#define OXP_X1_TURBO_LED_ON 0x02 > + > static const struct dmi_system_id dmi_table[] = { > { > .matches = { > @@ -453,6 +459,73 @@ static ssize_t tt_toggle_show(struct device *dev, > > static DEVICE_ATTR_RW(tt_toggle); > > +/* Callbacks for turbo toggle attribute */ > +static umode_t tt_led_is_visible(struct kobject *kobj, > + struct attribute *attr, int n) > +{ > + switch (board) { > + case oxp_x1: > + return attr->mode; > + default: > + break; > + } > + return 0; > +} > + > +static ssize_t tt_led_store(struct device *dev, > + struct device_attribute *attr, const char *buf, > + size_t count) > +{ > + u8 reg, val; > + int rval; > + bool value; > + Reverse xmas tree. > + rval = kstrtobool(buf, &value); > + if (rval) > + return rval; > + > + switch (board) { > + case oxp_x1: > + reg = OXP_X1_TURBO_LED_REG; > + val = value ? OXP_X1_TURBO_LED_ON : OXP_X1_TURBO_LED_OFF; > + break; > + default: > + return -EINVAL; > + } > + rval = write_to_ec(reg, val); > + > + if (rval) > + return rval; > + > + return count; > +} > + > +static ssize_t tt_led_show(struct device *dev, > + struct device_attribute *attr, char *buf) > +{ > + int retval; > + u8 reg; > + long enval; > + long val; > + Reverse xmas tree. Cheers, - Derek > + switch (board) { > + case oxp_x1: > + reg = OXP_X1_TURBO_LED_REG; > + enval = OXP_X1_TURBO_LED_ON; > + break; > + default: > + return -EINVAL; > + } > + > + retval = read_from_ec(reg, 1, &val); > + if (retval) > + return retval; > + > + return sysfs_emit(buf, "%d\n", val == enval); > +} > + > +static DEVICE_ATTR_RW(tt_led); > + > /* Callbacks for turbo toggle attribute */ > static bool charge_behaviour_supported(void) > { > @@ -898,8 +971,19 @@ static struct attribute_group oxp_tt_toggle_attribute_group = { > .attrs = oxp_tt_toggle_attrs, > }; > > +static struct attribute *oxp_tt_led_attrs[] = { > + &dev_attr_tt_led.attr, > + NULL > +}; > + > +static struct attribute_group oxp_tt_led_attribute_group = { > + .is_visible = tt_led_is_visible, > + .attrs = oxp_tt_led_attrs, > +}; > + > static const struct attribute_group *oxp_ec_groups[] = { > &oxp_tt_toggle_attribute_group, > + &oxp_tt_led_attribute_group, > NULL > }; > > -- > 2.48.1 >