Skip to content

Commit 3b196c3

Browse files
takaswietiwai
authored andcommitted
ALSA: firewire-lib: add no-header packet processing
As long as investigating Fireface 400, IEC 61883-1/6 is not applied to its packet streaming protocol. Remarks of the specific protocol are: * Each packet doesn't include CIP headers. * 64,0 and 128,0 kHz are supported. * The device doesn't necessarily transmit 8,000 packets per second. * 0, 1, 2, 3 are used as tag for rx isochronous packets, however 0 is used for tx isochronous packets. On the other hand, there's a common feature. The number of data blocks transferred in a second is the same as sampling transmission frequency. Current ALSA IEC 61883-1/6 engine already has a method to calculate it and this driver can utilize it for rx packets, as well as tx packets. This commit adds support for the transferring protocol. CIP_NO_HEADERS flag is newly added. When this flag is set: * Both of 0 (without CIP header) and 1 (with CIP header) are used as tag to handle incoming isochronous packet. * 0 (without CIP header) is used as tag to transfer outgoing isochronous packet. * Skip CIP header evaluation. * Use unique way to calculate the quadlets of isochronous packet payload. In ALSA PCM interface, 128.0 kHz is not supported, and the ALSA IEC 61883-1/6 engine doesn't support 64.0 kHz. These modes are dropped. The sequence of rx packet has a remarkable quirk about tag. This will be described in later commits. Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp> Signed-off-by: Takashi Iwai <tiwai@suse.de>
1 parent ff0fb5a commit 3b196c3

File tree

2 files changed

+81
-5
lines changed

2 files changed

+81
-5
lines changed

sound/firewire/amdtp-stream.c

Lines changed: 75 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727

2828
/* isochronous header parameters */
2929
#define ISO_DATA_LENGTH_SHIFT 16
30+
#define TAG_NO_CIP_HEADER 0
3031
#define TAG_CIP 1
3132

3233
/* common isochronous packet header parameters */
@@ -234,11 +235,15 @@ EXPORT_SYMBOL(amdtp_stream_set_parameters);
234235
unsigned int amdtp_stream_get_max_payload(struct amdtp_stream *s)
235236
{
236237
unsigned int multiplier = 1;
238+
unsigned int header_size = 0;
237239

238240
if (s->flags & CIP_JUMBO_PAYLOAD)
239241
multiplier = 5;
242+
if (!(s->flags & CIP_NO_HEADER))
243+
header_size = 8;
240244

241-
return 8 + s->syt_interval * s->data_block_quadlets * 4 * multiplier;
245+
return header_size +
246+
s->syt_interval * s->data_block_quadlets * 4 * multiplier;
242247
}
243248
EXPORT_SYMBOL(amdtp_stream_get_max_payload);
244249

