#define HCI_WIRELESS_BT_PRESENT                0x0f
 #define HCI_WIRELESS_BT_ATTACH         0x40
 #define HCI_WIRELESS_BT_POWER          0x80
+#define SCI_KBD_MODE_MASK              0x1f
 #define SCI_KBD_MODE_FNZ               0x1
 #define SCI_KBD_MODE_AUTO              0x2
+#define SCI_KBD_MODE_ON                        0x8
+#define SCI_KBD_MODE_OFF               0x10
+#define SCI_KBD_TIME_MAX               0x3c001a
 
 struct toshiba_acpi_dev {
        struct acpi_device *acpi_dev;
        int force_fan;
        int last_key_event;
        int key_event_valid;
+       int kbd_type;
        int kbd_mode;
        int kbd_time;
 
 }
 
 /* KBD Illumination */
+static int toshiba_kbd_illum_available(struct toshiba_acpi_dev *dev)
+{
+       u32 in[HCI_WORDS] = { SCI_GET, SCI_KBD_ILLUM_STATUS, 0, 0, 0, 0 };
+       u32 out[HCI_WORDS];
+       acpi_status status;
+
+       if (!sci_open(dev))
+               return 0;
+
+       status = hci_raw(dev, in, out);
+       sci_close(dev);
+       if (ACPI_FAILURE(status) || out[0] == SCI_INPUT_DATA_ERROR) {
+               pr_err("ACPI call to query kbd illumination support failed\n");
+               return 0;
+       } else if (out[0] == HCI_NOT_SUPPORTED) {
+               pr_info("Keyboard illumination not available\n");
+               return 0;
+       }
+
+       /* 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
+        */
+       if (out[3] == SCI_KBD_TIME_MAX)
+               dev->kbd_type = 2;
+       else
+               dev->kbd_type = 1;
+       /* Get the current keyboard backlight mode */
+       dev->kbd_mode = out[2] & SCI_KBD_MODE_MASK;
+       /* Get the current time (1-60 seconds) */
+       dev->kbd_time = out[2] >> HCI_MISC_SHIFT;
+
+       return 1;
+}
+
 static int toshiba_kbd_illum_status_set(struct toshiba_acpi_dev *dev, u32 time)
 {
        u32 result;
 /*
  * 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 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 umode_t toshiba_sysfs_is_visible(struct kobject *,
+                                       struct attribute *, int);
+
+static struct attribute_group toshiba_attr_group = {
+       .is_visible = toshiba_sysfs_is_visible,
+       .attrs = toshiba_attributes,
+};
 
 static ssize_t toshiba_kbd_bl_mode_store(struct device *dev,
                                         struct device_attribute *attr,
        ret = kstrtoint(buf, 0, &mode);
        if (ret)
                return ret;
-       if (mode != SCI_KBD_MODE_FNZ && mode != SCI_KBD_MODE_AUTO)
-               return -EINVAL;
+
+       /* Check for supported modes depending on keyboard backlight type */
+       if (toshiba->kbd_type == 1) {
+               /* Type 1 supports SCI_KBD_MODE_FNZ and SCI_KBD_MODE_AUTO */
+               if (mode != SCI_KBD_MODE_FNZ && mode != SCI_KBD_MODE_AUTO)
+                       return -EINVAL;
+       } else if (toshiba->kbd_type == 2) {
+               /* Type 2 doesn't support SCI_KBD_MODE_FNZ */
+               if (mode != SCI_KBD_MODE_AUTO && mode != SCI_KBD_MODE_ON &&
+                   mode != SCI_KBD_MODE_OFF)
+                       return -EINVAL;
+       }
 
        /* Set the Keyboard Backlight Mode where:
-        * Mode - Auto (2) | FN-Z (1)
         *      Auto - KBD backlight turns off automatically in given time
         *      FN-Z - KBD backlight "toggles" when hotkey pressed
+        *      ON   - KBD backlight is always on
+        *      OFF  - KBD backlight is always off
         */
+
+       /* Only make a change if the actual mode has changed */
        if (toshiba->kbd_mode != mode) {
+               /* Shift the time to "base time" (0x3c0000 == 60 seconds) */
                time = toshiba->kbd_time << HCI_MISC_SHIFT;
-               time = time + toshiba->kbd_mode;
+
+               /* OR the "base time" to the actual method format */
+               if (toshiba->kbd_type == 1) {
+                       /* Type 1 requires the current mode */
+                       time |= toshiba->kbd_mode;
+               } else if (toshiba->kbd_type == 2) {
+                       /* Type 2 requires the desired mode */
+                       time |= mode;
+               }
+
                ret = toshiba_kbd_illum_status_set(toshiba, time);
                if (ret)
                        return ret;
+
+               /* Update sysfs entries on successful mode change*/
+               ret = sysfs_update_group(&toshiba->acpi_dev->dev.kobj,
+                                        &toshiba_attr_group);
+               if (ret)
+                       return ret;
+
                toshiba->kbd_mode = mode;
        }
 
        if (toshiba_kbd_illum_status_get(toshiba, &time) < 0)
                return -EIO;
 
-       return sprintf(buf, "%i\n", time & 0x07);
+       return sprintf(buf, "%i\n", time & SCI_KBD_MODE_MASK);
+}
+
+static ssize_t toshiba_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 ssize_t toshiba_available_kbd_modes_show(struct device *dev,
+                                               struct device_attribute *attr,
+                                               char *buf)
+{
+       struct toshiba_acpi_dev *toshiba = dev_get_drvdata(dev);
+
+       if (toshiba->kbd_type == 1)
+               return sprintf(buf, "%x %x\n",
+                              SCI_KBD_MODE_FNZ, SCI_KBD_MODE_AUTO);
+
+       return sprintf(buf, "%x %x %x\n",
+                      SCI_KBD_MODE_AUTO, SCI_KBD_MODE_ON, SCI_KBD_MODE_OFF);
 }
 
 static ssize_t toshiba_kbd_bl_timeout_store(struct device *dev,
        return sprintf(buf, "%d %d %d\n", x, y, z);
 }
 
-static DEVICE_ATTR(kbd_backlight_mode, S_IRUGO | S_IWUSR,
-                  toshiba_kbd_bl_mode_show, toshiba_kbd_bl_mode_store);
-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 struct attribute *toshiba_attributes[] = {
-       &dev_attr_kbd_backlight_mode.attr,
-       &dev_attr_kbd_backlight_timeout.attr,
-       &dev_attr_touchpad.attr,
-       &dev_attr_position.attr,
-       NULL,
-};
-
 static umode_t toshiba_sysfs_is_visible(struct kobject *kobj,
                                        struct attribute *attr, int idx)
 {
        return exists ? attr->mode : 0;
 }
 
-static struct attribute_group toshiba_attr_group = {
-       .is_visible = toshiba_sysfs_is_visible,
-       .attrs = toshiba_attributes,
-};
-
 static bool toshiba_acpi_i8042_filter(unsigned char data, unsigned char str,
                                      struct serio *port)
 {
                        dev->eco_supported = 1;
        }
 
-       ret = toshiba_kbd_illum_status_get(dev, &dummy);
-       if (!ret) {
-               dev->kbd_time = dummy >> HCI_MISC_SHIFT;
-               dev->kbd_mode = dummy & 0x07;
-       }
-       dev->kbd_illum_supported = !ret;
+       dev->kbd_illum_supported = toshiba_kbd_illum_available(dev);
        /*
         * Only register the LED if KBD illumination is supported
         * and the keyboard backlight operation mode is set to FN-Z