diff options
| -rw-r--r-- | Documentation/kernel-parameters.txt | 5 | ||||
| -rw-r--r-- | Documentation/laptops/thinkpad-acpi.txt | 58 | ||||
| -rw-r--r-- | arch/x86/kernel/acpi/sleep.c | 2 | ||||
| -rw-r--r-- | drivers/acpi/sleep.c | 29 | ||||
| -rw-r--r-- | drivers/acpi/video.c | 8 | ||||
| -rw-r--r-- | drivers/char/ipmi/ipmi_si_intf.c | 4 | ||||
| -rw-r--r-- | drivers/platform/x86/Kconfig | 28 | ||||
| -rw-r--r-- | drivers/platform/x86/dell-wmi.c | 9 | ||||
| -rw-r--r-- | drivers/platform/x86/hp-wmi.c | 9 | ||||
| -rw-r--r-- | drivers/platform/x86/msi-wmi.c | 9 | ||||
| -rw-r--r-- | drivers/platform/x86/thinkpad_acpi.c | 59 | ||||
| -rw-r--r-- | drivers/platform/x86/wmi.c | 30 | ||||
| -rw-r--r-- | include/linux/acpi.h | 1 |
13 files changed, 207 insertions, 44 deletions
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 5ba4d9dff113..736d45602886 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt | |||
| @@ -240,7 +240,7 @@ and is between 256 and 4096 characters. It is defined in the file | |||
| 240 | 240 | ||
| 241 | acpi_sleep= [HW,ACPI] Sleep options | 241 | acpi_sleep= [HW,ACPI] Sleep options |
| 242 | Format: { s3_bios, s3_mode, s3_beep, s4_nohwsig, | 242 | Format: { s3_bios, s3_mode, s3_beep, s4_nohwsig, |
| 243 | old_ordering, s4_nonvs } | 243 | old_ordering, s4_nonvs, sci_force_enable } |
| 244 | See Documentation/power/video.txt for information on | 244 | See Documentation/power/video.txt for information on |
| 245 | s3_bios and s3_mode. | 245 | s3_bios and s3_mode. |
| 246 | s3_beep is for debugging; it makes the PC's speaker beep | 246 | s3_beep is for debugging; it makes the PC's speaker beep |
| @@ -253,6 +253,9 @@ and is between 256 and 4096 characters. It is defined in the file | |||
| 253 | of _PTS is used by default). | 253 | of _PTS is used by default). |
| 254 | s4_nonvs prevents the kernel from saving/restoring the | 254 | s4_nonvs prevents the kernel from saving/restoring the |
| 255 | ACPI NVS memory during hibernation. | 255 | ACPI NVS memory during hibernation. |
| 256 | sci_force_enable causes the kernel to set SCI_EN directly | ||
| 257 | on resume from S1/S3 (which is against the ACPI spec, | ||
| 258 | but some broken systems don't work without it). | ||
| 256 | 259 | ||
| 257 | acpi_use_timer_override [HW,ACPI] | 260 | acpi_use_timer_override [HW,ACPI] |
| 258 | Use timer override. For some broken Nvidia NF5 boards | 261 | Use timer override. For some broken Nvidia NF5 boards |
diff --git a/Documentation/laptops/thinkpad-acpi.txt b/Documentation/laptops/thinkpad-acpi.txt index 169091f75e6d..75afa1229fd7 100644 --- a/Documentation/laptops/thinkpad-acpi.txt +++ b/Documentation/laptops/thinkpad-acpi.txt | |||
| @@ -1092,8 +1092,8 @@ WARNING: | |||
| 1092 | its level up and down at every change. | 1092 | its level up and down at every change. |
| 1093 | 1093 | ||
| 1094 | 1094 | ||
| 1095 | Volume control | 1095 | Volume control (Console Audio control) |
| 1096 | -------------- | 1096 | -------------------------------------- |
| 1097 | 1097 | ||
| 1098 | procfs: /proc/acpi/ibm/volume | 1098 | procfs: /proc/acpi/ibm/volume |
| 1099 | ALSA: "ThinkPad Console Audio Control", default ID: "ThinkPadEC" | 1099 | ALSA: "ThinkPad Console Audio Control", default ID: "ThinkPadEC" |
| @@ -1110,9 +1110,53 @@ the desktop environment to just provide on-screen-display feedback. | |||
| 1110 | Software volume control should be done only in the main AC97/HDA | 1110 | Software volume control should be done only in the main AC97/HDA |
| 1111 | mixer. | 1111 | mixer. |
| 1112 | 1112 | ||
| 1113 | This feature allows volume control on ThinkPad models with a digital | 1113 | |
| 1114 | volume knob (when available, not all models have it), as well as | 1114 | About the ThinkPad Console Audio control: |
| 1115 | mute/unmute control. The available commands are: | 1115 | |
| 1116 | ThinkPads have a built-in amplifier and muting circuit that drives the | ||
| 1117 | console headphone and speakers. This circuit is after the main AC97 | ||
| 1118 | or HDA mixer in the audio path, and under exclusive control of the | ||
| 1119 | firmware. | ||
| 1120 | |||
| 1121 | ThinkPads have three special hotkeys to interact with the console | ||
| 1122 | audio control: volume up, volume down and mute. | ||
| 1123 | |||
| 1124 | It is worth noting that the normal way the mute function works (on | ||
| 1125 | ThinkPads that do not have a "mute LED") is: | ||
| 1126 | |||
| 1127 | 1. Press mute to mute. It will *always* mute, you can press it as | ||
| 1128 | many times as you want, and the sound will remain mute. | ||
| 1129 | |||
| 1130 | 2. Press either volume key to unmute the ThinkPad (it will _not_ | ||
| 1131 | change the volume, it will just unmute). | ||
| 1132 | |||
| 1133 | This is a very superior design when compared to the cheap software-only | ||
| 1134 | mute-toggle solution found on normal consumer laptops: you can be | ||
| 1135 | absolutely sure the ThinkPad will not make noise if you press the mute | ||
| 1136 | button, no matter the previous state. | ||
| 1137 | |||
| 1138 | The IBM ThinkPads, and the earlier Lenovo ThinkPads have variable-gain | ||
| 1139 | amplifiers driving the speakers and headphone output, and the firmware | ||
| 1140 | also handles volume control for the headphone and speakers on these | ||
| 1141 | ThinkPads without any help from the operating system (this volume | ||
| 1142 | control stage exists after the main AC97 or HDA mixer in the audio | ||
| 1143 | path). | ||
| 1144 | |||
| 1145 | The newer Lenovo models only have firmware mute control, and depend on | ||
| 1146 | the main HDA mixer to do volume control (which is done by the operating | ||
| 1147 | system). In this case, the volume keys are filtered out for unmute | ||
| 1148 | key press (there are some firmware bugs in this area) and delivered as | ||
| 1149 | normal key presses to the operating system (thinkpad-acpi is not | ||
| 1150 | involved). | ||
| 1151 | |||
| 1152 | |||
| 1153 | The ThinkPad-ACPI volume control: | ||
| 1154 | |||
| 1155 | The preferred way to interact with the Console Audio control is the | ||
| 1156 | ALSA interface. | ||
| 1157 | |||
| 1158 | The legacy procfs interface allows one to read the current state, | ||
| 1159 | and if volume control is enabled, accepts the following commands: | ||
| 1116 | 1160 | ||
| 1117 | echo up >/proc/acpi/ibm/volume | 1161 | echo up >/proc/acpi/ibm/volume |
| 1118 | echo down >/proc/acpi/ibm/volume | 1162 | echo down >/proc/acpi/ibm/volume |
| @@ -1121,12 +1165,10 @@ mute/unmute control. The available commands are: | |||
| 1121 | echo 'level <level>' >/proc/acpi/ibm/volume | 1165 | echo 'level <level>' >/proc/acpi/ibm/volume |
| 1122 | 1166 | ||
| 1123 | The <level> number range is 0 to 14 although not all of them may be | 1167 | The <level> number range is 0 to 14 although not all of them may be |
| 1124 | distinct. The unmute the volume after the mute command, use either the | 1168 | distinct. To unmute the volume after the mute command, use either the |
| 1125 | up or down command (the level command will not unmute the volume), or | 1169 | up or down command (the level command will not unmute the volume), or |
| 1126 | the unmute command. | 1170 | the unmute command. |
| 1127 | 1171 | ||
| 1128 | The current volume level and mute state is shown in the file. | ||
| 1129 | |||
| 1130 | You can use the volume_capabilities parameter to tell the driver | 1172 | You can use the volume_capabilities parameter to tell the driver |
| 1131 | whether your thinkpad has volume control or mute-only control: | 1173 | whether your thinkpad has volume control or mute-only control: |
| 1132 | volume_capabilities=1 for mixers with mute and volume control, | 1174 | volume_capabilities=1 for mixers with mute and volume control, |
diff --git a/arch/x86/kernel/acpi/sleep.c b/arch/x86/kernel/acpi/sleep.c index 82e508677b91..f9961034e557 100644 --- a/arch/x86/kernel/acpi/sleep.c +++ b/arch/x86/kernel/acpi/sleep.c | |||
| @@ -162,6 +162,8 @@ static int __init acpi_sleep_setup(char *str) | |||
| 162 | #endif | 162 | #endif |
| 163 | if (strncmp(str, "old_ordering", 12) == 0) | 163 | if (strncmp(str, "old_ordering", 12) == 0) |
| 164 | acpi_old_suspend_ordering(); | 164 | acpi_old_suspend_ordering(); |
| 165 | if (strncmp(str, "sci_force_enable", 16) == 0) | ||
| 166 | acpi_set_sci_en_on_resume(); | ||
| 165 | str = strchr(str, ','); | 167 | str = strchr(str, ','); |
| 166 | if (str != NULL) | 168 | if (str != NULL) |
| 167 | str += strspn(str, ", \t"); | 169 | str += strspn(str, ", \t"); |
diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index 5f2c379ab7bf..79d33d908b5a 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c | |||
| @@ -81,6 +81,23 @@ static int acpi_sleep_prepare(u32 acpi_state) | |||
| 81 | #ifdef CONFIG_ACPI_SLEEP | 81 | #ifdef CONFIG_ACPI_SLEEP |
| 82 | static u32 acpi_target_sleep_state = ACPI_STATE_S0; | 82 | static u32 acpi_target_sleep_state = ACPI_STATE_S0; |
| 83 | /* | 83 | /* |
| 84 | * According to the ACPI specification the BIOS should make sure that ACPI is | ||
| 85 | * enabled and SCI_EN bit is set on wake-up from S1 - S3 sleep states. Still, | ||
| 86 | * some BIOSes don't do that and therefore we use acpi_enable() to enable ACPI | ||
| 87 | * on such systems during resume. Unfortunately that doesn't help in | ||
| 88 | * particularly pathological cases in which SCI_EN has to be set directly on | ||
| 89 | * resume, although the specification states very clearly that this flag is | ||
| 90 | * owned by the hardware. The set_sci_en_on_resume variable will be set in such | ||
| 91 | * cases. | ||
| 92 | */ | ||
| 93 | static bool set_sci_en_on_resume; | ||
| 94 | |||
| 95 | void __init acpi_set_sci_en_on_resume(void) | ||
| 96 | { | ||
| 97 | set_sci_en_on_resume = true; | ||
| 98 | } | ||
| 99 | |||
| 100 | /* | ||
| 84 | * ACPI 1.0 wants us to execute _PTS before suspending devices, so we allow the | 101 | * ACPI 1.0 wants us to execute _PTS before suspending devices, so we allow the |
| 85 | * user to request that behavior by using the 'acpi_old_suspend_ordering' | 102 | * user to request that behavior by using the 'acpi_old_suspend_ordering' |
| 86 | * kernel command line option that causes the following variable to be set. | 103 | * kernel command line option that causes the following variable to be set. |
| @@ -170,18 +187,6 @@ static void acpi_pm_end(void) | |||
| 170 | #endif /* CONFIG_ACPI_SLEEP */ | 187 | #endif /* CONFIG_ACPI_SLEEP */ |
| 171 | 188 | ||
| 172 | #ifdef CONFIG_SUSPEND | 189 | #ifdef CONFIG_SUSPEND |
| 173 | /* | ||
| 174 | * According to the ACPI specification the BIOS should make sure that ACPI is | ||
| 175 | * enabled and SCI_EN bit is set on wake-up from S1 - S3 sleep states. Still, | ||
| 176 | * some BIOSes don't do that and therefore we use acpi_enable() to enable ACPI | ||
| 177 | * on such systems during resume. Unfortunately that doesn't help in | ||
| 178 | * particularly pathological cases in which SCI_EN has to be set directly on | ||
| 179 | * resume, although the specification states very clearly that this flag is | ||
| 180 | * owned by the hardware. The set_sci_en_on_resume variable will be set in such | ||
| 181 | * cases. | ||
| 182 | */ | ||
| 183 | static bool set_sci_en_on_resume; | ||
| 184 | |||
| 185 | extern void do_suspend_lowlevel(void); | 190 | extern void do_suspend_lowlevel(void); |
| 186 | 191 | ||
| 187 | static u32 acpi_suspend_states[] = { | 192 | static u32 acpi_suspend_states[] = { |
diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index 05dff631591c..72e76b4b6538 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c | |||
| @@ -999,8 +999,10 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device) | |||
| 999 | sprintf(name, "acpi_video%d", count++); | 999 | sprintf(name, "acpi_video%d", count++); |
| 1000 | device->backlight = backlight_device_register(name, | 1000 | device->backlight = backlight_device_register(name, |
| 1001 | NULL, device, &acpi_backlight_ops); | 1001 | NULL, device, &acpi_backlight_ops); |
| 1002 | device->backlight->props.max_brightness = device->brightness->count-3; | ||
| 1003 | kfree(name); | 1002 | kfree(name); |
| 1003 | if (IS_ERR(device->backlight)) | ||
| 1004 | return; | ||
| 1005 | device->backlight->props.max_brightness = device->brightness->count-3; | ||
| 1004 | 1006 | ||
| 1005 | result = sysfs_create_link(&device->backlight->dev.kobj, | 1007 | result = sysfs_create_link(&device->backlight->dev.kobj, |
| 1006 | &device->dev->dev.kobj, "device"); | 1008 | &device->dev->dev.kobj, "device"); |
| @@ -1979,6 +1981,10 @@ acpi_video_switch_brightness(struct acpi_video_device *device, int event) | |||
| 1979 | unsigned long long level_current, level_next; | 1981 | unsigned long long level_current, level_next; |
| 1980 | int result = -EINVAL; | 1982 | int result = -EINVAL; |
| 1981 | 1983 | ||
| 1984 | /* no warning message if acpi_backlight=vendor is used */ | ||
| 1985 | if (!acpi_video_backlight_support()) | ||
| 1986 | return 0; | ||
| 1987 | |||
| 1982 | if (!device->brightness) | 1988 | if (!device->brightness) |
| 1983 | goto out; | 1989 | goto out; |
| 1984 | 1990 | ||
diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index 679cd08b80b4..176f1751237f 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c | |||
| @@ -3204,7 +3204,7 @@ static __devinit int init_ipmi_si(void) | |||
| 3204 | #ifdef CONFIG_ACPI | 3204 | #ifdef CONFIG_ACPI |
| 3205 | spmi_find_bmc(); | 3205 | spmi_find_bmc(); |
| 3206 | #endif | 3206 | #endif |
| 3207 | #ifdef CONFIG_PNP | 3207 | #ifdef CONFIG_ACPI |
| 3208 | pnp_register_driver(&ipmi_pnp_driver); | 3208 | pnp_register_driver(&ipmi_pnp_driver); |
| 3209 | #endif | 3209 | #endif |
| 3210 | 3210 | ||
| @@ -3330,7 +3330,7 @@ static __exit void cleanup_ipmi_si(void) | |||
| 3330 | #ifdef CONFIG_PCI | 3330 | #ifdef CONFIG_PCI |
| 3331 | pci_unregister_driver(&ipmi_pci_driver); | 3331 | pci_unregister_driver(&ipmi_pci_driver); |
| 3332 | #endif | 3332 | #endif |
| 3333 | #ifdef CONFIG_PNP | 3333 | #ifdef CONFIG_ACPI |
| 3334 | pnp_unregister_driver(&ipmi_pnp_driver); | 3334 | pnp_unregister_driver(&ipmi_pnp_driver); |
| 3335 | #endif | 3335 | #endif |
| 3336 | 3336 | ||
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index ec4faffe6b05..db32c25e3605 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig | |||
| @@ -231,8 +231,36 @@ config THINKPAD_ACPI | |||
| 231 | 231 | ||
| 232 | This driver was formerly known as ibm-acpi. | 232 | This driver was formerly known as ibm-acpi. |
| 233 | 233 | ||
| 234 | Extra functionality will be available if the rfkill (CONFIG_RFKILL) | ||
| 235 | and/or ALSA (CONFIG_SND) subsystems are available in the kernel. | ||
| 236 | Note that if you want ThinkPad-ACPI to be built-in instead of | ||
| 237 | modular, ALSA and rfkill will also have to be built-in. | ||
| 238 | |||
| 234 | If you have an IBM or Lenovo ThinkPad laptop, say Y or M here. | 239 | If you have an IBM or Lenovo ThinkPad laptop, say Y or M here. |
| 235 | 240 | ||
| 241 | config THINKPAD_ACPI_ALSA_SUPPORT | ||
| 242 | bool "Console audio control ALSA interface" | ||
| 243 | depends on THINKPAD_ACPI | ||
| 244 | depends on SND | ||
| 245 | depends on SND = y || THINKPAD_ACPI = SND | ||
| 246 | default y | ||
| 247 | ---help--- | ||
| 248 | Enables monitoring of the built-in console audio output control | ||
| 249 | (headphone and speakers), which is operated by the mute and (in | ||
| 250 | some ThinkPad models) volume hotkeys. | ||
| 251 | |||
| 252 | If this option is enabled, ThinkPad-ACPI will export an ALSA card | ||
| 253 | with a single read-only mixer control, which should be used for | ||
| 254 | on-screen-display feedback purposes by the Desktop Environment. | ||
| 255 | |||
| 256 | Optionally, the driver will also allow software control (the | ||
| 257 | ALSA mixer will be made read-write). Please refer to the driver | ||
| 258 | documentation for details. | ||
| 259 | |||
| 260 | All IBM models have both volume and mute control. Newer Lenovo | ||
| 261 | models only have mute control (the volume hotkeys are just normal | ||
| 262 | keys and volume control is done through the main HDA mixer). | ||
| 263 | |||
| 236 | config THINKPAD_ACPI_DEBUGFACILITIES | 264 | config THINKPAD_ACPI_DEBUGFACILITIES |
| 237 | bool "Maintainer debug facilities" | 265 | bool "Maintainer debug facilities" |
| 238 | depends on THINKPAD_ACPI | 266 | depends on THINKPAD_ACPI |
diff --git a/drivers/platform/x86/dell-wmi.c b/drivers/platform/x86/dell-wmi.c index 4c7e70299d6b..1b1dddbd5744 100644 --- a/drivers/platform/x86/dell-wmi.c +++ b/drivers/platform/x86/dell-wmi.c | |||
| @@ -202,8 +202,13 @@ static void dell_wmi_notify(u32 value, void *context) | |||
| 202 | struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL }; | 202 | struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL }; |
| 203 | static struct key_entry *key; | 203 | static struct key_entry *key; |
| 204 | union acpi_object *obj; | 204 | union acpi_object *obj; |
| 205 | acpi_status status; | ||
| 205 | 206 | ||
| 206 | wmi_get_event_data(value, &response); | 207 | status = wmi_get_event_data(value, &response); |
| 208 | if (status != AE_OK) { | ||
| 209 | printk(KERN_INFO "dell-wmi: bad event status 0x%x\n", status); | ||
| 210 | return; | ||
| 211 | } | ||
| 207 | 212 | ||
| 208 | obj = (union acpi_object *)response.pointer; | 213 | obj = (union acpi_object *)response.pointer; |
| 209 | 214 | ||
| @@ -325,7 +330,7 @@ static int __init dell_wmi_init(void) | |||
| 325 | int err; | 330 | int err; |
| 326 | acpi_status status; | 331 | acpi_status status; |
| 327 | 332 | ||
| 328 | if (wmi_has_guid(DELL_EVENT_GUID)) { | 333 | if (!wmi_has_guid(DELL_EVENT_GUID)) { |
| 329 | printk(KERN_WARNING "dell-wmi: No known WMI GUID found\n"); | 334 | printk(KERN_WARNING "dell-wmi: No known WMI GUID found\n"); |
| 330 | return -ENODEV; | 335 | return -ENODEV; |
| 331 | } | 336 | } |
diff --git a/drivers/platform/x86/hp-wmi.c b/drivers/platform/x86/hp-wmi.c index 8781d8fa7a57..5b648f0c6075 100644 --- a/drivers/platform/x86/hp-wmi.c +++ b/drivers/platform/x86/hp-wmi.c | |||
| @@ -338,8 +338,13 @@ static void hp_wmi_notify(u32 value, void *context) | |||
| 338 | static struct key_entry *key; | 338 | static struct key_entry *key; |
| 339 | union acpi_object *obj; | 339 | union acpi_object *obj; |
| 340 | int eventcode; | 340 | int eventcode; |
| 341 | acpi_status status; | ||
| 341 | 342 | ||
| 342 | wmi_get_event_data(value, &response); | 343 | status = wmi_get_event_data(value, &response); |
| 344 | if (status != AE_OK) { | ||
| 345 | printk(KERN_INFO "hp-wmi: bad event status 0x%x\n", status); | ||
| 346 | return; | ||
| 347 | } | ||
| 343 | 348 | ||
| 344 | obj = (union acpi_object *)response.pointer; | 349 | obj = (union acpi_object *)response.pointer; |
| 345 | 350 | ||
| @@ -581,7 +586,7 @@ static int __init hp_wmi_init(void) | |||
| 581 | if (wmi_has_guid(HPWMI_EVENT_GUID)) { | 586 | if (wmi_has_guid(HPWMI_EVENT_GUID)) { |
| 582 | err = wmi_install_notify_handler(HPWMI_EVENT_GUID, | 587 | err = wmi_install_notify_handler(HPWMI_EVENT_GUID, |
| 583 | hp_wmi_notify, NULL); | 588 | hp_wmi_notify, NULL); |
| 584 | if (!err) | 589 | if (ACPI_SUCCESS(err)) |
| 585 | hp_wmi_input_setup(); | 590 | hp_wmi_input_setup(); |
| 586 | } | 591 | } |
| 587 | 592 | ||
diff --git a/drivers/platform/x86/msi-wmi.c b/drivers/platform/x86/msi-wmi.c index 7f77f908bb01..f5f70d4c6913 100644 --- a/drivers/platform/x86/msi-wmi.c +++ b/drivers/platform/x86/msi-wmi.c | |||
| @@ -149,8 +149,13 @@ static void msi_wmi_notify(u32 value, void *context) | |||
| 149 | static struct key_entry *key; | 149 | static struct key_entry *key; |
| 150 | union acpi_object *obj; | 150 | union acpi_object *obj; |
| 151 | ktime_t cur; | 151 | ktime_t cur; |
| 152 | acpi_status status; | ||
| 152 | 153 | ||
| 153 | wmi_get_event_data(value, &response); | 154 | status = wmi_get_event_data(value, &response); |
| 155 | if (status != AE_OK) { | ||
| 156 | printk(KERN_INFO DRV_PFX "bad event status 0x%x\n", status); | ||
| 157 | return; | ||
| 158 | } | ||
| 154 | 159 | ||
| 155 | obj = (union acpi_object *)response.pointer; | 160 | obj = (union acpi_object *)response.pointer; |
| 156 | 161 | ||
| @@ -236,7 +241,7 @@ static int __init msi_wmi_init(void) | |||
| 236 | } | 241 | } |
| 237 | err = wmi_install_notify_handler(MSIWMI_EVENT_GUID, | 242 | err = wmi_install_notify_handler(MSIWMI_EVENT_GUID, |
| 238 | msi_wmi_notify, NULL); | 243 | msi_wmi_notify, NULL); |
| 239 | if (err) | 244 | if (ACPI_FAILURE(err)) |
| 240 | return -EINVAL; | 245 | return -EINVAL; |
| 241 | 246 | ||
| 242 | err = msi_wmi_input_setup(); | 247 | err = msi_wmi_input_setup(); |
diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index 448c8aeb166b..e67e4feb35cb 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c | |||
| @@ -6384,11 +6384,13 @@ static struct ibm_struct brightness_driver_data = { | |||
| 6384 | * and we leave them unchanged. | 6384 | * and we leave them unchanged. |
| 6385 | */ | 6385 | */ |
| 6386 | 6386 | ||
| 6387 | #ifdef CONFIG_THINKPAD_ACPI_ALSA_SUPPORT | ||
| 6388 | |||
| 6387 | #define TPACPI_ALSA_DRVNAME "ThinkPad EC" | 6389 | #define TPACPI_ALSA_DRVNAME "ThinkPad EC" |
| 6388 | #define TPACPI_ALSA_SHRTNAME "ThinkPad Console Audio Control" | 6390 | #define TPACPI_ALSA_SHRTNAME "ThinkPad Console Audio Control" |
| 6389 | #define TPACPI_ALSA_MIXERNAME TPACPI_ALSA_SHRTNAME | 6391 | #define TPACPI_ALSA_MIXERNAME TPACPI_ALSA_SHRTNAME |
| 6390 | 6392 | ||
| 6391 | static int alsa_index = SNDRV_DEFAULT_IDX1; | 6393 | static int alsa_index = ~((1 << (SNDRV_CARDS - 3)) - 1); /* last three slots */ |
| 6392 | static char *alsa_id = "ThinkPadEC"; | 6394 | static char *alsa_id = "ThinkPadEC"; |
| 6393 | static int alsa_enable = SNDRV_DEFAULT_ENABLE1; | 6395 | static int alsa_enable = SNDRV_DEFAULT_ENABLE1; |
| 6394 | 6396 | ||
| @@ -6705,10 +6707,11 @@ static int __init volume_create_alsa_mixer(void) | |||
| 6705 | 6707 | ||
| 6706 | rc = snd_card_create(alsa_index, alsa_id, THIS_MODULE, | 6708 | rc = snd_card_create(alsa_index, alsa_id, THIS_MODULE, |
| 6707 | sizeof(struct tpacpi_alsa_data), &card); | 6709 | sizeof(struct tpacpi_alsa_data), &card); |
| 6708 | if (rc < 0) | 6710 | if (rc < 0 || !card) { |
| 6709 | return rc; | 6711 | printk(TPACPI_ERR |
| 6710 | if (!card) | 6712 | "Failed to create ALSA card structures: %d\n", rc); |
| 6711 | return -ENOMEM; | 6713 | return 1; |
| 6714 | } | ||
| 6712 | 6715 | ||
| 6713 | BUG_ON(!card->private_data); | 6716 | BUG_ON(!card->private_data); |
| 6714 | data = card->private_data; | 6717 | data = card->private_data; |
| @@ -6741,8 +6744,9 @@ static int __init volume_create_alsa_mixer(void) | |||
| 6741 | rc = snd_ctl_add(card, ctl_vol); | 6744 | rc = snd_ctl_add(card, ctl_vol); |
| 6742 | if (rc < 0) { | 6745 | if (rc < 0) { |
| 6743 | printk(TPACPI_ERR | 6746 | printk(TPACPI_ERR |
| 6744 | "Failed to create ALSA volume control\n"); | 6747 | "Failed to create ALSA volume control: %d\n", |
| 6745 | goto err_out; | 6748 | rc); |
| 6749 | goto err_exit; | ||
| 6746 | } | 6750 | } |
| 6747 | data->ctl_vol_id = &ctl_vol->id; | 6751 | data->ctl_vol_id = &ctl_vol->id; |
| 6748 | } | 6752 | } |
| @@ -6750,22 +6754,25 @@ static int __init volume_create_alsa_mixer(void) | |||
| 6750 | ctl_mute = snd_ctl_new1(&volume_alsa_control_mute, NULL); | 6754 | ctl_mute = snd_ctl_new1(&volume_alsa_control_mute, NULL); |
| 6751 | rc = snd_ctl_add(card, ctl_mute); | 6755 | rc = snd_ctl_add(card, ctl_mute); |
| 6752 | if (rc < 0) { | 6756 | if (rc < 0) { |
| 6753 | printk(TPACPI_ERR "Failed to create ALSA mute control\n"); | 6757 | printk(TPACPI_ERR "Failed to create ALSA mute control: %d\n", |
| 6754 | goto err_out; | 6758 | rc); |
| 6759 | goto err_exit; | ||
| 6755 | } | 6760 | } |
| 6756 | data->ctl_mute_id = &ctl_mute->id; | 6761 | data->ctl_mute_id = &ctl_mute->id; |
| 6757 | 6762 | ||
| 6758 | snd_card_set_dev(card, &tpacpi_pdev->dev); | 6763 | snd_card_set_dev(card, &tpacpi_pdev->dev); |
| 6759 | rc = snd_card_register(card); | 6764 | rc = snd_card_register(card); |
| 6760 | |||
| 6761 | err_out: | ||
| 6762 | if (rc < 0) { | 6765 | if (rc < 0) { |
| 6763 | snd_card_free(card); | 6766 | printk(TPACPI_ERR "Failed to register ALSA card: %d\n", rc); |
| 6764 | card = NULL; | 6767 | goto err_exit; |
| 6765 | } | 6768 | } |
| 6766 | 6769 | ||
| 6767 | alsa_card = card; | 6770 | alsa_card = card; |
| 6768 | return rc; | 6771 | return 0; |
| 6772 | |||
| 6773 | err_exit: | ||
| 6774 | snd_card_free(card); | ||
| 6775 | return 1; | ||
| 6769 | } | 6776 | } |
| 6770 | 6777 | ||
| 6771 | #define TPACPI_VOL_Q_MUTEONLY 0x0001 /* Mute-only control available */ | 6778 | #define TPACPI_VOL_Q_MUTEONLY 0x0001 /* Mute-only control available */ |
| @@ -7016,6 +7023,28 @@ static struct ibm_struct volume_driver_data = { | |||
| 7016 | .shutdown = volume_shutdown, | 7023 | .shutdown = volume_shutdown, |
| 7017 | }; | 7024 | }; |
| 7018 | 7025 | ||
| 7026 | #else /* !CONFIG_THINKPAD_ACPI_ALSA_SUPPORT */ | ||
| 7027 | |||
| 7028 | #define alsa_card NULL | ||
| 7029 | |||
| 7030 | static void inline volume_alsa_notify_change(void) | ||
| 7031 | { | ||
| 7032 | } | ||
| 7033 | |||
| 7034 | static int __init volume_init(struct ibm_init_struct *iibm) | ||
| 7035 | { | ||
| 7036 | printk(TPACPI_INFO | ||
| 7037 | "volume: disabled as there is no ALSA support in this kernel\n"); | ||
| 7038 | |||
| 7039 | return 1; | ||
| 7040 | } | ||
| 7041 | |||
| 7042 | static struct ibm_struct volume_driver_data = { | ||
| 7043 | .name = "volume", | ||
| 7044 | }; | ||
| 7045 | |||
| 7046 | #endif /* CONFIG_THINKPAD_ACPI_ALSA_SUPPORT */ | ||
| 7047 | |||
| 7019 | /************************************************************************* | 7048 | /************************************************************************* |
| 7020 | * Fan subdriver | 7049 | * Fan subdriver |
| 7021 | */ | 7050 | */ |
| @@ -8738,6 +8767,7 @@ MODULE_PARM_DESC(hotkey_report_mode, | |||
| 8738 | "used for backwards compatibility with userspace, " | 8767 | "used for backwards compatibility with userspace, " |
| 8739 | "see documentation"); | 8768 | "see documentation"); |
| 8740 | 8769 | ||
| 8770 | #ifdef CONFIG_THINKPAD_ACPI_ALSA_SUPPORT | ||
| 8741 | module_param_named(volume_mode, volume_mode, uint, 0444); | 8771 | module_param_named(volume_mode, volume_mode, uint, 0444); |
| 8742 | MODULE_PARM_DESC(volume_mode, | 8772 | MODULE_PARM_DESC(volume_mode, |
| 8743 | "Selects volume control strategy: " | 8773 | "Selects volume control strategy: " |
| @@ -8760,6 +8790,7 @@ module_param_named(id, alsa_id, charp, 0444); | |||
| 8760 | MODULE_PARM_DESC(id, "ALSA id for the ACPI EC Mixer"); | 8790 | MODULE_PARM_DESC(id, "ALSA id for the ACPI EC Mixer"); |
| 8761 | module_param_named(enable, alsa_enable, bool, 0444); | 8791 | module_param_named(enable, alsa_enable, bool, 0444); |
| 8762 | MODULE_PARM_DESC(enable, "Enable the ALSA interface for the ACPI EC Mixer"); | 8792 | MODULE_PARM_DESC(enable, "Enable the ALSA interface for the ACPI EC Mixer"); |
| 8793 | #endif /* CONFIG_THINKPAD_ACPI_ALSA_SUPPORT */ | ||
| 8763 | 8794 | ||
| 8764 | #define TPACPI_PARAM(feature) \ | 8795 | #define TPACPI_PARAM(feature) \ |
| 8765 | module_param_call(feature, set_ibm_param, NULL, NULL, 0); \ | 8796 | module_param_call(feature, set_ibm_param, NULL, NULL, 0); \ |
diff --git a/drivers/platform/x86/wmi.c b/drivers/platform/x86/wmi.c index cc9ad740bda1..b104302fea0a 100644 --- a/drivers/platform/x86/wmi.c +++ b/drivers/platform/x86/wmi.c | |||
| @@ -714,6 +714,22 @@ static int wmi_class_init(void) | |||
| 714 | return ret; | 714 | return ret; |
| 715 | } | 715 | } |
| 716 | 716 | ||
| 717 | static bool guid_already_parsed(const char *guid_string) | ||
| 718 | { | ||
| 719 | struct guid_block *gblock; | ||
| 720 | struct wmi_block *wblock; | ||
| 721 | struct list_head *p; | ||
| 722 | |||
| 723 | list_for_each(p, &wmi_blocks.list) { | ||
| 724 | wblock = list_entry(p, struct wmi_block, list); | ||
| 725 | gblock = &wblock->gblock; | ||
| 726 | |||
| 727 | if (strncmp(gblock->guid, guid_string, 16) == 0) | ||
| 728 | return true; | ||
| 729 | } | ||
| 730 | return false; | ||
| 731 | } | ||
| 732 | |||
| 717 | /* | 733 | /* |
| 718 | * Parse the _WDG method for the GUID data blocks | 734 | * Parse the _WDG method for the GUID data blocks |
| 719 | */ | 735 | */ |
| @@ -723,6 +739,7 @@ static __init acpi_status parse_wdg(acpi_handle handle) | |||
| 723 | union acpi_object *obj; | 739 | union acpi_object *obj; |
| 724 | struct guid_block *gblock; | 740 | struct guid_block *gblock; |
| 725 | struct wmi_block *wblock; | 741 | struct wmi_block *wblock; |
| 742 | char guid_string[37]; | ||
| 726 | acpi_status status; | 743 | acpi_status status; |
| 727 | u32 i, total; | 744 | u32 i, total; |
| 728 | 745 | ||
| @@ -745,6 +762,19 @@ static __init acpi_status parse_wdg(acpi_handle handle) | |||
| 745 | memcpy(gblock, obj->buffer.pointer, obj->buffer.length); | 762 | memcpy(gblock, obj->buffer.pointer, obj->buffer.length); |
| 746 | 763 | ||
| 747 | for (i = 0; i < total; i++) { | 764 | for (i = 0; i < total; i++) { |
| 765 | /* | ||
| 766 | Some WMI devices, like those for nVidia hooks, have a | ||
| 767 | duplicate GUID. It's not clear what we should do in this | ||
| 768 | case yet, so for now, we'll just ignore the duplicate. | ||
| 769 | Anyone who wants to add support for that device can come | ||
| 770 | up with a better workaround for the mess then. | ||
| 771 | */ | ||
| 772 | if (guid_already_parsed(gblock[i].guid) == true) { | ||
| 773 | wmi_gtoa(gblock[i].guid, guid_string); | ||
| 774 | printk(KERN_INFO PREFIX "Skipping duplicate GUID %s\n", | ||
| 775 | guid_string); | ||
| 776 | continue; | ||
| 777 | } | ||
| 748 | wblock = kzalloc(sizeof(struct wmi_block), GFP_KERNEL); | 778 | wblock = kzalloc(sizeof(struct wmi_block), GFP_KERNEL); |
| 749 | if (!wblock) | 779 | if (!wblock) |
| 750 | return AE_NO_MEMORY; | 780 | return AE_NO_MEMORY; |
diff --git a/include/linux/acpi.h b/include/linux/acpi.h index ce945d4845fc..36924255c0d5 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h | |||
| @@ -251,6 +251,7 @@ int acpi_check_mem_region(resource_size_t start, resource_size_t n, | |||
| 251 | void __init acpi_no_s4_hw_signature(void); | 251 | void __init acpi_no_s4_hw_signature(void); |
| 252 | void __init acpi_old_suspend_ordering(void); | 252 | void __init acpi_old_suspend_ordering(void); |
| 253 | void __init acpi_s4_no_nvs(void); | 253 | void __init acpi_s4_no_nvs(void); |
| 254 | void __init acpi_set_sci_en_on_resume(void); | ||
| 254 | #endif /* CONFIG_PM_SLEEP */ | 255 | #endif /* CONFIG_PM_SLEEP */ |
| 255 | 256 | ||
| 256 | struct acpi_osc_context { | 257 | struct acpi_osc_context { |
