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.c62
1 files changed, 42 insertions, 20 deletions
diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c
index 6b73efd26991..d0c545b73d78 100644
--- a/sound/soc/codecs/wm8994.c
+++ b/sound/soc/codecs/wm8994.c
@@ -56,7 +56,7 @@ static int wm8994_retune_mobile_base[] = {
56static int wm8994_readable(struct snd_soc_codec *codec, unsigned int reg) 56static int wm8994_readable(struct snd_soc_codec *codec, unsigned int reg)
57{ 57{
58 struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); 58 struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
59 struct wm8994 *control = wm8994->control_data; 59 struct wm8994 *control = codec->control_data;
60 60
61 switch (reg) { 61 switch (reg) {
62 case WM8994_GPIO_1: 62 case WM8994_GPIO_1:
@@ -1325,15 +1325,15 @@ SND_SOC_DAPM_DAC("DAC1R", NULL, WM8994_POWER_MANAGEMENT_5, 0, 0),
1325}; 1325};
1326 1326
1327static const struct snd_soc_dapm_widget wm8994_adc_revd_widgets[] = { 1327static const struct snd_soc_dapm_widget wm8994_adc_revd_widgets[] = {
1328SND_SOC_DAPM_MUX_E("ADCL Mux", WM8994_POWER_MANAGEMENT_4, 1, 0, &adcl_mux, 1328SND_SOC_DAPM_VIRT_MUX_E("ADCL Mux", WM8994_POWER_MANAGEMENT_4, 1, 0, &adcl_mux,
1329 adc_mux_ev, SND_SOC_DAPM_PRE_PMU), 1329 adc_mux_ev, SND_SOC_DAPM_PRE_PMU),
1330SND_SOC_DAPM_MUX_E("ADCR Mux", WM8994_POWER_MANAGEMENT_4, 0, 0, &adcr_mux, 1330SND_SOC_DAPM_VIRT_MUX_E("ADCR Mux", WM8994_POWER_MANAGEMENT_4, 0, 0, &adcr_mux,
1331 adc_mux_ev, SND_SOC_DAPM_PRE_PMU), 1331 adc_mux_ev, SND_SOC_DAPM_PRE_PMU),
1332}; 1332};
1333 1333
1334static const struct snd_soc_dapm_widget wm8994_adc_widgets[] = { 1334static const struct snd_soc_dapm_widget wm8994_adc_widgets[] = {
1335SND_SOC_DAPM_MUX("ADCL Mux", WM8994_POWER_MANAGEMENT_4, 1, 0, &adcl_mux), 1335SND_SOC_DAPM_VIRT_MUX("ADCL Mux", WM8994_POWER_MANAGEMENT_4, 1, 0, &adcl_mux),
1336SND_SOC_DAPM_MUX("ADCR Mux", WM8994_POWER_MANAGEMENT_4, 0, 0, &adcr_mux), 1336SND_SOC_DAPM_VIRT_MUX("ADCR Mux", WM8994_POWER_MANAGEMENT_4, 0, 0, &adcr_mux),
1337}; 1337};
1338 1338
1339static const struct snd_soc_dapm_widget wm8994_dapm_widgets[] = { 1339static const struct snd_soc_dapm_widget wm8994_dapm_widgets[] = {
@@ -2357,6 +2357,11 @@ static int wm8994_hw_params(struct snd_pcm_substream *substream,
2357 bclk |= best << WM8994_AIF1_BCLK_DIV_SHIFT; 2357 bclk |= best << WM8994_AIF1_BCLK_DIV_SHIFT;
2358 2358
2359 lrclk = bclk_rate / params_rate(params); 2359 lrclk = bclk_rate / params_rate(params);
2360 if (!lrclk) {
2361 dev_err(dai->dev, "Unable to generate LRCLK from %dHz BCLK\n",
2362 bclk_rate);
2363 return -EINVAL;
2364 }
2360 dev_dbg(dai->dev, "Using LRCLK rate %d for actual LRCLK %dHz\n", 2365 dev_dbg(dai->dev, "Using LRCLK rate %d for actual LRCLK %dHz\n",
2361 lrclk, bclk_rate / lrclk); 2366 lrclk, bclk_rate / lrclk);
2362 2367
@@ -3030,19 +3035,34 @@ static irqreturn_t wm8958_mic_irq(int irq, void *data)
3030{ 3035{
3031 struct wm8994_priv *wm8994 = data; 3036 struct wm8994_priv *wm8994 = data;
3032 struct snd_soc_codec *codec = wm8994->codec; 3037 struct snd_soc_codec *codec = wm8994->codec;
3033 int reg; 3038 int reg, count;
3034 3039
3035 reg = snd_soc_read(codec, WM8958_MIC_DETECT_3); 3040 /* We may occasionally read a detection without an impedence
3036 if (reg < 0) { 3041 * range being provided - if that happens loop again.
3037 dev_err(codec->dev, "Failed to read mic detect status: %d\n", 3042 */
3038 reg); 3043 count = 10;
3039 return IRQ_NONE; 3044 do {
3040 } 3045 reg = snd_soc_read(codec, WM8958_MIC_DETECT_3);
3046 if (reg < 0) {
3047 dev_err(codec->dev,
3048 "Failed to read mic detect status: %d\n",
3049 reg);
3050 return IRQ_NONE;
3051 }
3041 3052
3042 if (!(reg & WM8958_MICD_VALID)) { 3053 if (!(reg & WM8958_MICD_VALID)) {
3043 dev_dbg(codec->dev, "Mic detect data not valid\n"); 3054 dev_dbg(codec->dev, "Mic detect data not valid\n");
3044 goto out; 3055 goto out;
3045 } 3056 }
3057
3058 if (!(reg & WM8958_MICD_STS) || (reg & WM8958_MICD_LVL_MASK))
3059 break;
3060
3061 msleep(1);
3062 } while (count--);
3063
3064 if (count == 0)
3065 dev_warn(codec->dev, "No impedence range reported for jack\n");
3046 3066
3047#ifndef CONFIG_SND_SOC_WM8994_MODULE 3067#ifndef CONFIG_SND_SOC_WM8994_MODULE
3048 trace_snd_soc_jack_irq(dev_name(codec->dev)); 3068 trace_snd_soc_jack_irq(dev_name(codec->dev));
@@ -3163,6 +3183,8 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
3163 switch (wm8994->revision) { 3183 switch (wm8994->revision) {
3164 case 0: 3184 case 0:
3165 case 1: 3185 case 1:
3186 case 2:
3187 case 3:
3166 wm8994->hubs.dcs_codes_l = -9; 3188 wm8994->hubs.dcs_codes_l = -9;
3167 wm8994->hubs.dcs_codes_r = -5; 3189 wm8994->hubs.dcs_codes_r = -5;
3168 break; 3190 break;
@@ -3180,9 +3202,9 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
3180 3202
3181 wm8994_request_irq(codec->control_data, WM8994_IRQ_FIFOS_ERR, 3203 wm8994_request_irq(codec->control_data, WM8994_IRQ_FIFOS_ERR,
3182 wm8994_fifo_error, "FIFO error", codec); 3204 wm8994_fifo_error, "FIFO error", codec);
3183 wm8994_request_irq(wm8994->control_data, WM8994_IRQ_TEMP_WARN, 3205 wm8994_request_irq(codec->control_data, WM8994_IRQ_TEMP_WARN,
3184 wm8994_temp_warn, "Thermal warning", codec); 3206 wm8994_temp_warn, "Thermal warning", codec);
3185 wm8994_request_irq(wm8994->control_data, WM8994_IRQ_TEMP_SHUT, 3207 wm8994_request_irq(codec->control_data, WM8994_IRQ_TEMP_SHUT,
3186 wm8994_temp_shut, "Thermal shutdown", codec); 3208 wm8994_temp_shut, "Thermal shutdown", codec);
3187 3209
3188 ret = wm8994_request_irq(codec->control_data, WM8994_IRQ_DCS_DONE, 3210 ret = wm8994_request_irq(codec->control_data, WM8994_IRQ_DCS_DONE,