]> git.karo-electronics.de Git - mv-sheeva.git/commitdiff
Merge branch 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mjg59/platf...
authorLinus Torvalds <torvalds@linux-foundation.org>
Sat, 27 Feb 2010 01:20:18 +0000 (17:20 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sat, 27 Feb 2010 01:20:18 +0000 (17:20 -0800)
* 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mjg59/platform-drivers-x86:
  toshiba_acpi: Add full hotkey support
  hp-wmi: Add support for tablet rotation key
  dell-laptop: Add another Dell laptop to the DMI whitelist
  classmate-laptop: use a single MODULE_DEVICE_TABLE to get correct aliases
  dell-laptop: Pay attention to which devices the hardware switch controls
  dell-laptop: Use buffer with 32-bit physical address
  dell-laptop: Blacklist machines not supporting dell-laptop
  dell-laptop: Block software state changes when rfkill hard blocked
  dell-laptop: Fix small memory leak
  dell-laptop: Fix platform device unregistration
  dell-laptop: Update rfkill state on kill switch
  compal-laptop: Replace sysfs support with rfkill support
  compal-laptop: Add support for known Compal made Dell laptops
  MAINTAINERS: update drivers/platform/x86 information

MAINTAINERS
drivers/platform/x86/Kconfig
drivers/platform/x86/classmate-laptop.c
drivers/platform/x86/compal-laptop.c
drivers/platform/x86/dell-laptop.c
drivers/platform/x86/hp-wmi.c
drivers/platform/x86/toshiba_acpi.c

index a0491af7b243098d3ca72a4391000cf61ad6215f..2653b44f90dad7beb7bba8a42276482ba114566a 100644 (file)
@@ -221,6 +221,7 @@ F:  drivers/net/acenic*
 
 ACER ASPIRE ONE TEMPERATURE AND FAN DRIVER
 M:     Peter Feuerer <peter@piie.net>
+L:     platform-driver-x86@vger.kernel.org
 W:     http://piie.net/?section=acerhdf
 S:     Maintained
 F:     drivers/platform/x86/acerhdf.c
@@ -228,6 +229,7 @@ F:  drivers/platform/x86/acerhdf.c
 ACER WMI LAPTOP EXTRAS
 M:     Carlos Corbacho <carlos@strangeworlds.co.uk>
 L:     aceracpi@googlegroups.com (subscribers-only)
+L:     platform-driver-x86@vger.kernel.org
 W:     http://code.google.com/p/aceracpi
 S:     Maintained
 F:     drivers/platform/x86/acer-wmi.c
@@ -288,7 +290,7 @@ F:  drivers/acpi/video.c
 
 ACPI WMI DRIVER
 M:     Carlos Corbacho <carlos@strangeworlds.co.uk>
-L:     linux-acpi@vger.kernel.org
+L:     platform-driver-x86@vger.kernel.org
 W:     http://www.lesswatts.org/projects/acpi/
 S:     Maintained
 F:     drivers/platform/x86/wmi.c
@@ -968,6 +970,7 @@ ASUS ACPI EXTRAS DRIVER
 M:     Corentin Chary <corentincj@iksaif.net>
 M:     Karol Kozimor <sziwan@users.sourceforge.net>
 L:     acpi4asus-user@lists.sourceforge.net
+L:     platform-driver-x86@vger.kernel.org
 W:     http://acpi4asus.sf.net
 S:     Maintained
 F:     drivers/platform/x86/asus_acpi.c
@@ -981,6 +984,7 @@ F:  drivers/hwmon/asb100.c
 ASUS LAPTOP EXTRAS DRIVER
 M:     Corentin Chary <corentincj@iksaif.net>
 L:     acpi4asus-user@lists.sourceforge.net
+L:     platform-driver-x86@vger.kernel.org
 W:     http://acpi4asus.sf.net
 S:     Maintained
 F:     drivers/platform/x86/asus-laptop.c
@@ -1473,6 +1477,7 @@ F:        drivers/scsi/fnic/
 CMPC ACPI DRIVER
 M:     Thadeu Lima de Souza Cascardo <cascardo@holoscopio.com>
 M:     Daniel Oliveira Nascimento <don@syst.com.br>
+L:     platform-driver-x86@vger.kernel.org
 S:     Supported
 F:     drivers/platform/x86/classmate-laptop.c
 
@@ -1516,6 +1521,7 @@ F:        drivers/pci/hotplug/cpcihp_generic.c
 
 COMPAL LAPTOP SUPPORT
 M:     Cezary Jackiewicz <cezary.jackiewicz@gmail.com>
+L:     platform-driver-x86@vger.kernel.org
 S:     Maintained
 F:     drivers/platform/x86/compal-laptop.c
 
@@ -1746,6 +1752,7 @@ F:        drivers/net/defxx.*
 
 DELL LAPTOP DRIVER
 M:     Matthew Garrett <mjg59@srcf.ucam.org>
+L:     platform-driver-x86@vger.kernel.org
 S:     Maintained
 F:     drivers/platform/x86/dell-laptop.c
 
@@ -2028,6 +2035,7 @@ F:        drivers/edac/r82600_edac.c
 EEEPC LAPTOP EXTRAS DRIVER
 M:     Corentin Chary <corentincj@iksaif.net>
 L:     acpi4asus-user@lists.sourceforge.net
+L:     platform-driver-x86@vger.kernel.org
 W:     http://acpi4asus.sf.net
 S:     Maintained
 F:     drivers/platform/x86/eeepc-laptop.c
@@ -2306,7 +2314,7 @@ F:        arch/frv/
 
 FUJITSU LAPTOP EXTRAS
 M:     Jonathan Woithe <jwoithe@physics.adelaide.edu.au>
-L:     linux-acpi@vger.kernel.org
+L:     platform-driver-x86@vger.kernel.org
 S:     Maintained
 F:     drivers/platform/x86/fujitsu-laptop.c
 
@@ -2584,6 +2592,7 @@ F:        drivers/net/wireless/hostap/
 
 HP COMPAQ TC1100 TABLET WMI EXTRAS DRIVER
 M:     Carlos Corbacho <carlos@strangeworlds.co.uk>
+L:     platform-driver-x86@vger.kernel.org
 S:     Odd Fixes
 F:     drivers/platform/x86/tc1100-wmi.c
 
@@ -2794,7 +2803,7 @@ F:        drivers/video/i810/
 
 INTEL MENLOW THERMAL DRIVER
 M:     Sujith Thomas <sujith.thomas@intel.com>
-L:     linux-acpi@vger.kernel.org
+L:     platform-driver-x86@vger.kernel.org
 W:     http://www.lesswatts.org/projects/acpi/
 S:     Supported
 F:     drivers/platform/x86/intel_menlow.c
@@ -3660,6 +3669,7 @@ F:        drivers/char/mxser.*
 
 MSI LAPTOP SUPPORT
 M:     Lennart Poettering <mzxreary@0pointer.de>
+L:     platform-driver-x86@vger.kernel.org
 W:     https://tango.0pointer.de/mailman/listinfo/s270-linux
 W:     http://0pointer.de/lennart/tchibo.html
 S:     Maintained
@@ -3667,6 +3677,7 @@ F:        drivers/platform/x86/msi-laptop.c
 
 MSI WMI SUPPORT
 M:     Anisse Astier <anisse@astier.eu>
+L:     platform-driver-x86@vger.kernel.org
 S:     Supported
 F:     drivers/platform/x86/msi-wmi.c
 
@@ -4119,6 +4130,7 @@ F:        drivers/i2c/busses/i2c-pasemi.c
 
 PANASONIC LAPTOP ACPI EXTRAS DRIVER
 M:     Harald Welte <laforge@gnumonks.org>
+L:     platform-driver-x86@vger.kernel.org
 S:     Maintained
 F:     drivers/platform/x86/panasonic-laptop.c
 
@@ -5064,7 +5076,7 @@ F:        include/linux/ssb/
 
 SONY VAIO CONTROL DEVICE DRIVER
 M:     Mattia Dongili <malattia@linux.it>
-L:     linux-acpi@vger.kernel.org
+L:     platform-driver-x86@vger.kernel.org
 W:     http://www.linux.it/~malattia/wiki/index.php/Sony_drivers
 S:     Maintained
 F:     Documentation/laptops/sony-laptop.txt
@@ -5270,6 +5282,7 @@ F:        arch/xtensa/
 THINKPAD ACPI EXTRAS DRIVER
 M:     Henrique de Moraes Holschuh <ibm-acpi@hmh.eng.br>
 L:     ibm-acpi-devel@lists.sourceforge.net
+L:     platform-driver-x86@vger.kernel.org
 W:     http://ibm-acpi.sourceforge.net
 W:     http://thinkwiki.org/wiki/Ibm-acpi
 T:     git git://repo.or.cz/linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git
@@ -5323,10 +5336,12 @@ F:      security/tomoyo/
 
 TOPSTAR LAPTOP EXTRAS DRIVER
 M:     Herton Ronaldo Krzesinski <herton@mandriva.com.br>
+L:     platform-driver-x86@vger.kernel.org
 S:     Maintained
 F:     drivers/platform/x86/topstar-laptop.c
 
 TOSHIBA ACPI EXTRAS DRIVER
+L:     platform-driver-x86@vger.kernel.org
 S:     Orphan
 F:     drivers/platform/x86/toshiba_acpi.c
 
@@ -6054,6 +6069,12 @@ S:       Maintained
 F:     Documentation/x86/
 F:     arch/x86/
 
+X86 PLATFORM DRIVERS
+M:     Matthew Garrett <mjg@redhat.com>
+L:     platform-driver-x86@vger.kernel.org
+S:     Maintained
+F:     drivers/platform/x86
+
 XEN HYPERVISOR INTERFACE
 M:     Jeremy Fitzhardinge <jeremy@xensource.com>
 M:     Chris Wright <chrisw@sous-sol.org>
index f526e735c5abee0dbfc27936f6b5d7dbc1d22f2d..6848f213eb5303f66f2e077907d532fa99e698cc 100644 (file)
@@ -79,6 +79,7 @@ config DELL_LAPTOP
        depends on BACKLIGHT_CLASS_DEVICE
        depends on RFKILL || RFKILL = n
        depends on POWER_SUPPLY
+       depends on SERIO_I8042
        default n
        ---help---
        This driver adds support for rfkill and backlight control to Dell
index ed90082cdf1db82ec7ed9d17782369088590e9b5..8cb20e45bad6b9b8a440255f8affc9e5f42e6bd9 100644 (file)
@@ -34,6 +34,11 @@ struct cmpc_accel {
 #define CMPC_ACCEL_SENSITIVITY_DEFAULT         5
 
 
+#define CMPC_ACCEL_HID         "ACCE0000"
+#define CMPC_TABLET_HID                "TBLT0000"
+#define CMPC_BL_HID            "IPML200"
+#define CMPC_KEYS_HID          "FnBT0000"
+
 /*
  * Generic input device code.
  */
@@ -282,10 +287,9 @@ static int cmpc_accel_remove(struct acpi_device *acpi, int type)
 }
 
 static const struct acpi_device_id cmpc_accel_device_ids[] = {
-       {"ACCE0000", 0},
+       {CMPC_ACCEL_HID, 0},
        {"", 0}
 };
-MODULE_DEVICE_TABLE(acpi, cmpc_accel_device_ids);
 
 static struct acpi_driver cmpc_accel_acpi_driver = {
        .owner = THIS_MODULE,
@@ -366,10 +370,9 @@ static int cmpc_tablet_resume(struct acpi_device *acpi)
 }
 
 static const struct acpi_device_id cmpc_tablet_device_ids[] = {
-       {"TBLT0000", 0},
+       {CMPC_TABLET_HID, 0},
        {"", 0}
 };
-MODULE_DEVICE_TABLE(acpi, cmpc_tablet_device_ids);
 
 static struct acpi_driver cmpc_tablet_acpi_driver = {
        .owner = THIS_MODULE,
@@ -477,17 +480,16 @@ static int cmpc_bl_remove(struct acpi_device *acpi, int type)
        return 0;
 }
 
-static const struct acpi_device_id cmpc_device_ids[] = {
-       {"IPML200", 0},
+static const struct acpi_device_id cmpc_bl_device_ids[] = {
+       {CMPC_BL_HID, 0},
        {"", 0}
 };
-MODULE_DEVICE_TABLE(acpi, cmpc_device_ids);
 
 static struct acpi_driver cmpc_bl_acpi_driver = {
        .owner = THIS_MODULE,
        .name = "cmpc",
        .class = "cmpc",
-       .ids = cmpc_device_ids,
+       .ids = cmpc_bl_device_ids,
        .ops = {
                .add = cmpc_bl_add,
                .remove = cmpc_bl_remove
@@ -540,10 +542,9 @@ static int cmpc_keys_remove(struct acpi_device *acpi, int type)
 }
 
 static const struct acpi_device_id cmpc_keys_device_ids[] = {
-       {"FnBT0000", 0},
+       {CMPC_KEYS_HID, 0},
        {"", 0}
 };
-MODULE_DEVICE_TABLE(acpi, cmpc_keys_device_ids);
 
 static struct acpi_driver cmpc_keys_acpi_driver = {
        .owner = THIS_MODULE,
@@ -607,3 +608,13 @@ static void cmpc_exit(void)
 
 module_init(cmpc_init);
 module_exit(cmpc_exit);
+
+static const struct acpi_device_id cmpc_device_ids[] = {
+       {CMPC_ACCEL_HID, 0},
+       {CMPC_TABLET_HID, 0},
+       {CMPC_BL_HID, 0},
+       {CMPC_KEYS_HID, 0},
+       {"", 0}
+};
+
+MODULE_DEVICE_TABLE(acpi, cmpc_device_ids);
index 1a387e79f71945ac92b6536643ec83ec8398be3e..2740b40aad9b318bbaf289357c197b6294323bf8 100644 (file)
 /*
  * comapl-laptop.c - Compal laptop support.
  *
- * This driver exports a few files in /sys/devices/platform/compal-laptop/:
- *
- *   wlan - wlan subsystem state: contains 0 or 1 (rw)
- *
- *   bluetooth - Bluetooth subsystem state: contains 0 or 1 (rw)
- *
- *   raw - raw value taken from embedded controller register (ro)
- *
- * In addition to these platform device attributes the driver
- * registers itself in the Linux backlight control subsystem and is
- * available to userspace under /sys/class/backlight/compal-laptop/.
+ * The driver registers itself with the rfkill subsystem and
+ * the Linux backlight control subsystem.
  *
  * This driver might work on other laptops produced by Compal. If you
  * want to try it you can pass force=1 as argument to the module which
@@ -51,6 +42,7 @@
 #include <linux/dmi.h>
 #include <linux/backlight.h>
 #include <linux/platform_device.h>
+#include <linux/rfkill.h>
 
 #define COMPAL_DRIVER_VERSION "0.2.6"
 
 #define WLAN_MASK      0x01
 #define BT_MASK        0x02
 
+static struct rfkill *wifi_rfkill;
+static struct rfkill *bt_rfkill;
+static struct platform_device *compal_device;
+
 static int force;
 module_param(force, bool, 0);
 MODULE_PARM_DESC(force, "Force driver load, ignore DMI data");
@@ -88,65 +84,75 @@ static int get_lcd_level(void)
        return (int) result;
 }
 
-static int set_wlan_state(int state)
+static int compal_rfkill_set(void *data, bool blocked)
 {
+       unsigned long radio = (unsigned long) data;
        u8 result, value;
 
        ec_read(COMPAL_EC_COMMAND_WIRELESS, &result);
 
-       if ((result & KILLSWITCH_MASK) == 0)
-               return -EINVAL;
-       else {
-               if (state)
-                       value = (u8) (result | WLAN_MASK);
-               else
-                       value = (u8) (result & ~WLAN_MASK);
-               ec_write(COMPAL_EC_COMMAND_WIRELESS, value);
-       }
+       if (!blocked)
+               value = (u8) (result | radio);
+       else
+               value = (u8) (result & ~radio);
+       ec_write(COMPAL_EC_COMMAND_WIRELESS, value);
 
        return 0;
 }
 
-static int set_bluetooth_state(int state)
+static void compal_rfkill_poll(struct rfkill *rfkill, void *data)
 {
-       u8 result, value;
+       u8 result;
+       bool hw_blocked;
 
        ec_read(COMPAL_EC_COMMAND_WIRELESS, &result);
 
-       if ((result & KILLSWITCH_MASK) == 0)
-               return -EINVAL;
-       else {
-               if (state)
-                       value = (u8) (result | BT_MASK);
-               else
-                       value = (u8) (result & ~BT_MASK);
-               ec_write(COMPAL_EC_COMMAND_WIRELESS, value);
-       }
-
-       return 0;
+       hw_blocked = !(result & KILLSWITCH_MASK);
+       rfkill_set_hw_state(rfkill, hw_blocked);
 }
 
-static int get_wireless_state(int *wlan, int *bluetooth)
+static const struct rfkill_ops compal_rfkill_ops = {
+       .poll = compal_rfkill_poll,
+       .set_block = compal_rfkill_set,
+};
+
+static int setup_rfkill(void)
 {
-       u8 result;
+       int ret;
 
-       ec_read(COMPAL_EC_COMMAND_WIRELESS, &result);
+       wifi_rfkill = rfkill_alloc("compal-wifi", &compal_device->dev,
+                               RFKILL_TYPE_WLAN, &compal_rfkill_ops,
+                               (void *) WLAN_MASK);
+       if (!wifi_rfkill)
+               return -ENOMEM;
 
-       if (wlan) {
-               if ((result & KILLSWITCH_MASK) == 0)
-                       *wlan = 0;
-               else
-                       *wlan = result & WLAN_MASK;
-       }
+       ret = rfkill_register(wifi_rfkill);
+       if (ret)
+               goto err_wifi;
 
-       if (bluetooth) {
-               if ((result & KILLSWITCH_MASK) == 0)
-                       *bluetooth = 0;
-               else
-                       *bluetooth = (result & BT_MASK) >> 1;
+       bt_rfkill = rfkill_alloc("compal-bluetooth", &compal_device->dev,
+                               RFKILL_TYPE_BLUETOOTH, &compal_rfkill_ops,
+                               (void *) BT_MASK);
+       if (!bt_rfkill) {
+               ret = -ENOMEM;
+               goto err_allocate_bt;
        }
+       ret = rfkill_register(bt_rfkill);
+       if (ret)
+               goto err_register_bt;
 
        return 0;
+
+err_register_bt:
+       rfkill_destroy(bt_rfkill);
+
+err_allocate_bt:
+       rfkill_unregister(wifi_rfkill);
+
+err_wifi:
+       rfkill_destroy(wifi_rfkill);
+
+       return ret;
 }
 
 /* Backlight device stuff */
@@ -169,86 +175,6 @@ static struct backlight_ops compalbl_ops = {
 
 static struct backlight_device *compalbl_device;
 
-/* Platform device */
-
-static ssize_t show_wlan(struct device *dev,
-       struct device_attribute *attr, char *buf)
-{
-       int ret, enabled;
-
-       ret = get_wireless_state(&enabled, NULL);
-       if (ret < 0)
-               return ret;
-
-       return sprintf(buf, "%i\n", enabled);
-}
-
-static ssize_t show_raw(struct device *dev,
-       struct device_attribute *attr, char *buf)
-{
-       u8 result;
-
-       ec_read(COMPAL_EC_COMMAND_WIRELESS, &result);
-
-       return sprintf(buf, "%i\n", result);
-}
-
-static ssize_t show_bluetooth(struct device *dev,
-       struct device_attribute *attr, char *buf)
-{
-       int ret, enabled;
-
-       ret = get_wireless_state(NULL, &enabled);
-       if (ret < 0)
-               return ret;
-
-       return sprintf(buf, "%i\n", enabled);
-}
-
-static ssize_t store_wlan_state(struct device *dev,
-       struct device_attribute *attr, const char *buf, size_t count)
-{
-       int state, ret;
-
-       if (sscanf(buf, "%i", &state) != 1 || (state < 0 || state > 1))
-               return -EINVAL;
-
-       ret = set_wlan_state(state);
-       if (ret < 0)
-               return ret;
-
-       return count;
-}
-
-static ssize_t store_bluetooth_state(struct device *dev,
-       struct device_attribute *attr, const char *buf, size_t count)
-{
-       int state, ret;
-
-       if (sscanf(buf, "%i", &state) != 1 || (state < 0 || state > 1))
-               return -EINVAL;
-
-       ret = set_bluetooth_state(state);
-       if (ret < 0)
-               return ret;
-
-       return count;
-}
-
-static DEVICE_ATTR(bluetooth, 0644, show_bluetooth, store_bluetooth_state);
-static DEVICE_ATTR(wlan, 0644, show_wlan, store_wlan_state);
-static DEVICE_ATTR(raw, 0444, show_raw, NULL);
-
-static struct attribute *compal_attributes[] = {
-       &dev_attr_bluetooth.attr,
-       &dev_attr_wlan.attr,
-       &dev_attr_raw.attr,
-       NULL
-};
-
-static struct attribute_group compal_attribute_group = {
-       .attrs = compal_attributes
-};
 
 static struct platform_driver compal_driver = {
        .driver = {
@@ -257,8 +183,6 @@ static struct platform_driver compal_driver = {
        }
 };
 
-static struct platform_device *compal_device;
-
 /* Initialization */
 
 static int dmi_check_cb(const struct dmi_system_id *id)
@@ -310,6 +234,47 @@ static struct dmi_system_id __initdata compal_dmi_table[] = {
                },
                .callback = dmi_check_cb
        },
+       {
+               .ident = "Dell Mini 9",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 910"),
+               },
+               .callback = dmi_check_cb
+       },
+       {
+               .ident = "Dell Mini 10",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 1010"),
+               },
+               .callback = dmi_check_cb
+       },
+       {
+               .ident = "Dell Mini 10v",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 1011"),
+               },
+               .callback = dmi_check_cb
+       },
+       {
+               .ident = "Dell Inspiron 11z",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 1110"),
+               },
+               .callback = dmi_check_cb
+       },
+       {
+               .ident = "Dell Mini 12",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 1210"),
+               },
+               .callback = dmi_check_cb
+       },
+
        { }
 };
 
