diff options
author | Mario Limonciello <Mario_Limonciello@Dell.com> | 2009-08-25 11:30:13 -0400 |
---|---|---|
committer | Matthew Garrett <mjg@redhat.com> | 2010-02-25 11:50:40 -0500 |
commit | 493e91433e966a50964e221db92756eeb90dd54e (patch) | |
tree | d9de18019429a82f5e38339ff56937d0706a0874 | |
parent | 34325b9d2a7d36e2ba74a6652f2e3e8d57dfb145 (diff) |
compal-laptop: Replace sysfs support with rfkill support
This drops the support for manually groking the files in sysfs
to turn on and off the WLAN and BT for Compal laptops in favor
of platform rfkill support.
It has been combined into a single patch to not introduce regressions
in the process of simply adding rfkill support
Signed-off-by: Mario Limonciello <Mario_Limonciello@Dell.com>
Signed-off-by: Tim Gardner <tim.gardner@canonical.com>
Signed-off-by: Matthew Garrett <mjg@redhat.com>
Cc: Cezary Jackiewicz <cezary.jackiewicz@gmail.com>
-rw-r--r-- | drivers/platform/x86/compal-laptop.c | 201 |
1 files changed, 63 insertions, 138 deletions
diff --git a/drivers/platform/x86/compal-laptop.c b/drivers/platform/x86/compal-laptop.c index c78d254303bc..2740b40aad9b 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,6 +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> |
45 | #include <linux/rfkill.h> | ||
54 | 46 | ||
55 | #define COMPAL_DRIVER_VERSION "0.2.6" | 47 | #define COMPAL_DRIVER_VERSION "0.2.6" |
56 | 48 | ||
@@ -63,6 +55,10 @@ | |||
63 | #define WLAN_MASK 0x01 | 55 | #define WLAN_MASK 0x01 |
64 | #define BT_MASK 0x02 | 56 | #define BT_MASK 0x02 |
65 | 57 | ||
58 | static struct rfkill *wifi_rfkill; | ||
59 | static struct rfkill *bt_rfkill; | ||
60 | static struct platform_device *compal_device; | ||
61 | |||
66 | static int force; | 62 | static int force; |
67 | module_param(force, bool, 0); | 63 | module_param(force, bool, 0); |
68 | MODULE_PARM_DESC(force, "Force driver load, ignore DMI data"); | 64 | MODULE_PARM_DESC(force, "Force driver load, ignore DMI data"); |
@@ -88,65 +84,75 @@ static int get_lcd_level(void) | |||
88 | return (int) result; | 84 | return (int) result; |
89 | } | 85 | } |
90 | 86 | ||
91 | static int set_wlan_state(int state) | 87 | static int compal_rfkill_set(void *data, bool blocked) |
92 | { | 88 | { |
89 | unsigned long radio = (unsigned long) data; | ||
93 | u8 result, value; | 90 | u8 result, value; |
94 | 91 | ||
95 | ec_read(COMPAL_EC_COMMAND_WIRELESS, &result); | 92 | ec_read(COMPAL_EC_COMMAND_WIRELESS, &result); |
96 | 93 | ||
97 | if ((result & KILLSWITCH_MASK) == 0) | 94 | if (!blocked) |
98 | return -EINVAL; | 95 | value = (u8) (result | radio); |
99 | else { | 96 | else |
100 | if (state) | 97 | value = (u8) (result & ~radio); |
101 | value = (u8) (result | WLAN_MASK); | 98 | ec_write(COMPAL_EC_COMMAND_WIRELESS, value); |
102 | else | ||
103 | value = (u8) (result & ~WLAN_MASK); | ||
104 | ec_write(COMPAL_EC_COMMAND_WIRELESS, value); | ||
105 | } | ||
106 | 99 | ||
107 | return 0; | 100 | return 0; |
108 | } | 101 | } |
109 | 102 | ||
110 | static int set_bluetooth_state(int state) | 103 | static void compal_rfkill_poll(struct rfkill *rfkill, void *data) |
111 | { | 104 | { |
112 | u8 result, value; | 105 | u8 result; |
106 | bool hw_blocked; | ||
113 | 107 | ||
114 | ec_read(COMPAL_EC_COMMAND_WIRELESS, &result); | 108 | ec_read(COMPAL_EC_COMMAND_WIRELESS, &result); |
115 | 109 | ||
116 | if ((result & KILLSWITCH_MASK) == 0) | 110 | hw_blocked = !(result & KILLSWITCH_MASK); |
117 | return -EINVAL; | 111 | rfkill_set_hw_state(rfkill, hw_blocked); |
118 | else { | ||
119 | if (state) | ||
120 | value = (u8) (result | BT_MASK); | ||
121 | else | ||
122 | value = (u8) (result & ~BT_MASK); | ||
123 | ec_write(COMPAL_EC_COMMAND_WIRELESS, value); | ||
124 | } | ||
125 | |||
126 | return 0; | ||
127 | } | 112 | } |
128 | 113 | ||
129 | static int get_wireless_state(int *wlan, int *bluetooth) | 114 | static const struct rfkill_ops compal_rfkill_ops = { |
115 | .poll = compal_rfkill_poll, | ||
116 | .set_block = compal_rfkill_set, | ||
117 | }; | ||
118 | |||
119 | static int setup_rfkill(void) | ||
130 | { | 120 | { |
131 | u8 result; | 121 | int ret; |
132 | 122 | ||
133 | 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; | ||
134 | 128 | ||
135 | if (wlan) { | 129 | ret = rfkill_register(wifi_rfkill); |
136 | if ((result & KILLSWITCH_MASK) == 0) | 130 | if (ret) |
137 | *wlan = 0; | 131 | goto err_wifi; |
138 | else | ||
139 | *wlan = result & WLAN_MASK; | ||
140 | } | ||
141 | 132 | ||
142 | if (bluetooth) { | 133 | bt_rfkill = rfkill_alloc("compal-bluetooth", &compal_device->dev, |
143 | if ((result & KILLSWITCH_MASK) == 0) | 134 | RFKILL_TYPE_BLUETOOTH, &compal_rfkill_ops, |
144 | *bluetooth = 0; | 135 | (void *) BT_MASK); |
145 | else | 136 | if (!bt_rfkill) { |
146 | *bluetooth = (result & BT_MASK) >> 1; | 137 | ret = -ENOMEM; |
138 | goto err_allocate_bt; | ||
147 | } | 139 | } |
140 | ret = rfkill_register(bt_rfkill); | ||
141 | if (ret) | ||
142 | goto err_register_bt; | ||
148 | 143 | ||
149 | return 0; | 144 | return 0; |
145 | |||
146 | err_register_bt: | ||
147 | rfkill_destroy(bt_rfkill); | ||
148 | |||
149 | err_allocate_bt: | ||
150 | rfkill_unregister(wifi_rfkill); | ||
151 | |||
152 | err_wifi: | ||
153 | rfkill_destroy(wifi_rfkill); | ||
154 | |||
155 | return ret; | ||
150 | } | 156 | } |
151 | 157 | ||
152 | /* Backlight device stuff */ | 158 | /* Backlight device stuff */ |
@@ -169,86 +175,6 @@ static struct backlight_ops compalbl_ops = { | |||
169 | 175 | ||
170 | static struct backlight_device *compalbl_device; | 176 | static struct backlight_device *compalbl_device; |
171 | 177 | ||
172 | /* Platform device */ | ||
173 | |||
174 | static ssize_t show_wlan(struct device *dev, | ||
175 | struct device_attribute *attr, char *buf) | ||
176 | { | ||
177 | int ret, enabled; | ||
178 | |||
179 | ret = get_wireless_state(&enabled, NULL); | ||
180 | if (ret < 0) | ||
181 | return ret; | ||
182 | |||
183 | return sprintf(buf, "%i\n", enabled); | ||
184 | } | ||
185 | |||
186 | static ssize_t show_raw(struct device *dev, | ||
187 | struct device_attribute *attr, char *buf) | ||
188 | { | ||
189 | u8 result; | ||
190 | |||
191 | ec_read(COMPAL_EC_COMMAND_WIRELESS, &result); | ||
192 | |||
193 | return sprintf(buf, "%i\n", result); | ||
194 | } | ||
195 | |||
196 | static ssize_t show_bluetooth(struct device *dev, | ||
197 | struct device_attribute *attr, char *buf) | ||
198 | { | ||
199 | int ret, enabled; | ||
200 | |||
201 | ret = get_wireless_state(NULL, &enabled); | ||
202 | if (ret < 0) | ||
203 | return ret; | ||
204 | |||
205 | return sprintf(buf, "%i\n", enabled); | ||
206 | } | ||
207 | |||
208 | static ssize_t store_wlan_state(struct device *dev, | ||
209 | struct device_attribute *attr, const char *buf, size_t count) | ||
210 | { | ||
211 | int state, ret; | ||
212 | |||
213 | if (sscanf(buf, "%i", &state) != 1 || (state < 0 || state > 1)) | ||
214 | return -EINVAL; | ||
215 | |||
216 | ret = set_wlan_state(state); | ||
217 | if (ret < 0) | ||
218 | return ret; | ||
219 | |||
220 | return count; | ||
221 | } | ||
222 | |||
223 | static ssize_t store_bluetooth_state(struct device *dev, | ||
224 | struct device_attribute *attr, const char *buf, size_t count) | ||
225 | { | ||
226 | int state, ret; | ||
227 | |||
228 | if (sscanf(buf, "%i", &state) != 1 || (state < 0 || state > 1)) | ||
229 | return -EINVAL; | ||
230 | |||
231 | ret = set_bluetooth_state(state); | ||
232 | if (ret < 0) | ||
233 | return ret; | ||
234 | |||
235 | return count; | ||
236 | } | ||
237 | |||
238 | static DEVICE_ATTR(bluetooth, 0644, show_bluetooth, store_bluetooth_state); | ||
239 | static DEVICE_ATTR(wlan, 0644, show_wlan, store_wlan_state); | ||
240 | static DEVICE_ATTR(raw, 0444, show_raw, NULL); | ||
241 | |||
242 | static struct attribute *compal_attributes[] = { | ||
243 | &dev_attr_bluetooth.attr, | ||
244 | &dev_attr_wlan.attr, | ||
245 | &dev_attr_raw.attr, | ||
246 | NULL | ||
247 | }; | ||
248 | |||
249 | static struct attribute_group compal_attribute_group = { | ||
250 | .attrs = compal_attributes | ||
251 | }; | ||
252 | 178 | ||
253 | static struct platform_driver compal_driver = { | 179 | static struct platform_driver compal_driver = { |
254 | .driver = { | 180 | .driver = { |
@@ -257,8 +183,6 @@ static struct platform_driver compal_driver = { | |||
257 | } | 183 | } |
258 | }; | 184 | }; |
259 | 185 | ||
260 | static struct platform_device *compal_device; | ||
261 | |||
262 | /* Initialization */ | 186 | /* Initialization */ |
263 | 187 | ||
264 | static int dmi_check_cb(const struct dmi_system_id *id) | 188 | static int dmi_check_cb(const struct dmi_system_id *id) |
@@ -389,23 +313,21 @@ static int __init compal_init(void) | |||
389 | 313 | ||
390 | ret = platform_device_add(compal_device); | 314 | ret = platform_device_add(compal_device); |
391 | if (ret) | 315 | if (ret) |
392 | goto fail_platform_device1; | 316 | goto fail_platform_device; |
393 | 317 | ||
394 | ret = sysfs_create_group(&compal_device->dev.kobj, | 318 | ret = setup_rfkill(); |
395 | &compal_attribute_group); | ||
396 | if (ret) | 319 | if (ret) |
397 | goto fail_platform_device2; | 320 | goto fail_rfkill; |
398 | 321 | ||
399 | printk(KERN_INFO "compal-laptop: driver "COMPAL_DRIVER_VERSION | 322 | printk(KERN_INFO "compal-laptop: driver "COMPAL_DRIVER_VERSION |
400 | " successfully loaded.\n"); | 323 | " successfully loaded.\n"); |
401 | 324 | ||
402 | return 0; | 325 | return 0; |
403 | 326 | ||
404 | fail_platform_device2: | 327 | fail_rfkill: |
405 | |||
406 | platform_device_del(compal_device); | 328 | platform_device_del(compal_device); |
407 | 329 | ||
408 | fail_platform_device1: | 330 | fail_platform_device: |
409 | 331 | ||
410 | platform_device_put(compal_device); | 332 | platform_device_put(compal_device); |
411 | 333 | ||
@@ -423,10 +345,13 @@ fail_backlight: | |||
423 | static void __exit compal_cleanup(void) | 345 | static void __exit compal_cleanup(void) |
424 | { | 346 | { |
425 | 347 | ||
426 | sysfs_remove_group(&compal_device->dev.kobj, &compal_attribute_group); | ||
427 | platform_device_unregister(compal_device); | 348 | platform_device_unregister(compal_device); |
428 | platform_driver_unregister(&compal_driver); | 349 | platform_driver_unregister(&compal_driver); |
429 | backlight_device_unregister(compalbl_device); | 350 | backlight_device_unregister(compalbl_device); |
351 | rfkill_unregister(wifi_rfkill); | ||
352 | rfkill_destroy(wifi_rfkill); | ||
353 | rfkill_unregister(bt_rfkill); | ||
354 | rfkill_destroy(bt_rfkill); | ||
430 | 355 | ||
431 | printk(KERN_INFO "compal-laptop: driver unloaded.\n"); | 356 | printk(KERN_INFO "compal-laptop: driver unloaded.\n"); |
432 | } | 357 | } |