diff options
Diffstat (limited to 'sound/soc/codecs/wm8994.c')
-rw-r--r-- | sound/soc/codecs/wm8994.c | 62 |
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[] = { | |||
56 | static int wm8994_readable(struct snd_soc_codec *codec, unsigned int reg) | 56 | static 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 | ||
1327 | static const struct snd_soc_dapm_widget wm8994_adc_revd_widgets[] = { | 1327 | static const struct snd_soc_dapm_widget wm8994_adc_revd_widgets[] = { |
1328 | SND_SOC_DAPM_MUX_E("ADCL Mux", WM8994_POWER_MANAGEMENT_4, 1, 0, &adcl_mux, | 1328 | SND_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), |
1330 | SND_SOC_DAPM_MUX_E("ADCR Mux", WM8994_POWER_MANAGEMENT_4, 0, 0, &adcr_mux, | 1330 | SND_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 | ||
1334 | static const struct snd_soc_dapm_widget wm8994_adc_widgets[] = { | 1334 | static const struct snd_soc_dapm_widget wm8994_adc_widgets[] = { |
1335 | SND_SOC_DAPM_MUX("ADCL Mux", WM8994_POWER_MANAGEMENT_4, 1, 0, &adcl_mux), | 1335 | SND_SOC_DAPM_VIRT_MUX("ADCL Mux", WM8994_POWER_MANAGEMENT_4, 1, 0, &adcl_mux), |
1336 | SND_SOC_DAPM_MUX("ADCR Mux", WM8994_POWER_MANAGEMENT_4, 0, 0, &adcr_mux), | 1336 | SND_SOC_DAPM_VIRT_MUX("ADCR Mux", WM8994_POWER_MANAGEMENT_4, 0, 0, &adcr_mux), |
1337 | }; | 1337 | }; |
1338 | 1338 | ||
1339 | static const struct snd_soc_dapm_widget wm8994_dapm_widgets[] = { | 1339 | static 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, |