diff options
Diffstat (limited to 'drivers/platform/x86/toshiba_acpi.c')
-rw-r--r-- | drivers/platform/x86/toshiba_acpi.c | 463 |
1 files changed, 225 insertions, 238 deletions
diff --git a/drivers/platform/x86/toshiba_acpi.c b/drivers/platform/x86/toshiba_acpi.c index dbcb7a8915b8..3ad7b1fa24ce 100644 --- a/drivers/platform/x86/toshiba_acpi.c +++ b/drivers/platform/x86/toshiba_acpi.c @@ -31,7 +31,7 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -#define TOSHIBA_ACPI_VERSION "0.21" +#define TOSHIBA_ACPI_VERSION "0.22" #define PROC_INTERFACE_VERSION 1 #include <linux/kernel.h> @@ -41,7 +41,6 @@ #include <linux/proc_fs.h> #include <linux/seq_file.h> #include <linux/backlight.h> -#include <linux/rfkill.h> #include <linux/input.h> #include <linux/input/sparse-keymap.h> #include <linux/leds.h> @@ -51,6 +50,7 @@ #include <linux/acpi.h> #include <linux/dmi.h> #include <linux/uaccess.h> +#include <acpi/video.h> MODULE_AUTHOR("John Belmonte"); MODULE_DESCRIPTION("Toshiba Laptop ACPI Extras Driver"); @@ -81,7 +81,7 @@ MODULE_LICENSE("GPL"); #define TCI_WORDS 6 -/* operations */ +/* Operations */ #define HCI_SET 0xff00 #define HCI_GET 0xfe00 #define SCI_OPEN 0xf100 @@ -89,7 +89,7 @@ MODULE_LICENSE("GPL"); #define SCI_GET 0xf300 #define SCI_SET 0xf400 -/* return codes */ +/* Return codes */ #define TOS_SUCCESS 0x0000 #define TOS_OPEN_CLOSE_OK 0x0044 #define TOS_FAILURE 0x1000 @@ -104,7 +104,7 @@ MODULE_LICENSE("GPL"); #define TOS_NOT_INITIALIZED 0x8d50 #define TOS_NOT_INSTALLED 0x8e00 -/* registers */ +/* Registers */ #define HCI_FAN 0x0004 #define HCI_TR_BACKLIGHT 0x0005 #define HCI_SYSTEM_EVENT 0x0016 @@ -116,6 +116,7 @@ MODULE_LICENSE("GPL"); #define HCI_KBD_ILLUMINATION 0x0095 #define HCI_ECO_MODE 0x0097 #define HCI_ACCELEROMETER2 0x00a6 +#define HCI_SYSTEM_INFO 0xc000 #define SCI_PANEL_POWER_ON 0x010d #define SCI_ILLUMINATION 0x014e #define SCI_USB_SLEEP_CHARGE 0x0150 @@ -125,14 +126,17 @@ MODULE_LICENSE("GPL"); #define SCI_TOUCHPAD 0x050e #define SCI_KBD_FUNCTION_KEYS 0x0522 -/* field definitions */ +/* Field definitions */ #define HCI_ACCEL_MASK 0x7fff #define HCI_HOTKEY_DISABLE 0x0b #define HCI_HOTKEY_ENABLE 0x09 +#define HCI_HOTKEY_SPECIAL_FUNCTIONS 0x10 #define HCI_LCD_BRIGHTNESS_BITS 3 #define HCI_LCD_BRIGHTNESS_SHIFT (16-HCI_LCD_BRIGHTNESS_BITS) #define HCI_LCD_BRIGHTNESS_LEVELS (1 << HCI_LCD_BRIGHTNESS_BITS) #define HCI_MISC_SHIFT 0x10 +#define HCI_SYSTEM_TYPE1 0x10 +#define HCI_SYSTEM_TYPE2 0x11 #define HCI_VIDEO_OUT_LCD 0x1 #define HCI_VIDEO_OUT_CRT 0x2 #define HCI_VIDEO_OUT_TV 0x4 @@ -147,9 +151,10 @@ MODULE_LICENSE("GPL"); #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_DISABLED 0x00 +#define SCI_USB_CHARGE_ALTERNATE 0x09 +#define SCI_USB_CHARGE_TYPICAL 0x11 +#define SCI_USB_CHARGE_AUTO 0x21 #define SCI_USB_CHARGE_BAT_MASK 0x7 #define SCI_USB_CHARGE_BAT_LVL_OFF 0x1 #define SCI_USB_CHARGE_BAT_LVL_ON 0x4 @@ -159,7 +164,6 @@ MODULE_LICENSE("GPL"); struct toshiba_acpi_dev { struct acpi_device *acpi_dev; const char *method_hci; - struct rfkill *bt_rfk; struct input_dev *hotkey_dev; struct work_struct hotkey_work; struct backlight_device *backlight_dev; @@ -174,6 +178,8 @@ struct toshiba_acpi_dev { int kbd_mode; int kbd_time; int usbsc_bat_level; + int usbsc_mode_base; + int hotkey_event_type; unsigned int illumination_supported:1; unsigned int video_supported:1; @@ -194,8 +200,6 @@ struct toshiba_acpi_dev { unsigned int panel_power_on_supported:1; unsigned int usb_three_supported:1; unsigned int sysfs_created:1; - - struct mutex mutex; }; static struct toshiba_acpi_dev *toshiba_acpi; @@ -243,29 +247,6 @@ static const struct key_entry toshiba_acpi_keymap[] = { { KE_END, 0 }, }; -/* alternative keymap */ -static const struct dmi_system_id toshiba_alt_keymap_dmi[] = { - { - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), - DMI_MATCH(DMI_PRODUCT_NAME, "Satellite M840"), - }, - }, - { - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), - DMI_MATCH(DMI_PRODUCT_NAME, "Qosmio X75-A"), - }, - }, - { - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), - DMI_MATCH(DMI_PRODUCT_NAME, "TECRA A50-A"), - }, - }, - {} -}; - static const struct key_entry toshiba_acpi_alt_keymap[] = { { KE_KEY, 0x157, { KEY_MUTE } }, { KE_KEY, 0x102, { KEY_ZOOMOUT } }, @@ -281,6 +262,14 @@ static const struct key_entry toshiba_acpi_alt_keymap[] = { }; /* + * List of models which have a broken acpi-video backlight interface and thus + * need to use the toshiba (vendor) interface instead. + */ +static const struct dmi_system_id toshiba_vendor_backlight_dmi[] = { + {} +}; + +/* * Utility */ @@ -337,13 +326,13 @@ static acpi_status tci_raw(struct toshiba_acpi_dev *dev, } /* - * Common hci tasks (get or set one or two value) + * Common hci tasks * * In addition to the ACPI status, the HCI system returns a result which * may be useful (such as "not supported"). */ -static u32 hci_write1(struct toshiba_acpi_dev *dev, u32 reg, u32 in1) +static u32 hci_write(struct toshiba_acpi_dev *dev, u32 reg, u32 in1) { u32 in[TCI_WORDS] = { HCI_SET, reg, in1, 0, 0, 0 }; u32 out[TCI_WORDS]; @@ -352,7 +341,7 @@ static u32 hci_write1(struct toshiba_acpi_dev *dev, u32 reg, u32 in1) return ACPI_SUCCESS(status) ? out[0] : TOS_FAILURE; } -static u32 hci_read1(struct toshiba_acpi_dev *dev, u32 reg, u32 *out1) +static u32 hci_read(struct toshiba_acpi_dev *dev, u32 reg, u32 *out1) { u32 in[TCI_WORDS] = { HCI_GET, reg, 0, 0, 0, 0 }; u32 out[TCI_WORDS]; @@ -366,31 +355,6 @@ static u32 hci_read1(struct toshiba_acpi_dev *dev, u32 reg, u32 *out1) return out[0]; } -static u32 hci_write2(struct toshiba_acpi_dev *dev, u32 reg, u32 in1, u32 in2) -{ - u32 in[TCI_WORDS] = { HCI_SET, reg, in1, in2, 0, 0 }; - u32 out[TCI_WORDS]; - acpi_status status = tci_raw(dev, in, out); - - return ACPI_SUCCESS(status) ? out[0] : TOS_FAILURE; -} - -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; - - *out1 = out[2]; - *out2 = out[3]; - - return out[0]; -} - /* * Common sci tasks */ @@ -402,7 +366,7 @@ static int sci_open(struct toshiba_acpi_dev *dev) acpi_status status; status = tci_raw(dev, in, out); - if (ACPI_FAILURE(status) || out[0] == TOS_FAILURE) { + if (ACPI_FAILURE(status)) { pr_err("ACPI call to open SCI failed\n"); return 0; } @@ -440,7 +404,7 @@ static void sci_close(struct toshiba_acpi_dev *dev) acpi_status status; status = tci_raw(dev, in, out); - if (ACPI_FAILURE(status) || out[0] == TOS_FAILURE) { + if (ACPI_FAILURE(status)) { pr_err("ACPI call to close SCI failed\n"); return; } @@ -488,7 +452,7 @@ static int toshiba_illumination_available(struct toshiba_acpi_dev *dev) status = tci_raw(dev, in, out); sci_close(dev); - if (ACPI_FAILURE(status) || out[0] == TOS_FAILURE) { + if (ACPI_FAILURE(status)) { pr_err("ACPI call to query Illumination support failed\n"); return 0; } else if (out[0] == TOS_NOT_SUPPORTED) { @@ -529,7 +493,7 @@ static enum led_brightness toshiba_illumination_get(struct led_classdev *cdev) struct toshiba_acpi_dev, led_dev); u32 state, result; - /* First request : initialize communication. */ + /* First request : initialize communication. */ if (!sci_open(dev)) return LED_OFF; @@ -632,7 +596,7 @@ static enum led_brightness toshiba_kbd_backlight_get(struct led_classdev *cdev) u32 state, result; /* Check the keyboard backlight state */ - result = hci_read1(dev, HCI_KBD_ILLUMINATION, &state); + result = hci_read(dev, HCI_KBD_ILLUMINATION, &state); if (result == TOS_FAILURE || result == TOS_INPUT_DATA_ERROR) { pr_err("ACPI call to get the keyboard backlight failed\n"); return LED_OFF; @@ -653,7 +617,7 @@ static void toshiba_kbd_backlight_set(struct led_classdev *cdev, /* Set the keyboard backlight state */ state = brightness ? 1 : 0; - result = hci_write1(dev, HCI_KBD_ILLUMINATION, state); + result = hci_write(dev, HCI_KBD_ILLUMINATION, state); if (result == TOS_FAILURE || result == TOS_INPUT_DATA_ERROR) { pr_err("ACPI call to set KBD Illumination mode failed\n"); return; @@ -710,7 +674,7 @@ static int toshiba_eco_mode_available(struct toshiba_acpi_dev *dev) u32 out[TCI_WORDS]; status = tci_raw(dev, in, out); - if (ACPI_FAILURE(status) || out[0] == TOS_FAILURE) { + if (ACPI_FAILURE(status)) { pr_err("ACPI call to get ECO led failed\n"); } else if (out[0] == TOS_NOT_INSTALLED) { pr_info("ECO led not installed"); @@ -819,6 +783,54 @@ static int toshiba_accelerometer_get(struct toshiba_acpi_dev *dev, } /* Sleep (Charge and Music) utilities support */ +static void toshiba_usb_sleep_charge_available(struct toshiba_acpi_dev *dev) +{ + u32 in[TCI_WORDS] = { SCI_GET, SCI_USB_SLEEP_CHARGE, 0, 0, 0, 0 }; + u32 out[TCI_WORDS]; + acpi_status status; + + /* Set the feature to "not supported" in case of error */ + dev->usb_sleep_charge_supported = 0; + + if (!sci_open(dev)) + return; + + status = tci_raw(dev, in, out); + if (ACPI_FAILURE(status)) { + pr_err("ACPI call to get USB Sleep and Charge mode failed\n"); + sci_close(dev); + return; + } else if (out[0] == TOS_NOT_SUPPORTED) { + pr_info("USB Sleep and Charge not supported\n"); + sci_close(dev); + return; + } else if (out[0] == TOS_SUCCESS) { + dev->usbsc_mode_base = out[4]; + } + + in[5] = SCI_USB_CHARGE_BAT_LVL; + status = tci_raw(dev, in, out); + if (ACPI_FAILURE(status)) { + pr_err("ACPI call to get USB Sleep and Charge mode failed\n"); + sci_close(dev); + return; + } else if (out[0] == TOS_NOT_SUPPORTED) { + pr_info("USB Sleep and Charge not supported\n"); + sci_close(dev); + return; + } else if (out[0] == TOS_SUCCESS) { + dev->usbsc_bat_level = out[2]; + /* + * If we reach this point, it means that the laptop has support + * for this feature and all values are initialized. + * Set it as supported. + */ + dev->usb_sleep_charge_supported = 1; + } + + sci_close(dev); +} + static int toshiba_usb_sleep_charge_get(struct toshiba_acpi_dev *dev, u32 *mode) { @@ -878,7 +890,7 @@ static int toshiba_sleep_functions_status_get(struct toshiba_acpi_dev *dev, in[5] = SCI_USB_CHARGE_BAT_LVL; status = tci_raw(dev, in, out); sci_close(dev); - if (ACPI_FAILURE(status) || out[0] == TOS_FAILURE) { + if (ACPI_FAILURE(status)) { pr_err("ACPI call to get USB S&C battery level failed\n"); return -EIO; } else if (out[0] == TOS_NOT_SUPPORTED) { @@ -907,7 +919,7 @@ static int toshiba_sleep_functions_status_set(struct toshiba_acpi_dev *dev, in[5] = SCI_USB_CHARGE_BAT_LVL; status = tci_raw(dev, in, out); sci_close(dev); - if (ACPI_FAILURE(status) || out[0] == TOS_FAILURE) { + if (ACPI_FAILURE(status)) { pr_err("ACPI call to set USB S&C battery level failed\n"); return -EIO; } else if (out[0] == TOS_NOT_SUPPORTED) { @@ -933,12 +945,12 @@ static int toshiba_usb_rapid_charge_get(struct toshiba_acpi_dev *dev, 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"); + if (ACPI_FAILURE(status)) { + pr_err("ACPI call to get USB Rapid Charge 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"); + pr_info("USB Rapid Charge not supported\n"); return -ENODEV; } @@ -961,11 +973,11 @@ static int toshiba_usb_rapid_charge_set(struct toshiba_acpi_dev *dev, 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"); + if (ACPI_FAILURE(status)) { + pr_err("ACPI call to set USB Rapid Charge failed\n"); return -EIO; } else if (out[0] == TOS_NOT_SUPPORTED) { - pr_info("USB Sleep and Charge not supported\n"); + pr_info("USB Rapid Charge not supported\n"); return -ENODEV; } else if (out[0] == TOS_INPUT_DATA_ERROR) { return -EIO; @@ -984,10 +996,10 @@ static int toshiba_usb_sleep_music_get(struct toshiba_acpi_dev *dev, u32 *state) 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"); + pr_err("ACPI call to get Sleep and Music failed\n"); return -EIO; } else if (result == TOS_NOT_SUPPORTED) { - pr_info("USB Sleep and Charge not supported\n"); + pr_info("Sleep and Music not supported\n"); return -ENODEV; } else if (result == TOS_INPUT_DATA_ERROR) { return -EIO; @@ -1006,10 +1018,10 @@ static int toshiba_usb_sleep_music_set(struct toshiba_acpi_dev *dev, u32 state) 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"); + pr_err("ACPI call to set Sleep and Music failed\n"); return -EIO; } else if (result == TOS_NOT_SUPPORTED) { - pr_info("USB Sleep and Charge not supported\n"); + pr_info("Sleep and Music not supported\n"); return -ENODEV; } else if (result == TOS_INPUT_DATA_ERROR) { return -EIO; @@ -1149,103 +1161,35 @@ static int toshiba_usb_three_set(struct toshiba_acpi_dev *dev, u32 state) 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) +/* Hotkey Event type */ +static int toshiba_hotkey_event_type_get(struct toshiba_acpi_dev *dev, + u32 *type) { - 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); + u32 in[TCI_WORDS] = { HCI_GET, HCI_SYSTEM_INFO, 0x03, 0, 0, 0 }; + u32 out[TCI_WORDS]; + acpi_status status; - hci_result = hci_get_radio_state(dev, &value); - if (hci_result != TOS_SUCCESS) { - /* Can't do anything useful */ - mutex_unlock(&dev->mutex); - return; + status = tci_raw(dev, in, out); + if (ACPI_FAILURE(status)) { + pr_err("ACPI call to get System type failed\n"); + return -EIO; + } else if (out[0] == TOS_NOT_SUPPORTED) { + pr_info("System type not supported\n"); + return -ENODEV; } - new_rfk_state = value; + *type = out[3]; - 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, -}; - +/* Transflective Backlight */ 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); + hci_result = hci_read(dev, HCI_TR_BACKLIGHT, &status); *enabled = !status; return hci_result == TOS_SUCCESS ? 0 : -EIO; } @@ -1255,12 +1199,13 @@ 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); + hci_result = hci_write(dev, HCI_TR_BACKLIGHT, value); return hci_result == TOS_SUCCESS ? 0 : -EIO; } -static struct proc_dir_entry *toshiba_proc_dir /*= 0*/; +static struct proc_dir_entry *toshiba_proc_dir; +/* LCD Brightness */ static int __get_lcd_brightness(struct toshiba_acpi_dev *dev) { u32 hci_result; @@ -1278,7 +1223,7 @@ static int __get_lcd_brightness(struct toshiba_acpi_dev *dev) brightness++; } - hci_result = hci_read1(dev, HCI_LCD_BRIGHTNESS, &value); + hci_result = hci_read(dev, HCI_LCD_BRIGHTNESS, &value); if (hci_result == TOS_SUCCESS) return brightness + (value >> HCI_LCD_BRIGHTNESS_SHIFT); @@ -1333,7 +1278,7 @@ static int set_lcd_brightness(struct toshiba_acpi_dev *dev, int value) } value = value << HCI_LCD_BRIGHTNESS_SHIFT; - hci_result = hci_write1(dev, HCI_LCD_BRIGHTNESS, value); + hci_result = hci_write(dev, HCI_LCD_BRIGHTNESS, value); return hci_result == TOS_SUCCESS ? 0 : -EIO; } @@ -1383,7 +1328,7 @@ static int get_video_status(struct toshiba_acpi_dev *dev, u32 *status) { u32 hci_result; - hci_result = hci_read1(dev, HCI_VIDEO_OUT, status); + hci_result = hci_read(dev, HCI_VIDEO_OUT, status); return hci_result == TOS_SUCCESS ? 0 : -EIO; } @@ -1468,7 +1413,8 @@ static ssize_t video_proc_write(struct file *file, const char __user *buf, _set_bit(&new_video_out, HCI_VIDEO_OUT_TV, tv_out); /* * To avoid unnecessary video disruption, only write the new - * video setting if something changed. */ + * video setting if something changed. + */ if (new_video_out != video_out) ret = write_acpi_int(METHOD_VIDEO_OUT, new_video_out); } @@ -1489,7 +1435,7 @@ static int get_fan_status(struct toshiba_acpi_dev *dev, u32 *status) { u32 hci_result; - hci_result = hci_read1(dev, HCI_FAN, status); + hci_result = hci_read(dev, HCI_FAN, status); return hci_result == TOS_SUCCESS ? 0 : -EIO; } @@ -1529,7 +1475,7 @@ 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); + hci_result = hci_write(dev, HCI_FAN, value); if (hci_result == TOS_SUCCESS) dev->force_fan = value; else @@ -1557,7 +1503,7 @@ static int keys_proc_show(struct seq_file *m, void *v) u32 value; if (!dev->key_event_valid && dev->system_event_supported) { - hci_result = hci_read1(dev, HCI_SYSTEM_EVENT, &value); + hci_result = hci_read(dev, HCI_SYSTEM_EVENT, &value); if (hci_result == TOS_SUCCESS) { dev->key_event_valid = 1; dev->last_key_event = value; @@ -1569,7 +1515,7 @@ static int keys_proc_show(struct seq_file *m, void *v) * some machines where system events sporadically * become disabled. */ - hci_result = hci_write1(dev, HCI_SYSTEM_EVENT, 1); + hci_result = hci_write(dev, HCI_SYSTEM_EVENT, 1); pr_notice("Re-enabled hotkeys\n"); } else { pr_err("Error reading hotkey status\n"); @@ -1706,7 +1652,7 @@ static ssize_t fan_store(struct device *dev, if (state != 0 && state != 1) return -EINVAL; - result = hci_write1(toshiba, HCI_FAN, state); + result = hci_write(toshiba, HCI_FAN, state); if (result == TOS_FAILURE) return -EIO; else if (result == TOS_NOT_SUPPORTED) @@ -1973,17 +1919,21 @@ static ssize_t usb_sleep_charge_store(struct device *dev, * 0 - Disabled * 1 - Alternate (Non USB conformant devices that require more power) * 2 - Auto (USB conformant devices) + * 3 - Typical */ - if (state != 0 && state != 1 && state != 2) + if (state != 0 && state != 1 && state != 2 && state != 3) return -EINVAL; /* Set the USB charging mode to internal value */ + mode = toshiba->usbsc_mode_base; if (state == 0) - mode = SCI_USB_CHARGE_DISABLED; + mode |= SCI_USB_CHARGE_DISABLED; else if (state == 1) - mode = SCI_USB_CHARGE_ALTERNATE; + mode |= SCI_USB_CHARGE_ALTERNATE; else if (state == 2) - mode = SCI_USB_CHARGE_AUTO; + mode |= SCI_USB_CHARGE_AUTO; + else if (state == 3) + mode |= SCI_USB_CHARGE_TYPICAL; ret = toshiba_usb_sleep_charge_set(toshiba, mode); if (ret) @@ -2324,7 +2274,7 @@ static int toshiba_acpi_enable_hotkeys(struct toshiba_acpi_dev *dev) if (ACPI_FAILURE(status)) return -ENODEV; - result = hci_write1(dev, HCI_HOTKEY_EVENT, HCI_HOTKEY_ENABLE); + result = hci_write(dev, HCI_HOTKEY_EVENT, HCI_HOTKEY_ENABLE); if (result == TOS_FAILURE) return -EIO; else if (result == TOS_NOT_SUPPORTED) @@ -2333,6 +2283,20 @@ static int toshiba_acpi_enable_hotkeys(struct toshiba_acpi_dev *dev) return 0; } +static void toshiba_acpi_enable_special_functions(struct toshiba_acpi_dev *dev) +{ + u32 result; + + /* + * Re-activate the hotkeys, but this time, we are using the + * "Special Functions" mode. + */ + result = hci_write(dev, HCI_HOTKEY_EVENT, + HCI_HOTKEY_SPECIAL_FUNCTIONS); + if (result != TOS_SUCCESS) + pr_err("Could not enable the Special Function mode\n"); +} + static bool toshiba_acpi_i8042_filter(unsigned char data, unsigned char str, struct serio *port) { @@ -2409,7 +2373,7 @@ static void toshiba_acpi_process_hotkeys(struct toshiba_acpi_dev *dev) toshiba_acpi_report_hotkey(dev, scancode); } else if (dev->system_event_supported) { do { - hci_result = hci_read1(dev, HCI_SYSTEM_EVENT, &value); + hci_result = hci_read(dev, HCI_SYSTEM_EVENT, &value); switch (hci_result) { case TOS_SUCCESS: toshiba_acpi_report_hotkey(dev, (int)value); @@ -2421,7 +2385,7 @@ static void toshiba_acpi_process_hotkeys(struct toshiba_acpi_dev *dev) * sporadically become disabled. */ hci_result = - hci_write1(dev, HCI_SYSTEM_EVENT, 1); + hci_write(dev, HCI_SYSTEM_EVENT, 1); pr_notice("Re-enabled hotkeys\n"); /* Fall through */ default: @@ -2434,10 +2398,22 @@ static void toshiba_acpi_process_hotkeys(struct toshiba_acpi_dev *dev) static int toshiba_acpi_setup_keyboard(struct toshiba_acpi_dev *dev) { + const struct key_entry *keymap = toshiba_acpi_keymap; acpi_handle ec_handle; - int error; + u32 events_type; u32 hci_result; - const struct key_entry *keymap = toshiba_acpi_keymap; + int error; + + error = toshiba_acpi_enable_hotkeys(dev); + if (error) + return error; + + error = toshiba_hotkey_event_type_get(dev, &events_type); + if (error) { + pr_err("Unable to query Hotkey Event Type\n"); + return error; + } + dev->hotkey_event_type = events_type; dev->hotkey_dev = input_allocate_device(); if (!dev->hotkey_dev) @@ -2447,8 +2423,14 @@ static int toshiba_acpi_setup_keyboard(struct toshiba_acpi_dev *dev) dev->hotkey_dev->phys = "toshiba_acpi/input0"; dev->hotkey_dev->id.bustype = BUS_HOST; - if (dmi_check_system(toshiba_alt_keymap_dmi)) + if (events_type == HCI_SYSTEM_TYPE1 || + !dev->kbd_function_keys_supported) + keymap = toshiba_acpi_keymap; + else if (events_type == HCI_SYSTEM_TYPE2 || + dev->kbd_function_keys_supported) keymap = toshiba_acpi_alt_keymap; + else + pr_info("Unknown event type received %x\n", events_type); error = sparse_keymap_setup(dev->hotkey_dev, keymap, NULL); if (error) goto err_free_dev; @@ -2480,7 +2462,7 @@ static int toshiba_acpi_setup_keyboard(struct toshiba_acpi_dev *dev) if (acpi_has_method(dev->acpi_dev->handle, "INFO")) dev->info_supported = 1; else { - hci_result = hci_write1(dev, HCI_SYSTEM_EVENT, 1); + hci_result = hci_write(dev, HCI_SYSTEM_EVENT, 1); if (hci_result == TOS_SUCCESS) dev->system_event_supported = 1; } @@ -2490,12 +2472,6 @@ static int toshiba_acpi_setup_keyboard(struct toshiba_acpi_dev *dev) goto err_remove_filter; } - error = toshiba_acpi_enable_hotkeys(dev); - if (error) { - pr_info("Unable to enable hotkeys\n"); - goto err_remove_filter; - } - error = input_register_device(dev->hotkey_dev); if (error) { pr_info("Unable to register input device\n"); @@ -2541,6 +2517,17 @@ static int toshiba_acpi_setup_backlight(struct toshiba_acpi_dev *dev) ret = get_tr_backlight_status(dev, &enabled); dev->tr_backlight_supported = !ret; + /* + * Tell acpi-video-detect code to prefer vendor backlight on all + * systems with transflective backlight and on dmi matched systems. + */ + if (dev->tr_backlight_supported || + dmi_check_system(toshiba_vendor_backlight_dmi)) + acpi_video_set_dmi_backlight_type(acpi_backlight_vendor); + + if (acpi_video_get_backlight_type() != acpi_backlight_vendor) + return 0; + memset(&props, 0, sizeof(props)); props.type = BACKLIGHT_PLATFORM; props.max_brightness = HCI_LCD_BRIGHTNESS_LEVELS - 1; @@ -2585,11 +2572,6 @@ static int toshiba_acpi_remove(struct acpi_device *acpi_dev) sparse_keymap_free(dev->hotkey_dev); } - if (dev->bt_rfk) { - rfkill_unregister(dev->bt_rfk); - rfkill_destroy(dev->bt_rfk); - } - backlight_device_unregister(dev->backlight_dev); if (dev->illumination_supported) @@ -2624,8 +2606,8 @@ static int toshiba_acpi_add(struct acpi_device *acpi_dev) { struct toshiba_acpi_dev *dev; const char *hci_method; + u32 special_functions; u32 dummy; - bool bt_present; int ret = 0; if (toshiba_acpi) @@ -2648,36 +2630,23 @@ static int toshiba_acpi_add(struct acpi_device *acpi_dev) acpi_dev->driver_data = dev; dev_set_drvdata(&acpi_dev->dev, dev); + /* Query the BIOS for supported features */ + + /* + * The "Special Functions" are always supported by the laptops + * with the new keyboard layout, query for its presence to help + * determine the keymap layout to use. + */ + ret = toshiba_function_keys_get(dev, &special_functions); + dev->kbd_function_keys_supported = !ret; + if (toshiba_acpi_setup_keyboard(dev)) pr_info("Unable to activate hotkeys\n"); - mutex_init(&dev->mutex); - ret = toshiba_acpi_setup_backlight(dev); if (ret) goto error; - /* Register rfkill switch for Bluetooth */ - if (hci_get_bt_present(dev, &bt_present) == TOS_SUCCESS && bt_present) { - dev->bt_rfk = rfkill_alloc("Toshiba Bluetooth", - &acpi_dev->dev, - RFKILL_TYPE_BLUETOOTH, - &toshiba_rfk_ops, - dev); - if (!dev->bt_rfk) { - pr_err("unable to allocate rfkill device\n"); - ret = -ENOMEM; - goto error; - } - - ret = rfkill_register(dev->bt_rfk); - if (ret) { - pr_err("unable to register rfkill device\n"); - rfkill_destroy(dev->bt_rfk); - goto error; - } - } - if (toshiba_illumination_available(dev)) { dev->led_dev.name = "toshiba::illumination"; dev->led_dev.max_brightness = 1; @@ -2716,8 +2685,7 @@ 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; + toshiba_usb_sleep_charge_available(dev); ret = toshiba_usb_rapid_charge_get(dev, &dummy); dev->usb_rapid_charge_supported = !ret; @@ -2725,23 +2693,25 @@ static int toshiba_acpi_add(struct acpi_device *acpi_dev) 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); dev->video_supported = !ret; ret = get_fan_status(dev, &dummy); dev->fan_supported = !ret; + /* + * Enable the "Special Functions" mode only if they are + * supported and if they are activated. + */ + if (dev->kbd_function_keys_supported && special_functions) + toshiba_acpi_enable_special_functions(dev); + ret = sysfs_create_group(&dev->acpi_dev->dev.kobj, &toshiba_attr_group); if (ret) { @@ -2770,6 +2740,21 @@ static void toshiba_acpi_notify(struct acpi_device *acpi_dev, u32 event) case 0x80: /* Hotkeys and some system events */ toshiba_acpi_process_hotkeys(dev); break; + case 0x81: /* Dock events */ + case 0x82: + case 0x83: + pr_info("Dock event received %x\n", event); + break; + case 0x88: /* Thermal events */ + pr_info("Thermal event received\n"); + break; + case 0x8f: /* LID closed */ + case 0x90: /* LID is closed and Dock has been ejected */ + break; + case 0x8c: /* SATA power events */ + case 0x8b: + pr_info("SATA power event received %x\n", event); + break; case 0x92: /* Keyboard backlight mode changed */ /* Update sysfs entries */ ret = sysfs_update_group(&acpi_dev->dev.kobj, @@ -2777,17 +2762,19 @@ static void toshiba_acpi_notify(struct acpi_device *acpi_dev, u32 event) if (ret) pr_err("Unable to update sysfs entries\n"); break; - case 0x81: /* Unknown */ - case 0x82: /* Unknown */ - case 0x83: /* Unknown */ - case 0x8c: /* Unknown */ + case 0x85: /* Unknown */ + case 0x8d: /* Unknown */ case 0x8e: /* Unknown */ - case 0x8f: /* Unknown */ - case 0x90: /* Unknown */ + case 0x94: /* Unknown */ + case 0x95: /* Unknown */ default: pr_info("Unknown event received %x\n", event); break; } + + acpi_bus_generate_netlink_event(acpi_dev->pnp.device_class, + dev_name(&acpi_dev->dev), + event, 0); } #ifdef CONFIG_PM_SLEEP @@ -2797,7 +2784,7 @@ static int toshiba_acpi_suspend(struct device *device) u32 result; if (dev->hotkey_dev) - result = hci_write1(dev, HCI_HOTKEY_EVENT, HCI_HOTKEY_DISABLE); + result = hci_write(dev, HCI_HOTKEY_EVENT, HCI_HOTKEY_DISABLE); return 0; } |