Re: [PATCH v2] platform/x86: hp-wmi: add support for omen laptops

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

 



On Mon, Aug 23, 2021 at 04:40:08PM +0000, Barnabás Pőcze wrote:
> Hi
> 
> 
> 2021. augusztus 23., hétfő 16:15 keltezéssel, Enver Balalic írta:
> > This patch adds support for HP Omen laptops.
> > It adds support for most things that can be controlled via the
> > Windows Omen Command Center application.
> >
> >  - Fan speed monitoring through hwmon
> >  - Platform Profile support (cool, balanced, performance)
> >  - Max fan speed function toggle
> >
> > Also exposes the existing HDD temperature through hwmon since
> > this driver didn't use hwmon before this patch.
> >
> > This patch has been tested on a 2020 HP Omen 15 (AMD) 15-en0023dx.
> >
> >  - V1
> >    Initial Patch
> >  - V2
> >    Use standard hwmon ABI attributes
> >    Add existing non-standard "hddtemp" to hwmon
> >
> > Signed-off-by: Enver Balalic <balalic.enver@xxxxxxxxx>
> > ---
> >  drivers/platform/x86/Kconfig  |   1 +
> >  drivers/platform/x86/hp-wmi.c | 302 ++++++++++++++++++++++++++++++++--
> >  2 files changed, 292 insertions(+), 11 deletions(-)
> >
> > diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
> > index d12db6c316ea..f0b3d94e182b 100644
> > --- a/drivers/platform/x86/Kconfig
> > +++ b/drivers/platform/x86/Kconfig
> > @@ -431,6 +431,7 @@ config HP_WMI
> >  	tristate "HP WMI extras"
> >  	depends on ACPI_WMI
> >  	depends on INPUT
> > +	depends on HWMON
> >  	depends on RFKILL || RFKILL = n
> >  	select INPUT_SPARSEKMAP
> >  	select ACPI_PLATFORM_PROFILE
> > diff --git a/drivers/platform/x86/hp-wmi.c b/drivers/platform/x86/hp-wmi.c
> > index 027a1467d009..20cf8a32e76e 100644
> > --- a/drivers/platform/x86/hp-wmi.c
> > +++ b/drivers/platform/x86/hp-wmi.c
> > @@ -22,6 +22,7 @@
> > [...]
> >  enum hp_wmi_command {
> >  	HPWMI_READ	= 0x01,
> >  	HPWMI_WRITE	= 0x02,
> >  	HPWMI_ODM	= 0x03,
> > +	HPWMI_GM    = 0x20008,
>                 ^^^^
> The other command values are aligned using a single tab.
> 
> 
> >  };
> > [...]
> > +static int hp_wmi_get_fan_speed(int fan)
> > +{
> > +	int fsh, fsl, fan_speed;
> > +	char fan_data[4] = { fan, 0, 0, 0 };
> > +
> > +	int ret = hp_wmi_perform_query(HPWMI_FAN_SPEED_GET_QUERY, HPWMI_GM,
> > +				       &fan_data, sizeof(fan_data),
> > +				       sizeof(fan_data));
> > +
> > +	if (ret != 0)
> > +		return -EINVAL;
> > +
> > +	fsh = fan_data[2];
> > +	fsl = fan_data[3];
> > +
> > +	// sometimes one of these can be negative
> 
> If the speed is e.g. 1279 RPM, that's 0x04FF, which will be 4 and -1 if you interpret
> the bytes as a signed values on x86. Isn't this what's happening here? Or is the
> reason known?
Yes, that is what's happening. I initially had this working as a python script via
the acpi_call module first, and python didn't overflow to -1 here so I didn't think of 
that.
> 
> 
> > +	fan_speed = ((fsh > 0 ? fsh : 0) << 8) | (fsl > 0 ? fsl : 0);
> > +
> > +	return fan_speed;
> > +}
> > [...]
> > +static int omen_thermal_profile_set(int mode)
> > +{
> > +	char buffer[2] = {0, mode};
> > +	int ret;
> > +
> > +	if (mode < 0 || mode > 2)
> > +		return -EINVAL;
> > +
> > +	ret = hp_wmi_perform_query(HPWMI_SET_PERFORMANCE_MODE, HPWMI_GM,
> > +				   &buffer, sizeof(buffer), sizeof(buffer));
> > +
> > +	if (ret)
> > +		return ret < 0 ? ret : -EINVAL;
> 
> I think something like EIO would be more appropriate than EINVAL.
> (In other functions, too.)
I copied this part from the other set/get methods in this driver, they
return -EINVAL on fail here.
> 
> 
> > +
> > +	return mode;
> > +}
> > [...]
> > +static int omen_thermal_profile_get(void)
> 
> I would put this function next to `omen_thermal_profile_set`.
> 
> 
> > +{
> > +	u8 data;
> > +
> > +	int ret = ec_read(HP_OMEN_EC_THERMAL_PROFILE_OFFSET, &data);
> > +
> > +	if (ret)
> > +		return ret;
> > +
> > +	return data;
> > +}
> > [...]
> > +static int hp_wmi_hwmon_read(struct device *dev, enum hwmon_sensor_types type,
> > +			u32 attr, int channel, long *val)
> > +{
> > +	switch (type) {
> > +	case hwmon_temp:
> > +		return hp_wmi_read_int(HPWMI_HDDTEMP_QUERY);
> > +	case hwmon_fan:
> > +		int ret = hp_wmi_get_fan_speed(channel);
> > +
> > +		if (ret < 0)
> > +			return -EINVAL;
> > +		*val = ret;
> > +		return 0;
> > +	case hwmon_pwm:
> > +		return hp_wmi_fan_speed_max_get();
> 
> Shouldn't this "mapped back"? 1 -> 0, 0 -> 2?
Yes, it should.
> 
> 
> > +	default:
> > +		return -EINVAL;
> > +	};
>          ^
> This semicolon is not needed.
> 
> 
> > +}
> > +
> > +static int hp_wmi_hwmon_write(struct device *dev, enum hwmon_sensor_types type,
> > +			u32 attr, int channel, long val)
> > +{
> > +	switch (type) {
> > +	case hwmon_pwm:
> > +		switch (val) {
> > +		case 0:
> > +			// 1 is no fan speed control(automatic), which is 1 for us
>                                                    ^^
> Small thing, but I'd put a space there.
> 
> 
> > +			return hp_wmi_fan_speed_max_set(1);
> > +		case 2:
> > +			// 2 is automatic speed control, which is 0 for us
> > +			return hp_wmi_fan_speed_max_set(0);
> > +		default:
> > +			// we don't support manual fan speed control
> > +			return -EOPNOTSUPP;
> 
> /* this type of comments is preferred */
Noted, I ran this through checkpatch.pl and it didn't lint that,
thanks for the heads up.
> 
> 
> > +		}
> > +	default:
> > +		return -EOPNOTSUPP;
> > +	}
> > +}
> > [...]
> 
> 
> Best regards,
> Barnabás Pőcze

Thank you very much for the review, I'll fix these and anything else
that comes in and send out a V3.

Regards,
Enver.



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

  Powered by Linux