aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hwmon/hdaps.c
diff options
context:
space:
mode:
authorFrank Seidel <frank@f-seidel.de>2009-03-30 15:46:41 -0400
committerJean Delvare <khali@linux-fr.org>2009-03-30 15:46:41 -0400
commit2b8cf3e8c0638687a7a28a7517e673f855623e3b (patch)
tree0c549bbfb7d6f195d9e1e7b0412ae96884d311d0 /drivers/hwmon/hdaps.c
parent25f3311acc3405dd0dace3571a41f450e6cc6a65 (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.c64
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
68static struct platform_device *pdev; 72static struct platform_device *pdev;
69static struct input_polled_dev *hdaps_idev; 73static struct input_polled_dev *hdaps_idev;
70static unsigned int hdaps_invert; 74static 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. */
484static int __init hdaps_dmi_match_invert(const struct dmi_system_id *id) 489static 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. */
513static struct dmi_system_id __initdata hdaps_whitelist[] = { 514static 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)
627module_init(hdaps_init); 628module_init(hdaps_init);
628module_exit(hdaps_exit); 629module_exit(hdaps_exit);
629 630
630module_param_named(invert, hdaps_invert, bool, 0); 631module_param_named(invert, hdaps_invert, int, 0);
631MODULE_PARM_DESC(invert, "invert data along each axis"); 632MODULE_PARM_DESC(invert, "invert data along each axis. 1 invert x-axis, "
633 "2 invert y-axis, 3 invert both axes.");
632 634
633MODULE_AUTHOR("Robert Love"); 635MODULE_AUTHOR("Robert Love");
634MODULE_DESCRIPTION("IBM Hard Drive Active Protection System (HDAPS) driver"); 636MODULE_DESCRIPTION("IBM Hard Drive Active Protection System (HDAPS) driver");