From d48eccdba0ba6b4b4aa36b35d440ca5f47c06da7 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Wed, 30 Dec 2009 15:36:42 +0800 Subject: [PATCH] --- yaml --- r: 178646 b: refs/heads/master c: d7f0eea9e431e1b8b0742a74db1a9490730b2a25 h: refs/heads/master v: v3 --- [refs] | 2 +- trunk/Documentation/kernel-parameters.txt | 5 +- trunk/Documentation/laptops/thinkpad-acpi.txt | 58 +++--------------- trunk/arch/x86/kernel/acpi/sleep.c | 2 + trunk/drivers/acpi/sleep.c | 29 +++++---- trunk/drivers/acpi/video.c | 8 +-- trunk/drivers/char/ipmi/ipmi_si_intf.c | 4 +- trunk/drivers/platform/x86/Kconfig | 28 --------- trunk/drivers/platform/x86/dell-wmi.c | 18 ++---- trunk/drivers/platform/x86/hp-wmi.c | 9 +-- trunk/drivers/platform/x86/msi-wmi.c | 9 +-- trunk/drivers/platform/x86/thinkpad_acpi.c | 59 +++++-------------- trunk/drivers/platform/x86/wmi.c | 36 ++--------- trunk/include/linux/acpi.h | 1 + 14 files changed, 64 insertions(+), 204 deletions(-) diff --git a/[refs] b/[refs] index ace2c07ddc6d..7ef61dd9e332 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: cccc67a4cf52a952e6371ac75510994e0bddec96 +refs/heads/master: d7f0eea9e431e1b8b0742a74db1a9490730b2a25 diff --git a/trunk/Documentation/kernel-parameters.txt b/trunk/Documentation/kernel-parameters.txt index 5ba4d9dff113..736d45602886 100644 --- a/trunk/Documentation/kernel-parameters.txt +++ b/trunk/Documentation/kernel-parameters.txt @@ -240,7 +240,7 @@ and is between 256 and 4096 characters. It is defined in the file acpi_sleep= [HW,ACPI] Sleep options Format: { s3_bios, s3_mode, s3_beep, s4_nohwsig, - old_ordering, s4_nonvs } + old_ordering, s4_nonvs, sci_force_enable } See Documentation/power/video.txt for information on s3_bios and s3_mode. 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 of _PTS is used by default). s4_nonvs prevents the kernel from saving/restoring the ACPI NVS memory during hibernation. + sci_force_enable causes the kernel to set SCI_EN directly + on resume from S1/S3 (which is against the ACPI spec, + but some broken systems don't work without it). acpi_use_timer_override [HW,ACPI] Use timer override. For some broken Nvidia NF5 boards diff --git a/trunk/Documentation/laptops/thinkpad-acpi.txt b/trunk/Documentation/laptops/thinkpad-acpi.txt index 75afa1229fd7..169091f75e6d 100644 --- a/trunk/Documentation/laptops/thinkpad-acpi.txt +++ b/trunk/Documentation/laptops/thinkpad-acpi.txt @@ -1092,8 +1092,8 @@ WARNING: its level up and down at every change. -Volume control (Console Audio control) --------------------------------------- +Volume control +-------------- procfs: /proc/acpi/ibm/volume ALSA: "ThinkPad Console Audio Control", default ID: "ThinkPadEC" @@ -1110,53 +1110,9 @@ the desktop environment to just provide on-screen-display feedback. Software volume control should be done only in the main AC97/HDA mixer. - -About the ThinkPad Console Audio control: - -ThinkPads have a built-in amplifier and muting circuit that drives the -console headphone and speakers. This circuit is after the main AC97 -or HDA mixer in the audio path, and under exclusive control of the -firmware. - -ThinkPads have three special hotkeys to interact with the console -audio control: volume up, volume down and mute. - -It is worth noting that the normal way the mute function works (on -ThinkPads that do not have a "mute LED") is: - -1. Press mute to mute. It will *always* mute, you can press it as - many times as you want, and the sound will remain mute. - -2. Press either volume key to unmute the ThinkPad (it will _not_ - change the volume, it will just unmute). - -This is a very superior design when compared to the cheap software-only -mute-toggle solution found on normal consumer laptops: you can be -absolutely sure the ThinkPad will not make noise if you press the mute -button, no matter the previous state. - -The IBM ThinkPads, and the earlier Lenovo ThinkPads have variable-gain -amplifiers driving the speakers and headphone output, and the firmware -also handles volume control for the headphone and speakers on these -ThinkPads without any help from the operating system (this volume -control stage exists after the main AC97 or HDA mixer in the audio -path). - -The newer Lenovo models only have firmware mute control, and depend on -the main HDA mixer to do volume control (which is done by the operating -system). In this case, the volume keys are filtered out for unmute -key press (there are some firmware bugs in this area) and delivered as -normal key presses to the operating system (thinkpad-acpi is not -involved). - - -The ThinkPad-ACPI volume control: - -The preferred way to interact with the Console Audio control is the -ALSA interface. - -The legacy procfs interface allows one to read the current state, -and if volume control is enabled, accepts the following commands: +This feature allows volume control on ThinkPad models with a digital +volume knob (when available, not all models have it), as well as +mute/unmute control. The available commands are: echo up >/proc/acpi/ibm/volume echo down >/proc/acpi/ibm/volume @@ -1165,10 +1121,12 @@ and if volume control is enabled, accepts the following commands: echo 'level ' >/proc/acpi/ibm/volume The number range is 0 to 14 although not all of them may be -distinct. To unmute the volume after the mute command, use either the +distinct. The unmute the volume after the mute command, use either the up or down command (the level command will not unmute the volume), or the unmute command. +The current volume level and mute state is shown in the file. + You can use the volume_capabilities parameter to tell the driver whether your thinkpad has volume control or mute-only control: volume_capabilities=1 for mixers with mute and volume control, diff --git a/trunk/arch/x86/kernel/acpi/sleep.c b/trunk/arch/x86/kernel/acpi/sleep.c index 82e508677b91..f9961034e557 100644 --- a/trunk/arch/x86/kernel/acpi/sleep.c +++ b/trunk/arch/x86/kernel/acpi/sleep.c @@ -162,6 +162,8 @@ static int __init acpi_sleep_setup(char *str) #endif if (strncmp(str, "old_ordering", 12) == 0) acpi_old_suspend_ordering(); + if (strncmp(str, "sci_force_enable", 16) == 0) + acpi_set_sci_en_on_resume(); str = strchr(str, ','); if (str != NULL) str += strspn(str, ", \t"); diff --git a/trunk/drivers/acpi/sleep.c b/trunk/drivers/acpi/sleep.c index 5f2c379ab7bf..79d33d908b5a 100644 --- a/trunk/drivers/acpi/sleep.c +++ b/trunk/drivers/acpi/sleep.c @@ -80,6 +80,23 @@ static int acpi_sleep_prepare(u32 acpi_state) #ifdef CONFIG_ACPI_SLEEP static u32 acpi_target_sleep_state = ACPI_STATE_S0; +/* + * According to the ACPI specification the BIOS should make sure that ACPI is + * enabled and SCI_EN bit is set on wake-up from S1 - S3 sleep states. Still, + * some BIOSes don't do that and therefore we use acpi_enable() to enable ACPI + * on such systems during resume. Unfortunately that doesn't help in + * particularly pathological cases in which SCI_EN has to be set directly on + * resume, although the specification states very clearly that this flag is + * owned by the hardware. The set_sci_en_on_resume variable will be set in such + * cases. + */ +static bool set_sci_en_on_resume; + +void __init acpi_set_sci_en_on_resume(void) +{ + set_sci_en_on_resume = true; +} + /* * ACPI 1.0 wants us to execute _PTS before suspending devices, so we allow the * user to request that behavior by using the 'acpi_old_suspend_ordering' @@ -170,18 +187,6 @@ static void acpi_pm_end(void) #endif /* CONFIG_ACPI_SLEEP */ #ifdef CONFIG_SUSPEND -/* - * According to the ACPI specification the BIOS should make sure that ACPI is - * enabled and SCI_EN bit is set on wake-up from S1 - S3 sleep states. Still, - * some BIOSes don't do that and therefore we use acpi_enable() to enable ACPI - * on such systems during resume. Unfortunately that doesn't help in - * particularly pathological cases in which SCI_EN has to be set directly on - * resume, although the specification states very clearly that this flag is - * owned by the hardware. The set_sci_en_on_resume variable will be set in such - * cases. - */ -static bool set_sci_en_on_resume; - extern void do_suspend_lowlevel(void); static u32 acpi_suspend_states[] = { diff --git a/trunk/drivers/acpi/video.c b/trunk/drivers/acpi/video.c index 72e76b4b6538..05dff631591c 100644 --- a/trunk/drivers/acpi/video.c +++ b/trunk/drivers/acpi/video.c @@ -999,10 +999,8 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device) sprintf(name, "acpi_video%d", count++); device->backlight = backlight_device_register(name, NULL, device, &acpi_backlight_ops); - kfree(name); - if (IS_ERR(device->backlight)) - return; device->backlight->props.max_brightness = device->brightness->count-3; + kfree(name); result = sysfs_create_link(&device->backlight->dev.kobj, &device->dev->dev.kobj, "device"); @@ -1981,10 +1979,6 @@ acpi_video_switch_brightness(struct acpi_video_device *device, int event) unsigned long long level_current, level_next; int result = -EINVAL; - /* no warning message if acpi_backlight=vendor is used */ - if (!acpi_video_backlight_support()) - return 0; - if (!device->brightness) goto out; diff --git a/trunk/drivers/char/ipmi/ipmi_si_intf.c b/trunk/drivers/char/ipmi/ipmi_si_intf.c index 176f1751237f..679cd08b80b4 100644 --- a/trunk/drivers/char/ipmi/ipmi_si_intf.c +++ b/trunk/drivers/char/ipmi/ipmi_si_intf.c @@ -3204,7 +3204,7 @@ static __devinit int init_ipmi_si(void) #ifdef CONFIG_ACPI spmi_find_bmc(); #endif -#ifdef CONFIG_ACPI +#ifdef CONFIG_PNP pnp_register_driver(&ipmi_pnp_driver); #endif @@ -3330,7 +3330,7 @@ static __exit void cleanup_ipmi_si(void) #ifdef CONFIG_PCI pci_unregister_driver(&ipmi_pci_driver); #endif -#ifdef CONFIG_ACPI +#ifdef CONFIG_PNP pnp_unregister_driver(&ipmi_pnp_driver); #endif diff --git a/trunk/drivers/platform/x86/Kconfig b/trunk/drivers/platform/x86/Kconfig index db32c25e3605..ec4faffe6b05 100644 --- a/trunk/drivers/platform/x86/Kconfig +++ b/trunk/drivers/platform/x86/Kconfig @@ -231,36 +231,8 @@ config THINKPAD_ACPI This driver was formerly known as ibm-acpi. - Extra functionality will be available if the rfkill (CONFIG_RFKILL) - and/or ALSA (CONFIG_SND) subsystems are available in the kernel. - Note that if you want ThinkPad-ACPI to be built-in instead of - modular, ALSA and rfkill will also have to be built-in. - If you have an IBM or Lenovo ThinkPad laptop, say Y or M here. -config THINKPAD_ACPI_ALSA_SUPPORT - bool "Console audio control ALSA interface" - depends on THINKPAD_ACPI - depends on SND - depends on SND = y || THINKPAD_ACPI = SND - default y - ---help--- - Enables monitoring of the built-in console audio output control - (headphone and speakers), which is operated by the mute and (in - some ThinkPad models) volume hotkeys. - - If this option is enabled, ThinkPad-ACPI will export an ALSA card - with a single read-only mixer control, which should be used for - on-screen-display feedback purposes by the Desktop Environment. - - Optionally, the driver will also allow software control (the - ALSA mixer will be made read-write). Please refer to the driver - documentation for details. - - All IBM models have both volume and mute control. Newer Lenovo - models only have mute control (the volume hotkeys are just normal - keys and volume control is done through the main HDA mixer). - config THINKPAD_ACPI_DEBUGFACILITIES bool "Maintainer debug facilities" depends on THINKPAD_ACPI diff --git a/trunk/drivers/platform/x86/dell-wmi.c b/trunk/drivers/platform/x86/dell-wmi.c index 1b1dddbd5744..916ccb2b316c 100644 --- a/trunk/drivers/platform/x86/dell-wmi.c +++ b/trunk/drivers/platform/x86/dell-wmi.c @@ -202,13 +202,8 @@ static void dell_wmi_notify(u32 value, void *context) struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL }; static struct key_entry *key; union acpi_object *obj; - acpi_status status; - status = wmi_get_event_data(value, &response); - if (status != AE_OK) { - printk(KERN_INFO "dell-wmi: bad event status 0x%x\n", status); - return; - } + wmi_get_event_data(value, &response); obj = (union acpi_object *)response.pointer; @@ -328,9 +323,8 @@ static int __init dell_wmi_input_setup(void) static int __init dell_wmi_init(void) { int err; - acpi_status status; - if (!wmi_has_guid(DELL_EVENT_GUID)) { + if (wmi_has_guid(DELL_EVENT_GUID)) { printk(KERN_WARNING "dell-wmi: No known WMI GUID found\n"); return -ENODEV; } @@ -342,14 +336,14 @@ static int __init dell_wmi_init(void) if (err) return err; - status = wmi_install_notify_handler(DELL_EVENT_GUID, + err = wmi_install_notify_handler(DELL_EVENT_GUID, dell_wmi_notify, NULL); - if (ACPI_FAILURE(status)) { + if (err) { input_unregister_device(dell_wmi_input_dev); printk(KERN_ERR "dell-wmi: Unable to register notify handler - %d\n", - status); - return -ENODEV; + err); + return err; } return 0; diff --git a/trunk/drivers/platform/x86/hp-wmi.c b/trunk/drivers/platform/x86/hp-wmi.c index 5b648f0c6075..8781d8fa7a57 100644 --- a/trunk/drivers/platform/x86/hp-wmi.c +++ b/trunk/drivers/platform/x86/hp-wmi.c @@ -338,13 +338,8 @@ static void hp_wmi_notify(u32 value, void *context) static struct key_entry *key; union acpi_object *obj; int eventcode; - acpi_status status; - status = wmi_get_event_data(value, &response); - if (status != AE_OK) { - printk(KERN_INFO "hp-wmi: bad event status 0x%x\n", status); - return; - } + wmi_get_event_data(value, &response); obj = (union acpi_object *)response.pointer; @@ -586,7 +581,7 @@ static int __init hp_wmi_init(void) if (wmi_has_guid(HPWMI_EVENT_GUID)) { err = wmi_install_notify_handler(HPWMI_EVENT_GUID, hp_wmi_notify, NULL); - if (ACPI_SUCCESS(err)) + if (!err) hp_wmi_input_setup(); } diff --git a/trunk/drivers/platform/x86/msi-wmi.c b/trunk/drivers/platform/x86/msi-wmi.c index f5f70d4c6913..7f77f908bb01 100644 --- a/trunk/drivers/platform/x86/msi-wmi.c +++ b/trunk/drivers/platform/x86/msi-wmi.c @@ -149,13 +149,8 @@ static void msi_wmi_notify(u32 value, void *context) static struct key_entry *key; union acpi_object *obj; ktime_t cur; - acpi_status status; - status = wmi_get_event_data(value, &response); - if (status != AE_OK) { - printk(KERN_INFO DRV_PFX "bad event status 0x%x\n", status); - return; - } + wmi_get_event_data(value, &response); obj = (union acpi_object *)response.pointer; @@ -241,7 +236,7 @@ static int __init msi_wmi_init(void) } err = wmi_install_notify_handler(MSIWMI_EVENT_GUID, msi_wmi_notify, NULL); - if (ACPI_FAILURE(err)) + if (err) return -EINVAL; err = msi_wmi_input_setup(); diff --git a/trunk/drivers/platform/x86/thinkpad_acpi.c b/trunk/drivers/platform/x86/thinkpad_acpi.c index e67e4feb35cb..448c8aeb166b 100644 --- a/trunk/drivers/platform/x86/thinkpad_acpi.c +++ b/trunk/drivers/platform/x86/thinkpad_acpi.c @@ -6384,13 +6384,11 @@ static struct ibm_struct brightness_driver_data = { * and we leave them unchanged. */ -#ifdef CONFIG_THINKPAD_ACPI_ALSA_SUPPORT - #define TPACPI_ALSA_DRVNAME "ThinkPad EC" #define TPACPI_ALSA_SHRTNAME "ThinkPad Console Audio Control" #define TPACPI_ALSA_MIXERNAME TPACPI_ALSA_SHRTNAME -static int alsa_index = ~((1 << (SNDRV_CARDS - 3)) - 1); /* last three slots */ +static int alsa_index = SNDRV_DEFAULT_IDX1; static char *alsa_id = "ThinkPadEC"; static int alsa_enable = SNDRV_DEFAULT_ENABLE1; @@ -6707,11 +6705,10 @@ static int __init volume_create_alsa_mixer(void) rc = snd_card_create(alsa_index, alsa_id, THIS_MODULE, sizeof(struct tpacpi_alsa_data), &card); - if (rc < 0 || !card) { - printk(TPACPI_ERR - "Failed to create ALSA card structures: %d\n", rc); - return 1; - } + if (rc < 0) + return rc; + if (!card) + return -ENOMEM; BUG_ON(!card->private_data); data = card->private_data; @@ -6744,9 +6741,8 @@ static int __init volume_create_alsa_mixer(void) rc = snd_ctl_add(card, ctl_vol); if (rc < 0) { printk(TPACPI_ERR - "Failed to create ALSA volume control: %d\n", - rc); - goto err_exit; + "Failed to create ALSA volume control\n"); + goto err_out; } data->ctl_vol_id = &ctl_vol->id; } @@ -6754,25 +6750,22 @@ static int __init volume_create_alsa_mixer(void) ctl_mute = snd_ctl_new1(&volume_alsa_control_mute, NULL); rc = snd_ctl_add(card, ctl_mute); if (rc < 0) { - printk(TPACPI_ERR "Failed to create ALSA mute control: %d\n", - rc); - goto err_exit; + printk(TPACPI_ERR "Failed to create ALSA mute control\n"); + goto err_out; } data->ctl_mute_id = &ctl_mute->id; snd_card_set_dev(card, &tpacpi_pdev->dev); rc = snd_card_register(card); + +err_out: if (rc < 0) { - printk(TPACPI_ERR "Failed to register ALSA card: %d\n", rc); - goto err_exit; + snd_card_free(card); + card = NULL; } alsa_card = card; - return 0; - -err_exit: - snd_card_free(card); - return 1; + return rc; } #define TPACPI_VOL_Q_MUTEONLY 0x0001 /* Mute-only control available */ @@ -7023,28 +7016,6 @@ static struct ibm_struct volume_driver_data = { .shutdown = volume_shutdown, }; -#else /* !CONFIG_THINKPAD_ACPI_ALSA_SUPPORT */ - -#define alsa_card NULL - -static void inline volume_alsa_notify_change(void) -{ -} - -static int __init volume_init(struct ibm_init_struct *iibm) -{ - printk(TPACPI_INFO - "volume: disabled as there is no ALSA support in this kernel\n"); - - return 1; -} - -static struct ibm_struct volume_driver_data = { - .name = "volume", -}; - -#endif /* CONFIG_THINKPAD_ACPI_ALSA_SUPPORT */ - /************************************************************************* * Fan subdriver */ @@ -8767,7 +8738,6 @@ MODULE_PARM_DESC(hotkey_report_mode, "used for backwards compatibility with userspace, " "see documentation"); -#ifdef CONFIG_THINKPAD_ACPI_ALSA_SUPPORT module_param_named(volume_mode, volume_mode, uint, 0444); MODULE_PARM_DESC(volume_mode, "Selects volume control strategy: " @@ -8790,7 +8760,6 @@ module_param_named(id, alsa_id, charp, 0444); MODULE_PARM_DESC(id, "ALSA id for the ACPI EC Mixer"); module_param_named(enable, alsa_enable, bool, 0444); MODULE_PARM_DESC(enable, "Enable the ALSA interface for the ACPI EC Mixer"); -#endif /* CONFIG_THINKPAD_ACPI_ALSA_SUPPORT */ #define TPACPI_PARAM(feature) \ module_param_call(feature, set_ibm_param, NULL, NULL, 0); \ diff --git a/trunk/drivers/platform/x86/wmi.c b/trunk/drivers/platform/x86/wmi.c index b104302fea0a..9f93d6c0f510 100644 --- a/trunk/drivers/platform/x86/wmi.c +++ b/trunk/drivers/platform/x86/wmi.c @@ -492,7 +492,8 @@ wmi_notify_handler handler, void *data) if (!guid || !handler) return AE_BAD_PARAMETER; - if (!find_guid(guid, &block)) + find_guid(guid, &block); + if (!block) return AE_NOT_EXIST; if (block->handler) @@ -520,7 +521,8 @@ acpi_status wmi_remove_notify_handler(const char *guid) if (!guid) return AE_BAD_PARAMETER; - if (!find_guid(guid, &block)) + find_guid(guid, &block); + if (!block) return AE_NOT_EXIST; if (!block->handler) @@ -714,22 +716,6 @@ static int wmi_class_init(void) return ret; } -static bool guid_already_parsed(const char *guid_string) -{ - struct guid_block *gblock; - struct wmi_block *wblock; - struct list_head *p; - - list_for_each(p, &wmi_blocks.list) { - wblock = list_entry(p, struct wmi_block, list); - gblock = &wblock->gblock; - - if (strncmp(gblock->guid, guid_string, 16) == 0) - return true; - } - return false; -} - /* * Parse the _WDG method for the GUID data blocks */ @@ -739,7 +725,6 @@ static __init acpi_status parse_wdg(acpi_handle handle) union acpi_object *obj; struct guid_block *gblock; struct wmi_block *wblock; - char guid_string[37]; acpi_status status; u32 i, total; @@ -762,19 +747,6 @@ static __init acpi_status parse_wdg(acpi_handle handle) memcpy(gblock, obj->buffer.pointer, obj->buffer.length); for (i = 0; i < total; i++) { - /* - Some WMI devices, like those for nVidia hooks, have a - duplicate GUID. It's not clear what we should do in this - case yet, so for now, we'll just ignore the duplicate. - Anyone who wants to add support for that device can come - up with a better workaround for the mess then. - */ - if (guid_already_parsed(gblock[i].guid) == true) { - wmi_gtoa(gblock[i].guid, guid_string); - printk(KERN_INFO PREFIX "Skipping duplicate GUID %s\n", - guid_string); - continue; - } wblock = kzalloc(sizeof(struct wmi_block), GFP_KERNEL); if (!wblock) return AE_NO_MEMORY; diff --git a/trunk/include/linux/acpi.h b/trunk/include/linux/acpi.h index ce945d4845fc..36924255c0d5 100644 --- a/trunk/include/linux/acpi.h +++ b/trunk/include/linux/acpi.h @@ -251,6 +251,7 @@ int acpi_check_mem_region(resource_size_t start, resource_size_t n, void __init acpi_no_s4_hw_signature(void); void __init acpi_old_suspend_ordering(void); void __init acpi_s4_no_nvs(void); +void __init acpi_set_sci_en_on_resume(void); #endif /* CONFIG_PM_SLEEP */ struct acpi_osc_context {