summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Brown <broonie@opensource.wolfsonmicro.com>2009-08-11 16:28:39 +0100
committerMark Brown <broonie@opensource.wolfsonmicro.com>2009-08-11 16:29:21 +0100
commite0026beac0f1a6253488478b3f022ff243b012b9 (patch)
treea4d9eb2eb02ea90cdfe5e0074545c0887e3c4e4e
parent1921bab217c2c21e4b8dc78332f6ae11515fc014 (diff)
downloadlinux-3.10-e0026beac0f1a6253488478b3f022ff243b012b9.tar.gz
linux-3.10-e0026beac0f1a6253488478b3f022ff243b012b9.tar.bz2
linux-3.10-e0026beac0f1a6253488478b3f022ff243b012b9.zip
ASoC: Update WM9081 for tdm_slot() API change
Store the TDM slot width then if it's set use that rather than the sample size to calculate BCLK. Leave imposing constraints to the core (which should do this but doesn't yet) or machine driver. Also allow 0 TDM slots to be configure (for use when disabling TDM). Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
-rw-r--r--sound/soc/codecs/wm9081.c60
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 {
int master;
int fll_fref;
int fll_fout;
+ int tdm_width;
struct wm9081_retune_mobile_config *retune;
};
@@ -981,33 +982,37 @@ static int wm9081_hw_params(struct snd_pcm_substream *substream,
aif4 = snd_soc_read(codec, WM9081_AUDIO_INTERFACE_4);
aif4 &= ~WM9081_LRCLK_RATE_MASK;
- /* What BCLK do we need? */
wm9081->fs = params_rate(params);
- wm9081->bclk = 2 * wm9081->fs;
- switch (params_format(params)) {
- case SNDRV_PCM_FORMAT_S16_LE:
- wm9081->bclk *= 16;
- break;
- case SNDRV_PCM_FORMAT_S20_3LE:
- wm9081->bclk *= 20;
- aif2 |= 0x4;
- break;
- case SNDRV_PCM_FORMAT_S24_LE:
- wm9081->bclk *= 24;
- aif2 |= 0x8;
- break;
- case SNDRV_PCM_FORMAT_S32_LE:
- wm9081->bclk *= 32;
- aif2 |= 0xc;
- break;
- default:
- return -EINVAL;
- }
- if (aif1 & WM9081_AIFDAC_TDM_MODE_MASK) {
+ if (wm9081->tdm_width) {
+ /* If TDM is set up then that fixes our BCLK. */
int slots = ((aif1 & WM9081_AIFDAC_TDM_MODE_MASK) >>
WM9081_AIFDAC_TDM_MODE_SHIFT) + 1;
- wm9081->bclk *= slots;
+
+ wm9081->bclk = wm9081->fs * wm9081->tdm_width * slots;
+ } else {
+ /* Otherwise work out a BCLK from the sample size */
+ wm9081->bclk = 2 * wm9081->fs;
+
+ switch (params_format(params)) {
+ case SNDRV_PCM_FORMAT_S16_LE:
+ wm9081->bclk *= 16;
+ break;
+ case SNDRV_PCM_FORMAT_S20_3LE:
+ wm9081->bclk *= 20;
+ aif2 |= 0x4;
+ break;
+ case SNDRV_PCM_FORMAT_S24_LE:
+ wm9081->bclk *= 24;
+ aif2 |= 0x8;
+ break;
+ case SNDRV_PCM_FORMAT_S32_LE:
+ wm9081->bclk *= 32;
+ aif2 |= 0xc;
+ break;
+ default:
+ return -EINVAL;
+ }
}
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,
return 0;
}
-/* FIXME: Needs to handle slot_width */
static int wm9081_set_tdm_slot(struct snd_soc_dai *dai,
unsigned int tx_mask, unsigned int rx_mask, int slots, int slot_width)
{
struct snd_soc_codec *codec = dai->codec;
+ struct wm9081_priv *wm9081 = codec->private_data;
unsigned int aif1 = snd_soc_read(codec, WM9081_AUDIO_INTERFACE_1);
aif1 &= ~(WM9081_AIFDAC_TDM_SLOT_MASK | WM9081_AIFDAC_TDM_MODE_MASK);
- if (slots < 1 || slots > 4)
+ if (slots < 0 || slots > 4)
return -EINVAL;
+ wm9081->tdm_width = slot_width;
+
+ if (slots == 0)
+ slots = 1;
+
aif1 |= (slots - 1) << WM9081_AIFDAC_TDM_MODE_SHIFT;
switch (rx_mask) {