diff options
author | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2013-02-25 18:42:31 -0500 |
---|---|---|
committer | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2013-04-02 06:54:02 -0400 |
commit | 9c2ba270eaa227c999af451e1c2c9bf0d24aa8e5 (patch) | |
tree | 458b02da9a45743fce367c582f35bbf92c7fee24 /drivers/extcon/extcon-arizona.c | |
parent | db924ff5c7297cca85eb0faa79ea29e988f96420 (diff) |
extcon: arizona: Simplify HPDET based identification
Rather than measuring both HP channels we can simply directly measure the
microphone impedance and then rely on MICDET for final confirmation of the
presence of a suitable microphone. This improves the overall performance
of the identification process.
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'drivers/extcon/extcon-arizona.c')
-rw-r--r-- | drivers/extcon/extcon-arizona.c | 46 |
1 files changed, 25 insertions, 21 deletions
diff --git a/drivers/extcon/extcon-arizona.c b/drivers/extcon/extcon-arizona.c index 7c4ce812d735..a83ca27aa99f 100644 --- a/drivers/extcon/extcon-arizona.c +++ b/drivers/extcon/extcon-arizona.c | |||
@@ -459,7 +459,8 @@ static int arizona_hpdet_read(struct arizona_extcon_info *info) | |||
459 | return val; | 459 | return val; |
460 | } | 460 | } |
461 | 461 | ||
462 | static int arizona_hpdet_do_id(struct arizona_extcon_info *info, int *reading) | 462 | static int arizona_hpdet_do_id(struct arizona_extcon_info *info, int *reading, |
463 | bool *mic) | ||
463 | { | 464 | { |
464 | struct arizona *arizona = info->arizona; | 465 | struct arizona *arizona = info->arizona; |
465 | int id_gpio = arizona->pdata.hpdet_id_gpio; | 466 | int id_gpio = arizona->pdata.hpdet_id_gpio; |
@@ -470,11 +471,9 @@ static int arizona_hpdet_do_id(struct arizona_extcon_info *info, int *reading) | |||
470 | */ | 471 | */ |
471 | if (arizona->pdata.hpdet_acc_id) { | 472 | if (arizona->pdata.hpdet_acc_id) { |
472 | info->hpdet_res[info->num_hpdet_res++] = *reading; | 473 | info->hpdet_res[info->num_hpdet_res++] = *reading; |
473 | info->hpdet_res[info->num_hpdet_res++] = *reading; | ||
474 | 474 | ||
475 | /* Only check the mic directly if we didn't already ID it */ | 475 | /* Only check the mic directly if we didn't already ID it */ |
476 | if (id_gpio && info->num_hpdet_res == 2 && | 476 | if (id_gpio && info->num_hpdet_res == 1) { |
477 | !((info->hpdet_res[0] > info->hpdet_res[1] * 2))) { | ||
478 | dev_dbg(arizona->dev, "Measuring mic\n"); | 477 | dev_dbg(arizona->dev, "Measuring mic\n"); |
479 | 478 | ||
480 | regmap_update_bits(arizona->regmap, | 479 | regmap_update_bits(arizona->regmap, |
@@ -493,10 +492,8 @@ static int arizona_hpdet_do_id(struct arizona_extcon_info *info, int *reading) | |||
493 | } | 492 | } |
494 | 493 | ||
495 | /* OK, got both. Now, compare... */ | 494 | /* OK, got both. Now, compare... */ |
496 | dev_dbg(arizona->dev, "HPDET measured %d %d %d\n", | 495 | dev_dbg(arizona->dev, "HPDET measured %d %d\n", |
497 | info->hpdet_res[0], info->hpdet_res[1], | 496 | info->hpdet_res[0], info->hpdet_res[1]); |
498 | info->hpdet_res[2]); | ||
499 | |||
500 | 497 | ||
501 | /* Take the headphone impedance for the main report */ | 498 | /* Take the headphone impedance for the main report */ |
502 | *reading = info->hpdet_res[0]; | 499 | *reading = info->hpdet_res[0]; |
@@ -512,13 +509,11 @@ static int arizona_hpdet_do_id(struct arizona_extcon_info *info, int *reading) | |||
512 | } | 509 | } |
513 | 510 | ||
514 | /* | 511 | /* |
515 | * Either the two grounds measure differently or we | 512 | * If we measure the mic as |
516 | * measure the mic as high impedance. | ||
517 | */ | 513 | */ |
518 | if ((info->hpdet_res[0] > info->hpdet_res[1] * 2) || | 514 | if (!id_gpio || info->hpdet_res[1] > 50) { |
519 | (id_gpio && info->hpdet_res[2] > 1257)) { | ||
520 | dev_dbg(arizona->dev, "Detected mic\n"); | 515 | dev_dbg(arizona->dev, "Detected mic\n"); |
521 | info->mic = true; | 516 | *mic = true; |
522 | info->detecting = true; | 517 | info->detecting = true; |
523 | } else { | 518 | } else { |
524 | dev_dbg(arizona->dev, "Detected headphone\n"); | 519 | dev_dbg(arizona->dev, "Detected headphone\n"); |
@@ -541,6 +536,7 @@ static irqreturn_t arizona_hpdet_irq(int irq, void *data) | |||
541 | int id_gpio = arizona->pdata.hpdet_id_gpio; | 536 | int id_gpio = arizona->pdata.hpdet_id_gpio; |
542 | int report = ARIZONA_CABLE_HEADPHONE; | 537 | int report = ARIZONA_CABLE_HEADPHONE; |
543 | int ret, reading; | 538 | int ret, reading; |
539 | bool mic = false; | ||
544 | 540 | ||
545 | mutex_lock(&info->lock); | 541 | mutex_lock(&info->lock); |
546 | 542 | ||
@@ -576,7 +572,7 @@ static irqreturn_t arizona_hpdet_irq(int irq, void *data) | |||
576 | ARIZONA_HP_IMPEDANCE_RANGE_MASK | ARIZONA_HP_POLL, | 572 | ARIZONA_HP_IMPEDANCE_RANGE_MASK | ARIZONA_HP_POLL, |
577 | 0); | 573 | 0); |
578 | 574 | ||
579 | ret = arizona_hpdet_do_id(info, &reading); | 575 | ret = arizona_hpdet_do_id(info, &reading, &mic); |
580 | if (ret == -EAGAIN) { | 576 | if (ret == -EAGAIN) { |
581 | goto out; | 577 | goto out; |
582 | } else if (ret < 0) { | 578 | } else if (ret < 0) { |
@@ -606,7 +602,7 @@ done: | |||
606 | ARIZONA_ACCDET_MODE_MASK, ARIZONA_ACCDET_MODE_MIC); | 602 | ARIZONA_ACCDET_MODE_MASK, ARIZONA_ACCDET_MODE_MIC); |
607 | 603 | ||
608 | /* If we have a mic then reenable MICDET */ | 604 | /* If we have a mic then reenable MICDET */ |
609 | if (info->mic) | 605 | if (mic || info->mic) |
610 | arizona_start_mic(info); | 606 | arizona_start_mic(info); |
611 | 607 | ||
612 | if (info->hpdet_active) { | 608 | if (info->hpdet_active) { |
@@ -681,6 +677,8 @@ err: | |||
681 | static void arizona_start_hpdet_acc_id(struct arizona_extcon_info *info) | 677 | static void arizona_start_hpdet_acc_id(struct arizona_extcon_info *info) |
682 | { | 678 | { |
683 | struct arizona *arizona = info->arizona; | 679 | struct arizona *arizona = info->arizona; |
680 | int hp_reading = 32; | ||
681 | bool mic; | ||
684 | int ret; | 682 | int ret; |
685 | 683 | ||
686 | dev_dbg(arizona->dev, "Starting identification via HPDET\n"); | 684 | dev_dbg(arizona->dev, "Starting identification via HPDET\n"); |
@@ -702,12 +700,18 @@ static void arizona_start_hpdet_acc_id(struct arizona_extcon_info *info) | |||
702 | goto err; | 700 | goto err; |
703 | } | 701 | } |
704 | 702 | ||
705 | ret = regmap_update_bits(arizona->regmap, ARIZONA_HEADPHONE_DETECT_1, | 703 | if (arizona->pdata.hpdet_acc_id_line) { |
706 | ARIZONA_HP_POLL, ARIZONA_HP_POLL); | 704 | ret = regmap_update_bits(arizona->regmap, |
707 | if (ret != 0) { | 705 | ARIZONA_HEADPHONE_DETECT_1, |
708 | dev_err(arizona->dev, "Can't start HPDETL measurement: %d\n", | 706 | ARIZONA_HP_POLL, ARIZONA_HP_POLL); |
709 | ret); | 707 | if (ret != 0) { |
710 | goto err; | 708 | dev_err(arizona->dev, |
709 | "Can't start HPDETL measurement: %d\n", | ||
710 | ret); | ||
711 | goto err; | ||
712 | } | ||
713 | } else { | ||
714 | arizona_hpdet_do_id(info, &hp_reading, &mic); | ||
711 | } | 715 | } |
712 | 716 | ||
713 | return; | 717 | return; |