aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/codecs/wm8994.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/codecs/wm8994.c')
-rw-r--r--sound/soc/codecs/wm8994.c137
1 files changed, 134 insertions, 3 deletions
diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c
index bdda0936a404..fc3dce814924 100644
--- a/sound/soc/codecs/wm8994.c
+++ b/sound/soc/codecs/wm8994.c
@@ -61,6 +61,12 @@ static int wm8994_retune_mobile_base[] = {
61 61
62#define WM8994_REG_CACHE_SIZE 0x621 62#define WM8994_REG_CACHE_SIZE 0x621
63 63
64struct wm8994_micdet {
65 struct snd_soc_jack *jack;
66 int det;
67 int shrt;
68};
69
64/* codec private data */ 70/* codec private data */
65struct wm8994_priv { 71struct wm8994_priv {
66 struct wm_hubs_data hubs; 72 struct wm_hubs_data hubs;
@@ -86,6 +92,8 @@ struct wm8994_priv {
86 int retune_mobile_cfg[WM8994_NUM_EQ]; 92 int retune_mobile_cfg[WM8994_NUM_EQ];
87 struct soc_enum retune_mobile_enum; 93 struct soc_enum retune_mobile_enum;
88 94
95 struct wm8994_micdet micdet[2];
96
89 struct wm8994_pdata *pdata; 97 struct wm8994_pdata *pdata;
90}; 98};
91 99
@@ -3702,6 +3710,96 @@ struct snd_soc_codec_device soc_codec_dev_wm8994 = {
3702}; 3710};
3703EXPORT_SYMBOL_GPL(soc_codec_dev_wm8994); 3711EXPORT_SYMBOL_GPL(soc_codec_dev_wm8994);
3704 3712
3713/**
3714 * wm8994_mic_detect - Enable microphone detection via the WM8994 IRQ
3715 *
3716 * @codec: WM8994 codec
3717 * @jack: jack to report detection events on
3718 * @micbias: microphone bias to detect on
3719 * @det: value to report for presence detection
3720 * @shrt: value to report for short detection
3721 *
3722 * Enable microphone detection via IRQ on the WM8994. If GPIOs are
3723 * being used to bring out signals to the processor then only platform
3724 * data configuration is needed for WM8903 and processor GPIOs should
3725 * be configured using snd_soc_jack_add_gpios() instead.
3726 *
3727 * Configuration of detection levels is available via the micbias1_lvl
3728 * and micbias2_lvl platform data members.
3729 */
3730int wm8994_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack,
3731 int micbias, int det, int shrt)
3732{
3733 struct wm8994_priv *wm8994 = codec->private_data;
3734 struct wm8994_micdet *micdet;
3735 int reg;
3736
3737 switch (micbias) {
3738 case 1:
3739 micdet = &wm8994->micdet[0];
3740 break;
3741 case 2:
3742 micdet = &wm8994->micdet[1];
3743 break;
3744 default:
3745 return -EINVAL;
3746 }
3747
3748 dev_dbg(codec->dev, "Configuring microphone detection on %d: %x %x\n",
3749 micbias, det, shrt);
3750
3751 /* Store the configuration */
3752 micdet->jack = jack;
3753 micdet->det = det;
3754 micdet->shrt = shrt;
3755
3756 /* If either of the jacks is set up then enable detection */
3757 if (wm8994->micdet[0].jack || wm8994->micdet[1].jack)
3758 reg = WM8994_MICD_ENA;
3759 else
3760 reg = 0;
3761
3762 snd_soc_update_bits(codec, WM8994_MICBIAS, WM8994_MICD_ENA, reg);
3763
3764 return 0;
3765}
3766EXPORT_SYMBOL_GPL(wm8994_mic_detect);
3767
3768static irqreturn_t wm8994_mic_irq(int irq, void *data)
3769{
3770 struct wm8994_priv *priv = data;
3771 struct snd_soc_codec *codec = &priv->codec;
3772 int reg;
3773 int report;
3774
3775 reg = snd_soc_read(codec, WM8994_INTERRUPT_RAW_STATUS_2);
3776 if (reg < 0) {
3777 dev_err(codec->dev, "Failed to read microphone status: %d\n",
3778 reg);
3779 return IRQ_HANDLED;
3780 }
3781
3782 dev_dbg(codec->dev, "Microphone status: %x\n", reg);
3783
3784 report = 0;
3785 if (reg & WM8994_MIC1_DET_STS)
3786 report |= priv->micdet[0].det;
3787 if (reg & WM8994_MIC1_SHRT_STS)
3788 report |= priv->micdet[0].shrt;
3789 snd_soc_jack_report(priv->micdet[0].jack, report,
3790 priv->micdet[0].det | priv->micdet[0].shrt);
3791
3792 report = 0;
3793 if (reg & WM8994_MIC2_DET_STS)
3794 report |= priv->micdet[1].det;
3795 if (reg & WM8994_MIC2_SHRT_STS)
3796 report |= priv->micdet[1].shrt;
3797 snd_soc_jack_report(priv->micdet[1].jack, report,
3798 priv->micdet[1].det | priv->micdet[1].shrt);
3799
3800 return IRQ_HANDLED;
3801}
3802
3705static int wm8994_codec_probe(struct platform_device *pdev) 3803static int wm8994_codec_probe(struct platform_device *pdev)
3706{ 3804{
3707 int ret; 3805 int ret;
@@ -3774,6 +3872,30 @@ static int wm8994_codec_probe(struct platform_device *pdev)
3774 } 3872 }
3775 3873
3776 3874
3875 ret = wm8994_request_irq(codec->control_data, WM8994_IRQ_MIC1_DET,
3876 wm8994_mic_irq, "Mic 1 detect", wm8994);
3877 if (ret != 0)
3878 dev_warn(&pdev->dev,
3879 "Failed to request Mic1 detect IRQ: %d\n", ret);
3880
3881 ret = wm8994_request_irq(codec->control_data, WM8994_IRQ_MIC1_SHRT,
3882 wm8994_mic_irq, "Mic 1 short", wm8994);
3883 if (ret != 0)
3884 dev_warn(&pdev->dev,
3885 "Failed to request Mic1 short IRQ: %d\n", ret);
3886
3887 ret = wm8994_request_irq(codec->control_data, WM8994_IRQ_MIC2_DET,
3888 wm8994_mic_irq, "Mic 2 detect", wm8994);
3889 if (ret != 0)
3890 dev_warn(&pdev->dev,
3891 "Failed to request Mic2 detect IRQ: %d\n", ret);
3892
3893 ret = wm8994_request_irq(codec->control_data, WM8994_IRQ_MIC2_SHRT,
3894 wm8994_mic_irq, "Mic 2 short", wm8994);
3895 if (ret != 0)
3896 dev_warn(&pdev->dev,
3897 "Failed to request Mic2 short IRQ: %d\n", ret);
3898
3777 /* Remember if AIFnLRCLK is configured as a GPIO. This should be 3899 /* Remember if AIFnLRCLK is configured as a GPIO. This should be
3778 * configured on init - if a system wants to do this dynamically 3900 * configured on init - if a system wants to do this dynamically
3779 * at runtime we can deal with that then. 3901 * at runtime we can deal with that then.
@@ -3781,7 +3903,7 @@ static int wm8994_codec_probe(struct platform_device *pdev)
3781 ret = wm8994_reg_read(codec->control_data, WM8994_GPIO_1); 3903 ret = wm8994_reg_read(codec->control_data, WM8994_GPIO_1);
3782 if (ret < 0) { 3904 if (ret < 0) {
3783 dev_err(codec->dev, "Failed to read GPIO1 state: %d\n", ret); 3905 dev_err(codec->dev, "Failed to read GPIO1 state: %d\n", ret);
3784 goto err; 3906 goto err_irq;
3785 } 3907 }
3786 if ((ret & WM8994_GPN_FN_MASK) != WM8994_GP_FN_PIN_SPECIFIC) { 3908 if ((ret & WM8994_GPN_FN_MASK) != WM8994_GP_FN_PIN_SPECIFIC) {
3787 wm8994->lrclk_shared[0] = 1; 3909 wm8994->lrclk_shared[0] = 1;
@@ -3793,7 +3915,7 @@ static int wm8994_codec_probe(struct platform_device *pdev)
3793 ret = wm8994_reg_read(codec->control_data, WM8994_GPIO_6); 3915 ret = wm8994_reg_read(codec->control_data, WM8994_GPIO_6);
3794 if (ret < 0) { 3916 if (ret < 0) {
3795 dev_err(codec->dev, "Failed to read GPIO6 state: %d\n", ret); 3917 dev_err(codec->dev, "Failed to read GPIO6 state: %d\n", ret);
3796 goto err; 3918 goto err_irq;
3797 } 3919 }
3798 if ((ret & WM8994_GPN_FN_MASK) != WM8994_GP_FN_PIN_SPECIFIC) { 3920 if ((ret & WM8994_GPN_FN_MASK) != WM8994_GP_FN_PIN_SPECIFIC) {
3799 wm8994->lrclk_shared[1] = 1; 3921 wm8994->lrclk_shared[1] = 1;
@@ -3843,7 +3965,7 @@ static int wm8994_codec_probe(struct platform_device *pdev)
3843 ret = snd_soc_register_codec(codec); 3965 ret = snd_soc_register_codec(codec);
3844 if (ret != 0) { 3966 if (ret != 0) {
3845 dev_err(codec->dev, "Failed to register codec: %d\n", ret); 3967 dev_err(codec->dev, "Failed to register codec: %d\n", ret);
3846 goto err; 3968 goto err_irq;
3847 } 3969 }
3848 3970
3849 ret = snd_soc_register_dais(wm8994_dai, ARRAY_SIZE(wm8994_dai)); 3971 ret = snd_soc_register_dais(wm8994_dai, ARRAY_SIZE(wm8994_dai));
@@ -3858,6 +3980,11 @@ static int wm8994_codec_probe(struct platform_device *pdev)
3858 3980
3859err_codec: 3981err_codec:
3860 snd_soc_unregister_codec(codec); 3982 snd_soc_unregister_codec(codec);
3983err_irq:
3984 wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC2_SHRT, wm8994);
3985 wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC2_DET, wm8994);
3986 wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC1_SHRT, wm8994);
3987 wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC1_DET, wm8994);
3861err: 3988err:
3862 kfree(wm8994); 3989 kfree(wm8994);
3863 return ret; 3990 return ret;
@@ -3871,6 +3998,10 @@ static int __devexit wm8994_codec_remove(struct platform_device *pdev)
3871 wm8994_set_bias_level(codec, SND_SOC_BIAS_OFF); 3998 wm8994_set_bias_level(codec, SND_SOC_BIAS_OFF);
3872 snd_soc_unregister_dais(wm8994_dai, ARRAY_SIZE(wm8994_dai)); 3999 snd_soc_unregister_dais(wm8994_dai, ARRAY_SIZE(wm8994_dai));
3873 snd_soc_unregister_codec(&wm8994->codec); 4000 snd_soc_unregister_codec(&wm8994->codec);
4001 wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC2_SHRT, wm8994);
4002 wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC2_DET, wm8994);
4003 wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC1_SHRT, wm8994);
4004 wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC1_DET, wm8994);
3874 kfree(wm8994); 4005 kfree(wm8994);
3875 wm8994_codec = NULL; 4006 wm8994_codec = NULL;
3876 4007