aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/codecs/cs4271.c
diff options
context:
space:
mode:
authorAlexander Sverdlin <subaparts@yandex.ru>2011-03-07 12:29:45 -0500
committerMark Brown <broonie@opensource.wolfsonmicro.com>2011-03-09 08:08:16 -0500
commit5c3a12e96c9f3158602b2feac8583ae35c10b80e (patch)
treebb7ef9f5cd61d8f97a636bb668f772c9ce1f19a4 /sound/soc/codecs/cs4271.c
parent15086ded21ee7f065ad290c1edfdc49cf18cf96e (diff)
ASoC: Manage mode and rate bits correctly for CS4271 CODEC.
Manage mode and rate bits correctly, according to datasheet in CS4271 CODEC. This is done to make capture work properly. Signed-off-by: Alexander Sverdlin <subaparts@yandex.ru> Acked-by: Liam Girdwood <lrg@ti.com> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'sound/soc/codecs/cs4271.c')
-rw-r--r--sound/soc/codecs/cs4271.c83
1 files changed, 53 insertions, 30 deletions
diff --git a/sound/soc/codecs/cs4271.c b/sound/soc/codecs/cs4271.c
index 538e814136d3..083aab96ca80 100644
--- a/sound/soc/codecs/cs4271.c
+++ b/sound/soc/codecs/cs4271.c
@@ -168,27 +168,6 @@ struct cs4271_private {
168 int gpio_disable; 168 int gpio_disable;
169}; 169};
170 170
171struct cs4271_clk_cfg {
172 unsigned int ratio; /* MCLK / sample rate */
173 u8 speed_mode; /* codec speed mode: 1x, 2x, 4x */
174 u8 mclk_master; /* ratio bit mask for Master mode */
175 u8 mclk_slave; /* ratio bit mask for Slave mode */
176};
177
178static struct cs4271_clk_cfg cs4271_clk_tab[] = {
179 {64, CS4271_MODE1_MODE_4X, CS4271_MODE1_DIV_1, CS4271_MODE1_DIV_1},
180 {96, CS4271_MODE1_MODE_4X, CS4271_MODE1_DIV_15, CS4271_MODE1_DIV_1},
181 {128, CS4271_MODE1_MODE_2X, CS4271_MODE1_DIV_1, CS4271_MODE1_DIV_1},
182 {192, CS4271_MODE1_MODE_2X, CS4271_MODE1_DIV_15, CS4271_MODE1_DIV_1},
183 {256, CS4271_MODE1_MODE_1X, CS4271_MODE1_DIV_1, CS4271_MODE1_DIV_1},
184 {384, CS4271_MODE1_MODE_1X, CS4271_MODE1_DIV_15, CS4271_MODE1_DIV_1},
185 {512, CS4271_MODE1_MODE_1X, CS4271_MODE1_DIV_2, CS4271_MODE1_DIV_1},
186 {768, CS4271_MODE1_MODE_1X, CS4271_MODE1_DIV_3, CS4271_MODE1_DIV_3},
187 {1024, CS4271_MODE1_MODE_1X, CS4271_MODE1_DIV_3, CS4271_MODE1_DIV_3}
188};
189
190#define CS4171_NR_RATIOS ARRAY_SIZE(cs4271_clk_tab)
191
192/* 171/*
193 * @freq is the desired MCLK rate 172 * @freq is the desired MCLK rate
194 * MCLK rate should (c) be the sample rate, multiplied by one of the 173 * MCLK rate should (c) be the sample rate, multiplied by one of the
@@ -297,6 +276,45 @@ static int cs4271_put_deemph(struct snd_kcontrol *kcontrol,
297 return cs4271_set_deemph(codec); 276 return cs4271_set_deemph(codec);
298} 277}
299 278
279struct cs4271_clk_cfg {
280 bool master; /* codec mode */
281 u8 speed_mode; /* codec speed mode: 1x, 2x, 4x */
282 unsigned short ratio; /* MCLK / sample rate */
283 u8 ratio_mask; /* ratio bit mask for Master mode */
284};
285
286static struct cs4271_clk_cfg cs4271_clk_tab[] = {
287 {1, CS4271_MODE1_MODE_1X, 256, CS4271_MODE1_DIV_1},
288 {1, CS4271_MODE1_MODE_1X, 384, CS4271_MODE1_DIV_15},
289 {1, CS4271_MODE1_MODE_1X, 512, CS4271_MODE1_DIV_2},
290 {1, CS4271_MODE1_MODE_1X, 768, CS4271_MODE1_DIV_3},
291 {1, CS4271_MODE1_MODE_2X, 128, CS4271_MODE1_DIV_1},
292 {1, CS4271_MODE1_MODE_2X, 192, CS4271_MODE1_DIV_15},
293 {1, CS4271_MODE1_MODE_2X, 256, CS4271_MODE1_DIV_2},
294 {1, CS4271_MODE1_MODE_2X, 384, CS4271_MODE1_DIV_3},
295 {1, CS4271_MODE1_MODE_4X, 64, CS4271_MODE1_DIV_1},
296 {1, CS4271_MODE1_MODE_4X, 96, CS4271_MODE1_DIV_15},
297 {1, CS4271_MODE1_MODE_4X, 128, CS4271_MODE1_DIV_2},
298 {1, CS4271_MODE1_MODE_4X, 192, CS4271_MODE1_DIV_3},
299 {0, CS4271_MODE1_MODE_1X, 256, CS4271_MODE1_DIV_1},
300 {0, CS4271_MODE1_MODE_1X, 384, CS4271_MODE1_DIV_1},
301 {0, CS4271_MODE1_MODE_1X, 512, CS4271_MODE1_DIV_1},
302 {0, CS4271_MODE1_MODE_1X, 768, CS4271_MODE1_DIV_2},
303 {0, CS4271_MODE1_MODE_1X, 1024, CS4271_MODE1_DIV_2},
304 {0, CS4271_MODE1_MODE_2X, 128, CS4271_MODE1_DIV_1},
305 {0, CS4271_MODE1_MODE_2X, 192, CS4271_MODE1_DIV_1},
306 {0, CS4271_MODE1_MODE_2X, 256, CS4271_MODE1_DIV_1},
307 {0, CS4271_MODE1_MODE_2X, 384, CS4271_MODE1_DIV_2},
308 {0, CS4271_MODE1_MODE_2X, 512, CS4271_MODE1_DIV_2},
309 {0, CS4271_MODE1_MODE_4X, 64, CS4271_MODE1_DIV_1},
310 {0, CS4271_MODE1_MODE_4X, 96, CS4271_MODE1_DIV_1},
311 {0, CS4271_MODE1_MODE_4X, 128, CS4271_MODE1_DIV_1},
312 {0, CS4271_MODE1_MODE_4X, 192, CS4271_MODE1_DIV_2},
313 {0, CS4271_MODE1_MODE_4X, 256, CS4271_MODE1_DIV_2},
314};
315
316#define CS4171_NR_RATIOS ARRAY_SIZE(cs4271_clk_tab)
317
300static int cs4271_hw_params(struct snd_pcm_substream *substream, 318static int cs4271_hw_params(struct snd_pcm_substream *substream,
301 struct snd_pcm_hw_params *params, 319 struct snd_pcm_hw_params *params,
302 struct snd_soc_dai *dai) 320 struct snd_soc_dai *dai)
@@ -308,23 +326,28 @@ static int cs4271_hw_params(struct snd_pcm_substream *substream,
308 unsigned int ratio, val; 326 unsigned int ratio, val;
309 327
310 cs4271->rate = params_rate(params); 328 cs4271->rate = params_rate(params);
329
330 /* Configure DAC */
331 if (cs4271->rate < 50000)
332 val = CS4271_MODE1_MODE_1X;
333 else if (cs4271->rate < 100000)
334 val = CS4271_MODE1_MODE_2X;
335 else
336 val = CS4271_MODE1_MODE_4X;
337
311 ratio = cs4271->mclk / cs4271->rate; 338 ratio = cs4271->mclk / cs4271->rate;
312 for (i = 0; i < CS4171_NR_RATIOS; i++) 339 for (i = 0; i < CS4171_NR_RATIOS; i++)
313 if (cs4271_clk_tab[i].ratio == ratio) 340 if ((cs4271_clk_tab[i].master == cs4271->master) &&
341 (cs4271_clk_tab[i].speed_mode == val) &&
342 (cs4271_clk_tab[i].ratio == ratio))
314 break; 343 break;
315 344
316 if ((i == CS4171_NR_RATIOS) || ((ratio == 1024) && cs4271->master)) { 345 if (i == CS4171_NR_RATIOS) {
317 dev_err(codec->dev, "Invalid sample rate\n"); 346 dev_err(codec->dev, "Invalid sample rate\n");
318 return -EINVAL; 347 return -EINVAL;
319 } 348 }
320 349
321 /* Configure DAC */ 350 val |= cs4271_clk_tab[i].ratio_mask;
322 val = cs4271_clk_tab[i].speed_mode;
323
324 if (cs4271->master)
325 val |= cs4271_clk_tab[i].mclk_master;
326 else
327 val |= cs4271_clk_tab[i].mclk_slave;
328 351
329 ret = snd_soc_update_bits(codec, CS4271_MODE1, 352 ret = snd_soc_update_bits(codec, CS4271_MODE1,
330 CS4271_MODE1_MODE_MASK | CS4271_MODE1_DIV_MASK, val); 353 CS4271_MODE1_MODE_MASK | CS4271_MODE1_DIV_MASK, val);