aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/leds/leds-clevo-mail.c
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 /drivers/leds/leds-clevo-mail.c
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>
Diffstat (limited to 'drivers/leds/leds-clevo-mail.c')
-rw-r--r--drivers/leds/leds-clevo-mail.c182
1 files changed, 182 insertions, 0 deletions
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);