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
|
acpi_sleep= [HW,ACPI] Sleep options
|
||||||
Format: { s3_bios, s3_mode, s3_beep, s4_nohwsig,
|
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
|
See Documentation/power/video.txt for information on
|
||||||
s3_bios and s3_mode.
|
s3_bios and s3_mode.
|
||||||
s3_beep is for debugging; it makes the PC's speaker beep
|
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).
|
of _PTS is used by default).
|
||||||
s4_nonvs prevents the kernel from saving/restoring the
|
s4_nonvs prevents the kernel from saving/restoring the
|
||||||
ACPI NVS memory during hibernation.
|
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]
|
acpi_use_timer_override [HW,ACPI]
|
||||||
Use timer override. For some broken Nvidia NF5 boards
|
Use timer override. For some broken Nvidia NF5 boards
|
||||||
|
|
|
@ -1092,8 +1092,8 @@ WARNING:
|
||||||
its level up and down at every change.
|
its level up and down at every change.
|
||||||
|
|
||||||
|
|
||||||
Volume control
|
Volume control (Console Audio control)
|
||||||
--------------
|
--------------------------------------
|
||||||
|
|
||||||
procfs: /proc/acpi/ibm/volume
|
procfs: /proc/acpi/ibm/volume
|
||||||
ALSA: "ThinkPad Console Audio Control", default ID: "ThinkPadEC"
|
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
|
Software volume control should be done only in the main AC97/HDA
|
||||||
mixer.
|
mixer.
|
||||||
|
|
||||||
This feature allows volume control on ThinkPad models with a digital
|
|
||||||
volume knob (when available, not all models have it), as well as
|
About the ThinkPad Console Audio control:
|
||||||
mute/unmute control. The available commands are:
|
|
||||||
|
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 up >/proc/acpi/ibm/volume
|
||||||
echo down >/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
|
echo 'level <level>' >/proc/acpi/ibm/volume
|
||||||
|
|
||||||
The <level> number range is 0 to 14 although not all of them may be
|
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
|
up or down command (the level command will not unmute the volume), or
|
||||||
the unmute command.
|
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
|
You can use the volume_capabilities parameter to tell the driver
|
||||||
whether your thinkpad has volume control or mute-only control:
|
whether your thinkpad has volume control or mute-only control:
|
||||||
volume_capabilities=1 for mixers with mute and volume control,
|
volume_capabilities=1 for mixers with mute and volume control,
|
||||||
|
|
|
@ -162,6 +162,8 @@ static int __init acpi_sleep_setup(char *str)
|
||||||
#endif
|
#endif
|
||||||
if (strncmp(str, "old_ordering", 12) == 0)
|
if (strncmp(str, "old_ordering", 12) == 0)
|
||||||
acpi_old_suspend_ordering();
|
acpi_old_suspend_ordering();
|
||||||
|
if (strncmp(str, "sci_force_enable", 16) == 0)
|
||||||
|
acpi_set_sci_en_on_resume();
|
||||||
str = strchr(str, ',');
|
str = strchr(str, ',');
|
||||||
if (str != NULL)
|
if (str != NULL)
|
||||||
str += strspn(str, ", \t");
|
str += strspn(str, ", \t");
|
||||||
|
|
|
@ -80,6 +80,23 @@ static int acpi_sleep_prepare(u32 acpi_state)
|
||||||
|
|
||||||
#ifdef CONFIG_ACPI_SLEEP
|
#ifdef CONFIG_ACPI_SLEEP
|
||||||
static u32 acpi_target_sleep_state = ACPI_STATE_S0;
|
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
|
* 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'
|
* 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 */
|
#endif /* CONFIG_ACPI_SLEEP */
|
||||||
|
|
||||||
#ifdef CONFIG_SUSPEND
|
#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);
|
extern void do_suspend_lowlevel(void);
|
||||||
|
|
||||||
static u32 acpi_suspend_states[] = {
|
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++);
|
sprintf(name, "acpi_video%d", count++);
|
||||||
device->backlight = backlight_device_register(name,
|
device->backlight = backlight_device_register(name,
|
||||||
NULL, device, &acpi_backlight_ops);
|
NULL, device, &acpi_backlight_ops);
|
||||||
device->backlight->props.max_brightness = device->brightness->count-3;
|
|
||||||
kfree(name);
|
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,
|
result = sysfs_create_link(&device->backlight->dev.kobj,
|
||||||
&device->dev->dev.kobj, "device");
|
&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;
|
unsigned long long level_current, level_next;
|
||||||
int result = -EINVAL;
|
int result = -EINVAL;
|
||||||
|
|
||||||
|
/* no warning message if acpi_backlight=vendor is used */
|
||||||
|
if (!acpi_video_backlight_support())
|
||||||
|
return 0;
|
||||||
|
|
||||||
if (!device->brightness)
|
if (!device->brightness)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
|
|
@ -3204,7 +3204,7 @@ static __devinit int init_ipmi_si(void)
|
||||||
#ifdef CONFIG_ACPI
|
#ifdef CONFIG_ACPI
|
||||||
spmi_find_bmc();
|
spmi_find_bmc();
|
||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_PNP
|
#ifdef CONFIG_ACPI
|
||||||
pnp_register_driver(&ipmi_pnp_driver);
|
pnp_register_driver(&ipmi_pnp_driver);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -3330,7 +3330,7 @@ static __exit void cleanup_ipmi_si(void)
|
||||||
#ifdef CONFIG_PCI
|
#ifdef CONFIG_PCI
|
||||||
pci_unregister_driver(&ipmi_pci_driver);
|
pci_unregister_driver(&ipmi_pci_driver);
|
||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_PNP
|
#ifdef CONFIG_ACPI
|
||||||
pnp_unregister_driver(&ipmi_pnp_driver);
|
pnp_unregister_driver(&ipmi_pnp_driver);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -231,8 +231,36 @@ config THINKPAD_ACPI
|
||||||
|
|
||||||
This driver was formerly known as ibm-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.
|
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
|
config THINKPAD_ACPI_DEBUGFACILITIES
|
||||||
bool "Maintainer debug facilities"
|
bool "Maintainer debug facilities"
|
||||||
depends on THINKPAD_ACPI
|
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 };
|
struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL };
|
||||||
static struct key_entry *key;
|
static struct key_entry *key;
|
||||||
union acpi_object *obj;
|
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;
|
obj = (union acpi_object *)response.pointer;
|
||||||
|
|
||||||
|
@ -325,7 +330,7 @@ static int __init dell_wmi_init(void)
|
||||||
int err;
|
int err;
|
||||||
acpi_status status;
|
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");
|
printk(KERN_WARNING "dell-wmi: No known WMI GUID found\n");
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
|
@ -338,8 +338,13 @@ static void hp_wmi_notify(u32 value, void *context)
|
||||||
static struct key_entry *key;
|
static struct key_entry *key;
|
||||||
union acpi_object *obj;
|
union acpi_object *obj;
|
||||||
int eventcode;
|
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;
|
obj = (union acpi_object *)response.pointer;
|
||||||
|
|
||||||
|
@ -581,7 +586,7 @@ static int __init hp_wmi_init(void)
|
||||||
if (wmi_has_guid(HPWMI_EVENT_GUID)) {
|
if (wmi_has_guid(HPWMI_EVENT_GUID)) {
|
||||||
err = wmi_install_notify_handler(HPWMI_EVENT_GUID,
|
err = wmi_install_notify_handler(HPWMI_EVENT_GUID,
|
||||||
hp_wmi_notify, NULL);
|
hp_wmi_notify, NULL);
|
||||||
if (!err)
|
if (ACPI_SUCCESS(err))
|
||||||
hp_wmi_input_setup();
|
hp_wmi_input_setup();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -149,8 +149,13 @@ static void msi_wmi_notify(u32 value, void *context)
|
||||||
static struct key_entry *key;
|
static struct key_entry *key;
|
||||||
union acpi_object *obj;
|
union acpi_object *obj;
|
||||||
ktime_t cur;
|
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;
|
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,
|
err = wmi_install_notify_handler(MSIWMI_EVENT_GUID,
|
||||||
msi_wmi_notify, NULL);
|
msi_wmi_notify, NULL);
|
||||||
if (err)
|
if (ACPI_FAILURE(err))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
err = msi_wmi_input_setup();
|
err = msi_wmi_input_setup();
|
||||||
|
|
|
@ -6384,11 +6384,13 @@ static struct ibm_struct brightness_driver_data = {
|
||||||
* and we leave them unchanged.
|
* and we leave them unchanged.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifdef CONFIG_THINKPAD_ACPI_ALSA_SUPPORT
|
||||||
|
|
||||||
#define TPACPI_ALSA_DRVNAME "ThinkPad EC"
|
#define TPACPI_ALSA_DRVNAME "ThinkPad EC"
|
||||||
#define TPACPI_ALSA_SHRTNAME "ThinkPad Console Audio Control"
|
#define TPACPI_ALSA_SHRTNAME "ThinkPad Console Audio Control"
|
||||||
#define TPACPI_ALSA_MIXERNAME TPACPI_ALSA_SHRTNAME
|
#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 char *alsa_id = "ThinkPadEC";
|
||||||
static int alsa_enable = SNDRV_DEFAULT_ENABLE1;
|
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,
|
rc = snd_card_create(alsa_index, alsa_id, THIS_MODULE,
|
||||||
sizeof(struct tpacpi_alsa_data), &card);
|
sizeof(struct tpacpi_alsa_data), &card);
|
||||||
if (rc < 0)
|
if (rc < 0 || !card) {
|
||||||
return rc;
|
printk(TPACPI_ERR
|
||||||
if (!card)
|
"Failed to create ALSA card structures: %d\n", rc);
|
||||||
return -ENOMEM;
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
BUG_ON(!card->private_data);
|
BUG_ON(!card->private_data);
|
||||||
data = 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);
|
rc = snd_ctl_add(card, ctl_vol);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
printk(TPACPI_ERR
|
printk(TPACPI_ERR
|
||||||
"Failed to create ALSA volume control\n");
|
"Failed to create ALSA volume control: %d\n",
|
||||||
goto err_out;
|
rc);
|
||||||
|
goto err_exit;
|
||||||
}
|
}
|
||||||
data->ctl_vol_id = &ctl_vol->id;
|
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);
|
ctl_mute = snd_ctl_new1(&volume_alsa_control_mute, NULL);
|
||||||
rc = snd_ctl_add(card, ctl_mute);
|
rc = snd_ctl_add(card, ctl_mute);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
printk(TPACPI_ERR "Failed to create ALSA mute control\n");
|
printk(TPACPI_ERR "Failed to create ALSA mute control: %d\n",
|
||||||
goto err_out;
|
rc);
|
||||||
|
goto err_exit;
|
||||||
}
|
}
|
||||||
data->ctl_mute_id = &ctl_mute->id;
|
data->ctl_mute_id = &ctl_mute->id;
|
||||||
|
|
||||||
snd_card_set_dev(card, &tpacpi_pdev->dev);
|
snd_card_set_dev(card, &tpacpi_pdev->dev);
|
||||||
rc = snd_card_register(card);
|
rc = snd_card_register(card);
|
||||||
|
|
||||||
err_out:
|
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
snd_card_free(card);
|
printk(TPACPI_ERR "Failed to register ALSA card: %d\n", rc);
|
||||||
card = NULL;
|
goto err_exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
alsa_card = card;
|
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 */
|
#define TPACPI_VOL_Q_MUTEONLY 0x0001 /* Mute-only control available */
|
||||||
|
@ -7016,6 +7023,28 @@ static struct ibm_struct volume_driver_data = {
|
||||||
.shutdown = volume_shutdown,
|
.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
|
* Fan subdriver
|
||||||
*/
|
*/
|
||||||
|
@ -8738,6 +8767,7 @@ MODULE_PARM_DESC(hotkey_report_mode,
|
||||||
"used for backwards compatibility with userspace, "
|
"used for backwards compatibility with userspace, "
|
||||||
"see documentation");
|
"see documentation");
|
||||||
|
|
||||||
|
#ifdef CONFIG_THINKPAD_ACPI_ALSA_SUPPORT
|
||||||
module_param_named(volume_mode, volume_mode, uint, 0444);
|
module_param_named(volume_mode, volume_mode, uint, 0444);
|
||||||
MODULE_PARM_DESC(volume_mode,
|
MODULE_PARM_DESC(volume_mode,
|
||||||
"Selects volume control strategy: "
|
"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_PARM_DESC(id, "ALSA id for the ACPI EC Mixer");
|
||||||
module_param_named(enable, alsa_enable, bool, 0444);
|
module_param_named(enable, alsa_enable, bool, 0444);
|
||||||
MODULE_PARM_DESC(enable, "Enable the ALSA interface for the ACPI EC Mixer");
|
MODULE_PARM_DESC(enable, "Enable the ALSA interface for the ACPI EC Mixer");
|
||||||
|
#endif /* CONFIG_THINKPAD_ACPI_ALSA_SUPPORT */
|
||||||
|
|
||||||
#define TPACPI_PARAM(feature) \
|
#define TPACPI_PARAM(feature) \
|
||||||
module_param_call(feature, set_ibm_param, NULL, NULL, 0); \
|
module_param_call(feature, set_ibm_param, NULL, NULL, 0); \
|
||||||
|
|
|
@ -714,6 +714,22 @@ static int wmi_class_init(void)
|
||||||
return ret;
|
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
|
* 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;
|
union acpi_object *obj;
|
||||||
struct guid_block *gblock;
|
struct guid_block *gblock;
|
||||||
struct wmi_block *wblock;
|
struct wmi_block *wblock;
|
||||||
|
char guid_string[37];
|
||||||
acpi_status status;
|
acpi_status status;
|
||||||
u32 i, total;
|
u32 i, total;
|
||||||
|
|
||||||
|
@ -745,6 +762,19 @@ static __init acpi_status parse_wdg(acpi_handle handle)
|
||||||
memcpy(gblock, obj->buffer.pointer, obj->buffer.length);
|
memcpy(gblock, obj->buffer.pointer, obj->buffer.length);
|
||||||
|
|
||||||
for (i = 0; i < total; i++) {
|
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);
|
wblock = kzalloc(sizeof(struct wmi_block), GFP_KERNEL);
|
||||||
if (!wblock)
|
if (!wblock)
|
||||||
return AE_NO_MEMORY;
|
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_no_s4_hw_signature(void);
|
||||||
void __init acpi_old_suspend_ordering(void);
|
void __init acpi_old_suspend_ordering(void);
|
||||||
void __init acpi_s4_no_nvs(void);
|
void __init acpi_s4_no_nvs(void);
|
||||||
|
void __init acpi_set_sci_en_on_resume(void);
|
||||||
#endif /* CONFIG_PM_SLEEP */
|
#endif /* CONFIG_PM_SLEEP */
|
||||||
|
|
||||||
struct acpi_osc_context {
|
struct acpi_osc_context {
|
||||||
|
|
Loading…
Reference in New Issue