diff options
Diffstat (limited to 'sound/soc/codecs')
-rw-r--r-- | sound/soc/codecs/wm9081.c | 60 |
1 files changed, 35 insertions, 25 deletions
diff --git a/sound/soc/codecs/wm9081.c b/sound/soc/codecs/wm9081.c index c147f2b8723..c64e55aa63b 100644 --- a/sound/soc/codecs/wm9081.c +++ b/sound/soc/codecs/wm9081.c | |||
@@ -165,6 +165,7 @@ struct wm9081_priv { | |||
165 | int master; | 165 | int master; |
166 | int fll_fref; | 166 | int fll_fref; |
167 | int fll_fout; | 167 | int fll_fout; |
168 | int tdm_width; | ||
168 | struct wm9081_retune_mobile_config *retune; | 169 | struct wm9081_retune_mobile_config *retune; |
169 | }; | 170 | }; |
170 | 171 | ||
@@ -981,33 +982,37 @@ static int wm9081_hw_params(struct snd_pcm_substream *substream, | |||
981 | aif4 = snd_soc_read(codec, WM9081_AUDIO_INTERFACE_4); | 982 | aif4 = snd_soc_read(codec, WM9081_AUDIO_INTERFACE_4); |
982 | aif4 &= ~WM9081_LRCLK_RATE_MASK; | 983 | aif4 &= ~WM9081_LRCLK_RATE_MASK; |
983 | 984 | ||
984 | /* What BCLK do we need? */ | ||
985 | wm9081->fs = params_rate(params); | 985 | wm9081->fs = params_rate(params); |
986 | wm9081->bclk = 2 * wm9081->fs; | ||
987 | switch (params_format(params)) { | ||
988 | case SNDRV_PCM_FORMAT_S16_LE: | ||
989 | wm9081->bclk *= 16; | ||
990 | break; | ||
991 | case SNDRV_PCM_FORMAT_S20_3LE: | ||
992 | wm9081->bclk *= 20; | ||
993 | aif2 |= 0x4; | ||
994 | break; | ||
995 | case SNDRV_PCM_FORMAT_S24_LE: | ||
996 | wm9081->bclk *= 24; | ||
997 | aif2 |= 0x8; | ||
998 | break; | ||
999 | case SNDRV_PCM_FORMAT_S32_LE: | ||
1000 | wm9081->bclk *= 32; | ||
1001 | aif2 |= 0xc; | ||
1002 | break; | ||
1003 | default: | ||
1004 | return -EINVAL; | ||
1005 | } | ||
1006 | 986 | ||
1007 | if (aif1 & WM9081_AIFDAC_TDM_MODE_MASK) { | 987 | if (wm9081->tdm_width) { |
988 | /* If TDM is set up then that fixes our BCLK. */ | ||
1008 | int slots = ((aif1 & WM9081_AIFDAC_TDM_MODE_MASK) >> | 989 | int slots = ((aif1 & WM9081_AIFDAC_TDM_MODE_MASK) >> |
1009 | WM9081_AIFDAC_TDM_MODE_SHIFT) + 1; | 990 | WM9081_AIFDAC_TDM_MODE_SHIFT) + 1; |
1010 | wm9081->bclk *= slots; | 991 | |
992 | wm9081->bclk = wm9081->fs * wm9081->tdm_width * slots; | ||
993 | } else { | ||
994 | /* Otherwise work out a BCLK from the sample size */ | ||
995 | wm9081->bclk = 2 * wm9081->fs; | ||
996 | |||
997 | switch (params_format(params)) { | ||
998 | case SNDRV_PCM_FORMAT_S16_LE: | ||
999 | wm9081->bclk *= 16; | ||
1000 | break; | ||
1001 | case SNDRV_PCM_FORMAT_S20_3LE: | ||
1002 | wm9081->bclk *= 20; | ||
1003 | aif2 |= 0x4; | ||
1004 | break; | ||
1005 | case SNDRV_PCM_FORMAT_S24_LE: | ||
1006 | wm9081->bclk *= 24; | ||
1007 | aif2 |= 0x8; | ||
1008 | break; | ||
1009 | case SNDRV_PCM_FORMAT_S32_LE: | ||
1010 | wm9081->bclk *= 32; | ||
1011 | aif2 |= 0xc; | ||
1012 | break; | ||
1013 | default: | ||
1014 | return -EINVAL; | ||
1015 | } | ||
1011 | } | 1016 | } |
1012 | 1017 | ||
1013 | dev_dbg(codec->dev, "Target BCLK is %dHz\n", wm9081->bclk); | 1018 | dev_dbg(codec->dev, "Target BCLK is %dHz\n", wm9081->bclk); |
@@ -1149,18 +1154,23 @@ static int wm9081_set_sysclk(struct snd_soc_dai *codec_dai, | |||
1149 | return 0; | 1154 | return 0; |
1150 | } | 1155 | } |
1151 | 1156 | ||
1152 | /* FIXME: Needs to handle slot_width */ | ||
1153 | static int wm9081_set_tdm_slot(struct snd_soc_dai *dai, | 1157 | static int wm9081_set_tdm_slot(struct snd_soc_dai *dai, |
1154 | unsigned int tx_mask, unsigned int rx_mask, int slots, int slot_width) | 1158 | unsigned int tx_mask, unsigned int rx_mask, int slots, int slot_width) |
1155 | { | 1159 | { |
1156 | struct snd_soc_codec *codec = dai->codec; | 1160 | struct snd_soc_codec *codec = dai->codec; |
1161 | struct wm9081_priv *wm9081 = codec->private_data; | ||
1157 | unsigned int aif1 = snd_soc_read(codec, WM9081_AUDIO_INTERFACE_1); | 1162 | unsigned int aif1 = snd_soc_read(codec, WM9081_AUDIO_INTERFACE_1); |
1158 | 1163 | ||
1159 | aif1 &= ~(WM9081_AIFDAC_TDM_SLOT_MASK | WM9081_AIFDAC_TDM_MODE_MASK); | 1164 | aif1 &= ~(WM9081_AIFDAC_TDM_SLOT_MASK | WM9081_AIFDAC_TDM_MODE_MASK); |
1160 | 1165 | ||
1161 | if (slots < 1 || slots > 4) | 1166 | if (slots < 0 || slots > 4) |
1162 | return -EINVAL; | 1167 | return -EINVAL; |
1163 | 1168 | ||
1169 | wm9081->tdm_width = slot_width; | ||
1170 | |||
1171 | if (slots == 0) | ||
1172 | slots = 1; | ||
1173 | |||
1164 | aif1 |= (slots - 1) << WM9081_AIFDAC_TDM_MODE_SHIFT; | 1174 | aif1 |= (slots - 1) << WM9081_AIFDAC_TDM_MODE_SHIFT; |
1165 | 1175 | ||
1166 | switch (rx_mask) { | 1176 | switch (rx_mask) { |