aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Hennerich <michael.hennerich@analog.com>2011-05-17 02:17:40 -0400
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2011-05-17 02:20:17 -0400
commitf1e430e6369f5edac552d99bff15369ef8c6bbd2 (patch)
tree878ff70b8fd431e25b7cba736cd08ca367936582
parent3532cb0ca2774b05e3c660f536ba3d1b38061fc9 (diff)
Input: ad714x - fix captouch wheel option algorithm
As reported by Jean-Francois Dagenais, the wheel algorithm caused a divide by zero exception due to missing variable pre-initialization. In fact it turned out that the whole algorithm had several problems. It is therefore replaced with something that is known working. Signed-off-by: Michael Hennerich <michael.hennerich@analog.com> Tested-by: Jean-Francois Dagenais <jeff.dagenais@gmail.com> Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
-rw-r--r--drivers/input/misc/ad714x.c109
1 files changed, 19 insertions, 90 deletions
diff --git a/drivers/input/misc/ad714x.c b/drivers/input/misc/ad714x.c
index 5f683ec2999e..c3a62c42cd28 100644
--- a/drivers/input/misc/ad714x.c
+++ b/drivers/input/misc/ad714x.c
@@ -79,13 +79,7 @@ struct ad714x_slider_drv {
79struct ad714x_wheel_drv { 79struct ad714x_wheel_drv {
80 int abs_pos; 80 int abs_pos;
81 int flt_pos; 81 int flt_pos;
82 int pre_mean_value;
83 int pre_highest_stage; 82 int pre_highest_stage;
84 int pre_mean_value_no_offset;
85 int mean_value;
86 int mean_value_no_offset;
87 int pos_offset;
88 int pos_ratio;
89 int highest_stage; 83 int highest_stage;
90 enum ad714x_device_state state; 84 enum ad714x_device_state state;
91 struct input_dev *input; 85 struct input_dev *input;
@@ -404,7 +398,6 @@ static void ad714x_slider_state_machine(struct ad714x_chip *ad714x, int idx)
404 ad714x_slider_cal_highest_stage(ad714x, idx); 398 ad714x_slider_cal_highest_stage(ad714x, idx);
405 ad714x_slider_cal_abs_pos(ad714x, idx); 399 ad714x_slider_cal_abs_pos(ad714x, idx);
406 ad714x_slider_cal_flt_pos(ad714x, idx); 400 ad714x_slider_cal_flt_pos(ad714x, idx);
407
408 input_report_abs(sw->input, ABS_X, sw->flt_pos); 401 input_report_abs(sw->input, ABS_X, sw->flt_pos);
409 input_report_key(sw->input, BTN_TOUCH, 1); 402 input_report_key(sw->input, BTN_TOUCH, 1);
410 } else { 403 } else {
@@ -468,104 +461,41 @@ static void ad714x_wheel_cal_sensor_val(struct ad714x_chip *ad714x, int idx)
468/* 461/*
469 * When the scroll wheel is activated, we compute the absolute position based 462 * When the scroll wheel is activated, we compute the absolute position based
470 * on the sensor values. To calculate the position, we first determine the 463 * on the sensor values. To calculate the position, we first determine the
471 * sensor that has the greatest response among the 8 sensors that constitutes 464 * sensor that has the greatest response among the sensors that constitutes
472 * the scrollwheel. Then we determined the 2 sensors on either sides of the 465 * the scrollwheel. Then we determined the sensors on either sides of the
473 * sensor with the highest response and we apply weights to these sensors. The 466 * sensor with the highest response and we apply weights to these sensors. The
474 * result of this computation gives us the mean value which defined by the 467 * result of this computation gives us the mean value.
475 * following formula:
476 * For i= second_before_highest_stage to i= second_after_highest_stage
477 * v += Sensor response(i)*WEIGHT*(i+3)
478 * w += Sensor response(i)
479 * Mean_Value=v/w
480 * pos_on_scrollwheel = (Mean_Value - position_offset) / position_ratio
481 */ 468 */
482 469
483#define WEIGHT_FACTOR 30
484/* This constant prevents the "PositionOffset" from reaching a big value */
485#define OFFSET_POSITION_CLAMP 120
486static void ad714x_wheel_cal_abs_pos(struct ad714x_chip *ad714x, int idx) 470static void ad714x_wheel_cal_abs_pos(struct ad714x_chip *ad714x, int idx)
487{ 471{
488 struct ad714x_wheel_plat *hw = &ad714x->hw->wheel[idx]; 472 struct ad714x_wheel_plat *hw = &ad714x->hw->wheel[idx];
489 struct ad714x_wheel_drv *sw = &ad714x->sw->wheel[idx]; 473 struct ad714x_wheel_drv *sw = &ad714x->sw->wheel[idx];
490 int stage_num = hw->end_stage - hw->start_stage + 1; 474 int stage_num = hw->end_stage - hw->start_stage + 1;
491 int second_before, first_before, highest, first_after, second_after; 475 int first_before, highest, first_after;
492 int a_param, b_param; 476 int a_param, b_param;
493 477
494 /* Calculate Mean value */
495
496 second_before = (sw->highest_stage + stage_num - 2) % stage_num;
497 first_before = (sw->highest_stage + stage_num - 1) % stage_num; 478 first_before = (sw->highest_stage + stage_num - 1) % stage_num;
498 highest = sw->highest_stage; 479 highest = sw->highest_stage;
499 first_after = (sw->highest_stage + stage_num + 1) % stage_num; 480 first_after = (sw->highest_stage + stage_num + 1) % stage_num;
500 second_after = (sw->highest_stage + stage_num + 2) % stage_num;
501
502 if (((sw->highest_stage - hw->start_stage) > 1) &&
503 ((hw->end_stage - sw->highest_stage) > 1)) {
504 a_param = ad714x->sensor_val[second_before] *
505 (second_before - hw->start_stage + 3) +
506 ad714x->sensor_val[first_before] *
507 (second_before - hw->start_stage + 3) +
508 ad714x->sensor_val[highest] *
509 (second_before - hw->start_stage + 3) +
510 ad714x->sensor_val[first_after] *
511 (first_after - hw->start_stage + 3) +
512 ad714x->sensor_val[second_after] *
513 (second_after - hw->start_stage + 3);
514 } else {
515 a_param = ad714x->sensor_val[second_before] *
516 (second_before - hw->start_stage + 1) +
517 ad714x->sensor_val[first_before] *
518 (second_before - hw->start_stage + 2) +
519 ad714x->sensor_val[highest] *
520 (second_before - hw->start_stage + 3) +
521 ad714x->sensor_val[first_after] *
522 (first_after - hw->start_stage + 4) +
523 ad714x->sensor_val[second_after] *
524 (second_after - hw->start_stage + 5);
525 }
526 a_param *= WEIGHT_FACTOR;
527 481
528 b_param = ad714x->sensor_val[second_before] + 482 a_param = ad714x->sensor_val[highest] *
483 (highest - hw->start_stage) +
484 ad714x->sensor_val[first_before] *
485 (highest - hw->start_stage - 1) +
486 ad714x->sensor_val[first_after] *
487 (highest - hw->start_stage + 1);
488 b_param = ad714x->sensor_val[highest] +
529 ad714x->sensor_val[first_before] + 489 ad714x->sensor_val[first_before] +
530 ad714x->sensor_val[highest] + 490 ad714x->sensor_val[first_after];
531 ad714x->sensor_val[first_after] + 491
532 ad714x->sensor_val[second_after]; 492 sw->abs_pos = ((hw->max_coord / (hw->end_stage - hw->start_stage)) *
533 493 a_param) / b_param;
534 sw->pre_mean_value = sw->mean_value; 494
535 sw->mean_value = a_param / b_param;
536
537 /* Calculate the offset */
538
539 if ((sw->pre_highest_stage == hw->end_stage) &&
540 (sw->highest_stage == hw->start_stage))
541 sw->pos_offset = sw->mean_value;
542 else if ((sw->pre_highest_stage == hw->start_stage) &&
543 (sw->highest_stage == hw->end_stage))
544 sw->pos_offset = sw->pre_mean_value;
545
546 if (sw->pos_offset > OFFSET_POSITION_CLAMP)
547 sw->pos_offset = OFFSET_POSITION_CLAMP;
548
549 /* Calculate the mean value without the offset */
550
551 sw->pre_mean_value_no_offset = sw->mean_value_no_offset;
552 sw->mean_value_no_offset = sw->mean_value - sw->pos_offset;
553 if (sw->mean_value_no_offset < 0)
554 sw->mean_value_no_offset = 0;
555
556 /* Calculate ratio to scale down to NUMBER_OF_WANTED_POSITIONS */
557
558 if ((sw->pre_highest_stage == hw->end_stage) &&
559 (sw->highest_stage == hw->start_stage))
560 sw->pos_ratio = (sw->pre_mean_value_no_offset * 100) /
561 hw->max_coord;
562 else if ((sw->pre_highest_stage == hw->start_stage) &&
563 (sw->highest_stage == hw->end_stage))
564 sw->pos_ratio = (sw->mean_value_no_offset * 100) /
565 hw->max_coord;
566 sw->abs_pos = (sw->mean_value_no_offset * 100) / sw->pos_ratio;
567 if (sw->abs_pos > hw->max_coord) 495 if (sw->abs_pos > hw->max_coord)
568 sw->abs_pos = hw->max_coord; 496 sw->abs_pos = hw->max_coord;
497 else if (sw->abs_pos < 0)
498 sw->abs_pos = 0;
569} 499}
570 500
571static void ad714x_wheel_cal_flt_pos(struct ad714x_chip *ad714x, int idx) 501static void ad714x_wheel_cal_flt_pos(struct ad714x_chip *ad714x, int idx)
@@ -639,9 +569,8 @@ static void ad714x_wheel_state_machine(struct ad714x_chip *ad714x, int idx)
639 ad714x_wheel_cal_highest_stage(ad714x, idx); 569 ad714x_wheel_cal_highest_stage(ad714x, idx);
640 ad714x_wheel_cal_abs_pos(ad714x, idx); 570 ad714x_wheel_cal_abs_pos(ad714x, idx);
641 ad714x_wheel_cal_flt_pos(ad714x, idx); 571 ad714x_wheel_cal_flt_pos(ad714x, idx);
642
643 input_report_abs(sw->input, ABS_WHEEL, 572 input_report_abs(sw->input, ABS_WHEEL,
644 sw->abs_pos); 573 sw->flt_pos);
645 input_report_key(sw->input, BTN_TOUCH, 1); 574 input_report_key(sw->input, BTN_TOUCH, 1);
646 } else { 575 } else {
647 /* When the user lifts off the sensor, configure 576 /* When the user lifts off the sensor, configure