aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/platform
diff options
context:
space:
mode:
authorPierre Ducroquet <pinaraf@pinaraf.info>2010-07-29 05:56:59 -0400
committerMatthew Garrett <mjg@redhat.com>2010-08-03 09:49:10 -0400
commit6c3f6e6c575a0a992429427d4978c6091756a526 (patch)
tree596239acbe95dcd6b936683ca515c9b97a01a75b /drivers/platform
parent5ca56718917a353a7a916b182f6d7f1f2479c5bf (diff)
toshiba-acpi: Add support for Toshiba Illumination.
Add support for Toshiba Illumination. This is a set of LEDs installed on some Toshiba laptops. It is controlled through ACPI, the commands has been found through reverse engineering. It has been tested on a Toshiba Qosmio G50-122. Signed-off-by: Pierre Ducroquet <pinaraf@pinaraf.info> Signed-off-by: Matthew Garrett <mjg@redhat.com>
Diffstat (limited to 'drivers/platform')
-rw-r--r--drivers/platform/x86/toshiba_acpi.c117
1 files changed, 117 insertions, 0 deletions
diff --git a/drivers/platform/x86/toshiba_acpi.c b/drivers/platform/x86/toshiba_acpi.c
index 627fc384d068..7d67a45bb2b0 100644
--- a/drivers/platform/x86/toshiba_acpi.c
+++ b/drivers/platform/x86/toshiba_acpi.c
@@ -4,6 +4,7 @@
4 * 4 *
5 * Copyright (C) 2002-2004 John Belmonte 5 * Copyright (C) 2002-2004 John Belmonte
6 * Copyright (C) 2008 Philip Langdale 6 * Copyright (C) 2008 Philip Langdale
7 * Copyright (C) 2010 Pierre Ducroquet
7 * 8 *
8 * This program is free software; you can redistribute it and/or modify 9 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by 10 * it under the terms of the GNU General Public License as published by
@@ -47,6 +48,7 @@
47#include <linux/platform_device.h> 48#include <linux/platform_device.h>
48#include <linux/rfkill.h> 49#include <linux/rfkill.h>
49#include <linux/input.h> 50#include <linux/input.h>
51#include <linux/leds.h>
50#include <linux/slab.h> 52#include <linux/slab.h>
51 53
52#include <asm/uaccess.h> 54#include <asm/uaccess.h>
@@ -287,6 +289,7 @@ struct toshiba_acpi_dev {
287 struct platform_device *p_dev; 289 struct platform_device *p_dev;
288 struct rfkill *bt_rfk; 290 struct rfkill *bt_rfk;
289 struct input_dev *hotkey_dev; 291 struct input_dev *hotkey_dev;
292 int illumination_installed;
290 acpi_handle handle; 293 acpi_handle handle;
291 294
292 const char *bt_name; 295 const char *bt_name;
@@ -294,6 +297,110 @@ struct toshiba_acpi_dev {
294 struct mutex mutex; 297 struct mutex mutex;
295}; 298};
296 299
300/* Illumination support */
301static int toshiba_illumination_available(void)
302{
303 u32 in[HCI_WORDS] = { 0, 0, 0, 0, 0, 0 };
304 u32 out[HCI_WORDS];
305 acpi_status status;
306
307 in[0] = 0xf100;
308 status = hci_raw(in, out);
309 if (ACPI_FAILURE(status)) {
310 printk(MY_INFO "Illumination device not available\n");
311 return 0;
312 }
313 in[0] = 0xf400;
314 status = hci_raw(in, out);
315 return 1;
316}
317
318static void toshiba_illumination_set(struct led_classdev *cdev,
319 enum led_brightness brightness)
320{
321 u32 in[HCI_WORDS] = { 0, 0, 0, 0, 0, 0 };
322 u32 out[HCI_WORDS];
323 acpi_status status;
324
325 /* First request : initialize communication. */
326 in[0] = 0xf100;
327 status = hci_raw(in, out);
328 if (ACPI_FAILURE(status)) {
329 printk(MY_INFO "Illumination device not available\n");
330 return;
331 }
332
333 if (brightness) {
334 /* Switch the illumination on */
335 in[0] = 0xf400;
336 in[1] = 0x14e;
337 in[2] = 1;
338 status = hci_raw(in, out);
339 if (ACPI_FAILURE(status)) {
340 printk(MY_INFO "ACPI call for illumination failed.\n");
341 return;
342 }
343 } else {
344 /* Switch the illumination off */
345 in[0] = 0xf400;
346 in[1] = 0x14e;
347 in[2] = 0;
348 status = hci_raw(in, out);
349 if (ACPI_FAILURE(status)) {
350 printk(MY_INFO "ACPI call for illumination failed.\n");
351 return;
352 }
353 }
354
355 /* Last request : close communication. */
356 in[0] = 0xf200;
357 in[1] = 0;
358 in[2] = 0;
359 hci_raw(in, out);
360}
361
362static enum led_brightness toshiba_illumination_get(struct led_classdev *cdev)
363{
364 u32 in[HCI_WORDS] = { 0, 0, 0, 0, 0, 0 };
365 u32 out[HCI_WORDS];
366 acpi_status status;
367 enum led_brightness result;
368
369 /* First request : initialize communication. */
370 in[0] = 0xf100;
371 status = hci_raw(in, out);
372 if (ACPI_FAILURE(status)) {
373 printk(MY_INFO "Illumination device not available\n");
374 return LED_OFF;
375 }
376
377 /* Check the illumination */
378 in[0] = 0xf300;
379 in[1] = 0x14e;
380 status = hci_raw(in, out);
381 if (ACPI_FAILURE(status)) {
382 printk(MY_INFO "ACPI call for illumination failed.\n");
383 return LED_OFF;
384 }
385
386 result = out[2] ? LED_FULL : LED_OFF;
387
388 /* Last request : close communication. */
389 in[0] = 0xf200;
390 in[1] = 0;
391 in[2] = 0;
392 hci_raw(in, out);
393
394 return result;
395}
396
397static struct led_classdev toshiba_led = {
398 .name = "toshiba::illumination",
399 .max_brightness = 1,
400 .brightness_set = toshiba_illumination_set,
401 .brightness_get = toshiba_illumination_get,
402};
403
297static struct toshiba_acpi_dev toshiba_acpi = { 404static struct toshiba_acpi_dev toshiba_acpi = {
298 .bt_name = "Toshiba Bluetooth", 405 .bt_name = "Toshiba Bluetooth",
299}; 406};
@@ -913,6 +1020,9 @@ static void toshiba_acpi_exit(void)
913 acpi_remove_notify_handler(toshiba_acpi.handle, ACPI_DEVICE_NOTIFY, 1020 acpi_remove_notify_handler(toshiba_acpi.handle, ACPI_DEVICE_NOTIFY,
914 toshiba_acpi_notify); 1021 toshiba_acpi_notify);
915 1022
1023 if (toshiba_acpi.illumination_installed)
1024 led_classdev_unregister(&toshiba_led);
1025
916 platform_device_unregister(toshiba_acpi.p_dev); 1026 platform_device_unregister(toshiba_acpi.p_dev);
917 1027
918 return; 1028 return;
@@ -1007,6 +1117,13 @@ static int __init toshiba_acpi_init(void)
1007 } 1117 }
1008 } 1118 }
1009 1119
1120 toshiba_acpi.illumination_installed = 0;
1121 if (toshiba_illumination_available()) {
1122 if (!led_classdev_register(&(toshiba_acpi.p_dev->dev),
1123 &toshiba_led))
1124 toshiba_acpi.illumination_installed = 1;
1125 }
1126
1010 return 0; 1127 return 0;
1011} 1128}
1012 1129