Commit Graph

116 Commits

Author SHA1 Message Date
Takashi Sakamoto
62f00e40b0 ALSA: firewire-lib: enable the same feature as CIP_SKIP_INIT_DBC_CHECK flag
In former commit, drivers in ALSA firewire stack always starts IT context
before IR context. If IR context starts after packets are transmitted by
peer unit, packet discontinuity may be detected because the context starts
in the middle of packet streaming. This situation is rare because IT
context usually starts immediately. However, it's better to solve this
issue. This is suppressed with CIP_SKIP_INIT_DBC_CHECK flag.

This commit enables the same feature as CIP_SKIP_INIT_DBC_CHECK.

Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2016-05-10 17:04:01 +02:00
Takashi Sakamoto
390a1512e6 ALSA: firewire-lib: code cleanup for outgoing packet handling
In previous commit, this module has no need to reuse parameters of
incoming packets for outgoing packets anymore. This commit arranges some
needless codes for outgoing packet processing.

Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2016-05-10 17:04:01 +02:00
Takashi Sakamoto
d9a16fc926 ALSA: firewire-lib: code cleanup for incoming packet handling
In previous commit, this module has no need to reuse parameters of
incoming packets for outgoing packets anymore. This commit arranges some
needless codes for incoming packet processing.

Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2016-05-10 17:04:00 +02:00
Takashi Sakamoto
dec63cc8b6 ALSA: firewire-lib: handle IT/IR contexts in each software interrupt context
In clause 6.3 of IEC 61883-6:2000, there's an explanation about processing
of presentation timestamp. In the clause, we can see "If a function block
receives a CIP, processes it and subsequently re-transmits it, then the
SYT of the outgoing CIP shall be the sum of the incoming SYT and the
processing delay." ALSA firewire stack has an implementation to partly
satisfy this specification. Developers assumed the stack to perform as an
Audio function block[1].

Following to the assumption, current implementation of ALSA firewire stack
use one software interrupt context to handle both of in/out packets. In
most case, this is processed in 1394 OHCI IR context independently of the
opposite context. Thus, this implementation uses longer CPU time in the
software interrupt context. This is not better for whole system.

Against the assumption, I confirmed that each ASIC for IEC 61883-1/6
doesn't necessarily expect it to the stack. Thus, current implementation
of ALSA firewire stack includes over-engineering.

This commit purges the implementation. As a result, packets of one
direction are handled in one software interrupt context and spends
minimum CPU time.

[1] [alsa-devel] [PATCH 0/8] [RFC] new driver for Echo Audio's Fireworks based devices
http://mailman.alsa-project.org/pipermail/alsa-devel/2013-June/062660.html

Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2016-05-10 17:03:59 +02:00
Takashi Sakamoto
0c95c1d619 ALSA: firewire-lib: add tracepoints to dump a part of isochronous packet data
When audio and music units have some quirks in their sequence of packet,
it's really hard for non-owners to identify the quirks. Although developers
need dumps for sequence of packets, it's difficult for users who have no
knowledges and no equipments for this purpose.

This commit adds tracepoints for this situation. When users encounter
the issue, they can dump a part of packet data via Linux tracing framework
as long as using drivers in ALSA firewire stack.

Additionally, tracepoints for outgoing packets will be our help to check
and debug packet processing of ALSA firewire stack.

This commit newly adds 'snd_firewire_lib' subsystem with 'in_packet' and
'out_packet' events. In the events, some attributes of packets and the
index of packet managed by this module are recorded per packet.

This is an usage:

$ trace-cmd record -e snd_firewire_lib:out_packet \
                   -e snd_firewire_lib:in_packet
/sys/kernel/tracing/events/snd_firewire_lib/out_packet/filter
/sys/kernel/tracing/events/snd_firewire_lib/in_packet/filter
Hit Ctrl^C to stop recording
^C
$ trace-cmd report trace.dat
...
23647.033934: in_packet:  01 4073 ffc0 ffc1 00 000f0040 9001b2d1 122 44
23647.033936: in_packet:  01 4074 ffc0 ffc1 00 000f0048 9001c83b 122 45
23647.033937: in_packet:  01 4075 ffc0 ffc1 00 000f0050 9001ffff 002 46
23647.033938: in_packet:  01 4076 ffc0 ffc1 00 000f0050 9001e1a6 122 47
23647.035426: out_packet: 01 4123 ffc1 ffc0 01 010f00d0 9001fb40 122 17
23647.035428: out_packet: 01 4124 ffc1 ffc0 01 010f00d8 9001ffff 002 18
23647.035429: out_packet: 01 4125 ffc1 ffc0 01 010f00d8 900114aa 122 19
23647.035430: out_packet: 01 4126 ffc1 ffc0 01 010f00e0 90012a15 122 20
(Here, some common fields are omitted so that a line to be within 80
characters.)
...

One line represent one packet. The legend for the last nine fields is:
 - The second of cycle scheduled for the packet
 - The count of cycle scheduled for the packet
 - The ID of node as source (hex)
  - Some devices transfer packets with invalid source node ID in their CIP
    header.
 - The ID of node as destination (hex)
  - The value is not in CIP header of packets.
 - The value of isochronous channel
 - The first quadlet of CIP header (hex)
 - The second quadlet of CIP header (hex)
 - The number of included quadlets
 - The index of packet in a buffer maintained by this module

This is an example to parse these lines from text file by Python3 script:

\#!/usr/bin/env python3
import sys

def parse_ts(second, cycle, syt):
    offset = syt & 0xfff
    syt >>= 12
    if cycle & 0x0f > syt:
        cycle += 0x10
    cycle &= 0x1ff0
    cycle |= syt
    second += cycle // 8000
    cycle %= 8000
    # In CYCLE_TIMER of 1394 OHCI, second is represented in 8 bit.
    second %= 128
    return (second, cycle, offset)

def calc_ts(second, cycle, offset):
    ts = offset
    ts += cycle * 3072
    # In DMA descriptor of 1394 OHCI, second is represented in 3 bit.
    ts += (second % 8) * 8000 * 3072
    return ts

def subtract_ts(minuend, subtrahend):
    # In DMA descriptor of 1394 OHCI, second is represented in 3 bit.
    if minuend < subtrahend:
        minuend += 8 * 8000 * 3072
    return minuend - subtrahend

if len(sys.argv) != 2:
    print('At least, one argument is required for packet dump.')
    sys.exit()

filename = sys.argv[1]

data = []

prev = 0
with open(filename, 'r') as f:
    for line in f:
        pos = line.find('packet:')
        if pos < 0:
            continue

        pos += len('packet:')
        line = line[pos:].strip()
        fields = line.split(' ')

        datum = []

        datum.append(fields[8])

        syt = int(fields[6][4:], 16)

        # Empty packet in IEC 61883-1, or NODATA in IEC 61883-6
        if syt == 0xffff:
            data_blocks = 0
        else:
            payload_size = int(fields[7], 10)
            data_block_size = int(fields[5][2:4], 16)
            data_blocks = (payload_size - 2) / data_block_size
        datum.append(data_blocks)

        second = int(fields[0], 10)
        cycle = int(fields[1], 10)
        start = (second << 25) | (cycle << 12)
        datum.append('0x{0:08x}'.format(start))
        start = calc_ts(second, cycle, 0)

        datum.append("0x" + fields[5])
        datum.append("0x" + fields[6])

        if syt == 0xffff:
            second = 0
            cycle = 0
            tick = 0
        else:
            second, cycle, tick = parse_ts(second, cycle, syt)
        ts = calc_ts(second, cycle, tick)
        datum.append(start)
        datum.append(ts)
        if ts == 0:
            datum.append(0)
            datum.append(0)
        else:
            # Usual case, or a case over 8 seconds.
            if ts > start or start > 7 * 8000 * 3072:
                datum.append(subtract_ts(ts, start))
                if ts > prev or start > 7 * 8000 * 3072:
                    gap = subtract_ts(ts, prev)
                    datum.append(gap)
                else:
                    datum.append('backward')
            else:
                datum.append('invalid')
            prev = ts

        data.append(datum)

sys.exit()

The data variable includes array with these elements:
- The index of the packet
- The number of data blocks in the packet
- The value of cycle count (hex)
- The value of CIP header 1 (hex)
- The value of CIP header 2 (hex)
- The value of cycle count (tick)
- The value of calculated presentation timestamp (tick)
- The offset between the cycle count and presentation timestamp
- The elapsed ticks from the previous presentation timestamp

Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2016-05-09 15:18:25 +02:00
Takashi Sakamoto
f90e2dedf7 ALSA: firewire-lib: compute the value of second field in cycle count for IR context
In callback function of isochronous context, modules can queue packets to
indicated isochronous cycles. Although the cycle to queue a packet is
deterministic by calculation, this module doesn't implement the calculation
because it's useless for processing.

In future, the cycle count is going to be printed with the other parameters
for debugging. This commit is the preparation. The cycle count is computed
by cycle unit, and correctly arranged to corresponding packets. The
calculated count is used in later commit.

Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2016-05-09 15:18:25 +02:00
Takashi Sakamoto
73fc7f0801 ALSA: firewire-lib: compute the value of second field in cycle count for IT context
In callback function of isochronous context, u32 variable is passed for
cycle count. The value of this variable comes from DMA descriptors of 1394
Open Host Controller Interface (1394 OHCI). In the specification, DMA
descriptors transport lower 3 bits for second field and full cycle field in
16 bits field, therefore 16 bits of the u32 variable are available. The
value for second is modulo 8, and the value for cycle is modulo 8,000.

Currently, ALSA firewire-lib module don't use the value of the second
field, because the value is useless to calculate presentation timestamp in
IEC 61883-6. However, the value may be useful for debugging. In later
commit, it will be printed with the other parameters for debugging.

