Merge master.kernel.org:/pub/scm/linux/kernel/git/gregkh/i2c-2.6

+779 -18
+7
MAINTAINERS
··· 964 964 W: http://www.lm-sensors.nu/ 965 965 S: Maintained 966 966 967 + HARD DRIVE ACTIVE PROTECTION SYSTEM (HDAPS) DRIVER 968 + P: Robert Love 969 + M: rlove@rlove.org 970 + M: linux-kernel@vger.kernel.org 971 + W: http://www.kernel.org/pub/linux/kernel/people/rml/hdaps/ 972 + S: Maintained 973 + 967 974 HARMONY SOUND DRIVER 968 975 P: Kyle McMartin 969 976 M: kyle@parisc-linux.org
+17
drivers/hwmon/Kconfig
··· 411 411 This driver can also be built as a module. If so, the module 412 412 will be called w83627ehf. 413 413 414 + config SENSORS_HDAPS 415 + tristate "IBM Hard Drive Active Protection System (hdaps)" 416 + depends on HWMON && INPUT && X86 417 + default n 418 + help 419 + This driver provides support for the IBM Hard Drive Active Protection 420 + System (hdaps), which provides an accelerometer and other misc. data. 421 + Supported laptops include the IBM ThinkPad T41, T42, T43, and R51. 422 + The accelerometer data is readable via sysfs. 423 + 424 + This driver also provides an input class device, allowing the 425 + laptop to act as a pinball machine-esque mouse. This is off by 426 + default but enabled via sysfs or the module parameter "mousedev". 427 + 428 + Say Y here if you have an applicable laptop and want to experience 429 + the awesome power of hdaps. 430 + 414 431 config HWMON_DEBUG_CHIP 415 432 bool "Hardware Monitoring Chip debugging messages" 416 433 depends on HWMON
+1
drivers/hwmon/Makefile
··· 22 22 obj-$(CONFIG_SENSORS_FSCPOS) += fscpos.o 23 23 obj-$(CONFIG_SENSORS_GL518SM) += gl518sm.o 24 24 obj-$(CONFIG_SENSORS_GL520SM) += gl520sm.o 25 + obj-$(CONFIG_SENSORS_HDAPS) += hdaps.o 25 26 obj-$(CONFIG_SENSORS_IT87) += it87.o 26 27 obj-$(CONFIG_SENSORS_LM63) += lm63.o 27 28 obj-$(CONFIG_SENSORS_LM75) += lm75.o
+739
drivers/hwmon/hdaps.c
··· 1 + /* 2 + * drivers/hwmon/hdaps.c - driver for IBM's Hard Drive Active Protection System 3 + * 4 + * Copyright (C) 2005 Robert Love <rml@novell.com> 5 + * Copyright (C) 2005 Jesper Juhl <jesper.juhl@gmail.com> 6 + * 7 + * The HardDisk Active Protection System (hdaps) is present in the IBM ThinkPad 8 + * T41, T42, T43, R51, and X40, at least. It provides a basic two-axis 9 + * accelerometer and other data, such as the device's temperature. 10 + * 11 + * Based on the document by Mark A. Smith available at 12 + * http://www.almaden.ibm.com/cs/people/marksmith/tpaps.html and a lot of trial 13 + * and error. 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/device.h> 31 + #include <linux/input.h> 32 + #include <linux/kernel.h> 33 + #include <linux/module.h> 34 + #include <linux/timer.h> 35 + #include <linux/dmi.h> 36 + #include <asm/io.h> 37 + 38 + #define HDAPS_LOW_PORT 0x1600 /* first port used by hdaps */ 39 + #define HDAPS_NR_PORTS 0x30 /* 0x1600 - 0x162f */ 40 + 41 + #define STATE_FRESH 0x50 /* accelerometer data is fresh */ 42 + 43 + #define REFRESH_ASYNC 0x00 /* do asynchronous refresh */ 44 + #define REFRESH_SYNC 0x01 /* do synchronous refresh */ 45 + 46 + #define HDAPS_PORT_STATE 0x1611 /* device state */ 47 + #define HDAPS_PORT_YPOS 0x1612 /* y-axis position */ 48 + #define HDAPS_PORT_XPOS 0x1614 /* x-axis position */ 49 + #define HDAPS_PORT_TEMP1 0x1616 /* device temperature, in celcius */ 50 + #define HDAPS_PORT_YVAR 0x1617 /* y-axis variance (what is this?) */ 51 + #define HDAPS_PORT_XVAR 0x1619 /* x-axis variance (what is this?) */ 52 + #define HDAPS_PORT_TEMP2 0x161b /* device temperature (again?) */ 53 + #define HDAPS_PORT_UNKNOWN 0x161c /* what is this? */ 54 + #define HDAPS_PORT_KMACT 0x161d /* keyboard or mouse activity */ 55 + 56 + #define HDAPS_READ_MASK 0xff /* some reads have the low 8 bits set */ 57 + 58 + #define KEYBD_MASK 0x20 /* set if keyboard activity */ 59 + #define MOUSE_MASK 0x40 /* set if mouse activity */ 60 + #define KEYBD_ISSET(n) (!! (n & KEYBD_MASK)) /* keyboard used? */ 61 + #define MOUSE_ISSET(n) (!! (n & MOUSE_MASK)) /* mouse used? */ 62 + 63 + #define INIT_TIMEOUT_MSECS 4000 /* wait up to 4s for device init ... */ 64 + #define INIT_WAIT_MSECS 200 /* ... in 200ms increments */ 65 + 66 + static struct platform_device *pdev; 67 + static struct input_dev hdaps_idev; 68 + static struct timer_list hdaps_timer; 69 + static unsigned int hdaps_mousedev_threshold = 4; 70 + static unsigned long hdaps_poll_ms = 50; 71 + static unsigned int hdaps_mousedev; 72 + static unsigned int hdaps_invert; 73 + static u8 km_activity; 74 + static int rest_x; 75 + static int rest_y; 76 + 77 + static DECLARE_MUTEX(hdaps_sem); 78 + 79 + /* 80 + * __get_latch - Get the value from a given port. Callers must hold hdaps_sem. 81 + */ 82 + static inline u8 __get_latch(u16 port) 83 + { 84 + return inb(port) & HDAPS_READ_MASK; 85 + } 86 + 87 + /* 88 + * __check_latch - Check a port latch for a given value. Callers must hold 89 + * hdaps_sem. Returns zero if the port contains the given value. 90 + */ 91 + static inline unsigned int __check_latch(u16 port, u8 val) 92 + { 93 + if (__get_latch(port) == val) 94 + return 0; 95 + return -EINVAL; 96 + } 97 + 98 + /* 99 + * __wait_latch - Wait up to 100us for a port latch to get a certain value, 100 + * returning zero if the value is obtained. Callers must hold hdaps_sem. 101 + */ 102 + static unsigned int __wait_latch(u16 port, u8 val) 103 + { 104 + unsigned int i; 105 + 106 + for (i = 0; i < 20; i++) { 107 + if (!__check_latch(port, val)) 108 + return 0; 109 + udelay(5); 110 + } 111 + 112 + return -EINVAL; 113 + } 114 + 115 + /* 116 + * __device_refresh - Request a refresh from the accelerometer. 117 + * 118 + * If sync is REFRESH_SYNC, we perform a synchronous refresh and will wait. 119 + * Returns zero if successful and nonzero on error. 120 + * 121 + * If sync is REFRESH_ASYNC, we merely kick off a new refresh if the device is 122 + * not up-to-date. Always returns zero. 123 + * 124 + * Callers must hold hdaps_sem. 125 + */ 126 + static int __device_refresh(unsigned int sync) 127 + { 128 + u8 state; 129 + 130 + udelay(100); 131 + 132 + state = inb(0x1604); 133 + if (state == STATE_FRESH) 134 + return 0; 135 + 136 + outb(0x11, 0x1610); 137 + outb(0x01, 0x161f); 138 + if (sync == REFRESH_ASYNC) 139 + return 0; 140 + 141 + return __wait_latch(0x1604, STATE_FRESH); 142 + } 143 + 144 + /* 145 + * __device_complete - Indicate to the accelerometer that we are done reading 146 + * data, and then initiate an async refresh. Callers must hold hdaps_sem. 147 + */ 148 + static inline void __device_complete(void) 149 + { 150 + inb(0x161f); 151 + inb(0x1604); 152 + __device_refresh(REFRESH_ASYNC); 153 + } 154 + 155 + static int __hdaps_readb_one(unsigned int port, u8 *val) 156 + { 157 + /* do a sync refresh -- we need to be sure that we read fresh data */ 158 + if (__device_refresh(REFRESH_SYNC)) 159 + return -EIO; 160 + 161 + *val = inb(port); 162 + __device_complete(); 163 + 164 + return 0; 165 + } 166 + 167 + /* 168 + * hdaps_readb_one - reads a byte from a single I/O port, placing the value in 169 + * the given pointer. Returns zero on success or a negative error on failure. 170 + * Can sleep. 171 + */ 172 + static int hdaps_readb_one(unsigned int port, u8 *val) 173 + { 174 + int ret; 175 + 176 + down(&hdaps_sem); 177 + ret = __hdaps_readb_one(port, val); 178 + up(&hdaps_sem); 179 + 180 + return ret; 181 + } 182 + 183 + static int __hdaps_read_pair(unsigned int port1, unsigned int port2, 184 + int *x, int *y) 185 + { 186 + /* do a sync refresh -- we need to be sure that we read fresh data */ 187 + if (__device_refresh(REFRESH_SYNC)) 188 + return -EIO; 189 + 190 + *y = inw(port2); 191 + *x = inw(port1); 192 + km_activity = inb(HDAPS_PORT_KMACT); 193 + __device_complete(); 194 + 195 + /* if hdaps_invert is set, negate the two values */ 196 + if (hdaps_invert) { 197 + *x = -*x; 198 + *y = -*y; 199 + } 200 + 201 + return 0; 202 + } 203 + 204 + /* 205 + * hdaps_read_pair - reads the values from a pair of ports, placing the values 206 + * in the given pointers. Returns zero on success. Can sleep. 207 + */ 208 + static int hdaps_read_pair(unsigned int port1, unsigned int port2, 209 + int *val1, int *val2) 210 + { 211 + int ret; 212 + 213 + down(&hdaps_sem); 214 + ret = __hdaps_read_pair(port1, port2, val1, val2); 215 + up(&hdaps_sem); 216 + 217 + return ret; 218 + } 219 + 220 + /* initialize the accelerometer */ 221 + static int hdaps_device_init(void) 222 + { 223 + unsigned int total_msecs = INIT_TIMEOUT_MSECS; 224 + int ret = -ENXIO; 225 + 226 + down(&hdaps_sem); 227 + 228 + outb(0x13, 0x1610); 229 + outb(0x01, 0x161f); 230 + if (__wait_latch(0x161f, 0x00)) 231 + goto out; 232 + 233 + /* 234 + * The 0x03 value appears to only work on some thinkpads, such as the 235 + * T42p. Others return 0x01. 236 + * 237 + * The 0x02 value occurs when the chip has been previously initialized. 238 + */ 239 + if (__check_latch(0x1611, 0x03) && 240 + __check_latch(0x1611, 0x02) && 241 + __check_latch(0x1611, 0x01)) 242 + goto out; 243 + 244 + printk(KERN_DEBUG "hdaps: initial latch check good (0x%02x).\n", 245 + __get_latch(0x1611)); 246 + 247 + outb(0x17, 0x1610); 248 + outb(0x81, 0x1611); 249 + outb(0x01, 0x161f); 250 + if (__wait_latch(0x161f, 0x00)) 251 + goto out; 252 + if (__wait_latch(0x1611, 0x00)) 253 + goto out; 254 + if (__wait_latch(0x1612, 0x60)) 255 + goto out; 256 + if (__wait_latch(0x1613, 0x00)) 257 + goto out; 258 + outb(0x14, 0x1610); 259 + outb(0x01, 0x1611); 260 + outb(0x01, 0x161f); 261 + if (__wait_latch(0x161f, 0x00)) 262 + goto out; 263 + outb(0x10, 0x1610); 264 + outb(0xc8, 0x1611); 265 + outb(0x00, 0x1612); 266 + outb(0x02, 0x1613); 267 + outb(0x01, 0x161f); 268 + if (__wait_latch(0x161f, 0x00)) 269 + goto out; 270 + if (__device_refresh(REFRESH_SYNC)) 271 + goto out; 272 + if (__wait_latch(0x1611, 0x00)) 273 + goto out; 274 + 275 + /* we have done our dance, now let's wait for the applause */ 276 + while (total_msecs > 0) { 277 + u8 ignored; 278 + 279 + /* a read of the device helps push it into action */ 280 + __hdaps_readb_one(HDAPS_PORT_UNKNOWN, &ignored); 281 + if (!__wait_latch(0x1611, 0x02)) { 282 + ret = 0; 283 + break; 284 + } 285 + 286 + msleep(INIT_WAIT_MSECS); 287 + total_msecs -= INIT_WAIT_MSECS; 288 + } 289 + 290 + out: 291 + up(&hdaps_sem); 292 + return ret; 293 + } 294 + 295 + 296 + /* Input class stuff */ 297 + 298 + /* 299 + * hdaps_calibrate - Zero out our "resting" values. Callers must hold hdaps_sem. 300 + */ 301 + static void hdaps_calibrate(void) 302 + { 303 + int x, y; 304 + 305 + if (__hdaps_read_pair(HDAPS_PORT_XPOS, HDAPS_PORT_YPOS, &x, &y)) 306 + return; 307 + 308 + rest_x = x; 309 + rest_y = y; 310 + } 311 + 312 + static void hdaps_mousedev_poll(unsigned long unused) 313 + { 314 + int x, y; 315 + 316 + /* Cannot sleep. Try nonblockingly. If we fail, try again later. */ 317 + if (down_trylock(&hdaps_sem)) { 318 + mod_timer(&hdaps_timer,jiffies+msecs_to_jiffies(hdaps_poll_ms)); 319 + return; 320 + } 321 + 322 + if (__hdaps_read_pair(HDAPS_PORT_XPOS, HDAPS_PORT_YPOS, &x, &y)) 323 + goto out; 324 + 325 + x -= rest_x; 326 + y -= rest_y; 327 + if (abs(x) > hdaps_mousedev_threshold) 328 + input_report_rel(&hdaps_idev, REL_X, x); 329 + if (abs(y) > hdaps_mousedev_threshold) 330 + input_report_rel(&hdaps_idev, REL_Y, y); 331 + input_sync(&hdaps_idev); 332 + 333 + mod_timer(&hdaps_timer, jiffies + msecs_to_jiffies(hdaps_poll_ms)); 334 + 335 + out: 336 + up(&hdaps_sem); 337 + } 338 + 339 + /* 340 + * hdaps_mousedev_enable - enable the input class device. Can sleep. 341 + */ 342 + static void hdaps_mousedev_enable(void) 343 + { 344 + down(&hdaps_sem); 345 + 346 + /* calibrate the device before enabling */ 347 + hdaps_calibrate(); 348 + 349 + /* initialize the input class */ 350 + init_input_dev(&hdaps_idev); 351 + hdaps_idev.dev = &pdev->dev; 352 + hdaps_idev.evbit[0] = BIT(EV_KEY) | BIT(EV_REL); 353 + hdaps_idev.relbit[0] = BIT(REL_X) | BIT(REL_Y); 354 + hdaps_idev.keybit[LONG(BTN_LEFT)] = BIT(BTN_LEFT); 355 + input_register_device(&hdaps_idev); 356 + 357 + /* start up our timer */ 358 + init_timer(&hdaps_timer); 359 + hdaps_timer.function = hdaps_mousedev_poll; 360 + hdaps_timer.expires = jiffies + msecs_to_jiffies(hdaps_poll_ms); 361 + add_timer(&hdaps_timer); 362 + 363 + hdaps_mousedev = 1; 364 + 365 + up(&hdaps_sem); 366 + 367 + printk(KERN_INFO "hdaps: input device enabled.\n"); 368 + } 369 + 370 + /* 371 + * hdaps_mousedev_disable - disable the input class device. Caller must hold 372 + * hdaps_sem. 373 + */ 374 + static void hdaps_mousedev_disable(void) 375 + { 376 + down(&hdaps_sem); 377 + if (hdaps_mousedev) { 378 + hdaps_mousedev = 0; 379 + del_timer_sync(&hdaps_timer); 380 + input_unregister_device(&hdaps_idev); 381 + } 382 + up(&hdaps_sem); 383 + } 384 + 385 + 386 + /* Device model stuff */ 387 + 388 + static int hdaps_probe(struct device *dev) 389 + { 390 + int ret; 391 + 392 + ret = hdaps_device_init(); 393 + if (ret) 394 + return ret; 395 + 396 + printk(KERN_INFO "hdaps: device successfully initialized.\n"); 397 + return 0; 398 + } 399 + 400 + static int hdaps_resume(struct device *dev, u32 level) 401 + { 402 + if (level == RESUME_ENABLE) 403 + return hdaps_device_init(); 404 + return 0; 405 + } 406 + 407 + static struct device_driver hdaps_driver = { 408 + .name = "hdaps", 409 + .bus = &platform_bus_type, 410 + .owner = THIS_MODULE, 411 + .probe = hdaps_probe, 412 + .resume = hdaps_resume 413 + }; 414 + 415 + 416 + /* Sysfs Files */ 417 + 418 + static ssize_t hdaps_position_show(struct device *dev, 419 + struct device_attribute *attr, char *buf) 420 + { 421 + int ret, x, y; 422 + 423 + ret = hdaps_read_pair(HDAPS_PORT_XPOS, HDAPS_PORT_YPOS, &x, &y); 424 + if (ret) 425 + return ret; 426 + 427 + return sprintf(buf, "(%d,%d)\n", x, y); 428 + } 429 + 430 + static ssize_t hdaps_variance_show(struct device *dev, 431 + struct device_attribute *attr, char *buf) 432 + { 433 + int ret, x, y; 434 + 435 + ret = hdaps_read_pair(HDAPS_PORT_XVAR, HDAPS_PORT_YVAR, &x, &y); 436 + if (ret) 437 + return ret; 438 + 439 + return sprintf(buf, "(%d,%d)\n", x, y); 440 + } 441 + 442 + static ssize_t hdaps_temp1_show(struct device *dev, 443 + struct device_attribute *attr, char *buf) 444 + { 445 + u8 temp; 446 + int ret; 447 + 448 + ret = hdaps_readb_one(HDAPS_PORT_TEMP1, &temp); 449 + if (ret < 0) 450 + return ret; 451 + 452 + return sprintf(buf, "%u\n", temp); 453 + } 454 + 455 + static ssize_t hdaps_temp2_show(struct device *dev, 456 + struct device_attribute *attr, char *buf) 457 + { 458 + u8 temp; 459 + int ret; 460 + 461 + ret = hdaps_readb_one(HDAPS_PORT_TEMP2, &temp); 462 + if (ret < 0) 463 + return ret; 464 + 465 + return sprintf(buf, "%u\n", temp); 466 + } 467 + 468 + static ssize_t hdaps_keyboard_activity_show(struct device *dev, 469 + struct device_attribute *attr, 470 + char *buf) 471 + { 472 + return sprintf(buf, "%u\n", KEYBD_ISSET(km_activity)); 473 + } 474 + 475 + static ssize_t hdaps_mouse_activity_show(struct device *dev, 476 + struct device_attribute *attr, 477 + char *buf) 478 + { 479 + return sprintf(buf, "%u\n", MOUSE_ISSET(km_activity)); 480 + } 481 + 482 + static ssize_t hdaps_calibrate_show(struct device *dev, 483 + struct device_attribute *attr, char *buf) 484 + { 485 + return sprintf(buf, "(%d,%d)\n", rest_x, rest_y); 486 + } 487 + 488 + static ssize_t hdaps_calibrate_store(struct device *dev, 489 + struct device_attribute *attr, 490 + const char *buf, size_t count) 491 + { 492 + down(&hdaps_sem); 493 + hdaps_calibrate(); 494 + up(&hdaps_sem); 495 + 496 + return count; 497 + } 498 + 499 + static ssize_t hdaps_invert_show(struct device *dev, 500 + struct device_attribute *attr, char *buf) 501 + { 502 + return sprintf(buf, "%u\n", hdaps_invert); 503 + } 504 + 505 + static ssize_t hdaps_invert_store(struct device *dev, 506 + struct device_attribute *attr, 507 + const char *buf, size_t count) 508 + { 509 + int invert; 510 + 511 + if (sscanf(buf, "%d", &invert) != 1 || (invert != 1 && invert != 0)) 512 + return -EINVAL; 513 + 514 + hdaps_invert = invert; 515 + hdaps_calibrate(); 516 + 517 + return count; 518 + } 519 + 520 + static ssize_t hdaps_mousedev_show(struct device *dev, 521 + struct device_attribute *attr, char *buf) 522 + { 523 + return sprintf(buf, "%d\n", hdaps_mousedev); 524 + } 525 + 526 + static ssize_t hdaps_mousedev_store(struct device *dev, 527 + struct device_attribute *attr, 528 + const char *buf, size_t count) 529 + { 530 + int enable; 531 + 532 + if (sscanf(buf, "%d", &enable) != 1) 533 + return -EINVAL; 534 + 535 + if (enable == 1) 536 + hdaps_mousedev_enable(); 537 + else if (enable == 0) 538 + hdaps_mousedev_disable(); 539 + else 540 + return -EINVAL; 541 + 542 + return count; 543 + } 544 + 545 + static ssize_t hdaps_poll_show(struct device *dev, 546 + struct device_attribute *attr, char *buf) 547 + { 548 + return sprintf(buf, "%lu\n", hdaps_poll_ms); 549 + } 550 + 551 + static ssize_t hdaps_poll_store(struct device *dev, 552 + struct device_attribute *attr, 553 + const char *buf, size_t count) 554 + { 555 + unsigned int poll; 556 + 557 + if (sscanf(buf, "%u", &poll) != 1 || poll == 0) 558 + return -EINVAL; 559 + hdaps_poll_ms = poll; 560 + 561 + return count; 562 + } 563 + 564 + static ssize_t hdaps_threshold_show(struct device *dev, 565 + struct device_attribute *attr, char *buf) 566 + { 567 + return sprintf(buf, "%u\n", hdaps_mousedev_threshold); 568 + } 569 + 570 + static ssize_t hdaps_threshold_store(struct device *dev, 571 + struct device_attribute *attr, 572 + const char *buf, size_t count) 573 + { 574 + unsigned int threshold; 575 + 576 + if (sscanf(buf, "%u", &threshold) != 1 || threshold == 0) 577 + return -EINVAL; 578 + hdaps_mousedev_threshold = threshold; 579 + 580 + return count; 581 + } 582 + 583 + static DEVICE_ATTR(position, 0444, hdaps_position_show, NULL); 584 + static DEVICE_ATTR(variance, 0444, hdaps_variance_show, NULL); 585 + static DEVICE_ATTR(temp1, 0444, hdaps_temp1_show, NULL); 586 + static DEVICE_ATTR(temp2, 0444, hdaps_temp2_show, NULL); 587 + static DEVICE_ATTR(keyboard_activity, 0444, hdaps_keyboard_activity_show, NULL); 588 + static DEVICE_ATTR(mouse_activity, 0444, hdaps_mouse_activity_show, NULL); 589 + static DEVICE_ATTR(calibrate, 0644, hdaps_calibrate_show,hdaps_calibrate_store); 590 + static DEVICE_ATTR(invert, 0644, hdaps_invert_show, hdaps_invert_store); 591 + static DEVICE_ATTR(mousedev, 0644, hdaps_mousedev_show, hdaps_mousedev_store); 592 + static DEVICE_ATTR(mousedev_poll_ms, 0644, hdaps_poll_show, hdaps_poll_store); 593 + static DEVICE_ATTR(mousedev_threshold, 0644, hdaps_threshold_show, 594 + hdaps_threshold_store); 595 + 596 + static struct attribute *hdaps_attributes[] = { 597 + &dev_attr_position.attr, 598 + &dev_attr_variance.attr, 599 + &dev_attr_temp1.attr, 600 + &dev_attr_temp2.attr, 601 + &dev_attr_keyboard_activity.attr, 602 + &dev_attr_mouse_activity.attr, 603 + &dev_attr_calibrate.attr, 604 + &dev_attr_mousedev.attr, 605 + &dev_attr_mousedev_threshold.attr, 606 + &dev_attr_mousedev_poll_ms.attr, 607 + &dev_attr_invert.attr, 608 + NULL, 609 + }; 610 + 611 + static struct attribute_group hdaps_attribute_group = { 612 + .attrs = hdaps_attributes, 613 + }; 614 + 615 + 616 + /* Module stuff */ 617 + 618 + /* 619 + * XXX: We should be able to return nonzero and halt the detection process. 620 + * But there is a bug in dmi_check_system() where a nonzero return from the 621 + * first match will result in a return of failure from dmi_check_system(). 622 + * I fixed this; the patch is in 2.6-mm. Once in Linus's tree we can make 623 + * hdaps_dmi_match_invert() return hdaps_dmi_match(), which in turn returns 1. 624 + */ 625 + static int hdaps_dmi_match(struct dmi_system_id *id) 626 + { 627 + printk(KERN_INFO "hdaps: %s detected.\n", id->ident); 628 + return 0; 629 + } 630 + 631 + static int hdaps_dmi_match_invert(struct dmi_system_id *id) 632 + { 633 + hdaps_invert = 1; 634 + printk(KERN_INFO "hdaps: inverting axis readings.\n"); 635 + return 0; 636 + } 637 + 638 + #define HDAPS_DMI_MATCH_NORMAL(model) { \ 639 + .ident = "IBM " model, \ 640 + .callback = hdaps_dmi_match, \ 641 + .matches = { \ 642 + DMI_MATCH(DMI_BOARD_VENDOR, "IBM"), \ 643 + DMI_MATCH(DMI_PRODUCT_VERSION, model) \ 644 + } \ 645 + } 646 + 647 + #define HDAPS_DMI_MATCH_INVERT(model) { \ 648 + .ident = "IBM " model, \ 649 + .callback = hdaps_dmi_match_invert, \ 650 + .matches = { \ 651 + DMI_MATCH(DMI_BOARD_VENDOR, "IBM"), \ 652 + DMI_MATCH(DMI_PRODUCT_VERSION, model) \ 653 + } \ 654 + } 655 + 656 + static int __init hdaps_init(void) 657 + { 658 + int ret; 659 + 660 + /* Note that DMI_MATCH(...,"ThinkPad T42") will match "ThinkPad T42p" */ 661 + struct dmi_system_id hdaps_whitelist[] = { 662 + HDAPS_DMI_MATCH_INVERT("ThinkPad R50p"), 663 + HDAPS_DMI_MATCH_NORMAL("ThinkPad R50"), 664 + HDAPS_DMI_MATCH_NORMAL("ThinkPad R51"), 665 + HDAPS_DMI_MATCH_INVERT("ThinkPad T41p"), 666 + HDAPS_DMI_MATCH_NORMAL("ThinkPad T41"), 667 + HDAPS_DMI_MATCH_INVERT("ThinkPad T42p"), 668 + HDAPS_DMI_MATCH_NORMAL("ThinkPad T42"), 669 + HDAPS_DMI_MATCH_NORMAL("ThinkPad T43"), 670 + HDAPS_DMI_MATCH_NORMAL("ThinkPad X40"), 671 + { .ident = NULL } 672 + }; 673 + 674 + if (!dmi_check_system(hdaps_whitelist)) { 675 + printk(KERN_WARNING "hdaps: supported laptop not found!\n"); 676 + ret = -ENXIO; 677 + goto out; 678 + } 679 + 680 + if (!request_region(HDAPS_LOW_PORT, HDAPS_NR_PORTS, "hdaps")) { 681 + ret = -ENXIO; 682 + goto out; 683 + } 684 + 685 + ret = driver_register(&hdaps_driver); 686 + if (ret) 687 + goto out_region; 688 + 689 + pdev = platform_device_register_simple("hdaps", -1, NULL, 0); 690 + if (IS_ERR(pdev)) { 691 + ret = PTR_ERR(pdev); 692 + goto out_driver; 693 + } 694 + 695 + ret = sysfs_create_group(&pdev->dev.kobj, &hdaps_attribute_group); 696 + if (ret) 697 + goto out_device; 698 + 699 + if (hdaps_mousedev) 700 + hdaps_mousedev_enable(); 701 + 702 + printk(KERN_INFO "hdaps: driver successfully loaded.\n"); 703 + return 0; 704 + 705 + out_device: 706 + platform_device_unregister(pdev); 707 + out_driver: 708 + driver_unregister(&hdaps_driver); 709 + out_region: 710 + release_region(HDAPS_LOW_PORT, HDAPS_NR_PORTS); 711 + out: 712 + printk(KERN_WARNING "hdaps: driver init failed (ret=%d)!\n", ret); 713 + return ret; 714 + } 715 + 716 + static void __exit hdaps_exit(void) 717 + { 718 + hdaps_mousedev_disable(); 719 + 720 + sysfs_remove_group(&pdev->dev.kobj, &hdaps_attribute_group); 721 + platform_device_unregister(pdev); 722 + driver_unregister(&hdaps_driver); 723 + release_region(HDAPS_LOW_PORT, HDAPS_NR_PORTS); 724 + 725 + printk(KERN_INFO "hdaps: driver unloaded.\n"); 726 + } 727 + 728 + module_init(hdaps_init); 729 + module_exit(hdaps_exit); 730 + 731 + module_param_named(mousedev, hdaps_mousedev, bool, 0); 732 + MODULE_PARM_DESC(mousedev, "enable the input class device"); 733 + 734 + module_param_named(invert, hdaps_invert, bool, 0); 735 + MODULE_PARM_DESC(invert, "invert data along each axis"); 736 + 737 + MODULE_AUTHOR("Robert Love"); 738 + MODULE_DESCRIPTION("IBM Hard Drive Active Protection System (HDAPS) driver"); 739 + MODULE_LICENSE("GPL v2");
-5
drivers/hwmon/sis5595.c
··· 758 758 return -ENODEV; 759 759 } 760 760 761 - if (!address) { 762 - dev_err(&dev->dev,"No SiS 5595 sensors found.\n"); 763 - return -ENODEV; 764 - } 765 - 766 761 s_bridge = pci_dev_get(dev); 767 762 if (i2c_isa_add_driver(&sis5595_driver)) { 768 763 pci_dev_put(s_bridge);
+2 -2
drivers/hwmon/smsc47m1.c
··· 2 2 smsc47m1.c - Part of lm_sensors, Linux kernel modules 3 3 for hardware monitoring 4 4 5 - Supports the SMSC LPC47B27x, LPC47M10x, LPC47M13x and LPC47M14x 6 - Super-I/O chips. 5 + Supports the SMSC LPC47B27x, LPC47M10x, LPC47M13x, LPC47M14x, 6 + LPC47M15x and LPC47M192 Super-I/O chips. 7 7 8 8 Copyright (C) 2002 Mark D. Studebaker <mdsxyz123@yahoo.com> 9 9 Copyright (C) 2004 Jean Delvare <khali@linux-fr.org>
-5
drivers/hwmon/via686a.c
··· 812 812 return -ENODEV; 813 813 } 814 814 815 - if (!address) { 816 - dev_err(&dev->dev, "No Via 686A sensors found.\n"); 817 - return -ENODEV; 818 - } 819 - 820 815 s_bridge = pci_dev_get(dev); 821 816 if (i2c_isa_add_driver(&via686a_driver)) { 822 817 pci_dev_put(s_bridge);
+13 -1
drivers/hwmon/w83627hf.c
··· 64 64 /* Insmod parameters */ 65 65 enum chips { any_chip, w83627hf, w83627thf, w83697hf, w83637hf }; 66 66 67 + static int reset; 68 + module_param(reset, bool, 0); 69 + MODULE_PARM_DESC(reset, "Set to one to reset chip on load"); 70 + 67 71 static int init = 1; 68 72 module_param(init, bool, 0); 69 73 MODULE_PARM_DESC(init, "Set to zero to bypass chip initialization"); ··· 1283 1279 int type = data->type; 1284 1280 u8 tmp; 1285 1281 1286 - if(init) { 1282 + if (reset) { 1283 + /* Resetting the chip has been the default for a long time, 1284 + but repeatedly caused problems (fans going to full 1285 + speed...) so it is now optional. It might even go away if 1286 + nobody reports it as being useful, as I see very little 1287 + reason why this would be needed at all. */ 1288 + dev_info(&client->dev, "If reset=1 solved a problem you were " 1289 + "having, please report!\n"); 1290 + 1287 1291 /* save this register */ 1288 1292 i = w83627hf_read_value(client, W83781D_REG_BEEP_CONFIG); 1289 1293 /* Reset all except Watchdog values and last conversion values
-5
drivers/i2c/busses/i2c-nforce2.c
··· 98 98 #define NVIDIA_SMB_PRTCL_PEC 0x80 99 99 100 100 101 - /* Other settings */ 102 - #define MAX_TIMEOUT 256 103 - 104 - 105 - 106 101 static s32 nforce2_access(struct i2c_adapter *adap, u16 addr, 107 102 unsigned short flags, char read_write, 108 103 u8 command, int size, union i2c_smbus_data *data);