Merge tag 'platform-drivers-x86-v3.20-1' of git://git.infradead.org/users/dvhart...
authorLinus Torvalds <torvalds@linux-foundation.org>
Thu, 19 Feb 2015 18:56:51 +0000 (10:56 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 19 Feb 2015 18:56:51 +0000 (10:56 -0800)
Pull platform driver update from Darren Hart:
 "This includes a significant update to the toshiba_acpi driver,
  bringing it to feature parity with the Windows driver, followed by
  some needed cleanups.

  The other changes are mostly minor updates, quirks, sparse fixes, or
  cleanups.

  Details:

   - toshiba_acpi:
       Add support for missing features from the Windows driver, bump the
       sysfs version, and clean up the driver.

   - thinkpad_acpi:
       BIOS string versions, unhandled hkey events.

   - msamsung-laptop:
       Add native backlight quirk, enable better lid handling.

   - intel_scu_ipc:
       Read resources from PCI configuration

   - other:
       Fix sparse warnings, general cleanups"

* tag 'platform-drivers-x86-v3.20-1' of git://git.infradead.org/users/dvhart/linux-platform-drivers-x86: (34 commits)
  toshiba_acpi: Cleanup GPL header
  toshiba_acpi: Cleanup comment blocks and capitalization
  toshiba_acpi: Make use of DEVICE_ATTR_{RO, RW} macros
  toshiba_acpi: Drop the toshiba_ prefix from sysfs function names
  toshiba_acpi: Move sysfs function and struct declarations further down
  Documentation/ABI: Add file describing the sysfs entries for toshiba_acpi
  toshiba_acpi: Clean file according to coding style
  toshiba_acpi: Bump version number to 0.21
  toshiba_acpi: Add support to enable/disable USB 3
  toshiba_acpi: Add support for Panel Power ON
  toshiba_acpi: Add support for Keyboard functions mode
  toshiba_acpi: Add fan entry to sysfs
  toshiba_acpi: Add version entry to sysfs
  thinkpad_acpi: support new BIOS version string pattern
  thinkpad_acpi: unhandled hkey event
  toshiba_acpi: Make toshiba_eco_mode_available more robust
  classmate-laptop: Fix sparse warning (0 as NULL)
  Sony-laptop: Fix sparse warning (make undeclared var static)
  thinkpad_acpi.c: Fix sparse warning (make undeclared var static)
  samsung-laptop.c: Prefer kstrtoint over single variable sscanf
  ...

Documentation/ABI/testing/sysfs-driver-samsung-laptop
Documentation/ABI/testing/sysfs-driver-toshiba_acpi [new file with mode: 0644]
drivers/platform/x86/asus-laptop.c
drivers/platform/x86/classmate-laptop.c
drivers/platform/x86/fujitsu-laptop.c
drivers/platform/x86/intel_scu_ipc.c
drivers/platform/x86/samsung-laptop.c
drivers/platform/x86/sony-laptop.c
drivers/platform/x86/thinkpad_acpi.c
drivers/platform/x86/toshiba_acpi.c

index 678819a3f8bf89e3b43e134979af2fa3f28199fd..63c1ad0212fc8624432f1691240443b9015b5d3f 100644 (file)
@@ -35,3 +35,11 @@ Contact:     Corentin Chary <corentin.chary@gmail.com>
 Description:   Use your USB ports to charge devices, even
                when your laptop is powered off.
                1 means enabled, 0 means disabled.
+
+What:          /sys/devices/platform/samsung/lid_handling
+Date:          December 11, 2014
+KernelVersion: 3.19
+Contact:       Julijonas Kikutis <julijonas.kikutis@gmail.com>
+Description:   Some Samsung laptops handle lid closing quicker and
+               only handle lid opening with this mode enabled.
+               1 means enabled, 0 means disabled.
diff --git a/Documentation/ABI/testing/sysfs-driver-toshiba_acpi b/Documentation/ABI/testing/sysfs-driver-toshiba_acpi
new file mode 100644 (file)
index 0000000..ca9c71a
--- /dev/null
@@ -0,0 +1,114 @@
+What:          /sys/devices/LNXSYSTM:00/LNXSYBUS:00/TOS{1900,620{0,7,8}}:00/kbd_backlight_mode
+Date:          June 8, 2014
+KernelVersion: 3.15
+Contact:       Azael Avalos <coproscefalo@gmail.com>
+Description:   This file controls the keyboard backlight operation mode, valid
+               values are:
+                       * 0x1  -> FN-Z
+                       * 0x2  -> AUTO (also called TIMER)
+                       * 0x8  -> ON
+                       * 0x10 -> OFF
+               Note that the kernel 3.16 onwards this file accepts all listed
+               parameters, kernel 3.15 only accepts the first two (FN-Z and
+               AUTO).
+Users:         KToshiba
+
+What:          /sys/devices/LNXSYSTM:00/LNXSYBUS:00/TOS{1900,620{0,7,8}}:00/kbd_backlight_timeout
+Date:          June 8, 2014
+KernelVersion: 3.15
+Contact:       Azael Avalos <coproscefalo@gmail.com>
+Description:   This file controls the timeout of the keyboard backlight
+               whenever the operation mode is set to AUTO (or TIMER),
+               valid values range from 0-60.
+               Note that the kernel 3.15 only had support for the first
+               keyboard type, the kernel 3.16 added support for the second
+               type and the range accepted for type 2 is 1-60.
+               See the entry named "kbd_type"
+Users:         KToshiba
+
+What:          /sys/devices/LNXSYSTM:00/LNXSYBUS:00/TOS{1900,620{0,7,8}}:00/position
+Date:          June 8, 2014
+KernelVersion: 3.15
+Contact:       Azael Avalos <coproscefalo@gmail.com>
+Description:   This file shows the absolute position of the built-in
+               accelereometer.
+
+What:          /sys/devices/LNXSYSTM:00/LNXSYBUS:00/TOS{1900,620{0,7,8}}:00/touchpad
+Date:          June 8, 2014
+KernelVersion: 3.15
+Contact:       Azael Avalos <coproscefalo@gmail.com>
+Description:   This files controls the status of the touchpad and pointing
+               stick (if available), valid values are:
+                       * 0 -> OFF
+                       * 1 -> ON
+Users:         KToshiba
+
+What:          /sys/devices/LNXSYSTM:00/LNXSYBUS:00/TOS{1900,620{0,7,8}}:00/available_kbd_modes
+Date:          August 3, 2014
+KernelVersion: 3.16
+Contact:       Azael Avalos <coproscefalo@gmail.com>
+Description:   This file shows the supported keyboard backlight modes
+               the system supports, which can be:
+                       * 0x1  -> FN-Z
+                       * 0x2  -> AUTO (also called TIMER)
+                       * 0x8  -> ON
+                       * 0x10 -> OFF
+               Note that not all keyboard types support the listed modes.
+               See the entry named "available_kbd_modes"
+Users:         KToshiba
+
+What:          /sys/devices/LNXSYSTM:00/LNXSYBUS:00/TOS{1900,620{0,7,8}}:00/kbd_type
+Date:          August 3, 2014
+KernelVersion: 3.16
+Contact:       Azael Avalos <coproscefalo@gmail.com>
+Description:   This file shows the current keyboard backlight type,
+               which can be:
+                       * 1 -> Type 1, supporting modes FN-Z and AUTO
+                       * 2 -> Type 2, supporting modes TIMER, ON and OFF
+Users:         KToshiba
+
+What:          /sys/devices/LNXSYSTM:00/LNXSYBUS:00/TOS{1900,620{0,7,8}}:00/version
+Date:          February, 2015
+KernelVersion: 3.20
+Contact:       Azael Avalos <coproscefalo@gmail.com>
+Description:   This file shows the current version of the driver
+
+What:          /sys/devices/LNXSYSTM:00/LNXSYBUS:00/TOS{1900,620{0,7,8}}:00/fan
+Date:          February, 2015
+KernelVersion: 3.20
+Contact:       Azael Avalos <coproscefalo@gmail.com>
+Description:   This file controls the state of the internal fan, valid
+               values are:
+                       * 0 -> OFF
+                       * 1 -> ON
+
+What:          /sys/devices/LNXSYSTM:00/LNXSYBUS:00/TOS{1900,620{0,7,8}}:00/kbd_function_keys
+Date:          February, 2015
+KernelVersion: 3.20
+Contact:       Azael Avalos <coproscefalo@gmail.com>
+Description:   This file controls the Special Functions (hotkeys) operation
+               mode, valid values are:
+                       * 0 -> Normal Operation
+                       * 1 -> Special Functions
+               In the "Normal Operation" mode, the F{1-12} keys are as usual
+               and the hotkeys are accessed via FN-F{1-12}.
+               In the "Special Functions" mode, the F{1-12} keys trigger the
+               hotkey and the F{1-12} keys are accessed via FN-F{1-12}.
+
+What:          /sys/devices/LNXSYSTM:00/LNXSYBUS:00/TOS{1900,620{0,7,8}}:00/panel_power_on
+Date:          February, 2015
+KernelVersion: 3.20
+Contact:       Azael Avalos <coproscefalo@gmail.com>
+Description:   This file controls whether the laptop should turn ON whenever
+               the LID is opened, valid values are:
+                       * 0 -> Disabled
+                       * 1 -> Enabled
+
+What:          /sys/devices/LNXSYSTM:00/LNXSYBUS:00/TOS{1900,620{0,7,8}}:00/usb_three
+Date:          February, 2015
+KernelVersion: 3.20
+Contact:       Azael Avalos <coproscefalo@gmail.com>
+Description:   This file controls whether the USB 3 functionality, valid
+               values are:
+                       * 0 -> Disabled (Acts as a regular USB 2)
+                       * 1 -> Enabled (Full USB 3 functionality)
index f71700e0d13212cb3a93701d939c9fced2b0f6ca..46b27469387283eed295e664a6c728a639860fa5 100644 (file)
@@ -856,8 +856,8 @@ static void asus_backlight_exit(struct asus_laptop *asus)
  * than count bytes. We set eof to 1 if we handle those 2 values. We return the
  * number of bytes written in page
  */
-static ssize_t show_infos(struct device *dev,
-                         struct device_attribute *attr, char *page)
+static ssize_t infos_show(struct device *dev, struct device_attribute *attr,
+                         char *page)
 {
        struct asus_laptop *asus = dev_get_drvdata(dev);
        int len = 0;
@@ -926,6 +926,7 @@ static ssize_t show_infos(struct device *dev,
 
        return len;
 }
+static DEVICE_ATTR_RO(infos);
 
 static int parse_arg(const char *buf, unsigned long count, int *val)
 {
@@ -957,15 +958,15 @@ static ssize_t sysfs_acpi_set(struct asus_laptop *asus,
 /*
  * LEDD display
  */
-static ssize_t show_ledd(struct device *dev,
-                        struct device_attribute *attr, char *buf)
+static ssize_t ledd_show(struct device *dev, struct device_attribute *attr,
+                        char *buf)
 {
        struct asus_laptop *asus = dev_get_drvdata(dev);
 
        return sprintf(buf, "0x%08x\n", asus->ledd_status);
 }
 
-static ssize_t store_ledd(struct device *dev, struct device_attribute *attr,
+static ssize_t ledd_store(struct device *dev, struct device_attribute *attr,
                          const char *buf, size_t count)
 {
        struct asus_laptop *asus = dev_get_drvdata(dev);
@@ -981,6 +982,7 @@ static ssize_t store_ledd(struct device *dev, struct device_attribute *attr,
        }
        return rv;
 }
+static DEVICE_ATTR_RW(ledd);
 
 /*
  * Wireless
@@ -1014,21 +1016,22 @@ static int asus_wlan_set(struct asus_laptop *asus, int status)
        return 0;
 }
 
-static ssize_t show_wlan(struct device *dev,
-                        struct device_attribute *attr, char *buf)
+static ssize_t wlan_show(struct device *dev, struct device_attribute *attr,
+                        char *buf)
 {
        struct asus_laptop *asus = dev_get_drvdata(dev);
 
        return sprintf(buf, "%d\n", asus_wireless_status(asus, WL_RSTS));
 }
 
-static ssize_t store_wlan(struct device *dev, struct device_attribute *attr,
+static ssize_t wlan_store(struct device *dev, struct device_attribute *attr,
                          const char *buf, size_t count)
 {
        struct asus_laptop *asus = dev_get_drvdata(dev);
 
        return sysfs_acpi_set(asus, buf, count, METHOD_WLAN);
 }
+static DEVICE_ATTR_RW(wlan);
 
 /*e
  * Bluetooth
@@ -1042,15 +1045,15 @@ static int asus_bluetooth_set(struct asus_laptop *asus, int status)
        return 0;
 }
 
-static ssize_t show_bluetooth(struct device *dev,
-                             struct device_attribute *attr, char *buf)
+static ssize_t bluetooth_show(struct device *dev, struct device_attribute *attr,
+                             char *buf)
 {
        struct asus_laptop *asus = dev_get_drvdata(dev);
 
        return sprintf(buf, "%d\n", asus_wireless_status(asus, BT_RSTS));
 }
 
-static ssize_t store_bluetooth(struct device *dev,
+static ssize_t bluetooth_store(struct device *dev,
                               struct device_attribute *attr, const char *buf,
                               size_t count)
 {
@@ -1058,6 +1061,7 @@ static ssize_t store_bluetooth(struct device *dev,
 
        return sysfs_acpi_set(asus, buf, count, METHOD_BLUETOOTH);
 }
+static DEVICE_ATTR_RW(bluetooth);
 
 /*
  * Wimax
@@ -1071,22 +1075,22 @@ static int asus_wimax_set(struct asus_laptop *asus, int status)
        return 0;
 }
 
-static ssize_t show_wimax(struct device *dev,
-                             struct device_attribute *attr, char *buf)
+static ssize_t wimax_show(struct device *dev, struct device_attribute *attr,
+                         char *buf)
 {
        struct asus_laptop *asus = dev_get_drvdata(dev);
 
        return sprintf(buf, "%d\n", asus_wireless_status(asus, WM_RSTS));
 }
 
-static ssize_t store_wimax(struct device *dev,
-                              struct device_attribute *attr, const char *buf,
-                              size_t count)
+static ssize_t wimax_store(struct device *dev, struct device_attribute *attr,
+                          const char *buf, size_t count)
 {
        struct asus_laptop *asus = dev_get_drvdata(dev);
 
        return sysfs_acpi_set(asus, buf, count, METHOD_WIMAX);
 }
+static DEVICE_ATTR_RW(wimax);
 
 /*
  * Wwan
@@ -1100,22 +1104,22 @@ static int asus_wwan_set(struct asus_laptop *asus, int status)
        return 0;
 }
 
-static ssize_t show_wwan(struct device *dev,
-                             struct device_attribute *attr, char *buf)
+static ssize_t wwan_show(struct device *dev, struct device_attribute *attr,
+                        char *buf)
 {
        struct asus_laptop *asus = dev_get_drvdata(dev);
 
        return sprintf(buf, "%d\n", asus_wireless_status(asus, WW_RSTS));
 }
 
-static ssize_t store_wwan(struct device *dev,
-                              struct device_attribute *attr, const char *buf,
-                              size_t count)
+static ssize_t wwan_store(struct device *dev, struct device_attribute *attr,
+                         const char *buf, size_t count)
 {
        struct asus_laptop *asus = dev_get_drvdata(dev);
 
        return sysfs_acpi_set(asus, buf, count, METHOD_WWAN);
 }
+static DEVICE_ATTR_RW(wwan);
 
 /*
  * Display
@@ -1135,8 +1139,8 @@ static void asus_set_display(struct asus_laptop *asus, int value)
  * displays hooked up simultaneously, so be warned. See the acpi4asus README
  * for more info.
  */
-static ssize_t store_disp(struct device *dev, struct device_attribute *attr,
-                         const char *buf, size_t count)
+static ssize_t display_store(struct device *dev, struct device_attribute *attr,
+                            const char *buf, size_t count)
 {
        struct asus_laptop *asus = dev_get_drvdata(dev);
        int rv, value;
@@ -1146,6 +1150,7 @@ static ssize_t store_disp(struct device *dev, struct device_attribute *attr,
                asus_set_display(asus, value);
        return rv;
 }
+static DEVICE_ATTR_WO(display);
 
 /*
  * Light Sens
@@ -1167,16 +1172,17 @@ static void asus_als_switch(struct asus_laptop *asus, int value)
        asus->light_switch = value;
 }
 
-static ssize_t show_lssw(struct device *dev,
-                        struct device_attribute *attr, char *buf)
+static ssize_t ls_switch_show(struct device *dev, struct device_attribute *attr,
+                             char *buf)
 {
        struct asus_laptop *asus = dev_get_drvdata(dev);
 
        return sprintf(buf, "%d\n", asus->light_switch);
 }
 
-static ssize_t store_lssw(struct device *dev, struct device_attribute *attr,
-                         const char *buf, size_t count)
+static ssize_t ls_switch_store(struct device *dev,
+                              struct device_attribute *attr, const char *buf,
+                              size_t count)
 {
        struct asus_laptop *asus = dev_get_drvdata(dev);
        int rv, value;
@@ -1187,6 +1193,7 @@ static ssize_t store_lssw(struct device *dev, struct device_attribute *attr,
 
        return rv;
 }
+static DEVICE_ATTR_RW(ls_switch);
 
 static void asus_als_level(struct asus_laptop *asus, int value)
 {
@@ -1195,16 +1202,16 @@ static void asus_als_level(struct asus_laptop *asus, int value)
        asus->light_level = value;
 }
 
-static ssize_t show_lslvl(struct device *dev,
-                         struct device_attribute *attr, char *buf)
+static ssize_t ls_level_show(struct device *dev, struct device_attribute *attr,
+                            char *buf)
 {
        struct asus_laptop *asus = dev_get_drvdata(dev);
 
        return sprintf(buf, "%d\n", asus->light_level);
 }
 
-static ssize_t store_lslvl(struct device *dev, struct device_attribute *attr,
-                          const char *buf, size_t count)
+static ssize_t ls_level_store(struct device *dev, struct device_attribute *attr,
+                             const char *buf, size_t count)
 {
        struct asus_laptop *asus = dev_get_drvdata(dev);
        int rv, value;
@@ -1218,6 +1225,7 @@ static ssize_t store_lslvl(struct device *dev, struct device_attribute *attr,
 
        return rv;
 }
+static DEVICE_ATTR_RW(ls_level);
 
 static int pega_int_read(struct asus_laptop *asus, int arg, int *result)
 {
@@ -1234,8 +1242,8 @@ static int pega_int_read(struct asus_laptop *asus, int arg, int *result)
        return err;
 }
 
-static ssize_t show_lsvalue(struct device *dev,
-                           struct device_attribute *attr, char *buf)
+static ssize_t ls_value_show(struct device *dev, struct device_attribute *attr,
+                            char *buf)
 {
        struct asus_laptop *asus = dev_get_drvdata(dev);
        int err, hi, lo;
@@ -1247,6 +1255,7 @@ static ssize_t show_lsvalue(struct device *dev,
                return sprintf(buf, "%d\n", 10 * hi + lo);
        return err;
 }
+static DEVICE_ATTR_RO(ls_value);
 
 /*
  * GPS
@@ -1274,15 +1283,15 @@ static int asus_gps_switch(struct asus_laptop *asus, int status)
        return 0;
 }
 
-static ssize_t show_gps(struct device *dev,
-                       struct device_attribute *attr, char *buf)
+static ssize_t gps_show(struct device *dev, struct device_attribute *attr,
+                       char *buf)
 {
        struct asus_laptop *asus = dev_get_drvdata(dev);
 
        return sprintf(buf, "%d\n", asus_gps_status(asus));
 }
 
-static ssize_t store_gps(struct device *dev, struct device_attribute *attr,
+static ssize_t gps_store(struct device *dev, struct device_attribute *attr,
                         const char *buf, size_t count)
 {
        struct asus_laptop *asus = dev_get_drvdata(dev);
@@ -1298,6 +1307,7 @@ static ssize_t store_gps(struct device *dev, struct device_attribute *attr,
        rfkill_set_sw_state(asus->gps.rfkill, !value);
        return rv;
 }
+static DEVICE_ATTR_RW(gps);
 
 /*
  * rfkill
@@ -1569,19 +1579,6 @@ static void asus_acpi_notify(struct acpi_device *device, u32 event)
        asus_input_notify(asus, event);
 }
 
-static DEVICE_ATTR(infos, S_IRUGO, show_infos, NULL);
-static DEVICE_ATTR(wlan, S_IRUGO | S_IWUSR, show_wlan, store_wlan);
-static DEVICE_ATTR(bluetooth, S_IRUGO | S_IWUSR,
-                  show_bluetooth, store_bluetooth);
-static DEVICE_ATTR(wimax, S_IRUGO | S_IWUSR, show_wimax, store_wimax);
-static DEVICE_ATTR(wwan, S_IRUGO | S_IWUSR, show_wwan, store_wwan);
-static DEVICE_ATTR(display, S_IWUSR, NULL, store_disp);
-static DEVICE_ATTR(ledd, S_IRUGO | S_IWUSR, show_ledd, store_ledd);
-static DEVICE_ATTR(ls_value, S_IRUGO, show_lsvalue, NULL);
-static DEVICE_ATTR(ls_level, S_IRUGO | S_IWUSR, show_lslvl, store_lslvl);
-static DEVICE_ATTR(ls_switch, S_IRUGO | S_IWUSR, show_lssw, store_lssw);
-static DEVICE_ATTR(gps, S_IRUGO | S_IWUSR, show_gps, store_gps);
-
 static struct attribute *asus_attributes[] = {
        &dev_attr_infos.attr,
        &dev_attr_wlan.attr,
@@ -1616,7 +1613,7 @@ static umode_t asus_sysfs_is_visible(struct kobject *kobj,
                else
                        goto normal;
 
-               return supported;
+               return supported ? attr->mode : 0;
        }
 
 normal:
index 70d355a9ae2cc2f7cdc2efb04941a2c76688139f..55cf10bc78174b2b50094ec3aebf59ded10847b1 100644 (file)
@@ -520,7 +520,7 @@ static acpi_status cmpc_get_accel(acpi_handle handle,
 {
        union acpi_object param[2];
        struct acpi_object_list input;
-       struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, 0 };
+       struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
        unsigned char *locs;
        acpi_status status;
 
index 7c21c1c44dfa9acc05bcdf235f12fff4fd8969b0..2a9afa261c615bffb1f1586f2fcb3a287fd33d4b 100644 (file)
@@ -64,6 +64,7 @@
 #include <linux/acpi.h>
 #include <linux/dmi.h>
 #include <linux/backlight.h>
+#include <linux/fb.h>
 #include <linux/input.h>
 #include <linux/kfifo.h>
 #include <linux/platform_device.h>
@@ -398,7 +399,7 @@ static int bl_get_brightness(struct backlight_device *b)
 static int bl_update_status(struct backlight_device *b)
 {
        int ret;
-       if (b->props.power == 4)
+       if (b->props.power == FB_BLANK_POWERDOWN)
                ret = call_fext_func(FUNC_BACKLIGHT, 0x1, 0x4, 0x3);
        else
                ret = call_fext_func(FUNC_BACKLIGHT, 0x1, 0x4, 0x0);
@@ -1139,9 +1140,9 @@ static int __init fujitsu_init(void)
 
        if (!acpi_video_backlight_support()) {
                if (call_fext_func(FUNC_BACKLIGHT, 0x2, 0x4, 0x0) == 3)
-                       fujitsu->bl_device->props.power = 4;
+                       fujitsu->bl_device->props.power = FB_BLANK_POWERDOWN;
                else
-                       fujitsu->bl_device->props.power = 0;
+                       fujitsu->bl_device->props.power = FB_BLANK_UNBLANK;
        }
 
        pr_info("driver " FUJITSU_DRIVER_VERSION " successfully loaded\n");
index 66a4d3284aab7cca2cef0ecb85b792d39013bfbb..001b199a8c33d3a90e6693edd6475a63bf6dc6a5 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * intel_scu_ipc.c: Driver for the Intel SCU IPC mechanism
  *
- * (C) Copyright 2008-2010 Intel Corporation
+ * (C) Copyright 2008-2010,2015 Intel Corporation
  * Author: Sreedhara DS (sreedhara.ds@intel.com)
  *
  * This program is free software; you can redistribute it and/or
 /*
  * IPC register summary
  *
- * IPC register blocks are memory mapped at fixed address of 0xFF11C000
+ * IPC register blocks are memory mapped at fixed address of PCI BAR 0.
  * To read or write information to the SCU, driver writes to IPC-1 memory
- * mapped registers (base address 0xFF11C000). The following is the IPC
- * mechanism
+ * mapped registers. The following is the IPC mechanism
  *
  * 1. IA core cDMI interface claims this transaction and converts it to a
  *    Transaction Layer Packet (TLP) message which is sent across the cDMI.
 #define PCI_DEVICE_ID_CLOVERVIEW       0x08ea
 #define PCI_DEVICE_ID_TANGIER          0x11a0
 
-/* intel scu ipc driver data*/
+/* intel scu ipc driver data */
 struct intel_scu_ipc_pdata_t {
-       u32 ipc_base;
        u32 i2c_base;
-       u32 ipc_len;
        u32 i2c_len;
        u8 irq_mode;
 };
 
 static struct intel_scu_ipc_pdata_t intel_scu_ipc_lincroft_pdata = {
-       .ipc_base = 0xff11c000,
        .i2c_base = 0xff12b000,
-       .ipc_len = 0x100,
        .i2c_len = 0x10,
        .irq_mode = 0,
 };
 
 /* Penwell and Cloverview */
 static struct intel_scu_ipc_pdata_t intel_scu_ipc_penwell_pdata = {
-       .ipc_base = 0xff11c000,
        .i2c_base = 0xff12b000,
-       .ipc_len = 0x100,
        .i2c_len = 0x10,
        .irq_mode = 1,
 };
 
 static struct intel_scu_ipc_pdata_t intel_scu_ipc_tangier_pdata = {
-       .ipc_base = 0xff009000,
        .i2c_base  = 0xff00d000,
-       .ipc_len  = 0x100,
        .i2c_len = 0x10,
        .irq_mode = 0,
 };
@@ -114,8 +105,6 @@ struct intel_scu_ipc_dev {
 
 static struct intel_scu_ipc_dev  ipcdev; /* Only one for now */
 
-static int platform;           /* Platform type */
-
 /*
  * IPC Read Buffer (Read Only):
  * 16 byte buffer for receiving data from SCU, if IPC command
@@ -160,7 +149,6 @@ static inline void ipc_data_writel(u32 data, u32 offset) /* Write ipc data */
  * Format:
  * |rfu3(8)|error code(8)|initiator id(8)|cmd id(4)|rfu1(2)|error(1)|busy(1)|
  */
-
 static inline u8 ipc_read_status(void)
 {
        return __raw_readl(ipcdev.ipc_base + 0x04);
@@ -176,23 +164,24 @@ static inline u32 ipc_data_readl(u32 offset) /* Read ipc u32 data */
        return readl(ipcdev.ipc_base + IPC_READ_BUFFER + offset);
 }
 
-static inline int busy_loop(void) /* Wait till scu status is busy */
+/* Wait till scu status is busy */
+static inline int busy_loop(void)
 {
-       u32 status = 0;
-       u32 loop_count = 0;
+       u32 status = ipc_read_status();
+       u32 loop_count = 100000;
 
-       status = ipc_read_status();
-       while (status & 1) {
+       /* break if scu doesn't reset busy bit after huge retry */
+       while ((status & BIT(0)) && --loop_count) {
                udelay(1); /* scu processing time is in few u secods */
                status = ipc_read_status();
-               loop_count++;
-               /* break if scu doesn't reset busy bit after huge retry */
-               if (loop_count > 100000) {
-                       dev_err(&ipcdev.pdev->dev, "IPC timed out");
-                       return -ETIMEDOUT;
-               }
        }
-       if ((status >> 1) & 1)
+
+       if (status & BIT(0)) {
+               dev_err(&ipcdev.pdev->dev, "IPC timed out");
+               return -ETIMEDOUT;
+       }
+
+       if (status & BIT(1))
                return -EIO;
 
        return 0;
@@ -210,14 +199,13 @@ static inline int ipc_wait_for_interrupt(void)
        }
 
        status = ipc_read_status();
-
-       if ((status >> 1) & 1)
+       if (status & BIT(1))
                return -EIO;
 
        return 0;
 }
 
-int intel_scu_ipc_check_status(void)
+static int intel_scu_ipc_check_status(void)
 {
        return ipcdev.irq_mode ? ipc_wait_for_interrupt() : busy_loop();
 }
@@ -248,18 +236,18 @@ static int pwr_reg_rdwr(u16 *addr, u8 *data, u32 count, u32 op, u32 id)
        if (id == IPC_CMD_PCNTRL_R) {
                for (nc = 0, offset = 0; nc < count; nc++, offset += 4)
                        ipc_data_writel(wbuf[nc], offset);
-               ipc_command((count*2) << 16 |  id << 12 | 0 << 8 | op);
+               ipc_command((count * 2) << 16 | id << 12 | 0 << 8 | op);
        } else if (id == IPC_CMD_PCNTRL_W) {
                for (nc = 0; nc < count; nc++, offset += 1)
                        cbuf[offset] = data[nc];
                for (nc = 0, offset = 0; nc < count; nc++, offset += 4)
                        ipc_data_writel(wbuf[nc], offset);
-               ipc_command((count*3) << 16 |  id << 12 | 0 << 8 | op);
+               ipc_command((count * 3) << 16 | id << 12 | 0 << 8 | op);
        } else if (id == IPC_CMD_PCNTRL_M) {
                cbuf[offset] = data[0];
                cbuf[offset + 1] = data[1];
                ipc_data_writel(wbuf[0], 0); /* Write wbuff */
-               ipc_command(4 << 16 |  id << 12 | 0 << 8 | op);
+               ipc_command(4 << 16 | id << 12 | 0 << 8 | op);
        }
 
        err = intel_scu_ipc_check_status();
@@ -301,7 +289,7 @@ EXPORT_SYMBOL(intel_scu_ipc_ioread8);
  */
 int intel_scu_ipc_ioread16(u16 addr, u16 *data)
 {
-       u16 x[2] = {addr, addr + 1 };
+       u16 x[2] = {addr, addr + 1};
        return pwr_reg_rdwr(x, (u8 *)data, 2, IPCMSG_PCNTRL, IPC_CMD_PCNTRL_R);
 }
 EXPORT_SYMBOL(intel_scu_ipc_ioread16);
@@ -351,7 +339,7 @@ EXPORT_SYMBOL(intel_scu_ipc_iowrite8);
  */
 int intel_scu_ipc_iowrite16(u16 addr, u16 data)
 {
-       u16 x[2] = {addr, addr + 1 };
+       u16 x[2] = {addr, addr + 1};
        return pwr_reg_rdwr(x, (u8 *)&data, 2, IPCMSG_PCNTRL, IPC_CMD_PCNTRL_W);
 }
 EXPORT_SYMBOL(intel_scu_ipc_iowrite16);
@@ -412,7 +400,6 @@ int intel_scu_ipc_writev(u16 *addr, u8 *data, int len)
 }
 EXPORT_SYMBOL(intel_scu_ipc_writev);
 
-
 /**
  *     intel_scu_ipc_update_register   -       r/m/w a register
  *     @addr: register address
@@ -475,9 +462,8 @@ EXPORT_SYMBOL(intel_scu_ipc_simple_command);
  *     Issue a command to the SCU which involves data transfers. Do the
  *     data copies under the lock but leave it for the caller to interpret
  */
-
 int intel_scu_ipc_command(int cmd, int sub, u32 *in, int inlen,
-                                                       u32 *out, int outlen)
+                         u32 *out, int outlen)
 {
        int i, err;
 
@@ -503,7 +489,7 @@ int intel_scu_ipc_command(int cmd, int sub, u32 *in, int inlen,
 }
 EXPORT_SYMBOL(intel_scu_ipc_command);
 
-/*I2C commands */
+/* I2C commands */
 #define IPC_I2C_WRITE 1 /* I2C Write command */
 #define IPC_I2C_READ  2 /* I2C Read command */
 
@@ -577,7 +563,7 @@ static int ipc_probe(struct pci_dev *dev, const struct pci_device_id *id)
 {
        int err;
        struct intel_scu_ipc_pdata_t *pdata;
-       resource_size_t pci_resource;
+       resource_size_t base;
 
        if (ipcdev.pdev)                /* We support only one SCU */
                return -EBUSY;
@@ -595,8 +581,8 @@ static int ipc_probe(struct pci_dev *dev, const struct pci_device_id *id)
        if (err)
                return err;
 
-       pci_resource = pci_resource_start(dev, 0);
-       if (!pci_resource)
+       base = pci_resource_start(dev, 0);
+       if (!base)
                return -ENOMEM;
 
        init_completion(&ipcdev.cmd_complete);
@@ -604,7 +590,7 @@ static int ipc_probe(struct pci_dev *dev, const struct pci_device_id *id)
        if (request_irq(dev->irq, ioc, 0, "intel_scu_ipc", &ipcdev))
                return -EBUSY;
 
-       ipcdev.ipc_base = ioremap_nocache(pdata->ipc_base, pdata->ipc_len);
+       ipcdev.ipc_base = ioremap_nocache(base, pci_resource_len(dev, 0));
        if (!ipcdev.ipc_base)
                return -ENOMEM;
 
@@ -666,9 +652,10 @@ static struct pci_driver ipc_driver = {
        .remove = ipc_remove,
 };
 
-
 static int __init intel_scu_ipc_init(void)
 {
+       int platform;           /* Platform type */
+
        platform = intel_mid_identify_cpu();
        if (platform == 0)
                return -ENODEV;
index ff765d8e1a09f648ad40770cdd59cf6aadaaf7e8..9e701b2256f9571afca37e01a7185fe8e63e8399 100644 (file)
@@ -124,6 +124,10 @@ struct sabi_commands {
        u16 get_wireless_status;
        u16 set_wireless_status;
 
+       /* 0x80 is off, 0x81 is on */
+       u16 get_lid_handling;
+       u16 set_lid_handling;
+
        /* 0x81 to read, (0x82 | level << 8) to set, 0xaabb to enable */
        u16 kbd_backlight;
 
@@ -194,6 +198,9 @@ static const struct sabi_config sabi_configs[] = {
                        .get_wireless_status = 0xFFFF,
                        .set_wireless_status = 0xFFFF,
 
+                       .get_lid_handling = 0xFFFF,
+                       .set_lid_handling = 0xFFFF,
+
                        .kbd_backlight = 0xFFFF,
 
                        .set_linux = 0x0a,
@@ -254,6 +261,9 @@ static const struct sabi_config sabi_configs[] = {
                        .get_wireless_status = 0x69,
                        .set_wireless_status = 0x6a,
 
+                       .get_lid_handling = 0x6d,
+                       .set_lid_handling = 0x6e,
+
                        .kbd_backlight = 0x78,
 
                        .set_linux = 0xff,
@@ -353,6 +363,8 @@ struct samsung_quirks {
        bool broken_acpi_video;
        bool four_kbd_backlight_levels;
        bool enable_kbd_backlight;
+       bool use_native_backlight;
+       bool lid_handling;
 };
 
 static struct samsung_quirks samsung_unknown = {};
@@ -361,11 +373,19 @@ static struct samsung_quirks samsung_broken_acpi_video = {
        .broken_acpi_video = true,
 };
 
+static struct samsung_quirks samsung_use_native_backlight = {
+       .use_native_backlight = true,
+};
+
 static struct samsung_quirks samsung_np740u3e = {
        .four_kbd_backlight_levels = true,
        .enable_kbd_backlight = true,
 };
 
+static struct samsung_quirks samsung_lid_handling = {
+       .lid_handling = true,
+};
+
 static bool force;
 module_param(force, bool, 0);
 MODULE_PARM_DESC(force,
@@ -748,7 +768,7 @@ static ssize_t set_battery_life_extender(struct device *dev,
        struct samsung_laptop *samsung = dev_get_drvdata(dev);
        int ret, value;
 
-       if (!count || sscanf(buf, "%i", &value) != 1)
+       if (!count || kstrtoint(buf, 0, &value) != 0)
                return -EINVAL;
 
        ret = write_battery_life_extender(samsung, !!value);
@@ -817,7 +837,7 @@ static ssize_t set_usb_charge(struct device *dev,
        struct samsung_laptop *samsung = dev_get_drvdata(dev);
        int ret, value;
 
-       if (!count || sscanf(buf, "%i", &value) != 1)
+       if (!count || kstrtoint(buf, 0, &value) != 0)
                return -EINVAL;
 
        ret = write_usb_charge(samsung, !!value);
@@ -830,10 +850,76 @@ static ssize_t set_usb_charge(struct device *dev,
 static DEVICE_ATTR(usb_charge, S_IWUSR | S_IRUGO,
                   get_usb_charge, set_usb_charge);
 
+static int read_lid_handling(struct samsung_laptop *samsung)
+{
+       const struct sabi_commands *commands = &samsung->config->commands;
+       struct sabi_data data;
+       int retval;
+
+       if (commands->get_lid_handling == 0xFFFF)
+               return -ENODEV;
+
+       memset(&data, 0, sizeof(data));
+       retval = sabi_command(samsung, commands->get_lid_handling,
+                             &data, &data);
+
+       if (retval)
+               return retval;
+
+       return data.data[0] & 0x1;
+}
+
+static int write_lid_handling(struct samsung_laptop *samsung,
+                             int enabled)
+{
+       const struct sabi_commands *commands = &samsung->config->commands;
+       struct sabi_data data;
+
+       memset(&data, 0, sizeof(data));
+       data.data[0] = 0x80 | enabled;
+       return sabi_command(samsung, commands->set_lid_handling,
+                           &data, NULL);
+}
+
+static ssize_t get_lid_handling(struct device *dev,
+                               struct device_attribute *attr,
+                               char *buf)
+{
+       struct samsung_laptop *samsung = dev_get_drvdata(dev);
+       int ret;
+
+       ret = read_lid_handling(samsung);
+       if (ret < 0)
+               return ret;
+
+       return sprintf(buf, "%d\n", ret);
+}
+
+static ssize_t set_lid_handling(struct device *dev,
+                               struct device_attribute *attr,
+                               const char *buf, size_t count)
+{
+       struct samsung_laptop *samsung = dev_get_drvdata(dev);
+       int ret, value;
+
+       if (!count || kstrtoint(buf, 0, &value) != 0)
+               return -EINVAL;
+
+       ret = write_lid_handling(samsung, !!value);
+       if (ret < 0)
+               return ret;
+
+       return count;
+}
+
+static DEVICE_ATTR(lid_handling, S_IWUSR | S_IRUGO,
+                  get_lid_handling, set_lid_handling);
+
 static struct attribute *platform_attributes[] = {
        &dev_attr_performance_level.attr,
        &dev_attr_battery_life_extender.attr,
        &dev_attr_usb_charge.attr,
+       &dev_attr_lid_handling.attr,
        NULL
 };
 
@@ -956,6 +1042,22 @@ static int __init samsung_rfkill_init(struct samsung_laptop *samsung)
        return 0;
 }
 
+static void samsung_lid_handling_exit(struct samsung_laptop *samsung)
+{
+       if (samsung->quirks->lid_handling)
+               write_lid_handling(samsung, 0);
+}
+
+static int __init samsung_lid_handling_init(struct samsung_laptop *samsung)
+{
+       int retval = 0;
+
+       if (samsung->quirks->lid_handling)
+               retval = write_lid_handling(samsung, 1);
+
+       return retval;
+}
+
 static int kbd_backlight_enable(struct samsung_laptop *samsung)
 {
        const struct sabi_commands *commands = &samsung->config->commands;
@@ -1111,7 +1213,7 @@ static int __init samsung_backlight_init(struct samsung_laptop *samsung)
 }
 
 static umode_t samsung_sysfs_is_visible(struct kobject *kobj,
-                                      struct attribute *attr, int idx)
+                                       struct attribute *attr, int idx)
 {
        struct device *dev = container_of(kobj, struct device, kobj);
        struct platform_device *pdev = to_platform_device(dev);
@@ -1124,6 +1226,8 @@ static umode_t samsung_sysfs_is_visible(struct kobject *kobj,
                ok = !!(read_battery_life_extender(samsung) >= 0);
        if (attr == &dev_attr_usb_charge.attr)
                ok = !!(read_usb_charge(samsung) >= 0);
+       if (attr == &dev_attr_lid_handling.attr)
+               ok = !!(read_lid_handling(samsung) >= 0);
 
        return ok ? attr->mode : 0;
 }
@@ -1357,7 +1461,7 @@ static int __init samsung_sabi_init(struct samsung_laptop *samsung)
        samsung_sabi_diag(samsung);
 
        /* Try to find one of the signatures in memory to find the header */
-       for (i = 0; sabi_configs[i].test_string != 0; ++i) {
+       for (i = 0; sabi_configs[i].test_string != NULL; ++i) {
                samsung->config = &sabi_configs[i];
                loca = find_signature(samsung->f0000_segment,
                                      samsung->config->test_string);
@@ -1436,6 +1540,9 @@ static int samsung_pm_notification(struct notifier_block *nb,
            samsung->quirks->enable_kbd_backlight)
                kbd_backlight_enable(samsung);
 
+       if (val == PM_POST_HIBERNATION && samsung->quirks->lid_handling)
+               write_lid_handling(samsung, 1);
+
        return 0;
 }
 
@@ -1507,7 +1614,7 @@ static struct dmi_system_id __initdata samsung_dmi_table[] = {
                DMI_MATCH(DMI_PRODUCT_NAME, "N150P"),
                DMI_MATCH(DMI_BOARD_NAME, "N150P"),
                },
-        .driver_data = &samsung_broken_acpi_video,
+        .driver_data = &samsung_use_native_backlight,
        },
        {
         .callback = samsung_dmi_matched,
@@ -1517,7 +1624,7 @@ static struct dmi_system_id __initdata samsung_dmi_table[] = {
                DMI_MATCH(DMI_PRODUCT_NAME, "N145P/N250P/N260P"),
                DMI_MATCH(DMI_BOARD_NAME, "N145P/N250P/N260P"),
                },
-        .driver_data = &samsung_broken_acpi_video,
+        .driver_data = &samsung_use_native_backlight,
        },
        {
         .callback = samsung_dmi_matched,
@@ -1557,7 +1664,7 @@ static struct dmi_system_id __initdata samsung_dmi_table[] = {
                DMI_MATCH(DMI_PRODUCT_NAME, "N250P"),
                DMI_MATCH(DMI_BOARD_NAME, "N250P"),
                },
-        .driver_data = &samsung_broken_acpi_video,
+        .driver_data = &samsung_use_native_backlight,
        },
        {
         .callback = samsung_dmi_matched,
@@ -1578,6 +1685,15 @@ static struct dmi_system_id __initdata samsung_dmi_table[] = {
                },
         .driver_data = &samsung_np740u3e,
        },
+       {
+        .callback = samsung_dmi_matched,
+        .ident = "300V3Z/300V4Z/300V5Z",
+        .matches = {
+               DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
+               DMI_MATCH(DMI_PRODUCT_NAME, "300V3Z/300V4Z/300V5Z"),
+               },
+        .driver_data = &samsung_lid_handling,
+       },
        { },
 };
 MODULE_DEVICE_TABLE(dmi, samsung_dmi_table);
@@ -1616,6 +1732,15 @@ static int __init samsung_init(void)
                pr_info("Disabling ACPI video driver\n");
                acpi_video_unregister();
        }
+
+       if (samsung->quirks->use_native_backlight) {
+               pr_info("Using native backlight driver\n");
+               /* Tell acpi-video to not handle the backlight */
+               acpi_video_dmi_promote_vendor();
+               acpi_video_unregister();
+               /* And also do not handle it ourselves */
+               samsung->handle_backlight = false;
+       }
 #endif
 
        ret = samsung_platform_init(samsung);
@@ -1648,6 +1773,10 @@ static int __init samsung_init(void)
        if (ret)
                goto error_leds;
 
+       ret = samsung_lid_handling_init(samsung);
+       if (ret)
+               goto error_lid_handling;
+
        ret = samsung_debugfs_init(samsung);
        if (ret)
                goto error_debugfs;
@@ -1659,6 +1788,8 @@ static int __init samsung_init(void)
        return ret;
 
 error_debugfs:
+       samsung_lid_handling_exit(samsung);
+error_lid_handling:
        samsung_leds_exit(samsung);
 error_leds:
        samsung_rfkill_exit(samsung);
@@ -1683,6 +1814,7 @@ static void __exit samsung_exit(void)
        unregister_pm_notifier(&samsung->pm_nb);
 
        samsung_debugfs_exit(samsung);
+       samsung_lid_handling_exit(samsung);
        samsung_leds_exit(samsung);
        samsung_rfkill_exit(samsung);
        samsung_backlight_exit(samsung);
index 6dd1c0e7dcd9af81a43db55f0c4ba87956e37dde..e51c1e7536077306234e579121cf18badcb45a01 100644 (file)
@@ -1032,7 +1032,7 @@ struct sony_backlight_props {
        u8                      offset;
        u8                      maxlvl;
 };
-struct sony_backlight_props sony_bl_props;
+static struct sony_backlight_props sony_bl_props;
 
 static int sony_backlight_update_status(struct backlight_device *bd)
 {
index c3d11fabc46f21c98c6122497958837ae291b171..3b8ceee7c5cbfd891c87a5fd58c59017db5f34e8 100644 (file)
@@ -196,6 +196,7 @@ enum tpacpi_hkey_event_t {
        /* Key-related user-interface events */
        TP_HKEY_EV_KEY_NUMLOCK          = 0x6000, /* NumLock key pressed */
        TP_HKEY_EV_KEY_FN               = 0x6005, /* Fn key pressed? E420 */
+       TP_HKEY_EV_KEY_FN_ESC           = 0x6060, /* Fn+Esc key pressed X240 */
 
        /* Thermal events */
        TP_HKEY_EV_ALARM_BAT_HOT        = 0x6011, /* battery too hot */
@@ -3456,7 +3457,7 @@ enum ADAPTIVE_KEY_MODE {
        LAYFLAT_MODE
 };
 
-const int adaptive_keyboard_modes[] = {
+static const int adaptive_keyboard_modes[] = {
        HOME_MODE,
 /*     WEB_BROWSER_MODE = 2,
        WEB_CONFERENCE_MODE = 3, */
@@ -3712,6 +3713,7 @@ static bool hotkey_notify_6xxx(const u32 hkey,
 
        case TP_HKEY_EV_KEY_NUMLOCK:
        case TP_HKEY_EV_KEY_FN:
+       case TP_HKEY_EV_KEY_FN_ESC:
                /* key press events, we just ignore them as long as the EC
                 * is still reporting them in the normal keyboard stream */
                *send_acpi_ev = false;
@@ -8883,17 +8885,31 @@ static bool __pure __init tpacpi_is_fw_digit(const char c)
        return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z');
 }
 
-/* Most models: xxyTkkWW (#.##c); Ancient 570/600 and -SL lacks (#.##c) */
 static bool __pure __init tpacpi_is_valid_fw_id(const char * const s,
                                                const char t)
 {
-       return s && strlen(s) >= 8 &&
+       /*
+        * Most models: xxyTkkWW (#.##c)
+        * Ancient 570/600 and -SL lacks (#.##c)
+        */
+       if (s && strlen(s) >= 8 &&
                tpacpi_is_fw_digit(s[0]) &&
                tpacpi_is_fw_digit(s[1]) &&
                s[2] == t &&
                (s[3] == 'T' || s[3] == 'N') &&
                tpacpi_is_fw_digit(s[4]) &&
-               tpacpi_is_fw_digit(s[5]);
+               tpacpi_is_fw_digit(s[5]))
+               return true;
+
+       /* New models: xxxyTkkW (#.##c); T550 and some others */
+       return s && strlen(s) >= 8 &&
+               tpacpi_is_fw_digit(s[0]) &&
+               tpacpi_is_fw_digit(s[1]) &&
+               tpacpi_is_fw_digit(s[2]) &&
+               s[3] == t &&
+               (s[4] == 'T' || s[4] == 'N') &&
+               tpacpi_is_fw_digit(s[5]) &&
+               tpacpi_is_fw_digit(s[6]);
 }
 
 /* returns 0 - probe ok, or < 0 - probe error.
index fc34a71866ed067624c2a851c29a182e9be48f08..dbcb7a8915b84fb8794fd4daea15825e55a49cdd 100644 (file)
@@ -1,11 +1,10 @@
 /*
  *  toshiba_acpi.c - Toshiba Laptop ACPI Extras
  *
- *
  *  Copyright (C) 2002-2004 John Belmonte
  *  Copyright (C) 2008 Philip Langdale
  *  Copyright (C) 2010 Pierre Ducroquet
- *  Copyright (C) 2014 Azael Avalos
+ *  Copyright (C) 2014-2015 Azael Avalos
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  *  GNU General Public License for more details.
  *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
+ *  The full GNU General Public License is included in this distribution in
+ *  the file called "COPYING".
  *
  *  The devolpment page for this driver is located at
  *  http://memebeam.org/toys/ToshibaAcpiDriver.
  *             engineering the Windows drivers
  *     Yasushi Nagato - changes for linux kernel 2.4 -> 2.5
  *     Rob Miller - TV out and hotkeys help
- *
- *
- *  TODO
- *
  */
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
-#define TOSHIBA_ACPI_VERSION   "0.20"
+#define TOSHIBA_ACPI_VERSION   "0.21"
 #define PROC_INTERFACE_VERSION 1
 
 #include <linux/kernel.h>
@@ -57,7 +50,7 @@
 #include <linux/i8042.h>
 #include <linux/acpi.h>
 #include <linux/dmi.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 MODULE_AUTHOR("John Belmonte");
 MODULE_DESCRIPTION("Toshiba Laptop ACPI Extras Driver");
@@ -71,7 +64,8 @@ MODULE_LICENSE("GPL");
 /* Toshiba ACPI method paths */
 #define METHOD_VIDEO_OUT       "\\_SB_.VALX.DSSX"
 
-/* The Toshiba configuration interface is composed of the HCI and the SCI,
+/*
+ * The Toshiba configuration interface is composed of the HCI and the SCI,
  * which are defined as follows:
  *
  * HCI is Toshiba's "Hardware Control Interface" which is supposed to
@@ -108,6 +102,7 @@ MODULE_LICENSE("GPL");
 #define TOS_FIFO_EMPTY                 0x8c00
 #define TOS_DATA_NOT_AVAILABLE         0x8d20
 #define TOS_NOT_INITIALIZED            0x8d50
+#define TOS_NOT_INSTALLED              0x8e00
 
 /* registers */
 #define HCI_FAN                                0x0004
@@ -121,9 +116,14 @@ MODULE_LICENSE("GPL");
 #define HCI_KBD_ILLUMINATION           0x0095
 #define HCI_ECO_MODE                   0x0097
 #define HCI_ACCELEROMETER2             0x00a6
+#define SCI_PANEL_POWER_ON             0x010d
 #define SCI_ILLUMINATION               0x014e
+#define SCI_USB_SLEEP_CHARGE           0x0150
 #define SCI_KBD_ILLUM_STATUS           0x015c
+#define SCI_USB_SLEEP_MUSIC            0x015e
+#define SCI_USB_THREE                  0x0169
 #define SCI_TOUCHPAD                   0x050e
+#define SCI_KBD_FUNCTION_KEYS          0x0522
 
 /* field definitions */
 #define HCI_ACCEL_MASK                 0x7fff
@@ -146,6 +146,15 @@ MODULE_LICENSE("GPL");
 #define SCI_KBD_MODE_ON                        0x8
 #define SCI_KBD_MODE_OFF               0x10
 #define SCI_KBD_TIME_MAX               0x3c001a
+#define SCI_USB_CHARGE_MODE_MASK       0xff
+#define SCI_USB_CHARGE_DISABLED                0x30000
+#define SCI_USB_CHARGE_ALTERNATE       0x30009
+#define SCI_USB_CHARGE_AUTO            0x30021
+#define SCI_USB_CHARGE_BAT_MASK                0x7
+#define SCI_USB_CHARGE_BAT_LVL_OFF     0x1
+#define SCI_USB_CHARGE_BAT_LVL_ON      0x4
+#define SCI_USB_CHARGE_BAT_LVL         0x0200
+#define SCI_USB_CHARGE_RAPID_DSP       0x0300
 
 struct toshiba_acpi_dev {
        struct acpi_device *acpi_dev;
@@ -164,6 +173,7 @@ struct toshiba_acpi_dev {
        int kbd_type;
        int kbd_mode;
        int kbd_time;
+       int usbsc_bat_level;
 
        unsigned int illumination_supported:1;
        unsigned int video_supported:1;
@@ -177,6 +187,12 @@ struct toshiba_acpi_dev {
        unsigned int touchpad_supported:1;
        unsigned int eco_supported:1;
        unsigned int accelerometer_supported:1;
+       unsigned int usb_sleep_charge_supported:1;
+       unsigned int usb_rapid_charge_supported:1;
+       unsigned int usb_sleep_music_supported:1;
+       unsigned int kbd_function_keys_supported:1;
+       unsigned int panel_power_on_supported:1;
+       unsigned int usb_three_supported:1;
        unsigned int sysfs_created:1;
 
        struct mutex mutex;
@@ -264,15 +280,17 @@ static const struct key_entry toshiba_acpi_alt_keymap[] = {
        { KE_END, 0 },
 };
 
-/* utility
+/*
+ * Utility
  */
 
-static __inline__ void _set_bit(u32 * word, u32 mask, int value)
+static inline void _set_bit(u32 *word, u32 mask, int value)
 {
        *word = (*word & ~mask) | (mask * value);
 }
 
-/* acpi interface wrappers
+/*
+ * ACPI interface wrappers
  */
 
 static int write_acpi_int(const char *methodName, int val)
@@ -283,7 +301,8 @@ static int write_acpi_int(const char *methodName, int val)
        return (status == AE_OK) ? 0 : -EIO;
 }
 
-/* Perform a raw configuration call.  Here we don't care about input or output
+/*
+ * Perform a raw configuration call.  Here we don't care about input or output
  * buffer format.
  */
 static acpi_status tci_raw(struct toshiba_acpi_dev *dev,
@@ -310,15 +329,15 @@ static acpi_status tci_raw(struct toshiba_acpi_dev *dev,
                                      (char *)dev->method_hci, &params,
                                      &results);
        if ((status == AE_OK) && (out_objs->package.count <= TCI_WORDS)) {
-               for (i = 0; i < out_objs->package.count; ++i) {
+               for (i = 0; i < out_objs->package.count; ++i)
                        out[i] = out_objs->package.elements[i].integer.value;
-               }
        }
 
        return status;
 }
 
-/* common hci tasks (get or set one or two value)
+/*
+ * Common hci tasks (get or set one or two value)
  *
  * In addition to the ACPI status, the HCI system returns a result which
  * may be useful (such as "not supported").
@@ -338,6 +357,7 @@ static u32 hci_read1(struct toshiba_acpi_dev *dev, u32 reg, u32 *out1)
        u32 in[TCI_WORDS] = { HCI_GET, reg, 0, 0, 0, 0 };
        u32 out[TCI_WORDS];
        acpi_status status = tci_raw(dev, in, out);
+
        if (ACPI_FAILURE(status))
                return TOS_FAILURE;
 
@@ -355,11 +375,13 @@ static u32 hci_write2(struct toshiba_acpi_dev *dev, u32 reg, u32 in1, u32 in2)
        return ACPI_SUCCESS(status) ? out[0] : TOS_FAILURE;
 }
 
-static u32 hci_read2(struct toshiba_acpi_dev *dev, u32 reg, u32 *out1, u32 *out2)
+static u32 hci_read2(struct toshiba_acpi_dev *dev,
+                    u32 reg, u32 *out1, u32 *out2)
 {
        u32 in[TCI_WORDS] = { HCI_GET, reg, *out1, *out2, 0, 0 };
        u32 out[TCI_WORDS];
        acpi_status status = tci_raw(dev, in, out);
+
        if (ACPI_FAILURE(status))
                return TOS_FAILURE;
 
@@ -369,7 +391,8 @@ static u32 hci_read2(struct toshiba_acpi_dev *dev, u32 reg, u32 *out1, u32 *out2
        return out[0];
 }
 
-/* common sci tasks
+/*
+ * Common sci tasks
  */
 
 static int sci_open(struct toshiba_acpi_dev *dev)
@@ -389,6 +412,20 @@ static int sci_open(struct toshiba_acpi_dev *dev)
        } else if (out[0] == TOS_ALREADY_OPEN) {
                pr_info("Toshiba SCI already opened\n");
                return 1;
+       } else if (out[0] == TOS_NOT_SUPPORTED) {
+               /*
+                * Some BIOSes do not have the SCI open/close functions
+                * implemented and return 0x8000 (Not Supported), failing to
+                * register some supported features.
+                *
+                * Simply return 1 if we hit those affected laptops to make the
+                * supported features work.
+                *
+                * In the case that some laptops really do not support the SCI,
+                * all the SCI dependent functions check for TOS_NOT_SUPPORTED,
+                * and thus, not registering support for the queried feature.
+                */
+               return 1;
        } else if (out[0] == TOS_NOT_PRESENT) {
                pr_info("Toshiba SCI is not present\n");
        }
@@ -421,6 +458,7 @@ static u32 sci_read(struct toshiba_acpi_dev *dev, u32 reg, u32 *out1)
        u32 in[TCI_WORDS] = { SCI_GET, reg, 0, 0, 0, 0 };
        u32 out[TCI_WORDS];
        acpi_status status = tci_raw(dev, in, out);
+
        if (ACPI_FAILURE(status))
                return TOS_FAILURE;
 
@@ -529,10 +567,11 @@ static int toshiba_kbd_illum_available(struct toshiba_acpi_dev *dev)
                return 0;
        }
 
-       /* Check for keyboard backlight timeout max value,
+       /*
+        * Check for keyboard backlight timeout max value,
         * previous kbd backlight implementation set this to
         * 0x3c0003, and now the new implementation set this
-        * to 0x3c001a, use this to distinguish between them
+        * to 0x3c001a, use this to distinguish between them.
         */
        if (out[3] == SCI_KBD_TIME_MAX)
                dev->kbd_type = 2;
@@ -667,19 +706,37 @@ static int toshiba_touchpad_get(struct toshiba_acpi_dev *dev, u32 *state)
 static int toshiba_eco_mode_available(struct toshiba_acpi_dev *dev)
 {
        acpi_status status;
-       u32 in[TCI_WORDS] = { HCI_GET, HCI_ECO_MODE, 0, 1, 0, 0 };
+       u32 in[TCI_WORDS] = { HCI_GET, HCI_ECO_MODE, 0, 0, 0, 0 };
        u32 out[TCI_WORDS];
 
        status = tci_raw(dev, in, out);
-       if (ACPI_FAILURE(status) || out[0] == TOS_INPUT_DATA_ERROR) {
-               pr_info("ACPI call to get ECO led failed\n");
-               return 0;
+       if (ACPI_FAILURE(status) || out[0] == TOS_FAILURE) {
+               pr_err("ACPI call to get ECO led failed\n");
+       } else if (out[0] == TOS_NOT_INSTALLED) {
+               pr_info("ECO led not installed");
+       } else if (out[0] == TOS_INPUT_DATA_ERROR) {
+               /*
+                * If we receive 0x8300 (Input Data Error), it means that the
+                * LED device is present, but that we just screwed the input
+                * parameters.
+                *
+                * Let's query the status of the LED to see if we really have a
+                * success response, indicating the actual presense of the LED,
+                * bail out otherwise.
+                */
+               in[3] = 1;
+               status = tci_raw(dev, in, out);
+               if (ACPI_FAILURE(status) || out[0] == TOS_FAILURE)
+                       pr_err("ACPI call to get ECO led failed\n");
+               else if (out[0] == TOS_SUCCESS)
+                       return 1;
        }
 
-       return 1;
+       return 0;
 }
 
-static enum led_brightness toshiba_eco_mode_get_status(struct led_classdev *cdev)
+static enum led_brightness
+toshiba_eco_mode_get_status(struct led_classdev *cdev)
 {
        struct toshiba_acpi_dev *dev = container_of(cdev,
                        struct toshiba_acpi_dev, eco_led);
@@ -721,7 +778,8 @@ static int toshiba_accelerometer_supported(struct toshiba_acpi_dev *dev)
        u32 out[TCI_WORDS];
        acpi_status status;
 
-       /* Check if the accelerometer call exists,
+       /*
+        * Check if the accelerometer call exists,
         * this call also serves as initialization
         */
        status = tci_raw(dev, in, out);
@@ -760,198 +818,533 @@ static int toshiba_accelerometer_get(struct toshiba_acpi_dev *dev,
        return 0;
 }
 
-/* Bluetooth rfkill handlers */
-
-static u32 hci_get_bt_present(struct toshiba_acpi_dev *dev, bool *present)
+/* Sleep (Charge and Music) utilities support */
+static int toshiba_usb_sleep_charge_get(struct toshiba_acpi_dev *dev,
+                                       u32 *mode)
 {
-       u32 hci_result;
-       u32 value, value2;
+       u32 result;
 
-       value = 0;
-       value2 = 0;
-       hci_result = hci_read2(dev, HCI_WIRELESS, &value, &value2);
-       if (hci_result == TOS_SUCCESS)
-               *present = (value & HCI_WIRELESS_BT_PRESENT) ? true : false;
+       if (!sci_open(dev))
+               return -EIO;
 
-       return hci_result;
+       result = sci_read(dev, SCI_USB_SLEEP_CHARGE, mode);
+       sci_close(dev);
+       if (result == TOS_FAILURE) {
+               pr_err("ACPI call to set USB S&C mode failed\n");
+               return -EIO;
+       } else if (result == TOS_NOT_SUPPORTED) {
+               pr_info("USB Sleep and Charge not supported\n");
+               return -ENODEV;
+       } else if (result == TOS_INPUT_DATA_ERROR) {
+               return -EIO;
+       }
+
+       return 0;
 }
 
-static u32 hci_get_radio_state(struct toshiba_acpi_dev *dev, bool *radio_state)
+static int toshiba_usb_sleep_charge_set(struct toshiba_acpi_dev *dev,
+                                       u32 mode)
 {
-       u32 hci_result;
-       u32 value, value2;
+       u32 result;
 
-       value = 0;
-       value2 = 0x0001;
-       hci_result = hci_read2(dev, HCI_WIRELESS, &value, &value2);
+       if (!sci_open(dev))
+               return -EIO;
 
-       *radio_state = value & HCI_WIRELESS_KILL_SWITCH;
-       return hci_result;
+       result = sci_write(dev, SCI_USB_SLEEP_CHARGE, mode);
+       sci_close(dev);
+       if (result == TOS_FAILURE) {
+               pr_err("ACPI call to set USB S&C mode failed\n");
+               return -EIO;
+       } else if (result == TOS_NOT_SUPPORTED) {
+               pr_info("USB Sleep and Charge not supported\n");
+               return -ENODEV;
+       } else if (result == TOS_INPUT_DATA_ERROR) {
+               return -EIO;
+       }
+
+       return 0;
 }
 
-static int bt_rfkill_set_block(void *data, bool blocked)
+static int toshiba_sleep_functions_status_get(struct toshiba_acpi_dev *dev,
+                                             u32 *mode)
 {
-       struct toshiba_acpi_dev *dev = data;
-       u32 result1, result2;
-       u32 value;
-       int err;
-       bool radio_state;
-
-       value = (blocked == false);
+       u32 in[TCI_WORDS] = { SCI_GET, SCI_USB_SLEEP_CHARGE, 0, 0, 0, 0 };
+       u32 out[TCI_WORDS];
+       acpi_status status;
 
-       mutex_lock(&dev->mutex);
-       if (hci_get_radio_state(dev, &radio_state) != TOS_SUCCESS) {
-               err = -EIO;
-               goto out;
-       }
+       if (!sci_open(dev))
+               return -EIO;
 
-       if (!radio_state) {
-               err = 0;
-               goto out;
+       in[5] = SCI_USB_CHARGE_BAT_LVL;
+       status = tci_raw(dev, in, out);
+       sci_close(dev);
+       if (ACPI_FAILURE(status) || out[0] == TOS_FAILURE) {
+               pr_err("ACPI call to get USB S&C battery level failed\n");
+               return -EIO;
+       } else if (out[0] == TOS_NOT_SUPPORTED) {
+               pr_info("USB Sleep and Charge not supported\n");
+               return -ENODEV;
+       } else if (out[0] == TOS_INPUT_DATA_ERROR) {
+               return -EIO;
        }
 
-       result1 = hci_write2(dev, HCI_WIRELESS, value, HCI_WIRELESS_BT_POWER);
-       result2 = hci_write2(dev, HCI_WIRELESS, value, HCI_WIRELESS_BT_ATTACH);
+       *mode = out[2];
 
-       if (result1 != TOS_SUCCESS || result2 != TOS_SUCCESS)
-               err = -EIO;
-       else
-               err = 0;
- out:
-       mutex_unlock(&dev->mutex);
-       return err;
+       return 0;
 }
 
-static void bt_rfkill_poll(struct rfkill *rfkill, void *data)
+static int toshiba_sleep_functions_status_set(struct toshiba_acpi_dev *dev,
+                                             u32 mode)
 {
-       bool new_rfk_state;
-       bool value;
-       u32 hci_result;
-       struct toshiba_acpi_dev *dev = data;
+       u32 in[TCI_WORDS] = { SCI_SET, SCI_USB_SLEEP_CHARGE, 0, 0, 0, 0 };
+       u32 out[TCI_WORDS];
+       acpi_status status;
 
-       mutex_lock(&dev->mutex);
+       if (!sci_open(dev))
+               return -EIO;
 
-       hci_result = hci_get_radio_state(dev, &value);
-       if (hci_result != TOS_SUCCESS) {
-               /* Can't do anything useful */
-               mutex_unlock(&dev->mutex);
-               return;
+       in[2] = mode;
+       in[5] = SCI_USB_CHARGE_BAT_LVL;
+       status = tci_raw(dev, in, out);
+       sci_close(dev);
+       if (ACPI_FAILURE(status) || out[0] == TOS_FAILURE) {
+               pr_err("ACPI call to set USB S&C battery level failed\n");
+               return -EIO;
+       } else if (out[0] == TOS_NOT_SUPPORTED) {
+               pr_info("USB Sleep and Charge not supported\n");
+               return -ENODEV;
+       } else if (out[0] == TOS_INPUT_DATA_ERROR) {
+               return -EIO;
        }
 
-       new_rfk_state = value;
-
-       mutex_unlock(&dev->mutex);
-
-       if (rfkill_set_hw_state(rfkill, !new_rfk_state))
-               bt_rfkill_set_block(data, true);
+       return 0;
 }
 
-static const struct rfkill_ops toshiba_rfk_ops = {
-       .set_block = bt_rfkill_set_block,
-       .poll = bt_rfkill_poll,
-};
-
-static int get_tr_backlight_status(struct toshiba_acpi_dev *dev, bool *enabled)
+static int toshiba_usb_rapid_charge_get(struct toshiba_acpi_dev *dev,
+                                       u32 *state)
 {
-       u32 hci_result;
-       u32 status;
+       u32 in[TCI_WORDS] = { SCI_GET, SCI_USB_SLEEP_CHARGE, 0, 0, 0, 0 };
+       u32 out[TCI_WORDS];
+       acpi_status status;
 
-       hci_result = hci_read1(dev, HCI_TR_BACKLIGHT, &status);
-       *enabled = !status;
-       return hci_result == TOS_SUCCESS ? 0 : -EIO;
-}
+       if (!sci_open(dev))
+               return -EIO;
 
-static int set_tr_backlight_status(struct toshiba_acpi_dev *dev, bool enable)
-{
-       u32 hci_result;
-       u32 value = !enable;
+       in[5] = SCI_USB_CHARGE_RAPID_DSP;
+       status = tci_raw(dev, in, out);
+       sci_close(dev);
+       if (ACPI_FAILURE(status) || out[0] == TOS_FAILURE) {
+               pr_err("ACPI call to get USB S&C battery level failed\n");
+               return -EIO;
+       } else if (out[0] == TOS_NOT_SUPPORTED ||
+                  out[0] == TOS_INPUT_DATA_ERROR) {
+               pr_info("USB Sleep and Charge not supported\n");
+               return -ENODEV;
+       }
 
-       hci_result = hci_write1(dev, HCI_TR_BACKLIGHT, value);
-       return hci_result == TOS_SUCCESS ? 0 : -EIO;
-}
+       *state = out[2];
 
-static struct proc_dir_entry *toshiba_proc_dir /*= 0*/ ;
+       return 0;
+}
 
-static int __get_lcd_brightness(struct toshiba_acpi_dev *dev)
+static int toshiba_usb_rapid_charge_set(struct toshiba_acpi_dev *dev,
+                                       u32 state)
 {
-       u32 hci_result;
-       u32 value;
-       int brightness = 0;
+       u32 in[TCI_WORDS] = { SCI_SET, SCI_USB_SLEEP_CHARGE, 0, 0, 0, 0 };
+       u32 out[TCI_WORDS];
+       acpi_status status;
 
-       if (dev->tr_backlight_supported) {
-               bool enabled;
-               int ret = get_tr_backlight_status(dev, &enabled);
-               if (ret)
-                       return ret;
-               if (enabled)
-                       return 0;
-               brightness++;
-       }
+       if (!sci_open(dev))
+               return -EIO;
 
-       hci_result = hci_read1(dev, HCI_LCD_BRIGHTNESS, &value);
-       if (hci_result == TOS_SUCCESS)
-               return brightness + (value >> HCI_LCD_BRIGHTNESS_SHIFT);
+       in[2] = state;
+       in[5] = SCI_USB_CHARGE_RAPID_DSP;
+       status = tci_raw(dev, in, out);
+       sci_close(dev);
+       if (ACPI_FAILURE(status) || out[0] == TOS_FAILURE) {
+               pr_err("ACPI call to set USB S&C battery level failed\n");
+               return -EIO;
+       } else if (out[0] == TOS_NOT_SUPPORTED) {
+               pr_info("USB Sleep and Charge not supported\n");
+               return -ENODEV;
+       } else if (out[0] == TOS_INPUT_DATA_ERROR) {
+               return -EIO;
+       }
 
-       return -EIO;
+       return 0;
 }
 
-static int get_lcd_brightness(struct backlight_device *bd)
+static int toshiba_usb_sleep_music_get(struct toshiba_acpi_dev *dev, u32 *state)
 {
-       struct toshiba_acpi_dev *dev = bl_get_data(bd);
-       return __get_lcd_brightness(dev);
-}
+       u32 result;
 
-static int lcd_proc_show(struct seq_file *m, void *v)
-{
-       struct toshiba_acpi_dev *dev = m->private;
-       int value;
-       int levels;
+       if (!sci_open(dev))
+               return -EIO;
 
-       if (!dev->backlight_dev)
+       result = sci_read(dev, SCI_USB_SLEEP_MUSIC, state);
+       sci_close(dev);
+       if (result == TOS_FAILURE) {
+               pr_err("ACPI call to set USB S&C mode failed\n");
+               return -EIO;
+       } else if (result == TOS_NOT_SUPPORTED) {
+               pr_info("USB Sleep and Charge not supported\n");
                return -ENODEV;
-
-       levels = dev->backlight_dev->props.max_brightness + 1;
-       value = get_lcd_brightness(dev->backlight_dev);
-       if (value >= 0) {
-               seq_printf(m, "brightness:              %d\n", value);
-               seq_printf(m, "brightness_levels:       %d\n", levels);
-               return 0;
+       } else if (result == TOS_INPUT_DATA_ERROR) {
+               return -EIO;
        }
 
-       pr_err("Error reading LCD brightness\n");
-       return -EIO;
+       return 0;
 }
 
-static int lcd_proc_open(struct inode *inode, struct file *file)
+static int toshiba_usb_sleep_music_set(struct toshiba_acpi_dev *dev, u32 state)
 {
-       return single_open(file, lcd_proc_show, PDE_DATA(inode));
-}
+       u32 result;
 
-static int set_lcd_brightness(struct toshiba_acpi_dev *dev, int value)
-{
-       u32 hci_result;
+       if (!sci_open(dev))
+               return -EIO;
 
-       if (dev->tr_backlight_supported) {
-               bool enable = !value;
-               int ret = set_tr_backlight_status(dev, enable);
-               if (ret)
-                       return ret;
-               if (value)
-                       value--;
+       result = sci_write(dev, SCI_USB_SLEEP_MUSIC, state);
+       sci_close(dev);
+       if (result == TOS_FAILURE) {
+               pr_err("ACPI call to set USB S&C mode failed\n");
+               return -EIO;
+       } else if (result == TOS_NOT_SUPPORTED) {
+               pr_info("USB Sleep and Charge not supported\n");
+               return -ENODEV;
+       } else if (result == TOS_INPUT_DATA_ERROR) {
+               return -EIO;
        }
 
-       value = value << HCI_LCD_BRIGHTNESS_SHIFT;
-       hci_result = hci_write1(dev, HCI_LCD_BRIGHTNESS, value);
-       return hci_result == TOS_SUCCESS ? 0 : -EIO;
+       return 0;
 }
 
-static int set_lcd_status(struct backlight_device *bd)
+/* Keyboard function keys */
+static int toshiba_function_keys_get(struct toshiba_acpi_dev *dev, u32 *mode)
 {
-       struct toshiba_acpi_dev *dev = bl_get_data(bd);
-       return set_lcd_brightness(dev, bd->props.brightness);
-}
+       u32 result;
 
-static ssize_t lcd_proc_write(struct file *file, const char __user *buf,
+       if (!sci_open(dev))
+               return -EIO;
+
+       result = sci_read(dev, SCI_KBD_FUNCTION_KEYS, mode);
+       sci_close(dev);
+       if (result == TOS_FAILURE || result == TOS_INPUT_DATA_ERROR) {
+               pr_err("ACPI call to get KBD function keys failed\n");
+               return -EIO;
+       } else if (result == TOS_NOT_SUPPORTED) {
+               pr_info("KBD function keys not supported\n");
+               return -ENODEV;
+       }
+
+       return 0;
+}
+
+static int toshiba_function_keys_set(struct toshiba_acpi_dev *dev, u32 mode)
+{
+       u32 result;
+
+       if (!sci_open(dev))
+               return -EIO;
+
+       result = sci_write(dev, SCI_KBD_FUNCTION_KEYS, mode);
+       sci_close(dev);
+       if (result == TOS_FAILURE || result == TOS_INPUT_DATA_ERROR) {
+               pr_err("ACPI call to set KBD function keys failed\n");
+               return -EIO;
+       } else if (result == TOS_NOT_SUPPORTED) {
+               pr_info("KBD function keys not supported\n");
+               return -ENODEV;
+       }
+
+       return 0;
+}
+
+/* Panel Power ON */
+static int toshiba_panel_power_on_get(struct toshiba_acpi_dev *dev, u32 *state)
+{
+       u32 result;
+
+       if (!sci_open(dev))
+               return -EIO;
+
+       result = sci_read(dev, SCI_PANEL_POWER_ON, state);
+       sci_close(dev);
+       if (result == TOS_FAILURE) {
+               pr_err("ACPI call to get Panel Power ON failed\n");
+               return -EIO;
+       } else if (result == TOS_NOT_SUPPORTED) {
+               pr_info("Panel Power on not supported\n");
+               return -ENODEV;
+       } else if (result == TOS_INPUT_DATA_ERROR) {
+               return -EIO;
+       }
+
+       return 0;
+}
+
+static int toshiba_panel_power_on_set(struct toshiba_acpi_dev *dev, u32 state)
+{
+       u32 result;
+
+       if (!sci_open(dev))
+               return -EIO;
+
+       result = sci_write(dev, SCI_PANEL_POWER_ON, state);
+       sci_close(dev);
+       if (result == TOS_FAILURE) {
+               pr_err("ACPI call to set Panel Power ON failed\n");
+               return -EIO;
+       } else if (result == TOS_NOT_SUPPORTED) {
+               pr_info("Panel Power ON not supported\n");
+               return -ENODEV;
+       } else if (result == TOS_INPUT_DATA_ERROR) {
+               return -EIO;
+       }
+
+       return 0;
+}
+
+/* USB Three */
+static int toshiba_usb_three_get(struct toshiba_acpi_dev *dev, u32 *state)
+{
+       u32 result;
+
+       if (!sci_open(dev))
+               return -EIO;
+
+       result = sci_read(dev, SCI_USB_THREE, state);
+       sci_close(dev);
+       if (result == TOS_FAILURE) {
+               pr_err("ACPI call to get USB 3 failed\n");
+               return -EIO;
+       } else if (result == TOS_NOT_SUPPORTED) {
+               pr_info("USB 3 not supported\n");
+               return -ENODEV;
+       } else if (result == TOS_INPUT_DATA_ERROR) {
+               return -EIO;
+       }
+
+       return 0;
+}
+
+static int toshiba_usb_three_set(struct toshiba_acpi_dev *dev, u32 state)
+{
+       u32 result;
+
+       if (!sci_open(dev))
+               return -EIO;
+
+       result = sci_write(dev, SCI_USB_THREE, state);
+       sci_close(dev);
+       if (result == TOS_FAILURE) {
+               pr_err("ACPI call to set USB 3 failed\n");
+               return -EIO;
+       } else if (result == TOS_NOT_SUPPORTED) {
+               pr_info("USB 3 not supported\n");
+               return -ENODEV;
+       } else if (result == TOS_INPUT_DATA_ERROR) {
+               return -EIO;
+       }
+
+       return 0;
+}
+
+/* Bluetooth rfkill handlers */
+
+static u32 hci_get_bt_present(struct toshiba_acpi_dev *dev, bool *present)
+{
+       u32 hci_result;
+       u32 value, value2;
+
+       value = 0;
+       value2 = 0;
+       hci_result = hci_read2(dev, HCI_WIRELESS, &value, &value2);
+       if (hci_result == TOS_SUCCESS)
+               *present = (value & HCI_WIRELESS_BT_PRESENT) ? true : false;
+
+       return hci_result;
+}
+
+static u32 hci_get_radio_state(struct toshiba_acpi_dev *dev, bool *radio_state)
+{
+       u32 hci_result;
+       u32 value, value2;
+
+       value = 0;
+       value2 = 0x0001;
+       hci_result = hci_read2(dev, HCI_WIRELESS, &value, &value2);
+
+       *radio_state = value & HCI_WIRELESS_KILL_SWITCH;
+       return hci_result;
+}
+
+static int bt_rfkill_set_block(void *data, bool blocked)
+{
+       struct toshiba_acpi_dev *dev = data;
+       u32 result1, result2;
+       u32 value;
+       int err;
+       bool radio_state;
+
+       value = (blocked == false);
+
+       mutex_lock(&dev->mutex);
+       if (hci_get_radio_state(dev, &radio_state) != TOS_SUCCESS) {
+               err = -EIO;
+               goto out;
+       }
+
+       if (!radio_state) {
+               err = 0;
+               goto out;
+       }
+
+       result1 = hci_write2(dev, HCI_WIRELESS, value, HCI_WIRELESS_BT_POWER);
+       result2 = hci_write2(dev, HCI_WIRELESS, value, HCI_WIRELESS_BT_ATTACH);
+
+       if (result1 != TOS_SUCCESS || result2 != TOS_SUCCESS)
+               err = -EIO;
+       else
+               err = 0;
+ out:
+       mutex_unlock(&dev->mutex);
+       return err;
+}
+
+static void bt_rfkill_poll(struct rfkill *rfkill, void *data)
+{
+       bool new_rfk_state;
+       bool value;
+       u32 hci_result;
+       struct toshiba_acpi_dev *dev = data;
+
+       mutex_lock(&dev->mutex);
+
+       hci_result = hci_get_radio_state(dev, &value);
+       if (hci_result != TOS_SUCCESS) {
+               /* Can't do anything useful */
+               mutex_unlock(&dev->mutex);
+               return;
+       }
+
+       new_rfk_state = value;
+
+       mutex_unlock(&dev->mutex);
+
+       if (rfkill_set_hw_state(rfkill, !new_rfk_state))
+               bt_rfkill_set_block(data, true);
+}
+
+static const struct rfkill_ops toshiba_rfk_ops = {
+       .set_block = bt_rfkill_set_block,
+       .poll = bt_rfkill_poll,
+};
+
+static int get_tr_backlight_status(struct toshiba_acpi_dev *dev, bool *enabled)
+{
+       u32 hci_result;
+       u32 status;
+
+       hci_result = hci_read1(dev, HCI_TR_BACKLIGHT, &status);
+       *enabled = !status;
+       return hci_result == TOS_SUCCESS ? 0 : -EIO;
+}
+
+static int set_tr_backlight_status(struct toshiba_acpi_dev *dev, bool enable)
+{
+       u32 hci_result;
+       u32 value = !enable;
+
+       hci_result = hci_write1(dev, HCI_TR_BACKLIGHT, value);
+       return hci_result == TOS_SUCCESS ? 0 : -EIO;
+}
+
+static struct proc_dir_entry *toshiba_proc_dir /*= 0*/;
+
+static int __get_lcd_brightness(struct toshiba_acpi_dev *dev)
+{
+       u32 hci_result;
+       u32 value;
+       int brightness = 0;
+
+       if (dev->tr_backlight_supported) {
+               bool enabled;
+               int ret = get_tr_backlight_status(dev, &enabled);
+
+               if (ret)
+                       return ret;
+               if (enabled)
+                       return 0;
+               brightness++;
+       }
+
+       hci_result = hci_read1(dev, HCI_LCD_BRIGHTNESS, &value);
+       if (hci_result == TOS_SUCCESS)
+               return brightness + (value >> HCI_LCD_BRIGHTNESS_SHIFT);
+
+       return -EIO;
+}
+
+static int get_lcd_brightness(struct backlight_device *bd)
+{
+       struct toshiba_acpi_dev *dev = bl_get_data(bd);
+
+       return __get_lcd_brightness(dev);
+}
+
+static int lcd_proc_show(struct seq_file *m, void *v)
+{
+       struct toshiba_acpi_dev *dev = m->private;
+       int value;
+       int levels;
+
+       if (!dev->backlight_dev)
+               return -ENODEV;
+
+       levels = dev->backlight_dev->props.max_brightness + 1;
+       value = get_lcd_brightness(dev->backlight_dev);
+       if (value >= 0) {
+               seq_printf(m, "brightness:              %d\n", value);
+               seq_printf(m, "brightness_levels:       %d\n", levels);
+               return 0;
+       }
+
+       pr_err("Error reading LCD brightness\n");
+       return -EIO;
+}
+
+static int lcd_proc_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, lcd_proc_show, PDE_DATA(inode));
+}
+
+static int set_lcd_brightness(struct toshiba_acpi_dev *dev, int value)
+{
+       u32 hci_result;
+
+       if (dev->tr_backlight_supported) {
+               bool enable = !value;
+               int ret = set_tr_backlight_status(dev, enable);
+
+               if (ret)
+                       return ret;
+               if (value)
+                       value--;
+       }
+
+       value = value << HCI_LCD_BRIGHTNESS_SHIFT;
+       hci_result = hci_write1(dev, HCI_LCD_BRIGHTNESS, value);
+       return hci_result == TOS_SUCCESS ? 0 : -EIO;
+}
+
+static int set_lcd_status(struct backlight_device *bd)
+{
+       struct toshiba_acpi_dev *dev = bl_get_data(bd);
+
+       return set_lcd_brightness(dev, bd->props.brightness);
+}
+
+static ssize_t lcd_proc_write(struct file *file, const char __user *buf,
                              size_t count, loff_t *pos)
 {
        struct toshiba_acpi_dev *dev = PDE_DATA(file_inode(file));
@@ -1005,6 +1398,7 @@ static int video_proc_show(struct seq_file *m, void *v)
                int is_lcd = (value & HCI_VIDEO_OUT_LCD) ? 1 : 0;
                int is_crt = (value & HCI_VIDEO_OUT_CRT) ? 1 : 0;
                int is_tv = (value & HCI_VIDEO_OUT_TV) ? 1 : 0;
+
                seq_printf(m, "lcd_out:                 %d\n", is_lcd);
                seq_printf(m, "crt_out:                 %d\n", is_crt);
                seq_printf(m, "tv_out:                  %d\n", is_tv);
@@ -1042,9 +1436,9 @@ static ssize_t video_proc_write(struct file *file, const char __user *buf,
 
        buffer = cmd;
 
-       /* scan expression.  Multiple expressions may be delimited with ;
-        *
-        *  NOTE: to keep scanning simple, invalid fields are ignored
+       /*
+        * Scan expression.  Multiple expressions may be delimited with ;
+        * NOTE: To keep scanning simple, invalid fields are ignored.
         */
        while (remain) {
                if (sscanf(buffer, " lcd_out : %i", &value) == 1)
@@ -1053,12 +1447,11 @@ static ssize_t video_proc_write(struct file *file, const char __user *buf,
                        crt_out = value & 1;
                else if (sscanf(buffer, " tv_out : %i", &value) == 1)
                        tv_out = value & 1;
-               /* advance to one character past the next ; */
+               /* Advance to one character past the next ; */
                do {
                        ++buffer;
                        --remain;
-               }
-               while (remain && *(buffer - 1) != ';');
+               } while (remain && *(buffer - 1) != ';');
        }
 
        kfree(cmd);
@@ -1066,13 +1459,15 @@ static ssize_t video_proc_write(struct file *file, const char __user *buf,
        ret = get_video_status(dev, &video_out);
        if (!ret) {
                unsigned int new_video_out = video_out;
+
                if (lcd_out != -1)
                        _set_bit(&new_video_out, HCI_VIDEO_OUT_LCD, lcd_out);
                if (crt_out != -1)
                        _set_bit(&new_video_out, HCI_VIDEO_OUT_CRT, crt_out);
                if (tv_out != -1)
                        _set_bit(&new_video_out, HCI_VIDEO_OUT_TV, tv_out);
-               /* To avoid unnecessary video disruption, only write the new
+               /*
+                * To avoid unnecessary video disruption, only write the new
                 * video setting if something changed. */
                if (new_video_out != video_out)
                        ret = write_acpi_int(METHOD_VIDEO_OUT, new_video_out);
@@ -1135,10 +1530,10 @@ static ssize_t fan_proc_write(struct file *file, const char __user *buf,
        if (sscanf(cmd, " force_on : %i", &value) == 1 &&
            value >= 0 && value <= 1) {
                hci_result = hci_write1(dev, HCI_FAN, value);
-               if (hci_result != TOS_SUCCESS)
-                       return -EIO;
-               else
+               if (hci_result == TOS_SUCCESS)
                        dev->force_fan = value;
+               else
+                       return -EIO;
        } else {
                return -EINVAL;
        }
@@ -1167,11 +1562,13 @@ static int keys_proc_show(struct seq_file *m, void *v)
                        dev->key_event_valid = 1;
                        dev->last_key_event = value;
                } else if (hci_result == TOS_FIFO_EMPTY) {
-                       /* better luck next time */
+                       /* Better luck next time */
                } else if (hci_result == TOS_NOT_SUPPORTED) {
-                       /* This is a workaround for an unresolved issue on
+                       /*
+                        * This is a workaround for an unresolved issue on
                         * some machines where system events sporadically
-                        * become disabled. */
+                        * become disabled.
+                        */
                        hci_result = hci_write1(dev, HCI_SYSTEM_EVENT, 1);
                        pr_notice("Re-enabled hotkeys\n");
                } else {
@@ -1203,11 +1600,10 @@ static ssize_t keys_proc_write(struct file *file, const char __user *buf,
                return -EFAULT;
        cmd[len] = '\0';
 
-       if (sscanf(cmd, " hotkey_ready : %i", &value) == 1 && value == 0) {
+       if (sscanf(cmd, " hotkey_ready : %i", &value) == 1 && value == 0)
                dev->key_event_valid = 0;
-       } else {
+       else
                return -EINVAL;
-       }
 
        return count;
 }
@@ -1241,7 +1637,8 @@ static const struct file_operations version_proc_fops = {
        .release        = single_release,
 };
 
-/* proc and module init
+/*
+ * Proc and module init
  */
 
 #define PROC_TOSHIBA           "toshiba"
@@ -1286,66 +1683,56 @@ static const struct backlight_ops toshiba_backlight_data = {
 /*
  * Sysfs files
  */
-static ssize_t toshiba_kbd_bl_mode_store(struct device *dev,
-                                        struct device_attribute *attr,
-                                        const char *buf, size_t count);
-static ssize_t toshiba_kbd_bl_mode_show(struct device *dev,
-                                       struct device_attribute *attr,
-                                       char *buf);
-static ssize_t toshiba_kbd_type_show(struct device *dev,
-                                    struct device_attribute *attr,
-                                    char *buf);
-static ssize_t toshiba_available_kbd_modes_show(struct device *dev,
-                                       struct device_attribute *attr,
-                                       char *buf);
-static ssize_t toshiba_kbd_bl_timeout_store(struct device *dev,
-                                           struct device_attribute *attr,
-                                           const char *buf, size_t count);
-static ssize_t toshiba_kbd_bl_timeout_show(struct device *dev,
-                                          struct device_attribute *attr,
-                                          char *buf);
-static ssize_t toshiba_touchpad_store(struct device *dev,
-                                     struct device_attribute *attr,
-                                     const char *buf, size_t count);
-static ssize_t toshiba_touchpad_show(struct device *dev,
-                                    struct device_attribute *attr,
-                                    char *buf);
-static ssize_t toshiba_position_show(struct device *dev,
-                                    struct device_attribute *attr,
-                                    char *buf);
-
-static DEVICE_ATTR(kbd_backlight_mode, S_IRUGO | S_IWUSR,
-                  toshiba_kbd_bl_mode_show, toshiba_kbd_bl_mode_store);
-static DEVICE_ATTR(kbd_type, S_IRUGO, toshiba_kbd_type_show, NULL);
-static DEVICE_ATTR(available_kbd_modes, S_IRUGO,
-                  toshiba_available_kbd_modes_show, NULL);
-static DEVICE_ATTR(kbd_backlight_timeout, S_IRUGO | S_IWUSR,
-                  toshiba_kbd_bl_timeout_show, toshiba_kbd_bl_timeout_store);
-static DEVICE_ATTR(touchpad, S_IRUGO | S_IWUSR,
-                  toshiba_touchpad_show, toshiba_touchpad_store);
-static DEVICE_ATTR(position, S_IRUGO, toshiba_position_show, NULL);
+static ssize_t version_show(struct device *dev,
+                           struct device_attribute *attr, char *buf)
+{
+       return sprintf(buf, "%s\n", TOSHIBA_ACPI_VERSION);
+}
+static DEVICE_ATTR_RO(version);
 
-static struct attribute *toshiba_attributes[] = {
-       &dev_attr_kbd_backlight_mode.attr,
-       &dev_attr_kbd_type.attr,
-       &dev_attr_available_kbd_modes.attr,
-       &dev_attr_kbd_backlight_timeout.attr,
-       &dev_attr_touchpad.attr,
-       &dev_attr_position.attr,
-       NULL,
-};
+static ssize_t fan_store(struct device *dev,
+                        struct device_attribute *attr,
+                        const char *buf, size_t count)
+{
+       struct toshiba_acpi_dev *toshiba = dev_get_drvdata(dev);
+       u32 result;
+       int state;
+       int ret;
+
+       ret = kstrtoint(buf, 0, &state);
+       if (ret)
+               return ret;
+
+       if (state != 0 && state != 1)
+               return -EINVAL;
+
+       result = hci_write1(toshiba, HCI_FAN, state);
+       if (result == TOS_FAILURE)
+               return -EIO;
+       else if (result == TOS_NOT_SUPPORTED)
+               return -ENODEV;
+
+       return count;
+}
+
+static ssize_t fan_show(struct device *dev,
+                       struct device_attribute *attr, char *buf)
+{
+       struct toshiba_acpi_dev *toshiba = dev_get_drvdata(dev);
+       u32 value;
+       int ret;
 
-static umode_t toshiba_sysfs_is_visible(struct kobject *,
-                                       struct attribute *, int);
+       ret = get_fan_status(toshiba, &value);
+       if (ret)
+               return ret;
 
-static struct attribute_group toshiba_attr_group = {
-       .is_visible = toshiba_sysfs_is_visible,
-       .attrs = toshiba_attributes,
-};
+       return sprintf(buf, "%d\n", value);
+}
+static DEVICE_ATTR_RW(fan);
 
-static ssize_t toshiba_kbd_bl_mode_store(struct device *dev,
-                                        struct device_attribute *attr,
-                                        const char *buf, size_t count)
+static ssize_t kbd_backlight_mode_store(struct device *dev,
+                                       struct device_attribute *attr,
+                                       const char *buf, size_t count)
 {
        struct toshiba_acpi_dev *toshiba = dev_get_drvdata(dev);
        int mode;
@@ -1369,7 +1756,8 @@ static ssize_t toshiba_kbd_bl_mode_store(struct device *dev,
                        return -EINVAL;
        }
 
-       /* Set the Keyboard Backlight Mode where:
+       /*
+        * Set the Keyboard Backlight Mode where:
         *      Auto - KBD backlight turns off automatically in given time
         *      FN-Z - KBD backlight "toggles" when hotkey pressed
         *      ON   - KBD backlight is always on
@@ -1400,9 +1788,9 @@ static ssize_t toshiba_kbd_bl_mode_store(struct device *dev,
        return count;
 }
 
-static ssize_t toshiba_kbd_bl_mode_show(struct device *dev,
-                                       struct device_attribute *attr,
-                                       char *buf)
+static ssize_t kbd_backlight_mode_show(struct device *dev,
+                                      struct device_attribute *attr,
+                                      char *buf)
 {
        struct toshiba_acpi_dev *toshiba = dev_get_drvdata(dev);
        u32 time;
@@ -1412,19 +1800,20 @@ static ssize_t toshiba_kbd_bl_mode_show(struct device *dev,
 
        return sprintf(buf, "%i\n", time & SCI_KBD_MODE_MASK);
 }
+static DEVICE_ATTR_RW(kbd_backlight_mode);
 
-static ssize_t toshiba_kbd_type_show(struct device *dev,
-                                    struct device_attribute *attr,
-                                    char *buf)
+static ssize_t kbd_type_show(struct device *dev,
+                            struct device_attribute *attr, char *buf)
 {
        struct toshiba_acpi_dev *toshiba = dev_get_drvdata(dev);
 
        return sprintf(buf, "%d\n", toshiba->kbd_type);
 }
+static DEVICE_ATTR_RO(kbd_type);
 
-static ssize_t toshiba_available_kbd_modes_show(struct device *dev,
-                                               struct device_attribute *attr,
-                                               char *buf)
+static ssize_t available_kbd_modes_show(struct device *dev,
+                                       struct device_attribute *attr,
+                                       char *buf)
 {
        struct toshiba_acpi_dev *toshiba = dev_get_drvdata(dev);
 
@@ -1435,10 +1824,11 @@ static ssize_t toshiba_available_kbd_modes_show(struct device *dev,
        return sprintf(buf, "%x %x %x\n",
                       SCI_KBD_MODE_AUTO, SCI_KBD_MODE_ON, SCI_KBD_MODE_OFF);
 }
+static DEVICE_ATTR_RO(available_kbd_modes);
 
-static ssize_t toshiba_kbd_bl_timeout_store(struct device *dev,
-                                           struct device_attribute *attr,
-                                           const char *buf, size_t count)
+static ssize_t kbd_backlight_timeout_store(struct device *dev,
+                                          struct device_attribute *attr,
+                                          const char *buf, size_t count)
 {
        struct toshiba_acpi_dev *toshiba = dev_get_drvdata(dev);
        int time;
@@ -1479,9 +1869,9 @@ static ssize_t toshiba_kbd_bl_timeout_store(struct device *dev,
        return count;
 }
 
-static ssize_t toshiba_kbd_bl_timeout_show(struct device *dev,
-                                          struct device_attribute *attr,
-                                          char *buf)
+static ssize_t kbd_backlight_timeout_show(struct device *dev,
+                                         struct device_attribute *attr,
+                                         char *buf)
 {
        struct toshiba_acpi_dev *toshiba = dev_get_drvdata(dev);
        u32 time;
@@ -1491,10 +1881,11 @@ static ssize_t toshiba_kbd_bl_timeout_show(struct device *dev,
 
        return sprintf(buf, "%i\n", time >> HCI_MISC_SHIFT);
 }
+static DEVICE_ATTR_RW(kbd_backlight_timeout);
 
-static ssize_t toshiba_touchpad_store(struct device *dev,
-                                     struct device_attribute *attr,
-                                     const char *buf, size_t count)
+static ssize_t touchpad_store(struct device *dev,
+                             struct device_attribute *attr,
+                             const char *buf, size_t count)
 {
        struct toshiba_acpi_dev *toshiba = dev_get_drvdata(dev);
        int state;
@@ -1514,8 +1905,8 @@ static ssize_t toshiba_touchpad_store(struct device *dev,
        return count;
 }
 
-static ssize_t toshiba_touchpad_show(struct device *dev,
-                                    struct device_attribute *attr, char *buf)
+static ssize_t touchpad_show(struct device *dev,
+                            struct device_attribute *attr, char *buf)
 {
        struct toshiba_acpi_dev *toshiba = dev_get_drvdata(dev);
        u32 state;
@@ -1527,9 +1918,10 @@ static ssize_t toshiba_touchpad_show(struct device *dev,
 
        return sprintf(buf, "%i\n", state);
 }
+static DEVICE_ATTR_RW(touchpad);
 
-static ssize_t toshiba_position_show(struct device *dev,
-                                    struct device_attribute *attr, char *buf)
+static ssize_t position_show(struct device *dev,
+                            struct device_attribute *attr, char *buf)
 {
        struct toshiba_acpi_dev *toshiba = dev_get_drvdata(dev);
        u32 xyval, zval, tmp;
@@ -1548,6 +1940,336 @@ static ssize_t toshiba_position_show(struct device *dev,
 
        return sprintf(buf, "%d %d %d\n", x, y, z);
 }
+static DEVICE_ATTR_RO(position);
+
+static ssize_t usb_sleep_charge_show(struct device *dev,
+                                    struct device_attribute *attr, char *buf)
+{
+       struct toshiba_acpi_dev *toshiba = dev_get_drvdata(dev);
+       u32 mode;
+       int ret;
+
+       ret = toshiba_usb_sleep_charge_get(toshiba, &mode);
+       if (ret < 0)
+               return ret;
+
+       return sprintf(buf, "%x\n", mode & SCI_USB_CHARGE_MODE_MASK);
+}
+
+static ssize_t usb_sleep_charge_store(struct device *dev,
+                                     struct device_attribute *attr,
+                                     const char *buf, size_t count)
+{
+       struct toshiba_acpi_dev *toshiba = dev_get_drvdata(dev);
+       u32 mode;
+       int state;
+       int ret;
+
+       ret = kstrtoint(buf, 0, &state);
+       if (ret)
+               return ret;
+       /*
+        * Check for supported values, where:
+        * 0 - Disabled
+        * 1 - Alternate (Non USB conformant devices that require more power)
+        * 2 - Auto (USB conformant devices)
+        */
+       if (state != 0 && state != 1 && state != 2)
+               return -EINVAL;
+
+       /* Set the USB charging mode to internal value */
+       if (state == 0)
+               mode = SCI_USB_CHARGE_DISABLED;
+       else if (state == 1)
+               mode = SCI_USB_CHARGE_ALTERNATE;
+       else if (state == 2)
+               mode = SCI_USB_CHARGE_AUTO;
+
+       ret = toshiba_usb_sleep_charge_set(toshiba, mode);
+       if (ret)
+               return ret;
+
+       return count;
+}
+static DEVICE_ATTR_RW(usb_sleep_charge);
+
+static ssize_t sleep_functions_on_battery_show(struct device *dev,
+                                              struct device_attribute *attr,
+                                              char *buf)
+{
+       struct toshiba_acpi_dev *toshiba = dev_get_drvdata(dev);
+       u32 state;
+       int bat_lvl;
+       int status;
+       int ret;
+       int tmp;
+
+       ret = toshiba_sleep_functions_status_get(toshiba, &state);
+       if (ret < 0)
+               return ret;
+
+       /* Determine the status: 0x4 - Enabled | 0x1 - Disabled */
+       tmp = state & SCI_USB_CHARGE_BAT_MASK;
+       status = (tmp == 0x4) ? 1 : 0;
+       /* Determine the battery level set */
+       bat_lvl = state >> HCI_MISC_SHIFT;
+
+       return sprintf(buf, "%d %d\n", status, bat_lvl);
+}
+
+static ssize_t sleep_functions_on_battery_store(struct device *dev,
+                                               struct device_attribute *attr,
+                                               const char *buf, size_t count)
+{
+       struct toshiba_acpi_dev *toshiba = dev_get_drvdata(dev);
+       u32 status;
+       int value;
+       int ret;
+       int tmp;
+
+       ret = kstrtoint(buf, 0, &value);
+       if (ret)
+               return ret;
+
+       /*
+        * Set the status of the function:
+        * 0 - Disabled
+        * 1-100 - Enabled
+        */
+       if (value < 0 || value > 100)
+               return -EINVAL;
+
+       if (value == 0) {
+               tmp = toshiba->usbsc_bat_level << HCI_MISC_SHIFT;
+               status = tmp | SCI_USB_CHARGE_BAT_LVL_OFF;
+       } else {
+               tmp = value << HCI_MISC_SHIFT;
+               status = tmp | SCI_USB_CHARGE_BAT_LVL_ON;
+       }
+       ret = toshiba_sleep_functions_status_set(toshiba, status);
+       if (ret < 0)
+               return ret;
+
+       toshiba->usbsc_bat_level = status >> HCI_MISC_SHIFT;
+
+       return count;
+}
+static DEVICE_ATTR_RW(sleep_functions_on_battery);
+
+static ssize_t usb_rapid_charge_show(struct device *dev,
+                                    struct device_attribute *attr, char *buf)
+{
+       struct toshiba_acpi_dev *toshiba = dev_get_drvdata(dev);
+       u32 state;
+       int ret;
+
+       ret = toshiba_usb_rapid_charge_get(toshiba, &state);
+       if (ret < 0)
+               return ret;
+
+       return sprintf(buf, "%d\n", state);
+}
+
+static ssize_t usb_rapid_charge_store(struct device *dev,
+                                     struct device_attribute *attr,
+                                     const char *buf, size_t count)
+{
+       struct toshiba_acpi_dev *toshiba = dev_get_drvdata(dev);
+       int state;
+       int ret;
+
+       ret = kstrtoint(buf, 0, &state);
+       if (ret)
+               return ret;
+       if (state != 0 && state != 1)
+               return -EINVAL;
+
+       ret = toshiba_usb_rapid_charge_set(toshiba, state);
+       if (ret)
+               return ret;
+
+       return count;
+}
+static DEVICE_ATTR_RW(usb_rapid_charge);
+
+static ssize_t usb_sleep_music_show(struct device *dev,
+                                   struct device_attribute *attr, char *buf)
+{
+       struct toshiba_acpi_dev *toshiba = dev_get_drvdata(dev);
+       u32 state;
+       int ret;
+
+       ret = toshiba_usb_sleep_music_get(toshiba, &state);
+       if (ret < 0)
+               return ret;
+
+       return sprintf(buf, "%d\n", state);
+}
+
+static ssize_t usb_sleep_music_store(struct device *dev,
+                                    struct device_attribute *attr,
+                                    const char *buf, size_t count)
+{
+       struct toshiba_acpi_dev *toshiba = dev_get_drvdata(dev);
+       int state;
+       int ret;
+
+       ret = kstrtoint(buf, 0, &state);
+       if (ret)
+               return ret;
+       if (state != 0 && state != 1)
+               return -EINVAL;
+
+       ret = toshiba_usb_sleep_music_set(toshiba, state);
+       if (ret)
+               return ret;
+
+       return count;
+}
+static DEVICE_ATTR_RW(usb_sleep_music);
+
+static ssize_t kbd_function_keys_show(struct device *dev,
+                                     struct device_attribute *attr, char *buf)
+{
+       struct toshiba_acpi_dev *toshiba = dev_get_drvdata(dev);
+       int mode;
+       int ret;
+
+       ret = toshiba_function_keys_get(toshiba, &mode);
+       if (ret < 0)
+               return ret;
+
+       return sprintf(buf, "%d\n", mode);
+}
+
+static ssize_t kbd_function_keys_store(struct device *dev,
+                                      struct device_attribute *attr,
+                                      const char *buf, size_t count)
+{
+       struct toshiba_acpi_dev *toshiba = dev_get_drvdata(dev);
+       int mode;
+       int ret;
+
+       ret = kstrtoint(buf, 0, &mode);
+       if (ret)
+               return ret;
+       /*
+        * Check for the function keys mode where:
+        * 0 - Normal operation (F{1-12} as usual and hotkeys via FN-F{1-12})
+        * 1 - Special functions (Opposite of the above setting)
+        */
+       if (mode != 0 && mode != 1)
+               return -EINVAL;
+
+       ret = toshiba_function_keys_set(toshiba, mode);
+       if (ret)
+               return ret;
+
+       pr_info("Reboot for changes to KBD Function Keys to take effect");
+
+       return count;
+}
+static DEVICE_ATTR_RW(kbd_function_keys);
+
+static ssize_t panel_power_on_show(struct device *dev,
+                                  struct device_attribute *attr, char *buf)
+{
+       struct toshiba_acpi_dev *toshiba = dev_get_drvdata(dev);
+       u32 state;
+       int ret;
+
+       ret = toshiba_panel_power_on_get(toshiba, &state);
+       if (ret < 0)
+               return ret;
+
+       return sprintf(buf, "%d\n", state);
+}
+
+static ssize_t panel_power_on_store(struct device *dev,
+                                   struct device_attribute *attr,
+                                   const char *buf, size_t count)
+{
+       struct toshiba_acpi_dev *toshiba = dev_get_drvdata(dev);
+       int state;
+       int ret;
+
+       ret = kstrtoint(buf, 0, &state);
+       if (ret)
+               return ret;
+       if (state != 0 && state != 1)
+               return -EINVAL;
+
+       ret = toshiba_panel_power_on_set(toshiba, state);
+       if (ret)
+               return ret;
+
+       pr_info("Reboot for changes to Panel Power ON to take effect");
+
+       return count;
+}
+static DEVICE_ATTR_RW(panel_power_on);
+
+static ssize_t usb_three_show(struct device *dev,
+                             struct device_attribute *attr, char *buf)
+{
+       struct toshiba_acpi_dev *toshiba = dev_get_drvdata(dev);
+       u32 state;
+       int ret;
+
+       ret = toshiba_usb_three_get(toshiba, &state);
+       if (ret < 0)
+               return ret;
+
+       return sprintf(buf, "%d\n", state);
+}
+
+static ssize_t usb_three_store(struct device *dev,
+                              struct device_attribute *attr,
+                              const char *buf, size_t count)
+{
+       struct toshiba_acpi_dev *toshiba = dev_get_drvdata(dev);
+       int state;
+       int ret;
+
+       ret = kstrtoint(buf, 0, &state);
+       if (ret)
+               return ret;
+       /*
+        * Check for USB 3 mode where:
+        * 0 - Disabled (Acts like a USB 2 port, saving power)
+        * 1 - Enabled
+        */
+       if (state != 0 && state != 1)
+               return -EINVAL;
+
+       ret = toshiba_usb_three_set(toshiba, state);
+       if (ret)
+               return ret;
+
+       pr_info("Reboot for changes to USB 3 to take effect");
+
+       return count;
+}
+static DEVICE_ATTR_RW(usb_three);
+
+static struct attribute *toshiba_attributes[] = {
+       &dev_attr_version.attr,
+       &dev_attr_fan.attr,
+       &dev_attr_kbd_backlight_mode.attr,
+       &dev_attr_kbd_type.attr,
+       &dev_attr_available_kbd_modes.attr,
+       &dev_attr_kbd_backlight_timeout.attr,
+       &dev_attr_touchpad.attr,
+       &dev_attr_position.attr,
+       &dev_attr_usb_sleep_charge.attr,
+       &dev_attr_sleep_functions_on_battery.attr,
+       &dev_attr_usb_rapid_charge.attr,
+       &dev_attr_usb_sleep_music.attr,
+       &dev_attr_kbd_function_keys.attr,
+       &dev_attr_panel_power_on.attr,
+       &dev_attr_usb_three.attr,
+       NULL,
+};
 
 static umode_t toshiba_sysfs_is_visible(struct kobject *kobj,
                                        struct attribute *attr, int idx)
@@ -1556,7 +2278,9 @@ static umode_t toshiba_sysfs_is_visible(struct kobject *kobj,
        struct toshiba_acpi_dev *drv = dev_get_drvdata(dev);
        bool exists = true;
 
-       if (attr == &dev_attr_kbd_backlight_mode.attr)
+       if (attr == &dev_attr_fan.attr)
+               exists = (drv->fan_supported) ? true : false;
+       else if (attr == &dev_attr_kbd_backlight_mode.attr)
                exists = (drv->kbd_illum_supported) ? true : false;
        else if (attr == &dev_attr_kbd_backlight_timeout.attr)
                exists = (drv->kbd_mode == SCI_KBD_MODE_AUTO) ? true : false;
@@ -1564,10 +2288,29 @@ static umode_t toshiba_sysfs_is_visible(struct kobject *kobj,
                exists = (drv->touchpad_supported) ? true : false;
        else if (attr == &dev_attr_position.attr)
                exists = (drv->accelerometer_supported) ? true : false;
+       else if (attr == &dev_attr_usb_sleep_charge.attr)
+               exists = (drv->usb_sleep_charge_supported) ? true : false;
+       else if (attr == &dev_attr_sleep_functions_on_battery.attr)
+               exists = (drv->usb_sleep_charge_supported) ? true : false;
+       else if (attr == &dev_attr_usb_rapid_charge.attr)
+               exists = (drv->usb_rapid_charge_supported) ? true : false;
+       else if (attr == &dev_attr_usb_sleep_music.attr)
+               exists = (drv->usb_sleep_music_supported) ? true : false;
+       else if (attr == &dev_attr_kbd_function_keys.attr)
+               exists = (drv->kbd_function_keys_supported) ? true : false;
+       else if (attr == &dev_attr_panel_power_on.attr)
+               exists = (drv->panel_power_on_supported) ? true : false;
+       else if (attr == &dev_attr_usb_three.attr)
+               exists = (drv->usb_three_supported) ? true : false;
 
        return exists ? attr->mode : 0;
 }
 
+static struct attribute_group toshiba_attr_group = {
+       .is_visible = toshiba_sysfs_is_visible,
+       .attrs = toshiba_attributes,
+};
+
 /*
  * Hotkeys
  */
@@ -1644,7 +2387,7 @@ static void toshiba_acpi_report_hotkey(struct toshiba_acpi_dev *dev,
        if (scancode == 0x100)
                return;
 
-       /* act on key press; ignore key release */
+       /* Act on key press; ignore key release */
        if (scancode & 0x80)
                return;
 
@@ -1680,7 +2423,7 @@ static void toshiba_acpi_process_hotkeys(struct toshiba_acpi_dev *dev)
                                hci_result =
                                        hci_write1(dev, HCI_SYSTEM_EVENT, 1);
                                pr_notice("Re-enabled hotkeys\n");
-                               /* fall through */
+                               /* Fall through */
                        default:
                                retries--;
                                break;
@@ -1802,7 +2545,7 @@ static int toshiba_acpi_setup_backlight(struct toshiba_acpi_dev *dev)
        props.type = BACKLIGHT_PLATFORM;
        props.max_brightness = HCI_LCD_BRIGHTNESS_LEVELS - 1;
 
-       /* adding an extra level and having 0 change to transflective mode */
+       /* Adding an extra level and having 0 change to transflective mode */
        if (dev->tr_backlight_supported)
                props.max_brightness++;
 
@@ -1973,6 +2716,24 @@ static int toshiba_acpi_add(struct acpi_device *acpi_dev)
        ret = toshiba_accelerometer_supported(dev);
        dev->accelerometer_supported = !ret;
 
+       ret = toshiba_usb_sleep_charge_get(dev, &dummy);
+       dev->usb_sleep_charge_supported = !ret;
+
+       ret = toshiba_usb_rapid_charge_get(dev, &dummy);
+       dev->usb_rapid_charge_supported = !ret;
+
+       ret = toshiba_usb_sleep_music_get(dev, &dummy);
+       dev->usb_sleep_music_supported = !ret;
+
+       ret = toshiba_function_keys_get(dev, &dummy);
+       dev->kbd_function_keys_supported = !ret;
+
+       ret = toshiba_panel_power_on_get(dev, &dummy);
+       dev->panel_power_on_supported = !ret;
+
+       ret = toshiba_usb_three_get(dev, &dummy);
+       dev->usb_three_supported = !ret;
+
        /* Determine whether or not BIOS supports fan and video interfaces */
 
        ret = get_video_status(dev, &dummy);