aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/platform/x86/compal-laptop.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/platform/x86/compal-laptop.c')
-rw-r--r--drivers/platform/x86/compal-laptop.c259
1 files changed, 116 insertions, 143 deletions
diff --git a/drivers/platform/x86/compal-laptop.c b/drivers/platform/x86/compal-laptop.c
index 11003bba10d3..71ff1545a93e 100644
--- a/drivers/platform/x86/compal-laptop.c
+++ b/drivers/platform/x86/compal-laptop.c
@@ -26,17 +26,8 @@
26/* 26/*
27 * comapl-laptop.c - Compal laptop support. 27 * comapl-laptop.c - Compal laptop support.
28 * 28 *
29 * This driver exports a few files in /sys/devices/platform/compal-laptop/: 29 * The driver registers itself with the rfkill subsystem and
30 * 30 * the Linux backlight control subsystem.
31 * wlan - wlan subsystem state: contains 0 or 1 (rw)
32 *
33 * bluetooth - Bluetooth subsystem state: contains 0 or 1 (rw)
34 *
35 * raw - raw value taken from embedded controller register (ro)
36 *
37 * In addition to these platform device attributes the driver
38 * registers itself in the Linux backlight control subsystem and is
39 * available to userspace under /sys/class/backlight/compal-laptop/.
40 * 31 *
41 * This driver might work on other laptops produced by Compal. If you 32 * This driver might work on other laptops produced by Compal. If you
42 * want to try it you can pass force=1 as argument to the module which 33 * want to try it you can pass force=1 as argument to the module which
@@ -51,7 +42,7 @@
51#include <linux/dmi.h> 42#include <linux/dmi.h>
52#include <linux/backlight.h> 43#include <linux/backlight.h>
53#include <linux/platform_device.h> 44#include <linux/platform_device.h>
54#include <linux/autoconf.h> 45#include <linux/rfkill.h>
55 46
56#define COMPAL_DRIVER_VERSION "0.2.6" 47#define COMPAL_DRIVER_VERSION "0.2.6"
57 48
@@ -64,6 +55,10 @@
64#define WLAN_MASK 0x01 55#define WLAN_MASK 0x01
65#define BT_MASK 0x02 56#define BT_MASK 0x02
66 57
58static struct rfkill *wifi_rfkill;
59static struct rfkill *bt_rfkill;
60static struct platform_device *compal_device;
61
67static int force; 62static int force;
68module_param(force, bool, 0); 63module_param(force, bool, 0);
69MODULE_PARM_DESC(force, "Force driver load, ignore DMI data"); 64MODULE_PARM_DESC(force, "Force driver load, ignore DMI data");
@@ -89,65 +84,75 @@ static int get_lcd_level(void)
89 return (int) result; 84 return (int) result;
90} 85}
91 86
92static int set_wlan_state(int state) 87static int compal_rfkill_set(void *data, bool blocked)
93{ 88{
89 unsigned long radio = (unsigned long) data;
94 u8 result, value; 90 u8 result, value;
95 91
96 ec_read(COMPAL_EC_COMMAND_WIRELESS, &result); 92 ec_read(COMPAL_EC_COMMAND_WIRELESS, &result);
97 93
98 if ((result & KILLSWITCH_MASK) == 0) 94 if (!blocked)
99 return -EINVAL; 95 value = (u8) (result | radio);
100 else { 96 else
101 if (state) 97 value = (u8) (result & ~radio);
102 value = (u8) (result | WLAN_MASK); 98 ec_write(COMPAL_EC_COMMAND_WIRELESS, value);
103 else
104 value = (u8) (result & ~WLAN_MASK);
105 ec_write(COMPAL_EC_COMMAND_WIRELESS, value);
106 }
107 99
108 return 0; 100 return 0;
109} 101}
110 102
111static int set_bluetooth_state(int state) 103static void compal_rfkill_poll(struct rfkill *rfkill, void *data)
112{ 104{
113 u8 result, value; 105 u8 result;
106 bool hw_blocked;
114 107
115 ec_read(COMPAL_EC_COMMAND_WIRELESS, &result); 108 ec_read(COMPAL_EC_COMMAND_WIRELESS, &result);
116 109
117 if ((result & KILLSWITCH_MASK) == 0) 110 hw_blocked = !(result & KILLSWITCH_MASK);
118 return -EINVAL; 111 rfkill_set_hw_state(rfkill, hw_blocked);
119 else {
120 if (state)
121 value = (u8) (result | BT_MASK);
122 else
123 value = (u8) (result & ~BT_MASK);
124 ec_write(COMPAL_EC_COMMAND_WIRELESS, value);
125 }
126
127 return 0;
128} 112}
129 113
130static int get_wireless_state(int *wlan, int *bluetooth) 114static const struct rfkill_ops compal_rfkill_ops = {
115 .poll = compal_rfkill_poll,
116 .set_block = compal_rfkill_set,
117};
118
119static int setup_rfkill(void)
131{ 120{
132 u8 result; 121 int ret;
133 122
134 ec_read(COMPAL_EC_COMMAND_WIRELESS, &result); 123 wifi_rfkill = rfkill_alloc("compal-wifi", &compal_device->dev,
124 RFKILL_TYPE_WLAN, &compal_rfkill_ops,
125 (void *) WLAN_MASK);
126 if (!wifi_rfkill)
127 return -ENOMEM;
135 128
136 if (wlan) { 129 ret = rfkill_register(wifi_rfkill);
137 if ((result & KILLSWITCH_MASK) == 0) 130 if (ret)
138 *wlan = 0; 131 goto err_wifi;
139 else
140 *wlan = result & WLAN_MASK;
141 }
142 132
143 if (bluetooth) { 133 bt_rfkill = rfkill_alloc("compal-bluetooth", &compal_device->dev,
144 if ((result & KILLSWITCH_MASK) == 0) 134 RFKILL_TYPE_BLUETOOTH, &compal_rfkill_ops,
145 *bluetooth = 0; 135 (void *) BT_MASK);
146 else 136 if (!bt_rfkill) {
147 *bluetooth = (result & BT_MASK) >> 1; 137 ret = -ENOMEM;
138 goto err_allocate_bt;
148 } 139 }
140 ret = rfkill_register(bt_rfkill);
141 if (ret)
142 goto err_register_bt;
149 143
150 return 0; 144 return 0;
145
146err_register_bt:
147 rfkill_destroy(bt_rfkill);
148
149err_allocate_bt:
150 rfkill_unregister(wifi_rfkill);
151
152err_wifi:
153 rfkill_destroy(wifi_rfkill);
154
155 return ret;
151} 156}
152 157
153/* Backlight device stuff */ 158/* Backlight device stuff */
@@ -170,86 +175,6 @@ static struct backlight_ops compalbl_ops = {
170 175
171static struct backlight_device *compalbl_device; 176static struct backlight_device *compalbl_device;
172 177
173/* Platform device */
174
175static ssize_t show_wlan(struct device *dev,
176 struct device_attribute *attr, char *buf)
177{
178 int ret, enabled;
179
180 ret = get_wireless_state(&enabled, NULL);
181 if (ret < 0)
182 return ret;
183
184 return sprintf(buf, "%i\n", enabled);
185}
186
187static ssize_t show_raw(struct device *dev,
188 struct device_attribute *attr, char *buf)
189{
190 u8 result;
191
192 ec_read(COMPAL_EC_COMMAND_WIRELESS, &result);
193
194 return sprintf(buf, "%i\n", result);
195}
196
197static ssize_t show_bluetooth(struct device *dev,
198 struct device_attribute *attr, char *buf)
199{
200 int ret, enabled;
201
202 ret = get_wireless_state(NULL, &enabled);
203 if (ret < 0)
204 return ret;
205
206 return sprintf(buf, "%i\n", enabled);
207}
208
209static ssize_t store_wlan_state(struct device *dev,
210 struct device_attribute *attr, const char *buf, size_t count)
211{
212 int state, ret;
213
214 if (sscanf(buf, "%i", &state) != 1 || (state < 0 || state > 1))
215 return -EINVAL;
216
217 ret = set_wlan_state(state);
218 if (ret < 0)
219 return ret;
220
221 return count;
222}
223
224static ssize_t store_bluetooth_state(struct device *dev,
225 struct device_attribute *attr, const char *buf, size_t count)
226{
227 int state, ret;
228
229 if (sscanf(buf, "%i", &state) != 1 || (state < 0 || state > 1))
230 return -EINVAL;
231
232 ret = set_bluetooth_state(state);
233 if (ret < 0)
234 return ret;
235
236 return count;
237}
238
239static DEVICE_ATTR(bluetooth, 0644, show_bluetooth, store_bluetooth_state);
240static DEVICE_ATTR(wlan, 0644, show_wlan, store_wlan_state);
241static DEVICE_ATTR(raw, 0444, show_raw, NULL);
242
243static struct attribute *compal_attributes[] = {
244 &dev_attr_bluetooth.attr,
245 &dev_attr_wlan.attr,
246 &dev_attr_raw.attr,
247 NULL
248};
249
250static struct attribute_group compal_attribute_group = {
251 .attrs = compal_attributes
252};
253 178
254static struct platform_driver compal_driver = { 179static struct platform_driver compal_driver = {
255 .driver = { 180 .driver = {
@@ -258,8 +183,6 @@ static struct platform_driver compal_driver = {
258 } 183 }
259}; 184};
260 185
261static struct platform_device *compal_device;
262
263/* Initialization */ 186/* Initialization */
264 187
265static int dmi_check_cb(const struct dmi_system_id *id) 188static int dmi_check_cb(const struct dmi_system_id *id)
@@ -311,6 +234,47 @@ static struct dmi_system_id __initdata compal_dmi_table[] = {
311 }, 234 },
312 .callback = dmi_check_cb 235 .callback = dmi_check_cb
313 }, 236 },
237 {
238 .ident = "Dell Mini 9",
239 .matches = {
240 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
241 DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 910"),
242 },
243 .callback = dmi_check_cb
244 },
245 {
246 .ident = "Dell Mini 10",
247 .matches = {
248 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
249 DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 1010"),
250 },
251 .callback = dmi_check_cb
252 },
253 {
254 .ident = "Dell Mini 10v",
255 .matches = {
256 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
257 DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 1011"),
258 },
259 .callback = dmi_check_cb
260 },
261 {
262 .ident = "Dell Inspiron 11z",
263 .matches = {
264 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
265 DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 1110"),
266 },
267 .callback = dmi_check_cb
268 },
269 {
270 .ident = "Dell Mini 12",
271 .matches = {
272 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
273 DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 1210"),
274 },
275 .callback = dmi_check_cb
276 },
277
314 { } 278 { }
315}; 279};
316 280
@@ -327,12 +291,15 @@ static int __init compal_init(void)
327 /* Register backlight stuff */ 291 /* Register backlight stuff */
328 292
329 if (!acpi_video_backlight_support()) { 293 if (!acpi_video_backlight_support()) {
330 compalbl_device = backlight_device_register("compal-laptop", NULL, NULL, 294 struct backlight_properties props;
331 &compalbl_ops); 295 memset(&props, 0, sizeof(struct backlight_properties));
296 props.max_brightness = COMPAL_LCD_LEVEL_MAX - 1;
297 compalbl_device = backlight_device_register("compal-laptop",
298 NULL, NULL,
299 &compalbl_ops,
300 &props);
332 if (IS_ERR(compalbl_device)) 301 if (IS_ERR(compalbl_device))
333 return PTR_ERR(compalbl_device); 302 return PTR_ERR(compalbl_device);
334
335 compalbl_device->props.max_brightness = COMPAL_LCD_LEVEL_MAX-1;
336 } 303 }
337 304
338 ret = platform_driver_register(&compal_driver); 305 ret = platform_driver_register(&compal_driver);
@@ -349,23 +316,21 @@ static int __init compal_init(void)
349 316
350 ret = platform_device_add(compal_device); 317 ret = platform_device_add(compal_device);
351 if (ret) 318 if (ret)
352 goto fail_platform_device1; 319 goto fail_platform_device;
353 320
354 ret = sysfs_create_group(&compal_device->dev.kobj, 321 ret = setup_rfkill();
355 &compal_attribute_group);
356 if (ret) 322 if (ret)
357 goto fail_platform_device2; 323 goto fail_rfkill;
358 324
359 printk(KERN_INFO "compal-laptop: driver "COMPAL_DRIVER_VERSION 325 printk(KERN_INFO "compal-laptop: driver "COMPAL_DRIVER_VERSION
360 " successfully loaded.\n"); 326 " successfully loaded.\n");
361 327
362 return 0; 328 return 0;
363 329
364fail_platform_device2: 330fail_rfkill:
365
366 platform_device_del(compal_device); 331 platform_device_del(compal_device);
367 332
368fail_platform_device1: 333fail_platform_device:
369 334
370 platform_device_put(compal_device); 335 platform_device_put(compal_device);
371 336
@@ -383,10 +348,13 @@ fail_backlight:
383static void __exit compal_cleanup(void) 348static void __exit compal_cleanup(void)
384{ 349{
385 350
386 sysfs_remove_group(&compal_device->dev.kobj, &compal_attribute_group);
387 platform_device_unregister(compal_device); 351 platform_device_unregister(compal_device);
388 platform_driver_unregister(&compal_driver); 352 platform_driver_unregister(&compal_driver);
389 backlight_device_unregister(compalbl_device); 353 backlight_device_unregister(compalbl_device);
354 rfkill_unregister(wifi_rfkill);
355 rfkill_destroy(wifi_rfkill);
356 rfkill_unregister(bt_rfkill);
357 rfkill_destroy(bt_rfkill);
390 358
391 printk(KERN_INFO "compal-laptop: driver unloaded.\n"); 359 printk(KERN_INFO "compal-laptop: driver unloaded.\n");
392} 360}
@@ -404,3 +372,8 @@ MODULE_ALIAS("dmi:*:rnIFL90:rvrREFERENCE:*");
404MODULE_ALIAS("dmi:*:rnIFL91:rvrIFT00:*"); 372MODULE_ALIAS("dmi:*:rnIFL91:rvrIFT00:*");
405MODULE_ALIAS("dmi:*:rnJFL92:rvrIFT00:*"); 373MODULE_ALIAS("dmi:*:rnJFL92:rvrIFT00:*");
406MODULE_ALIAS("dmi:*:rnIFT00:rvrIFT00:*"); 374MODULE_ALIAS("dmi:*:rnIFT00:rvrIFT00:*");
375MODULE_ALIAS("dmi:*:svnDellInc.:pnInspiron910:*");
376MODULE_ALIAS("dmi:*:svnDellInc.:pnInspiron1010:*");
377MODULE_ALIAS("dmi:*:svnDellInc.:pnInspiron1011:*");
378MODULE_ALIAS("dmi:*:svnDellInc.:pnInspiron1110:*");
379MODULE_ALIAS("dmi:*:svnDellInc.:pnInspiron1210:*");