This commit makes this module to handle the whole cycle count including
second. The value is calculated by cycle unit. The existed code is already
written with ignoring the value of second, thus this commit causes no
issues.

Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2016-05-09 15:18:24 +02:00
Takashi Sakamoto
44c376b959 ALSA: firewire-lib: suppress kernel warnings when releasing uninitialized stream data
When any of AMDTP stream data are not initialized and private data is
going to be released, WARN_ON() in amdtp_stream_destroy() is hit and
dump messages. This may take users irritated.

This commit fixes the bug to skip releasing when it's not initialized.

Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2016-03-31 15:36:17 +02:00
Takashi Sakamoto
2a7e1713cd ALSA: firewire-lib: continue packet processing at detecting wrong CIP headers
In firewire-lib, isochronous packet streaming is stopped when detecting
wrong value for FMT field of CIP headers. Although this is appropriate
to IEC 61883-1 and 6, some BeBoB based devices with vendors' customization
use invalid value to FMT field of CIP headers in the beginning of
streaming.

$ journalctl
  snd-bebob fw1.0: Detect unexpected protocol: 01000000 8000ffff

I got this log with M-Audio FireWire 1814. In this line, the value of FMT
field is 0x00, while it should be 0x10 in usual AMDTP.

Except for the beginning, these devices continue to transfer packets with
valid value for FMT field, except for the beginning. Therefore, in this
case, firewire-lib should continue to process packets. The former
implementation of firewire-lib performs it.

This commit loosens the handling of wrong value, to continue packet
processing in the case.

Fixes: 414ba022a5 ('ALSA: firewire-lib: add support arbitrary value for fmt/fdf fields in CIP header')
Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2015-10-11 18:14:01 +02:00
Takashi Sakamoto
df075feefb ALSA: firewire-lib: complete AM824 data block processing layer
This commit moves the codes related to data block processing from packet
streaming layer to AM824 layer.

Each driver initializes amdtp stream structure for AM824 data block by
calling amdtp_am824_init(). Then, a memory block is allocated for AM824
specific structure. This memory block is released by calling
amdtp_stream_destroy().

When setting streaming parameters, it calls amdtp_am824_set_parameters().
When starting packet streaming, it calls amdtp_stream_start(). When
stopping packet streaming, it calls amdtp_stream_stop().

Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2015-09-29 12:51:20 +02:00
Takashi Sakamoto
49c7b3fcd9 ALSA: firewire-lib: rename macros with AM824 prefix
This commit renames some macros just related to AM824 format. In later
commit, they're moved to AM824 layer.

Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2015-09-29 12:50:23 +02:00
Takashi Sakamoto
85130cb43e ALSA: firewire-lib: rename PCM format helper function
Setting the format of PCM substream to AMDTP stream structure is important
to set a handler to copy actual PCM samples between buffers. The
processing should be in data block processing layer because essentially
it has no relationship to packet streaming.

This commit renames PCM format setting function to prepare for integrating
AM824 layer.

Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2015-09-29 12:49:04 +02:00
Takashi Sakamoto
bc8500da3e ALSA: firewire-lib: move PCM substream constraint to AM824 layer
In IEC 61883-6, PCM frames are transferred in Multi Bit Linear Audio data
channel. The data channel transfers 16/20/24 bit PCM samples. Thus, PCM
substream has a constrain about it.

This commit moves codes related to the constraint from packet streaming
layer to AM824 data block processing layer.

Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2015-09-29 12:48:19 +02:00
Takashi Sakamoto
51c29fd213 ALSA: firewire-lib: rename parameter setting function for AM824 with FDF field
The value of FDF field in CIP header is protocol-dependent. Thus, it's
better to allow data block processing layer to decide the value in any
timing.

In AM824 data format, the value of FDF field in CIP header indicates
N-flag and Nominal Sampling Frequency Code (sfc). The N-flag is for
switching 'Clock-based rate control mode' and 'Command-based rate control
mode'. In our implementation, 'Clock-based rate control mode' is just
supported. Therefore, When sampling transfer frequency is decided, then
the FDF can be set.

This commit replaces 'amdtp_stream_set_parameters' with
'amdtp_am824_set_parameters' to set the FDF. This is the same timing
to decide the ration between the number of data blocks and the number of
PCM frames.

Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2015-09-29 12:48:02 +02:00
Takashi Sakamoto
5955815e71 ALSA: firewire-lib: add data block processing layer for AM824 format
This commit adds data block processing layer for AM824 format. The new
layer initializes streaming layer with its value for fmt field.

Currently, most implementation of data block processing still remains
streaming layer. In later commits, these codes will be moved to the layer.

Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2015-09-29 12:47:45 +02:00
Takashi Sakamoto
d67c46b953 ALSA: firewire-lib: rename 'amdtp' to 'amdtp-stream' to prepare for functional separation
In later commit, data block processing layer will be newly added. This
layer will be named as 'amdtp-am824'.

This commit renames current amdtp file to amdtp-stream, to distinguish it
from the new layer.

Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2015-09-29 12:47:11 +02:00