aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMárton Németh <nm127@freemail.hu>2007-10-31 06:46:41 -0400
committerRichard Purdie <rpurdie@rpsys.net>2008-02-07 04:22:17 -0500
commitcec035de8265b18252742ef359b12e9694641112 (patch)
treee9098d3aa81807a36aeafe2503ec40f217e4cba9
parent488b5ec871191359b9b79262a3d48456dae7ea5f (diff)
leds: Add clevo notebook LED driver
The driver supports the mail LED commonly found on different Clevo notebooks. The driver access the LED through the i8042 hardware which is handled by the input subsystem. Signed-off-by: Márton Németh <nm127@freemail.hu> Signed-off-by: Richard Purdie <rpurdie@rpsys.net>
-rw-r--r--drivers/leds/Kconfig24
-rw-r--r--drivers/leds/Makefile1
-rw-r--r--drivers/leds/leds-clevo-mail.c182
3 files changed, 207 insertions, 0 deletions
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
index ec568fa1c6cc..cf3a6d4d9475 100644
--- a/drivers/leds/Kconfig
+++ b/drivers/leds/Kconfig
@@ -114,6 +114,30 @@ config LEDS_CM_X270
114 help 114 help
115 This option enables support for the CM-X270 LEDs. 115 This option enables support for the CM-X270 LEDs.
116 116
117config LEDS_CLEVO_MAIL
118 tristate "Mail LED on Clevo notebook (EXPERIMENTAL)"
119 depends on LEDS_CLASS && X86 && SERIO_I8042 && DMI && EXPERIMENTAL
120 help
121 This driver makes the mail LED accessible from userspace
122 programs through the leds subsystem. This LED have three
123 known mode: off, blink at 0.5Hz and blink at 1Hz.
124
125 As this LED cannot change it's brightness it blinks instead.
126 The brightness value 0 means off, 1..127 means blink at 0.5Hz
127 and 128..255 means blink at 1Hz.
128
129 This module can drive the mail LED for the following notebooks:
130
131 Clevo D410J
132 Clevo D410V
133 Clevo D400V/D470V (not tested, but might work)
134 Clevo M540N
135 Clevo M5x0N (not tested, but might work)
136 Positivo Mobile (Clevo M5x0V)
137
138 To compile this driver as a module, choose M here: the
139 module will be called leds-clevo-mail.
140
117comment "LED Triggers" 141comment "LED Triggers"
118 142
119config LEDS_TRIGGERS 143config LEDS_TRIGGERS
diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile
index a60de1b46c2c..e433e2f4e52b 100644
--- a/drivers/leds/Makefile
+++ b/drivers/leds/Makefile
@@ -19,6 +19,7 @@ obj-$(CONFIG_LEDS_COBALT_QUBE) += leds-cobalt-qube.o
19obj-$(CONFIG_LEDS_COBALT_RAQ) += leds-cobalt-raq.o 19obj-$(CONFIG_LEDS_COBALT_RAQ) += leds-cobalt-raq.o
20obj-$(CONFIG_LEDS_GPIO) += leds-gpio.o 20obj-$(CONFIG_LEDS_GPIO) += leds-gpio.o
21obj-$(CONFIG_LEDS_CM_X270) += leds-cm-x270.o 21obj-$(CONFIG_LEDS_CM_X270) += leds-cm-x270.o
22obj-$(CONFIG_LEDS_CLEVO_MAIL) += leds-clevo-mail.o
22 23
23# LED Triggers 24# LED Triggers
24obj-$(CONFIG_LEDS_TRIGGER_TIMER) += ledtrig-timer.o 25obj-$(CONFIG_LEDS_TRIGGER_TIMER) += ledtrig-timer.o
diff --git a/drivers/leds/leds-clevo-mail.c b/drivers/leds/leds-clevo-mail.c
new file mode 100644
index 000000000000..50aaa0b33810
--- /dev/null
+++ b/drivers/leds/leds-clevo-mail.c
@@ -0,0 +1,182 @@
1
2#include <linux/module.h>
3
4#include <linux/platform_device.h>
5#include <linux/err.h>
6#include <linux/leds.h>
7
8#include <linux/io.h>
9#include <linux/dmi.h>
10
11#include <linux/i8042.h>
12
13#define CLEVO_MAIL_LED_OFF 0x0084
14#define CLEVO_MAIL_LED_BLINK_1HZ 0x008A
15#define CLEVO_MAIL_LED_BLINK_0_5HZ 0x0083
16
17MODULE_AUTHOR("Márton Németh <nm127@freemail.hu>");
18MODULE_DESCRIPTION("Clevo mail LED driver");
19MODULE_LICENSE("GPL");
20
21static unsigned int __initdata nodetect;
22module_param_named(nodetect, nodetect, bool, 0);
23MODULE_PARM_DESC(nodetect, "Skip DMI hardware detection");
24
25static struct platform_device *pdev;
26
27static int __init clevo_mail_led_dmi_callback(const struct dmi_system_id *id)
28{
29 printk(KERN_INFO KBUILD_MODNAME ": '%s' found\n", id->ident);
30 return 1;
31}
32
33/*
34 * struct mail_led_whitelist - List of known good models
35 *
36 * Contains the known good models this driver is compatible with.
37 * When adding a new model try to be as strict as possible. This
38 * makes it possible to keep the false positives (the model is
39 * detected as working, but in reality it is not) as low as
40 * possible.
41 */
42static struct dmi_system_id __initdata mail_led_whitelist[] = {
43 {
44 .callback = clevo_mail_led_dmi_callback,
45 .ident = "Clevo D410J",
46 .matches = {
47 DMI_MATCH(DMI_SYS_VENDOR, "VIA"),
48 DMI_MATCH(DMI_PRODUCT_NAME, "K8N800"),
49 DMI_MATCH(DMI_PRODUCT_VERSION, "VT8204B")
50 }
51 },
52 {
53 .callback = clevo_mail_led_dmi_callback,
54 .ident = "Clevo M5x0N",
55 .matches = {
56 DMI_MATCH(DMI_SYS_VENDOR, "CLEVO Co."),
57 DMI_MATCH(DMI_PRODUCT_NAME, "M5x0N")
58 }
59 },
60 {
61 .callback = clevo_mail_led_dmi_callback,
62 .ident = "Positivo Mobile",
63 .matches = {
64 DMI_MATCH(DMI_BOARD_VENDOR, "CLEVO Co. "),
65 DMI_MATCH(DMI_BOARD_NAME, "M5X0V "),
66 DMI_MATCH(DMI_PRODUCT_NAME, "Positivo Mobile"),
67 DMI_MATCH(DMI_PRODUCT_VERSION, "VT6198")
68 }
69 },
70 {
71 .callback = clevo_mail_led_dmi_callback,
72 .ident = "Clevo D410V",
73 .matches = {
74 DMI_MATCH(DMI_BOARD_VENDOR, "Clevo, Co."),
75 DMI_MATCH(DMI_BOARD_NAME, "D400V/D470V"),
76 DMI_MATCH(DMI_BOARD_VERSION, "SS78B"),
77 DMI_MATCH(DMI_PRODUCT_VERSION, "Rev. A1")
78 }
79 },
80 { }
81};
82
83static void clevo_mail_led_set(struct led_classdev *led_cdev,
84 enum led_brightness value)
85{
86 if (value == LED_OFF)
87 i8042_command(NULL, CLEVO_MAIL_LED_OFF);
88 else if (value <= LED_HALF)
89 i8042_command(NULL, CLEVO_MAIL_LED_BLINK_0_5HZ);
90 else
91 i8042_command(NULL, CLEVO_MAIL_LED_BLINK_1HZ);
92
93}
94
95static struct led_classdev clevo_mail_led = {
96 .name = "clevo",
97 .brightness_set = clevo_mail_led_set,
98};
99
100static int __init clevo_mail_led_probe(struct platform_device *pdev)
101{
102 return led_classdev_register(&pdev->dev, &clevo_mail_led);
103}
104
105static int clevo_mail_led_remove(struct platform_device *pdev)
106{
107 led_classdev_unregister(&clevo_mail_led);
108 return 0;
109}
110
111#ifdef CONFIG_PM
112static int clevo_mail_led_suspend(struct platform_device *dev,
113 pm_message_t state)
114{
115 led_classdev_suspend(&clevo_mail_led);
116 return 0;
117}
118
119static int clevo_mail_led_resume(struct platform_device *dev)
120{
121 led_classdev_resume(&clevo_mail_led);
122 return 0;
123}
124#else
125#define clevo_mail_led_suspend NULL
126#define clevo_mail_led_resume NULL
127#endif
128
129static struct platform_driver clevo_mail_led_driver = {
130 .probe = clevo_mail_led_probe,
131 .remove = clevo_mail_led_remove,
132 .suspend = clevo_mail_led_suspend,
133 .resume = clevo_mail_led_resume,
134 .driver = {
135 .name = KBUILD_MODNAME,
136 },
137};
138
139static int __init clevo_mail_led_init(void)
140{
141 int error = 0;
142 int count = 0;
143
144 /* Check with the help of DMI if we are running on supported hardware */
145 if (!nodetect) {
146 count = dmi_check_system(mail_led_whitelist);
147 } else {
148 count = 1;
149 printk(KERN_ERR KBUILD_MODNAME ": Skipping DMI detection. "
150 "If the driver works on your hardware please "
151 "report model and the output of dmidecode in tracker "
152 "at http://sourceforge.net/projects/clevo-mailled/\n");
153 }
154
155 if (!count)
156 return -ENODEV;
157
158 pdev = platform_device_register_simple(KBUILD_MODNAME, -1, NULL, 0);
159 if (!IS_ERR(pdev)) {
160 error = platform_driver_probe(&clevo_mail_led_driver,
161 clevo_mail_led_probe);
162 if (error) {
163 printk(KERN_ERR KBUILD_MODNAME
164 ": Can't probe platform driver\n");
165 platform_device_unregister(pdev);
166 }
167 } else
168 error = PTR_ERR(pdev);
169
170 return error;
171}
172
173static void __exit clevo_mail_led_exit(void)
174{
175 platform_device_unregister(pdev);
176 platform_driver_unregister(&clevo_mail_led_driver);
177
178 clevo_mail_led_set(NULL, LED_OFF);
179}
180
181module_init(clevo_mail_led_init);
182module_exit(clevo_mail_led_exit);