@@ -380,7 +385,7 @@ static int queue_packet(struct amdtp_stream *s, unsigned int header_length,
380385
goto end;
381386

382387
p.interrupt = IS_ALIGNED(s->packet_index + 1, INTERRUPT_INTERVAL);
383-
p.tag = TAG_CIP;
388+
p.tag = s->tag;
384389
p.header_length = header_length;
385390
if (payload_length > 0)
386391
p.payload_length = payload_length;
@@ -457,6 +462,34 @@ static int handle_out_packet(struct amdtp_stream *s,
457462
return 0;
458463
}
459464

465+
static int handle_out_packet_without_header(struct amdtp_stream *s,
466+
unsigned int payload_length, unsigned int cycle,
467+
unsigned int index)
468+
{
469+
__be32 *buffer;
470+
unsigned int syt;
471+
unsigned int data_blocks;
472+
unsigned int pcm_frames;
473+
struct snd_pcm_substream *pcm;
474+
475+
buffer = s->buffer.packets[s->packet_index].buffer;
476+
syt = calculate_syt(s, cycle);
477+
data_blocks = calculate_data_blocks(s, syt);
478+
pcm_frames = s->process_data_blocks(s, buffer, data_blocks, &syt);
479+
s->data_block_counter = (s->data_block_counter + data_blocks) & 0xff;
480+
481+
payload_length = data_blocks * 4 * s->data_block_quadlets;
482+
if (queue_out_packet(s, payload_length) < 0)
483+
return -EIO;
484+
485+
pcm = ACCESS_ONCE(s->pcm);
486+
if (pcm && pcm_frames > 0)
487+
update_pcm_pointers(s, pcm, pcm_frames);
488+
489+
/* No need to return the number of handled data blocks. */
490+
return 0;
491+
}
492+
460493
static int handle_in_packet(struct amdtp_stream *s,
461494
unsigned int payload_length, unsigned int cycle,
462495
unsigned int index)
@@ -573,6 +606,30 @@ static int handle_in_packet(struct amdtp_stream *s,
573606
return 0;
574607
}
575608

609+
static int handle_in_packet_without_header(struct amdtp_stream *s,
610+
unsigned int payload_quadlets, unsigned int cycle,
611+
unsigned int index)
612+
{
613+
__be32 *buffer;
614+
unsigned int data_blocks;
615+
struct snd_pcm_substream *pcm;
616+
unsigned int pcm_frames;
617+
618+
buffer = s->buffer.packets[s->packet_index].buffer;
619+
data_blocks = payload_quadlets / s->data_block_quadlets;
620+
pcm_frames = s->process_data_blocks(s, buffer, data_blocks, NULL);
621+
s->data_block_counter = (s->data_block_counter + data_blocks) & 0xff;
622+
623+
if (queue_in_packet(s) < 0)
624+
return -EIO;
625+
626+
pcm = ACCESS_ONCE(s->pcm);
627+
if (pcm && pcm_frames > 0)
628+
update_pcm_pointers(s, pcm, pcm_frames);
629+
630+
return 0;
631+
}
632+
576633
/*
577634
* In CYCLE_TIMER register of IEEE 1394, 7 bits are used to represent second. On
578635
* the other hand, in DMA descriptors of 1394 OHCI, 3 bits are used to represent
@@ -616,7 +673,7 @@ static void out_stream_callback(struct fw_iso_context *context, u32 tstamp,
616673

617674
for (i = 0; i < packets; ++i) {
618675
cycle = increment_cycle_count(cycle, 1);
619-
if (handle_out_packet(s, 0, cycle, i) < 0) {
676+
if (s->handle_packet(s, 0, cycle, i) < 0) {
620677
s->packet_index = -1;
621678
amdtp_stream_pcm_abort(s);
622679
return;
@@ -663,7 +720,7 @@ static void in_stream_callback(struct fw_iso_context *context, u32 tstamp,
663720
break;
664721
}
665722

666-
if (handle_in_packet(s, payload_length, cycle, i) < 0)
723+
if (s->handle_packet(s, payload_length, cycle, i) < 0)
667724
break;
668725
}
669726

@@ -699,10 +756,18 @@ static void amdtp_stream_first_callback(struct fw_iso_context *context,
699756
packets = header_length / IN_PACKET_HEADER_SIZE;
700757
cycle = decrement_cycle_count(cycle, packets);
701758
context->callback.sc = in_stream_callback;
759+
if (s->flags & CIP_NO_HEADER)
760+
s->handle_packet = handle_in_packet_without_header;
761+
else
762+
s->handle_packet = handle_in_packet;
702763
} else {
703764
packets = header_length / 4;
704765
cycle = increment_cycle_count(cycle, QUEUE_LENGTH - packets);
705766
context->callback.sc = out_stream_callback;
767+
if (s->flags & CIP_NO_HEADER)
768+
s->handle_packet = handle_out_packet_without_header;
769+
else
770+
s->handle_packet = handle_out_packet;
706771
}
707772

708773
s->start_cycle = cycle;
@@ -782,6 +847,11 @@ int amdtp_stream_start(struct amdtp_stream *s, int channel, int speed)
782847

783848
amdtp_stream_update(s);
784849

850+
if (s->flags & CIP_NO_HEADER)
851+
s->tag = TAG_NO_CIP_HEADER;
852+
else
853+
s->tag = TAG_CIP;
854+
785855
s->packet_index = 0;
786856
do {
787857
if (s->direction == AMDTP_IN_STREAM)
@@ -794,7 +864,7 @@ int amdtp_stream_start(struct amdtp_stream *s, int channel, int speed)
794864

795865
/* NOTE: TAG1 matches CIP. This just affects in stream. */
796866
tag = FW_ISO_CONTEXT_MATCH_TAG1;
797-
if (s->flags & CIP_EMPTY_WITH_TAG0)
867+
if ((s->flags & CIP_EMPTY_WITH_TAG0) || (s->flags & CIP_NO_HEADER))
798868
tag |= FW_ISO_CONTEXT_MATCH_TAG0;
799869

800870
s->callbacked = false;

sound/firewire/amdtp-stream.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
* allows 5 times as large as IEC 61883-6 defines.
3232
* @CIP_HEADER_WITHOUT_EOH: Only for in-stream. CIP Header doesn't include
3333
* valid EOH.
34+
* @CIP_NO_HEADERS: a lack of headers in packets
3435
*/
3536
enum cip_flags {
3637
CIP_NONBLOCKING = 0x00,
@@ -42,6 +43,7 @@ enum cip_flags {
4243
CIP_EMPTY_HAS_WRONG_DBC = 0x20,
4344
CIP_JUMBO_PAYLOAD = 0x40,
4445
CIP_HEADER_WITHOUT_EOH = 0x80,
46+
CIP_NO_HEADER = 0x100,
4547
};
4648

4749
/**
@@ -104,6 +106,10 @@ struct amdtp_stream {
104106
struct fw_iso_context *context;
105107
struct iso_packets_buffer buffer;
106108
int packet_index;
109+
int tag;
110+
int (*handle_packet)(struct amdtp_stream *s,
111+
unsigned int payload_quadlets, unsigned int cycle,
112+
unsigned int index);
107113

108114
/* For CIP headers. */
109115
unsigned int source_node_id_field;

0 commit comments

Comments
 (0)