aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPeter Rosin <peda@axentia.se>2016-11-15 13:38:13 -0500
committerMark Brown <broonie@kernel.org>2016-11-16 06:02:31 -0500
commita85787edaaf7bc77ed011c89e23d52b3ff352c51 (patch)
treed705da6cfaf803fb1988a1f6778c41b35bc031f9
parent28549313da65cc8711401ee5466c526bd67de5f1 (diff)
ASoC: atmel_ssc_dai: if not provided, default to sensible dividers
When this driver masters BCLK and/or LRCLK, and noone has stated differently, assume that all the bits of a frame are used. This relieves the cpu dai users from the duty to fill in the dividers for the common case. Signed-off-by: Peter Rosin <peda@axentia.se> Signed-off-by: Mark Brown <broonie@kernel.org>
-rw-r--r--sound/soc/atmel/atmel_ssc_dai.c83
-rw-r--r--sound/soc/atmel/atmel_ssc_dai.h1
2 files changed, 77 insertions, 7 deletions
diff --git a/sound/soc/atmel/atmel_ssc_dai.c b/sound/soc/atmel/atmel_ssc_dai.c
index 16e459aedffe..a1e2c5682dcd 100644
--- a/sound/soc/atmel/atmel_ssc_dai.c
+++ b/sound/soc/atmel/atmel_ssc_dai.c
@@ -380,6 +380,7 @@ static void atmel_ssc_shutdown(struct snd_pcm_substream *substream,
380 ssc_writel(ssc_p->ssc->regs, CR, SSC_BIT(CR_SWRST)); 380 ssc_writel(ssc_p->ssc->regs, CR, SSC_BIT(CR_SWRST));
381 /* Clear the SSC dividers */ 381 /* Clear the SSC dividers */
382 ssc_p->cmr_div = ssc_p->tcmr_period = ssc_p->rcmr_period = 0; 382 ssc_p->cmr_div = ssc_p->tcmr_period = ssc_p->rcmr_period = 0;
383 ssc_p->forced_divider = 0;
383 } 384 }
384 spin_unlock_irq(&ssc_p->lock); 385 spin_unlock_irq(&ssc_p->lock);
385 386
@@ -426,14 +427,17 @@ static int atmel_ssc_set_dai_clkdiv(struct snd_soc_dai *cpu_dai,
426 else 427 else
427 if (div != ssc_p->cmr_div) 428 if (div != ssc_p->cmr_div)
428 return -EBUSY; 429 return -EBUSY;
430 ssc_p->forced_divider |= BIT(ATMEL_SSC_CMR_DIV);
429 break; 431 break;
430 432
431 case ATMEL_SSC_TCMR_PERIOD: 433 case ATMEL_SSC_TCMR_PERIOD:
432 ssc_p->tcmr_period = div; 434 ssc_p->tcmr_period = div;
435 ssc_p->forced_divider |= BIT(ATMEL_SSC_TCMR_PERIOD);
433 break; 436 break;
434 437
435 case ATMEL_SSC_RCMR_PERIOD: 438 case ATMEL_SSC_RCMR_PERIOD:
436 ssc_p->rcmr_period = div; 439 ssc_p->rcmr_period = div;
440 ssc_p->forced_divider |= BIT(ATMEL_SSC_RCMR_PERIOD);
437 break; 441 break;
438 442
439 default: 443 default:
@@ -443,6 +447,28 @@ static int atmel_ssc_set_dai_clkdiv(struct snd_soc_dai *cpu_dai,
443 return 0; 447 return 0;
444} 448}
445 449
450/* Is the cpu-dai master of the frame clock? */
451static int atmel_ssc_cfs(struct atmel_ssc_info *ssc_p)
452{
453 switch (ssc_p->daifmt & SND_SOC_DAIFMT_MASTER_MASK) {
454 case SND_SOC_DAIFMT_CBM_CFS:
455 case SND_SOC_DAIFMT_CBS_CFS:
456 return 1;
457 }
458 return 0;
459}
460
461/* Is the cpu-dai master of the bit clock? */
462static int atmel_ssc_cbs(struct atmel_ssc_info *ssc_p)
463{
464 switch (ssc_p->daifmt & SND_SOC_DAIFMT_MASTER_MASK) {
465 case SND_SOC_DAIFMT_CBS_CFM:
466 case SND_SOC_DAIFMT_CBS_CFS:
467 return 1;
468 }
469 return 0;
470}
471
446/* 472/*
447 * Configure the SSC. 473 * Configure the SSC.
448 */ 474 */
@@ -459,6 +485,9 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
459 u32 tfmr, rfmr, tcmr, rcmr; 485 u32 tfmr, rfmr, tcmr, rcmr;
460 int ret; 486 int ret;
461 int fslen, fslen_ext; 487 int fslen, fslen_ext;
488 u32 cmr_div;
489 u32 tcmr_period;
490 u32 rcmr_period;
462 491
463 /* 492 /*
464 * Currently, there is only one set of dma params for 493 * Currently, there is only one set of dma params for
@@ -470,6 +499,46 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
470 else 499 else
471 dir = 1; 500 dir = 1;
472 501
502 /*
503 * If the cpu dai should provide BCLK, but noone has provided the
504 * divider needed for that to work, fall back to something sensible.
505 */
506 cmr_div = ssc_p->cmr_div;
507 if (!(ssc_p->forced_divider & BIT(ATMEL_SSC_CMR_DIV)) &&
508 atmel_ssc_cbs(ssc_p)) {
509 int bclk_rate = snd_soc_params_to_bclk(params);
510
511 if (bclk_rate < 0) {
512 dev_err(dai->dev, "unable to calculate cmr_div: %d\n",
513 bclk_rate);
514 return bclk_rate;
515 }
516
517 cmr_div = DIV_ROUND_CLOSEST(ssc_p->mck_rate, 2 * bclk_rate);
518 }
519
520 /*
521 * If the cpu dai should provide LRCLK, but noone has provided the
522 * dividers needed for that to work, fall back to something sensible.
523 */
524 tcmr_period = ssc_p->tcmr_period;
525 rcmr_period = ssc_p->rcmr_period;
526 if (atmel_ssc_cfs(ssc_p)) {
527 int frame_size = snd_soc_params_to_frame_size(params);
528
529 if (frame_size < 0) {
530 dev_err(dai->dev,
531 "unable to calculate tx/rx cmr_period: %d\n",
532 frame_size);
533 return frame_size;
534 }
535
536 if (!(ssc_p->forced_divider & BIT(ATMEL_SSC_TCMR_PERIOD)))
537 tcmr_period = frame_size / 2 - 1;
538 if (!(ssc_p->forced_divider & BIT(ATMEL_SSC_RCMR_PERIOD)))
539 rcmr_period = frame_size / 2 - 1;
540 }
541
473 dma_params = ssc_p->dma_params[dir]; 542 dma_params = ssc_p->dma_params[dir];
474 543
475 channels = params_channels(params); 544 channels = params_channels(params);
@@ -524,7 +593,7 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
524 fslen_ext = (bits - 1) / 16; 593 fslen_ext = (bits - 1) / 16;
525 fslen = (bits - 1) % 16; 594 fslen = (bits - 1) % 16;
526 595
527 rcmr = SSC_BF(RCMR_PERIOD, ssc_p->rcmr_period) 596 rcmr = SSC_BF(RCMR_PERIOD, rcmr_period)
528 | SSC_BF(RCMR_STTDLY, START_DELAY) 597 | SSC_BF(RCMR_STTDLY, START_DELAY)
529 | SSC_BF(RCMR_START, SSC_START_FALLING_RF) 598 | SSC_BF(RCMR_START, SSC_START_FALLING_RF)
530 | SSC_BF(RCMR_CKI, SSC_CKI_RISING) 599 | SSC_BF(RCMR_CKI, SSC_CKI_RISING)
@@ -540,7 +609,7 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
540 | SSC_BF(RFMR_LOOP, 0) 609 | SSC_BF(RFMR_LOOP, 0)
541 | SSC_BF(RFMR_DATLEN, (bits - 1)); 610 | SSC_BF(RFMR_DATLEN, (bits - 1));
542 611
543 tcmr = SSC_BF(TCMR_PERIOD, ssc_p->tcmr_period) 612 tcmr = SSC_BF(TCMR_PERIOD, tcmr_period)
544 | SSC_BF(TCMR_STTDLY, START_DELAY) 613 | SSC_BF(TCMR_STTDLY, START_DELAY)
545 | SSC_BF(TCMR_START, SSC_START_FALLING_RF) 614 | SSC_BF(TCMR_START, SSC_START_FALLING_RF)
546 | SSC_BF(TCMR_CKI, SSC_CKI_FALLING) 615 | SSC_BF(TCMR_CKI, SSC_CKI_FALLING)
@@ -606,7 +675,7 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
606 fslen_ext = (bits - 1) / 16; 675 fslen_ext = (bits - 1) / 16;
607 fslen = (bits - 1) % 16; 676 fslen = (bits - 1) % 16;
608 677
609 rcmr = SSC_BF(RCMR_PERIOD, ssc_p->rcmr_period) 678 rcmr = SSC_BF(RCMR_PERIOD, rcmr_period)
610 | SSC_BF(RCMR_STTDLY, START_DELAY) 679 | SSC_BF(RCMR_STTDLY, START_DELAY)
611 | SSC_BF(RCMR_START, SSC_START_FALLING_RF) 680 | SSC_BF(RCMR_START, SSC_START_FALLING_RF)
612 | SSC_BF(RCMR_CKI, SSC_CKI_RISING) 681 | SSC_BF(RCMR_CKI, SSC_CKI_RISING)
@@ -623,7 +692,7 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
623 | SSC_BF(RFMR_LOOP, 0) 692 | SSC_BF(RFMR_LOOP, 0)
624 | SSC_BF(RFMR_DATLEN, (bits - 1)); 693 | SSC_BF(RFMR_DATLEN, (bits - 1));
625 694
626 tcmr = SSC_BF(TCMR_PERIOD, ssc_p->tcmr_period) 695 tcmr = SSC_BF(TCMR_PERIOD, tcmr_period)
627 | SSC_BF(TCMR_STTDLY, START_DELAY) 696 | SSC_BF(TCMR_STTDLY, START_DELAY)
628 | SSC_BF(TCMR_START, SSC_START_FALLING_RF) 697 | SSC_BF(TCMR_START, SSC_START_FALLING_RF)
629 | SSC_BF(TCMR_CKI, SSC_CKI_FALLING) 698 | SSC_BF(TCMR_CKI, SSC_CKI_FALLING)
@@ -650,7 +719,7 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
650 * MCK divider, and the BCLK signal is output 719 * MCK divider, and the BCLK signal is output
651 * on the SSC TK line. 720 * on the SSC TK line.
652 */ 721 */
653 rcmr = SSC_BF(RCMR_PERIOD, ssc_p->rcmr_period) 722 rcmr = SSC_BF(RCMR_PERIOD, rcmr_period)
654 | SSC_BF(RCMR_STTDLY, 1) 723 | SSC_BF(RCMR_STTDLY, 1)
655 | SSC_BF(RCMR_START, SSC_START_RISING_RF) 724 | SSC_BF(RCMR_START, SSC_START_RISING_RF)
656 | SSC_BF(RCMR_CKI, SSC_CKI_RISING) 725 | SSC_BF(RCMR_CKI, SSC_CKI_RISING)
@@ -665,7 +734,7 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
665 | SSC_BF(RFMR_LOOP, 0) 734 | SSC_BF(RFMR_LOOP, 0)
666 | SSC_BF(RFMR_DATLEN, (bits - 1)); 735 | SSC_BF(RFMR_DATLEN, (bits - 1));
667 736
668 tcmr = SSC_BF(TCMR_PERIOD, ssc_p->tcmr_period) 737 tcmr = SSC_BF(TCMR_PERIOD, tcmr_period)
669 | SSC_BF(TCMR_STTDLY, 1) 738 | SSC_BF(TCMR_STTDLY, 1)
670 | SSC_BF(TCMR_START, SSC_START_RISING_RF) 739 | SSC_BF(TCMR_START, SSC_START_RISING_RF)
671 | SSC_BF(TCMR_CKI, SSC_CKI_FALLING) 740 | SSC_BF(TCMR_CKI, SSC_CKI_FALLING)
@@ -760,7 +829,7 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
760 } 829 }
761 830
762 /* set SSC clock mode register */ 831 /* set SSC clock mode register */
763 ssc_writel(ssc_p->ssc->regs, CMR, ssc_p->cmr_div); 832 ssc_writel(ssc_p->ssc->regs, CMR, cmr_div);
764 833
765 /* set receive clock mode and format */ 834 /* set receive clock mode and format */
766 ssc_writel(ssc_p->ssc->regs, RCMR, rcmr); 835 ssc_writel(ssc_p->ssc->regs, RCMR, rcmr);
diff --git a/sound/soc/atmel/atmel_ssc_dai.h b/sound/soc/atmel/atmel_ssc_dai.h
index 80b153857a88..75194f582131 100644
--- a/sound/soc/atmel/atmel_ssc_dai.h
+++ b/sound/soc/atmel/atmel_ssc_dai.h
@@ -113,6 +113,7 @@ struct atmel_ssc_info {
113 unsigned short cmr_div; 113 unsigned short cmr_div;
114 unsigned short tcmr_period; 114 unsigned short tcmr_period;
115 unsigned short rcmr_period; 115 unsigned short rcmr_period;
116 unsigned int forced_divider;
116 struct atmel_pcm_dma_params *dma_params[2]; 117 struct atmel_pcm_dma_params *dma_params[2];
117 struct atmel_ssc_state ssc_state; 118 struct atmel_ssc_state ssc_state;
118 unsigned long mck_rate; 119 unsigned long mck_rate;