Commit 3b171194 authored by Shengjiu Wang's avatar Shengjiu Wang Committed by Mark Brown

ASoC: fsl-asoc-card: Support Headphone and Microphone Jack detection

Use asoc_simple_init_jack function from simple card to implement
the Headphone and Microphone detection.
Register notifier to disable Speaker when Headphone is plugged in
and enable Speaker when Headphone is unplugged.
Register notifier to disable Digital Microphone when Analog Microphone
is plugged in and enable DMIC when Analog Microphone is unplugged.
Signed-off-by: default avatarShengjiu Wang <shengjiu.wang@nxp.com>
Acked-by: default avatarNicolin Chen <nicoleotsuka@gmail.com>
Link: https://lore.kernel.org/r/1594822179-1849-4-git-send-email-shengjiu.wang@nxp.comSigned-off-by: default avatarMark Brown <broonie@kernel.org>
parent c3c058ab
...@@ -315,6 +315,7 @@ config SND_SOC_FSL_ASOC_CARD ...@@ -315,6 +315,7 @@ config SND_SOC_FSL_ASOC_CARD
depends on OF && I2C depends on OF && I2C
# enforce SND_SOC_FSL_ASOC_CARD=m if SND_AC97_CODEC=m: # enforce SND_SOC_FSL_ASOC_CARD=m if SND_AC97_CODEC=m:
depends on SND_AC97_CODEC || SND_AC97_CODEC=n depends on SND_AC97_CODEC || SND_AC97_CODEC=n
select SND_SIMPLE_CARD_UTILS
select SND_SOC_IMX_AUDMUX select SND_SOC_IMX_AUDMUX
select SND_SOC_IMX_PCM_DMA select SND_SOC_IMX_PCM_DMA
select SND_SOC_FSL_ESAI select SND_SOC_FSL_ESAI
......
...@@ -15,6 +15,8 @@ ...@@ -15,6 +15,8 @@
#endif #endif
#include <sound/pcm_params.h> #include <sound/pcm_params.h>
#include <sound/soc.h> #include <sound/soc.h>
#include <sound/jack.h>
#include <sound/simple_card_utils.h>
#include "fsl_esai.h" #include "fsl_esai.h"
#include "fsl_sai.h" #include "fsl_sai.h"
...@@ -65,6 +67,8 @@ struct cpu_priv { ...@@ -65,6 +67,8 @@ struct cpu_priv {
/** /**
* struct fsl_asoc_card_priv - Freescale Generic ASOC card private data * struct fsl_asoc_card_priv - Freescale Generic ASOC card private data
* @dai_link: DAI link structure including normal one and DPCM link * @dai_link: DAI link structure including normal one and DPCM link
* @hp_jack: Headphone Jack structure
* @mic_jack: Microphone Jack structure
* @pdev: platform device pointer * @pdev: platform device pointer
* @codec_priv: CODEC private data * @codec_priv: CODEC private data
* @cpu_priv: CPU private data * @cpu_priv: CPU private data
...@@ -79,6 +83,8 @@ struct cpu_priv { ...@@ -79,6 +83,8 @@ struct cpu_priv {
struct fsl_asoc_card_priv { struct fsl_asoc_card_priv {
struct snd_soc_dai_link dai_link[3]; struct snd_soc_dai_link dai_link[3];
struct asoc_simple_jack hp_jack;
struct asoc_simple_jack mic_jack;
struct platform_device *pdev; struct platform_device *pdev;
struct codec_priv codec_priv; struct codec_priv codec_priv;
struct cpu_priv cpu_priv; struct cpu_priv cpu_priv;
...@@ -445,6 +451,44 @@ static int fsl_asoc_card_audmux_init(struct device_node *np, ...@@ -445,6 +451,44 @@ static int fsl_asoc_card_audmux_init(struct device_node *np,
return 0; return 0;
} }
static int hp_jack_event(struct notifier_block *nb, unsigned long event,
void *data)
{
struct snd_soc_jack *jack = (struct snd_soc_jack *)data;
struct snd_soc_dapm_context *dapm = &jack->card->dapm;
if (event & SND_JACK_HEADPHONE)
/* Disable speaker if headphone is plugged in */
snd_soc_dapm_disable_pin(dapm, "Ext Spk");
else
snd_soc_dapm_enable_pin(dapm, "Ext Spk");
return 0;
}
static struct notifier_block hp_jack_nb = {
.notifier_call = hp_jack_event,
};
static int mic_jack_event(struct notifier_block *nb, unsigned long event,
void *data)
{
struct snd_soc_jack *jack = (struct snd_soc_jack *)data;
struct snd_soc_dapm_context *dapm = &jack->card->dapm;
if (event & SND_JACK_MICROPHONE)
/* Disable dmic if microphone is plugged in */
snd_soc_dapm_disable_pin(dapm, "DMIC");
else
snd_soc_dapm_enable_pin(dapm, "DMIC");
return 0;
}
static struct notifier_block mic_jack_nb = {
.notifier_call = mic_jack_event,
};
static int fsl_asoc_card_late_probe(struct snd_soc_card *card) static int fsl_asoc_card_late_probe(struct snd_soc_card *card)
{ {
struct fsl_asoc_card_priv *priv = snd_soc_card_get_drvdata(card); struct fsl_asoc_card_priv *priv = snd_soc_card_get_drvdata(card);
...@@ -745,8 +789,37 @@ static int fsl_asoc_card_probe(struct platform_device *pdev) ...@@ -745,8 +789,37 @@ static int fsl_asoc_card_probe(struct platform_device *pdev)
snd_soc_card_set_drvdata(&priv->card, priv); snd_soc_card_set_drvdata(&priv->card, priv);
ret = devm_snd_soc_register_card(&pdev->dev, &priv->card); ret = devm_snd_soc_register_card(&pdev->dev, &priv->card);
if (ret && ret != -EPROBE_DEFER) if (ret) {
dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret); if (ret != -EPROBE_DEFER)
dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret);
goto asrc_fail;
}
/*
* Properties "hp-det-gpio" and "mic-det-gpio" are optional, and
* asoc_simple_init_jack uses these properties for creating
* Headphone Jack and Microphone Jack.
*
* The notifier is initialized in snd_soc_card_jack_new(), then
* snd_soc_jack_notifier_register can be called.
*/
if (of_property_read_bool(np, "hp-det-gpio")) {
ret = asoc_simple_init_jack(&priv->card, &priv->hp_jack,
1, NULL, "Headphone Jack");
if (ret)
goto asrc_fail;
snd_soc_jack_notifier_register(&priv->hp_jack.jack, &hp_jack_nb);
}
if (of_property_read_bool(np, "mic-det-gpio")) {
ret = asoc_simple_init_jack(&priv->card, &priv->mic_jack,
0, NULL, "Mic Jack");
if (ret)
goto asrc_fail;
snd_soc_jack_notifier_register(&priv->mic_jack.jack, &mic_jack_nb);
}
asrc_fail: asrc_fail:
of_node_put(asrc_np); of_node_put(asrc_np);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment