[PATCH 2/2] platorm/x86: thinkpad_acpi: sysfs interface to interface to get wwan antenna type

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

 



On some newer Thinkpads we need to set SAR value based on antenna type.
This patch provides a sysfs interface that userspace can use to get
antenna type and set corresponding SAR value, as is required for FCC
certification.

Reviewed-by: Mark Pearson <markpearson@xxxxxxxxxx>
Signed-off-by: Nitin Joshi <njoshi1@xxxxxxxxxx>
---
 .../admin-guide/laptops/thinkpad-acpi.rst     | 21 +++++++
 drivers/platform/x86/thinkpad_acpi.c          | 55 ++++++++++++++++++-
 2 files changed, 74 insertions(+), 2 deletions(-)

diff --git a/Documentation/admin-guide/laptops/thinkpad-acpi.rst b/Documentation/admin-guide/laptops/thinkpad-acpi.rst
index 10410811b990..df6904f23dea 100644
--- a/Documentation/admin-guide/laptops/thinkpad-acpi.rst
+++ b/Documentation/admin-guide/laptops/thinkpad-acpi.rst
@@ -52,6 +52,7 @@ detailed description):
 	- LCD Shadow (PrivacyGuard) enable and disable
 	- Lap mode sensor
 	- WLAN transmission power control
+	- WWAN Antenna type
 
 A compatibility table by model and feature is maintained on the web
 site, http://ibm-acpi.sf.net/. I appreciate any success or failure
@@ -1465,6 +1466,26 @@ The available commands are::
 The first command restores the wlan transmission power and the latter one
 reduces wlan transmission power.
 
+WWAN Antenna type
+-----------------
+
+sysfs: wwan_antenna_type
+
+On some newer Thinkpads we need to set SAR value based on the antenna
+type. This interface will be used by userspace to get the antenna type
+and set the corresponding SAR value, as is required for FCC certification.
+
+The available commands are::
+
+        cat /sys/devices/platform/thinkpad_acpi/wwan_antenna_type
+
+Currently 2 antenna types are supported as mentioned below:
+- type a
+- type b
+
+The property is read-only. If the platform doesn't have support the sysfs
+class is not created.
+
 EXPERIMENTAL: UWB
 -----------------
 
diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c
index 6dbbd4a14264..db016a2a1837 100644
--- a/drivers/platform/x86/thinkpad_acpi.c
+++ b/drivers/platform/x86/thinkpad_acpi.c
@@ -9990,8 +9990,11 @@ static struct ibm_struct proxsensor_driver_data = {
 #define DPRC_GET_WLAN_STATE             0x20000
 #define DPRC_SET_WLAN_POWER_REDUCE      0x00030010
 #define DPRC_SET_WLAN_POWER_FULL        0x00030100
+#define DPRC_GET_WWAN_ANTENNA_TYPE      0x40000
 static int has_wlantxreduce;
 static int wlan_txreduce;
+static int has_antennatype;
+static int wwan_antennatype;
 
 static int dprc_command(int command, int *output)
 {
@@ -10035,6 +10038,26 @@ static int get_wlan_state(int *has_wlantxreduce, int *wlan_txreduce)
 	return 0;
 }
 
+static int get_wwan_antenna(int *has_antennatype, int *wwan_antennatype)
+{
+	int output, err;
+
+	/* Get current Antenna type */
+	err = dprc_command(DPRC_GET_WWAN_ANTENNA_TYPE, &output);
+	if (err)
+		return err;
+
+	if (output & BIT(4))
+		*wwan_antennatype = 1;
+	else if (output & BIT(8))
+		*wwan_antennatype = 2;
+	else
+		*wwan_antennatype = -1;
+
+	*has_antennatype = 1;
+	return 0;
+}
+
 /* sysfs wlan entry */
 static ssize_t wlan_tx_strength_reduce_show(struct device *dev,
 				struct device_attribute *attr,
@@ -10049,6 +10072,21 @@ static ssize_t wlan_tx_strength_reduce_show(struct device *dev,
 	return sysfs_emit(buf, "%d\n", wlan_txreduce);
 }
 
+/* sysfs wwan antenna type entry */
+static ssize_t wwan_antenna_type_show(struct device *dev,
+				struct device_attribute *attr,
+				char *buf)
+{
+	switch (wwan_antennatype) {
+	case 1:
+		return sysfs_emit(buf, "type a\n");
+	case 2:
+		return sysfs_emit(buf, "type b\n");
+	default:
+		return sysfs_emit(buf, "unknown type\n");
+	}
+}
+
 static ssize_t wlan_tx_strength_reduce_store(struct device *dev,
 				struct device_attribute *attr,
 				const char *buf, size_t count)
@@ -10076,24 +10114,29 @@ static ssize_t wlan_tx_strength_reduce_store(struct device *dev,
 	}
 
 	sysfs_notify(&tpacpi_pdev->dev.kobj, NULL, "wlan_tx_strength_reduce");
+
 	return count;
 }
 static DEVICE_ATTR_RW(wlan_tx_strength_reduce);
+static DEVICE_ATTR_RO(wwan_antenna_type);
 
 static int tpacpi_dprc_init(struct ibm_init_struct *iibm)
 {
-	int wlantx_err, err;
+	int wlantx_err, wwanantenna_err, err;
 
 	wlantx_err = get_wlan_state(&has_wlantxreduce, &wlan_txreduce);
+	wwanantenna_err = get_wwan_antenna(&has_antennatype, &wwan_antennatype);
 	/*
 	 * If support isn't available (ENODEV) for both devices then quit, but
 	 * don't return an error.
 	 */
-	if (wlantx_err == -ENODEV)
+	if ((wlantx_err == -ENODEV) && (wwanantenna_err == -ENODEV))
 		return 0;
 	/* Otherwise, if there was an error return it */
 	if (wlantx_err && (wlantx_err != -ENODEV))
 		return wlantx_err;
+	if (wwanantenna_err && (wwanantenna_err != -ENODEV))
+		return wwanantenna_err;
 
 	if (has_wlantxreduce) {
 		err = sysfs_create_file(&tpacpi_pdev->dev.kobj,
@@ -10101,6 +10144,12 @@ static int tpacpi_dprc_init(struct ibm_init_struct *iibm)
 		if (err)
 			return err;
 	}
+
+	if (has_antennatype) {
+		err = sysfs_create_file(&tpacpi_pdev->dev.kobj, &dev_attr_wwan_antenna_type.attr);
+		if (err)
+			return err;
+	}
 	return 0;
 }
 
@@ -10108,6 +10157,8 @@ static void dprc_exit(void)
 {
 	if (has_wlantxreduce)
 		sysfs_remove_file(&tpacpi_pdev->dev.kobj, &dev_attr_wlan_tx_strength_reduce.attr);
+	if (has_antennatype)
+		sysfs_remove_file(&tpacpi_pdev->dev.kobj, &dev_attr_wwan_antenna_type.attr);
 }
 
 static struct ibm_struct dprc_driver_data = {
-- 
2.25.1




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

  Powered by Linux