diff options
Diffstat (limited to 'drivers/input/mouse/alps.c')
-rw-r--r-- | drivers/input/mouse/alps.c | 691 |
1 files changed, 464 insertions, 227 deletions
diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c index fb15c64ffb95..a59a1a64b674 100644 --- a/drivers/input/mouse/alps.c +++ b/drivers/input/mouse/alps.c | |||
@@ -99,6 +99,8 @@ static const struct alps_nibble_commands alps_v6_nibble_commands[] = { | |||
99 | #define ALPS_FOUR_BUTTONS 0x40 /* 4 direction button present */ | 99 | #define ALPS_FOUR_BUTTONS 0x40 /* 4 direction button present */ |
100 | #define ALPS_PS2_INTERLEAVED 0x80 /* 3-byte PS/2 packet interleaved with | 100 | #define ALPS_PS2_INTERLEAVED 0x80 /* 3-byte PS/2 packet interleaved with |
101 | 6-byte ALPS packet */ | 101 | 6-byte ALPS packet */ |
102 | #define ALPS_IS_RUSHMORE 0x100 /* device is a rushmore */ | ||
103 | #define ALPS_BUTTONPAD 0x200 /* device is a clickpad */ | ||
102 | 104 | ||
103 | static const struct alps_model_info alps_model_data[] = { | 105 | static const struct alps_model_info alps_model_data[] = { |
104 | { { 0x32, 0x02, 0x14 }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* Toshiba Salellite Pro M10 */ | 106 | { { 0x32, 0x02, 0x14 }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* Toshiba Salellite Pro M10 */ |
@@ -281,11 +283,10 @@ static void alps_process_packet_v1_v2(struct psmouse *psmouse) | |||
281 | * | 283 | * |
282 | * The bitmaps don't have enough data to track fingers, so this function | 284 | * The bitmaps don't have enough data to track fingers, so this function |
283 | * only generates points representing a bounding box of at most two contacts. | 285 | * only generates points representing a bounding box of at most two contacts. |
284 | * These two points are returned in x1, y1, x2, and y2. | 286 | * These two points are returned in fields->mt. |
285 | */ | 287 | */ |
286 | static void alps_process_bitmap_dolphin(struct alps_data *priv, | 288 | static void alps_process_bitmap_dolphin(struct alps_data *priv, |
287 | struct alps_fields *fields, | 289 | struct alps_fields *fields) |
288 | int *x1, int *y1, int *x2, int *y2) | ||
289 | { | 290 | { |
290 | int box_middle_x, box_middle_y; | 291 | int box_middle_x, box_middle_y; |
291 | unsigned int x_map, y_map; | 292 | unsigned int x_map, y_map; |
@@ -308,8 +309,6 @@ static void alps_process_bitmap_dolphin(struct alps_data *priv, | |||
308 | if (x_msb > priv->x_bits || y_msb > priv->y_bits) | 309 | if (x_msb > priv->x_bits || y_msb > priv->y_bits) |
309 | return; | 310 | return; |
310 | 311 | ||
311 | *x1 = *y1 = *x2 = *y2 = 0; | ||
312 | |||
313 | if (fields->fingers > 1) { | 312 | if (fields->fingers > 1) { |
314 | start_bit = priv->x_bits - x_msb; | 313 | start_bit = priv->x_bits - x_msb; |
315 | end_bit = priv->x_bits - x_lsb; | 314 | end_bit = priv->x_bits - x_lsb; |
@@ -320,10 +319,35 @@ static void alps_process_bitmap_dolphin(struct alps_data *priv, | |||
320 | end_bit = y_msb - 1; | 319 | end_bit = y_msb - 1; |
321 | box_middle_y = (priv->y_max * (start_bit + end_bit)) / | 320 | box_middle_y = (priv->y_max * (start_bit + end_bit)) / |
322 | (2 * (priv->y_bits - 1)); | 321 | (2 * (priv->y_bits - 1)); |
323 | *x1 = fields->x; | 322 | fields->mt[0] = fields->st; |
324 | *y1 = fields->y; | 323 | fields->mt[1].x = 2 * box_middle_x - fields->mt[0].x; |
325 | *x2 = 2 * box_middle_x - *x1; | 324 | fields->mt[1].y = 2 * box_middle_y - fields->mt[0].y; |
326 | *y2 = 2 * box_middle_y - *y1; | 325 | } |
326 | } | ||
327 | |||
328 | static void alps_get_bitmap_points(unsigned int map, | ||
329 | struct alps_bitmap_point *low, | ||
330 | struct alps_bitmap_point *high, | ||
331 | int *fingers) | ||
332 | { | ||
333 | struct alps_bitmap_point *point; | ||
334 | int i, bit, prev_bit = 0; | ||
335 | |||
336 | point = low; | ||
337 | for (i = 0; map != 0; i++, map >>= 1) { | ||
338 | bit = map & 1; | ||
339 | if (bit) { | ||
340 | if (!prev_bit) { | ||
341 | point->start_bit = i; | ||
342 | point->num_bits = 0; | ||
343 | (*fingers)++; | ||
344 | } | ||
345 | point->num_bits++; | ||
346 | } else { | ||
347 | if (prev_bit) | ||
348 | point = high; | ||
349 | } | ||
350 | prev_bit = bit; | ||
327 | } | 351 | } |
328 | } | 352 | } |
329 | 353 | ||
@@ -334,71 +358,21 @@ static void alps_process_bitmap_dolphin(struct alps_data *priv, | |||
334 | * | 358 | * |
335 | * The bitmaps don't have enough data to track fingers, so this function | 359 | * The bitmaps don't have enough data to track fingers, so this function |
336 | * only generates points representing a bounding box of all contacts. | 360 | * only generates points representing a bounding box of all contacts. |
337 | * These points are returned in x1, y1, x2, and y2 when the return value | 361 | * These points are returned in fields->mt when the return value |
338 | * is greater than 0. | 362 | * is greater than 0. |
339 | */ | 363 | */ |
340 | static int alps_process_bitmap(struct alps_data *priv, | 364 | static int alps_process_bitmap(struct alps_data *priv, |
341 | unsigned int x_map, unsigned int y_map, | 365 | struct alps_fields *fields) |
342 | int *x1, int *y1, int *x2, int *y2) | ||
343 | { | 366 | { |
344 | struct alps_bitmap_point { | 367 | int i, fingers_x = 0, fingers_y = 0, fingers; |
345 | int start_bit; | ||
346 | int num_bits; | ||
347 | }; | ||
348 | |||
349 | int fingers_x = 0, fingers_y = 0, fingers; | ||
350 | int i, bit, prev_bit; | ||
351 | struct alps_bitmap_point x_low = {0,}, x_high = {0,}; | 368 | struct alps_bitmap_point x_low = {0,}, x_high = {0,}; |
352 | struct alps_bitmap_point y_low = {0,}, y_high = {0,}; | 369 | struct alps_bitmap_point y_low = {0,}, y_high = {0,}; |
353 | struct alps_bitmap_point *point; | ||
354 | 370 | ||
355 | if (!x_map || !y_map) | 371 | if (!fields->x_map || !fields->y_map) |
356 | return 0; | 372 | return 0; |
357 | 373 | ||
358 | *x1 = *y1 = *x2 = *y2 = 0; | 374 | alps_get_bitmap_points(fields->x_map, &x_low, &x_high, &fingers_x); |
359 | 375 | alps_get_bitmap_points(fields->y_map, &y_low, &y_high, &fingers_y); | |
360 | prev_bit = 0; | ||
361 | point = &x_low; | ||
362 | for (i = 0; x_map != 0; i++, x_map >>= 1) { | ||
363 | bit = x_map & 1; | ||
364 | if (bit) { | ||
365 | if (!prev_bit) { | ||
366 | point->start_bit = i; | ||
367 | fingers_x++; | ||
368 | } | ||
369 | point->num_bits++; | ||
370 | } else { | ||
371 | if (prev_bit) | ||
372 | point = &x_high; | ||
373 | else | ||
374 | point->num_bits = 0; | ||
375 | } | ||
376 | prev_bit = bit; | ||
377 | } | ||
378 | |||
379 | /* | ||
380 | * y bitmap is reversed for what we need (lower positions are in | ||
381 | * higher bits), so we process from the top end. | ||
382 | */ | ||
383 | y_map = y_map << (sizeof(y_map) * BITS_PER_BYTE - priv->y_bits); | ||
384 | prev_bit = 0; | ||
385 | point = &y_low; | ||
386 | for (i = 0; y_map != 0; i++, y_map <<= 1) { | ||
387 | bit = y_map & (1 << (sizeof(y_map) * BITS_PER_BYTE - 1)); | ||
388 | if (bit) { | ||
389 | if (!prev_bit) { | ||
390 | point->start_bit = i; | ||
391 | fingers_y++; | ||
392 | } | ||
393 | point->num_bits++; | ||
394 | } else { | ||
395 | if (prev_bit) | ||
396 | point = &y_high; | ||
397 | else | ||
398 | point->num_bits = 0; | ||
399 | } | ||
400 | prev_bit = bit; | ||
401 | } | ||
402 | 376 | ||
403 | /* | 377 | /* |
404 | * Fingers can overlap, so we use the maximum count of fingers | 378 | * Fingers can overlap, so we use the maximum count of fingers |
@@ -407,58 +381,91 @@ static int alps_process_bitmap(struct alps_data *priv, | |||
407 | fingers = max(fingers_x, fingers_y); | 381 | fingers = max(fingers_x, fingers_y); |
408 | 382 | ||
409 | /* | 383 | /* |
410 | * If total fingers is > 1 but either axis reports only a single | 384 | * If an axis reports only a single contact, we have overlapping or |
411 | * contact, we have overlapping or adjacent fingers. For the | 385 | * adjacent fingers. Divide the single contact between the two points. |
412 | * purposes of creating a bounding box, divide the single contact | ||
413 | * (roughly) equally between the two points. | ||
414 | */ | 386 | */ |
415 | if (fingers > 1) { | 387 | if (fingers_x == 1) { |
416 | if (fingers_x == 1) { | 388 | i = (x_low.num_bits - 1) / 2; |
417 | i = x_low.num_bits / 2; | 389 | x_low.num_bits = x_low.num_bits - i; |
418 | x_low.num_bits = x_low.num_bits - i; | 390 | x_high.start_bit = x_low.start_bit + i; |
419 | x_high.start_bit = x_low.start_bit + i; | 391 | x_high.num_bits = max(i, 1); |
420 | x_high.num_bits = max(i, 1); | 392 | } |
421 | } else if (fingers_y == 1) { | 393 | if (fingers_y == 1) { |
422 | i = y_low.num_bits / 2; | 394 | i = (y_low.num_bits - 1) / 2; |
423 | y_low.num_bits = y_low.num_bits - i; | 395 | y_low.num_bits = y_low.num_bits - i; |
424 | y_high.start_bit = y_low.start_bit + i; | 396 | y_high.start_bit = y_low.start_bit + i; |
425 | y_high.num_bits = max(i, 1); | 397 | y_high.num_bits = max(i, 1); |
426 | } | ||
427 | } | 398 | } |
428 | 399 | ||
429 | *x1 = (priv->x_max * (2 * x_low.start_bit + x_low.num_bits - 1)) / | 400 | fields->mt[0].x = |
430 | (2 * (priv->x_bits - 1)); | 401 | (priv->x_max * (2 * x_low.start_bit + x_low.num_bits - 1)) / |
431 | *y1 = (priv->y_max * (2 * y_low.start_bit + y_low.num_bits - 1)) / | 402 | (2 * (priv->x_bits - 1)); |
432 | (2 * (priv->y_bits - 1)); | 403 | fields->mt[0].y = |
433 | 404 | (priv->y_max * (2 * y_low.start_bit + y_low.num_bits - 1)) / | |
434 | if (fingers > 1) { | 405 | (2 * (priv->y_bits - 1)); |
435 | *x2 = (priv->x_max * | 406 | |
436 | (2 * x_high.start_bit + x_high.num_bits - 1)) / | 407 | fields->mt[1].x = |
437 | (2 * (priv->x_bits - 1)); | 408 | (priv->x_max * (2 * x_high.start_bit + x_high.num_bits - 1)) / |
438 | *y2 = (priv->y_max * | 409 | (2 * (priv->x_bits - 1)); |
439 | (2 * y_high.start_bit + y_high.num_bits - 1)) / | 410 | fields->mt[1].y = |
440 | (2 * (priv->y_bits - 1)); | 411 | (priv->y_max * (2 * y_high.start_bit + y_high.num_bits - 1)) / |
412 | (2 * (priv->y_bits - 1)); | ||
413 | |||
414 | /* y-bitmap order is reversed, except on rushmore */ | ||
415 | if (!(priv->flags & ALPS_IS_RUSHMORE)) { | ||
416 | fields->mt[0].y = priv->y_max - fields->mt[0].y; | ||
417 | fields->mt[1].y = priv->y_max - fields->mt[1].y; | ||
441 | } | 418 | } |
442 | 419 | ||
443 | return fingers; | 420 | return fingers; |
444 | } | 421 | } |
445 | 422 | ||
446 | static void alps_set_slot(struct input_dev *dev, int slot, bool active, | 423 | static void alps_set_slot(struct input_dev *dev, int slot, int x, int y) |
447 | int x, int y) | ||
448 | { | 424 | { |
449 | input_mt_slot(dev, slot); | 425 | input_mt_slot(dev, slot); |
450 | input_mt_report_slot_state(dev, MT_TOOL_FINGER, active); | 426 | input_mt_report_slot_state(dev, MT_TOOL_FINGER, true); |
451 | if (active) { | 427 | input_report_abs(dev, ABS_MT_POSITION_X, x); |
452 | input_report_abs(dev, ABS_MT_POSITION_X, x); | 428 | input_report_abs(dev, ABS_MT_POSITION_Y, y); |
453 | input_report_abs(dev, ABS_MT_POSITION_Y, y); | ||
454 | } | ||
455 | } | 429 | } |
456 | 430 | ||
457 | static void alps_report_semi_mt_data(struct input_dev *dev, int num_fingers, | 431 | static void alps_report_mt_data(struct psmouse *psmouse, int n) |
458 | int x1, int y1, int x2, int y2) | ||
459 | { | 432 | { |
460 | alps_set_slot(dev, 0, num_fingers != 0, x1, y1); | 433 | struct alps_data *priv = psmouse->private; |
461 | alps_set_slot(dev, 1, num_fingers == 2, x2, y2); | 434 | struct input_dev *dev = psmouse->dev; |
435 | struct alps_fields *f = &priv->f; | ||
436 | int i, slot[MAX_TOUCHES]; | ||
437 | |||
438 | input_mt_assign_slots(dev, slot, f->mt, n); | ||
439 | for (i = 0; i < n; i++) | ||
440 | alps_set_slot(dev, slot[i], f->mt[i].x, f->mt[i].y); | ||
441 | |||
442 | input_mt_sync_frame(dev); | ||
443 | } | ||
444 | |||
445 | static void alps_report_semi_mt_data(struct psmouse *psmouse, int fingers) | ||
446 | { | ||
447 | struct alps_data *priv = psmouse->private; | ||
448 | struct input_dev *dev = psmouse->dev; | ||
449 | struct alps_fields *f = &priv->f; | ||
450 | |||
451 | /* Use st data when we don't have mt data */ | ||
452 | if (fingers < 2) { | ||
453 | f->mt[0].x = f->st.x; | ||
454 | f->mt[0].y = f->st.y; | ||
455 | fingers = f->pressure > 0 ? 1 : 0; | ||
456 | } | ||
457 | |||
458 | alps_report_mt_data(psmouse, (fingers <= 2) ? fingers : 2); | ||
459 | |||
460 | input_mt_report_finger_count(dev, fingers); | ||
461 | |||
462 | input_report_key(dev, BTN_LEFT, f->left); | ||
463 | input_report_key(dev, BTN_RIGHT, f->right); | ||
464 | input_report_key(dev, BTN_MIDDLE, f->middle); | ||
465 | |||
466 | input_report_abs(dev, ABS_PRESSURE, f->pressure); | ||
467 | |||
468 | input_sync(dev); | ||
462 | } | 469 | } |
463 | 470 | ||
464 | static void alps_process_trackstick_packet_v3(struct psmouse *psmouse) | 471 | static void alps_process_trackstick_packet_v3(struct psmouse *psmouse) |
@@ -532,7 +539,7 @@ static void alps_decode_buttons_v3(struct alps_fields *f, unsigned char *p) | |||
532 | f->ts_middle = !!(p[3] & 0x40); | 539 | f->ts_middle = !!(p[3] & 0x40); |
533 | } | 540 | } |
534 | 541 | ||
535 | static void alps_decode_pinnacle(struct alps_fields *f, unsigned char *p, | 542 | static int alps_decode_pinnacle(struct alps_fields *f, unsigned char *p, |
536 | struct psmouse *psmouse) | 543 | struct psmouse *psmouse) |
537 | { | 544 | { |
538 | f->first_mp = !!(p[4] & 0x40); | 545 | f->first_mp = !!(p[4] & 0x40); |
@@ -546,24 +553,31 @@ static void alps_decode_pinnacle(struct alps_fields *f, unsigned char *p, | |||
546 | ((p[2] & 0x7f) << 1) | | 553 | ((p[2] & 0x7f) << 1) | |
547 | (p[4] & 0x01); | 554 | (p[4] & 0x01); |
548 | 555 | ||
549 | f->x = ((p[1] & 0x7f) << 4) | ((p[4] & 0x30) >> 2) | | 556 | f->st.x = ((p[1] & 0x7f) << 4) | ((p[4] & 0x30) >> 2) | |
550 | ((p[0] & 0x30) >> 4); | 557 | ((p[0] & 0x30) >> 4); |
551 | f->y = ((p[2] & 0x7f) << 4) | (p[4] & 0x0f); | 558 | f->st.y = ((p[2] & 0x7f) << 4) | (p[4] & 0x0f); |
552 | f->z = p[5] & 0x7f; | 559 | f->pressure = p[5] & 0x7f; |
553 | 560 | ||
554 | alps_decode_buttons_v3(f, p); | 561 | alps_decode_buttons_v3(f, p); |
562 | |||
563 | return 0; | ||
555 | } | 564 | } |
556 | 565 | ||
557 | static void alps_decode_rushmore(struct alps_fields *f, unsigned char *p, | 566 | static int alps_decode_rushmore(struct alps_fields *f, unsigned char *p, |
558 | struct psmouse *psmouse) | 567 | struct psmouse *psmouse) |
559 | { | 568 | { |
560 | alps_decode_pinnacle(f, p, psmouse); | 569 | alps_decode_pinnacle(f, p, psmouse); |
561 | 570 | ||
571 | /* Rushmore's packet decode has a bit difference with Pinnacle's */ | ||
572 | f->is_mp = !!(p[5] & 0x40); | ||
573 | f->fingers = max((p[5] & 0x3), ((p[5] >> 2) & 0x3)) + 1; | ||
562 | f->x_map |= (p[5] & 0x10) << 11; | 574 | f->x_map |= (p[5] & 0x10) << 11; |
563 | f->y_map |= (p[5] & 0x20) << 6; | 575 | f->y_map |= (p[5] & 0x20) << 6; |
576 | |||
577 | return 0; | ||
564 | } | 578 | } |
565 | 579 | ||
566 | static void alps_decode_dolphin(struct alps_fields *f, unsigned char *p, | 580 | static int alps_decode_dolphin(struct alps_fields *f, unsigned char *p, |
567 | struct psmouse *psmouse) | 581 | struct psmouse *psmouse) |
568 | { | 582 | { |
569 | u64 palm_data = 0; | 583 | u64 palm_data = 0; |
@@ -573,9 +587,9 @@ static void alps_decode_dolphin(struct alps_fields *f, unsigned char *p, | |||
573 | f->is_mp = !!(p[0] & 0x20); | 587 | f->is_mp = !!(p[0] & 0x20); |
574 | 588 | ||
575 | if (!f->is_mp) { | 589 | if (!f->is_mp) { |
576 | f->x = ((p[1] & 0x7f) | ((p[4] & 0x0f) << 7)); | 590 | f->st.x = ((p[1] & 0x7f) | ((p[4] & 0x0f) << 7)); |
577 | f->y = ((p[2] & 0x7f) | ((p[4] & 0xf0) << 3)); | 591 | f->st.y = ((p[2] & 0x7f) | ((p[4] & 0xf0) << 3)); |
578 | f->z = (p[0] & 4) ? 0 : p[5] & 0x7f; | 592 | f->pressure = (p[0] & 4) ? 0 : p[5] & 0x7f; |
579 | alps_decode_buttons_v3(f, p); | 593 | alps_decode_buttons_v3(f, p); |
580 | } else { | 594 | } else { |
581 | f->fingers = ((p[0] & 0x6) >> 1 | | 595 | f->fingers = ((p[0] & 0x6) >> 1 | |
@@ -596,19 +610,21 @@ static void alps_decode_dolphin(struct alps_fields *f, unsigned char *p, | |||
596 | f->x_map = (palm_data >> priv->y_bits) & | 610 | f->x_map = (palm_data >> priv->y_bits) & |
597 | (BIT(priv->x_bits) - 1); | 611 | (BIT(priv->x_bits) - 1); |
598 | } | 612 | } |
613 | |||
614 | return 0; | ||
599 | } | 615 | } |
600 | 616 | ||
601 | static void alps_process_touchpad_packet_v3_v5(struct psmouse *psmouse) | 617 | static void alps_process_touchpad_packet_v3_v5(struct psmouse *psmouse) |
602 | { | 618 | { |
603 | struct alps_data *priv = psmouse->private; | 619 | struct alps_data *priv = psmouse->private; |
604 | unsigned char *packet = psmouse->packet; | 620 | unsigned char *packet = psmouse->packet; |
605 | struct input_dev *dev = psmouse->dev; | ||
606 | struct input_dev *dev2 = priv->dev2; | 621 | struct input_dev *dev2 = priv->dev2; |
607 | int x1 = 0, y1 = 0, x2 = 0, y2 = 0; | 622 | struct alps_fields *f = &priv->f; |
608 | int fingers = 0, bmap_fn; | 623 | int fingers = 0; |
609 | struct alps_fields f = {0}; | ||
610 | 624 | ||
611 | priv->decode_fields(&f, packet, psmouse); | 625 | memset(f, 0, sizeof(*f)); |
626 | |||
627 | priv->decode_fields(f, packet, psmouse); | ||
612 | 628 | ||
613 | /* | 629 | /* |
614 | * There's no single feature of touchpad position and bitmap packets | 630 | * There's no single feature of touchpad position and bitmap packets |
@@ -623,22 +639,14 @@ static void alps_process_touchpad_packet_v3_v5(struct psmouse *psmouse) | |||
623 | * packet. Check for this, and when it happens process the | 639 | * packet. Check for this, and when it happens process the |
624 | * position packet as usual. | 640 | * position packet as usual. |
625 | */ | 641 | */ |
626 | if (f.is_mp) { | 642 | if (f->is_mp) { |
627 | fingers = f.fingers; | 643 | fingers = f->fingers; |
628 | if (priv->proto_version == ALPS_PROTO_V3) { | 644 | if (priv->proto_version == ALPS_PROTO_V3) { |
629 | bmap_fn = alps_process_bitmap(priv, f.x_map, | 645 | if (alps_process_bitmap(priv, f) == 0) |
630 | f.y_map, &x1, &y1, | 646 | fingers = 0; /* Use st data */ |
631 | &x2, &y2); | ||
632 | |||
633 | /* | ||
634 | * We shouldn't report more than one finger if | ||
635 | * we don't have two coordinates. | ||
636 | */ | ||
637 | if (fingers > 1 && bmap_fn < 2) | ||
638 | fingers = bmap_fn; | ||
639 | 647 | ||
640 | /* Now process position packet */ | 648 | /* Now process position packet */ |
641 | priv->decode_fields(&f, priv->multi_data, | 649 | priv->decode_fields(f, priv->multi_data, |
642 | psmouse); | 650 | psmouse); |
643 | } else { | 651 | } else { |
644 | /* | 652 | /* |
@@ -647,15 +655,14 @@ static void alps_process_touchpad_packet_v3_v5(struct psmouse *psmouse) | |||
647 | * calculate Pt2, so we need to do position | 655 | * calculate Pt2, so we need to do position |
648 | * packet decode first. | 656 | * packet decode first. |
649 | */ | 657 | */ |
650 | priv->decode_fields(&f, priv->multi_data, | 658 | priv->decode_fields(f, priv->multi_data, |
651 | psmouse); | 659 | psmouse); |
652 | 660 | ||
653 | /* | 661 | /* |
654 | * Since Dolphin's finger number is reliable, | 662 | * Since Dolphin's finger number is reliable, |
655 | * there is no need to compare with bmap_fn. | 663 | * there is no need to compare with bmap_fn. |
656 | */ | 664 | */ |
657 | alps_process_bitmap_dolphin(priv, &f, &x1, &y1, | 665 | alps_process_bitmap_dolphin(priv, f); |
658 | &x2, &y2); | ||
659 | } | 666 | } |
660 | } else { | 667 | } else { |
661 | priv->multi_packet = 0; | 668 | priv->multi_packet = 0; |
@@ -670,10 +677,10 @@ static void alps_process_touchpad_packet_v3_v5(struct psmouse *psmouse) | |||
670 | * out misidentified bitmap packets, we reject anything with this | 677 | * out misidentified bitmap packets, we reject anything with this |
671 | * bit set. | 678 | * bit set. |
672 | */ | 679 | */ |
673 | if (f.is_mp) | 680 | if (f->is_mp) |
674 | return; | 681 | return; |
675 | 682 | ||
676 | if (!priv->multi_packet && f.first_mp) { | 683 | if (!priv->multi_packet && f->first_mp) { |
677 | priv->multi_packet = 1; | 684 | priv->multi_packet = 1; |
678 | memcpy(priv->multi_data, packet, sizeof(priv->multi_data)); | 685 | memcpy(priv->multi_data, packet, sizeof(priv->multi_data)); |
679 | return; | 686 | return; |
@@ -687,44 +694,15 @@ static void alps_process_touchpad_packet_v3_v5(struct psmouse *psmouse) | |||
687 | * with x, y, and z all zero, so these seem to be flukes. | 694 | * with x, y, and z all zero, so these seem to be flukes. |
688 | * Ignore them. | 695 | * Ignore them. |
689 | */ | 696 | */ |
690 | if (f.x && f.y && !f.z) | 697 | if (f->st.x && f->st.y && !f->pressure) |
691 | return; | 698 | return; |
692 | 699 | ||
693 | /* | 700 | alps_report_semi_mt_data(psmouse, fingers); |
694 | * If we don't have MT data or the bitmaps were empty, we have | ||
695 | * to rely on ST data. | ||
696 | */ | ||
697 | if (!fingers) { | ||
698 | x1 = f.x; | ||
699 | y1 = f.y; | ||
700 | fingers = f.z > 0 ? 1 : 0; | ||
701 | } | ||
702 | |||
703 | if (f.z >= 64) | ||
704 | input_report_key(dev, BTN_TOUCH, 1); | ||
705 | else | ||
706 | input_report_key(dev, BTN_TOUCH, 0); | ||
707 | |||
708 | alps_report_semi_mt_data(dev, fingers, x1, y1, x2, y2); | ||
709 | |||
710 | input_mt_report_finger_count(dev, fingers); | ||
711 | |||
712 | input_report_key(dev, BTN_LEFT, f.left); | ||
713 | input_report_key(dev, BTN_RIGHT, f.right); | ||
714 | input_report_key(dev, BTN_MIDDLE, f.middle); | ||
715 | |||
716 | if (f.z > 0) { | ||
717 | input_report_abs(dev, ABS_X, f.x); | ||
718 | input_report_abs(dev, ABS_Y, f.y); | ||
719 | } | ||
720 | input_report_abs(dev, ABS_PRESSURE, f.z); | ||
721 | |||
722 | input_sync(dev); | ||
723 | 701 | ||
724 | if (!(priv->quirks & ALPS_QUIRK_TRACKSTICK_BUTTONS)) { | 702 | if (!(priv->quirks & ALPS_QUIRK_TRACKSTICK_BUTTONS)) { |
725 | input_report_key(dev2, BTN_LEFT, f.ts_left); | 703 | input_report_key(dev2, BTN_LEFT, f->ts_left); |
726 | input_report_key(dev2, BTN_RIGHT, f.ts_right); | 704 | input_report_key(dev2, BTN_RIGHT, f->ts_right); |
727 | input_report_key(dev2, BTN_MIDDLE, f.ts_middle); | 705 | input_report_key(dev2, BTN_MIDDLE, f->ts_middle); |
728 | input_sync(dev2); | 706 | input_sync(dev2); |
729 | } | 707 | } |
730 | } | 708 | } |
@@ -823,13 +801,8 @@ static void alps_process_packet_v4(struct psmouse *psmouse) | |||
823 | { | 801 | { |
824 | struct alps_data *priv = psmouse->private; | 802 | struct alps_data *priv = psmouse->private; |
825 | unsigned char *packet = psmouse->packet; | 803 | unsigned char *packet = psmouse->packet; |
826 | struct input_dev *dev = psmouse->dev; | 804 | struct alps_fields *f = &priv->f; |
827 | int offset; | 805 | int offset; |
828 | int x, y, z; | ||
829 | int left, right; | ||
830 | int x1, y1, x2, y2; | ||
831 | int fingers = 0; | ||
832 | unsigned int x_bitmap, y_bitmap; | ||
833 | 806 | ||
834 | /* | 807 | /* |
835 | * v4 has a 6-byte encoding for bitmap data, but this data is | 808 | * v4 has a 6-byte encoding for bitmap data, but this data is |
@@ -851,71 +824,207 @@ static void alps_process_packet_v4(struct psmouse *psmouse) | |||
851 | if (++priv->multi_packet > 2) { | 824 | if (++priv->multi_packet > 2) { |
852 | priv->multi_packet = 0; | 825 | priv->multi_packet = 0; |
853 | 826 | ||
854 | x_bitmap = ((priv->multi_data[2] & 0x1f) << 10) | | 827 | f->x_map = ((priv->multi_data[2] & 0x1f) << 10) | |
855 | ((priv->multi_data[3] & 0x60) << 3) | | 828 | ((priv->multi_data[3] & 0x60) << 3) | |
856 | ((priv->multi_data[0] & 0x3f) << 2) | | 829 | ((priv->multi_data[0] & 0x3f) << 2) | |
857 | ((priv->multi_data[1] & 0x60) >> 5); | 830 | ((priv->multi_data[1] & 0x60) >> 5); |
858 | y_bitmap = ((priv->multi_data[5] & 0x01) << 10) | | 831 | f->y_map = ((priv->multi_data[5] & 0x01) << 10) | |
859 | ((priv->multi_data[3] & 0x1f) << 5) | | 832 | ((priv->multi_data[3] & 0x1f) << 5) | |
860 | (priv->multi_data[1] & 0x1f); | 833 | (priv->multi_data[1] & 0x1f); |
861 | 834 | ||
862 | fingers = alps_process_bitmap(priv, x_bitmap, y_bitmap, | 835 | f->fingers = alps_process_bitmap(priv, f); |
863 | &x1, &y1, &x2, &y2); | ||
864 | |||
865 | /* Store MT data.*/ | ||
866 | priv->fingers = fingers; | ||
867 | priv->x1 = x1; | ||
868 | priv->x2 = x2; | ||
869 | priv->y1 = y1; | ||
870 | priv->y2 = y2; | ||
871 | } | 836 | } |
872 | 837 | ||
873 | left = packet[4] & 0x01; | 838 | f->left = packet[4] & 0x01; |
874 | right = packet[4] & 0x02; | 839 | f->right = packet[4] & 0x02; |
875 | 840 | ||
876 | x = ((packet[1] & 0x7f) << 4) | ((packet[3] & 0x30) >> 2) | | 841 | f->st.x = ((packet[1] & 0x7f) << 4) | ((packet[3] & 0x30) >> 2) | |
877 | ((packet[0] & 0x30) >> 4); | 842 | ((packet[0] & 0x30) >> 4); |
878 | y = ((packet[2] & 0x7f) << 4) | (packet[3] & 0x0f); | 843 | f->st.y = ((packet[2] & 0x7f) << 4) | (packet[3] & 0x0f); |
879 | z = packet[5] & 0x7f; | 844 | f->pressure = packet[5] & 0x7f; |
880 | 845 | ||
881 | /* | 846 | alps_report_semi_mt_data(psmouse, f->fingers); |
882 | * If there were no contacts in the bitmap, use ST | 847 | } |
883 | * points in MT reports. | 848 | |
884 | * If there were two contacts or more, report MT data. | 849 | static bool alps_is_valid_package_v7(struct psmouse *psmouse) |
885 | */ | 850 | { |
886 | if (priv->fingers < 2) { | 851 | switch (psmouse->pktcnt) { |
887 | x1 = x; | 852 | case 3: |
888 | y1 = y; | 853 | return (psmouse->packet[2] & 0x40) == 0x40; |
889 | fingers = z > 0 ? 1 : 0; | 854 | case 4: |
890 | } else { | 855 | return (psmouse->packet[3] & 0x48) == 0x48; |
891 | fingers = priv->fingers; | 856 | case 6: |
892 | x1 = priv->x1; | 857 | return (psmouse->packet[5] & 0x40) == 0x00; |
893 | x2 = priv->x2; | ||
894 | y1 = priv->y1; | ||
895 | y2 = priv->y2; | ||
896 | } | 858 | } |
859 | return true; | ||
860 | } | ||
897 | 861 | ||
898 | if (z >= 64) | 862 | static unsigned char alps_get_packet_id_v7(char *byte) |
899 | input_report_key(dev, BTN_TOUCH, 1); | 863 | { |
864 | unsigned char packet_id; | ||
865 | |||
866 | if (byte[4] & 0x40) | ||
867 | packet_id = V7_PACKET_ID_TWO; | ||
868 | else if (byte[4] & 0x01) | ||
869 | packet_id = V7_PACKET_ID_MULTI; | ||
870 | else if ((byte[0] & 0x10) && !(byte[4] & 0x43)) | ||
871 | packet_id = V7_PACKET_ID_NEW; | ||
872 | else if (byte[1] == 0x00 && byte[4] == 0x00) | ||
873 | packet_id = V7_PACKET_ID_IDLE; | ||
900 | else | 874 | else |
901 | input_report_key(dev, BTN_TOUCH, 0); | 875 | packet_id = V7_PACKET_ID_UNKNOWN; |
902 | 876 | ||
903 | alps_report_semi_mt_data(dev, fingers, x1, y1, x2, y2); | 877 | return packet_id; |
878 | } | ||
904 | 879 | ||
905 | input_mt_report_finger_count(dev, fingers); | 880 | static void alps_get_finger_coordinate_v7(struct input_mt_pos *mt, |
881 | unsigned char *pkt, | ||
882 | unsigned char pkt_id) | ||
883 | { | ||
884 | mt[0].x = ((pkt[2] & 0x80) << 4); | ||
885 | mt[0].x |= ((pkt[2] & 0x3F) << 5); | ||
886 | mt[0].x |= ((pkt[3] & 0x30) >> 1); | ||
887 | mt[0].x |= (pkt[3] & 0x07); | ||
888 | mt[0].y = (pkt[1] << 3) | (pkt[0] & 0x07); | ||
889 | |||
890 | mt[1].x = ((pkt[3] & 0x80) << 4); | ||
891 | mt[1].x |= ((pkt[4] & 0x80) << 3); | ||
892 | mt[1].x |= ((pkt[4] & 0x3F) << 4); | ||
893 | mt[1].y = ((pkt[5] & 0x80) << 3); | ||
894 | mt[1].y |= ((pkt[5] & 0x3F) << 4); | ||
895 | |||
896 | switch (pkt_id) { | ||
897 | case V7_PACKET_ID_TWO: | ||
898 | mt[1].x &= ~0x000F; | ||
899 | mt[1].y |= 0x000F; | ||
900 | break; | ||
906 | 901 | ||
907 | input_report_key(dev, BTN_LEFT, left); | 902 | case V7_PACKET_ID_MULTI: |
908 | input_report_key(dev, BTN_RIGHT, right); | 903 | mt[1].x &= ~0x003F; |
904 | mt[1].y &= ~0x0020; | ||
905 | mt[1].y |= ((pkt[4] & 0x02) << 4); | ||
906 | mt[1].y |= 0x001F; | ||
907 | break; | ||
909 | 908 | ||
910 | if (z > 0) { | 909 | case V7_PACKET_ID_NEW: |
911 | input_report_abs(dev, ABS_X, x); | 910 | mt[1].x &= ~0x003F; |
912 | input_report_abs(dev, ABS_Y, y); | 911 | mt[1].x |= (pkt[0] & 0x20); |
912 | mt[1].y |= 0x000F; | ||
913 | break; | ||
913 | } | 914 | } |
914 | input_report_abs(dev, ABS_PRESSURE, z); | 915 | |
916 | mt[0].y = 0x7FF - mt[0].y; | ||
917 | mt[1].y = 0x7FF - mt[1].y; | ||
918 | } | ||
919 | |||
920 | static int alps_get_mt_count(struct input_mt_pos *mt) | ||
921 | { | ||
922 | int i; | ||
923 | |||
924 | for (i = 0; i < MAX_TOUCHES && mt[i].x != 0 && mt[i].y != 0; i++) | ||
925 | /* empty */; | ||
926 | |||
927 | return i; | ||
928 | } | ||
929 | |||
930 | static int alps_decode_packet_v7(struct alps_fields *f, | ||
931 | unsigned char *p, | ||
932 | struct psmouse *psmouse) | ||
933 | { | ||
934 | unsigned char pkt_id; | ||
935 | |||
936 | pkt_id = alps_get_packet_id_v7(p); | ||
937 | if (pkt_id == V7_PACKET_ID_IDLE) | ||
938 | return 0; | ||
939 | if (pkt_id == V7_PACKET_ID_UNKNOWN) | ||
940 | return -1; | ||
941 | |||
942 | alps_get_finger_coordinate_v7(f->mt, p, pkt_id); | ||
943 | |||
944 | if (pkt_id == V7_PACKET_ID_TWO || pkt_id == V7_PACKET_ID_MULTI) { | ||
945 | f->left = (p[0] & 0x80) >> 7; | ||
946 | f->right = (p[0] & 0x20) >> 5; | ||
947 | f->middle = (p[0] & 0x10) >> 4; | ||
948 | } | ||
949 | |||
950 | if (pkt_id == V7_PACKET_ID_TWO) | ||
951 | f->fingers = alps_get_mt_count(f->mt); | ||
952 | else if (pkt_id == V7_PACKET_ID_MULTI) | ||
953 | f->fingers = 3 + (p[5] & 0x03); | ||
954 | |||
955 | return 0; | ||
956 | } | ||
957 | |||
958 | static void alps_process_trackstick_packet_v7(struct psmouse *psmouse) | ||
959 | { | ||
960 | struct alps_data *priv = psmouse->private; | ||
961 | unsigned char *packet = psmouse->packet; | ||
962 | struct input_dev *dev2 = priv->dev2; | ||
963 | int x, y, z, left, right, middle; | ||
964 | |||
965 | /* | ||
966 | * b7 b6 b5 b4 b3 b2 b1 b0 | ||
967 | * Byte0 0 1 0 0 1 0 0 0 | ||
968 | * Byte1 1 1 * * 1 M R L | ||
969 | * Byte2 X7 1 X5 X4 X3 X2 X1 X0 | ||
970 | * Byte3 Z6 1 Y6 X6 1 Y2 Y1 Y0 | ||
971 | * Byte4 Y7 0 Y5 Y4 Y3 1 1 0 | ||
972 | * Byte5 T&P 0 Z5 Z4 Z3 Z2 Z1 Z0 | ||
973 | * M / R / L: Middle / Right / Left button | ||
974 | */ | ||
975 | |||
976 | x = ((packet[2] & 0xbf)) | ((packet[3] & 0x10) << 2); | ||
977 | y = (packet[3] & 0x07) | (packet[4] & 0xb8) | | ||
978 | ((packet[3] & 0x20) << 1); | ||
979 | z = (packet[5] & 0x3f) | ((packet[3] & 0x80) >> 1); | ||
980 | |||
981 | left = (packet[1] & 0x01); | ||
982 | right = (packet[1] & 0x02) >> 1; | ||
983 | middle = (packet[1] & 0x04) >> 2; | ||
984 | |||
985 | /* Divide 2 since trackpoint's speed is too fast */ | ||
986 | input_report_rel(dev2, REL_X, (char)x / 2); | ||
987 | input_report_rel(dev2, REL_Y, -((char)y / 2)); | ||
988 | |||
989 | input_report_key(dev2, BTN_LEFT, left); | ||
990 | input_report_key(dev2, BTN_RIGHT, right); | ||
991 | input_report_key(dev2, BTN_MIDDLE, middle); | ||
992 | |||
993 | input_sync(dev2); | ||
994 | } | ||
995 | |||
996 | static void alps_process_touchpad_packet_v7(struct psmouse *psmouse) | ||
997 | { | ||
998 | struct alps_data *priv = psmouse->private; | ||
999 | struct input_dev *dev = psmouse->dev; | ||
1000 | struct alps_fields *f = &priv->f; | ||
1001 | |||
1002 | memset(f, 0, sizeof(*f)); | ||
1003 | |||
1004 | if (priv->decode_fields(f, psmouse->packet, psmouse)) | ||
1005 | return; | ||
1006 | |||
1007 | alps_report_mt_data(psmouse, alps_get_mt_count(f->mt)); | ||
1008 | |||
1009 | input_mt_report_finger_count(dev, f->fingers); | ||
1010 | |||
1011 | input_report_key(dev, BTN_LEFT, f->left); | ||
1012 | input_report_key(dev, BTN_RIGHT, f->right); | ||
1013 | input_report_key(dev, BTN_MIDDLE, f->middle); | ||
915 | 1014 | ||
916 | input_sync(dev); | 1015 | input_sync(dev); |
917 | } | 1016 | } |
918 | 1017 | ||
1018 | static void alps_process_packet_v7(struct psmouse *psmouse) | ||
1019 | { | ||
1020 | unsigned char *packet = psmouse->packet; | ||
1021 | |||
1022 | if (packet[0] == 0x48 && (packet[4] & 0x47) == 0x06) | ||
1023 | alps_process_trackstick_packet_v7(psmouse); | ||
1024 | else | ||
1025 | alps_process_touchpad_packet_v7(psmouse); | ||
1026 | } | ||
1027 | |||
919 | static void alps_report_bare_ps2_packet(struct psmouse *psmouse, | 1028 | static void alps_report_bare_ps2_packet(struct psmouse *psmouse, |
920 | unsigned char packet[], | 1029 | unsigned char packet[], |
921 | bool report_buttons) | 1030 | bool report_buttons) |
@@ -1080,6 +1189,14 @@ static psmouse_ret_t alps_process_byte(struct psmouse *psmouse) | |||
1080 | return PSMOUSE_BAD_DATA; | 1189 | return PSMOUSE_BAD_DATA; |
1081 | } | 1190 | } |
1082 | 1191 | ||
1192 | if (priv->proto_version == ALPS_PROTO_V7 && | ||
1193 | !alps_is_valid_package_v7(psmouse)) { | ||
1194 | psmouse_dbg(psmouse, "refusing packet[%i] = %x\n", | ||
1195 | psmouse->pktcnt - 1, | ||
1196 | psmouse->packet[psmouse->pktcnt - 1]); | ||
1197 | return PSMOUSE_BAD_DATA; | ||
1198 | } | ||
1199 | |||
1083 | if (psmouse->pktcnt == psmouse->pktsize) { | 1200 | if (psmouse->pktcnt == psmouse->pktsize) { |
1084 | priv->process_packet(psmouse); | 1201 | priv->process_packet(psmouse); |
1085 | return PSMOUSE_FULL_PACKET; | 1202 | return PSMOUSE_FULL_PACKET; |
@@ -1192,6 +1309,22 @@ static int alps_rpt_cmd(struct psmouse *psmouse, int init_command, | |||
1192 | return 0; | 1309 | return 0; |
1193 | } | 1310 | } |
1194 | 1311 | ||
1312 | static bool alps_check_valid_firmware_id(unsigned char id[]) | ||
1313 | { | ||
1314 | if (id[0] == 0x73) | ||
1315 | return true; | ||
1316 | |||
1317 | if (id[0] == 0x88 && | ||
1318 | (id[1] == 0x07 || | ||
1319 | id[1] == 0x08 || | ||
1320 | (id[1] & 0xf0) == 0xb0 || | ||
1321 | (id[1] & 0xf0) == 0xc0)) { | ||
1322 | return true; | ||
1323 | } | ||
1324 | |||
1325 | return false; | ||
1326 | } | ||
1327 | |||
1195 | static int alps_enter_command_mode(struct psmouse *psmouse) | 1328 | static int alps_enter_command_mode(struct psmouse *psmouse) |
1196 | { | 1329 | { |
1197 | unsigned char param[4]; | 1330 | unsigned char param[4]; |
@@ -1201,8 +1334,7 @@ static int alps_enter_command_mode(struct psmouse *psmouse) | |||
1201 | return -1; | 1334 | return -1; |
1202 | } | 1335 | } |
1203 | 1336 | ||
1204 | if ((param[0] != 0x88 || (param[1] != 0x07 && param[1] != 0x08)) && | 1337 | if (!alps_check_valid_firmware_id(param)) { |
1205 | param[0] != 0x73) { | ||
1206 | psmouse_dbg(psmouse, | 1338 | psmouse_dbg(psmouse, |
1207 | "unknown response while entering command mode\n"); | 1339 | "unknown response while entering command mode\n"); |
1208 | return -1; | 1340 | return -1; |
@@ -1660,6 +1792,45 @@ error: | |||
1660 | return -1; | 1792 | return -1; |
1661 | } | 1793 | } |
1662 | 1794 | ||
1795 | static int alps_get_v3_v7_resolution(struct psmouse *psmouse, int reg_pitch) | ||
1796 | { | ||
1797 | int reg, x_pitch, y_pitch, x_electrode, y_electrode, x_phys, y_phys; | ||
1798 | struct alps_data *priv = psmouse->private; | ||
1799 | |||
1800 | reg = alps_command_mode_read_reg(psmouse, reg_pitch); | ||
1801 | if (reg < 0) | ||
1802 | return reg; | ||
1803 | |||
1804 | x_pitch = (char)(reg << 4) >> 4; /* sign extend lower 4 bits */ | ||
1805 | x_pitch = 50 + 2 * x_pitch; /* In 0.1 mm units */ | ||
1806 | |||
1807 | y_pitch = (char)reg >> 4; /* sign extend upper 4 bits */ | ||
1808 | y_pitch = 36 + 2 * y_pitch; /* In 0.1 mm units */ | ||
1809 | |||
1810 | reg = alps_command_mode_read_reg(psmouse, reg_pitch + 1); | ||
1811 | if (reg < 0) | ||
1812 | return reg; | ||
1813 | |||
1814 | x_electrode = (char)(reg << 4) >> 4; /* sign extend lower 4 bits */ | ||
1815 | x_electrode = 17 + x_electrode; | ||
1816 | |||
1817 | y_electrode = (char)reg >> 4; /* sign extend upper 4 bits */ | ||
1818 | y_electrode = 13 + y_electrode; | ||
1819 | |||
1820 | x_phys = x_pitch * (x_electrode - 1); /* In 0.1 mm units */ | ||
1821 | y_phys = y_pitch * (y_electrode - 1); /* In 0.1 mm units */ | ||
1822 | |||
1823 | priv->x_res = priv->x_max * 10 / x_phys; /* units / mm */ | ||
1824 | priv->y_res = priv->y_max * 10 / y_phys; /* units / mm */ | ||
1825 | |||
1826 | psmouse_dbg(psmouse, | ||
1827 | "pitch %dx%d num-electrodes %dx%d physical size %dx%d mm res %dx%d\n", | ||
1828 | x_pitch, y_pitch, x_electrode, y_electrode, | ||
1829 | x_phys / 10, y_phys / 10, priv->x_res, priv->y_res); | ||
1830 | |||
1831 | return 0; | ||
1832 | } | ||
1833 | |||
1663 | static int alps_hw_init_rushmore_v3(struct psmouse *psmouse) | 1834 | static int alps_hw_init_rushmore_v3(struct psmouse *psmouse) |
1664 | { | 1835 | { |
1665 | struct alps_data *priv = psmouse->private; | 1836 | struct alps_data *priv = psmouse->private; |
@@ -1680,6 +1851,9 @@ static int alps_hw_init_rushmore_v3(struct psmouse *psmouse) | |||
1680 | alps_command_mode_write_reg(psmouse, 0xc2cb, 0x00)) | 1851 | alps_command_mode_write_reg(psmouse, 0xc2cb, 0x00)) |
1681 | goto error; | 1852 | goto error; |
1682 | 1853 | ||
1854 | if (alps_get_v3_v7_resolution(psmouse, 0xc2da)) | ||
1855 | goto error; | ||
1856 | |||
1683 | reg_val = alps_command_mode_read_reg(psmouse, 0xc2c6); | 1857 | reg_val = alps_command_mode_read_reg(psmouse, 0xc2c6); |
1684 | if (reg_val == -1) | 1858 | if (reg_val == -1) |
1685 | goto error; | 1859 | goto error; |
@@ -1856,6 +2030,35 @@ static int alps_hw_init_dolphin_v1(struct psmouse *psmouse) | |||
1856 | return 0; | 2030 | return 0; |
1857 | } | 2031 | } |
1858 | 2032 | ||
2033 | static int alps_hw_init_v7(struct psmouse *psmouse) | ||
2034 | { | ||
2035 | struct ps2dev *ps2dev = &psmouse->ps2dev; | ||
2036 | int reg_val, ret = -1; | ||
2037 | |||
2038 | if (alps_enter_command_mode(psmouse) || | ||
2039 | alps_command_mode_read_reg(psmouse, 0xc2d9) == -1) | ||
2040 | goto error; | ||
2041 | |||
2042 | if (alps_get_v3_v7_resolution(psmouse, 0xc397)) | ||
2043 | goto error; | ||
2044 | |||
2045 | if (alps_command_mode_write_reg(psmouse, 0xc2c9, 0x64)) | ||
2046 | goto error; | ||
2047 | |||
2048 | reg_val = alps_command_mode_read_reg(psmouse, 0xc2c4); | ||
2049 | if (reg_val == -1) | ||
2050 | goto error; | ||
2051 | if (__alps_command_mode_write_reg(psmouse, reg_val | 0x02)) | ||
2052 | goto error; | ||
2053 | |||
2054 | alps_exit_command_mode(psmouse); | ||
2055 | return ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE); | ||
2056 | |||
2057 | error: | ||
2058 | alps_exit_command_mode(psmouse); | ||
2059 | return ret; | ||
2060 | } | ||
2061 | |||
1859 | static void alps_set_defaults(struct alps_data *priv) | 2062 | static void alps_set_defaults(struct alps_data *priv) |
1860 | { | 2063 | { |
1861 | priv->byte0 = 0x8f; | 2064 | priv->byte0 = 0x8f; |
@@ -1914,6 +2117,21 @@ static void alps_set_defaults(struct alps_data *priv) | |||
1914 | priv->x_max = 2047; | 2117 | priv->x_max = 2047; |
1915 | priv->y_max = 1535; | 2118 | priv->y_max = 1535; |
1916 | break; | 2119 | break; |
2120 | case ALPS_PROTO_V7: | ||
2121 | priv->hw_init = alps_hw_init_v7; | ||
2122 | priv->process_packet = alps_process_packet_v7; | ||
2123 | priv->decode_fields = alps_decode_packet_v7; | ||
2124 | priv->set_abs_params = alps_set_abs_params_mt; | ||
2125 | priv->nibble_commands = alps_v3_nibble_commands; | ||
2126 | priv->addr_command = PSMOUSE_CMD_RESET_WRAP; | ||
2127 | priv->x_max = 0xfff; | ||
2128 | priv->y_max = 0x7ff; | ||
2129 | priv->byte0 = 0x48; | ||
2130 | priv->mask0 = 0x48; | ||
2131 | |||
2132 | if (priv->fw_ver[1] != 0xba) | ||
2133 | priv->flags |= ALPS_BUTTONPAD; | ||
2134 | break; | ||
1917 | } | 2135 | } |
1918 | } | 2136 | } |
1919 | 2137 | ||
@@ -1972,6 +2190,9 @@ static int alps_identify(struct psmouse *psmouse, struct alps_data *priv) | |||
1972 | alps_exit_command_mode(psmouse)) | 2190 | alps_exit_command_mode(psmouse)) |
1973 | return -EIO; | 2191 | return -EIO; |
1974 | 2192 | ||
2193 | /* Save the Firmware version */ | ||
2194 | memcpy(priv->fw_ver, ec, 3); | ||
2195 | |||
1975 | if (alps_match_table(psmouse, priv, e7, ec) == 0) { | 2196 | if (alps_match_table(psmouse, priv, e7, ec) == 0) { |
1976 | return 0; | 2197 | return 0; |
1977 | } else if (e7[0] == 0x73 && e7[1] == 0x03 && e7[2] == 0x50 && | 2198 | } else if (e7[0] == 0x73 && e7[1] == 0x03 && e7[2] == 0x50 && |
@@ -1982,6 +2203,12 @@ static int alps_identify(struct psmouse *psmouse, struct alps_data *priv) | |||
1982 | return -EIO; | 2203 | return -EIO; |
1983 | else | 2204 | else |
1984 | return 0; | 2205 | return 0; |
2206 | } else if (ec[0] == 0x88 && | ||
2207 | ((ec[1] & 0xf0) == 0xb0 || (ec[1] & 0xf0) == 0xc0)) { | ||
2208 | priv->proto_version = ALPS_PROTO_V7; | ||
2209 | alps_set_defaults(priv); | ||
2210 | |||
2211 | return 0; | ||
1985 | } else if (ec[0] == 0x88 && ec[1] == 0x08) { | 2212 | } else if (ec[0] == 0x88 && ec[1] == 0x08) { |
1986 | priv->proto_version = ALPS_PROTO_V3; | 2213 | priv->proto_version = ALPS_PROTO_V3; |
1987 | alps_set_defaults(priv); | 2214 | alps_set_defaults(priv); |
@@ -1990,6 +2217,7 @@ static int alps_identify(struct psmouse *psmouse, struct alps_data *priv) | |||
1990 | priv->decode_fields = alps_decode_rushmore; | 2217 | priv->decode_fields = alps_decode_rushmore; |
1991 | priv->x_bits = 16; | 2218 | priv->x_bits = 16; |
1992 | priv->y_bits = 12; | 2219 | priv->y_bits = 12; |
2220 | priv->flags |= ALPS_IS_RUSHMORE; | ||
1993 | 2221 | ||
1994 | /* hack to make addr_command, nibble_command available */ | 2222 | /* hack to make addr_command, nibble_command available */ |
1995 | psmouse->private = priv; | 2223 | psmouse->private = priv; |
@@ -2044,17 +2272,21 @@ static void alps_set_abs_params_st(struct alps_data *priv, | |||
2044 | static void alps_set_abs_params_mt(struct alps_data *priv, | 2272 | static void alps_set_abs_params_mt(struct alps_data *priv, |
2045 | struct input_dev *dev1) | 2273 | struct input_dev *dev1) |
2046 | { | 2274 | { |
2047 | set_bit(INPUT_PROP_SEMI_MT, dev1->propbit); | ||
2048 | input_mt_init_slots(dev1, 2, 0); | ||
2049 | input_set_abs_params(dev1, ABS_MT_POSITION_X, 0, priv->x_max, 0, 0); | 2275 | input_set_abs_params(dev1, ABS_MT_POSITION_X, 0, priv->x_max, 0, 0); |
2050 | input_set_abs_params(dev1, ABS_MT_POSITION_Y, 0, priv->y_max, 0, 0); | 2276 | input_set_abs_params(dev1, ABS_MT_POSITION_Y, 0, priv->y_max, 0, 0); |
2051 | 2277 | ||
2052 | set_bit(BTN_TOOL_DOUBLETAP, dev1->keybit); | 2278 | input_abs_set_res(dev1, ABS_MT_POSITION_X, priv->x_res); |
2279 | input_abs_set_res(dev1, ABS_MT_POSITION_Y, priv->y_res); | ||
2280 | |||
2281 | input_mt_init_slots(dev1, MAX_TOUCHES, INPUT_MT_POINTER | | ||
2282 | INPUT_MT_DROP_UNUSED | INPUT_MT_TRACK | INPUT_MT_SEMI_MT); | ||
2283 | |||
2053 | set_bit(BTN_TOOL_TRIPLETAP, dev1->keybit); | 2284 | set_bit(BTN_TOOL_TRIPLETAP, dev1->keybit); |
2054 | set_bit(BTN_TOOL_QUADTAP, dev1->keybit); | 2285 | set_bit(BTN_TOOL_QUADTAP, dev1->keybit); |
2055 | 2286 | ||
2056 | input_set_abs_params(dev1, ABS_X, 0, priv->x_max, 0, 0); | 2287 | /* V7 is real multi-touch */ |
2057 | input_set_abs_params(dev1, ABS_Y, 0, priv->y_max, 0, 0); | 2288 | if (priv->proto_version == ALPS_PROTO_V7) |
2289 | clear_bit(INPUT_PROP_SEMI_MT, dev1->propbit); | ||
2058 | } | 2290 | } |
2059 | 2291 | ||
2060 | int alps_init(struct psmouse *psmouse) | 2292 | int alps_init(struct psmouse *psmouse) |
@@ -2100,7 +2332,9 @@ int alps_init(struct psmouse *psmouse) | |||
2100 | dev1->evbit[BIT_WORD(EV_ABS)] |= BIT_MASK(EV_ABS); | 2332 | dev1->evbit[BIT_WORD(EV_ABS)] |= BIT_MASK(EV_ABS); |
2101 | 2333 | ||
2102 | priv->set_abs_params(priv, dev1); | 2334 | priv->set_abs_params(priv, dev1); |
2103 | input_set_abs_params(dev1, ABS_PRESSURE, 0, 127, 0, 0); | 2335 | /* No pressure on V7 */ |
2336 | if (priv->proto_version != ALPS_PROTO_V7) | ||
2337 | input_set_abs_params(dev1, ABS_PRESSURE, 0, 127, 0, 0); | ||
2104 | 2338 | ||
2105 | if (priv->flags & ALPS_WHEEL) { | 2339 | if (priv->flags & ALPS_WHEEL) { |
2106 | dev1->evbit[BIT_WORD(EV_REL)] |= BIT_MASK(EV_REL); | 2340 | dev1->evbit[BIT_WORD(EV_REL)] |= BIT_MASK(EV_REL); |
@@ -2117,6 +2351,9 @@ int alps_init(struct psmouse *psmouse) | |||
2117 | dev1->keybit[BIT_WORD(BTN_1)] |= BIT_MASK(BTN_1); | 2351 | dev1->keybit[BIT_WORD(BTN_1)] |= BIT_MASK(BTN_1); |
2118 | dev1->keybit[BIT_WORD(BTN_2)] |= BIT_MASK(BTN_2); | 2352 | dev1->keybit[BIT_WORD(BTN_2)] |= BIT_MASK(BTN_2); |
2119 | dev1->keybit[BIT_WORD(BTN_3)] |= BIT_MASK(BTN_3); | 2353 | dev1->keybit[BIT_WORD(BTN_3)] |= BIT_MASK(BTN_3); |
2354 | } else if (priv->flags & ALPS_BUTTONPAD) { | ||
2355 | set_bit(INPUT_PROP_BUTTONPAD, dev1->propbit); | ||
2356 | clear_bit(BTN_RIGHT, dev1->keybit); | ||
2120 | } else { | 2357 | } else { |
2121 | dev1->keybit[BIT_WORD(BTN_MIDDLE)] |= BIT_MASK(BTN_MIDDLE); | 2358 | dev1->keybit[BIT_WORD(BTN_MIDDLE)] |= BIT_MASK(BTN_MIDDLE); |
2122 | } | 2359 | } |