aboutsummaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
authorTakashi Sakamoto <o-takashi@sakamocchi.jp>2014-04-25 09:45:04 -0400
committerTakashi Iwai <tiwai@suse.de>2014-05-26 08:24:47 -0400
commitc8bdf49b9935cdeec917347df00a5434d58e9df0 (patch)
treef178340abddc6f5527dfe4a03d2a8e9124cc3b59 /sound
parent7ab566453fe32d6745a82772a16e9bc34c5403a5 (diff)
ALSA: fireworks/firewire-lib: Add a quirk for the meaning of dbc
Fireworks has a quirk for the value of dbc field in transmitted packets. For Fireworks, dbc means the end of events in current packet. This is out of specification. For example, AudioFire4: CIP0 CIP1 Payload 01070092 90FFFFFF 02 0107009A 9001E17B 3A <- 010700A2 9001F6E5 3A 010700A2 90FFFFFF 02 010700AA 9001104F 3A <- 010700B2 900125B9 3A 010700BA 90013B23 3A 010700BA 90FFFFFF 02 010700C2 9001548E 3A <- 010700CA 900169F8 3A 010700CA 90FFFFFF 02 010700D2 90018362 3A <- 010700DA 900198CC 3A According to IEC 61883-1/6, a packet following to empty packet has the same value for its dbc. But for Fireworks, it's incremented and empty packet has the same value as previous packet in dbc field. This commit adds a flag for Fireworks and some codes to checking dbc continuity. Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp> Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound')
-rw-r--r--sound/firewire/amdtp.c15
-rw-r--r--sound/firewire/amdtp.h3
-rw-r--r--sound/firewire/fireworks/fireworks_stream.c2
3 files changed, 18 insertions, 2 deletions
diff --git a/sound/firewire/amdtp.c b/sound/firewire/amdtp.c
index dce4c6dd3f6d..51aad680886d 100644
--- a/sound/firewire/amdtp.c
+++ b/sound/firewire/amdtp.c
@@ -620,6 +620,7 @@ static void handle_in_packet(struct amdtp_stream *s,
620 u32 cip_header[2]; 620 u32 cip_header[2];
621 unsigned int data_blocks, data_block_quadlets, data_block_counter; 621 unsigned int data_blocks, data_block_quadlets, data_block_counter;
622 struct snd_pcm_substream *pcm = NULL; 622 struct snd_pcm_substream *pcm = NULL;
623 bool lost;
623 624
624 cip_header[0] = be32_to_cpu(buffer[0]); 625 cip_header[0] = be32_to_cpu(buffer[0]);
625 cip_header[1] = be32_to_cpu(buffer[1]); 626 cip_header[1] = be32_to_cpu(buffer[1]);
@@ -658,7 +659,13 @@ static void handle_in_packet(struct amdtp_stream *s,
658 659
659 /* Check data block counter continuity */ 660 /* Check data block counter continuity */
660 data_block_counter = cip_header[0] & AMDTP_DBC_MASK; 661 data_block_counter = cip_header[0] & AMDTP_DBC_MASK;
661 if (data_block_counter != s->data_block_counter) { 662 if (!(s->flags & CIP_DBC_IS_END_EVENT))
663 lost = data_block_counter != s->data_block_counter;
664 else
665 lost = data_block_counter !=
666 ((s->data_block_counter + data_blocks) & 0xff);
667
668 if (lost) {
662 dev_info(&s->unit->device, 669 dev_info(&s->unit->device,
663 "Detect discontinuity of CIP: %02X %02X\n", 670 "Detect discontinuity of CIP: %02X %02X\n",
664 s->data_block_counter, data_block_counter); 671 s->data_block_counter, data_block_counter);
@@ -676,7 +683,11 @@ static void handle_in_packet(struct amdtp_stream *s,
676 amdtp_pull_midi(s, buffer, data_blocks); 683 amdtp_pull_midi(s, buffer, data_blocks);
677 } 684 }
678 685
679 s->data_block_counter = (data_block_counter + data_blocks) & 0xff; 686 if (s->flags & CIP_DBC_IS_END_EVENT)
687 s->data_block_counter = data_block_counter;
688 else
689 s->data_block_counter =
690 (data_block_counter + data_blocks) & 0xff;
680end: 691end:
681 if (queue_in_packet(s) < 0) 692 if (queue_in_packet(s) < 0)
682 goto err; 693 goto err;
diff --git a/sound/firewire/amdtp.h b/sound/firewire/amdtp.h
index 96b96ec812b2..1ca1a193bbc0 100644
--- a/sound/firewire/amdtp.h
+++ b/sound/firewire/amdtp.h
@@ -19,12 +19,15 @@
19 * @CIP_SYNC_TO_DEVICE: In sync to device mode, time stamp in out packets is 19 * @CIP_SYNC_TO_DEVICE: In sync to device mode, time stamp in out packets is
20 * generated by in packets. Defaultly this driver generates timestamp. 20 * generated by in packets. Defaultly this driver generates timestamp.
21 * @CIP_EMPTY_WITH_TAG0: Only for in-stream. Empty in-packets have TAG0. 21 * @CIP_EMPTY_WITH_TAG0: Only for in-stream. Empty in-packets have TAG0.
22 * @CIP_DBC_IS_END_EVENT: Only for in-stream. The value of dbc in an in-packet
23 * corresponds to the end of event in the packet. Out of IEC 61883.
22 */ 24 */
23enum cip_flags { 25enum cip_flags {
24 CIP_NONBLOCKING = 0x00, 26 CIP_NONBLOCKING = 0x00,
25 CIP_BLOCKING = 0x01, 27 CIP_BLOCKING = 0x01,
26 CIP_SYNC_TO_DEVICE = 0x02, 28 CIP_SYNC_TO_DEVICE = 0x02,
27 CIP_EMPTY_WITH_TAG0 = 0x04, 29 CIP_EMPTY_WITH_TAG0 = 0x04,
30 CIP_DBC_IS_END_EVENT = 0x08,
28}; 31};
29 32
30/** 33/**
diff --git a/sound/firewire/fireworks/fireworks_stream.c b/sound/firewire/fireworks/fireworks_stream.c
index 360e871bf838..d687b047446b 100644
--- a/sound/firewire/fireworks/fireworks_stream.c
+++ b/sound/firewire/fireworks/fireworks_stream.c
@@ -196,6 +196,8 @@ int snd_efw_stream_init_duplex(struct snd_efw *efw)
196 goto end; 196 goto end;
197 /* Fireworks transmits NODATA packets with TAG0. */ 197 /* Fireworks transmits NODATA packets with TAG0. */
198 efw->tx_stream.flags |= CIP_EMPTY_WITH_TAG0; 198 efw->tx_stream.flags |= CIP_EMPTY_WITH_TAG0;
199 /* Fireworks has its own meaning for dbc. */
200 efw->tx_stream.flags |= CIP_DBC_IS_END_EVENT;
199 201
200 err = init_stream(efw, &efw->rx_stream); 202 err = init_stream(efw, &efw->rx_stream);
201 if (err < 0) { 203 if (err < 0) {