@@ -348,23 +313,21 @@ static int __init compal_init(void)
 
        ret = platform_device_add(compal_device);
        if (ret)
-               goto fail_platform_device1;
+               goto fail_platform_device;
 
-       ret = sysfs_create_group(&compal_device->dev.kobj,
-               &compal_attribute_group);
+       ret = setup_rfkill();
        if (ret)
-               goto fail_platform_device2;
+               goto fail_rfkill;
 
        printk(KERN_INFO "compal-laptop: driver "COMPAL_DRIVER_VERSION
                " successfully loaded.\n");
 
        return 0;
 
-fail_platform_device2:
-
+fail_rfkill:
        platform_device_del(compal_device);
 
-fail_platform_device1:
+fail_platform_device:
 
        platform_device_put(compal_device);
 
@@ -382,10 +345,13 @@ fail_backlight:
 static void __exit compal_cleanup(void)
 {
 
-       sysfs_remove_group(&compal_device->dev.kobj, &compal_attribute_group);
        platform_device_unregister(compal_device);
        platform_driver_unregister(&compal_driver);
        backlight_device_unregister(compalbl_device);
+       rfkill_unregister(wifi_rfkill);
+       rfkill_destroy(wifi_rfkill);
+       rfkill_unregister(bt_rfkill);
+       rfkill_destroy(bt_rfkill);
 
        printk(KERN_INFO "compal-laptop: driver unloaded.\n");
 }
