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 | |
| 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>
| -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); |
