diff options
author | Frank Seidel <frank@f-seidel.de> | 2009-03-30 15:46:41 -0400 |
---|---|---|
committer | Jean Delvare <khali@linux-fr.org> | 2009-03-30 15:46:41 -0400 |
commit | 2b8cf3e8c0638687a7a28a7517e673f855623e3b (patch) | |
tree | 0c549bbfb7d6f195d9e1e7b0412ae96884d311d0 /drivers/hwmon/hdaps.c | |
parent | 25f3311acc3405dd0dace3571a41f450e6cc6a65 (diff) |
hwmon: (hdaps) Allow inversion of separate axis
Fix for kernel.org bug #7154: hdaps inversion of each axis. This
version is based on the work from Michael Ruoss <miruoss@student.ethz.ch>.
Signed-off-by: Frank Seidel <frank@f-seidel.de>
Signed-off-by: Jean Delvare <khali@linux-fr.org>
Diffstat (limited to 'drivers/hwmon/hdaps.c')
-rw-r--r-- | drivers/hwmon/hdaps.c | 64 |
1 files changed, 33 insertions, 31 deletions
diff --git a/drivers/hwmon/hdaps.c b/drivers/hwmon/hdaps.c index a4d92d246d52..dd058e06e344 100644 --- a/drivers/hwmon/hdaps.c +++ b/drivers/hwmon/hdaps.c | |||
@@ -65,6 +65,10 @@ | |||
65 | #define HDAPS_INPUT_FUZZ 4 /* input event threshold */ | 65 | #define HDAPS_INPUT_FUZZ 4 /* input event threshold */ |
66 | #define HDAPS_INPUT_FLAT 4 | 66 | #define HDAPS_INPUT_FLAT 4 |
67 | 67 | ||
68 | #define HDAPS_X_AXIS (1 << 0) | ||
69 | #define HDAPS_Y_AXIS (1 << 1) | ||
70 | #define HDAPS_BOTH_AXES (HDAPS_X_AXIS | HDAPS_Y_AXIS) | ||
71 | |||
68 | static struct platform_device *pdev; | 72 | static struct platform_device *pdev; |
69 | static struct input_polled_dev *hdaps_idev; | 73 | static struct input_polled_dev *hdaps_idev; |
70 | static unsigned int hdaps_invert; | 74 | static unsigned int hdaps_invert; |
@@ -182,11 +186,11 @@ static int __hdaps_read_pair(unsigned int port1, unsigned int port2, | |||
182 | km_activity = inb(HDAPS_PORT_KMACT); | 186 | km_activity = inb(HDAPS_PORT_KMACT); |
183 | __device_complete(); | 187 | __device_complete(); |
184 | 188 | ||
185 | /* if hdaps_invert is set, negate the two values */ | 189 | /* hdaps_invert is a bitvector to negate the axes */ |
186 | if (hdaps_invert) { | 190 | if (hdaps_invert & HDAPS_X_AXIS) |
187 | *x = -*x; | 191 | *x = -*x; |
192 | if (hdaps_invert & HDAPS_Y_AXIS) | ||
188 | *y = -*y; | 193 | *y = -*y; |
189 | } | ||
190 | 194 | ||
191 | return 0; | 195 | return 0; |
192 | } | 196 | } |
@@ -436,7 +440,8 @@ static ssize_t hdaps_invert_store(struct device *dev, | |||
436 | { | 440 | { |
437 | int invert; | 441 | int invert; |
438 | 442 | ||
439 | if (sscanf(buf, "%d", &invert) != 1 || (invert != 1 && invert != 0)) | 443 | if (sscanf(buf, "%d", &invert) != 1 || |
444 | invert < 0 || invert > HDAPS_BOTH_AXES) | ||
440 | return -EINVAL; | 445 | return -EINVAL; |
441 | 446 | ||
442 | hdaps_invert = invert; | 447 | hdaps_invert = invert; |
@@ -483,56 +488,52 @@ static int __init hdaps_dmi_match(const struct dmi_system_id *id) | |||
483 | /* hdaps_dmi_match_invert - found an inverted match. */ | 488 | /* hdaps_dmi_match_invert - found an inverted match. */ |
484 | static int __init hdaps_dmi_match_invert(const struct dmi_system_id *id) | 489 | static int __init hdaps_dmi_match_invert(const struct dmi_system_id *id) |
485 | { | 490 | { |
486 | hdaps_invert = 1; | 491 | hdaps_invert = (unsigned long)id->driver_data; |
487 | printk(KERN_INFO "hdaps: inverting axis readings.\n"); | 492 | printk(KERN_INFO "hdaps: inverting axis (%u) readings.\n", |
493 | hdaps_invert); | ||
488 | return hdaps_dmi_match(id); | 494 | return hdaps_dmi_match(id); |
489 | } | 495 | } |
490 | 496 | ||
491 | #define HDAPS_DMI_MATCH_NORMAL(vendor, model) { \ | 497 | #define HDAPS_DMI_MATCH_INVERT(vendor, model, axes) { \ |
492 | .ident = vendor " " model, \ | ||
493 | .callback = hdaps_dmi_match, \ | ||
494 | .matches = { \ | ||
495 | DMI_MATCH(DMI_BOARD_VENDOR, vendor), \ | ||
496 | DMI_MATCH(DMI_PRODUCT_VERSION, model) \ | ||
497 | } \ | ||
498 | } | ||
499 | |||
500 | #define HDAPS_DMI_MATCH_INVERT(vendor, model) { \ | ||
501 | .ident = vendor " " model, \ | 498 | .ident = vendor " " model, \ |
502 | .callback = hdaps_dmi_match_invert, \ | 499 | .callback = hdaps_dmi_match_invert, \ |
500 | .driver_data = (void *)axes, \ | ||
503 | .matches = { \ | 501 | .matches = { \ |
504 | DMI_MATCH(DMI_BOARD_VENDOR, vendor), \ | 502 | DMI_MATCH(DMI_BOARD_VENDOR, vendor), \ |
505 | DMI_MATCH(DMI_PRODUCT_VERSION, model) \ | 503 | DMI_MATCH(DMI_PRODUCT_VERSION, model) \ |
506 | } \ | 504 | } \ |
507 | } | 505 | } |
508 | 506 | ||
507 | #define HDAPS_DMI_MATCH_NORMAL(vendor, model) \ | ||
508 | HDAPS_DMI_MATCH_INVERT(vendor, model, 0) | ||
509 | |||
509 | /* Note that HDAPS_DMI_MATCH_NORMAL("ThinkPad T42") would match | 510 | /* Note that HDAPS_DMI_MATCH_NORMAL("ThinkPad T42") would match |
510 | "ThinkPad T42p", so the order of the entries matters. | 511 | "ThinkPad T42p", so the order of the entries matters. |
511 | If your ThinkPad is not recognized, please update to latest | 512 | If your ThinkPad is not recognized, please update to latest |
512 | BIOS. This is especially the case for some R52 ThinkPads. */ | 513 | BIOS. This is especially the case for some R52 ThinkPads. */ |
513 | static struct dmi_system_id __initdata hdaps_whitelist[] = { | 514 | static struct dmi_system_id __initdata hdaps_whitelist[] = { |
514 | HDAPS_DMI_MATCH_INVERT("IBM", "ThinkPad R50p"), | 515 | HDAPS_DMI_MATCH_INVERT("IBM", "ThinkPad R50p", HDAPS_BOTH_AXES), |
515 | HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad R50"), | 516 | HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad R50"), |
516 | HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad R51"), | 517 | HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad R51"), |
517 | HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad R52"), | 518 | HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad R52"), |
518 | HDAPS_DMI_MATCH_INVERT("LENOVO", "ThinkPad R61i"), | 519 | HDAPS_DMI_MATCH_INVERT("LENOVO", "ThinkPad R61i", HDAPS_BOTH_AXES), |
519 | HDAPS_DMI_MATCH_INVERT("LENOVO", "ThinkPad R61"), | 520 | HDAPS_DMI_MATCH_INVERT("LENOVO", "ThinkPad R61", HDAPS_BOTH_AXES), |
520 | HDAPS_DMI_MATCH_INVERT("IBM", "ThinkPad T41p"), | 521 | HDAPS_DMI_MATCH_INVERT("IBM", "ThinkPad T41p", HDAPS_BOTH_AXES), |
521 | HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad T41"), | 522 | HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad T41"), |
522 | HDAPS_DMI_MATCH_INVERT("IBM", "ThinkPad T42p"), | 523 | HDAPS_DMI_MATCH_INVERT("IBM", "ThinkPad T42p", HDAPS_BOTH_AXES), |
523 | HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad T42"), | 524 | HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad T42"), |
524 | HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad T43"), | 525 | HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad T43"), |
525 | HDAPS_DMI_MATCH_INVERT("LENOVO", "ThinkPad T60"), | 526 | HDAPS_DMI_MATCH_INVERT("LENOVO", "ThinkPad T60", HDAPS_BOTH_AXES), |
526 | HDAPS_DMI_MATCH_INVERT("LENOVO", "ThinkPad T61p"), | 527 | HDAPS_DMI_MATCH_INVERT("LENOVO", "ThinkPad T61p", HDAPS_BOTH_AXES), |
527 | HDAPS_DMI_MATCH_INVERT("LENOVO", "ThinkPad T61"), | 528 | HDAPS_DMI_MATCH_INVERT("LENOVO", "ThinkPad T61", HDAPS_BOTH_AXES), |
528 | HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad X40"), | 529 | HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad X40"), |
529 | HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad X41"), | 530 | HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad X41"), |
530 | HDAPS_DMI_MATCH_INVERT("LENOVO", "ThinkPad X60"), | 531 | HDAPS_DMI_MATCH_INVERT("LENOVO", "ThinkPad X60", HDAPS_BOTH_AXES), |
531 | HDAPS_DMI_MATCH_INVERT("LENOVO", "ThinkPad X61s"), | 532 | HDAPS_DMI_MATCH_INVERT("LENOVO", "ThinkPad X61s", HDAPS_BOTH_AXES), |
532 | HDAPS_DMI_MATCH_INVERT("LENOVO", "ThinkPad X61"), | 533 | HDAPS_DMI_MATCH_INVERT("LENOVO", "ThinkPad X61", HDAPS_BOTH_AXES), |
533 | HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad Z60m"), | 534 | HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad Z60m"), |
534 | HDAPS_DMI_MATCH_INVERT("LENOVO", "ThinkPad Z61m"), | 535 | HDAPS_DMI_MATCH_INVERT("LENOVO", "ThinkPad Z61m", HDAPS_BOTH_AXES), |
535 | HDAPS_DMI_MATCH_INVERT("LENOVO", "ThinkPad Z61p"), | 536 | HDAPS_DMI_MATCH_INVERT("LENOVO", "ThinkPad Z61p", HDAPS_BOTH_AXES), |
536 | { .ident = NULL } | 537 | { .ident = NULL } |
537 | }; | 538 | }; |
538 | 539 | ||
@@ -627,8 +628,9 @@ static void __exit hdaps_exit(void) | |||
627 | module_init(hdaps_init); | 628 | module_init(hdaps_init); |
628 | module_exit(hdaps_exit); | 629 | module_exit(hdaps_exit); |
629 | 630 | ||
630 | module_param_named(invert, hdaps_invert, bool, 0); | 631 | module_param_named(invert, hdaps_invert, int, 0); |
631 | MODULE_PARM_DESC(invert, "invert data along each axis"); | 632 | MODULE_PARM_DESC(invert, "invert data along each axis. 1 invert x-axis, " |
633 | "2 invert y-axis, 3 invert both axes."); | ||
632 | 634 | ||
633 | MODULE_AUTHOR("Robert Love"); | 635 | MODULE_AUTHOR("Robert Love"); |
634 | MODULE_DESCRIPTION("IBM Hard Drive Active Protection System (HDAPS) driver"); | 636 | MODULE_DESCRIPTION("IBM Hard Drive Active Protection System (HDAPS) driver"); |