Merge branch 'fix/asoc' into for-linus
[linux-2.6-block.git] / drivers / hwmon / applesmc.c
CommitLineData
6f2fad74
NB
1/*
2 * drivers/hwmon/applesmc.c - driver for Apple's SMC (accelerometer, temperature
3 * sensors, fan control, keyboard backlight control) used in Intel-based Apple
4 * computers.
5 *
6 * Copyright (C) 2007 Nicolas Boichat <nicolas@boichat.ch>
7 *
8 * Based on hdaps.c driver:
9 * Copyright (C) 2005 Robert Love <rml@novell.com>
10 * Copyright (C) 2005 Jesper Juhl <jesper.juhl@gmail.com>
11 *
12 * Fan control based on smcFanControl:
13 * Copyright (C) 2006 Hendrik Holtmann <holtmann@mac.com>
14 *
15 * This program is free software; you can redistribute it and/or modify it
16 * under the terms of the GNU General Public License v2 as published by the
17 * Free Software Foundation.
18 *
19 * This program is distributed in the hope that it will be useful, but WITHOUT
20 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
22 * more details.
23 *
24 * You should have received a copy of the GNU General Public License along with
25 * this program; if not, write to the Free Software Foundation, Inc.,
26 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
27 */
28
29#include <linux/delay.h>
30#include <linux/platform_device.h>
d5cf2b99 31#include <linux/input-polldev.h>
6f2fad74
NB
32#include <linux/kernel.h>
33#include <linux/module.h>
34#include <linux/timer.h>
35#include <linux/dmi.h>
36#include <linux/mutex.h>
37#include <linux/hwmon-sysfs.h>
38#include <asm/io.h>
39#include <linux/leds.h>
40#include <linux/hwmon.h>
41#include <linux/workqueue.h>
42
43/* data port used by Apple SMC */
44#define APPLESMC_DATA_PORT 0x300
45/* command/status port used by Apple SMC */
46#define APPLESMC_CMD_PORT 0x304
47
48#define APPLESMC_NR_PORTS 32 /* 0x300-0x31f */
49
50#define APPLESMC_MAX_DATA_LENGTH 32
51
8c9398d1
HR
52#define APPLESMC_MIN_WAIT 0x0040
53#define APPLESMC_MAX_WAIT 0x8000
54
6f2fad74
NB
55#define APPLESMC_STATUS_MASK 0x0f
56#define APPLESMC_READ_CMD 0x10
57#define APPLESMC_WRITE_CMD 0x11
58#define APPLESMC_GET_KEY_BY_INDEX_CMD 0x12
59#define APPLESMC_GET_KEY_TYPE_CMD 0x13
60
61#define KEY_COUNT_KEY "#KEY" /* r-o ui32 */
62
8bd1a12a
HR
63#define LIGHT_SENSOR_LEFT_KEY "ALV0" /* r-o {alv (6-10 bytes) */
64#define LIGHT_SENSOR_RIGHT_KEY "ALV1" /* r-o {alv (6-10 bytes) */
d5cf2b99 65#define BACKLIGHT_KEY "LKSB" /* w-o {lkb (2 bytes) */
6f2fad74 66
d5cf2b99 67#define CLAMSHELL_KEY "MSLD" /* r-o ui8 (unused) */
6f2fad74
NB
68
69#define MOTION_SENSOR_X_KEY "MO_X" /* r-o sp78 (2 bytes) */
70#define MOTION_SENSOR_Y_KEY "MO_Y" /* r-o sp78 (2 bytes) */
71#define MOTION_SENSOR_Z_KEY "MO_Z" /* r-o sp78 (2 bytes) */
72#define MOTION_SENSOR_KEY "MOCN" /* r/w ui16 */
73
74#define FANS_COUNT "FNum" /* r-o ui8 */
75#define FANS_MANUAL "FS! " /* r-w ui16 */
76#define FAN_ACTUAL_SPEED "F0Ac" /* r-o fpe2 (2 bytes) */
77#define FAN_MIN_SPEED "F0Mn" /* r-o fpe2 (2 bytes) */
78#define FAN_MAX_SPEED "F0Mx" /* r-o fpe2 (2 bytes) */
79#define FAN_SAFE_SPEED "F0Sf" /* r-o fpe2 (2 bytes) */
80#define FAN_TARGET_SPEED "F0Tg" /* r-w fpe2 (2 bytes) */
81#define FAN_POSITION "F0ID" /* r-o char[16] */
82
83/*
84 * Temperature sensors keys (sp78 - 2 bytes).
6f2fad74 85 */
8de57709 86static const char* temperature_sensors_sets[][36] = {
1bed24b9 87/* Set 0: Macbook Pro */
6f2fad74
NB
88 { "TA0P", "TB0T", "TC0D", "TC0P", "TG0H", "TG0P", "TG0T", "Th0H",
89 "Th1H", "Tm0P", "Ts0P", "Ts1P", NULL },
cd19ba13
RO
90/* Set 1: Macbook2 set */
91 { "TB0T", "TC0D", "TC0P", "TM0P", "TN0P", "TN1P", "TTF0", "Th0H",
92 "Th0S", "Th1H", NULL },
93/* Set 2: Macbook set */
1bed24b9
MS
94 { "TB0T", "TC0D", "TC0P", "TM0P", "TN0P", "TN1P", "Th0H", "Th0S",
95 "Th1H", "Ts0P", NULL },
cd19ba13 96/* Set 3: Macmini set */
8de57709 97 { "TC0D", "TC0P", NULL },
cd19ba13 98/* Set 4: Mac Pro (2 x Quad-Core) */
8de57709
RR
99 { "TA0P", "TCAG", "TCAH", "TCBG", "TCBH", "TC0C", "TC0D", "TC0P",
100 "TC1C", "TC1D", "TC2C", "TC2D", "TC3C", "TC3D", "THTG", "TH0P",
101 "TH1P", "TH2P", "TH3P", "TMAP", "TMAS", "TMBS", "TM0P", "TM0S",
102 "TM1P", "TM1S", "TM2P", "TM2S", "TM3S", "TM8P", "TM8S", "TM9P",
103 "TM9S", "TN0H", "TS0C", NULL },
9f86f28d
RDI
104/* Set 5: iMac */
105 { "TC0D", "TA0P", "TG0P", "TG0D", "TG0H", "TH0P", "Tm0P", "TO0P",
106 "Tp0C", NULL },
f91a79fe
GS
107/* Set 6: Macbook3 set */
108 { "TB0T", "TC0D", "TC0P", "TM0P", "TN0P", "TTF0", "TW0P", "Th0H",
109 "Th0S", "Th1H", NULL },
f5274c97
HR
110/* Set 7: Macbook Air */
111 { "TB0T", "TB1S", "TB1T", "TB2S", "TB2T", "TC0D", "TC0P", "TCFP",
112 "TTF0", "TW0P", "Th0H", "Tp0P", "TpFP", "Ts0P", "Ts0S", NULL },
d7549905
HR
113/* Set 8: Macbook Pro 4,1 (Penryn) */
114 { "TB0T", "TC0D", "TC0P", "TG0D", "TG0H", "TTF0", "TW0P", "Th0H",
115 "Th1H", "Th2H", "Tm0P", "Ts0P", NULL },
07e8dbd3
HR
116/* Set 9: Macbook Pro 3,1 (Santa Rosa) */
117 { "TALP", "TB0T", "TC0D", "TC0P", "TG0D", "TG0H", "TTF0", "TW0P",
118 "Th0H", "Th1H", "Th2H", "Tm0P", "Ts0P", NULL },
6e3530fa
HR
119/* Set 10: iMac 5,1 */
120 { "TA0P", "TC0D", "TC0P", "TG0D", "TH0P", "TO0P", "Tm0P", NULL },
181209a1
HR
121/* Set 11: Macbook 5,1 */
122 { "TB0T", "TB1T", "TB2T", "TB3T", "TC0D", "TC0P", "TN0D", "TN0P",
123 "TTF0", "Th0H", "Th1H", "ThFH", "Ts0P", "Ts0S", NULL },
a6660325
HR
124/* Set 12: Macbook Pro 5,1 */
125 { "TB0T", "TB1T", "TB2T", "TB3T", "TC0D", "TC0F", "TC0P", "TG0D",
126 "TG0F", "TG0H", "TG0P", "TG0T", "TG1H", "TN0D", "TN0P", "TTF0",
127 "Th2H", "Tm0P", "Ts0P", "Ts0S", NULL },
eefc488f
HR
128/* Set 13: iMac 8,1 */
129 { "TA0P", "TC0D", "TC0H", "TC0P", "TG0D", "TG0H", "TG0P", "TH0P",
130 "TL0P", "TO0P", "TW0P", "Tm0P", "Tp0P", NULL },
9ca791bb
HR
131/* Set 14: iMac 6,1 */
132 { "TA0P", "TC0D", "TC0H", "TC0P", "TG0D", "TG0H", "TG0P", "TH0P",
133 "TO0P", "Tp0P", NULL },
85e0e5ad
HR
134/* Set 15: MacBook Air 2,1 */
135 { "TB0T", "TB1S", "TB1T", "TB2S", "TB2T", "TC0D", "TN0D", "TTF0",
136 "TV0P", "TVFP", "TW0P", "Th0P", "Tp0P", "Tp1P", "TpFP", "Ts0P",
137 "Ts0S", NULL },
6f2fad74
NB
138};
139
140/* List of keys used to read/write fan speeds */
141static const char* fan_speed_keys[] = {
142 FAN_ACTUAL_SPEED,
143 FAN_MIN_SPEED,
144 FAN_MAX_SPEED,
145 FAN_SAFE_SPEED,
146 FAN_TARGET_SPEED
147};
148
149#define INIT_TIMEOUT_MSECS 5000 /* wait up to 5s for device init ... */
150#define INIT_WAIT_MSECS 50 /* ... in 50ms increments */
151
d5cf2b99 152#define APPLESMC_POLL_INTERVAL 50 /* msecs */
6f2fad74
NB
153#define APPLESMC_INPUT_FUZZ 4 /* input event threshold */
154#define APPLESMC_INPUT_FLAT 4
155
156#define SENSOR_X 0
157#define SENSOR_Y 1
158#define SENSOR_Z 2
159
160/* Structure to be passed to DMI_MATCH function */
161struct dmi_match_data {
162/* Indicates whether this computer has an accelerometer. */
163 int accelerometer;
164/* Indicates whether this computer has light sensors and keyboard backlight. */
165 int light;
166/* Indicates which temperature sensors set to use. */
167 int temperature_set;
168};
169
170static const int debug;
171static struct platform_device *pdev;
172static s16 rest_x;
173static s16 rest_y;
1beeffe4 174static struct device *hwmon_dev;
d5cf2b99 175static struct input_polled_dev *applesmc_idev;
6f2fad74
NB
176
177/* Indicates whether this computer has an accelerometer. */
178static unsigned int applesmc_accelerometer;
179
180/* Indicates whether this computer has light sensors and keyboard backlight. */
181static unsigned int applesmc_light;
182
183/* Indicates which temperature sensors set to use. */
184static unsigned int applesmc_temperature_set;
185
d5cf2b99 186static DEFINE_MUTEX(applesmc_lock);
6f2fad74
NB
187
188/*
189 * Last index written to key_at_index sysfs file, and value to use for all other
190 * key_at_index_* sysfs files.
191 */
192static unsigned int key_at_index;
193
194static struct workqueue_struct *applesmc_led_wq;
195
196/*
8c9398d1 197 * __wait_status - Wait up to 32ms for the status port to get a certain value
6f2fad74
NB
198 * (masked with 0x0f), returning zero if the value is obtained. Callers must
199 * hold applesmc_lock.
200 */
201static int __wait_status(u8 val)
202{
8c9398d1 203 int us;
6f2fad74
NB
204
205 val = val & APPLESMC_STATUS_MASK;
206
8c9398d1
HR
207 for (us = APPLESMC_MIN_WAIT; us < APPLESMC_MAX_WAIT; us <<= 1) {
208 udelay(us);
6f2fad74
NB
209 if ((inb(APPLESMC_CMD_PORT) & APPLESMC_STATUS_MASK) == val) {
210 if (debug)
211 printk(KERN_DEBUG
8c9398d1
HR
212 "Waited %d us for status %x\n",
213 2 * us - APPLESMC_MIN_WAIT, val);
6f2fad74
NB
214 return 0;
215 }
6f2fad74
NB
216 }
217
218 printk(KERN_WARNING "applesmc: wait status failed: %x != %x\n",
219 val, inb(APPLESMC_CMD_PORT));
220
221 return -EIO;
222}
223
84d2d7f2
HR
224/*
225 * special treatment of command port - on newer macbooks, it seems necessary
226 * to resend the command byte before polling the status again. Callers must
227 * hold applesmc_lock.
228 */
229static int send_command(u8 cmd)
230{
8c9398d1
HR
231 int us;
232 for (us = APPLESMC_MIN_WAIT; us < APPLESMC_MAX_WAIT; us <<= 1) {
84d2d7f2 233 outb(cmd, APPLESMC_CMD_PORT);
8c9398d1 234 udelay(us);
84d2d7f2
HR
235 if ((inb(APPLESMC_CMD_PORT) & APPLESMC_STATUS_MASK) == 0x0c)
236 return 0;
84d2d7f2
HR
237 }
238 printk(KERN_WARNING "applesmc: command failed: %x -> %x\n",
239 cmd, inb(APPLESMC_CMD_PORT));
240 return -EIO;
241}
242
6f2fad74
NB
243/*
244 * applesmc_read_key - reads len bytes from a given key, and put them in buffer.
245 * Returns zero on success or a negative error on failure. Callers must
246 * hold applesmc_lock.
247 */
248static int applesmc_read_key(const char* key, u8* buffer, u8 len)
249{
250 int i;
251
252 if (len > APPLESMC_MAX_DATA_LENGTH) {
253 printk(KERN_ERR "applesmc_read_key: cannot read more than "
254 "%d bytes\n", APPLESMC_MAX_DATA_LENGTH);
255 return -EINVAL;
256 }
257
84d2d7f2 258 if (send_command(APPLESMC_READ_CMD))
6f2fad74
NB
259 return -EIO;
260
261 for (i = 0; i < 4; i++) {
262 outb(key[i], APPLESMC_DATA_PORT);
263 if (__wait_status(0x04))
264 return -EIO;
265 }
266 if (debug)
267 printk(KERN_DEBUG "<%s", key);
268
269 outb(len, APPLESMC_DATA_PORT);
270 if (debug)
271 printk(KERN_DEBUG ">%x", len);
272
273 for (i = 0; i < len; i++) {
274 if (__wait_status(0x05))
275 return -EIO;
276 buffer[i] = inb(APPLESMC_DATA_PORT);
277 if (debug)
278 printk(KERN_DEBUG "<%x", buffer[i]);
279 }
280 if (debug)
281 printk(KERN_DEBUG "\n");
282
283 return 0;
284}
285
286/*
287 * applesmc_write_key - writes len bytes from buffer to a given key.
288 * Returns zero on success or a negative error on failure. Callers must
289 * hold applesmc_lock.
290 */
291static int applesmc_write_key(const char* key, u8* buffer, u8 len)
292{
293 int i;
294
295 if (len > APPLESMC_MAX_DATA_LENGTH) {
296 printk(KERN_ERR "applesmc_write_key: cannot write more than "
297 "%d bytes\n", APPLESMC_MAX_DATA_LENGTH);
298 return -EINVAL;
299 }
300
84d2d7f2 301 if (send_command(APPLESMC_WRITE_CMD))
6f2fad74
NB
302 return -EIO;
303
304 for (i = 0; i < 4; i++) {
305 outb(key[i], APPLESMC_DATA_PORT);
306 if (__wait_status(0x04))
307 return -EIO;
308 }
309
310 outb(len, APPLESMC_DATA_PORT);
311
312 for (i = 0; i < len; i++) {
313 if (__wait_status(0x04))
314 return -EIO;
315 outb(buffer[i], APPLESMC_DATA_PORT);
316 }
317
318 return 0;
319}
320
321/*
322 * applesmc_get_key_at_index - get key at index, and put the result in key
323 * (char[6]). Returns zero on success or a negative error on failure. Callers
324 * must hold applesmc_lock.
325 */
326static int applesmc_get_key_at_index(int index, char* key)
327{
328 int i;
329 u8 readkey[4];
330 readkey[0] = index >> 24;
331 readkey[1] = index >> 16;
332 readkey[2] = index >> 8;
333 readkey[3] = index;
334
84d2d7f2 335 if (send_command(APPLESMC_GET_KEY_BY_INDEX_CMD))
6f2fad74
NB
336 return -EIO;
337
338 for (i = 0; i < 4; i++) {
339 outb(readkey[i], APPLESMC_DATA_PORT);
340 if (__wait_status(0x04))
341 return -EIO;
342 }
343
344 outb(4, APPLESMC_DATA_PORT);
345
346 for (i = 0; i < 4; i++) {
347 if (__wait_status(0x05))
348 return -EIO;
349 key[i] = inb(APPLESMC_DATA_PORT);
350 }
351 key[4] = 0;
352
353 return 0;
354}
355
356/*
357 * applesmc_get_key_type - get key type, and put the result in type (char[6]).
358 * Returns zero on success or a negative error on failure. Callers must
359 * hold applesmc_lock.
360 */
361static int applesmc_get_key_type(char* key, char* type)
362{
363 int i;
364
84d2d7f2 365 if (send_command(APPLESMC_GET_KEY_TYPE_CMD))
6f2fad74
NB
366 return -EIO;
367
368 for (i = 0; i < 4; i++) {
369 outb(key[i], APPLESMC_DATA_PORT);
370 if (__wait_status(0x04))
371 return -EIO;
372 }
373
05224091 374 outb(6, APPLESMC_DATA_PORT);
6f2fad74
NB
375
376 for (i = 0; i < 6; i++) {
377 if (__wait_status(0x05))
378 return -EIO;
379 type[i] = inb(APPLESMC_DATA_PORT);
380 }
381 type[5] = 0;
382
383 return 0;
384}
385
386/*
387 * applesmc_read_motion_sensor - Read motion sensor (X, Y or Z). Callers must
388 * hold applesmc_lock.
389 */
390static int applesmc_read_motion_sensor(int index, s16* value)
391{
392 u8 buffer[2];
393 int ret;
394
395 switch (index) {
396 case SENSOR_X:
397 ret = applesmc_read_key(MOTION_SENSOR_X_KEY, buffer, 2);
398 break;
399 case SENSOR_Y:
400 ret = applesmc_read_key(MOTION_SENSOR_Y_KEY, buffer, 2);
401 break;
402 case SENSOR_Z:
403 ret = applesmc_read_key(MOTION_SENSOR_Z_KEY, buffer, 2);
404 break;
405 default:
406 ret = -EINVAL;
407 }
408
409 *value = ((s16)buffer[0] << 8) | buffer[1];
410
411 return ret;
412}
413
414/*
415 * applesmc_device_init - initialize the accelerometer. Returns zero on success
416 * and negative error code on failure. Can sleep.
417 */
418static int applesmc_device_init(void)
419{
420 int total, ret = -ENXIO;
421 u8 buffer[2];
422
423 if (!applesmc_accelerometer)
424 return 0;
425
426 mutex_lock(&applesmc_lock);
427
428 for (total = INIT_TIMEOUT_MSECS; total > 0; total -= INIT_WAIT_MSECS) {
429 if (debug)
430 printk(KERN_DEBUG "applesmc try %d\n", total);
431 if (!applesmc_read_key(MOTION_SENSOR_KEY, buffer, 2) &&
432 (buffer[0] != 0x00 || buffer[1] != 0x00)) {
433 if (total == INIT_TIMEOUT_MSECS) {
434 printk(KERN_DEBUG "applesmc: device has"
435 " already been initialized"
436 " (0x%02x, 0x%02x).\n",
437 buffer[0], buffer[1]);
438 } else {
439 printk(KERN_DEBUG "applesmc: device"
440 " successfully initialized"
441 " (0x%02x, 0x%02x).\n",
442 buffer[0], buffer[1]);
443 }
444 ret = 0;
445 goto out;
446 }
447 buffer[0] = 0xe0;
448 buffer[1] = 0x00;
449 applesmc_write_key(MOTION_SENSOR_KEY, buffer, 2);
450 msleep(INIT_WAIT_MSECS);
451 }
452
453 printk(KERN_WARNING "applesmc: failed to init the device\n");
454
455out:
456 mutex_unlock(&applesmc_lock);
457 return ret;
458}
459
460/*
461 * applesmc_get_fan_count - get the number of fans. Callers must NOT hold
462 * applesmc_lock.
463 */
464static int applesmc_get_fan_count(void)
465{
466 int ret;
467 u8 buffer[1];
468
469 mutex_lock(&applesmc_lock);
470
471 ret = applesmc_read_key(FANS_COUNT, buffer, 1);
472
473 mutex_unlock(&applesmc_lock);
474 if (ret)
475 return ret;
476 else
477 return buffer[0];
478}
479
480/* Device model stuff */
481static int applesmc_probe(struct platform_device *dev)
482{
483 int ret;
484
485 ret = applesmc_device_init();
486 if (ret)
487 return ret;
488
489 printk(KERN_INFO "applesmc: device successfully initialized.\n");
490 return 0;
491}
492
493static int applesmc_resume(struct platform_device *dev)
494{
495 return applesmc_device_init();
496}
497
498static struct platform_driver applesmc_driver = {
499 .probe = applesmc_probe,
500 .resume = applesmc_resume,
501 .driver = {
502 .name = "applesmc",
503 .owner = THIS_MODULE,
504 },
505};
506
507/*
508 * applesmc_calibrate - Set our "resting" values. Callers must
509 * hold applesmc_lock.
510 */
511static void applesmc_calibrate(void)
512{
513 applesmc_read_motion_sensor(SENSOR_X, &rest_x);
514 applesmc_read_motion_sensor(SENSOR_Y, &rest_y);
515 rest_x = -rest_x;
516}
517
d5cf2b99 518static void applesmc_idev_poll(struct input_polled_dev *dev)
6f2fad74 519{
d5cf2b99 520 struct input_dev *idev = dev->input;
6f2fad74
NB
521 s16 x, y;
522
d5cf2b99 523 mutex_lock(&applesmc_lock);
6f2fad74
NB
524
525 if (applesmc_read_motion_sensor(SENSOR_X, &x))
526 goto out;
527 if (applesmc_read_motion_sensor(SENSOR_Y, &y))
528 goto out;
529
530 x = -x;
d5cf2b99
DT
531 input_report_abs(idev, ABS_X, x - rest_x);
532 input_report_abs(idev, ABS_Y, y - rest_y);
533 input_sync(idev);
6f2fad74
NB
534
535out:
6f2fad74
NB
536 mutex_unlock(&applesmc_lock);
537}
538
539/* Sysfs Files */
540
fa74419b
NB
541static ssize_t applesmc_name_show(struct device *dev,
542 struct device_attribute *attr, char *buf)
543{
544 return snprintf(buf, PAGE_SIZE, "applesmc\n");
545}
546
6f2fad74
NB
547static ssize_t applesmc_position_show(struct device *dev,
548 struct device_attribute *attr, char *buf)
549{
550 int ret;
551 s16 x, y, z;
552
553 mutex_lock(&applesmc_lock);
554
555 ret = applesmc_read_motion_sensor(SENSOR_X, &x);
556 if (ret)
557 goto out;
558 ret = applesmc_read_motion_sensor(SENSOR_Y, &y);
559 if (ret)
560 goto out;
561 ret = applesmc_read_motion_sensor(SENSOR_Z, &z);
562 if (ret)
563 goto out;
564
565out:
566 mutex_unlock(&applesmc_lock);
567 if (ret)
568 return ret;
569 else
570 return snprintf(buf, PAGE_SIZE, "(%d,%d,%d)\n", x, y, z);
571}
572
573static ssize_t applesmc_light_show(struct device *dev,
574 struct device_attribute *attr, char *sysfsbuf)
575{
8bd1a12a 576 static int data_length;
6f2fad74
NB
577 int ret;
578 u8 left = 0, right = 0;
8bd1a12a 579 u8 buffer[10], query[6];
6f2fad74
NB
580
581 mutex_lock(&applesmc_lock);
582
8bd1a12a
HR
583 if (!data_length) {
584 ret = applesmc_get_key_type(LIGHT_SENSOR_LEFT_KEY, query);
585 if (ret)
586 goto out;
587 data_length = clamp_val(query[0], 0, 10);
588 printk(KERN_INFO "applesmc: light sensor data length set to "
589 "%d\n", data_length);
590 }
591
592 ret = applesmc_read_key(LIGHT_SENSOR_LEFT_KEY, buffer, data_length);
c3d6362b
AM
593 /* newer macbooks report a single 10-bit bigendian value */
594 if (data_length == 10) {
595 left = be16_to_cpu(*(__be16 *)(buffer + 6)) >> 2;
596 goto out;
597 }
6f2fad74
NB
598 left = buffer[2];
599 if (ret)
600 goto out;
8bd1a12a 601 ret = applesmc_read_key(LIGHT_SENSOR_RIGHT_KEY, buffer, data_length);
6f2fad74
NB
602 right = buffer[2];
603
604out:
605 mutex_unlock(&applesmc_lock);
606 if (ret)
607 return ret;
608 else
609 return snprintf(sysfsbuf, PAGE_SIZE, "(%d,%d)\n", left, right);
610}
611
612/* Displays degree Celsius * 1000 */
613static ssize_t applesmc_show_temperature(struct device *dev,
614 struct device_attribute *devattr, char *sysfsbuf)
615{
616 int ret;
617 u8 buffer[2];
618 unsigned int temp;
619 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
620 const char* key =
621 temperature_sensors_sets[applesmc_temperature_set][attr->index];
622
623 mutex_lock(&applesmc_lock);
624
625 ret = applesmc_read_key(key, buffer, 2);
626 temp = buffer[0]*1000;
627 temp += (buffer[1] >> 6) * 250;
628
629 mutex_unlock(&applesmc_lock);
630
631 if (ret)
632 return ret;
633 else
634 return snprintf(sysfsbuf, PAGE_SIZE, "%u\n", temp);
635}
636
637static ssize_t applesmc_show_fan_speed(struct device *dev,
638 struct device_attribute *attr, char *sysfsbuf)
639{
640 int ret;
641 unsigned int speed = 0;
642 char newkey[5];
643 u8 buffer[2];
644 struct sensor_device_attribute_2 *sensor_attr =
645 to_sensor_dev_attr_2(attr);
646
647 newkey[0] = fan_speed_keys[sensor_attr->nr][0];
648 newkey[1] = '0' + sensor_attr->index;
649 newkey[2] = fan_speed_keys[sensor_attr->nr][2];
650 newkey[3] = fan_speed_keys[sensor_attr->nr][3];
651 newkey[4] = 0;
652
653 mutex_lock(&applesmc_lock);
654
655 ret = applesmc_read_key(newkey, buffer, 2);
656 speed = ((buffer[0] << 8 | buffer[1]) >> 2);
657
658 mutex_unlock(&applesmc_lock);
659 if (ret)
660 return ret;
661 else
662 return snprintf(sysfsbuf, PAGE_SIZE, "%u\n", speed);
663}
664
665static ssize_t applesmc_store_fan_speed(struct device *dev,
666 struct device_attribute *attr,
667 const char *sysfsbuf, size_t count)
668{
669 int ret;
670 u32 speed;
671 char newkey[5];
672 u8 buffer[2];
673 struct sensor_device_attribute_2 *sensor_attr =
674 to_sensor_dev_attr_2(attr);
675
676 speed = simple_strtoul(sysfsbuf, NULL, 10);
677
678 if (speed > 0x4000) /* Bigger than a 14-bit value */
679 return -EINVAL;
680
681 newkey[0] = fan_speed_keys[sensor_attr->nr][0];
682 newkey[1] = '0' + sensor_attr->index;
683 newkey[2] = fan_speed_keys[sensor_attr->nr][2];
684 newkey[3] = fan_speed_keys[sensor_attr->nr][3];
685 newkey[4] = 0;
686
687 mutex_lock(&applesmc_lock);
688
689 buffer[0] = (speed >> 6) & 0xff;
690 buffer[1] = (speed << 2) & 0xff;
691 ret = applesmc_write_key(newkey, buffer, 2);
692
693 mutex_unlock(&applesmc_lock);
694 if (ret)
695 return ret;
696 else
697 return count;
698}
699
700static ssize_t applesmc_show_fan_manual(struct device *dev,
701 struct device_attribute *devattr, char *sysfsbuf)
702{
703 int ret;
704 u16 manual = 0;
705 u8 buffer[2];
706 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
707
708 mutex_lock(&applesmc_lock);
709
710 ret = applesmc_read_key(FANS_MANUAL, buffer, 2);
711 manual = ((buffer[0] << 8 | buffer[1]) >> attr->index) & 0x01;
712
713 mutex_unlock(&applesmc_lock);
714 if (ret)
715 return ret;
716 else
717 return snprintf(sysfsbuf, PAGE_SIZE, "%d\n", manual);
718}
719
720static ssize_t applesmc_store_fan_manual(struct device *dev,
721 struct device_attribute *devattr,
722 const char *sysfsbuf, size_t count)
723{
724 int ret;
725 u8 buffer[2];
726 u32 input;
727 u16 val;
728 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
729
730 input = simple_strtoul(sysfsbuf, NULL, 10);
731
732 mutex_lock(&applesmc_lock);
733
734 ret = applesmc_read_key(FANS_MANUAL, buffer, 2);
735 val = (buffer[0] << 8 | buffer[1]);
736 if (ret)
737 goto out;
738
739 if (input)
740 val = val | (0x01 << attr->index);
741 else
742 val = val & ~(0x01 << attr->index);
743
744 buffer[0] = (val >> 8) & 0xFF;
745 buffer[1] = val & 0xFF;
746
747 ret = applesmc_write_key(FANS_MANUAL, buffer, 2);
748
749out:
750 mutex_unlock(&applesmc_lock);
751 if (ret)
752 return ret;
753 else
754 return count;
755}
756
757static ssize_t applesmc_show_fan_position(struct device *dev,
758 struct device_attribute *attr, char *sysfsbuf)
759{
760 int ret;
761 char newkey[5];
762 u8 buffer[17];
763 struct sensor_device_attribute_2 *sensor_attr =
764 to_sensor_dev_attr_2(attr);
765
766 newkey[0] = FAN_POSITION[0];
767 newkey[1] = '0' + sensor_attr->index;
768 newkey[2] = FAN_POSITION[2];
769 newkey[3] = FAN_POSITION[3];
770 newkey[4] = 0;
771
772 mutex_lock(&applesmc_lock);
773
774 ret = applesmc_read_key(newkey, buffer, 16);
775 buffer[16] = 0;
776
777 mutex_unlock(&applesmc_lock);
778 if (ret)
779 return ret;
780 else
781 return snprintf(sysfsbuf, PAGE_SIZE, "%s\n", buffer+4);
782}
783
784static ssize_t applesmc_calibrate_show(struct device *dev,
785 struct device_attribute *attr, char *sysfsbuf)
786{
787 return snprintf(sysfsbuf, PAGE_SIZE, "(%d,%d)\n", rest_x, rest_y);
788}
789
790static ssize_t applesmc_calibrate_store(struct device *dev,
791 struct device_attribute *attr, const char *sysfsbuf, size_t count)
792{
793 mutex_lock(&applesmc_lock);
794 applesmc_calibrate();
795 mutex_unlock(&applesmc_lock);
796
797 return count;
798}
799
800/* Store the next backlight value to be written by the work */
801static unsigned int backlight_value;
802
803static void applesmc_backlight_set(struct work_struct *work)
804{
805 u8 buffer[2];
806
807 mutex_lock(&applesmc_lock);
808 buffer[0] = backlight_value;
809 buffer[1] = 0x00;
810 applesmc_write_key(BACKLIGHT_KEY, buffer, 2);
811 mutex_unlock(&applesmc_lock);
812}
813static DECLARE_WORK(backlight_work, &applesmc_backlight_set);
814
815static void applesmc_brightness_set(struct led_classdev *led_cdev,
816 enum led_brightness value)
817{
818 int ret;
819
820 backlight_value = value;
821 ret = queue_work(applesmc_led_wq, &backlight_work);
822
823 if (debug && (!ret))
824 printk(KERN_DEBUG "applesmc: work was already on the queue.\n");
825}
826
827static ssize_t applesmc_key_count_show(struct device *dev,
828 struct device_attribute *attr, char *sysfsbuf)
829{
830 int ret;
831 u8 buffer[4];
832 u32 count;
833
834 mutex_lock(&applesmc_lock);
835
836 ret = applesmc_read_key(KEY_COUNT_KEY, buffer, 4);
837 count = ((u32)buffer[0]<<24) + ((u32)buffer[1]<<16) +
838 ((u32)buffer[2]<<8) + buffer[3];
839
840 mutex_unlock(&applesmc_lock);
841 if (ret)
842 return ret;
843 else
844 return snprintf(sysfsbuf, PAGE_SIZE, "%d\n", count);
845}
846
847static ssize_t applesmc_key_at_index_read_show(struct device *dev,
848 struct device_attribute *attr, char *sysfsbuf)
849{
850 char key[5];
851 char info[6];
852 int ret;
853
854 mutex_lock(&applesmc_lock);
855
856 ret = applesmc_get_key_at_index(key_at_index, key);
857
858 if (ret || !key[0]) {
859 mutex_unlock(&applesmc_lock);
860
861 return -EINVAL;
862 }
863
864 ret = applesmc_get_key_type(key, info);
865
866 if (ret) {
867 mutex_unlock(&applesmc_lock);
868
869 return ret;
870 }
871
872 /*
873 * info[0] maximum value (APPLESMC_MAX_DATA_LENGTH) is much lower than
874 * PAGE_SIZE, so we don't need any checks before writing to sysfsbuf.
875 */
876 ret = applesmc_read_key(key, sysfsbuf, info[0]);
877
878 mutex_unlock(&applesmc_lock);
879
880 if (!ret) {
881 return info[0];
d5cf2b99 882 } else {
6f2fad74
NB
883 return ret;
884 }
885}
886
887static ssize_t applesmc_key_at_index_data_length_show(struct device *dev,
888 struct device_attribute *attr, char *sysfsbuf)
889{
890 char key[5];
891 char info[6];
892 int ret;
893
894 mutex_lock(&applesmc_lock);
895
896 ret = applesmc_get_key_at_index(key_at_index, key);
897
898 if (ret || !key[0]) {
899 mutex_unlock(&applesmc_lock);
900
901 return -EINVAL;
902 }
903
904 ret = applesmc_get_key_type(key, info);
905
906 mutex_unlock(&applesmc_lock);
907
908 if (!ret)
909 return snprintf(sysfsbuf, PAGE_SIZE, "%d\n", info[0]);
910 else
911 return ret;
912}
913
914static ssize_t applesmc_key_at_index_type_show(struct device *dev,
915 struct device_attribute *attr, char *sysfsbuf)
916{
917 char key[5];
918 char info[6];
919 int ret;
920
921 mutex_lock(&applesmc_lock);
922
923 ret = applesmc_get_key_at_index(key_at_index, key);
924
925 if (ret || !key[0]) {
926 mutex_unlock(&applesmc_lock);
927
928 return -EINVAL;
929 }
930
931 ret = applesmc_get_key_type(key, info);
932
933 mutex_unlock(&applesmc_lock);
934
935 if (!ret)
936 return snprintf(sysfsbuf, PAGE_SIZE, "%s\n", info+1);
937 else
938 return ret;
939}
940
941static ssize_t applesmc_key_at_index_name_show(struct device *dev,
942 struct device_attribute *attr, char *sysfsbuf)
943{
944 char key[5];
945 int ret;
946
947 mutex_lock(&applesmc_lock);
948
949 ret = applesmc_get_key_at_index(key_at_index, key);
950
951 mutex_unlock(&applesmc_lock);
952
953 if (!ret && key[0])
954 return snprintf(sysfsbuf, PAGE_SIZE, "%s\n", key);
955 else
956 return -EINVAL;
957}
958
959static ssize_t applesmc_key_at_index_show(struct device *dev,
960 struct device_attribute *attr, char *sysfsbuf)
961{
962 return snprintf(sysfsbuf, PAGE_SIZE, "%d\n", key_at_index);
963}
964
965static ssize_t applesmc_key_at_index_store(struct device *dev,
966 struct device_attribute *attr, const char *sysfsbuf, size_t count)
967{
968 mutex_lock(&applesmc_lock);
969
970 key_at_index = simple_strtoul(sysfsbuf, NULL, 10);
971
972 mutex_unlock(&applesmc_lock);
973
974 return count;
975}
976
977static struct led_classdev applesmc_backlight = {
6c152bee 978 .name = "smc::kbd_backlight",
6f2fad74
NB
979 .default_trigger = "nand-disk",
980 .brightness_set = applesmc_brightness_set,
981};
982
fa74419b
NB
983static DEVICE_ATTR(name, 0444, applesmc_name_show, NULL);
984
6f2fad74
NB
985static DEVICE_ATTR(position, 0444, applesmc_position_show, NULL);
986static DEVICE_ATTR(calibrate, 0644,
987 applesmc_calibrate_show, applesmc_calibrate_store);
988
989static struct attribute *accelerometer_attributes[] = {
990 &dev_attr_position.attr,
991 &dev_attr_calibrate.attr,
992 NULL
993};
994
995static const struct attribute_group accelerometer_attributes_group =
996 { .attrs = accelerometer_attributes };
997
998static DEVICE_ATTR(light, 0444, applesmc_light_show, NULL);
999
1000static DEVICE_ATTR(key_count, 0444, applesmc_key_count_show, NULL);
1001static DEVICE_ATTR(key_at_index, 0644,
1002 applesmc_key_at_index_show, applesmc_key_at_index_store);
1003static DEVICE_ATTR(key_at_index_name, 0444,
1004 applesmc_key_at_index_name_show, NULL);
1005static DEVICE_ATTR(key_at_index_type, 0444,
1006 applesmc_key_at_index_type_show, NULL);
1007static DEVICE_ATTR(key_at_index_data_length, 0444,
1008 applesmc_key_at_index_data_length_show, NULL);
1009static DEVICE_ATTR(key_at_index_data, 0444,
1010 applesmc_key_at_index_read_show, NULL);
1011
1012static struct attribute *key_enumeration_attributes[] = {
1013 &dev_attr_key_count.attr,
1014 &dev_attr_key_at_index.attr,
1015 &dev_attr_key_at_index_name.attr,
1016 &dev_attr_key_at_index_type.attr,
1017 &dev_attr_key_at_index_data_length.attr,
1018 &dev_attr_key_at_index_data.attr,
1019 NULL
1020};
1021
1022static const struct attribute_group key_enumeration_group =
1023 { .attrs = key_enumeration_attributes };
1024
1025/*
1026 * Macro defining SENSOR_DEVICE_ATTR for a fan sysfs entries.
1027 * - show actual speed
1028 * - show/store minimum speed
1029 * - show maximum speed
1030 * - show safe speed
1031 * - show/store target speed
1032 * - show/store manual mode
1033 */
1034#define sysfs_fan_speeds_offset(offset) \
1035static SENSOR_DEVICE_ATTR_2(fan##offset##_input, S_IRUGO, \
1036 applesmc_show_fan_speed, NULL, 0, offset-1); \
1037\
1038static SENSOR_DEVICE_ATTR_2(fan##offset##_min, S_IRUGO | S_IWUSR, \
1039 applesmc_show_fan_speed, applesmc_store_fan_speed, 1, offset-1); \
1040\
1041static SENSOR_DEVICE_ATTR_2(fan##offset##_max, S_IRUGO, \
1042 applesmc_show_fan_speed, NULL, 2, offset-1); \
1043\
1044static SENSOR_DEVICE_ATTR_2(fan##offset##_safe, S_IRUGO, \
1045 applesmc_show_fan_speed, NULL, 3, offset-1); \
1046\
1047static SENSOR_DEVICE_ATTR_2(fan##offset##_output, S_IRUGO | S_IWUSR, \
1048 applesmc_show_fan_speed, applesmc_store_fan_speed, 4, offset-1); \
1049\
1050static SENSOR_DEVICE_ATTR(fan##offset##_manual, S_IRUGO | S_IWUSR, \
1051 applesmc_show_fan_manual, applesmc_store_fan_manual, offset-1); \
1052\
da4e8ca3 1053static SENSOR_DEVICE_ATTR(fan##offset##_label, S_IRUGO, \
6f2fad74
NB
1054 applesmc_show_fan_position, NULL, offset-1); \
1055\
1056static struct attribute *fan##offset##_attributes[] = { \
1057 &sensor_dev_attr_fan##offset##_input.dev_attr.attr, \
1058 &sensor_dev_attr_fan##offset##_min.dev_attr.attr, \
1059 &sensor_dev_attr_fan##offset##_max.dev_attr.attr, \
1060 &sensor_dev_attr_fan##offset##_safe.dev_attr.attr, \
1061 &sensor_dev_attr_fan##offset##_output.dev_attr.attr, \
1062 &sensor_dev_attr_fan##offset##_manual.dev_attr.attr, \
da4e8ca3 1063 &sensor_dev_attr_fan##offset##_label.dev_attr.attr, \
6f2fad74
NB
1064 NULL \
1065};
1066
1067/*
1068 * Create the needed functions for each fan using the macro defined above
8de57709 1069 * (4 fans are supported)
6f2fad74
NB
1070 */
1071sysfs_fan_speeds_offset(1);
1072sysfs_fan_speeds_offset(2);
8de57709
RR
1073sysfs_fan_speeds_offset(3);
1074sysfs_fan_speeds_offset(4);
6f2fad74
NB
1075
1076static const struct attribute_group fan_attribute_groups[] = {
1077 { .attrs = fan1_attributes },
8de57709
RR
1078 { .attrs = fan2_attributes },
1079 { .attrs = fan3_attributes },
1080 { .attrs = fan4_attributes },
6f2fad74
NB
1081};
1082
1083/*
1084 * Temperature sensors sysfs entries.
1085 */
1086static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO,
1087 applesmc_show_temperature, NULL, 0);
1088static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO,
1089 applesmc_show_temperature, NULL, 1);
1090static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO,
1091 applesmc_show_temperature, NULL, 2);
1092static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO,
1093 applesmc_show_temperature, NULL, 3);
1094static SENSOR_DEVICE_ATTR(temp5_input, S_IRUGO,
1095 applesmc_show_temperature, NULL, 4);
1096static SENSOR_DEVICE_ATTR(temp6_input, S_IRUGO,
1097 applesmc_show_temperature, NULL, 5);
1098static SENSOR_DEVICE_ATTR(temp7_input, S_IRUGO,
1099 applesmc_show_temperature, NULL, 6);
1100static SENSOR_DEVICE_ATTR(temp8_input, S_IRUGO,
1101 applesmc_show_temperature, NULL, 7);
1102static SENSOR_DEVICE_ATTR(temp9_input, S_IRUGO,
1103 applesmc_show_temperature, NULL, 8);
1104static SENSOR_DEVICE_ATTR(temp10_input, S_IRUGO,
1105 applesmc_show_temperature, NULL, 9);
1106static SENSOR_DEVICE_ATTR(temp11_input, S_IRUGO,
1107 applesmc_show_temperature, NULL, 10);
1108static SENSOR_DEVICE_ATTR(temp12_input, S_IRUGO,
1109 applesmc_show_temperature, NULL, 11);
8de57709
RR
1110static SENSOR_DEVICE_ATTR(temp13_input, S_IRUGO,
1111 applesmc_show_temperature, NULL, 12);
1112static SENSOR_DEVICE_ATTR(temp14_input, S_IRUGO,
1113 applesmc_show_temperature, NULL, 13);
1114static SENSOR_DEVICE_ATTR(temp15_input, S_IRUGO,
1115 applesmc_show_temperature, NULL, 14);
1116static SENSOR_DEVICE_ATTR(temp16_input, S_IRUGO,
1117 applesmc_show_temperature, NULL, 15);
1118static SENSOR_DEVICE_ATTR(temp17_input, S_IRUGO,
1119 applesmc_show_temperature, NULL, 16);
1120static SENSOR_DEVICE_ATTR(temp18_input, S_IRUGO,
1121 applesmc_show_temperature, NULL, 17);
1122static SENSOR_DEVICE_ATTR(temp19_input, S_IRUGO,
1123 applesmc_show_temperature, NULL, 18);
1124static SENSOR_DEVICE_ATTR(temp20_input, S_IRUGO,
1125 applesmc_show_temperature, NULL, 19);
1126static SENSOR_DEVICE_ATTR(temp21_input, S_IRUGO,
1127 applesmc_show_temperature, NULL, 20);
1128static SENSOR_DEVICE_ATTR(temp22_input, S_IRUGO,
1129 applesmc_show_temperature, NULL, 21);
1130static SENSOR_DEVICE_ATTR(temp23_input, S_IRUGO,
1131 applesmc_show_temperature, NULL, 22);
1132static SENSOR_DEVICE_ATTR(temp24_input, S_IRUGO,
1133 applesmc_show_temperature, NULL, 23);
1134static SENSOR_DEVICE_ATTR(temp25_input, S_IRUGO,
1135 applesmc_show_temperature, NULL, 24);
1136static SENSOR_DEVICE_ATTR(temp26_input, S_IRUGO,
1137 applesmc_show_temperature, NULL, 25);
1138static SENSOR_DEVICE_ATTR(temp27_input, S_IRUGO,
1139 applesmc_show_temperature, NULL, 26);
1140static SENSOR_DEVICE_ATTR(temp28_input, S_IRUGO,
1141 applesmc_show_temperature, NULL, 27);
1142static SENSOR_DEVICE_ATTR(temp29_input, S_IRUGO,
1143 applesmc_show_temperature, NULL, 28);
1144static SENSOR_DEVICE_ATTR(temp30_input, S_IRUGO,
1145 applesmc_show_temperature, NULL, 29);
1146static SENSOR_DEVICE_ATTR(temp31_input, S_IRUGO,
1147 applesmc_show_temperature, NULL, 30);
1148static SENSOR_DEVICE_ATTR(temp32_input, S_IRUGO,
1149 applesmc_show_temperature, NULL, 31);
1150static SENSOR_DEVICE_ATTR(temp33_input, S_IRUGO,
1151 applesmc_show_temperature, NULL, 32);
1152static SENSOR_DEVICE_ATTR(temp34_input, S_IRUGO,
1153 applesmc_show_temperature, NULL, 33);
1154static SENSOR_DEVICE_ATTR(temp35_input, S_IRUGO,
1155 applesmc_show_temperature, NULL, 34);
6f2fad74
NB
1156
1157static struct attribute *temperature_attributes[] = {
1158 &sensor_dev_attr_temp1_input.dev_attr.attr,
1159 &sensor_dev_attr_temp2_input.dev_attr.attr,
1160 &sensor_dev_attr_temp3_input.dev_attr.attr,
1161 &sensor_dev_attr_temp4_input.dev_attr.attr,
1162 &sensor_dev_attr_temp5_input.dev_attr.attr,
1163 &sensor_dev_attr_temp6_input.dev_attr.attr,
1164 &sensor_dev_attr_temp7_input.dev_attr.attr,
1165 &sensor_dev_attr_temp8_input.dev_attr.attr,
1166 &sensor_dev_attr_temp9_input.dev_attr.attr,
1167 &sensor_dev_attr_temp10_input.dev_attr.attr,
1168 &sensor_dev_attr_temp11_input.dev_attr.attr,
1169 &sensor_dev_attr_temp12_input.dev_attr.attr,
8de57709
RR
1170 &sensor_dev_attr_temp13_input.dev_attr.attr,
1171 &sensor_dev_attr_temp14_input.dev_attr.attr,
1172 &sensor_dev_attr_temp15_input.dev_attr.attr,
1173 &sensor_dev_attr_temp16_input.dev_attr.attr,
1174 &sensor_dev_attr_temp17_input.dev_attr.attr,
1175 &sensor_dev_attr_temp18_input.dev_attr.attr,
1176 &sensor_dev_attr_temp19_input.dev_attr.attr,
1177 &sensor_dev_attr_temp20_input.dev_attr.attr,
1178 &sensor_dev_attr_temp21_input.dev_attr.attr,
1179 &sensor_dev_attr_temp22_input.dev_attr.attr,
1180 &sensor_dev_attr_temp23_input.dev_attr.attr,
1181 &sensor_dev_attr_temp24_input.dev_attr.attr,
1182 &sensor_dev_attr_temp25_input.dev_attr.attr,
1183 &sensor_dev_attr_temp26_input.dev_attr.attr,
1184 &sensor_dev_attr_temp27_input.dev_attr.attr,
1185 &sensor_dev_attr_temp28_input.dev_attr.attr,
1186 &sensor_dev_attr_temp29_input.dev_attr.attr,
1187 &sensor_dev_attr_temp30_input.dev_attr.attr,
1188 &sensor_dev_attr_temp31_input.dev_attr.attr,
1189 &sensor_dev_attr_temp32_input.dev_attr.attr,
1190 &sensor_dev_attr_temp33_input.dev_attr.attr,
1191 &sensor_dev_attr_temp34_input.dev_attr.attr,
1192 &sensor_dev_attr_temp35_input.dev_attr.attr,
6f2fad74
NB
1193 NULL
1194};
1195
1196static const struct attribute_group temperature_attributes_group =
1197 { .attrs = temperature_attributes };
1198
1199/* Module stuff */
1200
1201/*
1202 * applesmc_dmi_match - found a match. return one, short-circuiting the hunt.
1203 */
1855256c 1204static int applesmc_dmi_match(const struct dmi_system_id *id)
6f2fad74
NB
1205{
1206 int i = 0;
1207 struct dmi_match_data* dmi_data = id->driver_data;
1208 printk(KERN_INFO "applesmc: %s detected:\n", id->ident);
1209 applesmc_accelerometer = dmi_data->accelerometer;
1210 printk(KERN_INFO "applesmc: - Model %s accelerometer\n",
1211 applesmc_accelerometer ? "with" : "without");
1212 applesmc_light = dmi_data->light;
1213 printk(KERN_INFO "applesmc: - Model %s light sensors and backlight\n",
1214 applesmc_light ? "with" : "without");
1215
1216 applesmc_temperature_set = dmi_data->temperature_set;
1217 while (temperature_sensors_sets[applesmc_temperature_set][i] != NULL)
1218 i++;
1219 printk(KERN_INFO "applesmc: - Model with %d temperature sensors\n", i);
1220 return 1;
1221}
1222
1223/* Create accelerometer ressources */
1224static int applesmc_create_accelerometer(void)
1225{
d5cf2b99 1226 struct input_dev *idev;
6f2fad74
NB
1227 int ret;
1228
1229 ret = sysfs_create_group(&pdev->dev.kobj,
1230 &accelerometer_attributes_group);
1231 if (ret)
1232 goto out;
1233
d5cf2b99 1234 applesmc_idev = input_allocate_polled_device();
6f2fad74
NB
1235 if (!applesmc_idev) {
1236 ret = -ENOMEM;
1237 goto out_sysfs;
1238 }
1239
d5cf2b99
DT
1240 applesmc_idev->poll = applesmc_idev_poll;
1241 applesmc_idev->poll_interval = APPLESMC_POLL_INTERVAL;
1242
6f2fad74
NB
1243 /* initial calibrate for the input device */
1244 applesmc_calibrate();
1245
d5cf2b99
DT
1246 /* initialize the input device */
1247 idev = applesmc_idev->input;
1248 idev->name = "applesmc";
1249 idev->id.bustype = BUS_HOST;
1250 idev->dev.parent = &pdev->dev;
7b19ada2 1251 idev->evbit[0] = BIT_MASK(EV_ABS);
d5cf2b99 1252 input_set_abs_params(idev, ABS_X,
6f2fad74 1253 -256, 256, APPLESMC_INPUT_FUZZ, APPLESMC_INPUT_FLAT);
d5cf2b99 1254 input_set_abs_params(idev, ABS_Y,
6f2fad74
NB
1255 -256, 256, APPLESMC_INPUT_FUZZ, APPLESMC_INPUT_FLAT);
1256
d5cf2b99 1257 ret = input_register_polled_device(applesmc_idev);
6f2fad74
NB
1258 if (ret)
1259 goto out_idev;
1260
6f2fad74
NB
1261 return 0;
1262
1263out_idev:
d5cf2b99 1264 input_free_polled_device(applesmc_idev);
6f2fad74
NB
1265
1266out_sysfs:
1267 sysfs_remove_group(&pdev->dev.kobj, &accelerometer_attributes_group);
1268
1269out:
1270 printk(KERN_WARNING "applesmc: driver init failed (ret=%d)!\n", ret);
1271 return ret;
1272}
1273
1274/* Release all ressources used by the accelerometer */
1275static void applesmc_release_accelerometer(void)
1276{
d5cf2b99
DT
1277 input_unregister_polled_device(applesmc_idev);
1278 input_free_polled_device(applesmc_idev);
6f2fad74
NB
1279 sysfs_remove_group(&pdev->dev.kobj, &accelerometer_attributes_group);
1280}
1281
1282static __initdata struct dmi_match_data applesmc_dmi_data[] = {
1283/* MacBook Pro: accelerometer, backlight and temperature set 0 */
1284 { .accelerometer = 1, .light = 1, .temperature_set = 0 },
cd19ba13 1285/* MacBook2: accelerometer and temperature set 1 */
1bed24b9 1286 { .accelerometer = 1, .light = 0, .temperature_set = 1 },
cd19ba13
RO
1287/* MacBook: accelerometer and temperature set 2 */
1288 { .accelerometer = 1, .light = 0, .temperature_set = 2 },
1289/* MacMini: temperature set 3 */
8de57709 1290 { .accelerometer = 0, .light = 0, .temperature_set = 3 },
cd19ba13
RO
1291/* MacPro: temperature set 4 */
1292 { .accelerometer = 0, .light = 0, .temperature_set = 4 },
9f86f28d
RDI
1293/* iMac: temperature set 5 */
1294 { .accelerometer = 0, .light = 0, .temperature_set = 5 },
468cc032 1295/* MacBook3, MacBook4: accelerometer and temperature set 6 */
f91a79fe 1296 { .accelerometer = 1, .light = 0, .temperature_set = 6 },
f5274c97
HR
1297/* MacBook Air: accelerometer, backlight and temperature set 7 */
1298 { .accelerometer = 1, .light = 1, .temperature_set = 7 },
d7549905
HR
1299/* MacBook Pro 4: accelerometer, backlight and temperature set 8 */
1300 { .accelerometer = 1, .light = 1, .temperature_set = 8 },
07e8dbd3
HR
1301/* MacBook Pro 3: accelerometer, backlight and temperature set 9 */
1302 { .accelerometer = 1, .light = 1, .temperature_set = 9 },
6e3530fa
HR
1303/* iMac 5: light sensor only, temperature set 10 */
1304 { .accelerometer = 0, .light = 0, .temperature_set = 10 },
181209a1
HR
1305/* MacBook 5: accelerometer, backlight and temperature set 11 */
1306 { .accelerometer = 1, .light = 1, .temperature_set = 11 },
a6660325
HR
1307/* MacBook Pro 5: accelerometer, backlight and temperature set 12 */
1308 { .accelerometer = 1, .light = 1, .temperature_set = 12 },
eefc488f
HR
1309/* iMac 8: light sensor only, temperature set 13 */
1310 { .accelerometer = 0, .light = 0, .temperature_set = 13 },
9ca791bb
HR
1311/* iMac 6: light sensor only, temperature set 14 */
1312 { .accelerometer = 0, .light = 0, .temperature_set = 14 },
85e0e5ad
HR
1313/* MacBook Air 2,1: accelerometer, backlight and temperature set 15 */
1314 { .accelerometer = 1, .light = 1, .temperature_set = 15 },
6f2fad74
NB
1315};
1316
1317/* Note that DMI_MATCH(...,"MacBook") will match "MacBookPro1,1".
1318 * So we need to put "Apple MacBook Pro" before "Apple MacBook". */
1319static __initdata struct dmi_system_id applesmc_whitelist[] = {
85e0e5ad
HR
1320 { applesmc_dmi_match, "Apple MacBook Air 2", {
1321 DMI_MATCH(DMI_BOARD_VENDOR, "Apple"),
1322 DMI_MATCH(DMI_PRODUCT_NAME, "MacBookAir2") },
1323 &applesmc_dmi_data[15]},
f5274c97
HR
1324 { applesmc_dmi_match, "Apple MacBook Air", {
1325 DMI_MATCH(DMI_BOARD_VENDOR, "Apple"),
1326 DMI_MATCH(DMI_PRODUCT_NAME, "MacBookAir") },
7b5e3cb2 1327 &applesmc_dmi_data[7]},
a6660325
HR
1328 { applesmc_dmi_match, "Apple MacBook Pro 5", {
1329 DMI_MATCH(DMI_BOARD_VENDOR, "Apple"),
1330 DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro5") },
1331 &applesmc_dmi_data[12]},
d7549905
HR
1332 { applesmc_dmi_match, "Apple MacBook Pro 4", {
1333 DMI_MATCH(DMI_BOARD_VENDOR, "Apple"),
1334 DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro4") },
1335 &applesmc_dmi_data[8]},
07e8dbd3
HR
1336 { applesmc_dmi_match, "Apple MacBook Pro 3", {
1337 DMI_MATCH(DMI_BOARD_VENDOR, "Apple"),
1338 DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro3") },
1339 &applesmc_dmi_data[9]},
6f2fad74
NB
1340 { applesmc_dmi_match, "Apple MacBook Pro", {
1341 DMI_MATCH(DMI_BOARD_VENDOR,"Apple"),
1342 DMI_MATCH(DMI_PRODUCT_NAME,"MacBookPro") },
7b5e3cb2 1343 &applesmc_dmi_data[0]},
f91a79fe 1344 { applesmc_dmi_match, "Apple MacBook (v2)", {
6f2fad74 1345 DMI_MATCH(DMI_BOARD_VENDOR,"Apple"),
cd19ba13 1346 DMI_MATCH(DMI_PRODUCT_NAME,"MacBook2") },
7b5e3cb2 1347 &applesmc_dmi_data[1]},
f91a79fe
GS
1348 { applesmc_dmi_match, "Apple MacBook (v3)", {
1349 DMI_MATCH(DMI_BOARD_VENDOR,"Apple"),
1350 DMI_MATCH(DMI_PRODUCT_NAME,"MacBook3") },
7b5e3cb2 1351 &applesmc_dmi_data[6]},
468cc032
HR
1352 { applesmc_dmi_match, "Apple MacBook 4", {
1353 DMI_MATCH(DMI_BOARD_VENDOR, "Apple"),
1354 DMI_MATCH(DMI_PRODUCT_NAME, "MacBook4") },
1355 &applesmc_dmi_data[6]},
181209a1
HR
1356 { applesmc_dmi_match, "Apple MacBook 5", {
1357 DMI_MATCH(DMI_BOARD_VENDOR, "Apple"),
1358 DMI_MATCH(DMI_PRODUCT_NAME, "MacBook5") },
1359 &applesmc_dmi_data[11]},
cd19ba13
RO
1360 { applesmc_dmi_match, "Apple MacBook", {
1361 DMI_MATCH(DMI_BOARD_VENDOR,"Apple"),
1362 DMI_MATCH(DMI_PRODUCT_NAME,"MacBook") },
7b5e3cb2 1363 &applesmc_dmi_data[2]},
6f2fad74
NB
1364 { applesmc_dmi_match, "Apple Macmini", {
1365 DMI_MATCH(DMI_BOARD_VENDOR,"Apple"),
1366 DMI_MATCH(DMI_PRODUCT_NAME,"Macmini") },
7b5e3cb2 1367 &applesmc_dmi_data[3]},
8de57709
RR
1368 { applesmc_dmi_match, "Apple MacPro2", {
1369 DMI_MATCH(DMI_BOARD_VENDOR,"Apple"),
1370 DMI_MATCH(DMI_PRODUCT_NAME,"MacPro2") },
7b5e3cb2 1371 &applesmc_dmi_data[4]},
45a3a36b
HR
1372 { applesmc_dmi_match, "Apple MacPro", {
1373 DMI_MATCH(DMI_BOARD_VENDOR, "Apple"),
1374 DMI_MATCH(DMI_PRODUCT_NAME, "MacPro") },
1375 &applesmc_dmi_data[4]},
eefc488f
HR
1376 { applesmc_dmi_match, "Apple iMac 8", {
1377 DMI_MATCH(DMI_BOARD_VENDOR, "Apple"),
1378 DMI_MATCH(DMI_PRODUCT_NAME, "iMac8") },
1379 &applesmc_dmi_data[13]},
9ca791bb
HR
1380 { applesmc_dmi_match, "Apple iMac 6", {
1381 DMI_MATCH(DMI_BOARD_VENDOR, "Apple"),
1382 DMI_MATCH(DMI_PRODUCT_NAME, "iMac6") },
1383 &applesmc_dmi_data[14]},
6e3530fa
HR
1384 { applesmc_dmi_match, "Apple iMac 5", {
1385 DMI_MATCH(DMI_BOARD_VENDOR, "Apple"),
1386 DMI_MATCH(DMI_PRODUCT_NAME, "iMac5") },
1387 &applesmc_dmi_data[10]},
9f86f28d
RDI
1388 { applesmc_dmi_match, "Apple iMac", {
1389 DMI_MATCH(DMI_BOARD_VENDOR,"Apple"),
1390 DMI_MATCH(DMI_PRODUCT_NAME,"iMac") },
7b5e3cb2 1391 &applesmc_dmi_data[5]},
6f2fad74
NB
1392 { .ident = NULL }
1393};
1394
1395static int __init applesmc_init(void)
1396{
1397 int ret;
1398 int count;
1399 int i;
1400
6f2fad74
NB
1401 if (!dmi_check_system(applesmc_whitelist)) {
1402 printk(KERN_WARNING "applesmc: supported laptop not found!\n");
1403 ret = -ENODEV;
1404 goto out;
1405 }
1406
1407 if (!request_region(APPLESMC_DATA_PORT, APPLESMC_NR_PORTS,
1408 "applesmc")) {
1409 ret = -ENXIO;
1410 goto out;
1411 }
1412
1413 ret = platform_driver_register(&applesmc_driver);
1414 if (ret)
1415 goto out_region;
1416
ddfbf2af
JD
1417 pdev = platform_device_register_simple("applesmc", APPLESMC_DATA_PORT,
1418 NULL, 0);
6f2fad74
NB
1419 if (IS_ERR(pdev)) {
1420 ret = PTR_ERR(pdev);
1421 goto out_driver;
1422 }
1423
fa74419b 1424 ret = sysfs_create_file(&pdev->dev.kobj, &dev_attr_name.attr);
6996abf0
NB
1425 if (ret)
1426 goto out_device;
fa74419b 1427
6f2fad74
NB
1428 /* Create key enumeration sysfs files */
1429 ret = sysfs_create_group(&pdev->dev.kobj, &key_enumeration_group);
1430 if (ret)
6996abf0 1431 goto out_name;
6f2fad74
NB
1432
1433 /* create fan files */
1434 count = applesmc_get_fan_count();
1435 if (count < 0) {
1436 printk(KERN_ERR "applesmc: Cannot get the number of fans.\n");
1437 } else {
1438 printk(KERN_INFO "applesmc: %d fans found.\n", count);
1439
1440 switch (count) {
1441 default:
8de57709
RR
1442 printk(KERN_WARNING "applesmc: More than 4 fans found,"
1443 " but at most 4 fans are supported"
6f2fad74 1444 " by the driver.\n");
8de57709
RR
1445 case 4:
1446 ret = sysfs_create_group(&pdev->dev.kobj,
1447 &fan_attribute_groups[3]);
1448 if (ret)
1449 goto out_key_enumeration;
1450 case 3:
1451 ret = sysfs_create_group(&pdev->dev.kobj,
1452 &fan_attribute_groups[2]);
1453 if (ret)
1454 goto out_key_enumeration;
6f2fad74
NB
1455 case 2:
1456 ret = sysfs_create_group(&pdev->dev.kobj,
1457 &fan_attribute_groups[1]);
1458 if (ret)
1459 goto out_key_enumeration;
1460 case 1:
1461 ret = sysfs_create_group(&pdev->dev.kobj,
1462 &fan_attribute_groups[0]);
1463 if (ret)
1464 goto out_fan_1;
1465 case 0:
1466 ;
1467 }
1468 }
1469
1470 for (i = 0;
1471 temperature_sensors_sets[applesmc_temperature_set][i] != NULL;
1472 i++) {
1473 if (temperature_attributes[i] == NULL) {
1474 printk(KERN_ERR "applesmc: More temperature sensors "
1475 "in temperature_sensors_sets (at least %i)"
1476 "than available sysfs files in "
1477 "temperature_attributes (%i), please report "
1478 "this bug.\n", i, i-1);
1479 goto out_temperature;
1480 }
1481 ret = sysfs_create_file(&pdev->dev.kobj,
1482 temperature_attributes[i]);
1483 if (ret)
1484 goto out_temperature;
1485 }
1486
1487 if (applesmc_accelerometer) {
1488 ret = applesmc_create_accelerometer();
1489 if (ret)
1490 goto out_temperature;
1491 }
1492
1493 if (applesmc_light) {
1494 /* Add light sensor file */
1495 ret = sysfs_create_file(&pdev->dev.kobj, &dev_attr_light.attr);
1496 if (ret)
1497 goto out_accelerometer;
1498
1499 /* Create the workqueue */
1500 applesmc_led_wq = create_singlethread_workqueue("applesmc-led");
1501 if (!applesmc_led_wq) {
1502 ret = -ENOMEM;
1503 goto out_light_sysfs;
1504 }
1505
1506 /* register as a led device */
1507 ret = led_classdev_register(&pdev->dev, &applesmc_backlight);
1508 if (ret < 0)
1509 goto out_light_wq;
1510 }
1511
1beeffe4
TJ
1512 hwmon_dev = hwmon_device_register(&pdev->dev);
1513 if (IS_ERR(hwmon_dev)) {
1514 ret = PTR_ERR(hwmon_dev);
6f2fad74
NB
1515 goto out_light_ledclass;
1516 }
1517
1518 printk(KERN_INFO "applesmc: driver successfully loaded.\n");
1519
1520 return 0;
1521
1522out_light_ledclass:
1523 if (applesmc_light)
1524 led_classdev_unregister(&applesmc_backlight);
1525out_light_wq:
1526 if (applesmc_light)
1527 destroy_workqueue(applesmc_led_wq);
1528out_light_sysfs:
1529 if (applesmc_light)
1530 sysfs_remove_file(&pdev->dev.kobj, &dev_attr_light.attr);
1531out_accelerometer:
1532 if (applesmc_accelerometer)
1533 applesmc_release_accelerometer();
1534out_temperature:
1535 sysfs_remove_group(&pdev->dev.kobj, &temperature_attributes_group);
1536 sysfs_remove_group(&pdev->dev.kobj, &fan_attribute_groups[0]);
1537out_fan_1:
1538 sysfs_remove_group(&pdev->dev.kobj, &fan_attribute_groups[1]);
1539out_key_enumeration:
1540 sysfs_remove_group(&pdev->dev.kobj, &key_enumeration_group);
6996abf0
NB
1541out_name:
1542 sysfs_remove_file(&pdev->dev.kobj, &dev_attr_name.attr);
6f2fad74
NB
1543out_device:
1544 platform_device_unregister(pdev);
1545out_driver:
1546 platform_driver_unregister(&applesmc_driver);
1547out_region:
1548 release_region(APPLESMC_DATA_PORT, APPLESMC_NR_PORTS);
1549out:
1550 printk(KERN_WARNING "applesmc: driver init failed (ret=%d)!\n", ret);
1551 return ret;
1552}
1553
1554static void __exit applesmc_exit(void)
1555{
1beeffe4 1556 hwmon_device_unregister(hwmon_dev);
6f2fad74
NB
1557 if (applesmc_light) {
1558 led_classdev_unregister(&applesmc_backlight);
1559 destroy_workqueue(applesmc_led_wq);
1560 sysfs_remove_file(&pdev->dev.kobj, &dev_attr_light.attr);
1561 }
1562 if (applesmc_accelerometer)
1563 applesmc_release_accelerometer();
1564 sysfs_remove_group(&pdev->dev.kobj, &temperature_attributes_group);
1565 sysfs_remove_group(&pdev->dev.kobj, &fan_attribute_groups[0]);
1566 sysfs_remove_group(&pdev->dev.kobj, &fan_attribute_groups[1]);
1567 sysfs_remove_group(&pdev->dev.kobj, &key_enumeration_group);
6996abf0 1568 sysfs_remove_file(&pdev->dev.kobj, &dev_attr_name.attr);
6f2fad74
NB
1569 platform_device_unregister(pdev);
1570 platform_driver_unregister(&applesmc_driver);
1571 release_region(APPLESMC_DATA_PORT, APPLESMC_NR_PORTS);
1572
1573 printk(KERN_INFO "applesmc: driver unloaded.\n");
1574}
1575
1576module_init(applesmc_init);
1577module_exit(applesmc_exit);
1578
1579MODULE_AUTHOR("Nicolas Boichat");
1580MODULE_DESCRIPTION("Apple SMC");
1581MODULE_LICENSE("GPL v2");
dc924efb 1582MODULE_DEVICE_TABLE(dmi, applesmc_whitelist);