diff options
author | Alexander Sverdlin <subaparts@yandex.ru> | 2011-03-07 12:29:45 -0500 |
---|---|---|
committer | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2011-03-09 08:08:16 -0500 |
commit | 5c3a12e96c9f3158602b2feac8583ae35c10b80e (patch) | |
tree | bb7ef9f5cd61d8f97a636bb668f772c9ce1f19a4 /sound/soc/codecs/cs4271.c | |
parent | 15086ded21ee7f065ad290c1edfdc49cf18cf96e (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.c | 83 |
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 | ||
171 | struct 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 | |||
178 | static 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 | ||
279 | struct 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 | |||
286 | static 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 | |||
300 | static int cs4271_hw_params(struct snd_pcm_substream *substream, | 318 | static 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); |