diff options
Diffstat (limited to 'sound/soc/davinci')
-rw-r--r-- | sound/soc/davinci/davinci-pcm.c | 154 | ||||
-rw-r--r-- | sound/soc/davinci/davinci-vcif.c | 9 |
2 files changed, 94 insertions, 69 deletions
diff --git a/sound/soc/davinci/davinci-pcm.c b/sound/soc/davinci/davinci-pcm.c index 9d35b8c1a62..a49e667373b 100644 --- a/sound/soc/davinci/davinci-pcm.c +++ b/sound/soc/davinci/davinci-pcm.c | |||
@@ -46,11 +46,28 @@ static void print_buf_info(int slot, char *name) | |||
46 | } | 46 | } |
47 | #endif | 47 | #endif |
48 | 48 | ||
49 | #define DAVINCI_PCM_FMTBITS (\ | ||
50 | SNDRV_PCM_FMTBIT_S8 |\ | ||
51 | SNDRV_PCM_FMTBIT_U8 |\ | ||
52 | SNDRV_PCM_FMTBIT_S16_LE |\ | ||
53 | SNDRV_PCM_FMTBIT_S16_BE |\ | ||
54 | SNDRV_PCM_FMTBIT_U16_LE |\ | ||
55 | SNDRV_PCM_FMTBIT_U16_BE |\ | ||
56 | SNDRV_PCM_FMTBIT_S24_LE |\ | ||
57 | SNDRV_PCM_FMTBIT_S24_BE |\ | ||
58 | SNDRV_PCM_FMTBIT_U24_LE |\ | ||
59 | SNDRV_PCM_FMTBIT_U24_BE |\ | ||
60 | SNDRV_PCM_FMTBIT_S32_LE |\ | ||
61 | SNDRV_PCM_FMTBIT_S32_BE |\ | ||
62 | SNDRV_PCM_FMTBIT_U32_LE |\ | ||
63 | SNDRV_PCM_FMTBIT_U32_BE) | ||
64 | |||
49 | static struct snd_pcm_hardware pcm_hardware_playback = { | 65 | static struct snd_pcm_hardware pcm_hardware_playback = { |
50 | .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | | 66 | .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | |
51 | SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID | | 67 | SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID | |
52 | SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME), | 68 | SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME| |
53 | .formats = (SNDRV_PCM_FMTBIT_S16_LE), | 69 | SNDRV_PCM_INFO_BATCH), |
70 | .formats = DAVINCI_PCM_FMTBITS, | ||
54 | .rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | | 71 | .rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | |
55 | SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 | | 72 | SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 | |
56 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | | 73 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | |
@@ -59,7 +76,7 @@ static struct snd_pcm_hardware pcm_hardware_playback = { | |||
59 | .rate_min = 8000, | 76 | .rate_min = 8000, |
60 | .rate_max = 96000, | 77 | .rate_max = 96000, |
61 | .channels_min = 2, | 78 | .channels_min = 2, |
62 | .channels_max = 2, | 79 | .channels_max = 384, |
63 | .buffer_bytes_max = 128 * 1024, | 80 | .buffer_bytes_max = 128 * 1024, |
64 | .period_bytes_min = 32, | 81 | .period_bytes_min = 32, |
65 | .period_bytes_max = 8 * 1024, | 82 | .period_bytes_max = 8 * 1024, |
@@ -71,8 +88,9 @@ static struct snd_pcm_hardware pcm_hardware_playback = { | |||
71 | static struct snd_pcm_hardware pcm_hardware_capture = { | 88 | static struct snd_pcm_hardware pcm_hardware_capture = { |
72 | .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | | 89 | .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | |
73 | SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID | | 90 | SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID | |
74 | SNDRV_PCM_INFO_PAUSE), | 91 | SNDRV_PCM_INFO_PAUSE | |
75 | .formats = (SNDRV_PCM_FMTBIT_S16_LE), | 92 | SNDRV_PCM_INFO_BATCH), |
93 | .formats = DAVINCI_PCM_FMTBITS, | ||
76 | .rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | | 94 | .rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | |
77 | SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 | | 95 | SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 | |
78 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | | 96 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | |
@@ -81,7 +99,7 @@ static struct snd_pcm_hardware pcm_hardware_capture = { | |||
81 | .rate_min = 8000, | 99 | .rate_min = 8000, |
82 | .rate_max = 96000, | 100 | .rate_max = 96000, |
83 | .channels_min = 2, | 101 | .channels_min = 2, |
84 | .channels_max = 2, | 102 | .channels_max = 384, |
85 | .buffer_bytes_max = 128 * 1024, | 103 | .buffer_bytes_max = 128 * 1024, |
86 | .period_bytes_min = 32, | 104 | .period_bytes_min = 32, |
87 | .period_bytes_max = 8 * 1024, | 105 | .period_bytes_max = 8 * 1024, |
@@ -139,6 +157,22 @@ struct davinci_runtime_data { | |||
139 | struct edmacc_param ram_params; | 157 | struct edmacc_param ram_params; |
140 | }; | 158 | }; |
141 | 159 | ||
160 | static void davinci_pcm_period_elapsed(struct snd_pcm_substream *substream) | ||
161 | { | ||
162 | struct davinci_runtime_data *prtd = substream->runtime->private_data; | ||
163 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
164 | |||
165 | prtd->period++; | ||
166 | if (unlikely(prtd->period >= runtime->periods)) | ||
167 | prtd->period = 0; | ||
168 | } | ||
169 | |||
170 | static void davinci_pcm_period_reset(struct snd_pcm_substream *substream) | ||
171 | { | ||
172 | struct davinci_runtime_data *prtd = substream->runtime->private_data; | ||
173 | |||
174 | prtd->period = 0; | ||
175 | } | ||
142 | /* | 176 | /* |
143 | * Not used with ping/pong | 177 | * Not used with ping/pong |
144 | */ | 178 | */ |
@@ -199,10 +233,6 @@ static void davinci_pcm_enqueue_dma(struct snd_pcm_substream *substream) | |||
199 | else | 233 | else |
200 | edma_set_transfer_params(link, acnt, fifo_level, count, | 234 | edma_set_transfer_params(link, acnt, fifo_level, count, |
201 | fifo_level, ABSYNC); | 235 | fifo_level, ABSYNC); |
202 | |||
203 | prtd->period++; | ||
204 | if (unlikely(prtd->period >= runtime->periods)) | ||
205 | prtd->period = 0; | ||
206 | } | 236 | } |
207 | 237 | ||
208 | static void davinci_pcm_dma_irq(unsigned link, u16 ch_status, void *data) | 238 | static void davinci_pcm_dma_irq(unsigned link, u16 ch_status, void *data) |
@@ -217,12 +247,13 @@ static void davinci_pcm_dma_irq(unsigned link, u16 ch_status, void *data) | |||
217 | return; | 247 | return; |
218 | 248 | ||
219 | if (snd_pcm_running(substream)) { | 249 | if (snd_pcm_running(substream)) { |
250 | spin_lock(&prtd->lock); | ||
220 | if (prtd->ram_channel < 0) { | 251 | if (prtd->ram_channel < 0) { |
221 | /* No ping/pong must fix up link dma data*/ | 252 | /* No ping/pong must fix up link dma data*/ |
222 | spin_lock(&prtd->lock); | ||
223 | davinci_pcm_enqueue_dma(substream); | 253 | davinci_pcm_enqueue_dma(substream); |
224 | spin_unlock(&prtd->lock); | ||
225 | } | 254 | } |
255 | davinci_pcm_period_elapsed(substream); | ||
256 | spin_unlock(&prtd->lock); | ||
226 | snd_pcm_period_elapsed(substream); | 257 | snd_pcm_period_elapsed(substream); |
227 | } | 258 | } |
228 | } | 259 | } |
@@ -425,7 +456,8 @@ static int request_ping_pong(struct snd_pcm_substream *substream, | |||
425 | 456 | ||
426 | edma_read_slot(link, &prtd->asp_params); | 457 | edma_read_slot(link, &prtd->asp_params); |
427 | prtd->asp_params.opt &= ~(TCCMODE | EDMA_TCC(0x3f) | TCINTEN); | 458 | prtd->asp_params.opt &= ~(TCCMODE | EDMA_TCC(0x3f) | TCINTEN); |
428 | prtd->asp_params.opt |= TCCHEN | EDMA_TCC(prtd->ram_channel & 0x3f); | 459 | prtd->asp_params.opt |= TCCHEN | |
460 | EDMA_TCC(prtd->ram_channel & 0x3f); | ||
429 | edma_write_slot(link, &prtd->asp_params); | 461 | edma_write_slot(link, &prtd->asp_params); |
430 | 462 | ||
431 | /* pong */ | 463 | /* pong */ |
@@ -439,7 +471,7 @@ static int request_ping_pong(struct snd_pcm_substream *substream, | |||
439 | prtd->asp_params.opt &= ~(TCCMODE | EDMA_TCC(0x3f)); | 471 | prtd->asp_params.opt &= ~(TCCMODE | EDMA_TCC(0x3f)); |
440 | /* interrupt after every pong completion */ | 472 | /* interrupt after every pong completion */ |
441 | prtd->asp_params.opt |= TCINTEN | TCCHEN | | 473 | prtd->asp_params.opt |= TCINTEN | TCCHEN | |
442 | EDMA_TCC(EDMA_CHAN_SLOT(prtd->ram_channel)); | 474 | EDMA_TCC(prtd->ram_channel & 0x3f); |
443 | edma_write_slot(link, &prtd->asp_params); | 475 | edma_write_slot(link, &prtd->asp_params); |
444 | 476 | ||
445 | /* ram */ | 477 | /* ram */ |
@@ -527,6 +559,13 @@ static int davinci_pcm_trigger(struct snd_pcm_substream *substream, int cmd) | |||
527 | 559 | ||
528 | switch (cmd) { | 560 | switch (cmd) { |
529 | case SNDRV_PCM_TRIGGER_START: | 561 | case SNDRV_PCM_TRIGGER_START: |
562 | edma_start(prtd->asp_channel); | ||
563 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && | ||
564 | prtd->ram_channel >= 0) { | ||
565 | /* copy 1st iram buffer */ | ||
566 | edma_start(prtd->ram_channel); | ||
567 | } | ||
568 | break; | ||
530 | case SNDRV_PCM_TRIGGER_RESUME: | 569 | case SNDRV_PCM_TRIGGER_RESUME: |
531 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | 570 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: |
532 | edma_resume(prtd->asp_channel); | 571 | edma_resume(prtd->asp_channel); |
@@ -550,6 +589,7 @@ static int davinci_pcm_prepare(struct snd_pcm_substream *substream) | |||
550 | { | 589 | { |
551 | struct davinci_runtime_data *prtd = substream->runtime->private_data; | 590 | struct davinci_runtime_data *prtd = substream->runtime->private_data; |
552 | 591 | ||
592 | davinci_pcm_period_reset(substream); | ||
553 | if (prtd->ram_channel >= 0) { | 593 | if (prtd->ram_channel >= 0) { |
554 | int ret = ping_pong_dma_setup(substream); | 594 | int ret = ping_pong_dma_setup(substream); |
555 | if (ret < 0) | 595 | if (ret < 0) |
@@ -565,21 +605,31 @@ static int davinci_pcm_prepare(struct snd_pcm_substream *substream) | |||
565 | print_buf_info(prtd->asp_link[0], "asp_link[0]"); | 605 | print_buf_info(prtd->asp_link[0], "asp_link[0]"); |
566 | print_buf_info(prtd->asp_link[1], "asp_link[1]"); | 606 | print_buf_info(prtd->asp_link[1], "asp_link[1]"); |
567 | 607 | ||
568 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | 608 | /* |
569 | /* copy 1st iram buffer */ | 609 | * There is a phase offset of 2 periods between the position |
570 | edma_start(prtd->ram_channel); | 610 | * used by dma setup and the position reported in the pointer |
571 | } | 611 | * function. |
572 | edma_start(prtd->asp_channel); | 612 | * |
613 | * The phase offset, when not using ping-pong buffers, is due to | ||
614 | * the two consecutive calls to davinci_pcm_enqueue_dma() below. | ||
615 | * | ||
616 | * Whereas here, with ping-pong buffers, the phase is due to | ||
617 | * there being an entire buffer transfer complete before the | ||
618 | * first dma completion event triggers davinci_pcm_dma_irq(). | ||
619 | */ | ||
620 | davinci_pcm_period_elapsed(substream); | ||
621 | davinci_pcm_period_elapsed(substream); | ||
622 | |||
573 | return 0; | 623 | return 0; |
574 | } | 624 | } |
575 | prtd->period = 0; | ||
576 | davinci_pcm_enqueue_dma(substream); | 625 | davinci_pcm_enqueue_dma(substream); |
626 | davinci_pcm_period_elapsed(substream); | ||
577 | 627 | ||
578 | /* Copy self-linked parameter RAM entry into master channel */ | 628 | /* Copy self-linked parameter RAM entry into master channel */ |
579 | edma_read_slot(prtd->asp_link[0], &prtd->asp_params); | 629 | edma_read_slot(prtd->asp_link[0], &prtd->asp_params); |
580 | edma_write_slot(prtd->asp_channel, &prtd->asp_params); | 630 | edma_write_slot(prtd->asp_channel, &prtd->asp_params); |
581 | davinci_pcm_enqueue_dma(substream); | 631 | davinci_pcm_enqueue_dma(substream); |
582 | edma_start(prtd->asp_channel); | 632 | davinci_pcm_period_elapsed(substream); |
583 | 633 | ||
584 | return 0; | 634 | return 0; |
585 | } | 635 | } |
@@ -591,51 +641,23 @@ davinci_pcm_pointer(struct snd_pcm_substream *substream) | |||
591 | struct davinci_runtime_data *prtd = runtime->private_data; | 641 | struct davinci_runtime_data *prtd = runtime->private_data; |
592 | unsigned int offset; | 642 | unsigned int offset; |
593 | int asp_count; | 643 | int asp_count; |
594 | dma_addr_t asp_src, asp_dst; | 644 | unsigned int period_size = snd_pcm_lib_period_bytes(substream); |
595 | 645 | ||
646 | /* | ||
647 | * There is a phase offset of 2 periods between the position used by dma | ||
648 | * setup and the position reported in the pointer function. Either +2 in | ||
649 | * the dma setup or -2 here in the pointer function (with wrapping, | ||
650 | * both) accounts for this offset -- choose the latter since it makes | ||
651 | * the first-time setup clearer. | ||
652 | */ | ||
596 | spin_lock(&prtd->lock); | 653 | spin_lock(&prtd->lock); |
597 | if (prtd->ram_channel >= 0) { | 654 | asp_count = prtd->period - 2; |
598 | int ram_count; | ||
599 | int mod_ram; | ||
600 | dma_addr_t ram_src, ram_dst; | ||
601 | unsigned int period_size = snd_pcm_lib_period_bytes(substream); | ||
602 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | ||
603 | /* reading ram before asp should be safe | ||
604 | * as long as the asp transfers less than a ping size | ||
605 | * of bytes between the 2 reads | ||
606 | */ | ||
607 | edma_get_position(prtd->ram_channel, | ||
608 | &ram_src, &ram_dst); | ||
609 | edma_get_position(prtd->asp_channel, | ||
610 | &asp_src, &asp_dst); | ||
611 | asp_count = asp_src - prtd->asp_params.src; | ||
612 | ram_count = ram_src - prtd->ram_params.src; | ||
613 | mod_ram = ram_count % period_size; | ||
614 | mod_ram -= asp_count; | ||
615 | if (mod_ram < 0) | ||
616 | mod_ram += period_size; | ||
617 | else if (mod_ram == 0) { | ||
618 | if (snd_pcm_running(substream)) | ||
619 | mod_ram += period_size; | ||
620 | } | ||
621 | ram_count -= mod_ram; | ||
622 | if (ram_count < 0) | ||
623 | ram_count += period_size * runtime->periods; | ||
624 | } else { | ||
625 | edma_get_position(prtd->ram_channel, | ||
626 | &ram_src, &ram_dst); | ||
627 | ram_count = ram_dst - prtd->ram_params.dst; | ||
628 | } | ||
629 | asp_count = ram_count; | ||
630 | } else { | ||
631 | edma_get_position(prtd->asp_channel, &asp_src, &asp_dst); | ||
632 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
633 | asp_count = asp_src - runtime->dma_addr; | ||
634 | else | ||
635 | asp_count = asp_dst - runtime->dma_addr; | ||
636 | } | ||
637 | spin_unlock(&prtd->lock); | 655 | spin_unlock(&prtd->lock); |
638 | 656 | ||
657 | if (asp_count < 0) | ||
658 | asp_count += runtime->periods; | ||
659 | asp_count *= period_size; | ||
660 | |||
639 | offset = bytes_to_frames(runtime, asp_count); | 661 | offset = bytes_to_frames(runtime, asp_count); |
640 | if (offset >= runtime->buffer_size) | 662 | if (offset >= runtime->buffer_size) |
641 | offset = 0; | 663 | offset = 0; |
@@ -811,9 +833,11 @@ static void davinci_pcm_free(struct snd_pcm *pcm) | |||
811 | 833 | ||
812 | static u64 davinci_pcm_dmamask = 0xffffffff; | 834 | static u64 davinci_pcm_dmamask = 0xffffffff; |
813 | 835 | ||
814 | static int davinci_pcm_new(struct snd_card *card, | 836 | static int davinci_pcm_new(struct snd_soc_pcm_runtime *rtd) |
815 | struct snd_soc_dai *dai, struct snd_pcm *pcm) | ||
816 | { | 837 | { |
838 | struct snd_card *card = rtd->card->snd_card; | ||
839 | struct snd_soc_dai *dai = rtd->cpu_dai; | ||
840 | struct snd_pcm *pcm = rtd->pcm; | ||
817 | int ret; | 841 | int ret; |
818 | 842 | ||
819 | if (!card->dev->dma_mask) | 843 | if (!card->dev->dma_mask) |
diff --git a/sound/soc/davinci/davinci-vcif.c b/sound/soc/davinci/davinci-vcif.c index 9259f1f3489..1f11525d97e 100644 --- a/sound/soc/davinci/davinci-vcif.c +++ b/sound/soc/davinci/davinci-vcif.c | |||
@@ -62,9 +62,9 @@ static void davinci_vcif_start(struct snd_pcm_substream *substream) | |||
62 | w = readl(davinci_vc->base + DAVINCI_VC_CTRL); | 62 | w = readl(davinci_vc->base + DAVINCI_VC_CTRL); |
63 | 63 | ||
64 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | 64 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) |
65 | MOD_REG_BIT(w, DAVINCI_VC_CTRL_RSTDAC, 1); | 65 | MOD_REG_BIT(w, DAVINCI_VC_CTRL_RSTDAC, 0); |
66 | else | 66 | else |
67 | MOD_REG_BIT(w, DAVINCI_VC_CTRL_RSTADC, 1); | 67 | MOD_REG_BIT(w, DAVINCI_VC_CTRL_RSTADC, 0); |
68 | 68 | ||
69 | writel(w, davinci_vc->base + DAVINCI_VC_CTRL); | 69 | writel(w, davinci_vc->base + DAVINCI_VC_CTRL); |
70 | } | 70 | } |
@@ -80,9 +80,9 @@ static void davinci_vcif_stop(struct snd_pcm_substream *substream) | |||
80 | /* Reset transmitter/receiver and sample rate/frame sync generators */ | 80 | /* Reset transmitter/receiver and sample rate/frame sync generators */ |
81 | w = readl(davinci_vc->base + DAVINCI_VC_CTRL); | 81 | w = readl(davinci_vc->base + DAVINCI_VC_CTRL); |
82 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | 82 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) |
83 | MOD_REG_BIT(w, DAVINCI_VC_CTRL_RSTDAC, 0); | 83 | MOD_REG_BIT(w, DAVINCI_VC_CTRL_RSTDAC, 1); |
84 | else | 84 | else |
85 | MOD_REG_BIT(w, DAVINCI_VC_CTRL_RSTADC, 0); | 85 | MOD_REG_BIT(w, DAVINCI_VC_CTRL_RSTADC, 1); |
86 | 86 | ||
87 | writel(w, davinci_vc->base + DAVINCI_VC_CTRL); | 87 | writel(w, davinci_vc->base + DAVINCI_VC_CTRL); |
88 | } | 88 | } |
@@ -159,6 +159,7 @@ static int davinci_vcif_trigger(struct snd_pcm_substream *substream, int cmd, | |||
159 | case SNDRV_PCM_TRIGGER_RESUME: | 159 | case SNDRV_PCM_TRIGGER_RESUME: |
160 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | 160 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: |
161 | davinci_vcif_start(substream); | 161 | davinci_vcif_start(substream); |
162 | break; | ||
162 | case SNDRV_PCM_TRIGGER_STOP: | 163 | case SNDRV_PCM_TRIGGER_STOP: |
163 | case SNDRV_PCM_TRIGGER_SUSPEND: | 164 | case SNDRV_PCM_TRIGGER_SUSPEND: |
164 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | 165 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: |