aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/codecs/wm8994.c
diff options
context:
space:
mode:
authorMark Brown <broonie@opensource.wolfsonmicro.com>2011-07-12 06:47:59 -0400
committerMark Brown <broonie@opensource.wolfsonmicro.com>2011-07-13 11:38:22 -0400
commitc7ebf932e5afa9caf8720435519b857b5d6e63bc (patch)
tree6ddfd65bd572b2680782480a4d521095d7af40de /sound/soc/codecs/wm8994.c
parentb30ead5f391d34c6011e6affe88eb21bb0b9f9dd (diff)
ASoC: Use WM8994 FLL lock interrupt
If we have interrupts then wait for the FLL lock interrupt rather than using dead reckoning when waiting for the FLL to start. Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'sound/soc/codecs/wm8994.c')
-rw-r--r--sound/soc/codecs/wm8994.c40
1 files changed, 39 insertions, 1 deletions
diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c
index d2dcaa29c7ca..f89ae47f3c32 100644
--- a/sound/soc/codecs/wm8994.c
+++ b/sound/soc/codecs/wm8994.c
@@ -1635,6 +1635,7 @@ static int _wm8994_set_fll(struct snd_soc_codec *codec, int id, int src,
1635 int reg_offset, ret; 1635 int reg_offset, ret;
1636 struct fll_div fll; 1636 struct fll_div fll;
1637 u16 reg, aif1, aif2; 1637 u16 reg, aif1, aif2;
1638 unsigned long timeout;
1638 1639
1639 aif1 = snd_soc_read(codec, WM8994_AIF1_CLOCKING_1) 1640 aif1 = snd_soc_read(codec, WM8994_AIF1_CLOCKING_1)
1640 & WM8994_AIF1CLK_ENA; 1641 & WM8994_AIF1CLK_ENA;
@@ -1726,7 +1727,15 @@ static int _wm8994_set_fll(struct snd_soc_codec *codec, int id, int src,
1726 WM8994_FLL1_ENA | WM8994_FLL1_FRAC, 1727 WM8994_FLL1_ENA | WM8994_FLL1_FRAC,
1727 reg); 1728 reg);
1728 1729
1729 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 }
1730 } 1739 }
1731 1740
1732 wm8994->fll[id].in = freq_in; 1741 wm8994->fll[id].in = freq_in;
@@ -1744,6 +1753,14 @@ static int _wm8994_set_fll(struct snd_soc_codec *codec, int id, int src,
1744 return 0; 1753 return 0;
1745} 1754}
1746 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}
1747 1764
1748static 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 };
1749 1766
@@ -2879,6 +2896,9 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
2879 wm8994->pdata = dev_get_platdata(codec->dev->parent); 2896 wm8994->pdata = dev_get_platdata(codec->dev->parent);
2880 wm8994->codec = codec; 2897 wm8994->codec = codec;
2881 2898
2899 for (i = 0; i < ARRAY_SIZE(wm8994->fll_locked); i++)
2900 init_completion(&wm8994->fll_locked[i]);
2901
2882 if (wm8994->pdata && wm8994->pdata->micdet_irq) 2902 if (wm8994->pdata && wm8994->pdata->micdet_irq)
2883 wm8994->micdet_irq = wm8994->pdata->micdet_irq; 2903 wm8994->micdet_irq = wm8994->pdata->micdet_irq;
2884 else if (wm8994->pdata && wm8994->pdata->irq_base) 2904 else if (wm8994->pdata && wm8994->pdata->irq_base)
@@ -2994,6 +3014,16 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
2994 } 3014 }
2995 } 3015 }
2996 3016
3017 wm8994->fll_locked_irq = true;
3018 for (i = 0; i < ARRAY_SIZE(wm8994->fll_locked); i++) {
3019 ret = wm8994_request_irq(codec->control_data,
3020 WM8994_IRQ_FLL1_LOCK + i,
3021 wm8994_fll_locked_irq, "FLL lock",
3022 &wm8994->fll_locked[i]);
3023 if (ret != 0)
3024 wm8994->fll_locked_irq = false;
3025 }
3026
2997 /* Remember if AIFnLRCLK is configured as a GPIO. This should be 3027 /* Remember if AIFnLRCLK is configured as a GPIO. This should be
2998 * configured on init - if a system wants to do this dynamically 3028 * configured on init - if a system wants to do this dynamically
2999 * at runtime we can deal with that then. 3029 * at runtime we can deal with that then.
@@ -3179,6 +3209,9 @@ err_irq:
3179 wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC1_SHRT, wm8994); 3209 wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC1_SHRT, wm8994);
3180 if (wm8994->micdet_irq) 3210 if (wm8994->micdet_irq)
3181 free_irq(wm8994->micdet_irq, wm8994); 3211 free_irq(wm8994->micdet_irq, wm8994);
3212 for (i = 0; i < ARRAY_SIZE(wm8994->fll_locked); i++)
3213 wm8994_free_irq(codec->control_data, WM8994_IRQ_FLL1_LOCK + i,
3214 &wm8994->fll_locked[i]);
3182 wm8994_free_irq(codec->control_data, WM8994_IRQ_DCS_DONE, 3215 wm8994_free_irq(codec->control_data, WM8994_IRQ_DCS_DONE,
3183 &wm8994->hubs); 3216 &wm8994->hubs);
3184err: 3217err:
@@ -3190,11 +3223,16 @@ static int wm8994_codec_remove(struct snd_soc_codec *codec)
3190{ 3223{
3191 struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); 3224 struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
3192 struct wm8994 *control = codec->control_data; 3225 struct wm8994 *control = codec->control_data;
3226 int i;
3193 3227
3194 wm8994_set_bias_level(codec, SND_SOC_BIAS_OFF); 3228 wm8994_set_bias_level(codec, SND_SOC_BIAS_OFF);
3195 3229
3196 pm_runtime_disable(codec->dev); 3230 pm_runtime_disable(codec->dev);
3197 3231
3232 for (i = 0; i < ARRAY_SIZE(wm8994->fll_locked); i++)
3233 wm8994_free_irq(codec->control_data, WM8994_IRQ_FLL1_LOCK + i,
3234 &wm8994->fll_locked[i]);
3235
3198 wm8994_free_irq(codec->control_data, WM8994_IRQ_DCS_DONE, 3236 wm8994_free_irq(codec->control_data, WM8994_IRQ_DCS_DONE,
3199 &wm8994->hubs); 3237 &wm8994->hubs);
3200 3238