aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc
diff options
context:
space:
mode:
authorTimur Tabi <timur@freescale.com>2009-02-05 18:56:02 -0500
committerMark Brown <broonie@opensource.wolfsonmicro.com>2009-02-06 07:08:15 -0500
commit85ef2375ef2ebbb2bf660ad3a27c644d0ebf1b1a (patch)
treebc4b8904b3d74437f03744ecc37bb0a79828b027 /sound/soc
parent8836c273e4d44d088157b7ccbd2c108cefe70565 (diff)
ASoC: optimize init sequence of Freescale MPC8610 sound drivers
In the Freescale MPC8610 sound drivers, relocate all code from the _prepare functions into the corresponding _hw_params functions. These drivers assumed that the sample size is known in the _prepare function and not in the _hw_params function, but this is not true. Move the code in fsl_dma_prepare() into fsl_dma_hw_param(). Create fsl_ssi_hw_params() and move the code from fsl_ssi_prepare() into it. Turn off snooping for DMA operations to/from I/O registers, since that's not necessary. Signed-off-by: Timur Tabi <timur@freescale.com> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'sound/soc')
-rw-r--r--sound/soc/fsl/fsl_dma.c178
-rw-r--r--sound/soc/fsl/fsl_ssi.c19
2 files changed, 94 insertions, 103 deletions
diff --git a/sound/soc/fsl/fsl_dma.c b/sound/soc/fsl/fsl_dma.c
index 64993eda5679..58a3fa497503 100644
--- a/sound/soc/fsl/fsl_dma.c
+++ b/sound/soc/fsl/fsl_dma.c
@@ -464,11 +464,7 @@ static int fsl_dma_open(struct snd_pcm_substream *substream)
464 sizeof(struct fsl_dma_link_descriptor); 464 sizeof(struct fsl_dma_link_descriptor);
465 465
466 for (i = 0; i < NUM_DMA_LINKS; i++) { 466 for (i = 0; i < NUM_DMA_LINKS; i++) {
467 struct fsl_dma_link_descriptor *link = &dma_private->link[i]; 467 dma_private->link[i].next = cpu_to_be64(temp_link);
468
469 link->source_attr = cpu_to_be32(CCSR_DMA_ATR_SNOOP);
470 link->dest_attr = cpu_to_be32(CCSR_DMA_ATR_SNOOP);
471 link->next = cpu_to_be64(temp_link);
472 468
473 temp_link += sizeof(struct fsl_dma_link_descriptor); 469 temp_link += sizeof(struct fsl_dma_link_descriptor);
474 } 470 }
@@ -525,79 +521,9 @@ static int fsl_dma_open(struct snd_pcm_substream *substream)
525 * This function obtains hardware parameters about the opened stream and 521 * This function obtains hardware parameters about the opened stream and
526 * programs the DMA controller accordingly. 522 * programs the DMA controller accordingly.
527 * 523 *
528 * Note that due to a quirk of the SSI's STX register, the target address 524 * One drawback of big-endian is that when copying integers of different
529 * for the DMA operations depends on the sample size. So we don't program 525 * sizes to a fixed-sized register, the address to which the integer must be
530 * the dest_addr (for playback -- source_addr for capture) fields in the 526 * copied is dependent on the size of the integer.
531 * link descriptors here. We do that in fsl_dma_prepare()
532 */
533static int fsl_dma_hw_params(struct snd_pcm_substream *substream,
534 struct snd_pcm_hw_params *hw_params)
535{
536 struct snd_pcm_runtime *runtime = substream->runtime;
537 struct fsl_dma_private *dma_private = runtime->private_data;
538
539 dma_addr_t temp_addr; /* Pointer to next period */
540
541 unsigned int i;
542
543 /* Get all the parameters we need */
544 size_t buffer_size = params_buffer_bytes(hw_params);
545 size_t period_size = params_period_bytes(hw_params);
546
547 /* Initialize our DMA tracking variables */
548 dma_private->period_size = period_size;
549 dma_private->num_periods = params_periods(hw_params);
550 dma_private->dma_buf_end = dma_private->dma_buf_phys + buffer_size;
551 dma_private->dma_buf_next = dma_private->dma_buf_phys +
552 (NUM_DMA_LINKS * period_size);
553 if (dma_private->dma_buf_next >= dma_private->dma_buf_end)
554 dma_private->dma_buf_next = dma_private->dma_buf_phys;
555
556 /*
557 * The actual address in STX0 (destination for playback, source for
558 * capture) is based on the sample size, but we don't know the sample
559 * size in this function, so we'll have to adjust that later. See
560 * comments in fsl_dma_prepare().
561 *
562 * The DMA controller does not have a cache, so the CPU does not
563 * need to tell it to flush its cache. However, the DMA
564 * controller does need to tell the CPU to flush its cache.
565 * That's what the SNOOP bit does.
566 *
567 * Also, even though the DMA controller supports 36-bit addressing, for
568 * simplicity we currently support only 32-bit addresses for the audio
569 * buffer itself.
570 */
571 temp_addr = substream->dma_buffer.addr;
572
573 for (i = 0; i < NUM_DMA_LINKS; i++) {
574 struct fsl_dma_link_descriptor *link = &dma_private->link[i];
575
576 link->count = cpu_to_be32(period_size);
577
578 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
579 link->source_addr = cpu_to_be32(temp_addr);
580 else
581 link->dest_addr = cpu_to_be32(temp_addr);
582
583 temp_addr += period_size;
584 }
585
586 return 0;
587}
588
589/**
590 * fsl_dma_prepare - prepare the DMA registers for playback.
591 *
592 * This function is called after the specifics of the audio data are known,
593 * i.e. snd_pcm_runtime is initialized.
594 *
595 * In this function, we finish programming the registers of the DMA
596 * controller that are dependent on the sample size.
597 *
598 * One of the drawbacks with big-endian is that when copying integers of
599 * different sizes to a fixed-sized register, the address to which the
600 * integer must be copied is dependent on the size of the integer.
601 * 527 *
602 * For example, if P is the address of a 32-bit register, and X is a 32-bit 528 * For example, if P is the address of a 32-bit register, and X is a 32-bit
603 * integer, then X should be copied to address P. However, if X is a 16-bit 529 * integer, then X should be copied to address P. However, if X is a 16-bit
@@ -613,22 +539,58 @@ static int fsl_dma_hw_params(struct snd_pcm_substream *substream,
613 * and 8 bytes at a time). So we do not support packed 24-bit samples. 539 * and 8 bytes at a time). So we do not support packed 24-bit samples.
614 * 24-bit data must be padded to 32 bits. 540 * 24-bit data must be padded to 32 bits.
615 */ 541 */
616static int fsl_dma_prepare(struct snd_pcm_substream *substream) 542static int fsl_dma_hw_params(struct snd_pcm_substream *substream,
543 struct snd_pcm_hw_params *hw_params)
617{ 544{
618 struct snd_pcm_runtime *runtime = substream->runtime; 545 struct snd_pcm_runtime *runtime = substream->runtime;
619 struct fsl_dma_private *dma_private = runtime->private_data; 546 struct fsl_dma_private *dma_private = runtime->private_data;
547
548 /* Number of bits per sample */
549 unsigned int sample_size =
550 snd_pcm_format_physical_width(params_format(hw_params));
551
552 /* Number of bytes per frame */
553 unsigned int frame_size = 2 * (sample_size / 8);
554
555 /* Bus address of SSI STX register */
556 dma_addr_t ssi_sxx_phys = dma_private->ssi_sxx_phys;
557
558 /* Size of the DMA buffer, in bytes */
559 size_t buffer_size = params_buffer_bytes(hw_params);
560
561 /* Number of bytes per period */
562 size_t period_size = params_period_bytes(hw_params);
563
564 /* Pointer to next period */
565 dma_addr_t temp_addr = substream->dma_buffer.addr;
566
567 /* Pointer to DMA controller */
620 struct ccsr_dma_channel __iomem *dma_channel = dma_private->dma_channel; 568 struct ccsr_dma_channel __iomem *dma_channel = dma_private->dma_channel;
621 u32 mr; 569
570 u32 mr; /* DMA Mode Register */
571
622 unsigned int i; 572 unsigned int i;
623 dma_addr_t ssi_sxx_phys; /* Bus address of SSI STX register */
624 unsigned int frame_size; /* Number of bytes per frame */
625 573
626 ssi_sxx_phys = dma_private->ssi_sxx_phys; 574 /* Initialize our DMA tracking variables */
575 dma_private->period_size = period_size;
576 dma_private->num_periods = params_periods(hw_params);
577 dma_private->dma_buf_end = dma_private->dma_buf_phys + buffer_size;
578 dma_private->dma_buf_next = dma_private->dma_buf_phys +
579 (NUM_DMA_LINKS * period_size);
580
581 if (dma_private->dma_buf_next >= dma_private->dma_buf_end)
582 /* This happens if the number of periods == NUM_DMA_LINKS */
583 dma_private->dma_buf_next = dma_private->dma_buf_phys;
627 584
628 mr = in_be32(&dma_channel->mr) & ~(CCSR_DMA_MR_BWC_MASK | 585 mr = in_be32(&dma_channel->mr) & ~(CCSR_DMA_MR_BWC_MASK |
629 CCSR_DMA_MR_SAHTS_MASK | CCSR_DMA_MR_DAHTS_MASK); 586 CCSR_DMA_MR_SAHTS_MASK | CCSR_DMA_MR_DAHTS_MASK);
630 587
631 switch (runtime->sample_bits) { 588 /* Due to a quirk of the SSI's STX register, the target address
589 * for the DMA operations depends on the sample size. So we calculate
590 * that offset here. While we're at it, also tell the DMA controller
591 * how much data to transfer per sample.
592 */
593 switch (sample_size) {
632 case 8: 594 case 8:
633 mr |= CCSR_DMA_MR_DAHTS_1 | CCSR_DMA_MR_SAHTS_1; 595 mr |= CCSR_DMA_MR_DAHTS_1 | CCSR_DMA_MR_SAHTS_1;
634 ssi_sxx_phys += 3; 596 ssi_sxx_phys += 3;
@@ -641,12 +603,12 @@ static int fsl_dma_prepare(struct snd_pcm_substream *substream)
641 mr |= CCSR_DMA_MR_DAHTS_4 | CCSR_DMA_MR_SAHTS_4; 603 mr |= CCSR_DMA_MR_DAHTS_4 | CCSR_DMA_MR_SAHTS_4;
642 break; 604 break;
643 default: 605 default:
606 /* We should never get here */
644 dev_err(substream->pcm->card->dev, 607 dev_err(substream->pcm->card->dev,
645 "unsupported sample size %u\n", runtime->sample_bits); 608 "unsupported sample size %u\n", sample_size);
646 return -EINVAL; 609 return -EINVAL;
647 } 610 }
648 611
649 frame_size = runtime->frame_bits / 8;
650 /* 612 /*
651 * BWC should always be a multiple of the frame size. BWC determines 613 * BWC should always be a multiple of the frame size. BWC determines
652 * how many bytes are sent/received before the DMA controller checks the 614 * how many bytes are sent/received before the DMA controller checks the
@@ -655,7 +617,6 @@ static int fsl_dma_prepare(struct snd_pcm_substream *substream)
655 * capture, the receive FIFO is triggered when it contains one frame, so 617 * capture, the receive FIFO is triggered when it contains one frame, so
656 * we want to receive one frame at a time. 618 * we want to receive one frame at a time.
657 */ 619 */
658
659 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 620 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
660 mr |= CCSR_DMA_MR_BWC(2 * frame_size); 621 mr |= CCSR_DMA_MR_BWC(2 * frame_size);
661 else 622 else
@@ -663,16 +624,48 @@ static int fsl_dma_prepare(struct snd_pcm_substream *substream)
663 624
664 out_be32(&dma_channel->mr, mr); 625 out_be32(&dma_channel->mr, mr);
665 626
666 /*
667 * Program the address of the DMA transfer to/from the SSI.
668 */
669 for (i = 0; i < NUM_DMA_LINKS; i++) { 627 for (i = 0; i < NUM_DMA_LINKS; i++) {
670 struct fsl_dma_link_descriptor *link = &dma_private->link[i]; 628 struct fsl_dma_link_descriptor *link = &dma_private->link[i];
671 629
672 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 630 link->count = cpu_to_be32(period_size);
631
632 /* Even though the DMA controller supports 36-bit addressing,
633 * for simplicity we allow only 32-bit addresses for the audio
634 * buffer itself. This was enforced in fsl_dma_new() with the
635 * DMA mask.
636 *
637 * The snoop bit tells the DMA controller whether it should tell
638 * the ECM to snoop during a read or write to an address. For
639 * audio, we use DMA to transfer data between memory and an I/O
640 * device (the SSI's STX0 or SRX0 register). Snooping is only
641 * needed if there is a cache, so we need to snoop memory
642 * addresses only. For playback, that means we snoop the source
643 * but not the destination. For capture, we snoop the
644 * destination but not the source.
645 *
646 * Note that failing to snoop properly is unlikely to cause
647 * cache incoherency if the period size is larger than the
648 * size of L1 cache. This is because filling in one period will
649 * flush out the data for the previous period. So if you
650 * increased period_bytes_min to a large enough size, you might
651 * get more performance by not snooping, and you'll still be
652 * okay.
653 */
654 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
655 link->source_addr = cpu_to_be32(temp_addr);
656 link->source_attr = cpu_to_be32(CCSR_DMA_ATR_SNOOP);
657
673 link->dest_addr = cpu_to_be32(ssi_sxx_phys); 658 link->dest_addr = cpu_to_be32(ssi_sxx_phys);
674 else 659 link->dest_attr = cpu_to_be32(CCSR_DMA_ATR_NOSNOOP);
660 } else {
675 link->source_addr = cpu_to_be32(ssi_sxx_phys); 661 link->source_addr = cpu_to_be32(ssi_sxx_phys);
662 link->source_attr = cpu_to_be32(CCSR_DMA_ATR_NOSNOOP);
663
664 link->dest_addr = cpu_to_be32(temp_addr);
665 link->dest_attr = cpu_to_be32(CCSR_DMA_ATR_SNOOP);
666 }
667
668 temp_addr += period_size;
676 } 669 }
677 670
678 return 0; 671 return 0;
@@ -808,7 +801,6 @@ static struct snd_pcm_ops fsl_dma_ops = {
808 .ioctl = snd_pcm_lib_ioctl, 801 .ioctl = snd_pcm_lib_ioctl,
809 .hw_params = fsl_dma_hw_params, 802 .hw_params = fsl_dma_hw_params,
810 .hw_free = fsl_dma_hw_free, 803 .hw_free = fsl_dma_hw_free,
811 .prepare = fsl_dma_prepare,
812 .pointer = fsl_dma_pointer, 804 .pointer = fsl_dma_pointer,
813}; 805};
814 806
diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index c6d6eb71dc1d..6844009833db 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -400,7 +400,7 @@ static int fsl_ssi_startup(struct snd_pcm_substream *substream,
400} 400}
401 401
402/** 402/**
403 * fsl_ssi_prepare: prepare the SSI. 403 * fsl_ssi_hw_params - program the sample size
404 * 404 *
405 * Most of the SSI registers have been programmed in the startup function, 405 * Most of the SSI registers have been programmed in the startup function,
406 * but the word length must be programmed here. Unfortunately, programming 406 * but the word length must be programmed here. Unfortunately, programming
@@ -412,20 +412,19 @@ static int fsl_ssi_startup(struct snd_pcm_substream *substream,
412 * Note: The SxCCR.DC and SxCCR.PM bits are only used if the SSI is the 412 * Note: The SxCCR.DC and SxCCR.PM bits are only used if the SSI is the
413 * clock master. 413 * clock master.
414 */ 414 */
415static int fsl_ssi_prepare(struct snd_pcm_substream *substream, 415static int fsl_ssi_hw_params(struct snd_pcm_substream *substream,
416 struct snd_soc_dai *dai) 416 struct snd_pcm_hw_params *hw_params, struct snd_soc_dai *cpu_dai)
417{ 417{
418 struct snd_pcm_runtime *runtime = substream->runtime; 418 struct fsl_ssi_private *ssi_private = cpu_dai->private_data;
419 struct snd_soc_pcm_runtime *rtd = substream->private_data;
420 struct fsl_ssi_private *ssi_private = rtd->dai->cpu_dai->private_data;
421
422 struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
423 419
424 if (substream == ssi_private->first_stream) { 420 if (substream == ssi_private->first_stream) {
421 struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
422 unsigned int sample_size =
423 snd_pcm_format_width(params_format(hw_params));
425 u32 wl; 424 u32 wl;
426 425
427 /* The SSI should always be disabled at this points (SSIEN=0) */ 426 /* The SSI should always be disabled at this points (SSIEN=0) */
428 wl = CCSR_SSI_SxCCR_WL(snd_pcm_format_width(runtime->format)); 427 wl = CCSR_SSI_SxCCR_WL(sample_size);
429 428
430 /* In synchronous mode, the SSI uses STCCR for capture */ 429 /* In synchronous mode, the SSI uses STCCR for capture */
431 clrsetbits_be32(&ssi->stccr, CCSR_SSI_SxCCR_WL_MASK, wl); 430 clrsetbits_be32(&ssi->stccr, CCSR_SSI_SxCCR_WL_MASK, wl);
@@ -579,7 +578,7 @@ static struct snd_soc_dai fsl_ssi_dai_template = {
579 }, 578 },
580 .ops = { 579 .ops = {
581 .startup = fsl_ssi_startup, 580 .startup = fsl_ssi_startup,
582 .prepare = fsl_ssi_prepare, 581 .hw_params = fsl_ssi_hw_params,
583 .shutdown = fsl_ssi_shutdown, 582 .shutdown = fsl_ssi_shutdown,
584 .trigger = fsl_ssi_trigger, 583 .trigger = fsl_ssi_trigger,
585 .set_sysclk = fsl_ssi_set_sysclk, 584 .set_sysclk = fsl_ssi_set_sysclk,