aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/extcon/extcon-arizona.c
diff options
context:
space:
mode:
authorMark Brown <broonie@opensource.wolfsonmicro.com>2013-02-25 18:42:31 -0500
committerMark Brown <broonie@opensource.wolfsonmicro.com>2013-04-02 06:54:02 -0400
commit9c2ba270eaa227c999af451e1c2c9bf0d24aa8e5 (patch)
tree458b02da9a45743fce367c582f35bbf92c7fee24 /drivers/extcon/extcon-arizona.c
parentdb924ff5c7297cca85eb0faa79ea29e988f96420 (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.c46
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
462static int arizona_hpdet_do_id(struct arizona_extcon_info *info, int *reading) 462static 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:
681static void arizona_start_hpdet_acc_id(struct arizona_extcon_info *info) 677static 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;