diff options
Diffstat (limited to 'sound/soc/codecs/wm8994.c')
-rw-r--r-- | sound/soc/codecs/wm8994.c | 127 |
1 files changed, 65 insertions, 62 deletions
diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index c6c958ee5d59..3dc64c8b6a5c 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c | |||
@@ -102,8 +102,7 @@ struct wm8994_priv { | |||
102 | 102 | ||
103 | wm8958_micdet_cb jack_cb; | 103 | wm8958_micdet_cb jack_cb; |
104 | void *jack_cb_data; | 104 | void *jack_cb_data; |
105 | bool jack_is_mic; | 105 | int micdet_irq; |
106 | bool jack_is_video; | ||
107 | 106 | ||
108 | int revision; | 107 | int revision; |
109 | struct wm8994_pdata *pdata; | 108 | struct wm8994_pdata *pdata; |
@@ -115,7 +114,7 @@ struct wm8994_priv { | |||
115 | unsigned int aif2clk_disable:1; | 114 | unsigned int aif2clk_disable:1; |
116 | }; | 115 | }; |
117 | 116 | ||
118 | static int wm8994_readable(unsigned int reg) | 117 | static int wm8994_readable(struct snd_soc_codec *codec, unsigned int reg) |
119 | { | 118 | { |
120 | switch (reg) { | 119 | switch (reg) { |
121 | case WM8994_GPIO_1: | 120 | case WM8994_GPIO_1: |
@@ -142,7 +141,7 @@ static int wm8994_readable(unsigned int reg) | |||
142 | return wm8994_access_masks[reg].readable != 0; | 141 | return wm8994_access_masks[reg].readable != 0; |
143 | } | 142 | } |
144 | 143 | ||
145 | static int wm8994_volatile(unsigned int reg) | 144 | static int wm8994_volatile(struct snd_soc_codec *codec, unsigned int reg) |
146 | { | 145 | { |
147 | if (reg >= WM8994_CACHE_SIZE) | 146 | if (reg >= WM8994_CACHE_SIZE) |
148 | return 1; | 147 | return 1; |
@@ -170,7 +169,7 @@ static int wm8994_write(struct snd_soc_codec *codec, unsigned int reg, | |||
170 | 169 | ||
171 | BUG_ON(reg > WM8994_MAX_REGISTER); | 170 | BUG_ON(reg > WM8994_MAX_REGISTER); |
172 | 171 | ||
173 | if (!wm8994_volatile(reg)) { | 172 | if (!wm8994_volatile(codec, reg)) { |
174 | ret = snd_soc_cache_write(codec, reg, value); | 173 | ret = snd_soc_cache_write(codec, reg, value); |
175 | if (ret != 0) | 174 | if (ret != 0) |
176 | dev_err(codec->dev, "Cache write to %x failed: %d\n", | 175 | dev_err(codec->dev, "Cache write to %x failed: %d\n", |
@@ -188,7 +187,7 @@ static unsigned int wm8994_read(struct snd_soc_codec *codec, | |||
188 | 187 | ||
189 | BUG_ON(reg > WM8994_MAX_REGISTER); | 188 | BUG_ON(reg > WM8994_MAX_REGISTER); |
190 | 189 | ||
191 | if (!wm8994_volatile(reg) && wm8994_readable(reg) && | 190 | if (!wm8994_volatile(codec, reg) && wm8994_readable(codec, reg) && |
192 | reg < codec->driver->reg_cache_size) { | 191 | reg < codec->driver->reg_cache_size) { |
193 | ret = snd_soc_cache_read(codec, reg, &val); | 192 | ret = snd_soc_cache_read(codec, reg, &val); |
194 | if (ret >= 0) | 193 | if (ret >= 0) |
@@ -529,7 +528,7 @@ static int wm8994_get_retune_mobile_enum(struct snd_kcontrol *kcontrol, | |||
529 | struct snd_ctl_elem_value *ucontrol) | 528 | struct snd_ctl_elem_value *ucontrol) |
530 | { | 529 | { |
531 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | 530 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); |
532 | struct wm8994_priv *wm8994 =snd_soc_codec_get_drvdata(codec); | 531 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); |
533 | int block = wm8994_get_retune_mobile_block(kcontrol->id.name); | 532 | int block = wm8994_get_retune_mobile_block(kcontrol->id.name); |
534 | 533 | ||
535 | ucontrol->value.enumerated.item[0] = wm8994->retune_mobile_cfg[block]; | 534 | ucontrol->value.enumerated.item[0] = wm8994->retune_mobile_cfg[block]; |
@@ -1103,6 +1102,13 @@ static int adc_mux_ev(struct snd_soc_dapm_widget *w, | |||
1103 | return 0; | 1102 | return 0; |
1104 | } | 1103 | } |
1105 | 1104 | ||
1105 | static int micbias_ev(struct snd_soc_dapm_widget *w, | ||
1106 | struct snd_kcontrol *kcontrol, int event) | ||
1107 | { | ||
1108 | late_enable_ev(w, kcontrol, event); | ||
1109 | return 0; | ||
1110 | } | ||
1111 | |||
1106 | static int dac_ev(struct snd_soc_dapm_widget *w, | 1112 | static int dac_ev(struct snd_soc_dapm_widget *w, |
1107 | struct snd_kcontrol *kcontrol, int event) | 1113 | struct snd_kcontrol *kcontrol, int event) |
1108 | { | 1114 | { |
@@ -1440,6 +1446,10 @@ SND_SOC_DAPM_INPUT("DMIC1DAT"), | |||
1440 | SND_SOC_DAPM_INPUT("DMIC2DAT"), | 1446 | SND_SOC_DAPM_INPUT("DMIC2DAT"), |
1441 | SND_SOC_DAPM_INPUT("Clock"), | 1447 | SND_SOC_DAPM_INPUT("Clock"), |
1442 | 1448 | ||
1449 | SND_SOC_DAPM_MICBIAS("MICBIAS", WM8994_MICBIAS, 2, 0), | ||
1450 | SND_SOC_DAPM_SUPPLY_S("MICBIAS Supply", 1, SND_SOC_NOPM, 0, 0, micbias_ev, | ||
1451 | SND_SOC_DAPM_PRE_PMU), | ||
1452 | |||
1443 | SND_SOC_DAPM_SUPPLY("CLK_SYS", SND_SOC_NOPM, 0, 0, clk_sys_event, | 1453 | SND_SOC_DAPM_SUPPLY("CLK_SYS", SND_SOC_NOPM, 0, 0, clk_sys_event, |
1444 | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), | 1454 | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), |
1445 | 1455 | ||
@@ -1755,6 +1765,8 @@ static const struct snd_soc_dapm_route wm8994_revd_intercon[] = { | |||
1755 | { "AIF2DACDAT", NULL, "AIF1DACDAT" }, | 1765 | { "AIF2DACDAT", NULL, "AIF1DACDAT" }, |
1756 | { "AIF1ADCDAT", NULL, "AIF2ADCDAT" }, | 1766 | { "AIF1ADCDAT", NULL, "AIF2ADCDAT" }, |
1757 | { "AIF2ADCDAT", NULL, "AIF1ADCDAT" }, | 1767 | { "AIF2ADCDAT", NULL, "AIF1ADCDAT" }, |
1768 | { "MICBIAS", NULL, "CLK_SYS" }, | ||
1769 | { "MICBIAS", NULL, "MICBIAS Supply" }, | ||
1758 | }; | 1770 | }; |
1759 | 1771 | ||
1760 | static const struct snd_soc_dapm_route wm8994_intercon[] = { | 1772 | static const struct snd_soc_dapm_route wm8994_intercon[] = { |
@@ -2883,6 +2895,13 @@ static void wm8994_handle_pdata(struct wm8994_priv *wm8994) | |||
2883 | else | 2895 | else |
2884 | snd_soc_add_controls(wm8994->codec, wm8994_eq_controls, | 2896 | snd_soc_add_controls(wm8994->codec, wm8994_eq_controls, |
2885 | ARRAY_SIZE(wm8994_eq_controls)); | 2897 | ARRAY_SIZE(wm8994_eq_controls)); |
2898 | |||
2899 | for (i = 0; i < ARRAY_SIZE(pdata->micbias); i++) { | ||
2900 | if (pdata->micbias[i]) { | ||
2901 | snd_soc_write(codec, WM8958_MICBIAS1 + i, | ||
2902 | pdata->micbias[i] & 0xffff); | ||
2903 | } | ||
2904 | } | ||
2886 | } | 2905 | } |
2887 | 2906 | ||
2888 | /** | 2907 | /** |
@@ -2993,46 +3012,18 @@ static void wm8958_default_micdet(u16 status, void *data) | |||
2993 | int report = 0; | 3012 | int report = 0; |
2994 | 3013 | ||
2995 | /* If nothing present then clear our statuses */ | 3014 | /* If nothing present then clear our statuses */ |
2996 | if (!(status & WM8958_MICD_STS)) { | 3015 | if (!(status & WM8958_MICD_STS)) |
2997 | wm8994->jack_is_video = false; | ||
2998 | wm8994->jack_is_mic = false; | ||
2999 | goto done; | 3016 | goto done; |
3000 | } | ||
3001 | 3017 | ||
3002 | /* Assume anything over 475 ohms is a microphone and remember | 3018 | report = SND_JACK_MICROPHONE; |
3003 | * that we've seen one (since buttons override it) */ | ||
3004 | if (status & 0x600) | ||
3005 | wm8994->jack_is_mic = true; | ||
3006 | if (wm8994->jack_is_mic) | ||
3007 | report |= SND_JACK_MICROPHONE; | ||
3008 | |||
3009 | /* Video has an impedence of approximately 75 ohms; assume | ||
3010 | * this isn't used as a button and remember it since buttons | ||
3011 | * override it. */ | ||
3012 | if (status & 0x40) | ||
3013 | wm8994->jack_is_video = true; | ||
3014 | if (wm8994->jack_is_video) | ||
3015 | report |= SND_JACK_VIDEOOUT; | ||
3016 | 3019 | ||
3017 | /* Everything else is buttons; just assign slots */ | 3020 | /* Everything else is buttons; just assign slots */ |
3018 | if (status & 0x4) | 3021 | if (status & 0x1c0) |
3019 | report |= SND_JACK_BTN_0; | 3022 | report |= SND_JACK_BTN_0; |
3020 | if (status & 0x8) | ||
3021 | report |= SND_JACK_BTN_1; | ||
3022 | if (status & 0x10) | ||
3023 | report |= SND_JACK_BTN_2; | ||
3024 | if (status & 0x20) | ||
3025 | report |= SND_JACK_BTN_3; | ||
3026 | if (status & 0x80) | ||
3027 | report |= SND_JACK_BTN_4; | ||
3028 | if (status & 0x100) | ||
3029 | report |= SND_JACK_BTN_5; | ||
3030 | 3023 | ||
3031 | done: | 3024 | done: |
3032 | snd_soc_jack_report(wm8994->micdet[0].jack, report, | 3025 | snd_soc_jack_report(wm8994->micdet[0].jack, report, |
3033 | SND_JACK_BTN_0 | SND_JACK_BTN_1 | SND_JACK_BTN_2 | | 3026 | SND_JACK_BTN_0 | SND_JACK_MICROPHONE); |
3034 | SND_JACK_BTN_3 | SND_JACK_BTN_4 | SND_JACK_BTN_5 | | ||
3035 | SND_JACK_MICROPHONE | SND_JACK_VIDEOOUT); | ||
3036 | } | 3027 | } |
3037 | 3028 | ||
3038 | /** | 3029 | /** |
@@ -3131,13 +3122,19 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec) | |||
3131 | wm8994->pdata = dev_get_platdata(codec->dev->parent); | 3122 | wm8994->pdata = dev_get_platdata(codec->dev->parent); |
3132 | wm8994->codec = codec; | 3123 | wm8994->codec = codec; |
3133 | 3124 | ||
3125 | if (wm8994->pdata && wm8994->pdata->micdet_irq) | ||
3126 | wm8994->micdet_irq = wm8994->pdata->micdet_irq; | ||
3127 | else if (wm8994->pdata && wm8994->pdata->irq_base) | ||
3128 | wm8994->micdet_irq = wm8994->pdata->irq_base + | ||
3129 | WM8994_IRQ_MIC1_DET; | ||
3130 | |||
3134 | pm_runtime_enable(codec->dev); | 3131 | pm_runtime_enable(codec->dev); |
3135 | pm_runtime_resume(codec->dev); | 3132 | pm_runtime_resume(codec->dev); |
3136 | 3133 | ||
3137 | /* Read our current status back from the chip - we don't want to | 3134 | /* Read our current status back from the chip - we don't want to |
3138 | * reset as this may interfere with the GPIO or LDO operation. */ | 3135 | * reset as this may interfere with the GPIO or LDO operation. */ |
3139 | for (i = 0; i < WM8994_CACHE_SIZE; i++) { | 3136 | for (i = 0; i < WM8994_CACHE_SIZE; i++) { |
3140 | if (!wm8994_readable(i) || wm8994_volatile(i)) | 3137 | if (!wm8994_readable(codec, i) || wm8994_volatile(codec, i)) |
3141 | continue; | 3138 | continue; |
3142 | 3139 | ||
3143 | ret = wm8994_reg_read(codec->control_data, i); | 3140 | ret = wm8994_reg_read(codec->control_data, i); |
@@ -3179,14 +3176,17 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec) | |||
3179 | 3176 | ||
3180 | switch (control->type) { | 3177 | switch (control->type) { |
3181 | case WM8994: | 3178 | case WM8994: |
3182 | ret = wm8994_request_irq(codec->control_data, | 3179 | if (wm8994->micdet_irq) { |
3183 | WM8994_IRQ_MIC1_DET, | 3180 | ret = request_threaded_irq(wm8994->micdet_irq, NULL, |
3184 | wm8994_mic_irq, "Mic 1 detect", | 3181 | wm8994_mic_irq, |
3185 | wm8994); | 3182 | IRQF_TRIGGER_RISING, |
3186 | if (ret != 0) | 3183 | "Mic1 detect", |
3187 | dev_warn(codec->dev, | 3184 | wm8994); |
3188 | "Failed to request Mic1 detect IRQ: %d\n", | 3185 | if (ret != 0) |
3189 | ret); | 3186 | dev_warn(codec->dev, |
3187 | "Failed to request Mic1 detect IRQ: %d\n", | ||
3188 | ret); | ||
3189 | } | ||
3190 | 3190 | ||
3191 | ret = wm8994_request_irq(codec->control_data, | 3191 | ret = wm8994_request_irq(codec->control_data, |
3192 | WM8994_IRQ_MIC1_SHRT, | 3192 | WM8994_IRQ_MIC1_SHRT, |
@@ -3217,15 +3217,17 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec) | |||
3217 | break; | 3217 | break; |
3218 | 3218 | ||
3219 | case WM8958: | 3219 | case WM8958: |
3220 | ret = wm8994_request_irq(codec->control_data, | 3220 | if (wm8994->micdet_irq) { |
3221 | WM8994_IRQ_MIC1_DET, | 3221 | ret = request_threaded_irq(wm8994->micdet_irq, NULL, |
3222 | wm8958_mic_irq, "Mic detect", | 3222 | wm8958_mic_irq, |
3223 | wm8994); | 3223 | IRQF_TRIGGER_RISING, |
3224 | if (ret != 0) | 3224 | "Mic detect", |
3225 | dev_warn(codec->dev, | 3225 | wm8994); |
3226 | "Failed to request Mic detect IRQ: %d\n", | 3226 | if (ret != 0) |
3227 | ret); | 3227 | dev_warn(codec->dev, |
3228 | break; | 3228 | "Failed to request Mic detect IRQ: %d\n", |
3229 | ret); | ||
3230 | } | ||
3229 | } | 3231 | } |
3230 | 3232 | ||
3231 | /* Remember if AIFnLRCLK is configured as a GPIO. This should be | 3233 | /* Remember if AIFnLRCLK is configured as a GPIO. This should be |
@@ -3369,7 +3371,8 @@ err_irq: | |||
3369 | wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC2_SHRT, wm8994); | 3371 | wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC2_SHRT, wm8994); |
3370 | wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC2_DET, wm8994); | 3372 | wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC2_DET, wm8994); |
3371 | wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC1_SHRT, wm8994); | 3373 | wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC1_SHRT, wm8994); |
3372 | wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC1_DET, wm8994); | 3374 | if (wm8994->micdet_irq) |
3375 | free_irq(wm8994->micdet_irq, wm8994); | ||
3373 | err: | 3376 | err: |
3374 | kfree(wm8994); | 3377 | kfree(wm8994); |
3375 | return ret; | 3378 | return ret; |
@@ -3386,8 +3389,8 @@ static int wm8994_codec_remove(struct snd_soc_codec *codec) | |||
3386 | 3389 | ||
3387 | switch (control->type) { | 3390 | switch (control->type) { |
3388 | case WM8994: | 3391 | case WM8994: |
3389 | wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC2_SHRT, | 3392 | if (wm8994->micdet_irq) |
3390 | wm8994); | 3393 | free_irq(wm8994->micdet_irq, wm8994); |
3391 | wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC2_DET, | 3394 | wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC2_DET, |
3392 | wm8994); | 3395 | wm8994); |
3393 | wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC1_SHRT, | 3396 | wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC1_SHRT, |
@@ -3397,8 +3400,8 @@ static int wm8994_codec_remove(struct snd_soc_codec *codec) | |||
3397 | break; | 3400 | break; |
3398 | 3401 | ||
3399 | case WM8958: | 3402 | case WM8958: |
3400 | wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC1_DET, | 3403 | if (wm8994->micdet_irq) |
3401 | wm8994); | 3404 | free_irq(wm8994->micdet_irq, wm8994); |
3402 | break; | 3405 | break; |
3403 | } | 3406 | } |
3404 | kfree(wm8994->retune_mobile_texts); | 3407 | kfree(wm8994->retune_mobile_texts); |