@@ -403,3 +369,8 @@ MODULE_ALIAS("dmi:*:rnIFL90:rvrREFERENCE:*");
 MODULE_ALIAS("dmi:*:rnIFL91:rvrIFT00:*");
 MODULE_ALIAS("dmi:*:rnJFL92:rvrIFT00:*");
 MODULE_ALIAS("dmi:*:rnIFT00:rvrIFT00:*");
+MODULE_ALIAS("dmi:*:svnDellInc.:pnInspiron910:*");
+MODULE_ALIAS("dmi:*:svnDellInc.:pnInspiron1010:*");
+MODULE_ALIAS("dmi:*:svnDellInc.:pnInspiron1011:*");
+MODULE_ALIAS("dmi:*:svnDellInc.:pnInspiron1110:*");
+MODULE_ALIAS("dmi:*:svnDellInc.:pnInspiron1210:*");
index 3780994dc8f2a533795397cce09aba310d950b0a..b7f4d27059160a3343cdd77a5e1592589f3032a5 100644 (file)
@@ -22,6 +22,8 @@
 #include <linux/rfkill.h>
 #include <linux/power_supply.h>
 #include <linux/acpi.h>
+#include <linux/mm.h>
+#include <linux/i8042.h>
 #include "../../firmware/dcdbas.h"
 
 #define BRIGHTNESS_TOKEN 0x7d
