aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthias Reichl <hias@horus.com>2017-11-08 15:03:30 -0500
committerMark Brown <broonie@kernel.org>2017-11-10 16:26:07 -0500
commitabd4f0e1c24fd5b7241c77506006e9c0982128c0 (patch)
treed7382df4973dbc730256509cd157941a1e67eede
parent3d2b3c707b3f9516d6c183eb1ffbf02a6dc5dc98 (diff)
ASoC: bcm2835: Support left/right justified and DSP modes
DSP modes and left/right justified modes can be supported on bcm2835 by configuring the frame sync polarity and frame sync length registers and by adjusting the channel data position registers. Clock and frame sync polarity handling in hw_params has been refactored to make the interaction between logical rising/falling edge frame start and physical configuration (changed by normal/inverted polarity modes) clearer. Modes where the first active data bit is transmitted immediately after frame start (eg DSP mode B with slot 0 active) only work reliable if bcm2835 is configured as frame master. In frame slave mode channel swap (or shift, this isn't quite clear yet) can occur. Currently the driver only warns if an unstable configuration is detected but doensn't prevent using them. Signed-off-by: Matthias Reichl <hias@horus.com> Signed-off-by: Mark Brown <broonie@kernel.org>
-rw-r--r--sound/soc/bcm/bcm2835-i2s.c152
1 files changed, 99 insertions, 53 deletions
diff --git a/sound/soc/bcm/bcm2835-i2s.c b/sound/soc/bcm/bcm2835-i2s.c
index 111b4ef7ce35..2e449d7173fc 100644
--- a/sound/soc/bcm/bcm2835-i2s.c
+++ b/sound/soc/bcm/bcm2835-i2s.c
@@ -344,6 +344,9 @@ static int bcm2835_i2s_hw_params(struct snd_pcm_substream *substream,
344 unsigned int rx_mask, tx_mask; 344 unsigned int rx_mask, tx_mask;
345 unsigned int rx_ch1_pos, rx_ch2_pos, tx_ch1_pos, tx_ch2_pos; 345 unsigned int rx_ch1_pos, rx_ch2_pos, tx_ch1_pos, tx_ch2_pos;
346 unsigned int mode, format; 346 unsigned int mode, format;
347 bool bit_clock_master = false;
348 bool frame_sync_master = false;
349 bool frame_start_falling_edge = false;
347 uint32_t csreg; 350 uint32_t csreg;
348 int ret = 0; 351 int ret = 0;
349 352
@@ -387,16 +390,39 @@ static int bcm2835_i2s_hw_params(struct snd_pcm_substream *substream,
387 if (data_length > slot_width) 390 if (data_length > slot_width)
388 return -EINVAL; 391 return -EINVAL;
389 392
390 /* Clock should only be set up here if CPU is clock master */ 393 /* Check if CPU is bit clock master */
391 switch (dev->fmt & SND_SOC_DAIFMT_MASTER_MASK) { 394 switch (dev->fmt & SND_SOC_DAIFMT_MASTER_MASK) {
392 case SND_SOC_DAIFMT_CBS_CFS: 395 case SND_SOC_DAIFMT_CBS_CFS:
393 case SND_SOC_DAIFMT_CBS_CFM: 396 case SND_SOC_DAIFMT_CBS_CFM:
394 ret = clk_set_rate(dev->clk, bclk_rate); 397 bit_clock_master = true;
395 if (ret) 398 break;
396 return ret; 399 case SND_SOC_DAIFMT_CBM_CFS:
400 case SND_SOC_DAIFMT_CBM_CFM:
401 bit_clock_master = false;
397 break; 402 break;
398 default: 403 default:
404 return -EINVAL;
405 }
406
407 /* Check if CPU is frame sync master */
408 switch (dev->fmt & SND_SOC_DAIFMT_MASTER_MASK) {
409 case SND_SOC_DAIFMT_CBS_CFS:
410 case SND_SOC_DAIFMT_CBM_CFS:
411 frame_sync_master = true;
412 break;
413 case SND_SOC_DAIFMT_CBS_CFM:
414 case SND_SOC_DAIFMT_CBM_CFM:
415 frame_sync_master = false;
399 break; 416 break;
417 default:
418 return -EINVAL;
419 }
420
421 /* Clock should only be set up here if CPU is clock master */
422 if (bit_clock_master) {
423 ret = clk_set_rate(dev->clk, bclk_rate);
424 if (ret)
425 return ret;
400 } 426 }
401 427
402 /* Setup the frame format */ 428 /* Setup the frame format */
@@ -427,13 +453,41 @@ static int bcm2835_i2s_hw_params(struct snd_pcm_substream *substream,
427 453
428 /* Setup frame sync signal for 50% duty cycle */ 454 /* Setup frame sync signal for 50% duty cycle */
429 framesync_length = frame_length / 2; 455 framesync_length = frame_length / 2;
456 frame_start_falling_edge = true;
457 break;
458 case SND_SOC_DAIFMT_LEFT_J:
459 if (slots & 1)
460 return -EINVAL;
461
462 odd_slot_offset = slots >> 1;
463 data_delay = 0;
464 framesync_length = frame_length / 2;
465 frame_start_falling_edge = false;
466 break;
467 case SND_SOC_DAIFMT_RIGHT_J:
468 if (slots & 1)
469 return -EINVAL;
470
471 /* Odd frame lengths aren't supported */
472 if (frame_length & 1)
473 return -EINVAL;
474
475 odd_slot_offset = slots >> 1;
476 data_delay = slot_width - data_length;
477 framesync_length = frame_length / 2;
478 frame_start_falling_edge = false;
479 break;
480 case SND_SOC_DAIFMT_DSP_A:
481 data_delay = 1;
482 framesync_length = 1;
483 frame_start_falling_edge = false;
484 break;
485 case SND_SOC_DAIFMT_DSP_B:
486 data_delay = 0;
487 framesync_length = 1;
488 frame_start_falling_edge = false;
430 break; 489 break;
431 default: 490 default:
432 /*
433 * TODO
434 * Others are possible but are not implemented at the moment.
435 */
436 dev_err(dev->dev, "%s:bad format\n", __func__);
437 return -EINVAL; 491 return -EINVAL;
438 } 492 }
439 493
@@ -443,6 +497,15 @@ static int bcm2835_i2s_hw_params(struct snd_pcm_substream *substream,
443 tx_mask, slot_width, data_delay, odd_slot_offset); 497 tx_mask, slot_width, data_delay, odd_slot_offset);
444 498
445 /* 499 /*
500 * Transmitting data immediately after frame start, eg
501 * in left-justified or DSP mode A, only works stable
502 * if bcm2835 is the frame clock master.
503 */
504 if ((!rx_ch1_pos || !tx_ch1_pos) && !frame_sync_master)
505 dev_warn(dev->dev,
506 "Unstable slave config detected, L/R may be swapped");
507
508 /*
446 * Set format for both streams. 509 * Set format for both streams.
447 * We cannot set another frame length 510 * We cannot set another frame length
448 * (and therefore word length) anyway, 511 * (and therefore word length) anyway,
@@ -472,62 +535,38 @@ static int bcm2835_i2s_hw_params(struct snd_pcm_substream *substream,
472 mode |= BCM2835_I2S_FLEN(frame_length - 1); 535 mode |= BCM2835_I2S_FLEN(frame_length - 1);
473 mode |= BCM2835_I2S_FSLEN(framesync_length); 536 mode |= BCM2835_I2S_FSLEN(framesync_length);
474 537
475 /* Master or slave? */ 538 /* CLKM selects bcm2835 clock slave mode */
476 switch (dev->fmt & SND_SOC_DAIFMT_MASTER_MASK) { 539 if (!bit_clock_master)
477 case SND_SOC_DAIFMT_CBS_CFS:
478 /* CPU is master */
479 break;
480 case SND_SOC_DAIFMT_CBM_CFS:
481 /*
482 * CODEC is bit clock master
483 * CPU is frame master
484 */
485 mode |= BCM2835_I2S_CLKM; 540 mode |= BCM2835_I2S_CLKM;
486 break; 541
487 case SND_SOC_DAIFMT_CBS_CFM: 542 /* FSM selects bcm2835 frame sync slave mode */
488 /* 543 if (!frame_sync_master)
489 * CODEC is frame master
490 * CPU is bit clock master
491 */
492 mode |= BCM2835_I2S_FSM; 544 mode |= BCM2835_I2S_FSM;
545
546 /* CLKI selects normal clocking mode, sampling on rising edge */
547 switch (dev->fmt & SND_SOC_DAIFMT_INV_MASK) {
548 case SND_SOC_DAIFMT_NB_NF:
549 case SND_SOC_DAIFMT_NB_IF:
550 mode |= BCM2835_I2S_CLKI;
493 break; 551 break;
494 case SND_SOC_DAIFMT_CBM_CFM: 552 case SND_SOC_DAIFMT_IB_NF:
495 /* CODEC is master */ 553 case SND_SOC_DAIFMT_IB_IF:
496 mode |= BCM2835_I2S_CLKM;
497 mode |= BCM2835_I2S_FSM;
498 break; 554 break;
499 default: 555 default:
500 dev_err(dev->dev, "%s:bad master\n", __func__);
501 return -EINVAL; 556 return -EINVAL;
502 } 557 }
503 558
504 /* 559 /* FSI selects frame start on falling edge */
505 * Invert clocks?
506 *
507 * The BCM approach seems to be inverted to the classical I2S approach.
508 */
509 switch (dev->fmt & SND_SOC_DAIFMT_INV_MASK) { 560 switch (dev->fmt & SND_SOC_DAIFMT_INV_MASK) {
510 case SND_SOC_DAIFMT_NB_NF: 561 case SND_SOC_DAIFMT_NB_NF:
511 /* None. Therefore, both for BCM */ 562 case SND_SOC_DAIFMT_IB_NF:
512 mode |= BCM2835_I2S_CLKI; 563 if (frame_start_falling_edge)
513 mode |= BCM2835_I2S_FSI; 564 mode |= BCM2835_I2S_FSI;
514 break;
515 case SND_SOC_DAIFMT_IB_IF:
516 /* Both. Therefore, none for BCM */
517 break; 565 break;
518 case SND_SOC_DAIFMT_NB_IF: 566 case SND_SOC_DAIFMT_NB_IF:
519 /* 567 case SND_SOC_DAIFMT_IB_IF:
520 * Invert only frame sync. Therefore, 568 if (!frame_start_falling_edge)
521 * invert only bit clock for BCM 569 mode |= BCM2835_I2S_FSI;
522 */
523 mode |= BCM2835_I2S_CLKI;
524 break;
525 case SND_SOC_DAIFMT_IB_NF:
526 /*
527 * Invert only bit clock. Therefore,
528 * invert only frame sync for BCM
529 */
530 mode |= BCM2835_I2S_FSI;
531 break; 570 break;
532 default: 571 default:
533 return -EINVAL; 572 return -EINVAL;
@@ -563,6 +602,13 @@ static int bcm2835_i2s_hw_params(struct snd_pcm_substream *substream,
563 dev_dbg(dev->dev, "sampling rate: %d bclk rate: %d\n", 602 dev_dbg(dev->dev, "sampling rate: %d bclk rate: %d\n",
564 params_rate(params), bclk_rate); 603 params_rate(params), bclk_rate);
565 604
605 dev_dbg(dev->dev, "CLKM: %d CLKI: %d FSM: %d FSI: %d frame start: %s edge\n",
606 !!(mode & BCM2835_I2S_CLKM),
607 !!(mode & BCM2835_I2S_CLKI),
608 !!(mode & BCM2835_I2S_FSM),
609 !!(mode & BCM2835_I2S_FSI),
610 (mode & BCM2835_I2S_FSI) ? "falling" : "rising");
611
566 return ret; 612 return ret;
567} 613}
568 614