diff options
Diffstat (limited to 'sound/firewire/amdtp.c')
-rw-r--r-- | sound/firewire/amdtp.c | 33 |
1 files changed, 21 insertions, 12 deletions
diff --git a/sound/firewire/amdtp.c b/sound/firewire/amdtp.c index 046007ddbcae..b18140ff2b93 100644 --- a/sound/firewire/amdtp.c +++ b/sound/firewire/amdtp.c @@ -47,6 +47,7 @@ int amdtp_out_stream_init(struct amdtp_out_stream *s, struct fw_unit *unit, s->flags = flags; s->context = ERR_PTR(-1); mutex_init(&s->mutex); + s->packet_index = 0; return 0; } @@ -316,15 +317,19 @@ static void amdtp_fill_midi(struct amdtp_out_stream *s, static void queue_out_packet(struct amdtp_out_stream *s, unsigned int cycle) { __be32 *buffer; - unsigned int data_blocks, syt, ptr; + unsigned int index, data_blocks, syt, ptr; struct snd_pcm_substream *pcm; struct fw_iso_packet packet; int err; + if (s->packet_index < 0) + return; + index = s->packet_index; + data_blocks = calculate_data_blocks(s); syt = calculate_syt(s, cycle); - buffer = s->buffer.packets[s->packet_counter].buffer; + buffer = s->buffer.packets[index].buffer; buffer[0] = cpu_to_be32(ACCESS_ONCE(s->source_node_id_field) | (s->data_block_quadlets << 16) | s->data_block_counter); @@ -343,20 +348,24 @@ static void queue_out_packet(struct amdtp_out_stream *s, unsigned int cycle) s->data_block_counter = (s->data_block_counter + data_blocks) & 0xff; packet.payload_length = 8 + data_blocks * 4 * s->data_block_quadlets; - packet.interrupt = IS_ALIGNED(s->packet_counter + 1, - INTERRUPT_INTERVAL); + packet.interrupt = IS_ALIGNED(index + 1, INTERRUPT_INTERVAL); packet.skip = 0; packet.tag = TAG_CIP; packet.sy = 0; packet.header_length = 0; err = fw_iso_context_queue(s->context, &packet, &s->buffer.iso_buffer, - s->buffer.packets[s->packet_counter].offset); - if (err < 0) + s->buffer.packets[index].offset); + if (err < 0) { dev_err(&s->unit->device, "queueing error: %d\n", err); + s->packet_index = -1; + amdtp_out_stream_pcm_abort(s); + return; + } - if (++s->packet_counter >= QUEUE_LENGTH) - s->packet_counter = 0; + if (++index >= QUEUE_LENGTH) + index = 0; + s->packet_index = index; if (pcm) { ptr = s->pcm_buffer_pointer + data_blocks; @@ -398,13 +407,13 @@ static int queue_initial_skip_packets(struct amdtp_out_stream *s) int err; for (i = 0; i < QUEUE_LENGTH; ++i) { - skip_packet.interrupt = IS_ALIGNED(s->packet_counter + 1, + skip_packet.interrupt = IS_ALIGNED(s->packet_index + 1, INTERRUPT_INTERVAL); err = fw_iso_context_queue(s->context, &skip_packet, NULL, 0); if (err < 0) return err; - if (++s->packet_counter >= QUEUE_LENGTH) - s->packet_counter = 0; + if (++s->packet_index >= QUEUE_LENGTH) + s->packet_index = 0; } return 0; @@ -469,7 +478,7 @@ int amdtp_out_stream_start(struct amdtp_out_stream *s, int channel, int speed) amdtp_out_stream_update(s); - s->packet_counter = 0; + s->packet_index = 0; s->data_block_counter = 0; err = queue_initial_skip_packets(s); if (err < 0) |