Commit c8bdf49b authored by Takashi Sakamoto's avatar Takashi Sakamoto Committed by Takashi Iwai
Browse files

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: default avatarTakashi Sakamoto <o-takashi@sakamocchi.jp>
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent 7ab56645
...@@ -620,6 +620,7 @@ static void handle_in_packet(struct amdtp_stream *s, ...@@ -620,6 +620,7 @@ static void handle_in_packet(struct amdtp_stream *s,
u32 cip_header[2]; u32 cip_header[2];
unsigned int data_blocks, data_block_quadlets, data_block_counter; unsigned int data_blocks, data_block_quadlets, data_block_counter;
struct snd_pcm_substream *pcm = NULL; struct snd_pcm_substream *pcm = NULL;
bool lost;
cip_header[0] = be32_to_cpu(buffer[0]); cip_header[0] = be32_to_cpu(buffer[0]);
cip_header[1] = be32_to_cpu(buffer[1]); cip_header[1] = be32_to_cpu(buffer[1]);
...@@ -658,7 +659,13 @@ static void handle_in_packet(struct amdtp_stream *s, ...@@ -658,7 +659,13 @@ static void handle_in_packet(struct amdtp_stream *s,
/* Check data block counter continuity */ /* Check data block counter continuity */
data_block_counter = cip_header[0] & AMDTP_DBC_MASK; data_block_counter = cip_header[0] & AMDTP_DBC_MASK;
if (data_block_counter != s->data_block_counter) { if (!(s->flags & CIP_DBC_IS_END_EVENT))
lost = data_block_counter != s->data_block_counter;
else
lost = data_block_counter !=
((s->data_block_counter + data_blocks) & 0xff);
if (lost) {
dev_info(&s->unit->device, dev_info(&s->unit->device,
"Detect discontinuity of CIP: %02X %02X\n", "Detect discontinuity of CIP: %02X %02X\n",
s->data_block_counter, data_block_counter); s->data_block_counter, data_block_counter);
...@@ -676,7 +683,11 @@ static void handle_in_packet(struct amdtp_stream *s, ...@@ -676,7 +683,11 @@ static void handle_in_packet(struct amdtp_stream *s,
amdtp_pull_midi(s, buffer, data_blocks); amdtp_pull_midi(s, buffer, data_blocks);
} }
s->data_block_counter = (data_block_counter + data_blocks) & 0xff; if (s->flags & CIP_DBC_IS_END_EVENT)
s->data_block_counter = data_block_counter;
else
s->data_block_counter =
(data_block_counter + data_blocks) & 0xff;
end: end:
if (queue_in_packet(s) < 0) if (queue_in_packet(s) < 0)
goto err; goto err;
......
...@@ -19,12 +19,15 @@ ...@@ -19,12 +19,15 @@
* @CIP_SYNC_TO_DEVICE: In sync to device mode, time stamp in out packets is * @CIP_SYNC_TO_DEVICE: In sync to device mode, time stamp in out packets is
* generated by in packets. Defaultly this driver generates timestamp. * generated by in packets. Defaultly this driver generates timestamp.
* @CIP_EMPTY_WITH_TAG0: Only for in-stream. Empty in-packets have TAG0. * @CIP_EMPTY_WITH_TAG0: Only for in-stream. Empty in-packets have TAG0.
* @CIP_DBC_IS_END_EVENT: Only for in-stream. The value of dbc in an in-packet
* corresponds to the end of event in the packet. Out of IEC 61883.
*/ */
enum cip_flags { enum cip_flags {
CIP_NONBLOCKING = 0x00, CIP_NONBLOCKING = 0x00,
CIP_BLOCKING = 0x01, CIP_BLOCKING = 0x01,
CIP_SYNC_TO_DEVICE = 0x02, CIP_SYNC_TO_DEVICE = 0x02,
CIP_EMPTY_WITH_TAG0 = 0x04, CIP_EMPTY_WITH_TAG0 = 0x04,
CIP_DBC_IS_END_EVENT = 0x08,
}; };
/** /**
......
...@@ -196,6 +196,8 @@ int snd_efw_stream_init_duplex(struct snd_efw *efw) ...@@ -196,6 +196,8 @@ int snd_efw_stream_init_duplex(struct snd_efw *efw)
goto end; goto end;
/* Fireworks transmits NODATA packets with TAG0. */ /* Fireworks transmits NODATA packets with TAG0. */
efw->tx_stream.flags |= CIP_EMPTY_WITH_TAG0; efw->tx_stream.flags |= CIP_EMPTY_WITH_TAG0;
/* Fireworks has its own meaning for dbc. */
efw->tx_stream.flags |= CIP_DBC_IS_END_EVENT;
err = init_stream(efw, &efw->rx_stream); err = init_stream(efw, &efw->rx_stream);
if (err < 0) { if (err < 0) {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment