aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJay Fenlason <fenlason@redhat.com>2009-11-19 15:00:02 -0500
committerStefan Richter <stefanr@s5r6.in-berlin.de>2009-11-22 22:42:16 +0100
commitce82d255efa4d748e4ade922f71796a502a19c27 (patch)
tree5788f308ef82578fa84db013c61530dca90b8d25
parent1fb09ead370c8a35d82ae53b20afdb20ea0f0243 (diff)
downloadlibraw1394-ce82d255efa4d748e4ade922f71796a502a19c27.tar.gz
Fix reporting of isochronous transmit cycles on firewire-core
While firewire-core's iso reception ABI was fixed in its version 2 to report the cycle of each received packet to userspace like rawiso does, this same enhancement was forgotten to add to the iso transmission ABI, causing FFADO to fail to set up and maintain streaming. Since kernel commit 31769cef2e973544164aa7d0db2e2024660d5e21, we also get iso xmit cycles in fw_cdev_event_iso_interrupt.header. Pass these to the iso receive handler. In case of older kernels, calculate cycles based on the cycle of the iso interrupt event. These are inaccurate but better than nothing. Signed-off-by: Jay Fenlason <fenlason@redhat.com> Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de> (changelog, whitespace)
-rw-r--r--src/fw-iso.c56
1 files changed, 46 insertions, 10 deletions
diff --git a/src/fw-iso.c b/src/fw-iso.c
index edf2fd7..235040b 100644
--- a/src/fw-iso.c
+++ b/src/fw-iso.c
@@ -70,13 +70,12 @@ queue_packet(fw_handle_t handle,
}
static int
-queue_xmit_packets(raw1394handle_t handle, int limit)
+queue_xmit_packets(raw1394handle_t handle, int limit, int cycle)
{
fw_handle_t fwhandle = handle->mode.fw;
enum raw1394_iso_disposition d;
unsigned char tag, sy;
unsigned int len;
- int cycle = -1;
unsigned int dropped = 0;
if (fwhandle->iso.xmit_handler == NULL)
@@ -90,6 +89,11 @@ queue_xmit_packets(raw1394handle_t handle, int limit)
switch (d) {
case RAW1394_ISO_OK:
queue_packet(fwhandle, len, 0, tag, sy);
+ if (cycle >= 0) {
+ cycle++;
+ if (cycle >= 8000)
+ cycle %= 8000;
+ }
break;
case RAW1394_ISO_DEFER:
case RAW1394_ISO_AGAIN:
@@ -119,7 +123,21 @@ int fw_iso_xmit_start(raw1394handle_t handle, int start_on_cycle,
fwhandle->iso.prebuffer = prebuffer_packets;
fwhandle->iso.start_on_cycle = start_on_cycle;
- queue_xmit_packets(handle, prebuffer_packets);
+ retval = queue_xmit_packets(handle, prebuffer_packets, start_on_cycle);
+ if (retval)
+ return -1;
+
+ if (start_on_cycle >= 0) {
+ int tmp;
+
+ tmp = start_on_cycle + prebuffer_packets;
+ tmp %= 8000;
+ retval = queue_xmit_packets(handle, fwhandle->iso.buf_packets, tmp);
+ } else {
+ retval = queue_xmit_packets(handle, fwhandle->iso.buf_packets, -1);
+ }
+ if (retval)
+ return -1;
if (fwhandle->iso.prebuffer <= fwhandle->iso.packet_count) {
start_iso.cycle = start_on_cycle;
@@ -131,12 +149,7 @@ int fw_iso_xmit_start(raw1394handle_t handle, int start_on_cycle,
return retval;
}
- retval = queue_xmit_packets(handle, fwhandle->iso.buf_packets);
-
- if (retval)
- return -1;
- else
- fwhandle->iso.state = ISO_ACTIVE;
+ fwhandle->iso.state = ISO_ACTIVE;
return 0;
}
@@ -256,8 +269,31 @@ static int handle_iso_event(raw1394handle_t handle,
switch (fwhandle->iso.type) {
case FW_CDEV_ISO_CONTEXT_TRANSMIT:
+ {
+ int cycle;
+
fwhandle->iso.packet_count -= fwhandle->iso.irq_interval;
- return queue_xmit_packets(handle, fwhandle->iso.buf_packets);
+ if (interrupt->header_length) {
+ /*
+ * Take the cycle of the last packet transmitted, add
+ * the number of packets currently queued, plus one, and
+ * that's the cycle number of the next packet to ask
+ * for.
+ */
+ cycle = be32_to_cpu(interrupt->header[interrupt->header_length/4 - 1]);
+ cycle &= 0x1fff;
+ } else {
+ /*
+ * Bogusly faking it again. Assume that the last packet
+ * transmitted was transmitted on interrupt->cycle.
+ */
+ cycle = interrupt->cycle;
+ }
+ cycle += fwhandle->iso.packet_count;
+ cycle++;
+ cycle %= 8000;
+ return queue_xmit_packets(handle, fwhandle->iso.buf_packets, cycle);
+ }
case FW_CDEV_ISO_CONTEXT_RECEIVE:
return flush_recv_packets(handle, interrupt);
default: