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.c157
1 files changed, 135 insertions, 22 deletions
diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c
index c2fc0356c2a4..09e680ae88b2 100644
--- a/sound/soc/codecs/wm8994.c
+++ b/sound/soc/codecs/wm8994.c
@@ -195,10 +195,6 @@ static int configure_aif_clock(struct snd_soc_codec *codec, int aif)
195 aif + 1, rate); 195 aif + 1, rate);
196 } 196 }
197 197
198 if (rate && rate < 3000000)
199 dev_warn(codec->dev, "AIF%dCLK is %dHz, should be >=3MHz for optimal performance\n",
200 aif + 1, rate);
201
202 wm8994->aifclk[aif] = rate; 198 wm8994->aifclk[aif] = rate;
203 199
204 snd_soc_update_bits(codec, WM8994_AIF1_CLOCKING_1 + offset, 200 snd_soc_update_bits(codec, WM8994_AIF1_CLOCKING_1 + offset,
@@ -1146,13 +1142,33 @@ SND_SOC_DAPM_PGA_E("Late DAC2L Enable PGA", SND_SOC_NOPM, 0, 0, NULL, 0,
1146 late_enable_ev, SND_SOC_DAPM_PRE_PMU), 1142 late_enable_ev, SND_SOC_DAPM_PRE_PMU),
1147SND_SOC_DAPM_PGA_E("Late DAC2R Enable PGA", SND_SOC_NOPM, 0, 0, NULL, 0, 1143SND_SOC_DAPM_PGA_E("Late DAC2R Enable PGA", SND_SOC_NOPM, 0, 0, NULL, 0,
1148 late_enable_ev, SND_SOC_DAPM_PRE_PMU), 1144 late_enable_ev, SND_SOC_DAPM_PRE_PMU),
1145SND_SOC_DAPM_PGA_E("Direct Voice", SND_SOC_NOPM, 0, 0, NULL, 0,
1146 late_enable_ev, SND_SOC_DAPM_PRE_PMU),
1147
1148SND_SOC_DAPM_MIXER_E("SPKL", WM8994_POWER_MANAGEMENT_3, 8, 0,
1149 left_speaker_mixer, ARRAY_SIZE(left_speaker_mixer),
1150 late_enable_ev, SND_SOC_DAPM_PRE_PMU),
1151SND_SOC_DAPM_MIXER_E("SPKR", WM8994_POWER_MANAGEMENT_3, 9, 0,
1152 right_speaker_mixer, ARRAY_SIZE(right_speaker_mixer),
1153 late_enable_ev, SND_SOC_DAPM_PRE_PMU),
1154SND_SOC_DAPM_MUX_E("Left Headphone Mux", SND_SOC_NOPM, 0, 0, &hpl_mux,
1155 late_enable_ev, SND_SOC_DAPM_PRE_PMU),
1156SND_SOC_DAPM_MUX_E("Right Headphone Mux", SND_SOC_NOPM, 0, 0, &hpr_mux,
1157 late_enable_ev, SND_SOC_DAPM_PRE_PMU),
1149 1158
1150SND_SOC_DAPM_POST("Late Disable PGA", late_disable_ev) 1159SND_SOC_DAPM_POST("Late Disable PGA", late_disable_ev)
1151}; 1160};
1152 1161
1153static const struct snd_soc_dapm_widget wm8994_lateclk_widgets[] = { 1162static const struct snd_soc_dapm_widget wm8994_lateclk_widgets[] = {
1154SND_SOC_DAPM_SUPPLY("AIF1CLK", WM8994_AIF1_CLOCKING_1, 0, 0, NULL, 0), 1163SND_SOC_DAPM_SUPPLY("AIF1CLK", WM8994_AIF1_CLOCKING_1, 0, 0, NULL, 0),
1155SND_SOC_DAPM_SUPPLY("AIF2CLK", WM8994_AIF2_CLOCKING_1, 0, 0, NULL, 0) 1164SND_SOC_DAPM_SUPPLY("AIF2CLK", WM8994_AIF2_CLOCKING_1, 0, 0, NULL, 0),
1165SND_SOC_DAPM_PGA("Direct Voice", SND_SOC_NOPM, 0, 0, NULL, 0),
1166SND_SOC_DAPM_MIXER("SPKL", WM8994_POWER_MANAGEMENT_3, 8, 0,
1167 left_speaker_mixer, ARRAY_SIZE(left_speaker_mixer)),
1168SND_SOC_DAPM_MIXER("SPKR", WM8994_POWER_MANAGEMENT_3, 9, 0,
1169 right_speaker_mixer, ARRAY_SIZE(right_speaker_mixer)),
1170SND_SOC_DAPM_MUX("Left Headphone Mux", SND_SOC_NOPM, 0, 0, &hpl_mux),
1171SND_SOC_DAPM_MUX("Right Headphone Mux", SND_SOC_NOPM, 0, 0, &hpr_mux),
1156}; 1172};
1157 1173
1158static const struct snd_soc_dapm_widget wm8994_dac_revd_widgets[] = { 1174static const struct snd_soc_dapm_widget wm8994_dac_revd_widgets[] = {
@@ -1190,7 +1206,6 @@ SND_SOC_DAPM_INPUT("DMIC1DAT"),
1190SND_SOC_DAPM_INPUT("DMIC2DAT"), 1206SND_SOC_DAPM_INPUT("DMIC2DAT"),
1191SND_SOC_DAPM_INPUT("Clock"), 1207SND_SOC_DAPM_INPUT("Clock"),
1192 1208
1193SND_SOC_DAPM_MICBIAS("MICBIAS", WM8994_MICBIAS, 2, 0),
1194SND_SOC_DAPM_SUPPLY_S("MICBIAS Supply", 1, SND_SOC_NOPM, 0, 0, micbias_ev, 1209SND_SOC_DAPM_SUPPLY_S("MICBIAS Supply", 1, SND_SOC_NOPM, 0, 0, micbias_ev,
1195 SND_SOC_DAPM_PRE_PMU), 1210 SND_SOC_DAPM_PRE_PMU),
1196 1211
@@ -1283,14 +1298,6 @@ SND_SOC_DAPM_ADC("DMIC1R", NULL, WM8994_POWER_MANAGEMENT_4, 2, 0),
1283SND_SOC_DAPM_ADC("ADCL", NULL, SND_SOC_NOPM, 1, 0), 1298SND_SOC_DAPM_ADC("ADCL", NULL, SND_SOC_NOPM, 1, 0),
1284SND_SOC_DAPM_ADC("ADCR", NULL, SND_SOC_NOPM, 0, 0), 1299SND_SOC_DAPM_ADC("ADCR", NULL, SND_SOC_NOPM, 0, 0),
1285 1300
1286SND_SOC_DAPM_MUX("Left Headphone Mux", SND_SOC_NOPM, 0, 0, &hpl_mux),
1287SND_SOC_DAPM_MUX("Right Headphone Mux", SND_SOC_NOPM, 0, 0, &hpr_mux),
1288
1289SND_SOC_DAPM_MIXER("SPKL", WM8994_POWER_MANAGEMENT_3, 8, 0,
1290 left_speaker_mixer, ARRAY_SIZE(left_speaker_mixer)),
1291SND_SOC_DAPM_MIXER("SPKR", WM8994_POWER_MANAGEMENT_3, 9, 0,
1292 right_speaker_mixer, ARRAY_SIZE(right_speaker_mixer)),
1293
1294SND_SOC_DAPM_POST("Debug log", post_ev), 1301SND_SOC_DAPM_POST("Debug log", post_ev),
1295}; 1302};
1296 1303
@@ -1509,8 +1516,10 @@ static const struct snd_soc_dapm_route wm8994_revd_intercon[] = {
1509 { "AIF2DACDAT", NULL, "AIF1DACDAT" }, 1516 { "AIF2DACDAT", NULL, "AIF1DACDAT" },
1510 { "AIF1ADCDAT", NULL, "AIF2ADCDAT" }, 1517 { "AIF1ADCDAT", NULL, "AIF2ADCDAT" },
1511 { "AIF2ADCDAT", NULL, "AIF1ADCDAT" }, 1518 { "AIF2ADCDAT", NULL, "AIF1ADCDAT" },
1512 { "MICBIAS", NULL, "CLK_SYS" }, 1519 { "MICBIAS1", NULL, "CLK_SYS" },
1513 { "MICBIAS", NULL, "MICBIAS Supply" }, 1520 { "MICBIAS1", NULL, "MICBIAS Supply" },
1521 { "MICBIAS2", NULL, "CLK_SYS" },
1522 { "MICBIAS2", NULL, "MICBIAS Supply" },
1514}; 1523};
1515 1524
1516static const struct snd_soc_dapm_route wm8994_intercon[] = { 1525static const struct snd_soc_dapm_route wm8994_intercon[] = {
@@ -1623,6 +1632,7 @@ static int _wm8994_set_fll(struct snd_soc_codec *codec, int id, int src,
1623 int reg_offset, ret; 1632 int reg_offset, ret;
1624 struct fll_div fll; 1633 struct fll_div fll;
1625 u16 reg, aif1, aif2; 1634 u16 reg, aif1, aif2;
1635 unsigned long timeout;
1626 1636
1627 aif1 = snd_soc_read(codec, WM8994_AIF1_CLOCKING_1) 1637 aif1 = snd_soc_read(codec, WM8994_AIF1_CLOCKING_1)
1628 & WM8994_AIF1CLK_ENA; 1638 & WM8994_AIF1CLK_ENA;
@@ -1704,6 +1714,9 @@ static int _wm8994_set_fll(struct snd_soc_codec *codec, int id, int src,
1704 (fll.clk_ref_div << WM8994_FLL1_REFCLK_DIV_SHIFT) | 1714 (fll.clk_ref_div << WM8994_FLL1_REFCLK_DIV_SHIFT) |
1705 (src - 1)); 1715 (src - 1));
1706 1716
1717 /* Clear any pending completion from a previous failure */
1718 try_wait_for_completion(&wm8994->fll_locked[id]);
1719
1707 /* Enable (with fractional mode if required) */ 1720 /* Enable (with fractional mode if required) */
1708 if (freq_out) { 1721 if (freq_out) {
1709 if (fll.k) 1722 if (fll.k)
@@ -1714,7 +1727,15 @@ static int _wm8994_set_fll(struct snd_soc_codec *codec, int id, int src,
1714 WM8994_FLL1_ENA | WM8994_FLL1_FRAC, 1727 WM8994_FLL1_ENA | WM8994_FLL1_FRAC,
1715 reg); 1728 reg);
1716 1729
1717 msleep(5); 1730 if (wm8994->fll_locked_irq) {
1731 timeout = wait_for_completion_timeout(&wm8994->fll_locked[id],
1732 msecs_to_jiffies(10));
1733 if (timeout == 0)
1734 dev_warn(codec->dev,
1735 "Timed out waiting for FLL lock\n");
1736 } else {
1737 msleep(5);
1738 }
1718 } 1739 }
1719 1740
1720 wm8994->fll[id].in = freq_in; 1741 wm8994->fll[id].in = freq_in;
@@ -1732,6 +1753,14 @@ static int _wm8994_set_fll(struct snd_soc_codec *codec, int id, int src,
1732 return 0; 1753 return 0;
1733} 1754}
1734 1755
1756static irqreturn_t wm8994_fll_locked_irq(int irq, void *data)
1757{
1758 struct completion *completion = data;
1759
1760 complete(completion);
1761
1762 return IRQ_HANDLED;
1763}
1735 1764
1736static int opclk_divs[] = { 10, 20, 30, 40, 55, 60, 80, 120, 160 }; 1765static int opclk_divs[] = { 10, 20, 30, 40, 55, 60, 80, 120, 160 };
1737 1766
@@ -2271,6 +2300,33 @@ static int wm8994_aif3_hw_params(struct snd_pcm_substream *substream,
2271 return snd_soc_update_bits(codec, aif1_reg, WM8994_AIF1_WL_MASK, aif1); 2300 return snd_soc_update_bits(codec, aif1_reg, WM8994_AIF1_WL_MASK, aif1);
2272} 2301}
2273 2302
2303static void wm8994_aif_shutdown(struct snd_pcm_substream *substream,
2304 struct snd_soc_dai *dai)
2305{
2306 struct snd_soc_codec *codec = dai->codec;
2307 int rate_reg = 0;
2308
2309 switch (dai->id) {
2310 case 1:
2311 rate_reg = WM8994_AIF1_RATE;
2312 break;
2313 case 2:
2314 rate_reg = WM8994_AIF1_RATE;
2315 break;
2316 default:
2317 break;
2318 }
2319
2320 /* If the DAI is idle then configure the divider tree for the
2321 * lowest output rate to save a little power if the clock is
2322 * still active (eg, because it is system clock).
2323 */
2324 if (rate_reg && !dai->playback_active && !dai->capture_active)
2325 snd_soc_update_bits(codec, rate_reg,
2326 WM8994_AIF1_SR_MASK |
2327 WM8994_AIF1CLK_RATE_MASK, 0x9);
2328}
2329
2274static int wm8994_aif_mute(struct snd_soc_dai *codec_dai, int mute) 2330static int wm8994_aif_mute(struct snd_soc_dai *codec_dai, int mute)
2275{ 2331{
2276 struct snd_soc_codec *codec = codec_dai->codec; 2332 struct snd_soc_codec *codec = codec_dai->codec;
@@ -2337,6 +2393,7 @@ static struct snd_soc_dai_ops wm8994_aif1_dai_ops = {
2337 .set_sysclk = wm8994_set_dai_sysclk, 2393 .set_sysclk = wm8994_set_dai_sysclk,
2338 .set_fmt = wm8994_set_dai_fmt, 2394 .set_fmt = wm8994_set_dai_fmt,
2339 .hw_params = wm8994_hw_params, 2395 .hw_params = wm8994_hw_params,
2396 .shutdown = wm8994_aif_shutdown,
2340 .digital_mute = wm8994_aif_mute, 2397 .digital_mute = wm8994_aif_mute,
2341 .set_pll = wm8994_set_fll, 2398 .set_pll = wm8994_set_fll,
2342 .set_tristate = wm8994_set_tristate, 2399 .set_tristate = wm8994_set_tristate,
@@ -2346,6 +2403,7 @@ static struct snd_soc_dai_ops wm8994_aif2_dai_ops = {
2346 .set_sysclk = wm8994_set_dai_sysclk, 2403 .set_sysclk = wm8994_set_dai_sysclk,
2347 .set_fmt = wm8994_set_dai_fmt, 2404 .set_fmt = wm8994_set_dai_fmt,
2348 .hw_params = wm8994_hw_params, 2405 .hw_params = wm8994_hw_params,
2406 .shutdown = wm8994_aif_shutdown,
2349 .digital_mute = wm8994_aif_mute, 2407 .digital_mute = wm8994_aif_mute,
2350 .set_pll = wm8994_set_fll, 2408 .set_pll = wm8994_set_fll,
2351 .set_tristate = wm8994_set_tristate, 2409 .set_tristate = wm8994_set_tristate,
@@ -2763,7 +2821,7 @@ static void wm8958_default_micdet(u16 status, void *data)
2763 report = SND_JACK_MICROPHONE; 2821 report = SND_JACK_MICROPHONE;
2764 2822
2765 /* Everything else is buttons; just assign slots */ 2823 /* Everything else is buttons; just assign slots */
2766 if (status & 0x1c0) 2824 if (status & 0x1c)
2767 report |= SND_JACK_BTN_0; 2825 report |= SND_JACK_BTN_0;
2768 2826
2769done: 2827done:
@@ -2849,6 +2907,15 @@ out:
2849 return IRQ_HANDLED; 2907 return IRQ_HANDLED;
2850} 2908}
2851 2909
2910static irqreturn_t wm8994_fifo_error(int irq, void *data)
2911{
2912 struct snd_soc_codec *codec = data;
2913
2914 dev_err(codec->dev, "FIFO error\n");
2915
2916 return IRQ_HANDLED;
2917}
2918
2852static int wm8994_codec_probe(struct snd_soc_codec *codec) 2919static int wm8994_codec_probe(struct snd_soc_codec *codec)
2853{ 2920{
2854 struct wm8994 *control; 2921 struct wm8994 *control;
@@ -2867,6 +2934,9 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
2867 wm8994->pdata = dev_get_platdata(codec->dev->parent); 2934 wm8994->pdata = dev_get_platdata(codec->dev->parent);
2868 wm8994->codec = codec; 2935 wm8994->codec = codec;
2869 2936
2937 for (i = 0; i < ARRAY_SIZE(wm8994->fll_locked); i++)
2938 init_completion(&wm8994->fll_locked[i]);
2939
2870 if (wm8994->pdata && wm8994->pdata->micdet_irq) 2940 if (wm8994->pdata && wm8994->pdata->micdet_irq)
2871 wm8994->micdet_irq = wm8994->pdata->micdet_irq; 2941 wm8994->micdet_irq = wm8994->pdata->micdet_irq;
2872 else if (wm8994->pdata && wm8994->pdata->irq_base) 2942 else if (wm8994->pdata && wm8994->pdata->irq_base)
@@ -2905,6 +2975,7 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
2905 wm8994->hubs.dcs_codes = -5; 2975 wm8994->hubs.dcs_codes = -5;
2906 wm8994->hubs.hp_startup_mode = 1; 2976 wm8994->hubs.hp_startup_mode = 1;
2907 wm8994->hubs.dcs_readback_mode = 1; 2977 wm8994->hubs.dcs_readback_mode = 1;
2978 wm8994->hubs.series_startup = 1;
2908 break; 2979 break;
2909 default: 2980 default:
2910 wm8994->hubs.dcs_readback_mode = 1; 2981 wm8994->hubs.dcs_readback_mode = 1;
@@ -2919,6 +2990,15 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
2919 break; 2990 break;
2920 } 2991 }
2921 2992
2993 wm8994_request_irq(codec->control_data, WM8994_IRQ_FIFOS_ERR,
2994 wm8994_fifo_error, "FIFO error", codec);
2995
2996 ret = wm8994_request_irq(codec->control_data, WM8994_IRQ_DCS_DONE,
2997 wm_hubs_dcs_done, "DC servo done",
2998 &wm8994->hubs);
2999 if (ret == 0)
3000 wm8994->hubs.dcs_done_irq = true;
3001
2922 switch (control->type) { 3002 switch (control->type) {
2923 case WM8994: 3003 case WM8994:
2924 if (wm8994->micdet_irq) { 3004 if (wm8994->micdet_irq) {
@@ -2975,6 +3055,16 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
2975 } 3055 }
2976 } 3056 }
2977 3057
3058 wm8994->fll_locked_irq = true;
3059 for (i = 0; i < ARRAY_SIZE(wm8994->fll_locked); i++) {
3060 ret = wm8994_request_irq(codec->control_data,
3061 WM8994_IRQ_FLL1_LOCK + i,
3062 wm8994_fll_locked_irq, "FLL lock",
3063 &wm8994->fll_locked[i]);
3064 if (ret != 0)
3065 wm8994->fll_locked_irq = false;
3066 }
3067
2978 /* Remember if AIFnLRCLK is configured as a GPIO. This should be 3068 /* Remember if AIFnLRCLK is configured as a GPIO. This should be
2979 * configured on init - if a system wants to do this dynamically 3069 * configured on init - if a system wants to do this dynamically
2980 * at runtime we can deal with that then. 3070 * at runtime we can deal with that then.
@@ -3050,10 +3140,18 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
3050 1 << WM8994_AIF2DAC_3D_GAIN_SHIFT, 3140 1 << WM8994_AIF2DAC_3D_GAIN_SHIFT,
3051 1 << WM8994_AIF2DAC_3D_GAIN_SHIFT); 3141 1 << WM8994_AIF2DAC_3D_GAIN_SHIFT);
3052 3142
3053 /* Unconditionally enable AIF1 ADC TDM mode; it only affects 3143 /* Unconditionally enable AIF1 ADC TDM mode on chips which can
3054 * behaviour on idle TDM clock cycles. */ 3144 * use this; it only affects behaviour on idle TDM clock
3055 snd_soc_update_bits(codec, WM8994_AIF1_CONTROL_1, 3145 * cycles. */
3056 WM8994_AIF1ADC_TDM, WM8994_AIF1ADC_TDM); 3146 switch (control->type) {
3147 case WM8994:
3148 case WM8958:
3149 snd_soc_update_bits(codec, WM8994_AIF1_CONTROL_1,
3150 WM8994_AIF1ADC_TDM, WM8994_AIF1ADC_TDM);
3151 break;
3152 default:
3153 break;
3154 }
3057 3155
3058 wm8994_update_class_w(codec); 3156 wm8994_update_class_w(codec);
3059 3157
@@ -3152,6 +3250,12 @@ err_irq:
3152 wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC1_SHRT, wm8994); 3250 wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC1_SHRT, wm8994);
3153 if (wm8994->micdet_irq) 3251 if (wm8994->micdet_irq)
3154 free_irq(wm8994->micdet_irq, wm8994); 3252 free_irq(wm8994->micdet_irq, wm8994);
3253 for (i = 0; i < ARRAY_SIZE(wm8994->fll_locked); i++)
3254 wm8994_free_irq(codec->control_data, WM8994_IRQ_FLL1_LOCK + i,
3255 &wm8994->fll_locked[i]);
3256 wm8994_free_irq(codec->control_data, WM8994_IRQ_DCS_DONE,
3257 &wm8994->hubs);
3258 wm8994_free_irq(codec->control_data, WM8994_IRQ_FIFOS_ERR, codec);
3155err: 3259err:
3156 kfree(wm8994); 3260 kfree(wm8994);
3157 return ret; 3261 return ret;
@@ -3161,11 +3265,20 @@ static int wm8994_codec_remove(struct snd_soc_codec *codec)
3161{ 3265{
3162 struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); 3266 struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
3163 struct wm8994 *control = codec->control_data; 3267 struct wm8994 *control = codec->control_data;
3268 int i;
3164 3269
3165 wm8994_set_bias_level(codec, SND_SOC_BIAS_OFF); 3270 wm8994_set_bias_level(codec, SND_SOC_BIAS_OFF);
3166 3271
3167 pm_runtime_disable(codec->dev); 3272 pm_runtime_disable(codec->dev);
3168 3273
3274 for (i = 0; i < ARRAY_SIZE(wm8994->fll_locked); i++)
3275 wm8994_free_irq(codec->control_data, WM8994_IRQ_FLL1_LOCK + i,
3276 &wm8994->fll_locked[i]);
3277
3278 wm8994_free_irq(codec->control_data, WM8994_IRQ_DCS_DONE,
3279 &wm8994->hubs);
3280 wm8994_free_irq(codec->control_data, WM8994_IRQ_FIFOS_ERR, codec);
3281
3169 switch (control->type) { 3282 switch (control->type) {
3170 case WM8994: 3283 case WM8994:
3171 if (wm8994->micdet_irq) 3284 if (wm8994->micdet_irq)