summaryrefslogtreecommitdiff
blob: 860f9d43d7c03f4854f64cd17768786ac2502e0e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
[PATCH] applesmc case led and SCSI LED activity trigger

From: René Rebe <rene@exactcode.de>


---

 drivers/hwmon/applesmc.c |   70 ++++++++++++++++++++++++++++++++++++++++------
 1 files changed, 61 insertions(+), 9 deletions(-)

diff --git a/drivers/hwmon/applesmc.c b/drivers/hwmon/applesmc.c
index 86c66c3..377c96d 100644
--- a/drivers/hwmon/applesmc.c
+++ b/drivers/hwmon/applesmc.c
@@ -63,6 +63,8 @@
 
 #define CLAMSHELL_KEY		"MSLD" /* r-o ui8 (unused) */
 
+#define LED_KEY			"LSLF" /* r-w ui16 */
+
 #define MOTION_SENSOR_X_KEY	"MO_X" /* r-o sp78 (2 bytes) */
 #define MOTION_SENSOR_Y_KEY	"MO_Y" /* r-o sp78 (2 bytes) */
 #define MOTION_SENSOR_Z_KEY	"MO_Z" /* r-o sp78 (2 bytes) */
@@ -151,7 +153,7 @@ static DEFINE_MUTEX(applesmc_lock);
  */
 static unsigned int key_at_index;
 
-static struct workqueue_struct *applesmc_led_wq;
+static struct workqueue_struct *applesmc_led_wq, *applesmc_backlight_wq;
 
 /*
  * __wait_status - Wait up to 2ms for the status port to get a certain value
@@ -742,13 +744,40 @@ static void applesmc_backlight_set(struct work_struct *work)
 }
 static DECLARE_WORK(backlight_work, &applesmc_backlight_set);
 
-static void applesmc_brightness_set(struct led_classdev *led_cdev,
-						enum led_brightness value)
+static void applesmc_backlight_brightness_set(struct led_classdev *led_cdev,
+					      enum led_brightness value)
 {
 	int ret;
 
 	backlight_value = value;
-	ret = queue_work(applesmc_led_wq, &backlight_work);
+	ret = queue_work(applesmc_backlight_wq, &backlight_work);
+
+	if (debug && (!ret))
+		printk(KERN_DEBUG "applesmc: work was already on the queue.\n");
+}
+
+/* Store the next LED value to be written by the work */
+static unsigned int led_value;
+
+static void applesmc_led_set(struct work_struct *work)
+{
+	u8 buffer[2];
+
+	mutex_lock(&applesmc_lock);
+	buffer[0] = led_value;
+	buffer[1] = 0x00;
+	applesmc_write_key(LED_KEY, buffer, 2);
+	mutex_unlock(&applesmc_lock);
+}
+static DECLARE_WORK(led_work, &applesmc_led_set);
+
+static void applesmc_led_brightness_set(struct led_classdev *led_cdev,
+					 enum led_brightness value)
+{
+	int ret;
+
+	led_value = value;
+	ret = queue_work(applesmc_led_wq, &led_work);
 
 	if (debug && (!ret))
 		printk(KERN_DEBUG "applesmc: work was already on the queue.\n");
@@ -904,10 +933,16 @@ static ssize_t applesmc_key_at_index_store(struct device *dev,
 	return count;
 }
 
+static struct led_classdev applesmc_led = {
+	.name			= "smc:case-led",
+	.default_trigger	= "ide-disk",
+	.brightness_set		= applesmc_led_brightness_set,
+};
+
 static struct led_classdev applesmc_backlight = {
 	.name			= "smc:kbd_backlight",
 	.default_trigger	= "nand-disk",
-	.brightness_set		= applesmc_brightness_set,
+	.brightness_set		= applesmc_backlight_brightness_set,
 };
 
 static DEVICE_ATTR(name, 0444, applesmc_name_show, NULL);
@@ -1340,15 +1375,28 @@ static int __init applesmc_init(void)
 			goto out_temperature;
 	}
 
+        /* Create the workqueue */
+        applesmc_led_wq = create_singlethread_workqueue("applesmc-led");
+        if (!applesmc_led_wq) {
+                ret = -ENOMEM;
+                goto out_accelerometer;
+        }
+
+        /* register as a led device */
+        ret = led_classdev_register(&pdev->dev, &applesmc_led);
+        if (ret < 0)
+                goto out_led_wq;
+
+
 	if (applesmc_light) {
 		/* Add light sensor file */
 		ret = sysfs_create_file(&pdev->dev.kobj, &dev_attr_light.attr);
 		if (ret)
-			goto out_accelerometer;
+			goto out_led_ledclass;
 
 		/* Create the workqueue */
-		applesmc_led_wq = create_singlethread_workqueue("applesmc-led");
-		if (!applesmc_led_wq) {
+		applesmc_backlight_wq = create_singlethread_workqueue("applesmc-backlight");
+		if (!applesmc_backlight_wq) {
 			ret = -ENOMEM;
 			goto out_light_sysfs;
 		}
@@ -1374,10 +1422,14 @@ out_light_ledclass:
 		led_classdev_unregister(&applesmc_backlight);
 out_light_wq:
 	if (applesmc_light)
-		destroy_workqueue(applesmc_led_wq);
+		destroy_workqueue(applesmc_backlight_wq);
 out_light_sysfs:
 	if (applesmc_light)
 		sysfs_remove_file(&pdev->dev.kobj, &dev_attr_light.attr);
+out_led_ledclass:
+        led_classdev_unregister(&applesmc_led);
+out_led_wq:
+        destroy_workqueue(applesmc_led_wq);
 out_accelerometer:
 	if (applesmc_accelerometer)
 		applesmc_release_accelerometer();