aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/platform
diff options
context:
space:
mode:
authorAzael Avalos <coproscefalo@gmail.com>2015-01-18 20:30:23 -0500
committerDarren Hart <dvhart@linux.intel.com>2015-01-23 12:08:25 -0500
commit182bcaa5c90a66429fcf00a6a02a7bf845bf27c5 (patch)
tree149bacd08bdb5297c62cccd5c51583b75e3ac081 /drivers/platform
parente26ffe5124189bce99235fee403a71b719e10b6a (diff)
toshiba_acpi: Add support for USB Sleep functions under battery
Toshiba laptops supporting USB Sleep and Charge also come with a feature called "USB functions under battery", which what it does when enabled, is allows the USB Sleep functions when the computer is under battery power. This patch adds support to that function, creating a sysfs entry named "sleep_functions_on_battery", accepting values from 0-100, where zero disables the function and 1-100 sets the battery level at which point the USB Sleep functions will be disabled, and printing the current state of the functon and also the battery level currently set. Signed-off-by: Azael Avalos <coproscefalo@gmail.com> Signed-off-by: Darren Hart <dvhart@linux.intel.com>
Diffstat (limited to 'drivers/platform')
-rw-r--r--drivers/platform/x86/toshiba_acpi.c133
1 files changed, 133 insertions, 0 deletions
diff --git a/drivers/platform/x86/toshiba_acpi.c b/drivers/platform/x86/toshiba_acpi.c
index 6c3e25c65b70..a8b719f481f9 100644
--- a/drivers/platform/x86/toshiba_acpi.c
+++ b/drivers/platform/x86/toshiba_acpi.c
@@ -151,6 +151,10 @@ MODULE_LICENSE("GPL");
151#define SCI_USB_CHARGE_DISABLED 0x30000 151#define SCI_USB_CHARGE_DISABLED 0x30000
152#define SCI_USB_CHARGE_ALTERNATE 0x30009 152#define SCI_USB_CHARGE_ALTERNATE 0x30009
153#define SCI_USB_CHARGE_AUTO 0x30021 153#define SCI_USB_CHARGE_AUTO 0x30021
154#define SCI_USB_CHARGE_BAT_MASK 0x7
155#define SCI_USB_CHARGE_BAT_LVL_OFF 0x1
156#define SCI_USB_CHARGE_BAT_LVL_ON 0x4
157#define SCI_USB_CHARGE_BAT_LVL 0x0200
154 158
155struct toshiba_acpi_dev { 159struct toshiba_acpi_dev {
156 struct acpi_device *acpi_dev; 160 struct acpi_device *acpi_dev;
@@ -169,6 +173,7 @@ struct toshiba_acpi_dev {
169 int kbd_type; 173 int kbd_type;
170 int kbd_mode; 174 int kbd_mode;
171 int kbd_time; 175 int kbd_time;
176 int usbsc_bat_level;
172 177
173 unsigned int illumination_supported:1; 178 unsigned int illumination_supported:1;
174 unsigned int video_supported:1; 179 unsigned int video_supported:1;
@@ -813,6 +818,61 @@ static int toshiba_usb_sleep_charge_set(struct toshiba_acpi_dev *dev,
813 return 0; 818 return 0;
814} 819}
815 820
821static int toshiba_sleep_functions_status_get(struct toshiba_acpi_dev *dev,
822 u32 *mode)
823{
824 u32 in[TCI_WORDS] = { SCI_GET, SCI_USB_SLEEP_CHARGE, 0, 0, 0, 0 };
825 u32 out[TCI_WORDS];
826 acpi_status status;
827
828 if (!sci_open(dev))
829 return -EIO;
830
831 in[5] = SCI_USB_CHARGE_BAT_LVL;
832 status = tci_raw(dev, in, out);
833 sci_close(dev);
834 if (ACPI_FAILURE(status) || out[0] == TOS_FAILURE) {
835 pr_err("ACPI call to get USB S&C battery level failed\n");
836 return -EIO;
837 } else if (out[0] == TOS_NOT_SUPPORTED) {
838 pr_info("USB Sleep and Charge not supported\n");
839 return -ENODEV;
840 } else if (out[0] == TOS_INPUT_DATA_ERROR) {
841 return -EIO;
842 }
843
844 *mode = out[2];
845
846 return 0;
847}
848
849static int toshiba_sleep_functions_status_set(struct toshiba_acpi_dev *dev,
850 u32 mode)
851{
852 u32 in[TCI_WORDS] = { SCI_SET, SCI_USB_SLEEP_CHARGE, 0, 0, 0, 0 };
853 u32 out[TCI_WORDS];
854 acpi_status status;
855
856 if (!sci_open(dev))
857 return -EIO;
858
859 in[2] = mode;
860 in[5] = SCI_USB_CHARGE_BAT_LVL;
861 status = tci_raw(dev, in, out);
862 sci_close(dev);
863 if (ACPI_FAILURE(status) || out[0] == TOS_FAILURE) {
864 pr_err("ACPI call to set USB S&C battery level failed\n");
865 return -EIO;
866 } else if (out[0] == TOS_NOT_SUPPORTED) {
867 pr_info("USB Sleep and Charge not supported\n");
868 return -ENODEV;
869 } else if (out[0] == TOS_INPUT_DATA_ERROR) {
870 return -EIO;
871 }
872
873 return 0;
874}
875
816/* Bluetooth rfkill handlers */ 876/* Bluetooth rfkill handlers */
817 877
818static u32 hci_get_bt_present(struct toshiba_acpi_dev *dev, bool *present) 878static u32 hci_get_bt_present(struct toshiba_acpi_dev *dev, bool *present)
@@ -1372,6 +1432,12 @@ static ssize_t toshiba_usb_sleep_charge_show(struct device *dev,
1372static ssize_t toshiba_usb_sleep_charge_store(struct device *dev, 1432static ssize_t toshiba_usb_sleep_charge_store(struct device *dev,
1373 struct device_attribute *attr, 1433 struct device_attribute *attr,
1374 const char *buf, size_t count); 1434 const char *buf, size_t count);
1435static ssize_t sleep_functions_on_battery_show(struct device *dev,
1436 struct device_attribute *attr,
1437 char *buf);
1438static ssize_t sleep_functions_on_battery_store(struct device *dev,
1439 struct device_attribute *attr,
1440 const char *buf, size_t count);
1375 1441
1376static DEVICE_ATTR(kbd_backlight_mode, S_IRUGO | S_IWUSR, 1442static DEVICE_ATTR(kbd_backlight_mode, S_IRUGO | S_IWUSR,
1377 toshiba_kbd_bl_mode_show, toshiba_kbd_bl_mode_store); 1443 toshiba_kbd_bl_mode_show, toshiba_kbd_bl_mode_store);
@@ -1386,6 +1452,9 @@ static DEVICE_ATTR(position, S_IRUGO, toshiba_position_show, NULL);
1386static DEVICE_ATTR(usb_sleep_charge, S_IRUGO | S_IWUSR, 1452static DEVICE_ATTR(usb_sleep_charge, S_IRUGO | S_IWUSR,
1387 toshiba_usb_sleep_charge_show, 1453 toshiba_usb_sleep_charge_show,
1388 toshiba_usb_sleep_charge_store); 1454 toshiba_usb_sleep_charge_store);
1455static DEVICE_ATTR(sleep_functions_on_battery, S_IRUGO | S_IWUSR,
1456 sleep_functions_on_battery_show,
1457 sleep_functions_on_battery_store);
1389 1458
1390static struct attribute *toshiba_attributes[] = { 1459static struct attribute *toshiba_attributes[] = {
1391 &dev_attr_kbd_backlight_mode.attr, 1460 &dev_attr_kbd_backlight_mode.attr,
@@ -1395,6 +1464,7 @@ static struct attribute *toshiba_attributes[] = {
1395 &dev_attr_touchpad.attr, 1464 &dev_attr_touchpad.attr,
1396 &dev_attr_position.attr, 1465 &dev_attr_position.attr,
1397 &dev_attr_usb_sleep_charge.attr, 1466 &dev_attr_usb_sleep_charge.attr,
1467 &dev_attr_sleep_functions_on_battery.attr,
1398 NULL, 1468 NULL,
1399}; 1469};
1400 1470
@@ -1662,6 +1732,67 @@ static ssize_t toshiba_usb_sleep_charge_store(struct device *dev,
1662 return count; 1732 return count;
1663} 1733}
1664 1734
1735static ssize_t sleep_functions_on_battery_show(struct device *dev,
1736 struct device_attribute *attr,
1737 char *buf)
1738{
1739 struct toshiba_acpi_dev *toshiba = dev_get_drvdata(dev);
1740 u32 state;
1741 int bat_lvl;
1742 int status;
1743 int ret;
1744 int tmp;
1745
1746 ret = toshiba_sleep_functions_status_get(toshiba, &state);
1747 if (ret < 0)
1748 return ret;
1749
1750 /* Determine the status: 0x4 - Enabled | 0x1 - Disabled */
1751 tmp = state & SCI_USB_CHARGE_BAT_MASK;
1752 status = (tmp == 0x4) ? 1 : 0;
1753 /* Determine the battery level set */
1754 bat_lvl = state >> HCI_MISC_SHIFT;
1755
1756 return sprintf(buf, "%d %d\n", status, bat_lvl);
1757}
1758
1759static ssize_t sleep_functions_on_battery_store(struct device *dev,
1760 struct device_attribute *attr,
1761 const char *buf, size_t count)
1762{
1763 struct toshiba_acpi_dev *toshiba = dev_get_drvdata(dev);
1764 u32 status;
1765 int value;
1766 int ret;
1767 int tmp;
1768
1769 ret = kstrtoint(buf, 0, &value);
1770 if (ret)
1771 return ret;
1772
1773 /* Set the status of the function:
1774 * 0 - Disabled
1775 * 1-100 - Enabled
1776 */
1777 if (value < 0 || value > 100)
1778 return -EINVAL;
1779
1780 if (value == 0) {
1781 tmp = toshiba->usbsc_bat_level << HCI_MISC_SHIFT;
1782 status = tmp | SCI_USB_CHARGE_BAT_LVL_OFF;
1783 } else {
1784 tmp = value << HCI_MISC_SHIFT;
1785 status = tmp | SCI_USB_CHARGE_BAT_LVL_ON;
1786 }
1787 ret = toshiba_sleep_functions_status_set(toshiba, status);
1788 if (ret < 0)
1789 return ret;
1790
1791 toshiba->usbsc_bat_level = status >> HCI_MISC_SHIFT;
1792
1793 return count;
1794}
1795
1665static umode_t toshiba_sysfs_is_visible(struct kobject *kobj, 1796static umode_t toshiba_sysfs_is_visible(struct kobject *kobj,
1666 struct attribute *attr, int idx) 1797 struct attribute *attr, int idx)
1667{ 1798{
@@ -1679,6 +1810,8 @@ static umode_t toshiba_sysfs_is_visible(struct kobject *kobj,
1679 exists = (drv->accelerometer_supported) ? true : false; 1810 exists = (drv->accelerometer_supported) ? true : false;
1680 else if (attr == &dev_attr_usb_sleep_charge.attr) 1811 else if (attr == &dev_attr_usb_sleep_charge.attr)
1681 exists = (drv->usb_sleep_charge_supported) ? true : false; 1812 exists = (drv->usb_sleep_charge_supported) ? true : false;
1813 else if (attr == &dev_attr_sleep_functions_on_battery.attr)
1814 exists = (drv->usb_sleep_charge_supported) ? true : false;
1682 1815
1683 return exists ? attr->mode : 0; 1816 return exists ? attr->mode : 0;
1684} 1817}