diff options
author | Darren Hart <dvhart@infradead.org> | 2017-03-29 12:19:42 -0700 |
---|---|---|
committer | Darren Hart (VMware) <dvhart@infradead.org> | 2017-04-13 10:14:09 -0700 |
commit | 674b5d58366e3f319520a89785c292a60aacb702 (patch) | |
tree | c3ffbc0c7b14aa56c22802a000acbfb42e5f8d1e | |
parent | 6b8e7d8f6881109dedfcf721d72f6bc822f4c580 (diff) | |
parent | ab768386116d0d88b944d0ef958adff082c088a8 (diff) | |
download | linux-stable-674b5d58366e3f319520a89785c292a60aacb702.tar.gz linux-stable-674b5d58366e3f319520a89785c292a60aacb702.tar.bz2 linux-stable-674b5d58366e3f319520a89785c292a60aacb702.zip |
Merge branch 'linux-leds/dell-laptop-changes-for-4.12'
Merge branch 'dell-laptop-changes-for-4.12' of
git://git.kernel.org/pub/scm/linux/kernel/git/j.anaszewski/linux-leds.git
to avoid linux-next merge conflict with dell-laptop.c.
Signed-off-by: Darren Hart (VMware) <dvhart@infradead.org>
-rw-r--r-- | drivers/leds/Kconfig | 9 | ||||
-rw-r--r-- | drivers/leds/Makefile | 1 | ||||
-rw-r--r-- | drivers/leds/trigger/ledtrig-cpu.c | 33 | ||||
-rw-r--r-- | drivers/platform/x86/Kconfig | 8 | ||||
-rw-r--r-- | drivers/platform/x86/Makefile | 1 | ||||
-rw-r--r-- | drivers/platform/x86/dell-laptop.c | 28 | ||||
-rw-r--r-- | drivers/platform/x86/dell-wmi-led.c (renamed from drivers/leds/dell-led.c) | 141 | ||||
-rw-r--r-- | include/linux/dell-led.h | 6 | ||||
-rw-r--r-- | sound/pci/hda/dell_wmi_helper.c | 30 |
9 files changed, 117 insertions, 140 deletions
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig index 275f467956ee..6a88474b2970 100644 --- a/drivers/leds/Kconfig +++ b/drivers/leds/Kconfig @@ -463,15 +463,6 @@ config LEDS_ADP5520 To compile this driver as a module, choose M here: the module will be called leds-adp5520. -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. - config LEDS_MC13783 tristate "LED Support for MC13XXX PMIC" depends on LEDS_CLASS diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile index 6b8273736478..558d24675454 100644 --- a/drivers/leds/Makefile +++ b/drivers/leds/Makefile @@ -52,7 +52,6 @@ obj-$(CONFIG_LEDS_REGULATOR) += leds-regulator.o obj-$(CONFIG_LEDS_INTEL_SS4200) += leds-ss4200.o obj-$(CONFIG_LEDS_LT3593) += leds-lt3593.o obj-$(CONFIG_LEDS_ADP5520) += leds-adp5520.o -obj-$(CONFIG_LEDS_DELL_NETBOOKS) += dell-led.o obj-$(CONFIG_LEDS_MC13783) += leds-mc13783.o obj-$(CONFIG_LEDS_NS2) += leds-ns2.o obj-$(CONFIG_LEDS_NETXBIG) += leds-netxbig.o diff --git a/drivers/leds/trigger/ledtrig-cpu.c b/drivers/leds/trigger/ledtrig-cpu.c index a41896468cb3..66a626091936 100644 --- a/drivers/leds/trigger/ledtrig-cpu.c +++ b/drivers/leds/trigger/ledtrig-cpu.c @@ -31,12 +31,16 @@ #define MAX_NAME_LEN 8 struct led_trigger_cpu { + bool is_active; char name[MAX_NAME_LEN]; struct led_trigger *_trig; }; static DEFINE_PER_CPU(struct led_trigger_cpu, cpu_trig); +static struct led_trigger *trig_cpu_all; +static atomic_t num_active_cpus = ATOMIC_INIT(0); + /** * ledtrig_cpu - emit a CPU event as a trigger * @evt: CPU event to be emitted @@ -47,26 +51,46 @@ static DEFINE_PER_CPU(struct led_trigger_cpu, cpu_trig); void ledtrig_cpu(enum cpu_led_event ledevt) { struct led_trigger_cpu *trig = this_cpu_ptr(&cpu_trig); + bool is_active = trig->is_active; /* Locate the correct CPU LED */ switch (ledevt) { case CPU_LED_IDLE_END: case CPU_LED_START: /* Will turn the LED on, max brightness */ - led_trigger_event(trig->_trig, LED_FULL); + is_active = true; break; case CPU_LED_IDLE_START: case CPU_LED_STOP: case CPU_LED_HALTED: /* Will turn the LED off */ - led_trigger_event(trig->_trig, LED_OFF); + is_active = false; break; default: /* Will leave the LED as it is */ break; } + + if (is_active != trig->is_active) { + unsigned int active_cpus; + unsigned int total_cpus; + + /* Update trigger state */ + trig->is_active = is_active; + atomic_add(is_active ? 1 : -1, &num_active_cpus); + active_cpus = atomic_read(&num_active_cpus); + total_cpus = num_present_cpus(); + + led_trigger_event(trig->_trig, + is_active ? LED_FULL : LED_OFF); + + + led_trigger_event(trig_cpu_all, + DIV_ROUND_UP(LED_FULL * active_cpus, total_cpus)); + + } } EXPORT_SYMBOL(ledtrig_cpu); @@ -113,6 +137,11 @@ static int __init ledtrig_cpu_init(void) BUILD_BUG_ON(CONFIG_NR_CPUS > 9999); /* + * Registering a trigger for all CPUs. + */ + led_trigger_register_simple("cpu", &trig_cpu_all); + + /* * Registering CPU led trigger for each CPU core here * ignores CPU hotplug, but after this CPU hotplug works * fine with this trigger. diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index 4bc88eb52712..e1bffc9bb194 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig @@ -141,6 +141,14 @@ config DELL_WMI_AIO To compile this driver as a module, choose M here: the module will be called dell-wmi-aio. +config DELL_WMI_LED + tristate "External LED on Dell Business Netbooks" + depends on LEDS_CLASS + depends on ACPI_WMI + help + This adds support for the Latitude 2100 and similar + notebooks that have an external LED. + config DELL_SMO8800 tristate "Dell Latitude freefall driver (ACPI SMO88XX)" depends on ACPI diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile index 299d0f9e40f7..776b3a7a4984 100644 --- a/drivers/platform/x86/Makefile +++ b/drivers/platform/x86/Makefile @@ -15,6 +15,7 @@ obj-$(CONFIG_DELL_SMBIOS) += dell-smbios.o obj-$(CONFIG_DELL_LAPTOP) += dell-laptop.o obj-$(CONFIG_DELL_WMI) += dell-wmi.o obj-$(CONFIG_DELL_WMI_AIO) += dell-wmi-aio.o +obj-$(CONFIG_DELL_WMI_LED) += dell-wmi-led.o obj-$(CONFIG_DELL_SMO8800) += dell-smo8800.o obj-$(CONFIG_DELL_RBTN) += dell-rbtn.o obj-$(CONFIG_ACER_WMI) += acer-wmi.o diff --git a/drivers/platform/x86/dell-laptop.c b/drivers/platform/x86/dell-laptop.c index 1cd258b790e8..47fe6264cadf 100644 --- a/drivers/platform/x86/dell-laptop.c +++ b/drivers/platform/x86/dell-laptop.c @@ -29,6 +29,7 @@ #include <linux/mm.h> #include <linux/i8042.h> #include <linux/debugfs.h> +#include <linux/dell-led.h> #include <linux/seq_file.h> #include <acpi/video.h> #include "dell-rbtn.h" @@ -42,6 +43,8 @@ #define KBD_LED_AUTO_50_TOKEN 0x02EB #define KBD_LED_AUTO_75_TOKEN 0x02EC #define KBD_LED_AUTO_100_TOKEN 0x02F6 +#define GLOBAL_MIC_MUTE_ENABLE 0x0364 +#define GLOBAL_MIC_MUTE_DISABLE 0x0365 struct quirk_entry { u8 touchpad_led; @@ -2046,6 +2049,31 @@ static struct notifier_block dell_laptop_notifier = { .notifier_call = dell_laptop_notifier_call, }; +int dell_micmute_led_set(int state) +{ + struct calling_interface_buffer *buffer; + struct calling_interface_token *token; + + 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; + + if (!token) + return -ENODEV; + + 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; +} +EXPORT_SYMBOL_GPL(dell_micmute_led_set); + static int __init dell_init(void) { struct calling_interface_buffer *buffer; diff --git a/drivers/leds/dell-led.c b/drivers/platform/x86/dell-wmi-led.c index b3d6e9c15cf9..a0c7e99530ef 100644 --- a/drivers/leds/dell-led.c +++ b/drivers/platform/x86/dell-wmi-led.c @@ -1,6 +1,4 @@ /* - * dell_led.c - Dell LED Driver - * * Copyright (C) 2010 Dell Inc. * Louis Davis <louis_davis@dell.com> * Jim Dailey <jim_dailey@dell.com> @@ -15,16 +13,12 @@ #include <linux/leds.h> #include <linux/slab.h> #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"); MODULE_LICENSE("GPL"); #define DELL_LED_BIOS_GUID "F6E4FE6E-909D-47cb-8BAB-C9F6F2F8D396" -#define DELL_APP_GUID "A80593CE-A997-11DA-B012-B622A1EF5492" MODULE_ALIAS("wmi:" DELL_LED_BIOS_GUID); /* Error Result Codes: */ @@ -43,53 +37,6 @@ MODULE_ALIAS("wmi:" DELL_LED_BIOS_GUID); #define CMD_LED_OFF 17 #define CMD_LED_BLINK 18 -#define GLOBAL_MIC_MUTE_ENABLE 0x364 -#define GLOBAL_MIC_MUTE_DISABLE 0x365 - -static int dell_micmute_led_set(int state) -{ - struct calling_interface_buffer *buffer; - struct calling_interface_token *token; - - if (!wmi_has_guid(DELL_APP_GUID)) - return -ENODEV; - - 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; - - if (!token) - return -ENODEV; - - 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; -} - -int dell_app_wmi_led_set(int whichled, int on) -{ - int state = 0; - - switch (whichled) { - case DELL_LED_MICMUTE: - state = dell_micmute_led_set(on); - break; - default: - pr_warn("led type %x is not supported\n", whichled); - break; - } - - return state; -} -EXPORT_SYMBOL_GPL(dell_app_wmi_led_set); - struct bios_args { unsigned char length; unsigned char result_code; @@ -99,37 +46,29 @@ struct bios_args { unsigned char off_time; }; -static int dell_led_perform_fn(u8 length, - u8 result_code, - u8 device_id, - u8 command, - u8 on_time, - u8 off_time) +static int dell_led_perform_fn(u8 length, u8 result_code, u8 device_id, + u8 command, u8 on_time, u8 off_time) { - struct bios_args *bios_return; - u8 return_code; - union acpi_object *obj; struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; + struct bios_args *bios_return; struct acpi_buffer input; + union acpi_object *obj; acpi_status status; + u8 return_code; - struct bios_args args; - args.length = length; - args.result_code = result_code; - args.device_id = device_id; - args.command = command; - args.on_time = on_time; - args.off_time = off_time; + struct bios_args args = { + .length = length, + .result_code = result_code, + .device_id = device_id, + .command = command, + .on_time = on_time, + .off_time = off_time + }; input.length = sizeof(struct bios_args); input.pointer = &args; - status = wmi_evaluate_method(DELL_LED_BIOS_GUID, - 1, - 1, - &input, - &output); - + status = wmi_evaluate_method(DELL_LED_BIOS_GUID, 1, 1, &input, &output); if (ACPI_FAILURE(status)) return status; @@ -137,7 +76,7 @@ static int dell_led_perform_fn(u8 length, if (!obj) return -EINVAL; - else if (obj->type != ACPI_TYPE_BUFFER) { + if (obj->type != ACPI_TYPE_BUFFER) { kfree(obj); return -EINVAL; } @@ -170,8 +109,7 @@ static int led_off(void) 0); /* not used */ } -static int led_blink(unsigned char on_eighths, - unsigned char off_eighths) +static int led_blink(unsigned char on_eighths, unsigned char off_eighths) { return dell_led_perform_fn(5, /* Length of command */ INTERFACE_ERROR, /* Init to INTERFACE_ERROR */ @@ -182,7 +120,7 @@ static int led_blink(unsigned char on_eighths, } static void dell_led_set(struct led_classdev *led_cdev, - enum led_brightness value) + enum led_brightness value) { if (value == LED_OFF) led_off(); @@ -191,27 +129,22 @@ static void dell_led_set(struct led_classdev *led_cdev, } static int dell_led_blink(struct led_classdev *led_cdev, - unsigned long *delay_on, - unsigned long *delay_off) + unsigned long *delay_on, unsigned long *delay_off) { unsigned long on_eighths; unsigned long off_eighths; - /* The Dell LED delay is based on 125ms intervals. - Need to round up to next interval. */ + /* + * The Dell LED delay is based on 125ms intervals. + * Need to round up to next interval. + */ - on_eighths = (*delay_on + 124) / 125; - if (0 == on_eighths) - on_eighths = 1; - if (on_eighths > 255) - on_eighths = 255; + on_eighths = DIV_ROUND_UP(*delay_on, 125); + on_eighths = clamp_t(unsigned long, on_eighths, 1, 255); *delay_on = on_eighths * 125; - off_eighths = (*delay_off + 124) / 125; - if (0 == off_eighths) - off_eighths = 1; - if (off_eighths > 255) - off_eighths = 255; + off_eighths = DIV_ROUND_UP(*delay_off, 125); + off_eighths = clamp_t(unsigned long, off_eighths, 1, 255); *delay_off = off_eighths * 125; led_blink(on_eighths, off_eighths); @@ -232,29 +165,21 @@ static int __init dell_led_init(void) { int error = 0; - if (!wmi_has_guid(DELL_LED_BIOS_GUID) && !wmi_has_guid(DELL_APP_GUID)) + if (!wmi_has_guid(DELL_LED_BIOS_GUID)) return -ENODEV; - if (wmi_has_guid(DELL_LED_BIOS_GUID)) { - error = led_off(); - if (error != 0) - return -ENODEV; - - error = led_classdev_register(NULL, &dell_led); - } + error = led_off(); + if (error != 0) + return -ENODEV; - return error; + return led_classdev_register(NULL, &dell_led); } static void __exit dell_led_exit(void) { - int error = 0; + led_classdev_unregister(&dell_led); - if (wmi_has_guid(DELL_LED_BIOS_GUID)) { - error = led_off(); - if (error == 0) - led_classdev_unregister(&dell_led); - } + led_off(); } module_init(dell_led_init); diff --git a/include/linux/dell-led.h b/include/linux/dell-led.h index 7009b8bec77b..3f033c48071e 100644 --- a/include/linux/dell-led.h +++ b/include/linux/dell-led.h @@ -1,10 +1,6 @@ #ifndef __DELL_LED_H__ #define __DELL_LED_H__ -enum { - DELL_LED_MICMUTE, -}; - -int dell_app_wmi_led_set(int whichled, int on); +int dell_micmute_led_set(int on); #endif diff --git a/sound/pci/hda/dell_wmi_helper.c b/sound/pci/hda/dell_wmi_helper.c index 19d41da79f93..7efa7bd7acb2 100644 --- a/sound/pci/hda/dell_wmi_helper.c +++ b/sound/pci/hda/dell_wmi_helper.c @@ -2,11 +2,11 @@ * to be included from codec driver */ -#if IS_ENABLED(CONFIG_LEDS_DELL_NETBOOKS) +#if IS_ENABLED(CONFIG_DELL_LAPTOP) #include <linux/dell-led.h> static int dell_led_value; -static int (*dell_led_set_func)(int, int); +static int (*dell_micmute_led_set_func)(int); static void (*dell_old_cap_hook)(struct hda_codec *, struct snd_kcontrol *, struct snd_ctl_elem_value *); @@ -18,7 +18,7 @@ static void update_dell_wmi_micmute_led(struct hda_codec *codec, if (dell_old_cap_hook) dell_old_cap_hook(codec, kcontrol, ucontrol); - if (!ucontrol || !dell_led_set_func) + if (!ucontrol || !dell_micmute_led_set_func) return; if (strcmp("Capture Switch", ucontrol->id.name) == 0 && ucontrol->id.index == 0) { /* TODO: How do I verify if it's a mono or stereo here? */ @@ -26,8 +26,8 @@ static void update_dell_wmi_micmute_led(struct hda_codec *codec, if (val == dell_led_value) return; dell_led_value = val; - if (dell_led_set_func) - dell_led_set_func(DELL_LED_MICMUTE, dell_led_value); + if (dell_micmute_led_set_func) + dell_micmute_led_set_func(dell_led_value); } } @@ -39,15 +39,15 @@ static void alc_fixup_dell_wmi(struct hda_codec *codec, bool removefunc = false; if (action == HDA_FIXUP_ACT_PROBE) { - if (!dell_led_set_func) - dell_led_set_func = symbol_request(dell_app_wmi_led_set); - if (!dell_led_set_func) { - codec_warn(codec, "Failed to find dell wmi symbol dell_app_wmi_led_set\n"); + if (!dell_micmute_led_set_func) + dell_micmute_led_set_func = symbol_request(dell_micmute_led_set); + if (!dell_micmute_led_set_func) { + codec_warn(codec, "Failed to find dell wmi symbol dell_micmute_led_set\n"); return; } removefunc = true; - if (dell_led_set_func(DELL_LED_MICMUTE, false) >= 0) { + if (dell_micmute_led_set_func(false) >= 0) { dell_led_value = 0; if (spec->gen.num_adc_nids > 1 && !spec->gen.dyn_adc_switch) codec_dbg(codec, "Skipping micmute LED control due to several ADCs"); @@ -60,17 +60,17 @@ static void alc_fixup_dell_wmi(struct hda_codec *codec, } - if (dell_led_set_func && (action == HDA_FIXUP_ACT_FREE || removefunc)) { - symbol_put(dell_app_wmi_led_set); - dell_led_set_func = NULL; + if (dell_micmute_led_set_func && (action == HDA_FIXUP_ACT_FREE || removefunc)) { + symbol_put(dell_micmute_led_set); + dell_micmute_led_set_func = NULL; dell_old_cap_hook = NULL; } } -#else /* CONFIG_LEDS_DELL_NETBOOKS */ +#else /* CONFIG_DELL_LAPTOP */ static void alc_fixup_dell_wmi(struct hda_codec *codec, const struct hda_fixup *fix, int action) { } -#endif /* CONFIG_LEDS_DELL_NETBOOKS */ +#endif /* CONFIG_DELL_LAPTOP */ |