aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/codecs/tlv320aic23.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/codecs/tlv320aic23.c')
-rw-r--r--sound/soc/codecs/tlv320aic23.c262
1 files changed, 206 insertions, 56 deletions
diff --git a/sound/soc/codecs/tlv320aic23.c b/sound/soc/codecs/tlv320aic23.c
index 44308dac9e18..cfdea007c4cb 100644
--- a/sound/soc/codecs/tlv320aic23.c
+++ b/sound/soc/codecs/tlv320aic23.c
@@ -37,12 +37,6 @@
37 37
38#define AIC23_VERSION "0.1" 38#define AIC23_VERSION "0.1"
39 39
40struct tlv320aic23_srate_reg_info {
41 u32 sample_rate;
42 u8 control; /* SR3, SR2, SR1, SR0 and BOSR */
43 u8 divider; /* if 0 CLKIN = MCLK, if 1 CLKIN = MCLK/2 */
44};
45
46/* 40/*
47 * AIC23 register cache 41 * AIC23 register cache
48 */ 42 */
@@ -261,20 +255,156 @@ static const struct snd_soc_dapm_route intercon[] = {
261 255
262}; 256};
263 257
264/* tlv320aic23 related */ 258/* AIC23 driver data */
265static const struct tlv320aic23_srate_reg_info srate_reg_info[] = { 259struct aic23 {
266 {4000, 0x06, 1}, /* 4000 */ 260 struct snd_soc_codec codec;
267 {8000, 0x06, 0}, /* 8000 */ 261 int mclk;
268 {16000, 0x0C, 1}, /* 16000 */ 262 int requested_adc;
269 {22050, 0x11, 1}, /* 22050 */ 263 int requested_dac;
270 {24000, 0x00, 1}, /* 24000 */ 264};
271 {32000, 0x0C, 0}, /* 32000 */ 265
272 {44100, 0x11, 0}, /* 44100 */ 266/*
273 {48000, 0x00, 0}, /* 48000 */ 267 * Common Crystals used
274 {88200, 0x1F, 0}, /* 88200 */ 268 * 11.2896 Mhz /128 = *88.2k /192 = 58.8k
275 {96000, 0x0E, 0}, /* 96000 */ 269 * 12.0000 Mhz /125 = *96k /136 = 88.235K
270 * 12.2880 Mhz /128 = *96k /192 = 64k
271 * 16.9344 Mhz /128 = 132.3k /192 = *88.2k
272 * 18.4320 Mhz /128 = 144k /192 = *96k
273 */
274
275/*
276 * Normal BOSR 0-256/2 = 128, 1-384/2 = 192
277 * USB BOSR 0-250/2 = 125, 1-272/2 = 136
278 */
279static const int bosr_usb_divisor_table[] = {
280 128, 125, 192, 136
281};
282#define LOWER_GROUP ((1<<0) | (1<<1) | (1<<2) | (1<<3) | (1<<6) | (1<<7))
283#define UPPER_GROUP ((1<<8) | (1<<9) | (1<<10) | (1<<11) | (1<<15))
284static const unsigned short sr_valid_mask[] = {
285 LOWER_GROUP|UPPER_GROUP, /* Normal, bosr - 0*/
286 LOWER_GROUP|UPPER_GROUP, /* Normal, bosr - 1*/
287 LOWER_GROUP, /* Usb, bosr - 0*/
288 UPPER_GROUP, /* Usb, bosr - 1*/
289};
290/*
291 * Every divisor is a factor of 11*12
292 */
293#define SR_MULT (11*12)
294#define A(x) (x) ? (SR_MULT/x) : 0
295static const unsigned char sr_adc_mult_table[] = {
296 A(2), A(2), A(12), A(12), A(0), A(0), A(3), A(1),
297 A(2), A(2), A(11), A(11), A(0), A(0), A(0), A(1)
298};
299static const unsigned char sr_dac_mult_table[] = {
300 A(2), A(12), A(2), A(12), A(0), A(0), A(3), A(1),
301 A(2), A(11), A(2), A(11), A(0), A(0), A(0), A(1)
276}; 302};
277 303
304static unsigned get_score(int adc, int adc_l, int adc_h, int need_adc,
305 int dac, int dac_l, int dac_h, int need_dac)
306{
307 if ((adc >= adc_l) && (adc <= adc_h) &&
308 (dac >= dac_l) && (dac <= dac_h)) {
309 int diff_adc = need_adc - adc;
310 int diff_dac = need_dac - dac;
311 return abs(diff_adc) + abs(diff_dac);
312 }
313 return UINT_MAX;
314}
315
316static int find_rate(int mclk, u32 need_adc, u32 need_dac)
317{
318 int i, j;
319 int best_i = -1;
320 int best_j = -1;
321 int best_div = 0;
322 unsigned best_score = UINT_MAX;
323 int adc_l, adc_h, dac_l, dac_h;
324
325 need_adc *= SR_MULT;
326 need_dac *= SR_MULT;
327 /*
328 * rates given are +/- 1/32
329 */
330 adc_l = need_adc - (need_adc >> 5);
331 adc_h = need_adc + (need_adc >> 5);
332 dac_l = need_dac - (need_dac >> 5);
333 dac_h = need_dac + (need_dac >> 5);
334 for (i = 0; i < ARRAY_SIZE(bosr_usb_divisor_table); i++) {
335 int base = mclk / bosr_usb_divisor_table[i];
336 int mask = sr_valid_mask[i];
337 for (j = 0; j < ARRAY_SIZE(sr_adc_mult_table);
338 j++, mask >>= 1) {
339 int adc;
340 int dac;
341 int score;
342 if ((mask & 1) == 0)
343 continue;
344 adc = base * sr_adc_mult_table[j];
345 dac = base * sr_dac_mult_table[j];
346 score = get_score(adc, adc_l, adc_h, need_adc,
347 dac, dac_l, dac_h, need_dac);
348 if (best_score > score) {
349 best_score = score;
350 best_i = i;
351 best_j = j;
352 best_div = 0;
353 }
354 score = get_score((adc >> 1), adc_l, adc_h, need_adc,
355 (dac >> 1), dac_l, dac_h, need_dac);
356 /* prefer to have a /2 */
357 if ((score != UINT_MAX) && (best_score >= score)) {
358 best_score = score;
359 best_i = i;
360 best_j = j;
361 best_div = 1;
362 }
363 }
364 }
365 return (best_j << 2) | best_i | (best_div << TLV320AIC23_CLKIN_SHIFT);
366}
367
368#ifdef DEBUG
369static void get_current_sample_rates(struct snd_soc_codec *codec, int mclk,
370 u32 *sample_rate_adc, u32 *sample_rate_dac)
371{
372 int src = tlv320aic23_read_reg_cache(codec, TLV320AIC23_SRATE);
373 int sr = (src >> 2) & 0x0f;
374 int val = (mclk / bosr_usb_divisor_table[src & 3]);
375 int adc = (val * sr_adc_mult_table[sr]) / SR_MULT;
376 int dac = (val * sr_dac_mult_table[sr]) / SR_MULT;
377 if (src & TLV320AIC23_CLKIN_HALF) {
378 adc >>= 1;
379 dac >>= 1;
380 }
381 *sample_rate_adc = adc;
382 *sample_rate_dac = dac;
383}
384#endif
385
386static int set_sample_rate_control(struct snd_soc_codec *codec, int mclk,
387 u32 sample_rate_adc, u32 sample_rate_dac)
388{
389 /* Search for the right sample rate */
390 int data = find_rate(mclk, sample_rate_adc, sample_rate_dac);
391 if (data < 0) {
392 printk(KERN_ERR "%s:Invalid rate %u,%u requested\n",
393 __func__, sample_rate_adc, sample_rate_dac);
394 return -EINVAL;
395 }
396 tlv320aic23_write(codec, TLV320AIC23_SRATE, data);
397#ifdef DEBUG
398 {
399 u32 adc, dac;
400 get_current_sample_rates(codec, mclk, &adc, &dac);
401 printk(KERN_DEBUG "actual samplerate = %u,%u reg=%x\n",
402 adc, dac, data);
403 }
404#endif
405 return 0;
406}
407
278static int tlv320aic23_add_widgets(struct snd_soc_codec *codec) 408static int tlv320aic23_add_widgets(struct snd_soc_codec *codec)
279{ 409{
280 snd_soc_dapm_new_controls(codec, tlv320aic23_dapm_widgets, 410 snd_soc_dapm_new_controls(codec, tlv320aic23_dapm_widgets,
@@ -288,32 +418,36 @@ static int tlv320aic23_add_widgets(struct snd_soc_codec *codec)
288} 418}
289 419
290static int tlv320aic23_hw_params(struct snd_pcm_substream *substream, 420static int tlv320aic23_hw_params(struct snd_pcm_substream *substream,
291 struct snd_pcm_hw_params *params) 421 struct snd_pcm_hw_params *params,
422 struct snd_soc_dai *dai)
292{ 423{
293 struct snd_soc_pcm_runtime *rtd = substream->private_data; 424 struct snd_soc_pcm_runtime *rtd = substream->private_data;
294 struct snd_soc_device *socdev = rtd->socdev; 425 struct snd_soc_device *socdev = rtd->socdev;
295 struct snd_soc_codec *codec = socdev->codec; 426 struct snd_soc_codec *codec = socdev->codec;
296 u16 iface_reg, data; 427 u16 iface_reg;
297 u8 count = 0; 428 int ret;
429 struct aic23 *aic23 = container_of(codec, struct aic23, codec);
430 u32 sample_rate_adc = aic23->requested_adc;
431 u32 sample_rate_dac = aic23->requested_dac;
432 u32 sample_rate = params_rate(params);
433
434 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
435 aic23->requested_dac = sample_rate_dac = sample_rate;
436 if (!sample_rate_adc)
437 sample_rate_adc = sample_rate;
438 } else {
439 aic23->requested_adc = sample_rate_adc = sample_rate;
440 if (!sample_rate_dac)
441 sample_rate_dac = sample_rate;
442 }
443 ret = set_sample_rate_control(codec, aic23->mclk, sample_rate_adc,
444 sample_rate_dac);
445 if (ret < 0)
446 return ret;
298 447
299 iface_reg = 448 iface_reg =
300 tlv320aic23_read_reg_cache(codec, 449 tlv320aic23_read_reg_cache(codec,
301 TLV320AIC23_DIGT_FMT) & ~(0x03 << 2); 450 TLV320AIC23_DIGT_FMT) & ~(0x03 << 2);
302
303 /* Search for the right sample rate */
304 /* Verify what happens if the rate is not supported
305 * now it goes to 96Khz */
306 while ((srate_reg_info[count].sample_rate != params_rate(params)) &&
307 (count < ARRAY_SIZE(srate_reg_info))) {
308 count++;
309 }
310
311 data = (srate_reg_info[count].divider << TLV320AIC23_CLKIN_SHIFT) |
312 (srate_reg_info[count]. control << TLV320AIC23_BOSR_SHIFT) |
313 TLV320AIC23_USB_CLK_ON;
314
315 tlv320aic23_write(codec, TLV320AIC23_SRATE, data);
316
317 switch (params_format(params)) { 451 switch (params_format(params)) {
318 case SNDRV_PCM_FORMAT_S16_LE: 452 case SNDRV_PCM_FORMAT_S16_LE:
319 break; 453 break;
@@ -332,7 +466,8 @@ static int tlv320aic23_hw_params(struct snd_pcm_substream *substream,
332 return 0; 466 return 0;
333} 467}
334 468
335static int tlv320aic23_pcm_prepare(struct snd_pcm_substream *substream) 469static int tlv320aic23_pcm_prepare(struct snd_pcm_substream *substream,
470 struct snd_soc_dai *dai)
336{ 471{
337 struct snd_soc_pcm_runtime *rtd = substream->private_data; 472 struct snd_soc_pcm_runtime *rtd = substream->private_data;
338 struct snd_soc_device *socdev = rtd->socdev; 473 struct snd_soc_device *socdev = rtd->socdev;
@@ -344,17 +479,23 @@ static int tlv320aic23_pcm_prepare(struct snd_pcm_substream *substream)
344 return 0; 479 return 0;
345} 480}
346 481
347static void tlv320aic23_shutdown(struct snd_pcm_substream *substream) 482static void tlv320aic23_shutdown(struct snd_pcm_substream *substream,
483 struct snd_soc_dai *dai)
348{ 484{
349 struct snd_soc_pcm_runtime *rtd = substream->private_data; 485 struct snd_soc_pcm_runtime *rtd = substream->private_data;
350 struct snd_soc_device *socdev = rtd->socdev; 486 struct snd_soc_device *socdev = rtd->socdev;
351 struct snd_soc_codec *codec = socdev->codec; 487 struct snd_soc_codec *codec = socdev->codec;
488 struct aic23 *aic23 = container_of(codec, struct aic23, codec);
352 489
353 /* deactivate */ 490 /* deactivate */
354 if (!codec->active) { 491 if (!codec->active) {
355 udelay(50); 492 udelay(50);
356 tlv320aic23_write(codec, TLV320AIC23_ACTIVE, 0x0); 493 tlv320aic23_write(codec, TLV320AIC23_ACTIVE, 0x0);
357 } 494 }
495 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
496 aic23->requested_dac = 0;
497 else
498 aic23->requested_adc = 0;
358} 499}
359 500
360static int tlv320aic23_mute(struct snd_soc_dai *dai, int mute) 501static int tlv320aic23_mute(struct snd_soc_dai *dai, int mute)
@@ -400,7 +541,7 @@ static int tlv320aic23_set_dai_fmt(struct snd_soc_dai *codec_dai,
400 case SND_SOC_DAIFMT_I2S: 541 case SND_SOC_DAIFMT_I2S:
401 iface_reg |= TLV320AIC23_FOR_I2S; 542 iface_reg |= TLV320AIC23_FOR_I2S;
402 break; 543 break;
403 case SND_SOC_DAIFMT_DSP_A: 544 case SND_SOC_DAIFMT_DSP_B:
404 iface_reg |= TLV320AIC23_FOR_DSP; 545 iface_reg |= TLV320AIC23_FOR_DSP;
405 break; 546 break;
406 case SND_SOC_DAIFMT_RIGHT_J: 547 case SND_SOC_DAIFMT_RIGHT_J:
@@ -422,12 +563,9 @@ static int tlv320aic23_set_dai_sysclk(struct snd_soc_dai *codec_dai,
422 int clk_id, unsigned int freq, int dir) 563 int clk_id, unsigned int freq, int dir)
423{ 564{
424 struct snd_soc_codec *codec = codec_dai->codec; 565 struct snd_soc_codec *codec = codec_dai->codec;
425 566 struct aic23 *aic23 = container_of(codec, struct aic23, codec);
426 switch (freq) { 567 aic23->mclk = freq;
427 case 12000000: 568 return 0;
428 return 0;
429 }
430 return -EINVAL;
431} 569}
432 570
433static int tlv320aic23_set_bias_level(struct snd_soc_codec *codec, 571static int tlv320aic23_set_bias_level(struct snd_soc_codec *codec,
@@ -478,12 +616,10 @@ struct snd_soc_dai tlv320aic23_dai = {
478 .prepare = tlv320aic23_pcm_prepare, 616 .prepare = tlv320aic23_pcm_prepare,
479 .hw_params = tlv320aic23_hw_params, 617 .hw_params = tlv320aic23_hw_params,
480 .shutdown = tlv320aic23_shutdown, 618 .shutdown = tlv320aic23_shutdown,
481 }, 619 .digital_mute = tlv320aic23_mute,
482 .dai_ops = { 620 .set_fmt = tlv320aic23_set_dai_fmt,
483 .digital_mute = tlv320aic23_mute, 621 .set_sysclk = tlv320aic23_set_dai_sysclk,
484 .set_fmt = tlv320aic23_set_dai_fmt, 622 }
485 .set_sysclk = tlv320aic23_set_dai_sysclk,
486 }
487}; 623};
488EXPORT_SYMBOL_GPL(tlv320aic23_dai); 624EXPORT_SYMBOL_GPL(tlv320aic23_dai);
489 625
@@ -584,7 +720,7 @@ static int tlv320aic23_init(struct snd_soc_device *socdev)
584 720
585 tlv320aic23_add_controls(codec); 721 tlv320aic23_add_controls(codec);
586 tlv320aic23_add_widgets(codec); 722 tlv320aic23_add_widgets(codec);
587 ret = snd_soc_register_card(socdev); 723 ret = snd_soc_init_card(socdev);
588 if (ret < 0) { 724 if (ret < 0) {
589 printk(KERN_ERR "tlv320aic23: failed to register card\n"); 725 printk(KERN_ERR "tlv320aic23: failed to register card\n");
590 goto card_err; 726 goto card_err;
@@ -659,14 +795,15 @@ static int tlv320aic23_probe(struct platform_device *pdev)
659{ 795{
660 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 796 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
661 struct snd_soc_codec *codec; 797 struct snd_soc_codec *codec;
798 struct aic23 *aic23;
662 int ret = 0; 799 int ret = 0;
663 800
664 printk(KERN_INFO "AIC23 Audio Codec %s\n", AIC23_VERSION); 801 printk(KERN_INFO "AIC23 Audio Codec %s\n", AIC23_VERSION);
665 802
666 codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); 803 aic23 = kzalloc(sizeof(struct aic23), GFP_KERNEL);
667 if (codec == NULL) 804 if (aic23 == NULL)
668 return -ENOMEM; 805 return -ENOMEM;
669 806 codec = &aic23->codec;
670 socdev->codec = codec; 807 socdev->codec = codec;
671 mutex_init(&codec->mutex); 808 mutex_init(&codec->mutex);
672 INIT_LIST_HEAD(&codec->dapm_widgets); 809 INIT_LIST_HEAD(&codec->dapm_widgets);
@@ -687,6 +824,7 @@ static int tlv320aic23_remove(struct platform_device *pdev)
687{ 824{
688 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 825 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
689 struct snd_soc_codec *codec = socdev->codec; 826 struct snd_soc_codec *codec = socdev->codec;
827 struct aic23 *aic23 = container_of(codec, struct aic23, codec);
690 828
691 if (codec->control_data) 829 if (codec->control_data)
692 tlv320aic23_set_bias_level(codec, SND_SOC_BIAS_OFF); 830 tlv320aic23_set_bias_level(codec, SND_SOC_BIAS_OFF);
@@ -697,7 +835,7 @@ static int tlv320aic23_remove(struct platform_device *pdev)
697 i2c_del_driver(&tlv320aic23_i2c_driver); 835 i2c_del_driver(&tlv320aic23_i2c_driver);
698#endif 836#endif
699 kfree(codec->reg_cache); 837 kfree(codec->reg_cache);
700 kfree(codec); 838 kfree(aic23);
701 839
702 return 0; 840 return 0;
703} 841}
@@ -709,6 +847,18 @@ struct snd_soc_codec_device soc_codec_dev_tlv320aic23 = {
709}; 847};
710EXPORT_SYMBOL_GPL(soc_codec_dev_tlv320aic23); 848EXPORT_SYMBOL_GPL(soc_codec_dev_tlv320aic23);
711 849
850static int __init tlv320aic23_modinit(void)
851{
852 return snd_soc_register_dai(&tlv320aic23_dai);
853}
854module_init(tlv320aic23_modinit);
855
856static void __exit tlv320aic23_exit(void)
857{
858 snd_soc_unregister_dai(&tlv320aic23_dai);
859}
860module_exit(tlv320aic23_exit);
861
712MODULE_DESCRIPTION("ASoC TLV320AIC23 codec driver"); 862MODULE_DESCRIPTION("ASoC TLV320AIC23 codec driver");
713MODULE_AUTHOR("Arun KS <arunks@mistralsolutions.com>"); 863MODULE_AUTHOR("Arun KS <arunks@mistralsolutions.com>");
714MODULE_LICENSE("GPL"); 864MODULE_LICENSE("GPL");