summaryrefslogtreecommitdiff
path: root/sound/firewire/amdtp-stream.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/firewire/amdtp-stream.c')
-rw-r--r--sound/firewire/amdtp-stream.c46
1 files changed, 44 insertions, 2 deletions
diff --git a/sound/firewire/amdtp-stream.c b/sound/firewire/amdtp-stream.c
index 9e6f54f8c45d..3fc581a5ad62 100644
--- a/sound/firewire/amdtp-stream.c
+++ b/sound/firewire/amdtp-stream.c
@@ -148,8 +148,27 @@ EXPORT_SYMBOL(amdtp_rate_table);
int amdtp_stream_add_pcm_hw_constraints(struct amdtp_stream *s,
struct snd_pcm_runtime *runtime)
{
+ struct snd_pcm_hardware *hw = &runtime->hw;
int err;
+ hw->info = SNDRV_PCM_INFO_BATCH |
+ SNDRV_PCM_INFO_BLOCK_TRANSFER |
+ SNDRV_PCM_INFO_INTERLEAVED |
+ SNDRV_PCM_INFO_JOINT_DUPLEX |
+ SNDRV_PCM_INFO_MMAP |
+ SNDRV_PCM_INFO_MMAP_VALID;
+
+ /* SNDRV_PCM_INFO_BATCH */
+ hw->periods_min = 2;
+ hw->periods_max = UINT_MAX;
+
+ /* bytes for a frame */
+ hw->period_bytes_min = 4 * hw->channels_max;
+
+ /* Just to prevent from allocating much pages. */
+ hw->period_bytes_max = hw->period_bytes_min * 2048;
+ hw->buffer_bytes_max = hw->period_bytes_max * hw->periods_min;
+
/*
* Currently firewire-lib processes 16 packets in one software
* interrupt callback. This equals to 2msec but actually the
@@ -682,7 +701,9 @@ static void out_stream_callback(struct fw_iso_context *context, u32 tstamp,
cycle = increment_cycle_count(cycle, 1);
if (s->handle_packet(s, 0, cycle, i) < 0) {
s->packet_index = -1;
- amdtp_stream_pcm_abort(s);
+ if (in_interrupt())
+ amdtp_stream_pcm_abort(s);
+ WRITE_ONCE(s->pcm_buffer_pointer, SNDRV_PCM_POS_XRUN);
return;
}
}
@@ -734,7 +755,9 @@ static void in_stream_callback(struct fw_iso_context *context, u32 tstamp,
/* Queueing error or detecting invalid payload. */
if (i < packets) {
s->packet_index = -1;
- amdtp_stream_pcm_abort(s);
+ if (in_interrupt())
+ amdtp_stream_pcm_abort(s);
+ WRITE_ONCE(s->pcm_buffer_pointer, SNDRV_PCM_POS_XRUN);
return;
}
@@ -929,6 +952,25 @@ unsigned long amdtp_stream_pcm_pointer(struct amdtp_stream *s)
EXPORT_SYMBOL(amdtp_stream_pcm_pointer);
/**
+ * amdtp_stream_pcm_ack - acknowledge queued PCM frames
+ * @s: the AMDTP stream that transfers the PCM frames
+ *
+ * Returns zero always.
+ */
+int amdtp_stream_pcm_ack(struct amdtp_stream *s)
+{
+ /*
+ * Process isochronous packets for recent isochronous cycle to handle
+ * queued PCM frames.
+ */
+ if (amdtp_stream_running(s))
+ fw_iso_context_flush_completions(s->context);
+
+ return 0;
+}
+EXPORT_SYMBOL(amdtp_stream_pcm_ack);
+
+/**
* amdtp_stream_update - update the stream after a bus reset
* @s: the AMDTP stream
*/