diff options
Diffstat (limited to 'sound/soc/codecs/wm8994.c')
-rw-r--r-- | sound/soc/codecs/wm8994.c | 137 |
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 | ||
64 | struct wm8994_micdet { | ||
65 | struct snd_soc_jack *jack; | ||
66 | int det; | ||
67 | int shrt; | ||
68 | }; | ||
69 | |||
64 | /* codec private data */ | 70 | /* codec private data */ |
65 | struct wm8994_priv { | 71 | struct 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 | }; |
3703 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm8994); | 3711 | EXPORT_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 | */ | ||
3730 | int 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 | } | ||
3766 | EXPORT_SYMBOL_GPL(wm8994_mic_detect); | ||
3767 | |||
3768 | static 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 | |||
3705 | static int wm8994_codec_probe(struct platform_device *pdev) | 3803 | static 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 | ||
3859 | err_codec: | 3981 | err_codec: |
3860 | snd_soc_unregister_codec(codec); | 3982 | snd_soc_unregister_codec(codec); |
3983 | err_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); | ||
3861 | err: | 3988 | err: |
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 | ||