Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 193391
b: refs/heads/master
c: 8876698
h: refs/heads/master
i:
  193389: c51ea6c
  193387: d3ce2a3
  193383: fd34d66
  193375: 22060ec
v: v3
  • Loading branch information
Mark Brown committed Apr 5, 2010
1 parent 83ab49b commit 6f9c53a
Show file tree
Hide file tree
Showing 3 changed files with 138 additions and 4 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: ddf438cf2a6de9aa47783a45907e1188b9437ff7
refs/heads/master: 8876698406147986a9a7748586a54c4b14514c0e
137 changes: 134 additions & 3 deletions trunk/sound/soc/codecs/wm8994.c
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,12 @@ static int wm8994_retune_mobile_base[] = {

#define WM8994_REG_CACHE_SIZE 0x621

struct wm8994_micdet {
struct snd_soc_jack *jack;
int det;
int shrt;
};

/* codec private data */
struct wm8994_priv {
struct wm_hubs_data hubs;
Expand All @@ -86,6 +92,8 @@ struct wm8994_priv {
int retune_mobile_cfg[WM8994_NUM_EQ];
struct soc_enum retune_mobile_enum;

struct wm8994_micdet micdet[2];

struct wm8994_pdata *pdata;
};

Expand Down Expand Up @@ -3702,6 +3710,96 @@ struct snd_soc_codec_device soc_codec_dev_wm8994 = {
};
EXPORT_SYMBOL_GPL(soc_codec_dev_wm8994);

/**
* wm8994_mic_detect - Enable microphone detection via the WM8994 IRQ
*
* @codec: WM8994 codec
* @jack: jack to report detection events on
* @micbias: microphone bias to detect on
* @det: value to report for presence detection
* @shrt: value to report for short detection
*
* Enable microphone detection via IRQ on the WM8994. If GPIOs are
* being used to bring out signals to the processor then only platform
* data configuration is needed for WM8903 and processor GPIOs should
* be configured using snd_soc_jack_add_gpios() instead.
*
* Configuration of detection levels is available via the micbias1_lvl
* and micbias2_lvl platform data members.
*/
int wm8994_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack,
int micbias, int det, int shrt)
{
struct wm8994_priv *wm8994 = codec->private_data;
struct wm8994_micdet *micdet;
int reg;

switch (micbias) {
case 1:
micdet = &wm8994->micdet[0];
break;
case 2:
micdet = &wm8994->micdet[1];
break;
default:
return -EINVAL;
}

dev_dbg(codec->dev, "Configuring microphone detection on %d: %x %x\n",
micbias, det, shrt);

/* Store the configuration */
micdet->jack = jack;
micdet->det = det;
micdet->shrt = shrt;

/* If either of the jacks is set up then enable detection */
if (wm8994->micdet[0].jack || wm8994->micdet[1].jack)
reg = WM8994_MICD_ENA;
else
reg = 0;

snd_soc_update_bits(codec, WM8994_MICBIAS, WM8994_MICD_ENA, reg);

return 0;
}
EXPORT_SYMBOL_GPL(wm8994_mic_detect);

static irqreturn_t wm8994_mic_irq(int irq, void *data)
{
struct wm8994_priv *priv = data;
struct snd_soc_codec *codec = &priv->codec;
int reg;
int report;

reg = snd_soc_read(codec, WM8994_INTERRUPT_RAW_STATUS_2);
if (reg < 0) {
dev_err(codec->dev, "Failed to read microphone status: %d\n",
reg);
return IRQ_HANDLED;
}

dev_dbg(codec->dev, "Microphone status: %x\n", reg);

report = 0;
if (reg & WM8994_MIC1_DET_STS)
report |= priv->micdet[0].det;
if (reg & WM8994_MIC1_SHRT_STS)
report |= priv->micdet[0].shrt;
snd_soc_jack_report(priv->micdet[0].jack, report,
priv->micdet[0].det | priv->micdet[0].shrt);

report = 0;
if (reg & WM8994_MIC2_DET_STS)
report |= priv->micdet[1].det;
if (reg & WM8994_MIC2_SHRT_STS)
report |= priv->micdet[1].shrt;
snd_soc_jack_report(priv->micdet[1].jack, report,
priv->micdet[1].det | priv->micdet[1].shrt);

return IRQ_HANDLED;
}

static int wm8994_codec_probe(struct platform_device *pdev)
{
int ret;
Expand Down Expand Up @@ -3774,14 +3872,38 @@ static int wm8994_codec_probe(struct platform_device *pdev)
}


ret = wm8994_request_irq(codec->control_data, WM8994_IRQ_MIC1_DET,
wm8994_mic_irq, "Mic 1 detect", wm8994);
if (ret != 0)
dev_warn(&pdev->dev,
"Failed to request Mic1 detect IRQ: %d\n", ret);

ret = wm8994_request_irq(codec->control_data, WM8994_IRQ_MIC1_SHRT,
wm8994_mic_irq, "Mic 1 short", wm8994);
if (ret != 0)
dev_warn(&pdev->dev,
"Failed to request Mic1 short IRQ: %d\n", ret);

ret = wm8994_request_irq(codec->control_data, WM8994_IRQ_MIC2_DET,
wm8994_mic_irq, "Mic 2 detect", wm8994);
if (ret != 0)
dev_warn(&pdev->dev,
"Failed to request Mic2 detect IRQ: %d\n", ret);

ret = wm8994_request_irq(codec->control_data, WM8994_IRQ_MIC2_SHRT,
wm8994_mic_irq, "Mic 2 short", wm8994);
if (ret != 0)
dev_warn(&pdev->dev,
"Failed to request Mic2 short IRQ: %d\n", ret);

/* Remember if AIFnLRCLK is configured as a GPIO. This should be
* configured on init - if a system wants to do this dynamically
* at runtime we can deal with that then.
*/
ret = wm8994_reg_read(codec->control_data, WM8994_GPIO_1);
if (ret < 0) {
dev_err(codec->dev, "Failed to read GPIO1 state: %d\n", ret);
goto err;
goto err_irq;
}
if ((ret & WM8994_GPN_FN_MASK) != WM8994_GP_FN_PIN_SPECIFIC) {
wm8994->lrclk_shared[0] = 1;
Expand All @@ -3793,7 +3915,7 @@ static int wm8994_codec_probe(struct platform_device *pdev)
ret = wm8994_reg_read(codec->control_data, WM8994_GPIO_6);
if (ret < 0) {
dev_err(codec->dev, "Failed to read GPIO6 state: %d\n", ret);
goto err;
goto err_irq;
}
if ((ret & WM8994_GPN_FN_MASK) != WM8994_GP_FN_PIN_SPECIFIC) {
wm8994->lrclk_shared[1] = 1;
Expand Down Expand Up @@ -3843,7 +3965,7 @@ static int wm8994_codec_probe(struct platform_device *pdev)
ret = snd_soc_register_codec(codec);
if (ret != 0) {
dev_err(codec->dev, "Failed to register codec: %d\n", ret);
goto err;
goto err_irq;
}

ret = snd_soc_register_dais(wm8994_dai, ARRAY_SIZE(wm8994_dai));
Expand All @@ -3858,6 +3980,11 @@ static int wm8994_codec_probe(struct platform_device *pdev)

err_codec:
snd_soc_unregister_codec(codec);
err_irq:
wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC2_SHRT, wm8994);
wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC2_DET, wm8994);
wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC1_SHRT, wm8994);
wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC1_DET, wm8994);
err:
kfree(wm8994);
return ret;
Expand All @@ -3871,6 +3998,10 @@ static int __devexit wm8994_codec_remove(struct platform_device *pdev)
wm8994_set_bias_level(codec, SND_SOC_BIAS_OFF);
snd_soc_unregister_dais(wm8994_dai, ARRAY_SIZE(wm8994_dai));
snd_soc_unregister_codec(&wm8994->codec);
wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC2_SHRT, wm8994);
wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC2_DET, wm8994);
wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC1_SHRT, wm8994);
wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC1_DET, wm8994);
kfree(wm8994);
wm8994_codec = NULL;

Expand Down
3 changes: 3 additions & 0 deletions trunk/sound/soc/codecs/wm8994.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,7 @@ extern struct snd_soc_dai wm8994_dai[];
#define WM8994_FLL1 1
#define WM8994_FLL2 2

int wm8994_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack,
int micbias, int det, int shrt);

#endif

0 comments on commit 6f9c53a

Please sign in to comment.