Merge branch 'release' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux-acpi-2.6
* 'release' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux-acpi-2.6: ACPI: introduce kernel parameter acpi_sleep=sci_force_enable ACPI: WMI: Survive BIOS with duplicate GUIDs dell-wmi - fix condition to abort driver loading wmi: check find_guid() return value to prevent oops dell-wmi, hp-wmi, msi-wmi: check wmi_get_event_data() return value ACPI: hp-wmi, msi-wmi: clarify that wmi_install_notify_handler() returns an acpi_status dell-wmi: sys_init_module: 'dell_wmi'->init suspiciously returned 21, it should ACPI video: correct error-handling code ACPI video: no warning message if "acpi_backlight=vendor" is used ACPI: fix ACPI=n allmodconfig build thinkpad-acpi: improve Kconfig help text thinkpad-acpi: update volume subdriver documentation thinkpad-acpi: make volume subdriver optional thinkpad-acpi: don't fail to load the entire module due to ALSA problems thinkpad-acpi: don't take the first ALSA slot by default
This commit is contained in:
commit
08d869aa86
|
@ -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
|
||||
|
|
|
@ -1092,8 +1092,8 @@ WARNING:
|
|||
its level up and down at every change.
|
||||
|
||||
|
||||
Volume control
|
||||
--------------
|
||||
Volume control (Console Audio control)
|
||||
--------------------------------------
|
||||
|
||||
procfs: /proc/acpi/ibm/volume
|
||||
ALSA: "ThinkPad Console Audio Control", default ID: "ThinkPadEC"
|
||||
|
@ -1110,9 +1110,53 @@ the desktop environment to just provide on-screen-display feedback.
|
|||
Software volume control should be done only in the main AC97/HDA
|
||||
mixer.
|
||||
|
||||
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:
|
||||
|
||||
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:
|
||||
|
||||
echo up >/proc/acpi/ibm/volume
|
||||
echo down >/proc/acpi/ibm/volume
|
||||
|
@ -1121,12 +1165,10 @@ mute/unmute control. The available commands are:
|
|||
echo 'level <level>' >/proc/acpi/ibm/volume
|
||||
|
||||
The <level> number range is 0 to 14 although not all of them may be
|
||||
distinct. The unmute the volume after the mute command, use either the
|
||||
distinct. To 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,
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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[] = {
|
||||
|
|
|
@ -999,8 +999,10 @@ 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);
|
||||
device->backlight->props.max_brightness = device->brightness->count-3;
|
||||
kfree(name);
|
||||
if (IS_ERR(device->backlight))
|
||||
return;
|
||||
device->backlight->props.max_brightness = device->brightness->count-3;
|
||||
|
||||
result = sysfs_create_link(&device->backlight->dev.kobj,
|
||||
&device->dev->dev.kobj, "device");
|
||||
|
@ -1979,6 +1981,10 @@ 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;
|
||||
|
||||
|
|
|
@ -3204,7 +3204,7 @@ static __devinit int init_ipmi_si(void)
|
|||
#ifdef CONFIG_ACPI
|
||||
spmi_find_bmc();
|
||||
#endif
|
||||
#ifdef CONFIG_PNP
|
||||
#ifdef CONFIG_ACPI
|
||||
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_PNP
|
||||
#ifdef CONFIG_ACPI
|
||||
pnp_unregister_driver(&ipmi_pnp_driver);
|
||||
#endif
|
||||
|
||||
|
|
|
@ -231,8 +231,36 @@ 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
|
||||
|
|
|
@ -202,8 +202,13 @@ 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;
|
||||
|
||||
wmi_get_event_data(value, &response);
|
||||
status = wmi_get_event_data(value, &response);
|
||||
if (status != AE_OK) {
|
||||
printk(KERN_INFO "dell-wmi: bad event status 0x%x\n", status);
|
||||
return;
|
||||
}
|
||||
|
||||
obj = (union acpi_object *)response.pointer;
|
||||
|
||||
|
@ -325,7 +330,7 @@ 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;
|
||||
}
|
||||
|
|
|
@ -338,8 +338,13 @@ static void hp_wmi_notify(u32 value, void *context)
|
|||
static struct key_entry *key;
|
||||
union acpi_object *obj;
|
||||
int eventcode;
|
||||
acpi_status status;
|
||||
|
||||
wmi_get_event_data(value, &response);
|
||||
status = wmi_get_event_data(value, &response);
|
||||
if (status != AE_OK) {
|
||||
printk(KERN_INFO "hp-wmi: bad event status 0x%x\n", status);
|
||||
return;
|
||||
}
|
||||
|
||||
obj = (union acpi_object *)response.pointer;
|
||||
|
||||
|
@ -581,7 +586,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 (!err)
|
||||
if (ACPI_SUCCESS(err))
|
||||
hp_wmi_input_setup();
|
||||
}
|
||||
|
||||
|
|
|
@ -149,8 +149,13 @@ static void msi_wmi_notify(u32 value, void *context)
|
|||
static struct key_entry *key;
|
||||
union acpi_object *obj;
|
||||
ktime_t cur;
|
||||
acpi_status status;
|
||||
|
||||
wmi_get_event_data(value, &response);
|
||||
status = wmi_get_event_data(value, &response);
|
||||
if (status != AE_OK) {
|
||||
printk(KERN_INFO DRV_PFX "bad event status 0x%x\n", status);
|
||||
return;
|
||||
}
|
||||
|
||||
obj = (union acpi_object *)response.pointer;
|
||||
|
||||
|
@ -236,7 +241,7 @@ static int __init msi_wmi_init(void)
|
|||
}
|
||||
err = wmi_install_notify_handler(MSIWMI_EVENT_GUID,
|
||||
msi_wmi_notify, NULL);
|
||||
if (err)
|
||||
if (ACPI_FAILURE(err))
|
||||
return -EINVAL;
|
||||
|
||||
err = msi_wmi_input_setup();
|
||||
|
|
|
@ -6384,11 +6384,13 @@ 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 = SNDRV_DEFAULT_IDX1;
|
||||
static int alsa_index = ~((1 << (SNDRV_CARDS - 3)) - 1); /* last three slots */
|
||||
static char *alsa_id = "ThinkPadEC";
|
||||
static int alsa_enable = SNDRV_DEFAULT_ENABLE1;
|
||||
|
||||
|
@ -6705,10 +6707,11 @@ 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)
|
||||
return rc;
|
||||
if (!card)
|
||||
return -ENOMEM;
|
||||
if (rc < 0 || !card) {
|
||||
printk(TPACPI_ERR
|
||||
"Failed to create ALSA card structures: %d\n", rc);
|
||||
return 1;
|
||||
}
|
||||
|
||||
BUG_ON(!card->private_data);
|
||||
data = card->private_data;
|
||||
|
@ -6741,8 +6744,9 @@ 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\n");
|
||||
goto err_out;
|
||||
"Failed to create ALSA volume control: %d\n",
|
||||
rc);
|
||||
goto err_exit;
|
||||
}
|
||||
data->ctl_vol_id = &ctl_vol->id;
|
||||
}
|
||||
|
@ -6750,22 +6754,25 @@ 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\n");
|
||||
goto err_out;
|
||||
printk(TPACPI_ERR "Failed to create ALSA mute control: %d\n",
|
||||
rc);
|
||||
goto err_exit;
|
||||
}
|
||||
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) {
|
||||
snd_card_free(card);
|
||||
card = NULL;
|
||||
printk(TPACPI_ERR "Failed to register ALSA card: %d\n", rc);
|
||||
goto err_exit;
|
||||
}
|
||||
|
||||
alsa_card = card;
|
||||
return rc;
|
||||
return 0;
|
||||
|
||||
err_exit:
|
||||
snd_card_free(card);
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define TPACPI_VOL_Q_MUTEONLY 0x0001 /* Mute-only control available */
|
||||
|
@ -7016,6 +7023,28 @@ 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
|
||||
*/
|
||||
|
@ -8738,6 +8767,7 @@ 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: "
|
||||
|
@ -8760,6 +8790,7 @@ 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); \
|
||||
|
|
|
@ -714,6 +714,22 @@ 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
|
||||
*/
|
||||
|
@ -723,6 +739,7 @@ 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;
|
||||
|
||||
|
@ -745,6 +762,19 @@ 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;
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Reference in New Issue