aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/codecs/wm8962.c
diff options
context:
space:
mode:
authorMark Brown <broonie@opensource.wolfsonmicro.com>2011-06-08 09:44:06 -0400
committerMark Brown <broonie@opensource.wolfsonmicro.com>2011-06-08 10:24:48 -0400
commit417ceff939bc61d4c71d24f071fad3f20ba4a1bd (patch)
treefb8170cfd1bb8a214f06ac5e94804284ba994afe /sound/soc/codecs/wm8962.c
parent8f63aaa887d723f52d44b41074486defcd42ad95 (diff)
ASoC: Defer all WM8962 clocking configuration until power up
Don't require an audio rate SYSCLK in hw_params() in order to better support microphone detection use cases. Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'sound/soc/codecs/wm8962.c')
-rw-r--r--sound/soc/codecs/wm8962.c60
1 files changed, 33 insertions, 27 deletions
diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c
index 2b3d961eb6b5..9b6c46f54b4d 100644
--- a/sound/soc/codecs/wm8962.c
+++ b/sound/soc/codecs/wm8962.c
@@ -2790,18 +2790,44 @@ static const int bclk_divs[] = {
2790 1, -1, 2, 3, 4, -1, 6, 8, -1, 12, 16, 24, -1, 32, 32, 32 2790 1, -1, 2, 3, 4, -1, 6, 8, -1, 12, 16, 24, -1, 32, 32, 32
2791}; 2791};
2792 2792
2793static const int sysclk_rates[] = {
2794 64, 128, 192, 256, 384, 512, 768, 1024, 1408, 1536,
2795};
2796
2793static void wm8962_configure_bclk(struct snd_soc_codec *codec) 2797static void wm8962_configure_bclk(struct snd_soc_codec *codec)
2794{ 2798{
2795 struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); 2799 struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);
2796 int dspclk, i; 2800 int dspclk, i;
2797 int clocking2 = 0; 2801 int clocking2 = 0;
2802 int clocking4 = 0;
2798 int aif2 = 0; 2803 int aif2 = 0;
2799 2804
2800 if (!wm8962->bclk) { 2805 if (!wm8962->sysclk_rate) {
2801 dev_dbg(codec->dev, "No BCLK rate configured\n"); 2806 dev_dbg(codec->dev, "No SYSCLK configured\n");
2802 return; 2807 return;
2803 } 2808 }
2804 2809
2810 if (!wm8962->bclk || !wm8962->lrclk) {
2811 dev_dbg(codec->dev, "No audio clocks configured\n");
2812 return;
2813 }
2814
2815 for (i = 0; i < ARRAY_SIZE(sysclk_rates); i++) {
2816 if (sysclk_rates[i] == wm8962->sysclk_rate / wm8962->lrclk) {
2817 clocking4 |= i << WM8962_SYSCLK_RATE_SHIFT;
2818 break;
2819 }
2820 }
2821
2822 if (i == ARRAY_SIZE(sysclk_rates)) {
2823 dev_err(codec->dev, "Unsupported sysclk ratio %d\n",
2824 wm8962->sysclk_rate / wm8962->lrclk);
2825 return;
2826 }
2827
2828 snd_soc_update_bits(codec, WM8962_CLOCKING_4,
2829 WM8962_SYSCLK_RATE_MASK, clocking4);
2830
2805 dspclk = snd_soc_read(codec, WM8962_CLOCKING1); 2831 dspclk = snd_soc_read(codec, WM8962_CLOCKING1);
2806 if (dspclk < 0) { 2832 if (dspclk < 0) {
2807 dev_err(codec->dev, "Failed to read DSPCLK: %d\n", dspclk); 2833 dev_err(codec->dev, "Failed to read DSPCLK: %d\n", dspclk);
@@ -2871,6 +2897,8 @@ static int wm8962_set_bias_level(struct snd_soc_codec *codec,
2871 /* VMID 2*50k */ 2897 /* VMID 2*50k */
2872 snd_soc_update_bits(codec, WM8962_PWR_MGMT_1, 2898 snd_soc_update_bits(codec, WM8962_PWR_MGMT_1,
2873 WM8962_VMID_SEL_MASK, 0x80); 2899 WM8962_VMID_SEL_MASK, 0x80);
2900
2901 wm8962_configure_bclk(codec);
2874 break; 2902 break;
2875 2903
2876 case SND_SOC_BIAS_STANDBY: 2904 case SND_SOC_BIAS_STANDBY:
@@ -2903,8 +2931,6 @@ static int wm8962_set_bias_level(struct snd_soc_codec *codec,
2903 snd_soc_update_bits(codec, WM8962_CLOCKING2, 2931 snd_soc_update_bits(codec, WM8962_CLOCKING2,
2904 WM8962_CLKREG_OVD, 2932 WM8962_CLKREG_OVD,
2905 WM8962_CLKREG_OVD); 2933 WM8962_CLKREG_OVD);
2906
2907 wm8962_configure_bclk(codec);
2908 } 2934 }
2909 2935
2910 /* VMID 2*250k */ 2936 /* VMID 2*250k */
@@ -2945,10 +2971,6 @@ static const struct {
2945 { 96000, 6 }, 2971 { 96000, 6 },
2946}; 2972};
2947 2973
2948static const int sysclk_rates[] = {
2949 64, 128, 192, 256, 384, 512, 768, 1024, 1408, 1536,
2950};
2951
2952static int wm8962_hw_params(struct snd_pcm_substream *substream, 2974static int wm8962_hw_params(struct snd_pcm_substream *substream,
2953 struct snd_pcm_hw_params *params, 2975 struct snd_pcm_hw_params *params,
2954 struct snd_soc_dai *dai) 2976 struct snd_soc_dai *dai)
@@ -2956,41 +2978,27 @@ static int wm8962_hw_params(struct snd_pcm_substream *substream,
2956 struct snd_soc_pcm_runtime *rtd = substream->private_data; 2978 struct snd_soc_pcm_runtime *rtd = substream->private_data;
2957 struct snd_soc_codec *codec = rtd->codec; 2979 struct snd_soc_codec *codec = rtd->codec;
2958 struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); 2980 struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);
2959 int rate = params_rate(params);
2960 int i; 2981 int i;
2961 int aif0 = 0; 2982 int aif0 = 0;
2962 int adctl3 = 0; 2983 int adctl3 = 0;
2963 int clocking4 = 0;
2964 2984
2965 wm8962->bclk = snd_soc_params_to_bclk(params); 2985 wm8962->bclk = snd_soc_params_to_bclk(params);
2966 wm8962->lrclk = params_rate(params); 2986 wm8962->lrclk = params_rate(params);
2967 2987
2968 for (i = 0; i < ARRAY_SIZE(sr_vals); i++) { 2988 for (i = 0; i < ARRAY_SIZE(sr_vals); i++) {
2969 if (sr_vals[i].rate == rate) { 2989 if (sr_vals[i].rate == wm8962->lrclk) {
2970 adctl3 |= sr_vals[i].reg; 2990 adctl3 |= sr_vals[i].reg;
2971 break; 2991 break;
2972 } 2992 }
2973 } 2993 }
2974 if (i == ARRAY_SIZE(sr_vals)) { 2994 if (i == ARRAY_SIZE(sr_vals)) {
2975 dev_err(codec->dev, "Unsupported rate %dHz\n", rate); 2995 dev_err(codec->dev, "Unsupported rate %dHz\n", wm8962->lrclk);
2976 return -EINVAL; 2996 return -EINVAL;
2977 } 2997 }
2978 2998
2979 if (rate % 8000 == 0) 2999 if (wm8962->lrclk % 8000 == 0)
2980 adctl3 |= WM8962_SAMPLE_RATE_INT_MODE; 3000 adctl3 |= WM8962_SAMPLE_RATE_INT_MODE;
2981 3001
2982 for (i = 0; i < ARRAY_SIZE(sysclk_rates); i++) {
2983 if (sysclk_rates[i] == wm8962->sysclk_rate / rate) {
2984 clocking4 |= i << WM8962_SYSCLK_RATE_SHIFT;
2985 break;
2986 }
2987 }
2988 if (i == ARRAY_SIZE(sysclk_rates)) {
2989 dev_err(codec->dev, "Unsupported sysclk ratio %d\n",
2990 wm8962->sysclk_rate / rate);
2991 return -EINVAL;
2992 }
2993
2994 switch (params_format(params)) { 3002 switch (params_format(params)) {
2995 case SNDRV_PCM_FORMAT_S16_LE: 3003 case SNDRV_PCM_FORMAT_S16_LE:
2996 break; 3004 break;
@@ -3012,8 +3020,6 @@ static int wm8962_hw_params(struct snd_pcm_substream *substream,
3012 snd_soc_update_bits(codec, WM8962_ADDITIONAL_CONTROL_3, 3020 snd_soc_update_bits(codec, WM8962_ADDITIONAL_CONTROL_3,
3013 WM8962_SAMPLE_RATE_INT_MODE | 3021 WM8962_SAMPLE_RATE_INT_MODE |
3014 WM8962_SAMPLE_RATE_MASK, adctl3); 3022 WM8962_SAMPLE_RATE_MASK, adctl3);
3015 snd_soc_update_bits(codec, WM8962_CLOCKING_4,
3016 WM8962_SYSCLK_RATE_MASK, clocking4);
3017 3023
3018 wm8962_configure_bclk(codec); 3024 wm8962_configure_bclk(codec);
3019 3025