diff options
Diffstat (limited to 'drivers/leds')
-rw-r--r-- | drivers/leds/Kconfig | 1 | ||||
-rw-r--r-- | drivers/leds/dell-led.c | 126 |
2 files changed, 15 insertions, 112 deletions
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig index 1f6415168998..225147863e02 100644 --- a/drivers/leds/Kconfig +++ b/drivers/leds/Kconfig @@ -443,6 +443,7 @@ config LEDS_DELL_NETBOOKS tristate "External LED on Dell Business Netbooks" depends on LEDS_CLASS depends on X86 && ACPI_WMI + depends on DELL_SMBIOS help This adds support for the Latitude 2100 and similar notebooks that have an external LED. diff --git a/drivers/leds/dell-led.c b/drivers/leds/dell-led.c index c36acaf566a6..b3d6e9c15cf9 100644 --- a/drivers/leds/dell-led.c +++ b/drivers/leds/dell-led.c @@ -17,6 +17,7 @@ #include <linux/module.h> #include <linux/dmi.h> #include <linux/dell-led.h> +#include "../platform/x86/dell-smbios.h" MODULE_AUTHOR("Louis Davis/Jim Dailey"); MODULE_DESCRIPTION("Dell LED Control Driver"); @@ -42,120 +43,32 @@ MODULE_ALIAS("wmi:" DELL_LED_BIOS_GUID); #define CMD_LED_OFF 17 #define CMD_LED_BLINK 18 -struct app_wmi_args { - u16 class; - u16 selector; - u32 arg1; - u32 arg2; - u32 arg3; - u32 arg4; - u32 res1; - u32 res2; - u32 res3; - u32 res4; - char dummy[92]; -}; - #define GLOBAL_MIC_MUTE_ENABLE 0x364 #define GLOBAL_MIC_MUTE_DISABLE 0x365 -struct dell_bios_data_token { - u16 tokenid; - u16 location; - u16 value; -}; - -struct __attribute__ ((__packed__)) dell_bios_calling_interface { - struct dmi_header header; - u16 cmd_io_addr; - u8 cmd_io_code; - u32 supported_cmds; - struct dell_bios_data_token damap[]; -}; - -static struct dell_bios_data_token dell_mic_tokens[2]; - -static int dell_wmi_perform_query(struct app_wmi_args *args) -{ - struct app_wmi_args *bios_return; - union acpi_object *obj; - struct acpi_buffer input; - struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; - acpi_status status; - u32 rc = -EINVAL; - - input.length = 128; - input.pointer = args; - - status = wmi_evaluate_method(DELL_APP_GUID, 0, 1, &input, &output); - if (!ACPI_SUCCESS(status)) - goto err_out0; - - obj = output.pointer; - if (!obj) - goto err_out0; - - if (obj->type != ACPI_TYPE_BUFFER) - goto err_out1; - - bios_return = (struct app_wmi_args *)obj->buffer.pointer; - rc = bios_return->res1; - if (rc) - goto err_out1; - - memcpy(args, bios_return, sizeof(struct app_wmi_args)); - rc = 0; - - err_out1: - kfree(obj); - err_out0: - return rc; -} - -static void __init find_micmute_tokens(const struct dmi_header *dm, void *dummy) -{ - struct dell_bios_calling_interface *calling_interface; - struct dell_bios_data_token *token; - int token_size = sizeof(struct dell_bios_data_token); - int i = 0; - - if (dm->type == 0xda && dm->length > 17) { - calling_interface = container_of(dm, - struct dell_bios_calling_interface, header); - - token = &calling_interface->damap[i]; - while (token->tokenid != 0xffff) { - if (token->tokenid == GLOBAL_MIC_MUTE_DISABLE) - memcpy(&dell_mic_tokens[0], token, token_size); - else if (token->tokenid == GLOBAL_MIC_MUTE_ENABLE) - memcpy(&dell_mic_tokens[1], token, token_size); - - i++; - token = &calling_interface->damap[i]; - } - } -} - static int dell_micmute_led_set(int state) { - struct app_wmi_args args; - struct dell_bios_data_token *token; + struct calling_interface_buffer *buffer; + struct calling_interface_token *token; if (!wmi_has_guid(DELL_APP_GUID)) return -ENODEV; - if (state == 0 || state == 1) - token = &dell_mic_tokens[state]; + if (state == 0) + token = dell_smbios_find_token(GLOBAL_MIC_MUTE_DISABLE); + else if (state == 1) + token = dell_smbios_find_token(GLOBAL_MIC_MUTE_ENABLE); else return -EINVAL; - memset(&args, 0, sizeof(struct app_wmi_args)); - - args.class = 1; - args.arg1 = token->location; - args.arg2 = token->value; + if (!token) + return -ENODEV; - dell_wmi_perform_query(&args); + buffer = dell_smbios_get_buffer(); + buffer->input[0] = token->location; + buffer->input[1] = token->value; + dell_smbios_send_request(1, 0); + dell_smbios_release_buffer(); return state; } @@ -177,14 +90,6 @@ int dell_app_wmi_led_set(int whichled, int on) } EXPORT_SYMBOL_GPL(dell_app_wmi_led_set); -static int __init dell_micmute_led_init(void) -{ - memset(dell_mic_tokens, 0, sizeof(struct dell_bios_data_token) * 2); - dmi_walk(find_micmute_tokens, NULL); - - return 0; -} - struct bios_args { unsigned char length; unsigned char result_code; @@ -330,9 +235,6 @@ static int __init dell_led_init(void) if (!wmi_has_guid(DELL_LED_BIOS_GUID) && !wmi_has_guid(DELL_APP_GUID)) return -ENODEV; - if (wmi_has_guid(DELL_APP_GUID)) - error = dell_micmute_led_init(); - if (wmi_has_guid(DELL_LED_BIOS_GUID)) { error = led_off(); if (error != 0) |