Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 355073
b: refs/heads/master
c: bbbd46e
h: refs/heads/master
i:
  355071: e26e593
v: v3
  • Loading branch information
Mark Brown committed Feb 7, 2013
1 parent 9e0ebc4 commit 85f3a27
Show file tree
Hide file tree
Showing 4 changed files with 98 additions and 2 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 2e033db5ddf299de2ae568919d78b0258a5a6423
refs/heads/master: bbbd46e3d7fcdf1c8362bf1c83bcc08a93676cc9
2 changes: 1 addition & 1 deletion trunk/drivers/extcon/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ config EXTCON_MAX8997

config EXTCON_ARIZONA
tristate "Wolfson Arizona EXTCON support"
depends on MFD_ARIZONA && INPUT
depends on MFD_ARIZONA && INPUT && SND_SOC
help
Say Y here to enable support for external accessory detection
with Wolfson Arizona devices. These are audio CODECs with
Expand Down
93 changes: 93 additions & 0 deletions trunk/drivers/extcon/extcon-arizona.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
#include <linux/regulator/consumer.h>
#include <linux/extcon.h>

#include <sound/soc.h>

#include <linux/mfd/arizona/core.h>
#include <linux/mfd/arizona/pdata.h>
#include <linux/mfd/arizona/registers.h>
Expand Down Expand Up @@ -113,6 +115,52 @@ static void arizona_extcon_set_mode(struct arizona_extcon_info *info, int mode)
dev_dbg(arizona->dev, "Set jack polarity to %d\n", mode);
}

static const char *arizona_extcon_get_micbias(struct arizona_extcon_info *info)
{
switch (info->micd_modes[0].bias >> ARIZONA_MICD_BIAS_SRC_SHIFT) {
case 1:
return "MICBIAS1";
case 2:
return "MICBIAS2";
case 3:
return "MICBIAS3";
default:
return "MICVDD";
}
}

static void arizona_extcon_pulse_micbias(struct arizona_extcon_info *info)
{
struct arizona *arizona = info->arizona;
const char *widget = arizona_extcon_get_micbias(info);
struct snd_soc_dapm_context *dapm = arizona->dapm;
int ret;

mutex_lock(&dapm->card->dapm_mutex);

ret = snd_soc_dapm_force_enable_pin(dapm, widget);
if (ret != 0)
dev_warn(arizona->dev, "Failed to enable %s: %d\n",
widget, ret);

mutex_unlock(&dapm->card->dapm_mutex);

snd_soc_dapm_sync(dapm);

if (!arizona->pdata.micd_force_micbias) {
mutex_lock(&dapm->card->dapm_mutex);

ret = snd_soc_dapm_disable_pin(arizona->dapm, widget);
if (ret != 0)
dev_warn(arizona->dev, "Failed to disable %s: %d\n",
widget, ret);

mutex_unlock(&dapm->card->dapm_mutex);

snd_soc_dapm_sync(dapm);
}
}

static void arizona_start_mic(struct arizona_extcon_info *info)
{
struct arizona *arizona = info->arizona;
Expand All @@ -122,6 +170,15 @@ static void arizona_start_mic(struct arizona_extcon_info *info)
/* Microphone detection can't use idle mode */
pm_runtime_get(info->dev);

if (info->detecting) {
ret = regulator_allow_bypass(info->micvdd, false);
if (ret != 0) {
dev_err(arizona->dev,
"Failed to regulate MICVDD: %d\n",
ret);
}
}

ret = regulator_enable(info->micvdd);
if (ret != 0) {
dev_err(arizona->dev, "Failed to enable MICVDD: %d\n",
Expand All @@ -138,6 +195,8 @@ static void arizona_start_mic(struct arizona_extcon_info *info)
ARIZONA_ACCESSORY_DETECT_MODE_1,
ARIZONA_ACCDET_MODE_MASK, ARIZONA_ACCDET_MODE_MIC);

arizona_extcon_pulse_micbias(info);

regmap_update_bits_check(arizona->regmap, ARIZONA_MIC_DETECT_1,
ARIZONA_MICD_ENA, ARIZONA_MICD_ENA,
&change);
Expand All @@ -150,18 +209,39 @@ static void arizona_start_mic(struct arizona_extcon_info *info)
static void arizona_stop_mic(struct arizona_extcon_info *info)
{
struct arizona *arizona = info->arizona;
const char *widget = arizona_extcon_get_micbias(info);
struct snd_soc_dapm_context *dapm = arizona->dapm;
bool change;
int ret;

regmap_update_bits_check(arizona->regmap, ARIZONA_MIC_DETECT_1,
ARIZONA_MICD_ENA, 0,
&change);

mutex_lock(&dapm->card->dapm_mutex);

ret = snd_soc_dapm_disable_pin(dapm, widget);
if (ret != 0)
dev_warn(arizona->dev,
"Failed to disable %s: %d\n",
widget, ret);

mutex_unlock(&dapm->card->dapm_mutex);

snd_soc_dapm_sync(dapm);

if (info->micd_reva) {
regmap_write(arizona->regmap, 0x80, 0x3);
regmap_write(arizona->regmap, 0x294, 2);
regmap_write(arizona->regmap, 0x80, 0x0);
}

ret = regulator_allow_bypass(info->micvdd, true);
if (ret != 0) {
dev_err(arizona->dev, "Failed to bypass MICVDD: %d\n",
ret);
}

if (change) {
regulator_disable(info->micvdd);
pm_runtime_mark_last_busy(info->dev);
Expand Down Expand Up @@ -564,6 +644,8 @@ static void arizona_start_hpdet_acc_id(struct arizona_extcon_info *info)

info->hpdet_active = true;

arizona_extcon_pulse_micbias(info);

ret = regmap_update_bits(arizona->regmap, 0x225, 0x4000, 0x4000);
if (ret != 0)
dev_warn(arizona->dev, "Failed to do magic: %d\n", ret);
Expand Down Expand Up @@ -649,6 +731,13 @@ static irqreturn_t arizona_micdet(int irq, void *data)
dev_err(arizona->dev, "Headset report failed: %d\n",
ret);

/* Don't need to regulate for button detection */
ret = regulator_allow_bypass(info->micvdd, false);
if (ret != 0) {
dev_err(arizona->dev, "Failed to bypass MICVDD: %d\n",
ret);
}

info->mic = true;
info->detecting = false;
goto handled;
Expand Down Expand Up @@ -716,6 +805,7 @@ static irqreturn_t arizona_micdet(int irq, void *data)
input_report_key(info->input,
arizona_lvl_to_key[i].report, 0);
input_sync(info->input);
arizona_extcon_pulse_micbias(info);
}

handled:
Expand Down Expand Up @@ -817,6 +907,9 @@ static int arizona_extcon_probe(struct platform_device *pdev)
int jack_irq_fall, jack_irq_rise;
int ret, mode, i;

if (!arizona->dapm || !arizona->dapm->card)
return -EPROBE_DEFER;

pdata = dev_get_platdata(arizona->dev);

info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
Expand Down
3 changes: 3 additions & 0 deletions trunk/include/linux/mfd/arizona/pdata.h
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,9 @@ struct arizona_pdata {
/** Mic detect debounce level */
int micd_dbtime;

/** Force MICBIAS on for mic detect */
bool micd_force_micbias;

/** Headset polarity configurations */
struct arizona_micd_config *micd_configs;
int num_micd_configs;
Expand Down

0 comments on commit 85f3a27

Please sign in to comment.