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