Re: [PATCH] Add IdeaPad quick_charge attribute to sysfs

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi


2022. szeptember 11., vasárnap 18:17 keltezéssel, Philipp Jungkamp írta:
> More recent IdeaPads allow USB-C quick-charging to be controlled via
> ACPI. This seems to be mutually exclusive with the ACPI conservation
> mode.
> 
> Expose a readable and writable 'quick_charge' sysfs attribute next when
> support is indicated in ACPI.
> ---
> I deduced the indicator bits from their names in the DSDT (QCHO and
> QCHX). I don't have an IdeaPad except mine on hand and can't check
> whether these are indeed the intended uses or their behaviour on other
> IdeaPads. I can confirm that a change in the quick_charge toggle is
> visible in Lenovo Vantage when dual booting into Windows 11.
> 
> Greetings,
> Philipp Jungkamp

There is already an entry for this on the kernel bugzilla:
https://bugzilla.kernel.org/show_bug.cgi?id=216176

I have two concerns: one, it adds a new driver specific attribute for a somewhat
generic functionality; two, Lenovo Vantage does not only check this single bit
before allowing this mode to be enabled (as far as I can recall).


Regards,
Barnabás Pőcze


> 
>  drivers/platform/x86/ideapad-laptop.c | 64 ++++++++++++++++++++++++++-
>  1 file changed, 62 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/platform/x86/ideapad-laptop.c b/drivers/platform/x86/ideapad-laptop.c
> index abd0c81d62c4..dea35779264a 100644
> --- a/drivers/platform/x86/ideapad-laptop.c
> +++ b/drivers/platform/x86/ideapad-laptop.c
> @@ -54,12 +54,16 @@ enum {
>  };
> 
>  enum {
> -	GBMD_CONSERVATION_STATE_BIT = 5,
> +	GBMD_QUICK_CHARGE_STATE_BIT   = 2,
> +	GBMD_CONSERVATION_STATE_BIT   = 5,
> +	GBMD_QUICK_CHARGE_SUPPORT_BIT = 17,
>  };
> 
>  enum {
>  	SBMC_CONSERVATION_ON  = 3,
>  	SBMC_CONSERVATION_OFF = 5,
> +	SBMC_QUICK_CHARGE_ON  = 7,
> +	SBMC_QUICK_CHARGE_OFF = 8,
>  };
> 
>  enum {
> @@ -140,6 +144,7 @@ struct ideapad_private {
>  		bool kbd_bl               : 1;
>  		bool touchpad_ctrl_via_ec : 1;
>  		bool usb_charging         : 1;
> +		bool quick_charge         : 1;
>  	} features;
>  	struct {
>  		bool initialized;
> @@ -482,6 +487,12 @@ static ssize_t conservation_mode_store(struct device *dev,
>  	if (err)
>  		return err;
> 
> +	if (priv->features.quick_charge && state) {
> +		err = exec_sbmc(priv->adev->handle, SBMC_QUICK_CHARGE_OFF);
> +		if (err)
> +			return err;
> +	}
> +
>  	err = exec_sbmc(priv->adev->handle, state ? SBMC_CONSERVATION_ON : SBMC_CONSERVATION_OFF);
>  	if (err)
>  		return err;
> @@ -491,6 +502,48 @@ static ssize_t conservation_mode_store(struct device *dev,
> 
>  static DEVICE_ATTR_RW(conservation_mode);
> 
> +static ssize_t quick_charge_show(struct device *dev,
> +				 struct device_attribute *attr,
> +				 char *buf)
> +{
> +	struct ideapad_private *priv = dev_get_drvdata(dev);
> +	unsigned long result;
> +	int err;
> +
> +	err = eval_gbmd(priv->adev->handle, &result);
> +	if (err)
> +		return err;
> +
> +	return sysfs_emit(buf, "%d\n", !!test_bit(GBMD_QUICK_CHARGE_STATE_BIT, &result));
> +}
> +
> +static ssize_t quick_charge_store(struct device *dev,
> +				  struct device_attribute *attr,
> +				  const char *buf, size_t count)
> +{
> +	struct ideapad_private *priv = dev_get_drvdata(dev);
> +	bool state;
> +	int err;
> +
> +	err = kstrtobool(buf, &state);
> +	if (err)
> +		return err;
> +
> +	if (priv->features.conservation_mode && state) {
> +		err = exec_sbmc(priv->adev->handle, SBMC_CONSERVATION_OFF);
> +		if (err)
> +			return err;
> +	}
> +
> +	err = exec_sbmc(priv->adev->handle, state ? SBMC_QUICK_CHARGE_ON : SBMC_QUICK_CHARGE_OFF);
> +	if (err)
> +		return err;
> +
> +	return count;
> +}
> +
> +static DEVICE_ATTR_RW(quick_charge);
> +
>  static ssize_t fan_mode_show(struct device *dev,
>  			     struct device_attribute *attr,
>  			     char *buf)
> @@ -641,6 +694,7 @@ static DEVICE_ATTR_RW(usb_charging);
>  static struct attribute *ideapad_attributes[] = {
>  	&dev_attr_camera_power.attr,
>  	&dev_attr_conservation_mode.attr,
> +	&dev_attr_quick_charge.attr,
>  	&dev_attr_fan_mode.attr,
>  	&dev_attr_fn_lock.attr,
>  	&dev_attr_touchpad.attr,
> @@ -660,6 +714,8 @@ static umode_t ideapad_is_visible(struct kobject *kobj,
>  		supported = test_bit(CFG_CAP_CAM_BIT, &priv->cfg);
>  	else if (attr == &dev_attr_conservation_mode.attr)
>  		supported = priv->features.conservation_mode;
> +	else if (attr == &dev_attr_quick_charge.attr)
> +		supported = priv->features.quick_charge;
>  	else if (attr == &dev_attr_fan_mode.attr)
>  		supported = priv->features.fan_mode;
>  	else if (attr == &dev_attr_fn_lock.attr)
> @@ -1546,9 +1602,13 @@ static void ideapad_check_features(struct ideapad_private *priv)
>  	if (!read_ec_data(handle, VPCCMD_R_FAN, &val))
>  		priv->features.fan_mode = true;
> 
> -	if (acpi_has_method(handle, "GBMD") && acpi_has_method(handle, "SBMC"))
> +	if (acpi_has_method(handle, "GBMD") && acpi_has_method(handle, "SBMC")) {
>  		priv->features.conservation_mode = true;
> 
> +		if (!eval_gbmd(handle,&val) && test_bit(GBMD_QUICK_CHARGE_SUPPORT_BIT, &val))
> +			priv->features.quick_charge = true;
> +	}
> +
>  	if (acpi_has_method(handle, "DYTC"))
>  		priv->features.dytc = true;
> 
> --
> 2.37.3
> 




[Index of Archives]     [Linux Kernel Development]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux