mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-10 15:13:44 -04:00
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>
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -112,6 +136,11 @@ static int __init ledtrig_cpu_init(void)
|
||||
/* Supports up to 9999 cpu cores */
|
||||
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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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_off();
|
||||
if (error != 0)
|
||||
return -ENODEV;
|
||||
|
||||
error = led_classdev_register(NULL, &dell_led);
|
||||
}
|
||||
|
||||
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);
|
||||
@@ -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
|
||||
|
||||
@@ -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 */
|
||||
|
||||
Reference in New Issue
Block a user