aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sound/firewire/amdtp.c229
-rw-r--r--sound/firewire/amdtp.h2
2 files changed, 214 insertions, 17 deletions
diff --git a/sound/firewire/amdtp.c b/sound/firewire/amdtp.c
index 790aa86da825..be1aabcda0d2 100644
--- a/sound/firewire/amdtp.c
+++ b/sound/firewire/amdtp.c
@@ -39,6 +39,7 @@
39 * only "Clock-based rate control mode" is supported 39 * only "Clock-based rate control mode" is supported
40 */ 40 */
41#define AMDTP_FDF_AM824 (0 << (CIP_FDF_SFC_SHIFT + 3)) 41#define AMDTP_FDF_AM824 (0 << (CIP_FDF_SFC_SHIFT + 3))
42#define AMDTP_FDF_NO_DATA 0xff
42#define AMDTP_DBS_MASK 0x00ff0000 43#define AMDTP_DBS_MASK 0x00ff0000
43#define AMDTP_DBS_SHIFT 16 44#define AMDTP_DBS_SHIFT 16
44#define AMDTP_DBC_MASK 0x000000ff 45#define AMDTP_DBC_MASK 0x000000ff
@@ -47,6 +48,7 @@
47#define INTERRUPT_INTERVAL 16 48#define INTERRUPT_INTERVAL 16
48#define QUEUE_LENGTH 48 49#define QUEUE_LENGTH 48
49 50
51#define IN_PACKET_HEADER_SIZE 4
50#define OUT_PACKET_HEADER_SIZE 0 52#define OUT_PACKET_HEADER_SIZE 0
51 53
52static void pcm_period_tasklet(unsigned long data); 54static void pcm_period_tasklet(unsigned long data);
@@ -179,6 +181,12 @@ static void amdtp_write_s16_dualwire(struct amdtp_stream *s,
179static void amdtp_write_s32_dualwire(struct amdtp_stream *s, 181static void amdtp_write_s32_dualwire(struct amdtp_stream *s,
180 struct snd_pcm_substream *pcm, 182 struct snd_pcm_substream *pcm,
181 __be32 *buffer, unsigned int frames); 183 __be32 *buffer, unsigned int frames);
184static void amdtp_read_s32(struct amdtp_stream *s,
185 struct snd_pcm_substream *pcm,
186 __be32 *buffer, unsigned int frames);
187static void amdtp_read_s32_dualwire(struct amdtp_stream *s,
188 struct snd_pcm_substream *pcm,
189 __be32 *buffer, unsigned int frames);
182 190
183/** 191/**
184 * amdtp_stream_set_pcm_format - set the PCM format 192 * amdtp_stream_set_pcm_format - set the PCM format
@@ -200,16 +208,27 @@ void amdtp_stream_set_pcm_format(struct amdtp_stream *s,
200 WARN_ON(1); 208 WARN_ON(1);
201 /* fall through */ 209 /* fall through */
202 case SNDRV_PCM_FORMAT_S16: 210 case SNDRV_PCM_FORMAT_S16:
203 if (s->dual_wire) 211 if (s->direction == AMDTP_OUT_STREAM) {
204 s->transfer_samples = amdtp_write_s16_dualwire; 212 if (s->dual_wire)
205 else 213 s->transfer_samples = amdtp_write_s16_dualwire;
206 s->transfer_samples = amdtp_write_s16; 214 else
207 break; 215 s->transfer_samples = amdtp_write_s16;
216 break;
217 }
218 WARN_ON(1);
219 /* fall through */
208 case SNDRV_PCM_FORMAT_S32: 220 case SNDRV_PCM_FORMAT_S32:
209 if (s->dual_wire) 221 if (s->direction == AMDTP_OUT_STREAM) {
210 s->transfer_samples = amdtp_write_s32_dualwire; 222 if (s->dual_wire)
211 else 223 s->transfer_samples = amdtp_write_s32_dualwire;
212 s->transfer_samples = amdtp_write_s32; 224 else
225 s->transfer_samples = amdtp_write_s32;
226 } else {
227 if (s->dual_wire)
228 s->transfer_samples = amdtp_read_s32_dualwire;
229 else
230 s->transfer_samples = amdtp_read_s32;
231 }
213 break; 232 break;
214 } 233 }
215} 234}
@@ -420,6 +439,59 @@ static void amdtp_write_s16_dualwire(struct amdtp_stream *s,
420 } 439 }
421} 440}
422 441
442static void amdtp_read_s32(struct amdtp_stream *s,
443 struct snd_pcm_substream *pcm,
444 __be32 *buffer, unsigned int frames)
445{
446 struct snd_pcm_runtime *runtime = pcm->runtime;
447 unsigned int channels, remaining_frames, i, c;
448 u32 *dst;
449
450 channels = s->pcm_channels;
451 dst = (void *)runtime->dma_area +
452 frames_to_bytes(runtime, s->pcm_buffer_pointer);
453 remaining_frames = runtime->buffer_size - s->pcm_buffer_pointer;
454
455 for (i = 0; i < frames; ++i) {
456 for (c = 0; c < channels; ++c) {
457 *dst = be32_to_cpu(buffer[c]) << 8;
458 dst++;
459 }
460 buffer += s->data_block_quadlets;
461 if (--remaining_frames == 0)
462 dst = (void *)runtime->dma_area;
463 }
464}
465
466static void amdtp_read_s32_dualwire(struct amdtp_stream *s,
467 struct snd_pcm_substream *pcm,
468 __be32 *buffer, unsigned int frames)
469{
470 struct snd_pcm_runtime *runtime = pcm->runtime;
471 unsigned int channels, remaining_frames, i, c;
472 u32 *dst;
473
474 dst = (void *)runtime->dma_area +
475 frames_to_bytes(runtime, s->pcm_buffer_pointer);
476 remaining_frames = runtime->buffer_size - s->pcm_buffer_pointer;
477 channels = s->pcm_channels / 2;
478
479 for (i = 0; i < frames; ++i) {
480 for (c = 0; c < channels; ++c) {
481 *dst = be32_to_cpu(buffer[c * 2]) << 8;
482 dst++;
483 }
484 buffer += 1;
485 for (c = 0; c < channels; ++c) {
486 *dst = be32_to_cpu(buffer[c * 2]) << 8;
487 dst++;
488 }
489 buffer += s->data_block_quadlets - 1;
490 if (--remaining_frames == 0)
491 dst = (void *)runtime->dma_area;
492 }
493}
494
423static void amdtp_fill_pcm_silence(struct amdtp_stream *s, 495static void amdtp_fill_pcm_silence(struct amdtp_stream *s,
424 __be32 *buffer, unsigned int frames) 496 __be32 *buffer, unsigned int frames)
425{ 497{
@@ -504,6 +576,12 @@ static inline int queue_out_packet(struct amdtp_stream *s,
504 payload_length, skip); 576 payload_length, skip);
505} 577}
506 578
579static inline int queue_in_packet(struct amdtp_stream *s)
580{
581 return queue_packet(s, IN_PACKET_HEADER_SIZE,
582 amdtp_stream_get_max_payload(s), false);
583}
584
507static void handle_out_packet(struct amdtp_stream *s, unsigned int cycle) 585static void handle_out_packet(struct amdtp_stream *s, unsigned int cycle)
508{ 586{
509 __be32 *buffer; 587 __be32 *buffer;
@@ -552,6 +630,80 @@ static void handle_out_packet(struct amdtp_stream *s, unsigned int cycle)
552 update_pcm_pointers(s, pcm, data_blocks); 630 update_pcm_pointers(s, pcm, data_blocks);
553} 631}
554 632
633static void handle_in_packet(struct amdtp_stream *s,
634 unsigned int payload_quadlets,
635 __be32 *buffer)
636{
637 u32 cip_header[2];
638 unsigned int data_blocks, data_block_quadlets, data_block_counter;
639 struct snd_pcm_substream *pcm = NULL;
640
641 cip_header[0] = be32_to_cpu(buffer[0]);
642 cip_header[1] = be32_to_cpu(buffer[1]);
643
644 /*
645 * This module supports 'Two-quadlet CIP header with SYT field'.
646 * For convinience, also check FMT field is AM824 or not.
647 */
648 if (((cip_header[0] & CIP_EOH_MASK) == CIP_EOH) ||
649 ((cip_header[1] & CIP_EOH_MASK) != CIP_EOH) ||
650 ((cip_header[1] & CIP_FMT_MASK) != CIP_FMT_AM)) {
651 dev_info_ratelimited(&s->unit->device,
652 "Invalid CIP header for AMDTP: %08X:%08X\n",
653 cip_header[0], cip_header[1]);
654 goto end;
655 }
656
657 /* Calculate data blocks */
658 if (payload_quadlets < 3 ||
659 ((cip_header[1] & CIP_FDF_MASK) ==
660 (AMDTP_FDF_NO_DATA << CIP_FDF_SFC_SHIFT))) {
661 data_blocks = 0;
662 } else {
663 data_block_quadlets =
664 (cip_header[0] & AMDTP_DBS_MASK) >> AMDTP_DBS_SHIFT;
665 /* avoid division by zero */
666 if (data_block_quadlets == 0) {
667 dev_info_ratelimited(&s->unit->device,
668 "Detect invalid value in dbs field: %08X\n",
669 cip_header[0]);
670 goto err;
671 }
672
673 data_blocks = (payload_quadlets - 2) / data_block_quadlets;
674 }
675
676 /* Check data block counter continuity */
677 data_block_counter = cip_header[0] & AMDTP_DBC_MASK;
678 if (data_block_counter != s->data_block_counter) {
679 dev_info(&s->unit->device,
680 "Detect discontinuity of CIP: %02X %02X\n",
681 s->data_block_counter, data_block_counter);
682 goto err;
683 }
684
685 if (data_blocks > 0) {
686 buffer += 2;
687
688 pcm = ACCESS_ONCE(s->pcm);
689 if (pcm)
690 s->transfer_samples(s, pcm, buffer, data_blocks);
691 }
692
693 s->data_block_counter = (data_block_counter + data_blocks) & 0xff;
694end:
695 if (queue_in_packet(s) < 0)
696 goto err;
697
698 if (pcm)
699 update_pcm_pointers(s, pcm, data_blocks);
700
701 return;
702err:
703 s->packet_index = -1;
704 amdtp_stream_pcm_abort(s);
705}
706
555static void out_stream_callback(struct fw_iso_context *context, u32 cycle, 707static void out_stream_callback(struct fw_iso_context *context, u32 cycle,
556 size_t header_length, void *header, 708 size_t header_length, void *header,
557 void *private_data) 709 void *private_data)
@@ -571,6 +723,31 @@ static void out_stream_callback(struct fw_iso_context *context, u32 cycle,
571 fw_iso_context_queue_flush(s->context); 723 fw_iso_context_queue_flush(s->context);
572} 724}
573 725
726static void in_stream_callback(struct fw_iso_context *context, u32 cycle,
727 size_t header_length, void *header,
728 void *private_data)
729{
730 struct amdtp_stream *s = private_data;
731 unsigned int p, packets, payload_quadlets;
732 __be32 *buffer, *headers = header;
733
734 /* The number of packets in buffer */
735 packets = header_length / IN_PACKET_HEADER_SIZE;
736
737 for (p = 0; p < packets; p++) {
738 if (s->packet_index < 0)
739 return;
740 buffer = s->buffer.packets[s->packet_index].buffer;
741
742 /* The number of quadlets in this packet */
743 payload_quadlets =
744 (be32_to_cpu(headers[p]) >> ISO_DATA_LENGTH_SHIFT) / 4;
745 handle_in_packet(s, payload_quadlets, buffer);
746 }
747
748 fw_iso_context_queue_flush(s->context);
749}
750
574/** 751/**
575 * amdtp_stream_start - start transferring packets 752 * amdtp_stream_start - start transferring packets
576 * @s: the AMDTP stream to start 753 * @s: the AMDTP stream to start
@@ -595,7 +772,10 @@ int amdtp_stream_start(struct amdtp_stream *s, int channel, int speed)
595 [CIP_SFC_88200] = { 0, 67 }, 772 [CIP_SFC_88200] = { 0, 67 },
596 [CIP_SFC_176400] = { 0, 67 }, 773 [CIP_SFC_176400] = { 0, 67 },
597 }; 774 };
598 int err; 775 unsigned int header_size;
776 enum dma_data_direction dir;
777 fw_iso_callback_t cb;
778 int type, err;
599 779
600 mutex_lock(&s->mutex); 780 mutex_lock(&s->mutex);
601 781
@@ -610,16 +790,26 @@ int amdtp_stream_start(struct amdtp_stream *s, int channel, int speed)
610 s->syt_offset_state = initial_state[s->sfc].syt_offset; 790 s->syt_offset_state = initial_state[s->sfc].syt_offset;
611 s->last_syt_offset = TICKS_PER_CYCLE; 791 s->last_syt_offset = TICKS_PER_CYCLE;
612 792
793 /* initialize packet buffer */
794 if (s->direction == AMDTP_IN_STREAM) {
795 dir = DMA_FROM_DEVICE;
796 type = FW_ISO_CONTEXT_RECEIVE;
797 header_size = IN_PACKET_HEADER_SIZE;
798 cb = in_stream_callback;
799 } else {
800 dir = DMA_TO_DEVICE;
801 type = FW_ISO_CONTEXT_TRANSMIT;
802 header_size = OUT_PACKET_HEADER_SIZE;
803 cb = out_stream_callback;
804 }
613 err = iso_packets_buffer_init(&s->buffer, s->unit, QUEUE_LENGTH, 805 err = iso_packets_buffer_init(&s->buffer, s->unit, QUEUE_LENGTH,
614 amdtp_stream_get_max_payload(s), 806 amdtp_stream_get_max_payload(s), dir);
615 DMA_TO_DEVICE);
616 if (err < 0) 807 if (err < 0)
617 goto err_unlock; 808 goto err_unlock;
618 809
619 s->context = fw_iso_context_create(fw_parent_device(s->unit)->card, 810 s->context = fw_iso_context_create(fw_parent_device(s->unit)->card,
620 FW_ISO_CONTEXT_TRANSMIT, 811 type, channel, speed, header_size,
621 channel, speed, 0, 812 cb, s);
622 out_stream_callback, s);
623 if (IS_ERR(s->context)) { 813 if (IS_ERR(s->context)) {
624 err = PTR_ERR(s->context); 814 err = PTR_ERR(s->context);
625 if (err == -EBUSY) 815 if (err == -EBUSY)
@@ -632,12 +822,17 @@ int amdtp_stream_start(struct amdtp_stream *s, int channel, int speed)
632 822
633 s->packet_index = 0; 823 s->packet_index = 0;
634 do { 824 do {
635 err = queue_out_packet(s, 0, true); 825 if (s->direction == AMDTP_IN_STREAM)
826 err = queue_in_packet(s);
827 else
828 err = queue_out_packet(s, 0, true);
636 if (err < 0) 829 if (err < 0)
637 goto err_context; 830 goto err_context;
638 } while (s->packet_index > 0); 831 } while (s->packet_index > 0);
639 832
640 err = fw_iso_context_start(s->context, -1, 0, 0); 833 /* NOTE: TAG1 matches CIP. This just affects in stream. */
834 err = fw_iso_context_start(s->context, -1, 0,
835 FW_ISO_CONTEXT_MATCH_TAG1);
641 if (err < 0) 836 if (err < 0)
642 goto err_context; 837 goto err_context;
643 838
diff --git a/sound/firewire/amdtp.h b/sound/firewire/amdtp.h
index 019134edb9f7..c831aaa2a811 100644
--- a/sound/firewire/amdtp.h
+++ b/sound/firewire/amdtp.h
@@ -41,6 +41,8 @@ enum cip_sfc {
41 CIP_SFC_COUNT 41 CIP_SFC_COUNT
42}; 42};
43 43
44#define AMDTP_IN_PCM_FORMAT_BITS SNDRV_PCM_FMTBIT_S32
45
44#define AMDTP_OUT_PCM_FORMAT_BITS (SNDRV_PCM_FMTBIT_S16 | \ 46#define AMDTP_OUT_PCM_FORMAT_BITS (SNDRV_PCM_FMTBIT_S16 | \
45 SNDRV_PCM_FMTBIT_S32) 47 SNDRV_PCM_FMTBIT_S32)
46 48