Skip to content

Commit

Permalink
extcon: arizona: Simplify HPDET based identification
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Mark Brown committed Apr 2, 2013
1 parent db924ff commit 9c2ba27
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 21 deletions.
46 changes: 25 additions & 21 deletions drivers/extcon/extcon-arizona.c
Original file line number Diff line number Diff line change
Expand Up @@ -459,7 +459,8 @@ static int arizona_hpdet_read(struct arizona_extcon_info *info)
return val;
}

static int arizona_hpdet_do_id(struct arizona_extcon_info *info, int *reading)
static int arizona_hpdet_do_id(struct arizona_extcon_info *info, int *reading,
bool *mic)
{
struct arizona *arizona = info->arizona;
int id_gpio = arizona->pdata.hpdet_id_gpio;
Expand All @@ -470,11 +471,9 @@ static int arizona_hpdet_do_id(struct arizona_extcon_info *info, int *reading)
*/
if (arizona->pdata.hpdet_acc_id) {
info->hpdet_res[info->num_hpdet_res++] = *reading;
info->hpdet_res[info->num_hpdet_res++] = *reading;

/* Only check the mic directly if we didn't already ID it */
if (id_gpio && info->num_hpdet_res == 2 &&
!((info->hpdet_res[0] > info->hpdet_res[1] * 2))) {
if (id_gpio && info->num_hpdet_res == 1) {
dev_dbg(arizona->dev, "Measuring mic\n");

regmap_update_bits(arizona->regmap,
Expand All @@ -493,10 +492,8 @@ static int arizona_hpdet_do_id(struct arizona_extcon_info *info, int *reading)
}

/* OK, got both. Now, compare... */
dev_dbg(arizona->dev, "HPDET measured %d %d %d\n",
info->hpdet_res[0], info->hpdet_res[1],
info->hpdet_res[2]);

dev_dbg(arizona->dev, "HPDET measured %d %d\n",
info->hpdet_res[0], info->hpdet_res[1]);

/* Take the headphone impedance for the main report */
*reading = info->hpdet_res[0];
Expand All @@ -512,13 +509,11 @@ static int arizona_hpdet_do_id(struct arizona_extcon_info *info, int *reading)
}

/*
* Either the two grounds measure differently or we
* measure the mic as high impedance.
* If we measure the mic as
*/
if ((info->hpdet_res[0] > info->hpdet_res[1] * 2) ||
(id_gpio && info->hpdet_res[2] > 1257)) {
if (!id_gpio || info->hpdet_res[1] > 50) {
dev_dbg(arizona->dev, "Detected mic\n");
info->mic = true;
*mic = true;
info->detecting = true;
} else {
dev_dbg(arizona->dev, "Detected headphone\n");
Expand All @@ -541,6 +536,7 @@ static irqreturn_t arizona_hpdet_irq(int irq, void *data)
int id_gpio = arizona->pdata.hpdet_id_gpio;
int report = ARIZONA_CABLE_HEADPHONE;
int ret, reading;
bool mic = false;

mutex_lock(&info->lock);

Expand Down Expand Up @@ -576,7 +572,7 @@ static irqreturn_t arizona_hpdet_irq(int irq, void *data)
ARIZONA_HP_IMPEDANCE_RANGE_MASK | ARIZONA_HP_POLL,
0);

ret = arizona_hpdet_do_id(info, &reading);
ret = arizona_hpdet_do_id(info, &reading, &mic);
if (ret == -EAGAIN) {
goto out;
} else if (ret < 0) {
Expand Down Expand Up @@ -606,7 +602,7 @@ static irqreturn_t arizona_hpdet_irq(int irq, void *data)
ARIZONA_ACCDET_MODE_MASK, ARIZONA_ACCDET_MODE_MIC);

/* If we have a mic then reenable MICDET */
if (info->mic)
if (mic || info->mic)
arizona_start_mic(info);

if (info->hpdet_active) {
Expand Down Expand Up @@ -681,6 +677,8 @@ static void arizona_identify_headphone(struct arizona_extcon_info *info)
static void arizona_start_hpdet_acc_id(struct arizona_extcon_info *info)
{
struct arizona *arizona = info->arizona;
int hp_reading = 32;
bool mic;
int ret;

dev_dbg(arizona->dev, "Starting identification via HPDET\n");
Expand All @@ -702,12 +700,18 @@ static void arizona_start_hpdet_acc_id(struct arizona_extcon_info *info)
goto err;
}

ret = regmap_update_bits(arizona->regmap, ARIZONA_HEADPHONE_DETECT_1,
ARIZONA_HP_POLL, ARIZONA_HP_POLL);
if (ret != 0) {
dev_err(arizona->dev, "Can't start HPDETL measurement: %d\n",
ret);
goto err;
if (arizona->pdata.hpdet_acc_id_line) {
ret = regmap_update_bits(arizona->regmap,
ARIZONA_HEADPHONE_DETECT_1,
ARIZONA_HP_POLL, ARIZONA_HP_POLL);
if (ret != 0) {
dev_err(arizona->dev,
"Can't start HPDETL measurement: %d\n",
ret);
goto err;
}
} else {
arizona_hpdet_do_id(info, &hp_reading, &mic);
}

return;
Expand Down
3 changes: 3 additions & 0 deletions include/linux/mfd/arizona/pdata.h
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,9 @@ struct arizona_pdata {
/** Use the headphone detect circuit to identify the accessory */
bool hpdet_acc_id;

/** Check for line output with HPDET method */
bool hpdet_acc_id_line;

/** GPIO used for mic isolation with HPDET */
int hpdet_id_gpio;

Expand Down

0 comments on commit 9c2ba27

Please sign in to comment.