leds: Add driver for HP harddisk protection LEDs

HP notebooks contain accelerometer-based disk protection subsystem,
and LED that indicates hard disk is protected. This is driver for the
LED part.

Signed-off-by: Pavel Machek <pavel@suse.cz>
Signed-off-by: Richard Purdie <rpurdie@linux.intel.com>

authored by Pavel Machek and committed by Richard Purdie 9c78ff6e 0adaf6e4

+164
+7
drivers/leds/Kconfig
··· 113 113 outputs. To be useful the particular board must have LEDs 114 114 and they must be connected to the GPIO lines. 115 115 116 + config LEDS_HP_DISK 117 + tristate "LED Support for disk protection LED on HP notebooks" 118 + depends on LEDS_CLASS && ACPI 119 + help 120 + This option enable support for disk protection LED, found on 121 + newer HP notebooks. 122 + 116 123 config LEDS_CLEVO_MAIL 117 124 tristate "Mail LED on Clevo notebook (EXPERIMENTAL)" 118 125 depends on LEDS_CLASS && X86 && SERIO_I8042 && DMI && EXPERIMENTAL
+1
drivers/leds/Makefile
··· 22 22 obj-$(CONFIG_LEDS_FSG) += leds-fsg.o 23 23 obj-$(CONFIG_LEDS_PCA955X) += leds-pca955x.o 24 24 obj-$(CONFIG_LEDS_DA903X) += leds-da903x.o 25 + obj-$(CONFIG_LEDS_HP_DISK) += leds-hp-disk.o 25 26 26 27 # LED Triggers 27 28 obj-$(CONFIG_LEDS_TRIGGER_TIMER) += ledtrig-timer.o
+156
drivers/leds/leds-hp-disk.c
··· 1 + /* 2 + * leds-hp-disk.c - driver for HP "hard disk protection" LED 3 + * 4 + * Copyright (C) 2008 Pavel Machek 5 + * 6 + * This program is free software; you can redistribute it and/or modify 7 + * it under the terms of the GNU General Public License as published by 8 + * the Free Software Foundation; either version 2 of the License, or 9 + * (at your option) any later version. 10 + * 11 + * This program is distributed in the hope that it will be useful, 12 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 + * GNU General Public License for more details. 15 + * 16 + * You should have received a copy of the GNU General Public License 17 + * along with this program; if not, write to the Free Software 18 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 + */ 20 + 21 + #include <linux/kernel.h> 22 + #include <linux/init.h> 23 + #include <linux/dmi.h> 24 + #include <linux/module.h> 25 + #include <linux/types.h> 26 + #include <linux/platform_device.h> 27 + #include <linux/interrupt.h> 28 + #include <linux/input.h> 29 + #include <linux/kthread.h> 30 + #include <linux/version.h> 31 + #include <linux/leds.h> 32 + #include <acpi/acpi_drivers.h> 33 + 34 + #define DRIVER_NAME "leds-hp-disk" 35 + #define ACPI_MDPS_CLASS "led" 36 + 37 + /* For automatic insertion of the module */ 38 + static struct acpi_device_id hpled_device_ids[] = { 39 + {"HPQ0004", 0}, /* HP Mobile Data Protection System PNP */ 40 + {"", 0}, 41 + }; 42 + MODULE_DEVICE_TABLE(acpi, hpled_device_ids); 43 + 44 + struct acpi_hpled { 45 + struct acpi_device *device; /* The ACPI device */ 46 + }; 47 + 48 + static struct acpi_hpled adev; 49 + 50 + static acpi_status hpled_acpi_write(acpi_handle handle, int reg) 51 + { 52 + unsigned long ret; /* Not used when writing */ 53 + union acpi_object in_obj[1]; 54 + struct acpi_object_list args = { 1, in_obj }; 55 + 56 + in_obj[0].type = ACPI_TYPE_INTEGER; 57 + in_obj[0].integer.value = reg; 58 + 59 + return acpi_evaluate_integer(handle, "ALED", &args, &ret); 60 + } 61 + 62 + static void hpled_set(struct led_classdev *led_cdev, 63 + enum led_brightness value) 64 + { 65 + hpled_acpi_write(adev.device->handle, !!value); 66 + } 67 + 68 + static struct led_classdev hpled_led = { 69 + .name = "hp:red:hddprotection", 70 + .default_trigger = "heartbeat", 71 + .brightness_set = hpled_set, 72 + }; 73 + 74 + #ifdef CONFIG_PM 75 + static int hpled_suspend(struct acpi_device *dev, pm_message_t state) 76 + { 77 + led_classdev_suspend(&hpled_led); 78 + return 0; 79 + } 80 + 81 + static int hpled_resume(struct acpi_device *dev) 82 + { 83 + led_classdev_resume(&hpled_led); 84 + return 0; 85 + } 86 + #else 87 + #define hpled_suspend NULL 88 + #define hpled_resume NULL 89 + #endif 90 + 91 + static int hpled_add(struct acpi_device *device) 92 + { 93 + int ret; 94 + 95 + if (!device) 96 + return -EINVAL; 97 + 98 + adev.device = device; 99 + strcpy(acpi_device_name(device), DRIVER_NAME); 100 + strcpy(acpi_device_class(device), ACPI_MDPS_CLASS); 101 + acpi_driver_data(device) = &adev; 102 + 103 + ret = led_classdev_register(NULL, &hpled_led); 104 + return ret; 105 + } 106 + 107 + static int hpled_remove(struct acpi_device *device, int type) 108 + { 109 + if (!device) 110 + return -EINVAL; 111 + 112 + led_classdev_unregister(&hpled_led); 113 + return 0; 114 + } 115 + 116 + 117 + 118 + static struct acpi_driver leds_hp_driver = { 119 + .name = DRIVER_NAME, 120 + .class = ACPI_MDPS_CLASS, 121 + .ids = hpled_device_ids, 122 + .ops = { 123 + .add = hpled_add, 124 + .remove = hpled_remove, 125 + .suspend = hpled_suspend, 126 + .resume = hpled_resume, 127 + } 128 + }; 129 + 130 + static int __init hpled_init_module(void) 131 + { 132 + int ret; 133 + 134 + if (acpi_disabled) 135 + return -ENODEV; 136 + 137 + ret = acpi_bus_register_driver(&leds_hp_driver); 138 + if (ret < 0) 139 + return ret; 140 + 141 + printk(KERN_INFO DRIVER_NAME " driver loaded.\n"); 142 + 143 + return 0; 144 + } 145 + 146 + static void __exit hpled_exit_module(void) 147 + { 148 + acpi_bus_unregister_driver(&leds_hp_driver); 149 + } 150 + 151 + MODULE_DESCRIPTION("Driver for HP disk protection LED"); 152 + MODULE_AUTHOR("Pavel Machek <pavel@suse.cz>"); 153 + MODULE_LICENSE("GPL"); 154 + 155 + module_init(hpled_init_module); 156 + module_exit(hpled_exit_module);