aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc
diff options
context:
space:
mode:
authorLiam Girdwood <lg@opensource.wolfsonmicro.com>2006-10-19 14:35:56 -0400
committerJaroslav Kysela <perex@suse.cz>2007-02-09 03:01:07 -0500
commita71a468a50f1385855e28864e26251b02df829bb (patch)
tree243daee96ea5c55c88a186aa03b7917f7ad533f6 /sound/soc
parent543a0fbe18d0b44f3d037fe6b59458fa0c0d5e4b (diff)
[ALSA] ASoC: Add support for BCLK based on (Rate * Chn * Word Size)
This patch adds support for the DAI BCLK to be generated by multiplying Rate * Channels * Word Size (RCW). This now gives 3 options for BCLK clocking and synchronisation :- 1. BCLK = Rate * x 2. BCLK = MCLK / x 3. BCLK = Rate * Chn * Word Size. (New) Changes:- o Add support for RCW generation of BCLK o Update Documentation to include RCW. o Update DAI documentation for label = value DAI modes. o Add RCW support to wm8731, wm8750 and pxa2xx-i2s drivers. Signed-off-by: Liam Girdwood <lg@opensource.wolfsonmicro.com> Signed-off-by: Takashi Iwai <tiwai@suse.de> Signed-off-by: Jaroslav Kysela <perex@suse.cz>
Diffstat (limited to 'sound/soc')
-rw-r--r--sound/soc/codecs/wm8731.c33
-rw-r--r--sound/soc/codecs/wm8750.c15
-rw-r--r--sound/soc/pxa/pxa2xx-i2s.c3
-rw-r--r--sound/soc/soc-core.c215
4 files changed, 196 insertions, 70 deletions
diff --git a/sound/soc/codecs/wm8731.c b/sound/soc/codecs/wm8731.c
index 9adbd2d401c4..412291241ece 100644
--- a/sound/soc/codecs/wm8731.c
+++ b/sound/soc/codecs/wm8731.c
@@ -90,32 +90,36 @@ static struct snd_soc_dai_mode wm8731_modes[] = {
90 .pcmfmt = WM8731_HIFI_BITS, 90 .pcmfmt = WM8731_HIFI_BITS,
91 .pcmrate = SNDRV_PCM_RATE_8000, 91 .pcmrate = SNDRV_PCM_RATE_8000,
92 .pcmdir = WM8731_DIR, 92 .pcmdir = WM8731_DIR,
93 .flags = SND_SOC_DAI_BFS_RATE,
93 .fs = 1536, 94 .fs = 1536,
94 .bfs = SND_SOC_FSB(64), 95 .bfs = 64,
95 }, 96 },
96 { 97 {
97 .fmt = WM8731_DAIFMT | SND_SOC_DAIFMT_CBM_CFM, 98 .fmt = WM8731_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
98 .pcmfmt = WM8731_HIFI_BITS, 99 .pcmfmt = WM8731_HIFI_BITS,
99 .pcmrate = SNDRV_PCM_RATE_8000, 100 .pcmrate = SNDRV_PCM_RATE_8000,
100 .pcmdir = WM8731_DIR, 101 .pcmdir = WM8731_DIR,
102 .flags = SND_SOC_DAI_BFS_RATE,
101 .fs = 2304, 103 .fs = 2304,
102 .bfs = SND_SOC_FSB(64), 104 .bfs = 64,
103 }, 105 },
104 { 106 {
105 .fmt = WM8731_DAIFMT | SND_SOC_DAIFMT_CBM_CFM, 107 .fmt = WM8731_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
106 .pcmfmt = WM8731_HIFI_BITS, 108 .pcmfmt = WM8731_HIFI_BITS,
107 .pcmrate = SNDRV_PCM_RATE_8000, 109 .pcmrate = SNDRV_PCM_RATE_8000,
108 .pcmdir = WM8731_DIR, 110 .pcmdir = WM8731_DIR,
111 .flags = SND_SOC_DAI_BFS_RATE,
109 .fs = 1408, 112 .fs = 1408,
110 .bfs = SND_SOC_FSB(64), 113 .bfs = 64,
111 }, 114 },
112 { 115 {
113 .fmt = WM8731_DAIFMT | SND_SOC_DAIFMT_CBM_CFM, 116 .fmt = WM8731_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
114 .pcmfmt = WM8731_HIFI_BITS, 117 .pcmfmt = WM8731_HIFI_BITS,
115 .pcmrate = SNDRV_PCM_RATE_8000, 118 .pcmrate = SNDRV_PCM_RATE_8000,
116 .pcmdir = WM8731_DIR, 119 .pcmdir = WM8731_DIR,
120 .flags = SND_SOC_DAI_BFS_RATE,
117 .fs = 2112, 121 .fs = 2112,
118 .bfs = SND_SOC_FSB(64), 122 .bfs = 64,
119 }, 123 },
120 124
121 /* 32k */ 125 /* 32k */
@@ -124,16 +128,18 @@ static struct snd_soc_dai_mode wm8731_modes[] = {
124 .pcmfmt = WM8731_HIFI_BITS, 128 .pcmfmt = WM8731_HIFI_BITS,
125 .pcmrate = SNDRV_PCM_RATE_32000, 129 .pcmrate = SNDRV_PCM_RATE_32000,
126 .pcmdir = WM8731_DIR, 130 .pcmdir = WM8731_DIR,
131 .flags = SND_SOC_DAI_BFS_RATE,
127 .fs = 384, 132 .fs = 384,
128 .bfs = SND_SOC_FSB(64), 133 .bfs = 64,
129 }, 134 },
130 { 135 {
131 .fmt = WM8731_DAIFMT | SND_SOC_DAIFMT_CBM_CFM, 136 .fmt = WM8731_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
132 .pcmfmt = WM8731_HIFI_BITS, 137 .pcmfmt = WM8731_HIFI_BITS,
133 .pcmrate = SNDRV_PCM_RATE_32000, 138 .pcmrate = SNDRV_PCM_RATE_32000,
134 .pcmdir = WM8731_DIR, 139 .pcmdir = WM8731_DIR,
140 .flags = SND_SOC_DAI_BFS_RATE,
135 .fs = 576, 141 .fs = 576,
136 .bfs = SND_SOC_FSB(64), 142 .bfs = 64,
137 }, 143 },
138 144
139 /* 44.1k & 48k */ 145 /* 44.1k & 48k */
@@ -142,16 +148,18 @@ static struct snd_soc_dai_mode wm8731_modes[] = {
142 .pcmfmt = WM8731_HIFI_BITS, 148 .pcmfmt = WM8731_HIFI_BITS,
143 .pcmrate = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000, 149 .pcmrate = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000,
144 .pcmdir = WM8731_DIR, 150 .pcmdir = WM8731_DIR,
151 .flags = SND_SOC_DAI_BFS_RATE,
145 .fs = 256, 152 .fs = 256,
146 .bfs = SND_SOC_FSB(64), 153 .bfs = 64,
147 }, 154 },
148 { 155 {
149 .fmt = WM8731_DAIFMT | SND_SOC_DAIFMT_CBM_CFM, 156 .fmt = WM8731_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
150 .pcmfmt = WM8731_HIFI_BITS, 157 .pcmfmt = WM8731_HIFI_BITS,
151 .pcmrate = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000, 158 .pcmrate = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000,
152 .pcmdir = WM8731_DIR, 159 .pcmdir = WM8731_DIR,
160 .flags = SND_SOC_DAI_BFS_RATE,
153 .fs = 384, 161 .fs = 384,
154 .bfs = SND_SOC_FSB(64), 162 .bfs = 64,
155 }, 163 },
156 164
157 /* 88.2 & 96k */ 165 /* 88.2 & 96k */
@@ -160,17 +168,18 @@ static struct snd_soc_dai_mode wm8731_modes[] = {
160 .pcmfmt = WM8731_HIFI_BITS, 168 .pcmfmt = WM8731_HIFI_BITS,
161 .pcmrate = SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000, 169 .pcmrate = SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000,
162 .pcmdir = WM8731_DIR, 170 .pcmdir = WM8731_DIR,
171 .flags = SND_SOC_DAI_BFS_RATE,
163 .fs = 128, 172 .fs = 128,
164 .bfs = SND_SOC_FSB(64), 173 .bfs = 64,
165
166 }, 174 },
167 { 175 {
168 .fmt = WM8731_DAIFMT | SND_SOC_DAIFMT_CBM_CFM, 176 .fmt = WM8731_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
169 .pcmfmt = WM8731_HIFI_BITS, 177 .pcmfmt = WM8731_HIFI_BITS,
170 .pcmrate = SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000, 178 .pcmrate = SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000,
171 .pcmdir = WM8731_DIR, 179 .pcmdir = WM8731_DIR,
180 .flags = SND_SOC_DAI_BFS_RATE,
172 .fs = 192, 181 .fs = 192,
173 .bfs = SND_SOC_FSB(64), 182 .bfs = 64,
174 }, 183 },
175 184
176 /* USB codec frame and clock master modes */ 185 /* USB codec frame and clock master modes */
@@ -237,7 +246,7 @@ static struct snd_soc_dai_mode wm8731_modes[] = {
237 .pcmdir = WM8731_DIR, 246 .pcmdir = WM8731_DIR,
238 .flags = SND_SOC_DAI_BFS_DIV, 247 .flags = SND_SOC_DAI_BFS_DIV,
239 .fs = SND_SOC_FS_ALL, 248 .fs = SND_SOC_FS_ALL,
240 .bfs = SND_SOC_FSBD_ALL, 249 .bfs = SND_SOC_FSB_ALL,
241 }, 250 },
242}; 251};
243 252
diff --git a/sound/soc/codecs/wm8750.c b/sound/soc/codecs/wm8750.c
index 243da712d9c1..c5d13a9454d9 100644
--- a/sound/soc/codecs/wm8750.c
+++ b/sound/soc/codecs/wm8750.c
@@ -343,7 +343,7 @@ static struct snd_soc_dai_mode wm8750_modes[] = {
343 .pcmdir = WM8750_DIR, 343 .pcmdir = WM8750_DIR,
344 .flags = SND_SOC_DAI_BFS_DIV, 344 .flags = SND_SOC_DAI_BFS_DIV,
345 .fs = SND_SOC_FS_ALL, 345 .fs = SND_SOC_FS_ALL,
346 .bfs = SND_SOC_FSBD_ALL, 346 .bfs = SND_SOC_FSB_ALL,
347 }, 347 },
348}; 348};
349 349
@@ -829,6 +829,9 @@ static inline int get_coeff(int mclk, int rate)
829 if (coeff_div[i].rate == rate && coeff_div[i].mclk == mclk) 829 if (coeff_div[i].rate == rate && coeff_div[i].mclk == mclk)
830 return i; 830 return i;
831 } 831 }
832
833 printk(KERN_ERR "wm8750: could not get coeff for mclk %d @ rate %d\n",
834 mclk, rate);
832 return -EINVAL; 835 return -EINVAL;
833} 836}
834 837
@@ -836,13 +839,7 @@ static inline int get_coeff(int mclk, int rate)
836static unsigned int wm8750_config_sysclk(struct snd_soc_codec_dai *dai, 839static unsigned int wm8750_config_sysclk(struct snd_soc_codec_dai *dai,
837 struct snd_soc_clock_info *info, unsigned int clk) 840 struct snd_soc_clock_info *info, unsigned int clk)
838{ 841{
839 dai->mclk = 0; 842 dai->mclk = clk;
840
841 /* check that the calculated FS and rate actually match a clock from
842 * the machine driver */
843 if (info->fs * info->rate == clk)
844 dai->mclk = clk;
845
846 return dai->mclk; 843 return dai->mclk;
847} 844}
848 845
@@ -859,7 +856,7 @@ static int wm8750_pcm_prepare(struct snd_pcm_substream *substream)
859 if (i < 0) 856 if (i < 0)
860 return i; 857 return i;
861 858
862 bfs = SND_SOC_FSB_REAL(rtd->codec_dai->dai_runtime.bfs); 859 bfs = SND_SOC_FSBD_REAL(rtd->codec_dai->dai_runtime.bfs);
863 860
864 /* set master/slave audio interface */ 861 /* set master/slave audio interface */
865 switch (rtd->codec_dai->dai_runtime.fmt & SND_SOC_DAIFMT_CLOCK_MASK) { 862 switch (rtd->codec_dai->dai_runtime.fmt & SND_SOC_DAIFMT_CLOCK_MASK) {
diff --git a/sound/soc/pxa/pxa2xx-i2s.c b/sound/soc/pxa/pxa2xx-i2s.c
index 99f1da32744b..98b167fe68e5 100644
--- a/sound/soc/pxa/pxa2xx-i2s.c
+++ b/sound/soc/pxa/pxa2xx-i2s.c
@@ -126,7 +126,8 @@ static struct snd_soc_dai_mode pxa2xx_i2s_modes[] = {
126 .pcmrate = PXA_I2S_RATES, 126 .pcmrate = PXA_I2S_RATES,
127 .pcmdir = PXA_I2S_DIR, 127 .pcmdir = PXA_I2S_DIR,
128 .fs = SND_SOC_FS_ALL, 128 .fs = SND_SOC_FS_ALL,
129 .bfs = SND_SOC_FSB(64), 129 .flags = SND_SOC_DAI_BFS_RATE,
130 .bfs = 64,
130 .priv = 0x48, 131 .priv = 0x48,
131 }, 132 },
132}; 133};
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index 2ce0c8251dc3..6da1616bf776 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -51,6 +51,8 @@
51#define dbgc(format, arg...) 51#define dbgc(format, arg...)
52#endif 52#endif
53 53
54#define CODEC_CPU(codec, cpu) ((codec << 4) | cpu)
55
54static DEFINE_MUTEX(pcm_mutex); 56static DEFINE_MUTEX(pcm_mutex);
55static DEFINE_MUTEX(io_mutex); 57static DEFINE_MUTEX(io_mutex);
56static struct workqueue_struct *soc_workq; 58static struct workqueue_struct *soc_workq;
@@ -150,11 +152,11 @@ static unsigned inline int soc_get_mclk(struct snd_soc_pcm_runtime *rtd,
150} 152}
151 153
152/* changes a bitclk multiplier mask to a divider mask */ 154/* changes a bitclk multiplier mask to a divider mask */
153static u16 soc_bfs_mult_to_div(u16 bfs, int rate, unsigned int mclk, 155static u64 soc_bfs_rcw_to_div(u64 bfs, int rate, unsigned int mclk,
154 unsigned int pcmfmt, unsigned int chn) 156 unsigned int pcmfmt, unsigned int chn)
155{ 157{
156 int i, j; 158 int i, j;
157 u16 bfs_ = 0; 159 u64 bfs_ = 0;
158 int size = snd_pcm_format_physical_width(pcmfmt), min = 0; 160 int size = snd_pcm_format_physical_width(pcmfmt), min = 0;
159 161
160 if (size <= 0) 162 if (size <= 0)
@@ -162,17 +164,14 @@ static u16 soc_bfs_mult_to_div(u16 bfs, int rate, unsigned int mclk,
162 164
163 /* the minimum bit clock that has enough bandwidth */ 165 /* the minimum bit clock that has enough bandwidth */
164 min = size * rate * chn; 166 min = size * rate * chn;
165 dbgc("mult --> div min bclk %d with mclk %d\n", min, mclk); 167 dbgc("rcw --> div min bclk %d with mclk %d\n", min, mclk);
166 168
167 for (i = 0; i < 16; i++) { 169 for (i = 0; i < 64; i++) {
168 if ((bfs >> i) & 0x1) { 170 if ((bfs >> i) & 0x1) {
169 j = rate * SND_SOC_FSB_REAL(1<<i); 171 j = min * (i + 1);
170 172 bfs_ |= SND_SOC_FSBD(mclk/j);
171 if (j >= min) { 173 dbgc("rcw --> div support mult %d\n",
172 bfs_ |= SND_SOC_FSBD(mclk/j); 174 SND_SOC_FSBD_REAL(1<<i));
173 dbgc("mult --> div support mult %d\n",
174 SND_SOC_FSB_REAL(1<<i));
175 }
176 } 175 }
177 } 176 }
178 177
@@ -180,11 +179,11 @@ static u16 soc_bfs_mult_to_div(u16 bfs, int rate, unsigned int mclk,
180} 179}
181 180
182/* changes a bitclk divider mask to a multiplier mask */ 181/* changes a bitclk divider mask to a multiplier mask */
183static u16 soc_bfs_div_to_mult(u16 bfs, int rate, unsigned int mclk, 182static u64 soc_bfs_div_to_rcw(u64 bfs, int rate, unsigned int mclk,
184 unsigned int pcmfmt, unsigned int chn) 183 unsigned int pcmfmt, unsigned int chn)
185{ 184{
186 int i, j; 185 int i, j;
187 u16 bfs_ = 0; 186 u64 bfs_ = 0;
188 187
189 int size = snd_pcm_format_physical_width(pcmfmt), min = 0; 188 int size = snd_pcm_format_physical_width(pcmfmt), min = 0;
190 189
@@ -193,15 +192,15 @@ static u16 soc_bfs_div_to_mult(u16 bfs, int rate, unsigned int mclk,
193 192
194 /* the minimum bit clock that has enough bandwidth */ 193 /* the minimum bit clock that has enough bandwidth */
195 min = size * rate * chn; 194 min = size * rate * chn;
196 dbgc("div to mult min bclk %d with mclk %d\n", min, mclk); 195 dbgc("div to rcw min bclk %d with mclk %d\n", min, mclk);
197 196
198 for (i = 0; i < 16; i++) { 197 for (i = 0; i < 64; i++) {
199 if ((bfs >> i) & 0x1) { 198 if ((bfs >> i) & 0x1) {
200 j = mclk / (SND_SOC_FSBD_REAL(1<<i)); 199 j = mclk / (i + 1);
201 if (j >= min) { 200 if (j >= min) {
202 bfs_ |= SND_SOC_FSB(j/rate); 201 bfs_ |= SND_SOC_FSBW(j/min);
203 dbgc("div --> mult support div %d\n", 202 dbgc("div --> rcw support div %d\n",
204 SND_SOC_FSBD_REAL(1<<i)); 203 SND_SOC_FSBW_REAL(1<<i));
205 } 204 }
206 } 205 }
207 } 206 }
@@ -209,6 +208,52 @@ static u16 soc_bfs_div_to_mult(u16 bfs, int rate, unsigned int mclk,
209 return bfs_; 208 return bfs_;
210} 209}
211 210
211/* changes a constant bitclk to a multiplier mask */
212static u64 soc_bfs_rate_to_rcw(u64 bfs, int rate, unsigned int mclk,
213 unsigned int pcmfmt, unsigned int chn)
214{
215 unsigned int bfs_ = rate * bfs;
216 int size = snd_pcm_format_physical_width(pcmfmt), min = 0;
217
218 if (size <= 0)
219 return 0;
220
221 /* the minimum bit clock that has enough bandwidth */
222 min = size * rate * chn;
223 dbgc("rate --> rcw min bclk %d with mclk %d\n", min, mclk);
224
225 if (bfs_ < min)
226 return 0;
227 else {
228 bfs_ = SND_SOC_FSBW(bfs_/min);
229 dbgc("rate --> rcw support div %d\n", SND_SOC_FSBW_REAL(bfs_));
230 return bfs_;
231 }
232}
233
234/* changes a bitclk multiplier mask to a divider mask */
235static u64 soc_bfs_rate_to_div(u64 bfs, int rate, unsigned int mclk,
236 unsigned int pcmfmt, unsigned int chn)
237{
238 unsigned int bfs_ = rate * bfs;
239 int size = snd_pcm_format_physical_width(pcmfmt), min = 0;
240
241 if (size <= 0)
242 return 0;
243
244 /* the minimum bit clock that has enough bandwidth */
245 min = size * rate * chn;
246 dbgc("rate --> div min bclk %d with mclk %d\n", min, mclk);
247
248 if (bfs_ < min)
249 return 0;
250 else {
251 bfs_ = SND_SOC_FSBW(mclk/bfs_);
252 dbgc("rate --> div support div %d\n", SND_SOC_FSBD_REAL(bfs_));
253 return bfs_;
254 }
255}
256
212/* Matches codec DAI and SoC CPU DAI hardware parameters */ 257/* Matches codec DAI and SoC CPU DAI hardware parameters */
213static int soc_hw_match_params(struct snd_pcm_substream *substream, 258static int soc_hw_match_params(struct snd_pcm_substream *substream,
214 struct snd_pcm_hw_params *params) 259 struct snd_pcm_hw_params *params)
@@ -217,9 +262,10 @@ static int soc_hw_match_params(struct snd_pcm_substream *substream,
217 struct snd_soc_dai_mode *codec_dai_mode = NULL; 262 struct snd_soc_dai_mode *codec_dai_mode = NULL;
218 struct snd_soc_dai_mode *cpu_dai_mode = NULL; 263 struct snd_soc_dai_mode *cpu_dai_mode = NULL;
219 struct snd_soc_clock_info clk_info; 264 struct snd_soc_clock_info clk_info;
220 unsigned int fs, mclk, codec_bfs, cpu_bfs, rate = params_rate(params), 265 unsigned int fs, mclk, rate = params_rate(params),
221 chn, j, k, cpu_bclk, codec_bclk, pcmrate; 266 chn, j, k, cpu_bclk, codec_bclk, pcmrate;
222 u16 fmt = 0; 267 u16 fmt = 0;
268 u64 codec_bfs, cpu_bfs;
223 269
224 dbg("asoc: match version %s\n", SND_SOC_VERSION); 270 dbg("asoc: match version %s\n", SND_SOC_VERSION);
225 clk_info.rate = rate; 271 clk_info.rate = rate;
@@ -309,44 +355,98 @@ static int soc_hw_match_params(struct snd_pcm_substream *substream,
309 * used in the codec and cpu DAI modes. We always choose the 355 * used in the codec and cpu DAI modes. We always choose the
310 * lowest possible clocks to reduce power. 356 * lowest possible clocks to reduce power.
311 */ 357 */
312 if (codec_dai_mode->flags & cpu_dai_mode->flags & 358 switch (CODEC_CPU(codec_dai_mode->flags, cpu_dai_mode->flags)) {
313 SND_SOC_DAI_BFS_DIV) { 359 case CODEC_CPU(SND_SOC_DAI_BFS_DIV, SND_SOC_DAI_BFS_DIV):
314 /* cpu & codec bfs dividers */ 360 /* cpu & codec bfs dividers */
315 rtd->cpu_dai->dai_runtime.bfs = 361 rtd->cpu_dai->dai_runtime.bfs =
316 rtd->codec_dai->dai_runtime.bfs = 362 rtd->codec_dai->dai_runtime.bfs =
317 1 << (fls(codec_dai_mode->bfs & cpu_dai_mode->bfs) - 1); 363 1 << (fls(codec_dai_mode->bfs & cpu_dai_mode->bfs) - 1);
318 } else if (codec_dai_mode->flags & SND_SOC_DAI_BFS_DIV) { 364 break;
319 /* normalise bfs codec divider & cpu mult */ 365 case CODEC_CPU(SND_SOC_DAI_BFS_DIV, SND_SOC_DAI_BFS_RCW):
320 codec_bfs = soc_bfs_div_to_mult(codec_dai_mode->bfs, rate, 366 /* normalise bfs codec divider & cpu rcw mult */
367 codec_bfs = soc_bfs_div_to_rcw(codec_dai_mode->bfs, rate,
321 mclk, rtd->codec_dai->dai_runtime.pcmfmt, chn); 368 mclk, rtd->codec_dai->dai_runtime.pcmfmt, chn);
322 rtd->cpu_dai->dai_runtime.bfs = 369 rtd->cpu_dai->dai_runtime.bfs =
323 1 << (ffs(codec_bfs & cpu_dai_mode->bfs) - 1); 370 1 << (ffs(codec_bfs & cpu_dai_mode->bfs) - 1);
324 cpu_bfs = soc_bfs_mult_to_div(cpu_dai_mode->bfs, rate, mclk, 371 cpu_bfs = soc_bfs_rcw_to_div(cpu_dai_mode->bfs, rate, mclk,
325 rtd->codec_dai->dai_runtime.pcmfmt, chn); 372 rtd->codec_dai->dai_runtime.pcmfmt, chn);
326 rtd->codec_dai->dai_runtime.bfs = 373 rtd->codec_dai->dai_runtime.bfs =
327 1 << (fls(codec_dai_mode->bfs & cpu_bfs) - 1); 374 1 << (fls(codec_dai_mode->bfs & cpu_bfs) - 1);
328 } else if (cpu_dai_mode->flags & SND_SOC_DAI_BFS_DIV) { 375 break;
329 /* normalise bfs codec mult & cpu divider */ 376 case CODEC_CPU(SND_SOC_DAI_BFS_RCW, SND_SOC_DAI_BFS_DIV):
330 codec_bfs = soc_bfs_mult_to_div(codec_dai_mode->bfs, rate, 377 /* normalise bfs codec rcw mult & cpu divider */
378 codec_bfs = soc_bfs_rcw_to_div(codec_dai_mode->bfs, rate,
331 mclk, rtd->codec_dai->dai_runtime.pcmfmt, chn); 379 mclk, rtd->codec_dai->dai_runtime.pcmfmt, chn);
332 rtd->cpu_dai->dai_runtime.bfs = 380 rtd->cpu_dai->dai_runtime.bfs =
333 1 << (fls(codec_bfs & cpu_dai_mode->bfs) -1); 381 1 << (fls(codec_bfs & cpu_dai_mode->bfs) -1);
334 cpu_bfs = soc_bfs_div_to_mult(cpu_dai_mode->bfs, rate, mclk, 382 cpu_bfs = soc_bfs_div_to_rcw(cpu_dai_mode->bfs, rate, mclk,
335 rtd->codec_dai->dai_runtime.pcmfmt, chn); 383 rtd->codec_dai->dai_runtime.pcmfmt, chn);
336 rtd->codec_dai->dai_runtime.bfs = 384 rtd->codec_dai->dai_runtime.bfs =
337 1 << (ffs(codec_dai_mode->bfs & cpu_bfs) -1); 385 1 << (ffs(codec_dai_mode->bfs & cpu_bfs) -1);
338 } else { 386 break;
339 /* codec & cpu bfs rate multipliers */ 387 case CODEC_CPU(SND_SOC_DAI_BFS_RCW, SND_SOC_DAI_BFS_RCW):
388 /* codec & cpu bfs rate rcw multipliers */
340 rtd->cpu_dai->dai_runtime.bfs = 389 rtd->cpu_dai->dai_runtime.bfs =
341 rtd->codec_dai->dai_runtime.bfs = 390 rtd->codec_dai->dai_runtime.bfs =
342 1 << (ffs(codec_dai_mode->bfs & cpu_dai_mode->bfs) -1); 391 1 << (ffs(codec_dai_mode->bfs & cpu_dai_mode->bfs) -1);
392 break;
393 case CODEC_CPU(SND_SOC_DAI_BFS_DIV, SND_SOC_DAI_BFS_RATE):
394 /* normalise cpu bfs rate const multiplier & codec div */
395 cpu_bfs = soc_bfs_rate_to_div(cpu_dai_mode->bfs, rate,
396 mclk, rtd->codec_dai->dai_runtime.pcmfmt, chn);
397 if(codec_dai_mode->bfs & cpu_bfs) {
398 rtd->codec_dai->dai_runtime.bfs = cpu_bfs;
399 rtd->cpu_dai->dai_runtime.bfs = cpu_dai_mode->bfs;
400 } else
401 rtd->cpu_dai->dai_runtime.bfs = 0;
402 break;
403 case CODEC_CPU(SND_SOC_DAI_BFS_RCW, SND_SOC_DAI_BFS_RATE):
404 /* normalise cpu bfs rate const multiplier & codec rcw mult */
405 cpu_bfs = soc_bfs_rate_to_rcw(cpu_dai_mode->bfs, rate,
406 mclk, rtd->codec_dai->dai_runtime.pcmfmt, chn);
407 if(codec_dai_mode->bfs & cpu_bfs) {
408 rtd->codec_dai->dai_runtime.bfs = cpu_bfs;
409 rtd->cpu_dai->dai_runtime.bfs = cpu_dai_mode->bfs;
410 } else
411 rtd->cpu_dai->dai_runtime.bfs = 0;
412 break;
413 case CODEC_CPU(SND_SOC_DAI_BFS_RATE, SND_SOC_DAI_BFS_RCW):
414 /* normalise cpu bfs rate rcw multiplier & codec const mult */
415 codec_bfs = soc_bfs_rate_to_rcw(codec_dai_mode->bfs, rate,
416 mclk, rtd->codec_dai->dai_runtime.pcmfmt, chn);
417 if(cpu_dai_mode->bfs & codec_bfs) {
418 rtd->cpu_dai->dai_runtime.bfs = codec_bfs;
419 rtd->codec_dai->dai_runtime.bfs = codec_dai_mode->bfs;
420 } else
421 rtd->cpu_dai->dai_runtime.bfs = 0;
422 break;
423 case CODEC_CPU(SND_SOC_DAI_BFS_RATE, SND_SOC_DAI_BFS_DIV):
424 /* normalise cpu bfs div & codec const mult */
425 codec_bfs = soc_bfs_rate_to_div(codec_dai_mode->bfs, rate,
426 mclk, rtd->codec_dai->dai_runtime.pcmfmt, chn);
427 if(codec_dai_mode->bfs & codec_bfs) {
428 rtd->cpu_dai->dai_runtime.bfs = codec_bfs;
429 rtd->codec_dai->dai_runtime.bfs = codec_dai_mode->bfs;
430 } else
431 rtd->cpu_dai->dai_runtime.bfs = 0;
432 break;
433 case CODEC_CPU(SND_SOC_DAI_BFS_RATE, SND_SOC_DAI_BFS_RATE):
434 /* cpu & codec constant mult */
435 if(codec_dai_mode->bfs == cpu_dai_mode->bfs)
436 rtd->cpu_dai->dai_runtime.bfs =
437 rtd->codec_dai->dai_runtime.bfs =
438 codec_dai_mode->bfs;
439 else
440 rtd->cpu_dai->dai_runtime.bfs =
441 rtd->codec_dai->dai_runtime.bfs = 0;
442 break;
343 } 443 }
344 444
345 /* make sure the bit clock speed is acceptable */ 445 /* make sure the bit clock speed is acceptable */
346 if (!rtd->cpu_dai->dai_runtime.bfs || 446 if (!rtd->cpu_dai->dai_runtime.bfs ||
347 !rtd->codec_dai->dai_runtime.bfs) { 447 !rtd->codec_dai->dai_runtime.bfs) {
348 dbgc("asoc: DAI[%d:%d] failed to match BFS\n", j, k); 448 dbgc("asoc: DAI[%d:%d] failed to match BFS\n", j, k);
349 dbgc("asoc: cpu_dai %x codec %x\n", 449 dbgc("asoc: cpu_dai %llu codec %llu\n",
350 rtd->cpu_dai->dai_runtime.bfs, 450 rtd->cpu_dai->dai_runtime.bfs,
351 rtd->codec_dai->dai_runtime.bfs); 451 rtd->codec_dai->dai_runtime.bfs);
352 dbgc("asoc: mclk %d hwfmt %x\n", mclk, fmt); 452 dbgc("asoc: mclk %d hwfmt %x\n", mclk, fmt);
@@ -378,26 +478,41 @@ found:
378 dbg("asoc: codec fs %d mclk %d bfs div %d bclk %d\n", 478 dbg("asoc: codec fs %d mclk %d bfs div %d bclk %d\n",
379 rtd->codec_dai->dai_runtime.fs, mclk, 479 rtd->codec_dai->dai_runtime.fs, mclk,
380 SND_SOC_FSBD_REAL(rtd->codec_dai->dai_runtime.bfs), codec_bclk); 480 SND_SOC_FSBD_REAL(rtd->codec_dai->dai_runtime.bfs), codec_bclk);
381 } else { 481 } else if(rtd->codec_dai->dai_runtime.flags == SND_SOC_DAI_BFS_RATE) {
382 codec_bclk = params_rate(params) * 482 codec_bclk = params_rate(params) * rtd->codec_dai->dai_runtime.bfs;
383 SND_SOC_FSB_REAL(rtd->codec_dai->dai_runtime.bfs); 483 dbg("asoc: codec fs %d mclk %d bfs rate mult %llu bclk %d\n",
384 dbg("asoc: codec fs %d mclk %d bfs mult %d bclk %d\n",
385 rtd->codec_dai->dai_runtime.fs, mclk, 484 rtd->codec_dai->dai_runtime.fs, mclk,
386 SND_SOC_FSB_REAL(rtd->codec_dai->dai_runtime.bfs), codec_bclk); 485 rtd->codec_dai->dai_runtime.bfs, codec_bclk);
387 } 486 } else if (rtd->cpu_dai->dai_runtime.flags == SND_SOC_DAI_BFS_RCW) {
487 codec_bclk = params_rate(params) * params_channels(params) *
488 snd_pcm_format_physical_width(rtd->codec_dai->dai_runtime.pcmfmt) *
489 SND_SOC_FSBW_REAL(rtd->codec_dai->dai_runtime.bfs);
490 dbg("asoc: codec fs %d mclk %d bfs rcw mult %d bclk %d\n",
491 rtd->codec_dai->dai_runtime.fs, mclk,
492 SND_SOC_FSBW_REAL(rtd->codec_dai->dai_runtime.bfs), codec_bclk);
493 } else
494 codec_bclk = 0;
495
388 if (rtd->cpu_dai->dai_runtime.flags == SND_SOC_DAI_BFS_DIV) { 496 if (rtd->cpu_dai->dai_runtime.flags == SND_SOC_DAI_BFS_DIV) {
389 cpu_bclk = (rtd->cpu_dai->dai_runtime.fs * params_rate(params)) / 497 cpu_bclk = (rtd->cpu_dai->dai_runtime.fs * params_rate(params)) /
390 SND_SOC_FSBD_REAL(rtd->cpu_dai->dai_runtime.bfs); 498 SND_SOC_FSBD_REAL(rtd->cpu_dai->dai_runtime.bfs);
391 dbg("asoc: cpu fs %d mclk %d bfs div %d bclk %d\n", 499 dbg("asoc: cpu fs %d mclk %d bfs div %d bclk %d\n",
392 rtd->cpu_dai->dai_runtime.fs, mclk, 500 rtd->cpu_dai->dai_runtime.fs, mclk,
393 SND_SOC_FSBD_REAL(rtd->cpu_dai->dai_runtime.bfs), cpu_bclk); 501 SND_SOC_FSBD_REAL(rtd->cpu_dai->dai_runtime.bfs), cpu_bclk);
394 } else { 502 } else if (rtd->cpu_dai->dai_runtime.flags == SND_SOC_DAI_BFS_RATE) {
395 cpu_bclk = params_rate(params) * 503 cpu_bclk = params_rate(params) * rtd->cpu_dai->dai_runtime.bfs;
396 SND_SOC_FSB_REAL(rtd->cpu_dai->dai_runtime.bfs); 504 dbg("asoc: cpu fs %d mclk %d bfs rate mult %llu bclk %d\n",
397 dbg("asoc: cpu fs %d mclk %d bfs mult %d bclk %d\n",
398 rtd->cpu_dai->dai_runtime.fs, mclk, 505 rtd->cpu_dai->dai_runtime.fs, mclk,
399 SND_SOC_FSB_REAL(rtd->cpu_dai->dai_runtime.bfs), cpu_bclk); 506 rtd->cpu_dai->dai_runtime.bfs, cpu_bclk);
400 } 507 } else if (rtd->cpu_dai->dai_runtime.flags == SND_SOC_DAI_BFS_RCW) {
508 cpu_bclk = params_rate(params) * params_channels(params) *
509 snd_pcm_format_physical_width(rtd->cpu_dai->dai_runtime.pcmfmt) *
510 SND_SOC_FSBW_REAL(rtd->cpu_dai->dai_runtime.bfs);
511 dbg("asoc: cpu fs %d mclk %d bfs mult rcw %d bclk %d\n",
512 rtd->cpu_dai->dai_runtime.fs, mclk,
513 SND_SOC_FSBW_REAL(rtd->cpu_dai->dai_runtime.bfs), cpu_bclk);
514 } else
515 cpu_bclk = 0;
401 516
402 /* 517 /*
403 * Check we have matching bitclocks. If we don't then it means the 518 * Check we have matching bitclocks. If we don't then it means the
@@ -405,7 +520,7 @@ found:
405 * machine sysclock function) is wrong compared with the supported DAI 520 * machine sysclock function) is wrong compared with the supported DAI
406 * modes for the codec or cpu DAI. 521 * modes for the codec or cpu DAI.
407 */ 522 */
408 if (cpu_bclk != codec_bclk){ 523 if (cpu_bclk != codec_bclk && cpu_bclk){
409 printk(KERN_ERR 524 printk(KERN_ERR
410 "asoc: codec and cpu bitclocks differ, audio may be wrong speed\n" 525 "asoc: codec and cpu bitclocks differ, audio may be wrong speed\n"
411 ); 526 );
@@ -723,14 +838,18 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream)
723 mutex_lock(&pcm_mutex); 838 mutex_lock(&pcm_mutex);
724 if (platform->pcm_ops->prepare) { 839 if (platform->pcm_ops->prepare) {
725 ret = platform->pcm_ops->prepare(substream); 840 ret = platform->pcm_ops->prepare(substream);
726 if (ret < 0) 841 if (ret < 0) {
842 printk(KERN_ERR "asoc: platform prepare error\n");
727 goto out; 843 goto out;
844 }
728 } 845 }
729 846
730 if (rtd->codec_dai->ops.prepare) { 847 if (rtd->codec_dai->ops.prepare) {
731 ret = rtd->codec_dai->ops.prepare(substream); 848 ret = rtd->codec_dai->ops.prepare(substream);
732 if (ret < 0) 849 if (ret < 0) {
850 printk(KERN_ERR "asoc: codec DAI prepare error\n");
733 goto out; 851 goto out;
852 }
734 } 853 }
735 854
736 if (rtd->cpu_dai->ops.prepare) 855 if (rtd->cpu_dai->ops.prepare)