diff options
Diffstat (limited to 'drivers/platform/x86/toshiba_acpi.c')
-rw-r--r-- | drivers/platform/x86/toshiba_acpi.c | 641 |
1 files changed, 338 insertions, 303 deletions
diff --git a/drivers/platform/x86/toshiba_acpi.c b/drivers/platform/x86/toshiba_acpi.c index cb009b2629ee..13ef8c37471d 100644 --- a/drivers/platform/x86/toshiba_acpi.c +++ b/drivers/platform/x86/toshiba_acpi.c | |||
@@ -47,7 +47,6 @@ | |||
47 | #include <linux/proc_fs.h> | 47 | #include <linux/proc_fs.h> |
48 | #include <linux/seq_file.h> | 48 | #include <linux/seq_file.h> |
49 | #include <linux/backlight.h> | 49 | #include <linux/backlight.h> |
50 | #include <linux/platform_device.h> | ||
51 | #include <linux/rfkill.h> | 50 | #include <linux/rfkill.h> |
52 | #include <linux/input.h> | 51 | #include <linux/input.h> |
53 | #include <linux/input/sparse-keymap.h> | 52 | #include <linux/input/sparse-keymap.h> |
@@ -63,11 +62,7 @@ MODULE_DESCRIPTION("Toshiba Laptop ACPI Extras Driver"); | |||
63 | MODULE_LICENSE("GPL"); | 62 | MODULE_LICENSE("GPL"); |
64 | 63 | ||
65 | /* Toshiba ACPI method paths */ | 64 | /* Toshiba ACPI method paths */ |
66 | #define METHOD_LCD_BRIGHTNESS "\\_SB_.PCI0.VGA_.LCD_._BCM" | ||
67 | #define TOSH_INTERFACE_1 "\\_SB_.VALD" | ||
68 | #define TOSH_INTERFACE_2 "\\_SB_.VALZ" | ||
69 | #define METHOD_VIDEO_OUT "\\_SB_.VALX.DSSX" | 65 | #define METHOD_VIDEO_OUT "\\_SB_.VALX.DSSX" |
70 | #define GHCI_METHOD ".GHCI" | ||
71 | 66 | ||
72 | /* Toshiba HCI interface definitions | 67 | /* Toshiba HCI interface definitions |
73 | * | 68 | * |
@@ -111,6 +106,25 @@ MODULE_LICENSE("GPL"); | |||
111 | #define HCI_WIRELESS_BT_ATTACH 0x40 | 106 | #define HCI_WIRELESS_BT_ATTACH 0x40 |
112 | #define HCI_WIRELESS_BT_POWER 0x80 | 107 | #define HCI_WIRELESS_BT_POWER 0x80 |
113 | 108 | ||
109 | struct toshiba_acpi_dev { | ||
110 | struct acpi_device *acpi_dev; | ||
111 | const char *method_hci; | ||
112 | struct rfkill *bt_rfk; | ||
113 | struct input_dev *hotkey_dev; | ||
114 | struct backlight_device *backlight_dev; | ||
115 | struct led_classdev led_dev; | ||
116 | |||
117 | int force_fan; | ||
118 | int last_key_event; | ||
119 | int key_event_valid; | ||
120 | |||
121 | int illumination_supported:1; | ||
122 | int video_supported:1; | ||
123 | int fan_supported:1; | ||
124 | |||
125 | struct mutex mutex; | ||
126 | }; | ||
127 | |||
114 | static const struct acpi_device_id toshiba_device_ids[] = { | 128 | static const struct acpi_device_id toshiba_device_ids[] = { |
115 | {"TOS6200", 0}, | 129 | {"TOS6200", 0}, |
116 | {"TOS6208", 0}, | 130 | {"TOS6208", 0}, |
@@ -119,7 +133,7 @@ static const struct acpi_device_id toshiba_device_ids[] = { | |||
119 | }; | 133 | }; |
120 | MODULE_DEVICE_TABLE(acpi, toshiba_device_ids); | 134 | MODULE_DEVICE_TABLE(acpi, toshiba_device_ids); |
121 | 135 | ||
122 | static const struct key_entry toshiba_acpi_keymap[] __initconst = { | 136 | static const struct key_entry toshiba_acpi_keymap[] __devinitconst = { |
123 | { KE_KEY, 0x101, { KEY_MUTE } }, | 137 | { KE_KEY, 0x101, { KEY_MUTE } }, |
124 | { KE_KEY, 0x102, { KEY_ZOOMOUT } }, | 138 | { KE_KEY, 0x102, { KEY_ZOOMOUT } }, |
125 | { KE_KEY, 0x103, { KEY_ZOOMIN } }, | 139 | { KE_KEY, 0x103, { KEY_ZOOMIN } }, |
@@ -155,15 +169,6 @@ static __inline__ void _set_bit(u32 * word, u32 mask, int value) | |||
155 | /* acpi interface wrappers | 169 | /* acpi interface wrappers |
156 | */ | 170 | */ |
157 | 171 | ||
158 | static int is_valid_acpi_path(const char *methodName) | ||
159 | { | ||
160 | acpi_handle handle; | ||
161 | acpi_status status; | ||
162 | |||
163 | status = acpi_get_handle(NULL, (char *)methodName, &handle); | ||
164 | return !ACPI_FAILURE(status); | ||
165 | } | ||
166 | |||
167 | static int write_acpi_int(const char *methodName, int val) | 172 | static int write_acpi_int(const char *methodName, int val) |
168 | { | 173 | { |
169 | struct acpi_object_list params; | 174 | struct acpi_object_list params; |
@@ -176,32 +181,14 @@ static int write_acpi_int(const char *methodName, int val) | |||
176 | in_objs[0].integer.value = val; | 181 | in_objs[0].integer.value = val; |
177 | 182 | ||
178 | status = acpi_evaluate_object(NULL, (char *)methodName, ¶ms, NULL); | 183 | status = acpi_evaluate_object(NULL, (char *)methodName, ¶ms, NULL); |
179 | return (status == AE_OK); | 184 | return (status == AE_OK) ? 0 : -EIO; |
180 | } | ||
181 | |||
182 | #if 0 | ||
183 | static int read_acpi_int(const char *methodName, int *pVal) | ||
184 | { | ||
185 | struct acpi_buffer results; | ||
186 | union acpi_object out_objs[1]; | ||
187 | acpi_status status; | ||
188 | |||
189 | results.length = sizeof(out_objs); | ||
190 | results.pointer = out_objs; | ||
191 | |||
192 | status = acpi_evaluate_object(0, (char *)methodName, 0, &results); | ||
193 | *pVal = out_objs[0].integer.value; | ||
194 | |||
195 | return (status == AE_OK) && (out_objs[0].type == ACPI_TYPE_INTEGER); | ||
196 | } | 185 | } |
197 | #endif | ||
198 | |||
199 | static const char *method_hci /*= 0*/ ; | ||
200 | 186 | ||
201 | /* Perform a raw HCI call. Here we don't care about input or output buffer | 187 | /* Perform a raw HCI call. Here we don't care about input or output buffer |
202 | * format. | 188 | * format. |
203 | */ | 189 | */ |
204 | static acpi_status hci_raw(const u32 in[HCI_WORDS], u32 out[HCI_WORDS]) | 190 | static acpi_status hci_raw(struct toshiba_acpi_dev *dev, |
191 | const u32 in[HCI_WORDS], u32 out[HCI_WORDS]) | ||
205 | { | 192 | { |
206 | struct acpi_object_list params; | 193 | struct acpi_object_list params; |
207 | union acpi_object in_objs[HCI_WORDS]; | 194 | union acpi_object in_objs[HCI_WORDS]; |
@@ -220,7 +207,8 @@ static acpi_status hci_raw(const u32 in[HCI_WORDS], u32 out[HCI_WORDS]) | |||
220 | results.length = sizeof(out_objs); | 207 | results.length = sizeof(out_objs); |
221 | results.pointer = out_objs; | 208 | results.pointer = out_objs; |
222 | 209 | ||
223 | status = acpi_evaluate_object(NULL, (char *)method_hci, ¶ms, | 210 | status = acpi_evaluate_object(dev->acpi_dev->handle, |
211 | (char *)dev->method_hci, ¶ms, | ||
224 | &results); | 212 | &results); |
225 | if ((status == AE_OK) && (out_objs->package.count <= HCI_WORDS)) { | 213 | if ((status == AE_OK) && (out_objs->package.count <= HCI_WORDS)) { |
226 | for (i = 0; i < out_objs->package.count; ++i) { | 214 | for (i = 0; i < out_objs->package.count; ++i) { |
@@ -237,85 +225,79 @@ static acpi_status hci_raw(const u32 in[HCI_WORDS], u32 out[HCI_WORDS]) | |||
237 | * may be useful (such as "not supported"). | 225 | * may be useful (such as "not supported"). |
238 | */ | 226 | */ |
239 | 227 | ||
240 | static acpi_status hci_write1(u32 reg, u32 in1, u32 * result) | 228 | static acpi_status hci_write1(struct toshiba_acpi_dev *dev, u32 reg, |
229 | u32 in1, u32 *result) | ||
241 | { | 230 | { |
242 | u32 in[HCI_WORDS] = { HCI_SET, reg, in1, 0, 0, 0 }; | 231 | u32 in[HCI_WORDS] = { HCI_SET, reg, in1, 0, 0, 0 }; |
243 | u32 out[HCI_WORDS]; | 232 | u32 out[HCI_WORDS]; |
244 | acpi_status status = hci_raw(in, out); | 233 | acpi_status status = hci_raw(dev, in, out); |
245 | *result = (status == AE_OK) ? out[0] : HCI_FAILURE; | 234 | *result = (status == AE_OK) ? out[0] : HCI_FAILURE; |
246 | return status; | 235 | return status; |
247 | } | 236 | } |
248 | 237 | ||
249 | static acpi_status hci_read1(u32 reg, u32 * out1, u32 * result) | 238 | static acpi_status hci_read1(struct toshiba_acpi_dev *dev, u32 reg, |
239 | u32 *out1, u32 *result) | ||
250 | { | 240 | { |
251 | u32 in[HCI_WORDS] = { HCI_GET, reg, 0, 0, 0, 0 }; | 241 | u32 in[HCI_WORDS] = { HCI_GET, reg, 0, 0, 0, 0 }; |
252 | u32 out[HCI_WORDS]; | 242 | u32 out[HCI_WORDS]; |
253 | acpi_status status = hci_raw(in, out); | 243 | acpi_status status = hci_raw(dev, in, out); |
254 | *out1 = out[2]; | 244 | *out1 = out[2]; |
255 | *result = (status == AE_OK) ? out[0] : HCI_FAILURE; | 245 | *result = (status == AE_OK) ? out[0] : HCI_FAILURE; |
256 | return status; | 246 | return status; |
257 | } | 247 | } |
258 | 248 | ||
259 | static acpi_status hci_write2(u32 reg, u32 in1, u32 in2, u32 *result) | 249 | static acpi_status hci_write2(struct toshiba_acpi_dev *dev, u32 reg, |
250 | u32 in1, u32 in2, u32 *result) | ||
260 | { | 251 | { |
261 | u32 in[HCI_WORDS] = { HCI_SET, reg, in1, in2, 0, 0 }; | 252 | u32 in[HCI_WORDS] = { HCI_SET, reg, in1, in2, 0, 0 }; |
262 | u32 out[HCI_WORDS]; | 253 | u32 out[HCI_WORDS]; |
263 | acpi_status status = hci_raw(in, out); | 254 | acpi_status status = hci_raw(dev, in, out); |
264 | *result = (status == AE_OK) ? out[0] : HCI_FAILURE; | 255 | *result = (status == AE_OK) ? out[0] : HCI_FAILURE; |
265 | return status; | 256 | return status; |
266 | } | 257 | } |
267 | 258 | ||
268 | static acpi_status hci_read2(u32 reg, u32 *out1, u32 *out2, u32 *result) | 259 | static acpi_status hci_read2(struct toshiba_acpi_dev *dev, u32 reg, |
260 | u32 *out1, u32 *out2, u32 *result) | ||
269 | { | 261 | { |
270 | u32 in[HCI_WORDS] = { HCI_GET, reg, *out1, *out2, 0, 0 }; | 262 | u32 in[HCI_WORDS] = { HCI_GET, reg, *out1, *out2, 0, 0 }; |
271 | u32 out[HCI_WORDS]; | 263 | u32 out[HCI_WORDS]; |
272 | acpi_status status = hci_raw(in, out); | 264 | acpi_status status = hci_raw(dev, in, out); |
273 | *out1 = out[2]; | 265 | *out1 = out[2]; |
274 | *out2 = out[3]; | 266 | *out2 = out[3]; |
275 | *result = (status == AE_OK) ? out[0] : HCI_FAILURE; | 267 | *result = (status == AE_OK) ? out[0] : HCI_FAILURE; |
276 | return status; | 268 | return status; |
277 | } | 269 | } |
278 | 270 | ||
279 | struct toshiba_acpi_dev { | ||
280 | struct platform_device *p_dev; | ||
281 | struct rfkill *bt_rfk; | ||
282 | struct input_dev *hotkey_dev; | ||
283 | int illumination_installed; | ||
284 | acpi_handle handle; | ||
285 | |||
286 | const char *bt_name; | ||
287 | |||
288 | struct mutex mutex; | ||
289 | }; | ||
290 | |||
291 | /* Illumination support */ | 271 | /* Illumination support */ |
292 | static int toshiba_illumination_available(void) | 272 | static int toshiba_illumination_available(struct toshiba_acpi_dev *dev) |
293 | { | 273 | { |
294 | u32 in[HCI_WORDS] = { 0, 0, 0, 0, 0, 0 }; | 274 | u32 in[HCI_WORDS] = { 0, 0, 0, 0, 0, 0 }; |
295 | u32 out[HCI_WORDS]; | 275 | u32 out[HCI_WORDS]; |
296 | acpi_status status; | 276 | acpi_status status; |
297 | 277 | ||
298 | in[0] = 0xf100; | 278 | in[0] = 0xf100; |
299 | status = hci_raw(in, out); | 279 | status = hci_raw(dev, in, out); |
300 | if (ACPI_FAILURE(status)) { | 280 | if (ACPI_FAILURE(status)) { |
301 | pr_info("Illumination device not available\n"); | 281 | pr_info("Illumination device not available\n"); |
302 | return 0; | 282 | return 0; |
303 | } | 283 | } |
304 | in[0] = 0xf400; | 284 | in[0] = 0xf400; |
305 | status = hci_raw(in, out); | 285 | status = hci_raw(dev, in, out); |
306 | return 1; | 286 | return 1; |
307 | } | 287 | } |
308 | 288 | ||
309 | static void toshiba_illumination_set(struct led_classdev *cdev, | 289 | static void toshiba_illumination_set(struct led_classdev *cdev, |
310 | enum led_brightness brightness) | 290 | enum led_brightness brightness) |
311 | { | 291 | { |
292 | struct toshiba_acpi_dev *dev = container_of(cdev, | ||
293 | struct toshiba_acpi_dev, led_dev); | ||
312 | u32 in[HCI_WORDS] = { 0, 0, 0, 0, 0, 0 }; | 294 | u32 in[HCI_WORDS] = { 0, 0, 0, 0, 0, 0 }; |
313 | u32 out[HCI_WORDS]; | 295 | u32 out[HCI_WORDS]; |
314 | acpi_status status; | 296 | acpi_status status; |
315 | 297 | ||
316 | /* First request : initialize communication. */ | 298 | /* First request : initialize communication. */ |
317 | in[0] = 0xf100; | 299 | in[0] = 0xf100; |
318 | status = hci_raw(in, out); | 300 | status = hci_raw(dev, in, out); |
319 | if (ACPI_FAILURE(status)) { | 301 | if (ACPI_FAILURE(status)) { |
320 | pr_info("Illumination device not available\n"); | 302 | pr_info("Illumination device not available\n"); |
321 | return; | 303 | return; |
@@ -326,7 +308,7 @@ static void toshiba_illumination_set(struct led_classdev *cdev, | |||
326 | in[0] = 0xf400; | 308 | in[0] = 0xf400; |
327 | in[1] = 0x14e; | 309 | in[1] = 0x14e; |
328 | in[2] = 1; | 310 | in[2] = 1; |
329 | status = hci_raw(in, out); | 311 | status = hci_raw(dev, in, out); |
330 | if (ACPI_FAILURE(status)) { | 312 | if (ACPI_FAILURE(status)) { |
331 | pr_info("ACPI call for illumination failed\n"); | 313 | pr_info("ACPI call for illumination failed\n"); |
332 | return; | 314 | return; |
@@ -336,7 +318,7 @@ static void toshiba_illumination_set(struct led_classdev *cdev, | |||
336 | in[0] = 0xf400; | 318 | in[0] = 0xf400; |
337 | in[1] = 0x14e; | 319 | in[1] = 0x14e; |
338 | in[2] = 0; | 320 | in[2] = 0; |
339 | status = hci_raw(in, out); | 321 | status = hci_raw(dev, in, out); |
340 | if (ACPI_FAILURE(status)) { | 322 | if (ACPI_FAILURE(status)) { |
341 | pr_info("ACPI call for illumination failed.\n"); | 323 | pr_info("ACPI call for illumination failed.\n"); |
342 | return; | 324 | return; |
@@ -347,11 +329,13 @@ static void toshiba_illumination_set(struct led_classdev *cdev, | |||
347 | in[0] = 0xf200; | 329 | in[0] = 0xf200; |
348 | in[1] = 0; | 330 | in[1] = 0; |
349 | in[2] = 0; | 331 | in[2] = 0; |
350 | hci_raw(in, out); | 332 | hci_raw(dev, in, out); |
351 | } | 333 | } |
352 | 334 | ||
353 | static enum led_brightness toshiba_illumination_get(struct led_classdev *cdev) | 335 | static enum led_brightness toshiba_illumination_get(struct led_classdev *cdev) |
354 | { | 336 | { |
337 | struct toshiba_acpi_dev *dev = container_of(cdev, | ||
338 | struct toshiba_acpi_dev, led_dev); | ||
355 | u32 in[HCI_WORDS] = { 0, 0, 0, 0, 0, 0 }; | 339 | u32 in[HCI_WORDS] = { 0, 0, 0, 0, 0, 0 }; |
356 | u32 out[HCI_WORDS]; | 340 | u32 out[HCI_WORDS]; |
357 | acpi_status status; | 341 | acpi_status status; |
@@ -359,7 +343,7 @@ static enum led_brightness toshiba_illumination_get(struct led_classdev *cdev) | |||
359 | 343 | ||
360 | /*Â First request : initialize communication. */ | 344 | /*Â First request : initialize communication. */ |
361 | in[0] = 0xf100; | 345 | in[0] = 0xf100; |
362 | status = hci_raw(in, out); | 346 | status = hci_raw(dev, in, out); |
363 | if (ACPI_FAILURE(status)) { | 347 | if (ACPI_FAILURE(status)) { |
364 | pr_info("Illumination device not available\n"); | 348 | pr_info("Illumination device not available\n"); |
365 | return LED_OFF; | 349 | return LED_OFF; |
@@ -368,7 +352,7 @@ static enum led_brightness toshiba_illumination_get(struct led_classdev *cdev) | |||
368 | /* Check the illumination */ | 352 | /* Check the illumination */ |
369 | in[0] = 0xf300; | 353 | in[0] = 0xf300; |
370 | in[1] = 0x14e; | 354 | in[1] = 0x14e; |
371 | status = hci_raw(in, out); | 355 | status = hci_raw(dev, in, out); |
372 | if (ACPI_FAILURE(status)) { | 356 | if (ACPI_FAILURE(status)) { |
373 | pr_info("ACPI call for illumination failed.\n"); | 357 | pr_info("ACPI call for illumination failed.\n"); |
374 | return LED_OFF; | 358 | return LED_OFF; |
@@ -380,46 +364,35 @@ static enum led_brightness toshiba_illumination_get(struct led_classdev *cdev) | |||
380 | in[0] = 0xf200; | 364 | in[0] = 0xf200; |
381 | in[1] = 0; | 365 | in[1] = 0; |
382 | in[2] = 0; | 366 | in[2] = 0; |
383 | hci_raw(in, out); | 367 | hci_raw(dev, in, out); |
384 | 368 | ||
385 | return result; | 369 | return result; |
386 | } | 370 | } |
387 | 371 | ||
388 | static struct led_classdev toshiba_led = { | ||
389 | .name = "toshiba::illumination", | ||
390 | .max_brightness = 1, | ||
391 | .brightness_set = toshiba_illumination_set, | ||
392 | .brightness_get = toshiba_illumination_get, | ||
393 | }; | ||
394 | |||
395 | static struct toshiba_acpi_dev toshiba_acpi = { | ||
396 | .bt_name = "Toshiba Bluetooth", | ||
397 | }; | ||
398 | |||
399 | /* Bluetooth rfkill handlers */ | 372 | /* Bluetooth rfkill handlers */ |
400 | 373 | ||
401 | static u32 hci_get_bt_present(bool *present) | 374 | static u32 hci_get_bt_present(struct toshiba_acpi_dev *dev, bool *present) |
402 | { | 375 | { |
403 | u32 hci_result; | 376 | u32 hci_result; |
404 | u32 value, value2; | 377 | u32 value, value2; |
405 | 378 | ||
406 | value = 0; | 379 | value = 0; |
407 | value2 = 0; | 380 | value2 = 0; |
408 | hci_read2(HCI_WIRELESS, &value, &value2, &hci_result); | 381 | hci_read2(dev, HCI_WIRELESS, &value, &value2, &hci_result); |
409 | if (hci_result == HCI_SUCCESS) | 382 | if (hci_result == HCI_SUCCESS) |
410 | *present = (value & HCI_WIRELESS_BT_PRESENT) ? true : false; | 383 | *present = (value & HCI_WIRELESS_BT_PRESENT) ? true : false; |
411 | 384 | ||
412 | return hci_result; | 385 | return hci_result; |
413 | } | 386 | } |
414 | 387 | ||
415 | static u32 hci_get_radio_state(bool *radio_state) | 388 | static u32 hci_get_radio_state(struct toshiba_acpi_dev *dev, bool *radio_state) |
416 | { | 389 | { |
417 | u32 hci_result; | 390 | u32 hci_result; |
418 | u32 value, value2; | 391 | u32 value, value2; |
419 | 392 | ||
420 | value = 0; | 393 | value = 0; |
421 | value2 = 0x0001; | 394 | value2 = 0x0001; |
422 | hci_read2(HCI_WIRELESS, &value, &value2, &hci_result); | 395 | hci_read2(dev, HCI_WIRELESS, &value, &value2, &hci_result); |
423 | 396 | ||
424 | *radio_state = value & HCI_WIRELESS_KILL_SWITCH; | 397 | *radio_state = value & HCI_WIRELESS_KILL_SWITCH; |
425 | return hci_result; | 398 | return hci_result; |
@@ -436,8 +409,8 @@ static int bt_rfkill_set_block(void *data, bool blocked) | |||
436 | value = (blocked == false); | 409 | value = (blocked == false); |
437 | 410 | ||
438 | mutex_lock(&dev->mutex); | 411 | mutex_lock(&dev->mutex); |
439 | if (hci_get_radio_state(&radio_state) != HCI_SUCCESS) { | 412 | if (hci_get_radio_state(dev, &radio_state) != HCI_SUCCESS) { |
440 | err = -EBUSY; | 413 | err = -EIO; |
441 | goto out; | 414 | goto out; |
442 | } | 415 | } |
443 | 416 | ||
@@ -446,11 +419,11 @@ static int bt_rfkill_set_block(void *data, bool blocked) | |||
446 | goto out; | 419 | goto out; |
447 | } | 420 | } |
448 | 421 | ||
449 | hci_write2(HCI_WIRELESS, value, HCI_WIRELESS_BT_POWER, &result1); | 422 | hci_write2(dev, HCI_WIRELESS, value, HCI_WIRELESS_BT_POWER, &result1); |
450 | hci_write2(HCI_WIRELESS, value, HCI_WIRELESS_BT_ATTACH, &result2); | 423 | hci_write2(dev, HCI_WIRELESS, value, HCI_WIRELESS_BT_ATTACH, &result2); |
451 | 424 | ||
452 | if (result1 != HCI_SUCCESS || result2 != HCI_SUCCESS) | 425 | if (result1 != HCI_SUCCESS || result2 != HCI_SUCCESS) |
453 | err = -EBUSY; | 426 | err = -EIO; |
454 | else | 427 | else |
455 | err = 0; | 428 | err = 0; |
456 | out: | 429 | out: |
@@ -467,7 +440,7 @@ static void bt_rfkill_poll(struct rfkill *rfkill, void *data) | |||
467 | 440 | ||
468 | mutex_lock(&dev->mutex); | 441 | mutex_lock(&dev->mutex); |
469 | 442 | ||
470 | hci_result = hci_get_radio_state(&value); | 443 | hci_result = hci_get_radio_state(dev, &value); |
471 | if (hci_result != HCI_SUCCESS) { | 444 | if (hci_result != HCI_SUCCESS) { |
472 | /* Can't do anything useful */ | 445 | /* Can't do anything useful */ |
473 | mutex_unlock(&dev->mutex); | 446 | mutex_unlock(&dev->mutex); |
@@ -488,63 +461,64 @@ static const struct rfkill_ops toshiba_rfk_ops = { | |||
488 | }; | 461 | }; |
489 | 462 | ||
490 | static struct proc_dir_entry *toshiba_proc_dir /*= 0*/ ; | 463 | static struct proc_dir_entry *toshiba_proc_dir /*= 0*/ ; |
491 | static struct backlight_device *toshiba_backlight_device; | ||
492 | static int force_fan; | ||
493 | static int last_key_event; | ||
494 | static int key_event_valid; | ||
495 | 464 | ||
496 | static int get_lcd(struct backlight_device *bd) | 465 | static int get_lcd(struct backlight_device *bd) |
497 | { | 466 | { |
467 | struct toshiba_acpi_dev *dev = bl_get_data(bd); | ||
498 | u32 hci_result; | 468 | u32 hci_result; |
499 | u32 value; | 469 | u32 value; |
500 | 470 | ||
501 | hci_read1(HCI_LCD_BRIGHTNESS, &value, &hci_result); | 471 | hci_read1(dev, HCI_LCD_BRIGHTNESS, &value, &hci_result); |
502 | if (hci_result == HCI_SUCCESS) { | 472 | if (hci_result == HCI_SUCCESS) |
503 | return (value >> HCI_LCD_BRIGHTNESS_SHIFT); | 473 | return (value >> HCI_LCD_BRIGHTNESS_SHIFT); |
504 | } else | 474 | |
505 | return -EFAULT; | 475 | return -EIO; |
506 | } | 476 | } |
507 | 477 | ||
508 | static int lcd_proc_show(struct seq_file *m, void *v) | 478 | static int lcd_proc_show(struct seq_file *m, void *v) |
509 | { | 479 | { |
510 | int value = get_lcd(NULL); | 480 | struct toshiba_acpi_dev *dev = m->private; |
481 | int value; | ||
482 | |||
483 | if (!dev->backlight_dev) | ||
484 | return -ENODEV; | ||
511 | 485 | ||
486 | value = get_lcd(dev->backlight_dev); | ||
512 | if (value >= 0) { | 487 | if (value >= 0) { |
513 | seq_printf(m, "brightness: %d\n", value); | 488 | seq_printf(m, "brightness: %d\n", value); |
514 | seq_printf(m, "brightness_levels: %d\n", | 489 | seq_printf(m, "brightness_levels: %d\n", |
515 | HCI_LCD_BRIGHTNESS_LEVELS); | 490 | HCI_LCD_BRIGHTNESS_LEVELS); |
516 | } else { | 491 | return 0; |
517 | pr_err("Error reading LCD brightness\n"); | ||
518 | } | 492 | } |
519 | 493 | ||
520 | return 0; | 494 | pr_err("Error reading LCD brightness\n"); |
495 | return -EIO; | ||
521 | } | 496 | } |
522 | 497 | ||
523 | static int lcd_proc_open(struct inode *inode, struct file *file) | 498 | static int lcd_proc_open(struct inode *inode, struct file *file) |
524 | { | 499 | { |
525 | return single_open(file, lcd_proc_show, NULL); | 500 | return single_open(file, lcd_proc_show, PDE(inode)->data); |
526 | } | 501 | } |
527 | 502 | ||
528 | static int set_lcd(int value) | 503 | static int set_lcd(struct toshiba_acpi_dev *dev, int value) |
529 | { | 504 | { |
530 | u32 hci_result; | 505 | u32 hci_result; |
531 | 506 | ||
532 | value = value << HCI_LCD_BRIGHTNESS_SHIFT; | 507 | value = value << HCI_LCD_BRIGHTNESS_SHIFT; |
533 | hci_write1(HCI_LCD_BRIGHTNESS, value, &hci_result); | 508 | hci_write1(dev, HCI_LCD_BRIGHTNESS, value, &hci_result); |
534 | if (hci_result != HCI_SUCCESS) | 509 | return hci_result == HCI_SUCCESS ? 0 : -EIO; |
535 | return -EFAULT; | ||
536 | |||
537 | return 0; | ||
538 | } | 510 | } |
539 | 511 | ||
540 | static int set_lcd_status(struct backlight_device *bd) | 512 | static int set_lcd_status(struct backlight_device *bd) |
541 | { | 513 | { |
542 | return set_lcd(bd->props.brightness); | 514 | struct toshiba_acpi_dev *dev = bl_get_data(bd); |
515 | return set_lcd(dev, bd->props.brightness); | ||
543 | } | 516 | } |
544 | 517 | ||
545 | static ssize_t lcd_proc_write(struct file *file, const char __user *buf, | 518 | static ssize_t lcd_proc_write(struct file *file, const char __user *buf, |
546 | size_t count, loff_t *pos) | 519 | size_t count, loff_t *pos) |
547 | { | 520 | { |
521 | struct toshiba_acpi_dev *dev = PDE(file->f_path.dentry->d_inode)->data; | ||
548 | char cmd[42]; | 522 | char cmd[42]; |
549 | size_t len; | 523 | size_t len; |
550 | int value; | 524 | int value; |
@@ -557,7 +531,7 @@ static ssize_t lcd_proc_write(struct file *file, const char __user *buf, | |||
557 | 531 | ||
558 | if (sscanf(cmd, " brightness : %i", &value) == 1 && | 532 | if (sscanf(cmd, " brightness : %i", &value) == 1 && |
559 | value >= 0 && value < HCI_LCD_BRIGHTNESS_LEVELS) { | 533 | value >= 0 && value < HCI_LCD_BRIGHTNESS_LEVELS) { |
560 | ret = set_lcd(value); | 534 | ret = set_lcd(dev, value); |
561 | if (ret == 0) | 535 | if (ret == 0) |
562 | ret = count; | 536 | ret = count; |
563 | } else { | 537 | } else { |
@@ -575,41 +549,49 @@ static const struct file_operations lcd_proc_fops = { | |||
575 | .write = lcd_proc_write, | 549 | .write = lcd_proc_write, |
576 | }; | 550 | }; |
577 | 551 | ||
578 | static int video_proc_show(struct seq_file *m, void *v) | 552 | static int get_video_status(struct toshiba_acpi_dev *dev, u32 *status) |
579 | { | 553 | { |
580 | u32 hci_result; | 554 | u32 hci_result; |
555 | |||
556 | hci_read1(dev, HCI_VIDEO_OUT, status, &hci_result); | ||
557 | return hci_result == HCI_SUCCESS ? 0 : -EIO; | ||
558 | } | ||
559 | |||
560 | static int video_proc_show(struct seq_file *m, void *v) | ||
561 | { | ||
562 | struct toshiba_acpi_dev *dev = m->private; | ||
581 | u32 value; | 563 | u32 value; |
564 | int ret; | ||
582 | 565 | ||
583 | hci_read1(HCI_VIDEO_OUT, &value, &hci_result); | 566 | ret = get_video_status(dev, &value); |
584 | if (hci_result == HCI_SUCCESS) { | 567 | if (!ret) { |
585 | int is_lcd = (value & HCI_VIDEO_OUT_LCD) ? 1 : 0; | 568 | int is_lcd = (value & HCI_VIDEO_OUT_LCD) ? 1 : 0; |
586 | int is_crt = (value & HCI_VIDEO_OUT_CRT) ? 1 : 0; | 569 | int is_crt = (value & HCI_VIDEO_OUT_CRT) ? 1 : 0; |
587 | int is_tv = (value & HCI_VIDEO_OUT_TV) ? 1 : 0; | 570 | int is_tv = (value & HCI_VIDEO_OUT_TV) ? 1 : 0; |
588 | seq_printf(m, "lcd_out: %d\n", is_lcd); | 571 | seq_printf(m, "lcd_out: %d\n", is_lcd); |
589 | seq_printf(m, "crt_out: %d\n", is_crt); | 572 | seq_printf(m, "crt_out: %d\n", is_crt); |
590 | seq_printf(m, "tv_out: %d\n", is_tv); | 573 | seq_printf(m, "tv_out: %d\n", is_tv); |
591 | } else { | ||
592 | pr_err("Error reading video out status\n"); | ||
593 | } | 574 | } |
594 | 575 | ||
595 | return 0; | 576 | return ret; |
596 | } | 577 | } |
597 | 578 | ||
598 | static int video_proc_open(struct inode *inode, struct file *file) | 579 | static int video_proc_open(struct inode *inode, struct file *file) |
599 | { | 580 | { |
600 | return single_open(file, video_proc_show, NULL); | 581 | return single_open(file, video_proc_show, PDE(inode)->data); |
601 | } | 582 | } |
602 | 583 | ||
603 | static ssize_t video_proc_write(struct file *file, const char __user *buf, | 584 | static ssize_t video_proc_write(struct file *file, const char __user *buf, |
604 | size_t count, loff_t *pos) | 585 | size_t count, loff_t *pos) |
605 | { | 586 | { |
587 | struct toshiba_acpi_dev *dev = PDE(file->f_path.dentry->d_inode)->data; | ||
606 | char *cmd, *buffer; | 588 | char *cmd, *buffer; |
589 | int ret; | ||
607 | int value; | 590 | int value; |
608 | int remain = count; | 591 | int remain = count; |
609 | int lcd_out = -1; | 592 | int lcd_out = -1; |
610 | int crt_out = -1; | 593 | int crt_out = -1; |
611 | int tv_out = -1; | 594 | int tv_out = -1; |
612 | u32 hci_result; | ||
613 | u32 video_out; | 595 | u32 video_out; |
614 | 596 | ||
615 | cmd = kmalloc(count + 1, GFP_KERNEL); | 597 | cmd = kmalloc(count + 1, GFP_KERNEL); |
@@ -644,8 +626,8 @@ static ssize_t video_proc_write(struct file *file, const char __user *buf, | |||
644 | 626 | ||
645 | kfree(cmd); | 627 | kfree(cmd); |
646 | 628 | ||
647 | hci_read1(HCI_VIDEO_OUT, &video_out, &hci_result); | 629 | ret = get_video_status(dev, &video_out); |
648 | if (hci_result == HCI_SUCCESS) { | 630 | if (!ret) { |
649 | unsigned int new_video_out = video_out; | 631 | unsigned int new_video_out = video_out; |
650 | if (lcd_out != -1) | 632 | if (lcd_out != -1) |
651 | _set_bit(&new_video_out, HCI_VIDEO_OUT_LCD, lcd_out); | 633 | _set_bit(&new_video_out, HCI_VIDEO_OUT_LCD, lcd_out); |
@@ -656,12 +638,10 @@ static ssize_t video_proc_write(struct file *file, const char __user *buf, | |||
656 | /* To avoid unnecessary video disruption, only write the new | 638 | /* To avoid unnecessary video disruption, only write the new |
657 | * video setting if something changed. */ | 639 | * video setting if something changed. */ |
658 | if (new_video_out != video_out) | 640 | if (new_video_out != video_out) |
659 | write_acpi_int(METHOD_VIDEO_OUT, new_video_out); | 641 | ret = write_acpi_int(METHOD_VIDEO_OUT, new_video_out); |
660 | } else { | ||
661 | return -EFAULT; | ||
662 | } | 642 | } |
663 | 643 | ||
664 | return count; | 644 | return ret ? ret : count; |
665 | } | 645 | } |
666 | 646 | ||
667 | static const struct file_operations video_proc_fops = { | 647 | static const struct file_operations video_proc_fops = { |
@@ -673,30 +653,38 @@ static const struct file_operations video_proc_fops = { | |||
673 | .write = video_proc_write, | 653 | .write = video_proc_write, |
674 | }; | 654 | }; |
675 | 655 | ||
676 | static int fan_proc_show(struct seq_file *m, void *v) | 656 | static int get_fan_status(struct toshiba_acpi_dev *dev, u32 *status) |
677 | { | 657 | { |
678 | u32 hci_result; | 658 | u32 hci_result; |
659 | |||
660 | hci_read1(dev, HCI_FAN, status, &hci_result); | ||
661 | return hci_result == HCI_SUCCESS ? 0 : -EIO; | ||
662 | } | ||
663 | |||
664 | static int fan_proc_show(struct seq_file *m, void *v) | ||
665 | { | ||
666 | struct toshiba_acpi_dev *dev = m->private; | ||
667 | int ret; | ||
679 | u32 value; | 668 | u32 value; |
680 | 669 | ||
681 | hci_read1(HCI_FAN, &value, &hci_result); | 670 | ret = get_fan_status(dev, &value); |
682 | if (hci_result == HCI_SUCCESS) { | 671 | if (!ret) { |
683 | seq_printf(m, "running: %d\n", (value > 0)); | 672 | seq_printf(m, "running: %d\n", (value > 0)); |
684 | seq_printf(m, "force_on: %d\n", force_fan); | 673 | seq_printf(m, "force_on: %d\n", dev->force_fan); |
685 | } else { | ||
686 | pr_err("Error reading fan status\n"); | ||
687 | } | 674 | } |
688 | 675 | ||
689 | return 0; | 676 | return ret; |
690 | } | 677 | } |
691 | 678 | ||
692 | static int fan_proc_open(struct inode *inode, struct file *file) | 679 | static int fan_proc_open(struct inode *inode, struct file *file) |
693 | { | 680 | { |
694 | return single_open(file, fan_proc_show, NULL); | 681 | return single_open(file, fan_proc_show, PDE(inode)->data); |
695 | } | 682 | } |
696 | 683 | ||
697 | static ssize_t fan_proc_write(struct file *file, const char __user *buf, | 684 | static ssize_t fan_proc_write(struct file *file, const char __user *buf, |
698 | size_t count, loff_t *pos) | 685 | size_t count, loff_t *pos) |
699 | { | 686 | { |
687 | struct toshiba_acpi_dev *dev = PDE(file->f_path.dentry->d_inode)->data; | ||
700 | char cmd[42]; | 688 | char cmd[42]; |
701 | size_t len; | 689 | size_t len; |
702 | int value; | 690 | int value; |
@@ -709,11 +697,11 @@ static ssize_t fan_proc_write(struct file *file, const char __user *buf, | |||
709 | 697 | ||
710 | if (sscanf(cmd, " force_on : %i", &value) == 1 && | 698 | if (sscanf(cmd, " force_on : %i", &value) == 1 && |
711 | value >= 0 && value <= 1) { | 699 | value >= 0 && value <= 1) { |
712 | hci_write1(HCI_FAN, value, &hci_result); | 700 | hci_write1(dev, HCI_FAN, value, &hci_result); |
713 | if (hci_result != HCI_SUCCESS) | 701 | if (hci_result != HCI_SUCCESS) |
714 | return -EFAULT; | 702 | return -EIO; |
715 | else | 703 | else |
716 | force_fan = value; | 704 | dev->force_fan = value; |
717 | } else { | 705 | } else { |
718 | return -EINVAL; | 706 | return -EINVAL; |
719 | } | 707 | } |
@@ -732,42 +720,43 @@ static const struct file_operations fan_proc_fops = { | |||
732 | 720 | ||
733 | static int keys_proc_show(struct seq_file *m, void *v) | 721 | static int keys_proc_show(struct seq_file *m, void *v) |
734 | { | 722 | { |
723 | struct toshiba_acpi_dev *dev = m->private; | ||
735 | u32 hci_result; | 724 | u32 hci_result; |
736 | u32 value; | 725 | u32 value; |
737 | 726 | ||
738 | if (!key_event_valid) { | 727 | if (!dev->key_event_valid) { |
739 | hci_read1(HCI_SYSTEM_EVENT, &value, &hci_result); | 728 | hci_read1(dev, HCI_SYSTEM_EVENT, &value, &hci_result); |
740 | if (hci_result == HCI_SUCCESS) { | 729 | if (hci_result == HCI_SUCCESS) { |
741 | key_event_valid = 1; | 730 | dev->key_event_valid = 1; |
742 | last_key_event = value; | 731 | dev->last_key_event = value; |
743 | } else if (hci_result == HCI_EMPTY) { | 732 | } else if (hci_result == HCI_EMPTY) { |
744 | /* better luck next time */ | 733 | /* better luck next time */ |
745 | } else if (hci_result == HCI_NOT_SUPPORTED) { | 734 | } else if (hci_result == HCI_NOT_SUPPORTED) { |
746 | /* This is a workaround for an unresolved issue on | 735 | /* This is a workaround for an unresolved issue on |
747 | * some machines where system events sporadically | 736 | * some machines where system events sporadically |
748 | * become disabled. */ | 737 | * become disabled. */ |
749 | hci_write1(HCI_SYSTEM_EVENT, 1, &hci_result); | 738 | hci_write1(dev, HCI_SYSTEM_EVENT, 1, &hci_result); |
750 | pr_notice("Re-enabled hotkeys\n"); | 739 | pr_notice("Re-enabled hotkeys\n"); |
751 | } else { | 740 | } else { |
752 | pr_err("Error reading hotkey status\n"); | 741 | pr_err("Error reading hotkey status\n"); |
753 | goto end; | 742 | return -EIO; |
754 | } | 743 | } |
755 | } | 744 | } |
756 | 745 | ||
757 | seq_printf(m, "hotkey_ready: %d\n", key_event_valid); | 746 | seq_printf(m, "hotkey_ready: %d\n", dev->key_event_valid); |
758 | seq_printf(m, "hotkey: 0x%04x\n", last_key_event); | 747 | seq_printf(m, "hotkey: 0x%04x\n", dev->last_key_event); |
759 | end: | ||
760 | return 0; | 748 | return 0; |
761 | } | 749 | } |
762 | 750 | ||
763 | static int keys_proc_open(struct inode *inode, struct file *file) | 751 | static int keys_proc_open(struct inode *inode, struct file *file) |
764 | { | 752 | { |
765 | return single_open(file, keys_proc_show, NULL); | 753 | return single_open(file, keys_proc_show, PDE(inode)->data); |
766 | } | 754 | } |
767 | 755 | ||
768 | static ssize_t keys_proc_write(struct file *file, const char __user *buf, | 756 | static ssize_t keys_proc_write(struct file *file, const char __user *buf, |
769 | size_t count, loff_t *pos) | 757 | size_t count, loff_t *pos) |
770 | { | 758 | { |
759 | struct toshiba_acpi_dev *dev = PDE(file->f_path.dentry->d_inode)->data; | ||
771 | char cmd[42]; | 760 | char cmd[42]; |
772 | size_t len; | 761 | size_t len; |
773 | int value; | 762 | int value; |
@@ -778,7 +767,7 @@ static ssize_t keys_proc_write(struct file *file, const char __user *buf, | |||
778 | cmd[len] = '\0'; | 767 | cmd[len] = '\0'; |
779 | 768 | ||
780 | if (sscanf(cmd, " hotkey_ready : %i", &value) == 1 && value == 0) { | 769 | if (sscanf(cmd, " hotkey_ready : %i", &value) == 1 && value == 0) { |
781 | key_event_valid = 0; | 770 | dev->key_event_valid = 0; |
782 | } else { | 771 | } else { |
783 | return -EINVAL; | 772 | return -EINVAL; |
784 | } | 773 | } |
@@ -820,21 +809,35 @@ static const struct file_operations version_proc_fops = { | |||
820 | 809 | ||
821 | #define PROC_TOSHIBA "toshiba" | 810 | #define PROC_TOSHIBA "toshiba" |
822 | 811 | ||
823 | static void __init create_toshiba_proc_entries(void) | 812 | static void __devinit |
813 | create_toshiba_proc_entries(struct toshiba_acpi_dev *dev) | ||
824 | { | 814 | { |
825 | proc_create("lcd", S_IRUGO | S_IWUSR, toshiba_proc_dir, &lcd_proc_fops); | 815 | if (dev->backlight_dev) |
826 | proc_create("video", S_IRUGO | S_IWUSR, toshiba_proc_dir, &video_proc_fops); | 816 | proc_create_data("lcd", S_IRUGO | S_IWUSR, toshiba_proc_dir, |
827 | proc_create("fan", S_IRUGO | S_IWUSR, toshiba_proc_dir, &fan_proc_fops); | 817 | &lcd_proc_fops, dev); |
828 | proc_create("keys", S_IRUGO | S_IWUSR, toshiba_proc_dir, &keys_proc_fops); | 818 | if (dev->video_supported) |
829 | proc_create("version", S_IRUGO, toshiba_proc_dir, &version_proc_fops); | 819 | proc_create_data("video", S_IRUGO | S_IWUSR, toshiba_proc_dir, |
820 | &video_proc_fops, dev); | ||
821 | if (dev->fan_supported) | ||
822 | proc_create_data("fan", S_IRUGO | S_IWUSR, toshiba_proc_dir, | ||
823 | &fan_proc_fops, dev); | ||
824 | if (dev->hotkey_dev) | ||
825 | proc_create_data("keys", S_IRUGO | S_IWUSR, toshiba_proc_dir, | ||
826 | &keys_proc_fops, dev); | ||
827 | proc_create_data("version", S_IRUGO, toshiba_proc_dir, | ||
828 | &version_proc_fops, dev); | ||
830 | } | 829 | } |
831 | 830 | ||
832 | static void remove_toshiba_proc_entries(void) | 831 | static void remove_toshiba_proc_entries(struct toshiba_acpi_dev *dev) |
833 | { | 832 | { |
834 | remove_proc_entry("lcd", toshiba_proc_dir); | 833 | if (dev->backlight_dev) |
835 | remove_proc_entry("video", toshiba_proc_dir); | 834 | remove_proc_entry("lcd", toshiba_proc_dir); |
836 | remove_proc_entry("fan", toshiba_proc_dir); | 835 | if (dev->video_supported) |
837 | remove_proc_entry("keys", toshiba_proc_dir); | 836 | remove_proc_entry("video", toshiba_proc_dir); |
837 | if (dev->fan_supported) | ||
838 | remove_proc_entry("fan", toshiba_proc_dir); | ||
839 | if (dev->hotkey_dev) | ||
840 | remove_proc_entry("keys", toshiba_proc_dir); | ||
838 | remove_proc_entry("version", toshiba_proc_dir); | 841 | remove_proc_entry("version", toshiba_proc_dir); |
839 | } | 842 | } |
840 | 843 | ||
@@ -843,224 +846,256 @@ static const struct backlight_ops toshiba_backlight_data = { | |||
843 | .update_status = set_lcd_status, | 846 | .update_status = set_lcd_status, |
844 | }; | 847 | }; |
845 | 848 | ||
846 | static void toshiba_acpi_notify(acpi_handle handle, u32 event, void *context) | 849 | static int __devinit toshiba_acpi_setup_keyboard(struct toshiba_acpi_dev *dev) |
847 | { | ||
848 | u32 hci_result, value; | ||
849 | |||
850 | if (event != 0x80) | ||
851 | return; | ||
852 | do { | ||
853 | hci_read1(HCI_SYSTEM_EVENT, &value, &hci_result); | ||
854 | if (hci_result == HCI_SUCCESS) { | ||
855 | if (value == 0x100) | ||
856 | continue; | ||
857 | /* act on key press; ignore key release */ | ||
858 | if (value & 0x80) | ||
859 | continue; | ||
860 | |||
861 | if (!sparse_keymap_report_event(toshiba_acpi.hotkey_dev, | ||
862 | value, 1, true)) { | ||
863 | pr_info("Unknown key %x\n", | ||
864 | value); | ||
865 | } | ||
866 | } else if (hci_result == HCI_NOT_SUPPORTED) { | ||
867 | /* This is a workaround for an unresolved issue on | ||
868 | * some machines where system events sporadically | ||
869 | * become disabled. */ | ||
870 | hci_write1(HCI_SYSTEM_EVENT, 1, &hci_result); | ||
871 | pr_notice("Re-enabled hotkeys\n"); | ||
872 | } | ||
873 | } while (hci_result != HCI_EMPTY); | ||
874 | } | ||
875 | |||
876 | static int __init toshiba_acpi_setup_keyboard(char *device) | ||
877 | { | 850 | { |
878 | acpi_status status; | 851 | acpi_status status; |
879 | int error; | 852 | int error; |
880 | 853 | ||
881 | status = acpi_get_handle(NULL, device, &toshiba_acpi.handle); | 854 | dev->hotkey_dev = input_allocate_device(); |
882 | if (ACPI_FAILURE(status)) { | 855 | if (!dev->hotkey_dev) { |
883 | pr_info("Unable to get notification device\n"); | ||
884 | return -ENODEV; | ||
885 | } | ||
886 | |||
887 | toshiba_acpi.hotkey_dev = input_allocate_device(); | ||
888 | if (!toshiba_acpi.hotkey_dev) { | ||
889 | pr_info("Unable to register input device\n"); | 856 | pr_info("Unable to register input device\n"); |
890 | return -ENOMEM; | 857 | return -ENOMEM; |
891 | } | 858 | } |
892 | 859 | ||
893 | toshiba_acpi.hotkey_dev->name = "Toshiba input device"; | 860 | dev->hotkey_dev->name = "Toshiba input device"; |
894 | toshiba_acpi.hotkey_dev->phys = device; | 861 | dev->hotkey_dev->phys = "toshiba_acpi/input0"; |
895 | toshiba_acpi.hotkey_dev->id.bustype = BUS_HOST; | 862 | dev->hotkey_dev->id.bustype = BUS_HOST; |
896 | 863 | ||
897 | error = sparse_keymap_setup(toshiba_acpi.hotkey_dev, | 864 | error = sparse_keymap_setup(dev->hotkey_dev, toshiba_acpi_keymap, NULL); |
898 | toshiba_acpi_keymap, NULL); | ||
899 | if (error) | 865 | if (error) |
900 | goto err_free_dev; | 866 | goto err_free_dev; |
901 | 867 | ||
902 | status = acpi_install_notify_handler(toshiba_acpi.handle, | 868 | status = acpi_evaluate_object(dev->acpi_dev->handle, "ENAB", NULL, NULL); |
903 | ACPI_DEVICE_NOTIFY, toshiba_acpi_notify, NULL); | ||
904 | if (ACPI_FAILURE(status)) { | ||
905 | pr_info("Unable to install hotkey notification\n"); | ||
906 | error = -ENODEV; | ||
907 | goto err_free_keymap; | ||
908 | } | ||
909 | |||
910 | status = acpi_evaluate_object(toshiba_acpi.handle, "ENAB", NULL, NULL); | ||
911 | if (ACPI_FAILURE(status)) { | 869 | if (ACPI_FAILURE(status)) { |
912 | pr_info("Unable to enable hotkeys\n"); | 870 | pr_info("Unable to enable hotkeys\n"); |
913 | error = -ENODEV; | 871 | error = -ENODEV; |
914 | goto err_remove_notify; | 872 | goto err_free_keymap; |
915 | } | 873 | } |
916 | 874 | ||
917 | error = input_register_device(toshiba_acpi.hotkey_dev); | 875 | error = input_register_device(dev->hotkey_dev); |
918 | if (error) { | 876 | if (error) { |
919 | pr_info("Unable to register input device\n"); | 877 | pr_info("Unable to register input device\n"); |
920 | goto err_remove_notify; | 878 | goto err_free_keymap; |
921 | } | 879 | } |
922 | 880 | ||
923 | return 0; | 881 | return 0; |
924 | 882 | ||
925 | err_remove_notify: | ||
926 | acpi_remove_notify_handler(toshiba_acpi.handle, | ||
927 | ACPI_DEVICE_NOTIFY, toshiba_acpi_notify); | ||
928 | err_free_keymap: | 883 | err_free_keymap: |
929 | sparse_keymap_free(toshiba_acpi.hotkey_dev); | 884 | sparse_keymap_free(dev->hotkey_dev); |
930 | err_free_dev: | 885 | err_free_dev: |
931 | input_free_device(toshiba_acpi.hotkey_dev); | 886 | input_free_device(dev->hotkey_dev); |
932 | toshiba_acpi.hotkey_dev = NULL; | 887 | dev->hotkey_dev = NULL; |
933 | return error; | 888 | return error; |
934 | } | 889 | } |
935 | 890 | ||
936 | static void toshiba_acpi_exit(void) | 891 | static int toshiba_acpi_remove(struct acpi_device *acpi_dev, int type) |
937 | { | 892 | { |
938 | if (toshiba_acpi.hotkey_dev) { | 893 | struct toshiba_acpi_dev *dev = acpi_driver_data(acpi_dev); |
939 | acpi_remove_notify_handler(toshiba_acpi.handle, | 894 | |
940 | ACPI_DEVICE_NOTIFY, toshiba_acpi_notify); | 895 | remove_toshiba_proc_entries(dev); |
941 | sparse_keymap_free(toshiba_acpi.hotkey_dev); | 896 | |
942 | input_unregister_device(toshiba_acpi.hotkey_dev); | 897 | if (dev->hotkey_dev) { |
898 | input_unregister_device(dev->hotkey_dev); | ||
899 | sparse_keymap_free(dev->hotkey_dev); | ||
943 | } | 900 | } |
944 | 901 | ||
945 | if (toshiba_acpi.bt_rfk) { | 902 | if (dev->bt_rfk) { |
946 | rfkill_unregister(toshiba_acpi.bt_rfk); | 903 | rfkill_unregister(dev->bt_rfk); |
947 | rfkill_destroy(toshiba_acpi.bt_rfk); | 904 | rfkill_destroy(dev->bt_rfk); |
948 | } | 905 | } |
949 | 906 | ||
950 | if (toshiba_backlight_device) | 907 | if (dev->backlight_dev) |
951 | backlight_device_unregister(toshiba_backlight_device); | 908 | backlight_device_unregister(dev->backlight_dev); |
952 | 909 | ||
953 | remove_toshiba_proc_entries(); | 910 | if (dev->illumination_supported) |
911 | led_classdev_unregister(&dev->led_dev); | ||
954 | 912 | ||
955 | if (toshiba_proc_dir) | 913 | kfree(dev); |
956 | remove_proc_entry(PROC_TOSHIBA, acpi_root_dir); | 914 | |
915 | return 0; | ||
916 | } | ||
917 | |||
918 | static const char * __devinit find_hci_method(acpi_handle handle) | ||
919 | { | ||
920 | acpi_status status; | ||
921 | acpi_handle hci_handle; | ||
957 | 922 | ||
958 | if (toshiba_acpi.illumination_installed) | 923 | status = acpi_get_handle(handle, "GHCI", &hci_handle); |
959 | led_classdev_unregister(&toshiba_led); | 924 | if (ACPI_SUCCESS(status)) |
925 | return "GHCI"; | ||
960 | 926 | ||
961 | platform_device_unregister(toshiba_acpi.p_dev); | 927 | status = acpi_get_handle(handle, "SPFC", &hci_handle); |
928 | if (ACPI_SUCCESS(status)) | ||
929 | return "SPFC"; | ||
962 | 930 | ||
963 | return; | 931 | return NULL; |
964 | } | 932 | } |
965 | 933 | ||
966 | static int __init toshiba_acpi_init(void) | 934 | static int __devinit toshiba_acpi_add(struct acpi_device *acpi_dev) |
967 | { | 935 | { |
936 | struct toshiba_acpi_dev *dev; | ||
937 | const char *hci_method; | ||
968 | u32 hci_result; | 938 | u32 hci_result; |
939 | u32 dummy; | ||
969 | bool bt_present; | 940 | bool bt_present; |
970 | int ret = 0; | 941 | int ret = 0; |
971 | struct backlight_properties props; | 942 | struct backlight_properties props; |
972 | 943 | ||
973 | if (acpi_disabled) | ||
974 | return -ENODEV; | ||
975 | |||
976 | /* simple device detection: look for HCI method */ | ||
977 | if (is_valid_acpi_path(TOSH_INTERFACE_1 GHCI_METHOD)) { | ||
978 | method_hci = TOSH_INTERFACE_1 GHCI_METHOD; | ||
979 | if (toshiba_acpi_setup_keyboard(TOSH_INTERFACE_1)) | ||
980 | pr_info("Unable to activate hotkeys\n"); | ||
981 | } else if (is_valid_acpi_path(TOSH_INTERFACE_2 GHCI_METHOD)) { | ||
982 | method_hci = TOSH_INTERFACE_2 GHCI_METHOD; | ||
983 | if (toshiba_acpi_setup_keyboard(TOSH_INTERFACE_2)) | ||
984 | pr_info("Unable to activate hotkeys\n"); | ||
985 | } else | ||
986 | return -ENODEV; | ||
987 | |||
988 | pr_info("Toshiba Laptop ACPI Extras version %s\n", | 944 | pr_info("Toshiba Laptop ACPI Extras version %s\n", |
989 | TOSHIBA_ACPI_VERSION); | 945 | TOSHIBA_ACPI_VERSION); |
990 | pr_info(" HCI method: %s\n", method_hci); | 946 | |
991 | 947 | hci_method = find_hci_method(acpi_dev->handle); | |
992 | mutex_init(&toshiba_acpi.mutex); | 948 | if (!hci_method) { |
993 | 949 | pr_err("HCI interface not found\n"); | |
994 | toshiba_acpi.p_dev = platform_device_register_simple("toshiba_acpi", | 950 | return -ENODEV; |
995 | -1, NULL, 0); | ||
996 | if (IS_ERR(toshiba_acpi.p_dev)) { | ||
997 | ret = PTR_ERR(toshiba_acpi.p_dev); | ||
998 | pr_err("unable to register platform device\n"); | ||
999 | toshiba_acpi.p_dev = NULL; | ||
1000 | toshiba_acpi_exit(); | ||
1001 | return ret; | ||
1002 | } | 951 | } |
1003 | 952 | ||
1004 | force_fan = 0; | 953 | dev = kzalloc(sizeof(*dev), GFP_KERNEL); |
1005 | key_event_valid = 0; | 954 | if (!dev) |
955 | return -ENOMEM; | ||
956 | dev->acpi_dev = acpi_dev; | ||
957 | dev->method_hci = hci_method; | ||
958 | acpi_dev->driver_data = dev; | ||
1006 | 959 | ||
1007 | /* enable event fifo */ | 960 | if (toshiba_acpi_setup_keyboard(dev)) |
1008 | hci_write1(HCI_SYSTEM_EVENT, 1, &hci_result); | 961 | pr_info("Unable to activate hotkeys\n"); |
1009 | 962 | ||
1010 | toshiba_proc_dir = proc_mkdir(PROC_TOSHIBA, acpi_root_dir); | 963 | mutex_init(&dev->mutex); |
1011 | if (!toshiba_proc_dir) { | 964 | |
1012 | toshiba_acpi_exit(); | 965 | /* enable event fifo */ |
1013 | return -ENODEV; | 966 | hci_write1(dev, HCI_SYSTEM_EVENT, 1, &hci_result); |
1014 | } else { | ||
1015 | create_toshiba_proc_entries(); | ||
1016 | } | ||
1017 | 967 | ||
1018 | props.type = BACKLIGHT_PLATFORM; | 968 | props.type = BACKLIGHT_PLATFORM; |
1019 | props.max_brightness = HCI_LCD_BRIGHTNESS_LEVELS - 1; | 969 | props.max_brightness = HCI_LCD_BRIGHTNESS_LEVELS - 1; |
1020 | toshiba_backlight_device = backlight_device_register("toshiba", | 970 | dev->backlight_dev = backlight_device_register("toshiba", |
1021 | &toshiba_acpi.p_dev->dev, | 971 | &acpi_dev->dev, |
1022 | NULL, | 972 | dev, |
1023 | &toshiba_backlight_data, | 973 | &toshiba_backlight_data, |
1024 | &props); | 974 | &props); |
1025 | if (IS_ERR(toshiba_backlight_device)) { | 975 | if (IS_ERR(dev->backlight_dev)) { |
1026 | ret = PTR_ERR(toshiba_backlight_device); | 976 | ret = PTR_ERR(dev->backlight_dev); |
1027 | 977 | ||
1028 | pr_err("Could not register toshiba backlight device\n"); | 978 | pr_err("Could not register toshiba backlight device\n"); |
1029 | toshiba_backlight_device = NULL; | 979 | dev->backlight_dev = NULL; |
1030 | toshiba_acpi_exit(); | 980 | goto error; |
1031 | return ret; | ||
1032 | } | 981 | } |
982 | dev->backlight_dev->props.brightness = get_lcd(dev->backlight_dev); | ||
1033 | 983 | ||
1034 | /* Register rfkill switch for Bluetooth */ | 984 | /* Register rfkill switch for Bluetooth */ |
1035 | if (hci_get_bt_present(&bt_present) == HCI_SUCCESS && bt_present) { | 985 | if (hci_get_bt_present(dev, &bt_present) == HCI_SUCCESS && bt_present) { |
1036 | toshiba_acpi.bt_rfk = rfkill_alloc(toshiba_acpi.bt_name, | 986 | dev->bt_rfk = rfkill_alloc("Toshiba Bluetooth", |
1037 | &toshiba_acpi.p_dev->dev, | 987 | &acpi_dev->dev, |
1038 | RFKILL_TYPE_BLUETOOTH, | 988 | RFKILL_TYPE_BLUETOOTH, |
1039 | &toshiba_rfk_ops, | 989 | &toshiba_rfk_ops, |
1040 | &toshiba_acpi); | 990 | dev); |
1041 | if (!toshiba_acpi.bt_rfk) { | 991 | if (!dev->bt_rfk) { |
1042 | pr_err("unable to allocate rfkill device\n"); | 992 | pr_err("unable to allocate rfkill device\n"); |
1043 | toshiba_acpi_exit(); | 993 | ret = -ENOMEM; |
1044 | return -ENOMEM; | 994 | goto error; |
1045 | } | 995 | } |
1046 | 996 | ||
1047 | ret = rfkill_register(toshiba_acpi.bt_rfk); | 997 | ret = rfkill_register(dev->bt_rfk); |
1048 | if (ret) { | 998 | if (ret) { |
1049 | pr_err("unable to register rfkill device\n"); | 999 | pr_err("unable to register rfkill device\n"); |
1050 | rfkill_destroy(toshiba_acpi.bt_rfk); | 1000 | rfkill_destroy(dev->bt_rfk); |
1051 | toshiba_acpi_exit(); | 1001 | goto error; |
1052 | return ret; | ||
1053 | } | 1002 | } |
1054 | } | 1003 | } |
1055 | 1004 | ||
1056 | toshiba_acpi.illumination_installed = 0; | 1005 | if (toshiba_illumination_available(dev)) { |
1057 | if (toshiba_illumination_available()) { | 1006 | dev->led_dev.name = "toshiba::illumination"; |
1058 | if (!led_classdev_register(&(toshiba_acpi.p_dev->dev), | 1007 | dev->led_dev.max_brightness = 1; |
1059 | &toshiba_led)) | 1008 | dev->led_dev.brightness_set = toshiba_illumination_set; |
1060 | toshiba_acpi.illumination_installed = 1; | 1009 | dev->led_dev.brightness_get = toshiba_illumination_get; |
1010 | if (!led_classdev_register(&acpi_dev->dev, &dev->led_dev)) | ||
1011 | dev->illumination_supported = 1; | ||
1061 | } | 1012 | } |
1062 | 1013 | ||
1014 | /* Determine whether or not BIOS supports fan and video interfaces */ | ||
1015 | |||
1016 | ret = get_video_status(dev, &dummy); | ||
1017 | dev->video_supported = !ret; | ||
1018 | |||
1019 | ret = get_fan_status(dev, &dummy); | ||
1020 | dev->fan_supported = !ret; | ||
1021 | |||
1022 | create_toshiba_proc_entries(dev); | ||
1023 | |||
1063 | return 0; | 1024 | return 0; |
1025 | |||
1026 | error: | ||
1027 | toshiba_acpi_remove(acpi_dev, 0); | ||
1028 | return ret; | ||
1029 | } | ||
1030 | |||
1031 | static void toshiba_acpi_notify(struct acpi_device *acpi_dev, u32 event) | ||
1032 | { | ||
1033 | struct toshiba_acpi_dev *dev = acpi_driver_data(acpi_dev); | ||
1034 | u32 hci_result, value; | ||
1035 | |||
1036 | if (event != 0x80) | ||
1037 | return; | ||
1038 | do { | ||
1039 | hci_read1(dev, HCI_SYSTEM_EVENT, &value, &hci_result); | ||
1040 | if (hci_result == HCI_SUCCESS) { | ||
1041 | if (value == 0x100) | ||
1042 | continue; | ||
1043 | /* act on key press; ignore key release */ | ||
1044 | if (value & 0x80) | ||
1045 | continue; | ||
1046 | |||
1047 | if (!sparse_keymap_report_event(dev->hotkey_dev, | ||
1048 | value, 1, true)) { | ||
1049 | pr_info("Unknown key %x\n", | ||
1050 | value); | ||
1051 | } | ||
1052 | } else if (hci_result == HCI_NOT_SUPPORTED) { | ||
1053 | /* This is a workaround for an unresolved issue on | ||
1054 | * some machines where system events sporadically | ||
1055 | * become disabled. */ | ||
1056 | hci_write1(dev, HCI_SYSTEM_EVENT, 1, &hci_result); | ||
1057 | pr_notice("Re-enabled hotkeys\n"); | ||
1058 | } | ||
1059 | } while (hci_result != HCI_EMPTY); | ||
1060 | } | ||
1061 | |||
1062 | |||
1063 | static struct acpi_driver toshiba_acpi_driver = { | ||
1064 | .name = "Toshiba ACPI driver", | ||
1065 | .owner = THIS_MODULE, | ||
1066 | .ids = toshiba_device_ids, | ||
1067 | .flags = ACPI_DRIVER_ALL_NOTIFY_EVENTS, | ||
1068 | .ops = { | ||
1069 | .add = toshiba_acpi_add, | ||
1070 | .remove = toshiba_acpi_remove, | ||
1071 | .notify = toshiba_acpi_notify, | ||
1072 | }, | ||
1073 | }; | ||
1074 | |||
1075 | static int __init toshiba_acpi_init(void) | ||
1076 | { | ||
1077 | int ret; | ||
1078 | |||
1079 | toshiba_proc_dir = proc_mkdir(PROC_TOSHIBA, acpi_root_dir); | ||
1080 | if (!toshiba_proc_dir) { | ||
1081 | pr_err("Unable to create proc dir " PROC_TOSHIBA "\n"); | ||
1082 | return -ENODEV; | ||
1083 | } | ||
1084 | |||
1085 | ret = acpi_bus_register_driver(&toshiba_acpi_driver); | ||
1086 | if (ret) { | ||
1087 | pr_err("Failed to register ACPI driver: %d\n", ret); | ||
1088 | remove_proc_entry(PROC_TOSHIBA, acpi_root_dir); | ||
1089 | } | ||
1090 | |||
1091 | return ret; | ||
1092 | } | ||
1093 | |||
1094 | static void __exit toshiba_acpi_exit(void) | ||
1095 | { | ||
1096 | acpi_bus_unregister_driver(&toshiba_acpi_driver); | ||
1097 | if (toshiba_proc_dir) | ||
1098 | remove_proc_entry(PROC_TOSHIBA, acpi_root_dir); | ||
1064 | } | 1099 | } |
1065 | 1100 | ||
1066 | module_init(toshiba_acpi_init); | 1101 | module_init(toshiba_acpi_init); |