[PATCH 1/2] platform/x86: thinkpad_acpi: Add palm sensor support

Alex Hung alex.hung at canonical.com
Sat Jan 16 02:59:38 UTC 2021


NACK.Will re-send with updated subjects

On 2021-01-15 6:43 p.m., Alex Hung wrote:
> From: Mark Pearson <markpearson at lenovo.com>
> 
> BugLink: https://bugs.launchpad.net/bugs/1912033
> 
> Add support to thinkpad_acpi for returning the status of the palm
> sensor.
> 
> This patch builds on the work done previously for the input device
> implementation (which was not needed). Both lap and palm sensor are using
> sysfs and they are combined into the proxsensor block.
> 
> Note: On some platforms, because of an issue in the HW implementation,
> the palm sensor presence may be incorrectly advertised as always
> enabled even if a palm sensor is not present. The palm sensor is
> intended for WWAN transmission power control and should be available
> and correct on all WWAN enabled systems. It is not recommended to use
> this interface for other use cases.
> 
> Signed-off-by: Mark Pearson <markpearson at lenovo.com>
> Link: https://lore.kernel.org/r/20201124181154.547518-1-markpearson@lenovo.com
> Signed-off-by: Hans de Goede <hdegoede at redhat.com>
> (cherry picked from commit 1ac09656bded6e4ea9312631579dd32189e00e62)
> Signed-off-by: Alex Hung <alex.hung at canonical.com>
> ---
>  drivers/platform/x86/thinkpad_acpi.c | 162 +++++++++++++++++----------
>  1 file changed, 103 insertions(+), 59 deletions(-)
> 
> diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c
> index c404706379d9..26b1502f9bbe 100644
> --- a/drivers/platform/x86/thinkpad_acpi.c
> +++ b/drivers/platform/x86/thinkpad_acpi.c
> @@ -4028,6 +4028,7 @@ static bool hotkey_notify_usrevent(const u32 hkey,
>  }
>  
>  static void thermal_dump_all_sensors(void);
> +static void palmsensor_refresh(void);
>  
>  static bool hotkey_notify_6xxx(const u32 hkey,
>  				 bool *send_acpi_ev,
> @@ -4094,8 +4095,8 @@ static bool hotkey_notify_6xxx(const u32 hkey,
>  
>  	case TP_HKEY_EV_PALM_DETECTED:
>  	case TP_HKEY_EV_PALM_UNDETECTED:
> -		/* palm detected hovering the keyboard, forward to user-space
> -		 * via netlink for consumption */
> +		/* palm detected  - pass on to event handler */
> +		palmsensor_refresh();
>  		return true;
>  
>  	default:
> @@ -9839,102 +9840,146 @@ static struct ibm_struct lcdshadow_driver_data = {
>  };
>  
>  /*************************************************************************
> - * DYTC subdriver, for the Lenovo lapmode feature
> + * Thinkpad sensor interfaces
>   */
>  
>  #define DYTC_CMD_GET          2 /* To get current IC function and mode */
>  #define DYTC_GET_LAPMODE_BIT 17 /* Set when in lapmode */
>  
> -static bool dytc_lapmode;
> +#define PALMSENSOR_PRESENT_BIT 0 /* Determine if psensor present */
> +#define PALMSENSOR_ON_BIT      1 /* psensor status */
>  
> -static void dytc_lapmode_notify_change(void)
> -{
> -	sysfs_notify(&tpacpi_pdev->dev.kobj, NULL, "dytc_lapmode");
> -}
> +static bool has_palmsensor;
> +static bool has_lapsensor;
> +static bool palm_state;
> +static bool lap_state;
>  
> -static int dytc_command(int command, int *output)
> +static int lapsensor_get(bool *present, bool *state)
>  {
>  	acpi_handle dytc_handle;
> +	int output;
>  
> -	if (ACPI_FAILURE(acpi_get_handle(hkey_handle, "DYTC", &dytc_handle))) {
> -		/* Platform doesn't support DYTC */
> +	*present = false;
> +	if (ACPI_FAILURE(acpi_get_handle(hkey_handle, "DYTC", &dytc_handle)))
>  		return -ENODEV;
> -	}
> -	if (!acpi_evalf(dytc_handle, output, NULL, "dd", command))
> +	if (!acpi_evalf(dytc_handle, &output, NULL, "dd", DYTC_CMD_GET))
>  		return -EIO;
> +
> +	*present = true; /*If we get his far, we have lapmode support*/
> +	*state = output & BIT(DYTC_GET_LAPMODE_BIT) ? true : false;
>  	return 0;
>  }
>  
> -static int dytc_lapmode_get(bool *state)
> +static int palmsensor_get(bool *present, bool *state)
>  {
> -	int output, err;
> +	acpi_handle psensor_handle;
> +	int output;
>  
> -	err = dytc_command(DYTC_CMD_GET, &output);
> -	if (err)
> -		return err;
> -	*state = output & BIT(DYTC_GET_LAPMODE_BIT) ? true : false;
> +	*present = false;
> +	if (ACPI_FAILURE(acpi_get_handle(hkey_handle, "GPSS", &psensor_handle)))
> +		return -ENODEV;
> +	if (!acpi_evalf(psensor_handle, &output, NULL, "d"))
> +		return -EIO;
> +
> +	*present = output & BIT(PALMSENSOR_PRESENT_BIT) ? true : false;
> +	*state = output & BIT(PALMSENSOR_ON_BIT) ? true : false;
>  	return 0;
>  }
>  
> -static void dytc_lapmode_refresh(void)
> +static void lapsensor_refresh(void)
>  {
> -	bool new_state;
> +	bool state;
>  	int err;
>  
> -	err = dytc_lapmode_get(&new_state);
> -	if (err || (new_state == dytc_lapmode))
> -		return;
> +	if (has_lapsensor) {
> +		err = lapsensor_get(&has_lapsensor, &state);
> +		if (err)
> +			return;
> +		if (lap_state != state) {
> +			lap_state = state;
> +			sysfs_notify(&tpacpi_pdev->dev.kobj, NULL, "dytc_lapmode");
> +		}
> +	}
> +}
>  
> -	dytc_lapmode = new_state;
> -	dytc_lapmode_notify_change();
> +static void palmsensor_refresh(void)
> +{
> +	bool state;
> +	int err;
> +
> +	if (has_palmsensor) {
> +		err = palmsensor_get(&has_palmsensor, &state);
> +		if (err)
> +			return;
> +		if (palm_state != state) {
> +			palm_state = state;
> +			sysfs_notify(&tpacpi_pdev->dev.kobj, NULL, "palmsensor");
> +		}
> +	}
>  }
>  
> -/* sysfs lapmode entry */
>  static ssize_t dytc_lapmode_show(struct device *dev,
>  					struct device_attribute *attr,
>  					char *buf)
>  {
> -	return snprintf(buf, PAGE_SIZE, "%d\n", dytc_lapmode);
> +	if (has_lapsensor)
> +		return sysfs_emit(buf, "%d\n", lap_state);
> +	return sysfs_emit(buf, "\n");
>  }
> -
>  static DEVICE_ATTR_RO(dytc_lapmode);
>  
> -static struct attribute *dytc_attributes[] = {
> -	&dev_attr_dytc_lapmode.attr,
> -	NULL,
> -};
> -
> -static const struct attribute_group dytc_attr_group = {
> -	.attrs = dytc_attributes,
> -};
> +static ssize_t palmsensor_show(struct device *dev,
> +					struct device_attribute *attr,
> +					char *buf)
> +{
> +	if (has_palmsensor)
> +		return sysfs_emit(buf, "%d\n", palm_state);
> +	return sysfs_emit(buf, "\n");
> +}
> +static DEVICE_ATTR_RO(palmsensor);
>  
> -static int tpacpi_dytc_init(struct ibm_init_struct *iibm)
> +static int tpacpi_proxsensor_init(struct ibm_init_struct *iibm)
>  {
> -	int err;
> +	int palm_err, lap_err, err;
>  
> -	err = dytc_lapmode_get(&dytc_lapmode);
> -	/* If support isn't available (ENODEV) then don't return an error
> -	 * but just don't create the sysfs group
> +	palm_err = palmsensor_get(&has_palmsensor, &palm_state);
> +	lap_err = lapsensor_get(&has_lapsensor, &lap_state);
> +	/*
> +	 * If support isn't available (ENODEV) for both devices then quit, but
> +	 * don't return an error.
>  	 */
> -	if (err == -ENODEV)
> +	if ((palm_err == -ENODEV) && (lap_err == -ENODEV))
>  		return 0;
> -	/* For all other errors we can flag the failure */
> -	if (err)
> -		return err;
> -
> -	/* Platform supports this feature - create the group */
> -	err = sysfs_create_group(&tpacpi_pdev->dev.kobj, &dytc_attr_group);
> -	return err;
> +	/* Otherwise, if there was an error return it */
> +	if (palm_err && (palm_err != ENODEV))
> +		return palm_err;
> +	if (lap_err && (lap_err != ENODEV))
> +		return lap_err;
> +
> +	if (has_palmsensor) {
> +		err = sysfs_create_file(&tpacpi_pdev->dev.kobj, &dev_attr_palmsensor.attr);
> +		if (err)
> +			return err;
> +	}
> +	if (has_lapsensor) {
> +		err = sysfs_create_file(&tpacpi_pdev->dev.kobj, &dev_attr_dytc_lapmode.attr);
> +		if (err)
> +			return err;
> +	}
> +	return 0;
>  }
>  
> -static void dytc_exit(void)
> +static void proxsensor_exit(void)
>  {
> -	sysfs_remove_group(&tpacpi_pdev->dev.kobj, &dytc_attr_group);
> +	if (has_lapsensor)
> +		sysfs_remove_file(&tpacpi_pdev->dev.kobj, &dev_attr_dytc_lapmode.attr);
> +	if (has_palmsensor)
> +		sysfs_remove_file(&tpacpi_pdev->dev.kobj, &dev_attr_palmsensor.attr);
>  }
>  
> -static struct ibm_struct dytc_driver_data = {
> -	.name = "dytc",
> -	.exit = dytc_exit,
> +static struct ibm_struct proxsensor_driver_data = {
> +	.name = "proximity-sensor",
> +	.exit = proxsensor_exit,
>  };
>  
>  /****************************************************************************
> @@ -9986,8 +10031,7 @@ static void tpacpi_driver_event(const unsigned int hkey_event)
>  	}
>  
>  	if (hkey_event == TP_HKEY_EV_THM_CSM_COMPLETED)
> -		dytc_lapmode_refresh();
> -
> +		lapsensor_refresh();
>  }
>  
>  static void hotkey_driver_event(const unsigned int scancode)
> @@ -10427,8 +10471,8 @@ static struct ibm_init_struct ibms_init[] __initdata = {
>  		.data = &lcdshadow_driver_data,
>  	},
>  	{
> -		.init = tpacpi_dytc_init,
> -		.data = &dytc_driver_data,
> +		.init = tpacpi_proxsensor_init,
> +		.data = &proxsensor_driver_data,
>  	},
>  };
>  
> 


-- 
Cheers,
Alex Hung



More information about the kernel-team mailing list