diff options
author | Jay Fenlason <fenlason@redhat.com> | 2009-11-20 18:05:56 -0500 |
---|---|---|
committer | Stefan Richter <stefanr@s5r6.in-berlin.de> | 2009-11-20 18:56:47 -0500 |
commit | 31769cef2e973544164aa7d0db2e2024660d5e21 (patch) | |
tree | 6f3c2ce2e742fa197ac1460012a14eaf09bf3afa /drivers/firewire/ohci.c | |
parent | 5ed1f321a71b8549cc2eea26c94fe7943ed01d31 (diff) |
firewire: ohci: pass correct iso xmit timestamps to core
Here is the final set of patches I used to get ffado to work with the
new firewire stack. With these patches, I was able to start ardour
and record from and playback to my PreSonus Inspire1394 from a
(mostly) Fedora 12 system.
Signed-off-by: Jay Fenlason <fenlason@redhat.com>
Until now, firewire-ohci exposed only the transmit cycle of the last
transmitted packet at each isochronous transmit complete event. This
made it impossible for FFADO (FireWire audio drivers in userspace) to
synchronize audio-out streams. The fix is to store the timestamp of
each packet in the iso xmit event. As a bonus, the transfer status is
stored too.
Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
Diffstat (limited to 'drivers/firewire/ohci.c')
-rw-r--r-- | drivers/firewire/ohci.c | 25 |
1 files changed, 20 insertions, 5 deletions
diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c index c07cfada190a..94260aa76aa3 100644 --- a/drivers/firewire/ohci.c +++ b/drivers/firewire/ohci.c | |||
@@ -1904,15 +1904,30 @@ static int handle_it_packet(struct context *context, | |||
1904 | { | 1904 | { |
1905 | struct iso_context *ctx = | 1905 | struct iso_context *ctx = |
1906 | container_of(context, struct iso_context, context); | 1906 | container_of(context, struct iso_context, context); |
1907 | int i; | ||
1908 | struct descriptor *pd; | ||
1907 | 1909 | ||
1908 | if (last->transfer_status == 0) | 1910 | for (pd = d; pd <= last; pd++) |
1909 | /* This descriptor isn't done yet, stop iteration. */ | 1911 | if (pd->transfer_status) |
1912 | break; | ||
1913 | if (pd > last) | ||
1914 | /* Descriptor(s) not done yet, stop iteration */ | ||
1910 | return 0; | 1915 | return 0; |
1911 | 1916 | ||
1912 | if (le16_to_cpu(last->control) & DESCRIPTOR_IRQ_ALWAYS) | 1917 | i = ctx->header_length; |
1918 | if (i + 4 < PAGE_SIZE) { | ||
1919 | /* Present this value as big-endian to match the receive code */ | ||
1920 | *(__be32 *)(ctx->header + i) = cpu_to_be32( | ||
1921 | ((u32)le16_to_cpu(pd->transfer_status) << 16) | | ||
1922 | le16_to_cpu(pd->res_count)); | ||
1923 | ctx->header_length += 4; | ||
1924 | } | ||
1925 | if (le16_to_cpu(last->control) & DESCRIPTOR_IRQ_ALWAYS) { | ||
1913 | ctx->base.callback(&ctx->base, le16_to_cpu(last->res_count), | 1926 | ctx->base.callback(&ctx->base, le16_to_cpu(last->res_count), |
1914 | 0, NULL, ctx->base.callback_data); | 1927 | ctx->header_length, ctx->header, |
1915 | 1928 | ctx->base.callback_data); | |
1929 | ctx->header_length = 0; | ||
1930 | } | ||
1916 | return 1; | 1931 | return 1; |
1917 | } | 1932 | } |
1918 | 1933 | ||