@@ -79,9 +81,73 @@ static const struct dmi_system_id __initdata dell_device_table[] = {
                        DMI_MATCH(DMI_CHASSIS_TYPE, "8"),
                },
        },
+       {
+               .ident = "Dell Computer Corporation",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
+                       DMI_MATCH(DMI_CHASSIS_TYPE, "8"),
+               },
+       },
        { }
 };
 
+static struct dmi_system_id __devinitdata dell_blacklist[] = {
+       /* Supported by compal-laptop */
+       {
+               .ident = "Dell Mini 9",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 910"),
+               },
+       },
+       {
+               .ident = "Dell Mini 10",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 1010"),
+               },
+       },
+       {
+               .ident = "Dell Mini 10v",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 1011"),
+               },
+       },
+       {
+               .ident = "Dell Inspiron 11z",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 1110"),
+               },
+       },
+       {
+               .ident = "Dell Mini 12",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 1210"),
+               },
+       },
+       {}
+};
+
+static struct calling_interface_buffer *buffer;
+struct page *bufferpage;
+DEFINE_MUTEX(buffer_mutex);
+
+static int hwswitch_state;
+
+static void get_buffer(void)
+{
+       mutex_lock(&buffer_mutex);
+       memset(buffer, 0, sizeof(struct calling_interface_buffer));
+}
+
+static void release_buffer(void)
+{
+       mutex_unlock(&buffer_mutex);
+}
+
 static void __init parse_da_table(const struct dmi_header *dm)
 {
        /* Final token is a terminator, so we don't want to copy it */
@@ -160,6 +226,8 @@ dell_send_request(struct calling_interface_buffer *buffer, int class,
 /* Derived from information in DellWirelessCtl.cpp:
    Class 17, select 11 is radio control. It returns an array of 32-bit values.
 
+   Input byte 0 = 0: Wireless information
+
    result[0]: return code
    result[1]:
      Bit 0:      Hardware switch supported
@@ -180,33 +248,62 @@ dell_send_request(struct calling_interface_buffer *buffer, int class,
      Bits 20-31: Reserved
    result[2]: NVRAM size in bytes
    result[3]: NVRAM format version number
+
+   Input byte 0 = 2: Wireless switch configuration
+   result[0]: return code
+   result[1]:
+     Bit 0:      Wifi controlled by switch
+     Bit 1:      Bluetooth controlled by switch
+     Bit 2:      WWAN controlled by switch
+     Bits 3-6:   Reserved
+     Bit 7:      Wireless switch config locked
+     Bit 8:      Wifi locator enabled
+     Bits 9-14:  Reserved
+     Bit 15:     Wifi locator setting locked
+     Bits 16-31: Reserved
 */
 
 static int dell_rfkill_set(void *data, bool blocked)
 {
-       struct calling_interface_buffer buffer;
        int disable = blocked ? 1 : 0;
        unsigned long radio = (unsigned long)data;
+       int hwswitch_bit = (unsigned long)data - 1;
+       int ret = 0;
+
+       get_buffer();
+       dell_send_request(buffer, 17, 11);
+
+       /* If the hardware switch controls this radio, and the hardware
+          switch is disabled, don't allow changing the software state */
+       if ((hwswitch_state & BIT(hwswitch_bit)) &&
+           !(buffer->output[1] & BIT(16))) {
+               ret = -EINVAL;
+               goto out;
+       }
 
-       memset(&buffer, 0, sizeof(struct calling_interface_buffer));
-       buffer.input[0] = (1 | (radio<<8) | (disable << 16));
-       dell_send_request(&buffer, 17, 11);
+       buffer->input[0] = (1 | (radio<<8) | (disable << 16));
+       dell_send_request(buffer, 17, 11);
 
-       return 0;
+out:
+       release_buffer();
+       return ret;
 }
 
 static void dell_rfkill_query(struct rfkill *rfkill, void *data)
 {
-       struct calling_interface_buffer buffer;
        int status;
        int bit = (unsigned long)data + 16;
+       int hwswitch_bit = (unsigned long)data - 1;
 
-       memset(&buffer, 0, sizeof(struct calling_interface_buffer));
-       dell_send_request(&buffer, 17, 11);
-       status = buffer.output[1];
+       get_buffer();
+       dell_send_request(buffer, 17, 11);
+       status = buffer->output[1];
+       release_buffer();
 
        rfkill_set_sw_state(rfkill, !!(status & BIT(bit)));
-       rfkill_set_hw_state(rfkill, !(status & BIT(16)));
+
+       if (hwswitch_state & (BIT(hwswitch_bit)))
+               rfkill_set_hw_state(rfkill, !(status & BIT(16)));
 }
 
 static const struct rfkill_ops dell_rfkill_ops = {
@@ -214,15 +311,36 @@ static const struct rfkill_ops dell_rfkill_ops = {
        .query = dell_rfkill_query,
 };
 
+static void dell_update_rfkill(struct work_struct *ignored)
+{
+       if (wifi_rfkill)
+               dell_rfkill_query(wifi_rfkill, (void *)1);
+       if (bluetooth_rfkill)
+               dell_rfkill_query(bluetooth_rfkill, (void *)2);
+       if (wwan_rfkill)
+               dell_rfkill_query(wwan_rfkill, (void *)3);
+}
+static DECLARE_DELAYED_WORK(dell_rfkill_work, dell_update_rfkill);
+
+
 static int __init dell_setup_rfkill(void)
 {
-       struct calling_interface_buffer buffer;
        int status;
        int ret;
 
-       memset(&buffer, 0, sizeof(struct calling_interface_buffer));
-       dell_send_request(&buffer, 17, 11);
-       status = buffer.output[1];
+       if (dmi_check_system(dell_blacklist)) {
+               printk(KERN_INFO "dell-laptop: Blacklisted hardware detected - "
+                               "not enabling rfkill\n");
+               return 0;
+       }
+
+       get_buffer();
+       dell_send_request(buffer, 17, 11);
+       status = buffer->output[1];
+       buffer->input[0] = 0x2;
+       dell_send_request(buffer, 17, 11);
+       hwswitch_state = buffer->output[1];
+       release_buffer();
 
        if ((status & (1<<2|1<<8)) == (1<<2|1<<8)) {
                wifi_rfkill = rfkill_alloc("dell-wifi", &platform_device->dev,
@@ -298,39 +416,49 @@ static void dell_cleanup_rfkill(void)
 
 static int dell_send_intensity(struct backlight_device *bd)
 {
-       struct calling_interface_buffer buffer;
+       int ret = 0;
 
-       memset(&buffer, 0, sizeof(struct calling_interface_buffer));
-       buffer.input[0] = find_token_location(BRIGHTNESS_TOKEN);
-       buffer.input[1] = bd->props.brightness;
+       get_buffer();
+       buffer->input[0] = find_token_location(BRIGHTNESS_TOKEN);
+       buffer->input[1] = bd->props.brightness;
 
-       if (buffer.input[0] == -1)
-               return -ENODEV;
+       if (buffer->input[0] == -1) {
+               ret = -ENODEV;
+               goto out;
+       }
 
        if (power_supply_is_system_supplied() > 0)
-               dell_send_request(&buffer, 1, 2);
+               dell_send_request(buffer, 1, 2);
        else
-               dell_send_request(&buffer, 1, 1);
+               dell_send_request(buffer, 1, 1);
 
+out:
+       release_buffer();
        return 0;
 }
 
 static int dell_get_intensity(struct backlight_device *bd)
 {
-       struct calling_interface_buffer buffer;
+       int ret = 0;
 
-       memset(&buffer, 0, sizeof(struct calling_interface_buffer));
-       buffer.input[0] = find_token_location(BRIGHTNESS_TOKEN);
+       get_buffer();
+       buffer->input[0] = find_token_location(BRIGHTNESS_TOKEN);
 
-       if (buffer.input[0] == -1)
-               return -ENODEV;
+       if (buffer->input[0] == -1) {
+               ret = -ENODEV;
+               goto out;
+       }
 
        if (power_supply_is_system_supplied() > 0)
-               dell_send_request(&buffer, 0, 2);
+               dell_send_request(buffer, 0, 2);
        else
-               dell_send_request(&buffer, 0, 1);
+               dell_send_request(buffer, 0, 1);
 
-       return buffer.output[1];
+out:
+       release_buffer();
+       if (ret)
+               return ret;
+       return buffer->output[1];
 }
 
 static struct backlight_ops dell_ops = {
@@ -338,9 +466,32 @@ static struct backlight_ops dell_ops = {
        .update_status  = dell_send_intensity,
 };
 
+bool dell_laptop_i8042_filter(unsigned char data, unsigned char str,
+                             struct serio *port)
+{
+       static bool extended;
+
+       if (str & 0x20)
+               return false;
+
+       if (unlikely(data == 0xe0)) {
+               extended = true;
+               return false;
+       } else if (unlikely(extended)) {
+               switch (data) {
+               case 0x8:
+                       schedule_delayed_work(&dell_rfkill_work,
+                                             round_jiffies_relative(HZ));
+                       break;
+               }
+               extended = false;
+       }
+
+       return false;
+}
+
 static int __init dell_init(void)
 {
-       struct calling_interface_buffer buffer;
        int max_intensity = 0;
        int ret;
 
@@ -366,6 +517,17 @@ static int __init dell_init(void)
        if (ret)
                goto fail_platform_device2;
 
+       /*
+        * Allocate buffer below 4GB for SMI data--only 32-bit physical addr
+        * is passed to SMI handler.
+        */
+       bufferpage = alloc_page(GFP_KERNEL | GFP_DMA32);
+
+       if (!bufferpage)
+               goto fail_buffer;
+       buffer = page_address(bufferpage);
+       mutex_init(&buffer_mutex);
+
        ret = dell_setup_rfkill();
 
        if (ret) {
@@ -373,6 +535,13 @@ static int __init dell_init(void)
                goto fail_rfkill;
        }
 
+       ret = i8042_install_filter(dell_laptop_i8042_filter);
+       if (ret) {
+               printk(KERN_WARNING
+                      "dell-laptop: Unable to install key filter\n");
+               goto fail_filter;
+       }
+
 #ifdef CONFIG_ACPI
        /* In the event of an ACPI backlight being available, don't
         * register the platform controller.
@@ -381,13 +550,13 @@ static int __init dell_init(void)
                return 0;
 #endif
 
-       memset(&buffer, 0, sizeof(struct calling_interface_buffer));
-       buffer.input[0] = find_token_location(BRIGHTNESS_TOKEN);
-
-       if (buffer.input[0] != -1) {
-               dell_send_request(&buffer, 0, 2);
-               max_intensity = buffer.output[3];
+       get_buffer();
+       buffer->input[0] = find_token_location(BRIGHTNESS_TOKEN);
+       if (buffer->input[0] != -1) {
+               dell_send_request(buffer, 0, 2);
+               max_intensity = buffer->output[3];
        }
+       release_buffer();
 
        if (max_intensity) {
                dell_backlight_device = backlight_device_register(
@@ -410,8 +579,12 @@ static int __init dell_init(void)
        return 0;
 
 fail_backlight:
+       i8042_remove_filter(dell_laptop_i8042_filter);
+fail_filter:
        dell_cleanup_rfkill();
 fail_rfkill:
+       free_page((unsigned long)bufferpage);
+fail_buffer:
        platform_device_del(platform_device);
 fail_platform_device2:
        platform_device_put(platform_device);
@@ -424,8 +597,16 @@ fail_platform_driver:
 
 static void __exit dell_exit(void)
 {
+       cancel_delayed_work_sync(&dell_rfkill_work);
+       i8042_remove_filter(dell_laptop_i8042_filter);
        backlight_device_unregister(dell_backlight_device);
        dell_cleanup_rfkill();
+       if (platform_device) {
+               platform_device_del(platform_device);
+               platform_driver_unregister(&platform_driver);
+       }
+       kfree(da_tokens);
+       free_page((unsigned long)buffer);
 }
 
 module_init(dell_init);
@@ -435,3 +616,4 @@ MODULE_AUTHOR("Matthew Garrett <mjg@redhat.com>");
 MODULE_DESCRIPTION("Dell laptop driver");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS("dmi:*svnDellInc.:*:ct8:*");
+MODULE_ALIAS("dmi:*svnDellComputerCorporation.:*:ct8:*");
index ad4c414dbfbcd1e056fa26c7010fb03d975edf87..3aa57da8b43ba4f09b0523908f46cd903d1518b4 100644 (file)
@@ -89,6 +89,7 @@ static struct key_entry hp_wmi_keymap[] = {
        {KE_KEY, 0x20e6, KEY_PROG1},
        {KE_KEY, 0x2142, KEY_MEDIA},
        {KE_KEY, 0x213b, KEY_INFO},
+       {KE_KEY, 0x2169, KEY_DIRECTION},
        {KE_KEY, 0x231b, KEY_HELP},
        {KE_END, 0}
 };
index 77bf5d8f893aae8368f3ae6253c9f5c98e4d86a9..26c211724acf7cb2374f46a7ddfcdeabe6e3a1d0 100644 (file)
@@ -46,6 +46,7 @@
 #include <linux/backlight.h>
 #include <linux/platform_device.h>
 #include <linux/rfkill.h>
+#include <linux/input.h>
 
 #include <asm/uaccess.h>
 
@@ -62,9 +63,10 @@ MODULE_LICENSE("GPL");
 
 /* Toshiba ACPI method paths */
 #define METHOD_LCD_BRIGHTNESS  "\\_SB_.PCI0.VGA_.LCD_._BCM"
-#define METHOD_HCI_1           "\\_SB_.VALD.GHCI"
-#define METHOD_HCI_2           "\\_SB_.VALZ.GHCI"
+#define TOSH_INTERFACE_1       "\\_SB_.VALD"
+#define TOSH_INTERFACE_2       "\\_SB_.VALZ"
 #define METHOD_VIDEO_OUT       "\\_SB_.VALX.DSSX"
+#define GHCI_METHOD            ".GHCI"
 
 /* Toshiba HCI interface definitions
  *
@@ -116,6 +118,36 @@ static const struct acpi_device_id toshiba_device_ids[] = {
 };
 MODULE_DEVICE_TABLE(acpi, toshiba_device_ids);
 
+struct key_entry {
+       char type;
+       u16 code;
+       u16 keycode;
+};
+
+enum {KE_KEY, KE_END};
+
+static struct key_entry toshiba_acpi_keymap[]  = {
+       {KE_KEY, 0x101, KEY_MUTE},
+       {KE_KEY, 0x13b, KEY_COFFEE},
+       {KE_KEY, 0x13c, KEY_BATTERY},
+       {KE_KEY, 0x13d, KEY_SLEEP},
+       {KE_KEY, 0x13e, KEY_SUSPEND},
+       {KE_KEY, 0x13f, KEY_SWITCHVIDEOMODE},
+       {KE_KEY, 0x140, KEY_BRIGHTNESSDOWN},
+       {KE_KEY, 0x141, KEY_BRIGHTNESSUP},
+       {KE_KEY, 0x142, KEY_WLAN},
+       {KE_KEY, 0x143, KEY_PROG1},
+       {KE_KEY, 0xb05, KEY_PROG2},
+       {KE_KEY, 0xb06, KEY_WWW},
+       {KE_KEY, 0xb07, KEY_MAIL},
+       {KE_KEY, 0xb30, KEY_STOP},
+       {KE_KEY, 0xb31, KEY_PREVIOUSSONG},
+       {KE_KEY, 0xb32, KEY_NEXTSONG},
+       {KE_KEY, 0xb33, KEY_PLAYPAUSE},
+       {KE_KEY, 0xb5a, KEY_MEDIA},
+       {KE_END, 0, 0},
+};
+
 /* utility
  */
 
@@ -251,6 +283,8 @@ static acpi_status hci_read2(u32 reg, u32 *out1, u32 *out2, u32 *result)
 struct toshiba_acpi_dev {
        struct platform_device *p_dev;
        struct rfkill *bt_rfk;
+       struct input_dev *hotkey_dev;
+       acpi_handle handle;
 
        const char *bt_name;
 
@@ -711,8 +745,159 @@ static struct backlight_ops toshiba_backlight_data = {
         .update_status  = set_lcd_status,
 };
 
+static struct key_entry *toshiba_acpi_get_entry_by_scancode(int code)
+{
+       struct key_entry *key;
+
+       for (key = toshiba_acpi_keymap; key->type != KE_END; key++)
+               if (code == key->code)
+                       return key;
+
+       return NULL;
+}
+
+static struct key_entry *toshiba_acpi_get_entry_by_keycode(int code)
+{
+       struct key_entry *key;
+
+       for (key = toshiba_acpi_keymap; key->type != KE_END; key++)
+               if (code == key->keycode && key->type == KE_KEY)
+                       return key;
+
+       return NULL;
+}
+
+static int toshiba_acpi_getkeycode(struct input_dev *dev, int scancode,
+                                  int *keycode)
+{
+       struct key_entry *key = toshiba_acpi_get_entry_by_scancode(scancode);
+
+       if (key && key->type == KE_KEY) {
+               *keycode = key->keycode;
+               return 0;
+       }
+
+       return -EINVAL;
+}
+
+static int toshiba_acpi_setkeycode(struct input_dev *dev, int scancode,
+                                  int keycode)
+{
+       struct key_entry *key;
+       int old_keycode;
+
+       if (keycode < 0 || keycode > KEY_MAX)
+               return -EINVAL;
+
+       key = toshiba_acpi_get_entry_by_scancode(scancode);
+       if (key && key->type == KE_KEY) {
+               old_keycode = key->keycode;
+               key->keycode = keycode;
+               set_bit(keycode, dev->keybit);
+               if (!toshiba_acpi_get_entry_by_keycode(old_keycode))
+                       clear_bit(old_keycode, dev->keybit);
+               return 0;
+       }
+
+       return -EINVAL;
+}
+
+static void toshiba_acpi_notify(acpi_handle handle, u32 event, void *context)
+{
+       u32 hci_result, value;
+       struct key_entry *key;
+
+       if (event != 0x80)
+               return;
+       do {
+               hci_read1(HCI_SYSTEM_EVENT, &value, &hci_result);
+               if (hci_result == HCI_SUCCESS) {
+                       if (value == 0x100)
+                               continue;
+                       else if (value & 0x80) {
+                               key = toshiba_acpi_get_entry_by_scancode
+                                       (value & ~0x80);
+                               if (!key) {
+                                       printk(MY_INFO "Unknown key %x\n",
+                                              value & ~0x80);
+                                       continue;
+                               }
+                               input_report_key(toshiba_acpi.hotkey_dev,
+                                                key->keycode, 1);
+                               input_sync(toshiba_acpi.hotkey_dev);
+                               input_report_key(toshiba_acpi.hotkey_dev,
+                                                key->keycode, 0);
+                               input_sync(toshiba_acpi.hotkey_dev);
+                       }
+               } else if (hci_result == HCI_NOT_SUPPORTED) {
+                       /* This is a workaround for an unresolved issue on
+                        * some machines where system events sporadically
+                        * become disabled. */
+                       hci_write1(HCI_SYSTEM_EVENT, 1, &hci_result);
+                       printk(MY_NOTICE "Re-enabled hotkeys\n");
+               }
+       } while (hci_result != HCI_EMPTY);
+}
+
+static int toshiba_acpi_setup_keyboard(char *device)
+{
+       acpi_status status;
+       acpi_handle handle;
+       int result;
+       const struct key_entry *key;
+
+       status = acpi_get_handle(NULL, device, &handle);
+       if (ACPI_FAILURE(status)) {
+               printk(MY_INFO "Unable to get notification device\n");
+               return -ENODEV;
+       }
+
+       toshiba_acpi.handle = handle;
+
+       status = acpi_evaluate_object(handle, "ENAB", NULL, NULL);
+       if (ACPI_FAILURE(status)) {
+               printk(MY_INFO "Unable to enable hotkeys\n");
+               return -ENODEV;
+       }
+
+       status = acpi_install_notify_handler(handle, ACPI_DEVICE_NOTIFY,
+                                             toshiba_acpi_notify, NULL);
+       if (ACPI_FAILURE(status)) {
+               printk(MY_INFO "Unable to install hotkey notification\n");
+               return -ENODEV;
+       }
+
+       toshiba_acpi.hotkey_dev = input_allocate_device();
+       if (!toshiba_acpi.hotkey_dev) {
+               printk(MY_INFO "Unable to register input device\n");
+               return -ENOMEM;
+       }
+
+       toshiba_acpi.hotkey_dev->name = "Toshiba input device";
+       toshiba_acpi.hotkey_dev->phys = device;
+       toshiba_acpi.hotkey_dev->id.bustype = BUS_HOST;
+       toshiba_acpi.hotkey_dev->getkeycode = toshiba_acpi_getkeycode;
+       toshiba_acpi.hotkey_dev->setkeycode = toshiba_acpi_setkeycode;
+
+       for (key = toshiba_acpi_keymap; key->type != KE_END; key++) {
+               set_bit(EV_KEY, toshiba_acpi.hotkey_dev->evbit);
+               set_bit(key->keycode, toshiba_acpi.hotkey_dev->keybit);
+       }
+
+       result = input_register_device(toshiba_acpi.hotkey_dev);
+       if (result) {
+               printk(MY_INFO "Unable to register input device\n");
+               return result;
+       }
+
+       return 0;
+}
+
 static void toshiba_acpi_exit(void)
 {
+       if (toshiba_acpi.hotkey_dev)
+               input_unregister_device(toshiba_acpi.hotkey_dev);
+
        if (toshiba_acpi.bt_rfk) {
                rfkill_unregister(toshiba_acpi.bt_rfk);
                rfkill_destroy(toshiba_acpi.bt_rfk);
@@ -726,6 +911,9 @@ static void toshiba_acpi_exit(void)
        if (toshiba_proc_dir)
                remove_proc_entry(PROC_TOSHIBA, acpi_root_dir);
 
+       acpi_remove_notify_handler(toshiba_acpi.handle, ACPI_DEVICE_NOTIFY,
+                                  toshiba_acpi_notify);
+
        platform_device_unregister(toshiba_acpi.p_dev);
 
        return;
@@ -742,11 +930,15 @@ static int __init toshiba_acpi_init(void)
                return -ENODEV;
 
        /* simple device detection: look for HCI method */
-       if (is_valid_acpi_path(METHOD_HCI_1))
-               method_hci = METHOD_HCI_1;
-       else if (is_valid_acpi_path(METHOD_HCI_2))
-               method_hci = METHOD_HCI_2;
-       else
+       if (is_valid_acpi_path(TOSH_INTERFACE_1 GHCI_METHOD)) {
+               method_hci = TOSH_INTERFACE_1 GHCI_METHOD;
+               if (toshiba_acpi_setup_keyboard(TOSH_INTERFACE_1))
+                       printk(MY_INFO "Unable to activate hotkeys\n");
+       } else if (is_valid_acpi_path(TOSH_INTERFACE_2 GHCI_METHOD)) {
+               method_hci = TOSH_INTERFACE_2 GHCI_METHOD;
+               if (toshiba_acpi_setup_keyboard(TOSH_INTERFACE_2))
+                       printk(MY_INFO "Unable to activate hotkeys\n");
+       } else
                return -ENODEV;
 
        printk(MY_INFO "Toshiba Laptop ACPI Extras version %s\n",