diff options
| author | Henrik Rydberg <rydberg@euromail.se> | 2012-07-26 15:54:06 +0200 |
|---|---|---|
| committer | Henrik Rydberg <rydberg@euromail.se> | 2012-07-27 14:15:51 +0200 |
| commit | 9130f8aef481626b733f9e0d535728c55b9bd706 (patch) | |
| tree | e864baeb179653cc39d12400001e595805efb1ad /usr/src/dkms_source_tree | |
| parent | e704f5eb16d58debf7d815942fc377392af60ebc (diff) | |
Update to pre-3.6
This also solves read and write errors on all machines.
Signed-off-by: Henrik Rydberg <rydberg@euromail.se>
Diffstat (limited to 'usr/src/dkms_source_tree')
| -rw-r--r-- | usr/src/dkms_source_tree/applesmc.c | 269 |
1 files changed, 146 insertions, 123 deletions
diff --git a/usr/src/dkms_source_tree/applesmc.c b/usr/src/dkms_source_tree/applesmc.c index 7b22f67..2827088 100644 --- a/usr/src/dkms_source_tree/applesmc.c +++ b/usr/src/dkms_source_tree/applesmc.c | |||
| @@ -8,7 +8,7 @@ | |||
| 8 | * | 8 | * |
| 9 | * Based on hdaps.c driver: | 9 | * Based on hdaps.c driver: |
| 10 | * Copyright (C) 2005 Robert Love <rml@novell.com> | 10 | * Copyright (C) 2005 Robert Love <rml@novell.com> |
| 11 | * Copyright (C) 2005 Jesper Juhl <jesper.juhl@gmail.com> | 11 | * Copyright (C) 2005 Jesper Juhl <jj@chaosbits.net> |
| 12 | * | 12 | * |
| 13 | * Fan control based on smcFanControl: | 13 | * Fan control based on smcFanControl: |
| 14 | * Copyright (C) 2006 Hendrik Holtmann <holtmann@mac.com> | 14 | * Copyright (C) 2006 Hendrik Holtmann <holtmann@mac.com> |
| @@ -44,16 +44,6 @@ | |||
| 44 | #include <linux/hwmon.h> | 44 | #include <linux/hwmon.h> |
| 45 | #include <linux/workqueue.h> | 45 | #include <linux/workqueue.h> |
| 46 | 46 | ||
| 47 | #ifndef pr_info | ||
| 48 | #define pr_info(fmt, ...) printk(KERN_INFO pr_fmt(fmt), ##__VA_ARGS__) | ||
| 49 | #endif | ||
| 50 | #ifndef pr_err | ||
| 51 | #define pr_err(fmt, ...) printk(KERN_ERR pr_fmt(fmt), ##__VA_ARGS__) | ||
| 52 | #endif | ||
| 53 | #ifndef pr_warn | ||
| 54 | #define pr_warn(fmt, ...) printk(KERN_WARNING pr_fmt(fmt), ##__VA_ARGS__) | ||
| 55 | #endif | ||
| 56 | |||
| 57 | /* data port used by Apple SMC */ | 47 | /* data port used by Apple SMC */ |
| 58 | #define APPLESMC_DATA_PORT 0x300 | 48 | #define APPLESMC_DATA_PORT 0x300 |
| 59 | /* command/status port used by Apple SMC */ | 49 | /* command/status port used by Apple SMC */ |
| @@ -64,10 +54,10 @@ | |||
| 64 | #define APPLESMC_MAX_DATA_LENGTH 32 | 54 | #define APPLESMC_MAX_DATA_LENGTH 32 |
| 65 | 55 | ||
| 66 | /* wait up to 32 ms for a status change. */ | 56 | /* wait up to 32 ms for a status change. */ |
| 67 | #define APPLESMC_MIN_WAIT 0x0040 | 57 | #define APPLESMC_MIN_WAIT 0x0010 |
| 58 | #define APPLESMC_RETRY_WAIT 0x0100 | ||
| 68 | #define APPLESMC_MAX_WAIT 0x8000 | 59 | #define APPLESMC_MAX_WAIT 0x8000 |
| 69 | 60 | ||
| 70 | #define APPLESMC_STATUS_MASK 0x0f | ||
| 71 | #define APPLESMC_READ_CMD 0x10 | 61 | #define APPLESMC_READ_CMD 0x10 |
| 72 | #define APPLESMC_WRITE_CMD 0x11 | 62 | #define APPLESMC_WRITE_CMD 0x11 |
| 73 | #define APPLESMC_GET_KEY_BY_INDEX_CMD 0x12 | 63 | #define APPLESMC_GET_KEY_BY_INDEX_CMD 0x12 |
| @@ -90,6 +80,8 @@ | |||
| 90 | #define FANS_MANUAL "FS! " /* r-w ui16 */ | 80 | #define FANS_MANUAL "FS! " /* r-w ui16 */ |
| 91 | #define FAN_ID_FMT "F%dID" /* r-o char[16] */ | 81 | #define FAN_ID_FMT "F%dID" /* r-o char[16] */ |
| 92 | 82 | ||
| 83 | #define TEMP_SENSOR_TYPE "sp78" | ||
| 84 | |||
| 93 | /* List of keys used to read/write fan speeds */ | 85 | /* List of keys used to read/write fan speeds */ |
| 94 | static const char *const fan_speed_fmt[] = { | 86 | static const char *const fan_speed_fmt[] = { |
| 95 | "F%dAc", /* actual speed */ | 87 | "F%dAc", /* actual speed */ |
| @@ -106,10 +98,6 @@ static const char *const fan_speed_fmt[] = { | |||
| 106 | #define APPLESMC_INPUT_FUZZ 4 /* input event threshold */ | 98 | #define APPLESMC_INPUT_FUZZ 4 /* input event threshold */ |
| 107 | #define APPLESMC_INPUT_FLAT 4 | 99 | #define APPLESMC_INPUT_FLAT 4 |
| 108 | 100 | ||
| 109 | #define SENSOR_X 0 | ||
| 110 | #define SENSOR_Y 1 | ||
| 111 | #define SENSOR_Z 2 | ||
| 112 | |||
| 113 | #define to_index(attr) (to_sensor_dev_attr(attr)->index & 0xffff) | 101 | #define to_index(attr) (to_sensor_dev_attr(attr)->index & 0xffff) |
| 114 | #define to_option(attr) (to_sensor_dev_attr(attr)->index >> 16) | 102 | #define to_option(attr) (to_sensor_dev_attr(attr)->index >> 16) |
| 115 | 103 | ||
| @@ -145,11 +133,13 @@ static struct applesmc_registers { | |||
| 145 | unsigned int temp_count; /* number of temperature registers */ | 133 | unsigned int temp_count; /* number of temperature registers */ |
| 146 | unsigned int temp_begin; /* temperature lower index bound */ | 134 | unsigned int temp_begin; /* temperature lower index bound */ |
| 147 | unsigned int temp_end; /* temperature upper index bound */ | 135 | unsigned int temp_end; /* temperature upper index bound */ |
| 136 | unsigned int index_count; /* size of temperature index array */ | ||
| 148 | int num_light_sensors; /* number of light sensors */ | 137 | int num_light_sensors; /* number of light sensors */ |
| 149 | bool has_accelerometer; /* has motion sensor */ | 138 | bool has_accelerometer; /* has motion sensor */ |
| 150 | bool has_key_backlight; /* has keyboard backlight */ | 139 | bool has_key_backlight; /* has keyboard backlight */ |
| 151 | bool init_complete; /* true when fully initialized */ | 140 | bool init_complete; /* true when fully initialized */ |
| 152 | struct applesmc_entry *cache; /* cached key entries */ | 141 | struct applesmc_entry *cache; /* cached key entries */ |
| 142 | const char **index; /* temperature key index */ | ||
| 153 | } smcreg = { | 143 | } smcreg = { |
| 154 | .mutex = __MUTEX_INITIALIZER(smcreg.mutex), | 144 | .mutex = __MUTEX_INITIALIZER(smcreg.mutex), |
| 155 | }; | 145 | }; |
| @@ -172,52 +162,68 @@ static unsigned int key_at_index; | |||
| 172 | static struct workqueue_struct *applesmc_led_wq; | 162 | static struct workqueue_struct *applesmc_led_wq; |
| 173 | 163 | ||
| 174 | /* | 164 | /* |
| 175 | * __wait_status - Wait up to 32ms for the status port to get a certain value | 165 | * wait_read - Wait for a byte to appear on SMC port. Callers must |
| 176 | * (masked with 0x0f), returning zero if the value is obtained. Callers must | ||
| 177 | * hold applesmc_lock. | 166 | * hold applesmc_lock. |
| 178 | */ | 167 | */ |
| 179 | static int __wait_status(u8 val) | 168 | static int wait_read(void) |
| 180 | { | 169 | { |
| 170 | u8 status; | ||
| 181 | int us; | 171 | int us; |
| 182 | |||
| 183 | val = val & APPLESMC_STATUS_MASK; | ||
| 184 | |||
| 185 | for (us = APPLESMC_MIN_WAIT; us < APPLESMC_MAX_WAIT; us <<= 1) { | 172 | for (us = APPLESMC_MIN_WAIT; us < APPLESMC_MAX_WAIT; us <<= 1) { |
| 186 | udelay(us); | 173 | udelay(us); |
| 187 | if ((inb(APPLESMC_CMD_PORT) & APPLESMC_STATUS_MASK) == val) { | 174 | status = inb(APPLESMC_CMD_PORT); |
| 175 | /* read: wait for smc to settle */ | ||
| 176 | if (status & 0x01) | ||
| 188 | return 0; | 177 | return 0; |
| 189 | } | ||
| 190 | } | 178 | } |
| 191 | 179 | ||
| 180 | pr_warn("wait_read() fail: 0x%02x\n", status); | ||
| 192 | return -EIO; | 181 | return -EIO; |
| 193 | } | 182 | } |
| 194 | 183 | ||
| 195 | /* | 184 | /* |
| 196 | * special treatment of command port - on newer macbooks, it seems necessary | 185 | * send_byte - Write to SMC port, retrying when necessary. Callers |
| 197 | * to resend the command byte before polling the status again. Callers must | 186 | * must hold applesmc_lock. |
| 198 | * hold applesmc_lock. | ||
| 199 | */ | 187 | */ |
| 200 | static int send_command(u8 cmd) | 188 | static int send_byte(u8 cmd, u16 port) |
| 201 | { | 189 | { |
| 190 | u8 status; | ||
| 202 | int us; | 191 | int us; |
| 192 | |||
| 193 | outb(cmd, port); | ||
| 203 | for (us = APPLESMC_MIN_WAIT; us < APPLESMC_MAX_WAIT; us <<= 1) { | 194 | for (us = APPLESMC_MIN_WAIT; us < APPLESMC_MAX_WAIT; us <<= 1) { |
| 204 | outb(cmd, APPLESMC_CMD_PORT); | ||
| 205 | udelay(us); | 195 | udelay(us); |
| 206 | if ((inb(APPLESMC_CMD_PORT) & APPLESMC_STATUS_MASK) == 0x0c) | 196 | status = inb(APPLESMC_CMD_PORT); |
| 197 | /* write: wait for smc to settle */ | ||
| 198 | if (status & 0x02) | ||
| 199 | continue; | ||
| 200 | /* ready: cmd accepted, return */ | ||
| 201 | if (status & 0x04) | ||
| 207 | return 0; | 202 | return 0; |
| 203 | /* timeout: give up */ | ||
| 204 | if (us << 1 == APPLESMC_MAX_WAIT) | ||
| 205 | break; | ||
| 206 | /* busy: long wait and resend */ | ||
| 207 | udelay(APPLESMC_RETRY_WAIT); | ||
| 208 | outb(cmd, port); | ||
| 208 | } | 209 | } |
| 210 | |||
| 211 | pr_warn("send_byte(0x%02x, 0x%04x) fail: 0x%02x\n", cmd, port, status); | ||
| 209 | return -EIO; | 212 | return -EIO; |
| 210 | } | 213 | } |
| 211 | 214 | ||
| 215 | static int send_command(u8 cmd) | ||
| 216 | { | ||
| 217 | return send_byte(cmd, APPLESMC_CMD_PORT); | ||
| 218 | } | ||
| 219 | |||
| 212 | static int send_argument(const char *key) | 220 | static int send_argument(const char *key) |
| 213 | { | 221 | { |
| 214 | int i; | 222 | int i; |
| 215 | 223 | ||
| 216 | for (i = 0; i < 4; i++) { | 224 | for (i = 0; i < 4; i++) |
| 217 | outb(key[i], APPLESMC_DATA_PORT); | 225 | if (send_byte(key[i], APPLESMC_DATA_PORT)) |
| 218 | if (__wait_status(0x04)) | ||
| 219 | return -EIO; | 226 | return -EIO; |
| 220 | } | ||
| 221 | return 0; | 227 | return 0; |
| 222 | } | 228 | } |
| 223 | 229 | ||
| @@ -226,15 +232,18 @@ static int read_smc(u8 cmd, const char *key, u8 *buffer, u8 len) | |||
| 226 | int i; | 232 | int i; |
| 227 | 233 | ||
| 228 | if (send_command(cmd) || send_argument(key)) { | 234 | if (send_command(cmd) || send_argument(key)) { |
| 229 | pr_warn("%s: read arg fail\n", key); | 235 | pr_warn("%.4s: read arg fail\n", key); |
| 230 | return -EIO; | 236 | return -EIO; |
| 231 | } | 237 | } |
| 232 | 238 | ||
| 233 | outb(len, APPLESMC_DATA_PORT); | 239 | if (send_byte(len, APPLESMC_DATA_PORT)) { |
| 240 | pr_warn("%.4s: read len fail\n", key); | ||
| 241 | return -EIO; | ||
| 242 | } | ||
| 234 | 243 | ||
| 235 | for (i = 0; i < len; i++) { | 244 | for (i = 0; i < len; i++) { |
| 236 | if (__wait_status(0x05)) { | 245 | if (wait_read()) { |
| 237 | pr_warn("%s: read data fail\n", key); | 246 | pr_warn("%.4s: read data[%d] fail\n", key, i); |
| 238 | return -EIO; | 247 | return -EIO; |
| 239 | } | 248 | } |
| 240 | buffer[i] = inb(APPLESMC_DATA_PORT); | 249 | buffer[i] = inb(APPLESMC_DATA_PORT); |
| @@ -252,14 +261,16 @@ static int write_smc(u8 cmd, const char *key, const u8 *buffer, u8 len) | |||
| 252 | return -EIO; | 261 | return -EIO; |
| 253 | } | 262 | } |
| 254 | 263 | ||
| 255 | outb(len, APPLESMC_DATA_PORT); | 264 | if (send_byte(len, APPLESMC_DATA_PORT)) { |
| 265 | pr_warn("%.4s: write len fail\n", key); | ||
| 266 | return -EIO; | ||
| 267 | } | ||
| 256 | 268 | ||
| 257 | for (i = 0; i < len; i++) { | 269 | for (i = 0; i < len; i++) { |
| 258 | if (__wait_status(0x04)) { | 270 | if (send_byte(buffer[i], APPLESMC_DATA_PORT)) { |
| 259 | pr_warn("%s: write data fail\n", key); | 271 | pr_warn("%s: write data fail\n", key); |
| 260 | return -EIO; | 272 | return -EIO; |
| 261 | } | 273 | } |
| 262 | outb(buffer[i], APPLESMC_DATA_PORT); | ||
| 263 | } | 274 | } |
| 264 | 275 | ||
| 265 | return 0; | 276 | return 0; |
| @@ -355,8 +366,10 @@ static int applesmc_get_lower_bound(unsigned int *lo, const char *key) | |||
| 355 | while (begin != end) { | 366 | while (begin != end) { |
| 356 | int middle = begin + (end - begin) / 2; | 367 | int middle = begin + (end - begin) / 2; |
| 357 | entry = applesmc_get_entry_by_index(middle); | 368 | entry = applesmc_get_entry_by_index(middle); |
| 358 | if (IS_ERR(entry)) | 369 | if (IS_ERR(entry)) { |
| 370 | *lo = 0; | ||
| 359 | return PTR_ERR(entry); | 371 | return PTR_ERR(entry); |
| 372 | } | ||
| 360 | if (strcmp(entry->key, key) < 0) | 373 | if (strcmp(entry->key, key) < 0) |
| 361 | begin = middle + 1; | 374 | begin = middle + 1; |
| 362 | else | 375 | else |
| @@ -375,8 +388,10 @@ static int applesmc_get_upper_bound(unsigned int *hi, const char *key) | |||
| 375 | while (begin != end) { | 388 | while (begin != end) { |
| 376 | int middle = begin + (end - begin) / 2; | 389 | int middle = begin + (end - begin) / 2; |
| 377 | entry = applesmc_get_entry_by_index(middle); | 390 | entry = applesmc_get_entry_by_index(middle); |
| 378 | if (IS_ERR(entry)) | 391 | if (IS_ERR(entry)) { |
| 392 | *hi = smcreg.key_count; | ||
| 379 | return PTR_ERR(entry); | 393 | return PTR_ERR(entry); |
| 394 | } | ||
| 380 | if (strcmp(key, entry->key) < 0) | 395 | if (strcmp(key, entry->key) < 0) |
| 381 | end = middle; | 396 | end = middle; |
| 382 | else | 397 | else |
| @@ -439,30 +454,19 @@ static int applesmc_has_key(const char *key, bool *value) | |||
| 439 | } | 454 | } |
| 440 | 455 | ||
| 441 | /* | 456 | /* |
| 442 | * applesmc_read_motion_sensor - Read motion sensor (X, Y or Z). | 457 | * applesmc_read_s16 - Read 16-bit signed big endian register |
| 443 | */ | 458 | */ |
| 444 | static int applesmc_read_motion_sensor(int index, s16* value) | 459 | static int applesmc_read_s16(const char *key, s16 *value) |
| 445 | { | 460 | { |
| 446 | u8 buffer[2]; | 461 | u8 buffer[2]; |
| 447 | int ret; | 462 | int ret; |
| 448 | 463 | ||
| 449 | switch (index) { | 464 | ret = applesmc_read_key(key, buffer, 2); |
| 450 | case SENSOR_X: | 465 | if (ret) |
| 451 | ret = applesmc_read_key(MOTION_SENSOR_X_KEY, buffer, 2); | 466 | return ret; |
| 452 | break; | ||
| 453 | case SENSOR_Y: | ||
| 454 | ret = applesmc_read_key(MOTION_SENSOR_Y_KEY, buffer, 2); | ||
| 455 | break; | ||
| 456 | case SENSOR_Z: | ||
| 457 | ret = applesmc_read_key(MOTION_SENSOR_Z_KEY, buffer, 2); | ||
| 458 | break; | ||
| 459 | default: | ||
| 460 | ret = -EINVAL; | ||
| 461 | } | ||
| 462 | 467 | ||
| 463 | *value = ((s16)buffer[0] << 8) | buffer[1]; | 468 | *value = ((s16)buffer[0] << 8) | buffer[1]; |
| 464 | 469 | return 0; | |
| 465 | return ret; | ||
| 466 | } | 470 | } |
| 467 | 471 | ||
| 468 | /* | 472 | /* |
| @@ -489,6 +493,30 @@ static void applesmc_device_init(void) | |||
| 489 | pr_warn("failed to init the device\n"); | 493 | pr_warn("failed to init the device\n"); |
| 490 | } | 494 | } |
| 491 | 495 | ||
| 496 | static int applesmc_init_index(struct applesmc_registers *s) | ||
| 497 | { | ||
| 498 | const struct applesmc_entry *entry; | ||
| 499 | unsigned int i; | ||
| 500 | |||
| 501 | if (s->index) | ||
| 502 | return 0; | ||
| 503 | |||
| 504 | s->index = kcalloc(s->temp_count, sizeof(s->index[0]), GFP_KERNEL); | ||
| 505 | if (!s->index) | ||
| 506 | return -ENOMEM; | ||
| 507 | |||
| 508 | for (i = s->temp_begin; i < s->temp_end; i++) { | ||
| 509 | entry = applesmc_get_entry_by_index(i); | ||
| 510 | if (IS_ERR(entry)) | ||
| 511 | continue; | ||
| 512 | if (strcmp(entry->type, TEMP_SENSOR_TYPE)) | ||
| 513 | continue; | ||
| 514 | s->index[s->index_count++] = entry->key; | ||
| 515 | } | ||
| 516 | |||
| 517 | return 0; | ||
| 518 | } | ||
| 519 | |||
| 492 | /* | 520 | /* |
| 493 | * applesmc_init_smcreg_try - Try to initialize register cache. Idempotent. | 521 | * applesmc_init_smcreg_try - Try to initialize register cache. Idempotent. |
| 494 | */ | 522 | */ |
| @@ -524,6 +552,10 @@ static int applesmc_init_smcreg_try(void) | |||
| 524 | return ret; | 552 | return ret; |
| 525 | s->temp_count = s->temp_end - s->temp_begin; | 553 | s->temp_count = s->temp_end - s->temp_begin; |
| 526 | 554 | ||
| 555 | ret = applesmc_init_index(s); | ||
| 556 | if (ret) | ||
| 557 | return ret; | ||
| 558 | |||
| 527 | ret = applesmc_has_key(LIGHT_SENSOR_LEFT_KEY, &left_light_sensor); | 559 | ret = applesmc_has_key(LIGHT_SENSOR_LEFT_KEY, &left_light_sensor); |
| 528 | if (ret) | 560 | if (ret) |
| 529 | return ret; | 561 | return ret; |
| @@ -540,8 +572,8 @@ static int applesmc_init_smcreg_try(void) | |||
| 540 | s->num_light_sensors = left_light_sensor + right_light_sensor; | 572 | s->num_light_sensors = left_light_sensor + right_light_sensor; |
| 541 | s->init_complete = true; | 573 | s->init_complete = true; |
| 542 | 574 | ||
| 543 | pr_info("key=%d fan=%d temp=%d acc=%d lux=%d kbd=%d\n", | 575 | pr_info("key=%d fan=%d temp=%d index=%d acc=%d lux=%d kbd=%d\n", |
| 544 | s->key_count, s->fan_count, s->temp_count, | 576 | s->key_count, s->fan_count, s->temp_count, s->index_count, |
| 545 | s->has_accelerometer, | 577 | s->has_accelerometer, |
| 546 | s->num_light_sensors, | 578 | s->num_light_sensors, |
| 547 | s->has_key_backlight); | 579 | s->has_key_backlight); |
| @@ -549,6 +581,15 @@ static int applesmc_init_smcreg_try(void) | |||
| 549 | return 0; | 581 | return 0; |
| 550 | } | 582 | } |
| 551 | 583 | ||
| 584 | static void applesmc_destroy_smcreg(void) | ||
| 585 | { | ||
| 586 | kfree(smcreg.index); | ||
| 587 | smcreg.index = NULL; | ||
| 588 | kfree(smcreg.cache); | ||
| 589 | smcreg.cache = NULL; | ||
| 590 | smcreg.init_complete = false; | ||
| 591 | } | ||
| 592 | |||
| 552 | /* | 593 | /* |
| 553 | * applesmc_init_smcreg - Initialize register cache. | 594 | * applesmc_init_smcreg - Initialize register cache. |
| 554 | * | 595 | * |
| @@ -569,19 +610,11 @@ static int applesmc_init_smcreg(void) | |||
| 569 | msleep(INIT_WAIT_MSECS); | 610 | msleep(INIT_WAIT_MSECS); |
| 570 | } | 611 | } |
| 571 | 612 | ||
| 572 | kfree(smcreg.cache); | 613 | applesmc_destroy_smcreg(); |
| 573 | smcreg.cache = NULL; | ||
| 574 | 614 | ||
| 575 | return ret; | 615 | return ret; |
| 576 | } | 616 | } |
| 577 | 617 | ||
| 578 | static void applesmc_destroy_smcreg(void) | ||
| 579 | { | ||
| 580 | kfree(smcreg.cache); | ||
| 581 | smcreg.cache = NULL; | ||
| 582 | smcreg.init_complete = false; | ||
| 583 | } | ||
| 584 | |||
| 585 | /* Device model stuff */ | 618 | /* Device model stuff */ |
| 586 | static int applesmc_probe(struct platform_device *dev) | 619 | static int applesmc_probe(struct platform_device *dev) |
| 587 | { | 620 | { |
| @@ -631,8 +664,8 @@ static struct platform_driver applesmc_driver = { | |||
| 631 | */ | 664 | */ |
| 632 | static void applesmc_calibrate(void) | 665 | static void applesmc_calibrate(void) |
| 633 | { | 666 | { |
| 634 | applesmc_read_motion_sensor(SENSOR_X, &rest_x); | 667 | applesmc_read_s16(MOTION_SENSOR_X_KEY, &rest_x); |
| 635 | applesmc_read_motion_sensor(SENSOR_Y, &rest_y); | 668 | applesmc_read_s16(MOTION_SENSOR_Y_KEY, &rest_y); |
| 636 | rest_x = -rest_x; | 669 | rest_x = -rest_x; |
| 637 | } | 670 | } |
| 638 | 671 | ||
| @@ -641,9 +674,9 @@ static void applesmc_idev_poll(struct input_polled_dev *dev) | |||
| 641 | struct input_dev *idev = dev->input; | 674 | struct input_dev *idev = dev->input; |
| 642 | s16 x, y; | 675 | s16 x, y; |
| 643 | 676 | ||
| 644 | if (applesmc_read_motion_sensor(SENSOR_X, &x)) | 677 | if (applesmc_read_s16(MOTION_SENSOR_X_KEY, &x)) |
| 645 | return; | 678 | return; |
| 646 | if (applesmc_read_motion_sensor(SENSOR_Y, &y)) | 679 | if (applesmc_read_s16(MOTION_SENSOR_Y_KEY, &y)) |
| 647 | return; | 680 | return; |
| 648 | 681 | ||
| 649 | x = -x; | 682 | x = -x; |
| @@ -666,13 +699,13 @@ static ssize_t applesmc_position_show(struct device *dev, | |||
| 666 | int ret; | 699 | int ret; |
| 667 | s16 x, y, z; | 700 | s16 x, y, z; |
| 668 | 701 | ||
| 669 | ret = applesmc_read_motion_sensor(SENSOR_X, &x); | 702 | ret = applesmc_read_s16(MOTION_SENSOR_X_KEY, &x); |
| 670 | if (ret) | 703 | if (ret) |
| 671 | goto out; | 704 | goto out; |
| 672 | ret = applesmc_read_motion_sensor(SENSOR_Y, &y); | 705 | ret = applesmc_read_s16(MOTION_SENSOR_Y_KEY, &y); |
| 673 | if (ret) | 706 | if (ret) |
| 674 | goto out; | 707 | goto out; |
| 675 | ret = applesmc_read_motion_sensor(SENSOR_Z, &z); | 708 | ret = applesmc_read_s16(MOTION_SENSOR_Z_KEY, &z); |
| 676 | if (ret) | 709 | if (ret) |
| 677 | goto out; | 710 | goto out; |
| 678 | 711 | ||
| @@ -725,44 +758,27 @@ out: | |||
| 725 | static ssize_t applesmc_show_sensor_label(struct device *dev, | 758 | static ssize_t applesmc_show_sensor_label(struct device *dev, |
| 726 | struct device_attribute *devattr, char *sysfsbuf) | 759 | struct device_attribute *devattr, char *sysfsbuf) |
| 727 | { | 760 | { |
| 728 | int index = smcreg.temp_begin + to_index(devattr); | 761 | const char *key = smcreg.index[to_index(devattr)]; |
| 729 | const struct applesmc_entry *entry; | ||
| 730 | |||
| 731 | entry = applesmc_get_entry_by_index(index); | ||
| 732 | if (IS_ERR(entry)) | ||
| 733 | return PTR_ERR(entry); | ||
| 734 | 762 | ||
| 735 | return snprintf(sysfsbuf, PAGE_SIZE, "%s\n", entry->key); | 763 | return snprintf(sysfsbuf, PAGE_SIZE, "%s\n", key); |
| 736 | } | 764 | } |
| 737 | 765 | ||
| 738 | /* Displays degree Celsius * 1000 */ | 766 | /* Displays degree Celsius * 1000 */ |
| 739 | static ssize_t applesmc_show_temperature(struct device *dev, | 767 | static ssize_t applesmc_show_temperature(struct device *dev, |
| 740 | struct device_attribute *devattr, char *sysfsbuf) | 768 | struct device_attribute *devattr, char *sysfsbuf) |
| 741 | { | 769 | { |
| 742 | int index = smcreg.temp_begin + to_index(devattr); | 770 | const char *key = smcreg.index[to_index(devattr)]; |
| 743 | const struct applesmc_entry *entry; | ||
| 744 | int ret; | 771 | int ret; |
| 745 | u8 buffer[2]; | 772 | s16 value; |
| 746 | unsigned int temp; | 773 | int temp; |
| 747 | 774 | ||
| 748 | entry = applesmc_get_entry_by_index(index); | 775 | ret = applesmc_read_s16(key, &value); |
| 749 | if (IS_ERR(entry)) | ||
| 750 | return PTR_ERR(entry); | ||
| 751 | if (entry->len > 2) | ||
| 752 | return -EINVAL; | ||
| 753 | |||
| 754 | ret = applesmc_read_entry(entry, buffer, entry->len); | ||
| 755 | if (ret) | 776 | if (ret) |
| 756 | return ret; | 777 | return ret; |
| 757 | 778 | ||
| 758 | if (entry->len == 2) { | 779 | temp = 250 * (value >> 6); |
| 759 | temp = buffer[0] * 1000; | ||
| 760 | temp += (buffer[1] >> 6) * 250; | ||
| 761 | } else { | ||
| 762 | temp = buffer[0] * 4000; | ||
| 763 | } | ||
| 764 | 780 | ||
| 765 | return snprintf(sysfsbuf, PAGE_SIZE, "%u\n", temp); | 781 | return snprintf(sysfsbuf, PAGE_SIZE, "%d\n", temp); |
| 766 | } | 782 | } |
| 767 | 783 | ||
| 768 | static ssize_t applesmc_show_fan_speed(struct device *dev, | 784 | static ssize_t applesmc_show_fan_speed(struct device *dev, |
| @@ -789,14 +805,12 @@ static ssize_t applesmc_store_fan_speed(struct device *dev, | |||
| 789 | const char *sysfsbuf, size_t count) | 805 | const char *sysfsbuf, size_t count) |
| 790 | { | 806 | { |
| 791 | int ret; | 807 | int ret; |
| 792 | u32 speed; | 808 | unsigned long speed; |
| 793 | char newkey[5]; | 809 | char newkey[5]; |
| 794 | u8 buffer[2]; | 810 | u8 buffer[2]; |
| 795 | 811 | ||
| 796 | speed = simple_strtoul(sysfsbuf, NULL, 10); | 812 | if (kstrtoul(sysfsbuf, 10, &speed) < 0 || speed >= 0x4000) |
| 797 | 813 | return -EINVAL; /* Bigger than a 14-bit value */ | |
| 798 | if (speed > 0x4000) /* Bigger than a 14-bit value */ | ||
| 799 | return -EINVAL; | ||
| 800 | 814 | ||
| 801 | sprintf(newkey, fan_speed_fmt[to_option(attr)], to_index(attr)); | 815 | sprintf(newkey, fan_speed_fmt[to_option(attr)], to_index(attr)); |
| 802 | 816 | ||
| @@ -832,10 +846,11 @@ static ssize_t applesmc_store_fan_manual(struct device *dev, | |||
| 832 | { | 846 | { |
| 833 | int ret; | 847 | int ret; |
| 834 | u8 buffer[2]; | 848 | u8 buffer[2]; |
| 835 | u32 input; | 849 | unsigned long input; |
| 836 | u16 val; | 850 | u16 val; |
| 837 | 851 | ||
| 838 | input = simple_strtoul(sysfsbuf, NULL, 10); | 852 | if (kstrtoul(sysfsbuf, 10, &input) < 0) |
| 853 | return -EINVAL; | ||
| 839 | 854 | ||
| 840 | ret = applesmc_read_key(FANS_MANUAL, buffer, 2); | 855 | ret = applesmc_read_key(FANS_MANUAL, buffer, 2); |
| 841 | val = (buffer[0] << 8 | buffer[1]); | 856 | val = (buffer[0] << 8 | buffer[1]); |
| @@ -987,8 +1002,13 @@ static ssize_t applesmc_key_at_index_show(struct device *dev, | |||
| 987 | static ssize_t applesmc_key_at_index_store(struct device *dev, | 1002 | static ssize_t applesmc_key_at_index_store(struct device *dev, |
| 988 | struct device_attribute *attr, const char *sysfsbuf, size_t count) | 1003 | struct device_attribute *attr, const char *sysfsbuf, size_t count) |
| 989 | { | 1004 | { |
| 990 | key_at_index = simple_strtoul(sysfsbuf, NULL, 10); | 1005 | unsigned long newkey; |
| 991 | 1006 | ||
| 1007 | if (kstrtoul(sysfsbuf, 10, &newkey) < 0 | ||
| 1008 | || newkey >= smcreg.key_count) | ||
| 1009 | return -EINVAL; | ||
| 1010 | |||
| 1011 | key_at_index = newkey; | ||
| 992 | return count; | 1012 | return count; |
| 993 | } | 1013 | } |
| 994 | 1014 | ||
| @@ -1079,6 +1099,7 @@ static int applesmc_create_nodes(struct applesmc_node_group *groups, int num) | |||
| 1079 | node->sda.dev_attr.show = grp->show; | 1099 | node->sda.dev_attr.show = grp->show; |
| 1080 | node->sda.dev_attr.store = grp->store; | 1100 | node->sda.dev_attr.store = grp->store; |
| 1081 | attr = &node->sda.dev_attr.attr; | 1101 | attr = &node->sda.dev_attr.attr; |
| 1102 | sysfs_attr_init(attr); | ||
| 1082 | attr->name = node->name; | 1103 | attr->name = node->name; |
| 1083 | attr->mode = S_IRUGO | (grp->store ? S_IWUSR : 0); | 1104 | attr->mode = S_IRUGO | (grp->store ? S_IWUSR : 0); |
| 1084 | ret = sysfs_create_file(&pdev->dev.kobj, attr); | 1105 | ret = sysfs_create_file(&pdev->dev.kobj, attr); |
| @@ -1195,32 +1216,34 @@ static int applesmc_dmi_match(const struct dmi_system_id *id) | |||
| 1195 | return 1; | 1216 | return 1; |
| 1196 | } | 1217 | } |
| 1197 | 1218 | ||
| 1198 | /* Note that DMI_MATCH(...,"MacBook") will match "MacBookPro1,1". | 1219 | /* |
| 1199 | * So we need to put "Apple MacBook Pro" before "Apple MacBook". */ | 1220 | * Note that DMI_MATCH(...,"MacBook") will match "MacBookPro1,1". |
| 1221 | * So we need to put "Apple MacBook Pro" before "Apple MacBook". | ||
| 1222 | */ | ||
| 1200 | static __initdata struct dmi_system_id applesmc_whitelist[] = { | 1223 | static __initdata struct dmi_system_id applesmc_whitelist[] = { |
| 1201 | { applesmc_dmi_match, "Apple MacBook Air", { | 1224 | { applesmc_dmi_match, "Apple MacBook Air", { |
| 1202 | DMI_MATCH(DMI_BOARD_VENDOR, "Apple"), | 1225 | DMI_MATCH(DMI_BOARD_VENDOR, "Apple"), |
| 1203 | DMI_MATCH(DMI_PRODUCT_NAME, "MacBookAir") }, | 1226 | DMI_MATCH(DMI_PRODUCT_NAME, "MacBookAir") }, |
| 1204 | }, | 1227 | }, |
| 1205 | { applesmc_dmi_match, "Apple MacBook Pro", { | 1228 | { applesmc_dmi_match, "Apple MacBook Pro", { |
| 1206 | DMI_MATCH(DMI_BOARD_VENDOR,"Apple"), | 1229 | DMI_MATCH(DMI_BOARD_VENDOR, "Apple"), |
| 1207 | DMI_MATCH(DMI_PRODUCT_NAME,"MacBookPro") }, | 1230 | DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro") }, |
| 1208 | }, | 1231 | }, |
| 1209 | { applesmc_dmi_match, "Apple MacBook", { | 1232 | { applesmc_dmi_match, "Apple MacBook", { |
| 1210 | DMI_MATCH(DMI_BOARD_VENDOR,"Apple"), | 1233 | DMI_MATCH(DMI_BOARD_VENDOR, "Apple"), |
| 1211 | DMI_MATCH(DMI_PRODUCT_NAME,"MacBook") }, | 1234 | DMI_MATCH(DMI_PRODUCT_NAME, "MacBook") }, |
| 1212 | }, | 1235 | }, |
| 1213 | { applesmc_dmi_match, "Apple Macmini", { | 1236 | { applesmc_dmi_match, "Apple Macmini", { |
| 1214 | DMI_MATCH(DMI_BOARD_VENDOR,"Apple"), | 1237 | DMI_MATCH(DMI_BOARD_VENDOR, "Apple"), |
| 1215 | DMI_MATCH(DMI_PRODUCT_NAME,"Macmini") }, | 1238 | DMI_MATCH(DMI_PRODUCT_NAME, "Macmini") }, |
| 1216 | }, | 1239 | }, |
| 1217 | { applesmc_dmi_match, "Apple MacPro", { | 1240 | { applesmc_dmi_match, "Apple MacPro", { |
| 1218 | DMI_MATCH(DMI_BOARD_VENDOR, "Apple"), | 1241 | DMI_MATCH(DMI_BOARD_VENDOR, "Apple"), |
| 1219 | DMI_MATCH(DMI_PRODUCT_NAME, "MacPro") }, | 1242 | DMI_MATCH(DMI_PRODUCT_NAME, "MacPro") }, |
| 1220 | }, | 1243 | }, |
| 1221 | { applesmc_dmi_match, "Apple iMac", { | 1244 | { applesmc_dmi_match, "Apple iMac", { |
| 1222 | DMI_MATCH(DMI_BOARD_VENDOR,"Apple"), | 1245 | DMI_MATCH(DMI_BOARD_VENDOR, "Apple"), |
| 1223 | DMI_MATCH(DMI_PRODUCT_NAME,"iMac") }, | 1246 | DMI_MATCH(DMI_PRODUCT_NAME, "iMac") }, |
| 1224 | }, | 1247 | }, |
| 1225 | { .ident = NULL } | 1248 | { .ident = NULL } |
| 1226 | }; | 1249 | }; |
| @@ -1265,7 +1288,7 @@ static int __init applesmc_init(void) | |||
| 1265 | if (ret) | 1288 | if (ret) |
| 1266 | goto out_info; | 1289 | goto out_info; |
| 1267 | 1290 | ||
| 1268 | ret = applesmc_create_nodes(temp_group, smcreg.temp_count); | 1291 | ret = applesmc_create_nodes(temp_group, smcreg.index_count); |
| 1269 | if (ret) | 1292 | if (ret) |
| 1270 | goto out_fans; | 1293 | goto out_fans; |
| 1271 | 1294 | ||
