summaryrefslogtreecommitdiff
path: root/sound/firewire
diff options
context:
space:
mode:
Diffstat (limited to 'sound/firewire')
-rw-r--r--sound/firewire/amdtp-stream.c44
-rw-r--r--sound/firewire/motu/amdtp-motu.c6
-rw-r--r--sound/firewire/motu/motu-protocol-v2.c43
-rw-r--r--sound/firewire/motu/motu.c15
-rw-r--r--sound/firewire/motu/motu.h1
5 files changed, 72 insertions, 37 deletions
diff --git a/sound/firewire/amdtp-stream.c b/sound/firewire/amdtp-stream.c
index 3ada55ed5381..43f28b813386 100644
--- a/sound/firewire/amdtp-stream.c
+++ b/sound/firewire/amdtp-stream.c
@@ -56,8 +56,9 @@
#define INTERRUPT_INTERVAL 16
#define QUEUE_LENGTH 48
-#define IN_PACKET_HEADER_SIZE 4
+#define IR_HEADER_SIZE 8 // For header and timestamp.
#define OUT_PACKET_HEADER_SIZE 0
+#define HEADER_TSTAMP_MASK 0x0000ffff
static void pcm_period_tasklet(unsigned long data);
@@ -456,7 +457,7 @@ static inline int queue_out_packet(struct amdtp_stream *s,
static inline int queue_in_packet(struct amdtp_stream *s)
{
- return queue_packet(s, IN_PACKET_HEADER_SIZE, s->max_payload_length);
+ return queue_packet(s, IR_HEADER_SIZE, s->max_payload_length);
}
static int handle_out_packet(struct amdtp_stream *s,
@@ -701,13 +702,6 @@ static inline u32 increment_cycle_count(u32 cycle, unsigned int addend)
return cycle;
}
-static inline u32 decrement_cycle_count(u32 cycle, unsigned int subtrahend)
-{
- if (cycle < subtrahend)
- cycle += 8 * CYCLES_PER_SECOND;
- return cycle - subtrahend;
-}
-
static void out_stream_callback(struct fw_iso_context *context, u32 tstamp,
size_t header_length, void *header,
void *private_data)
@@ -745,29 +739,26 @@ static void in_stream_callback(struct fw_iso_context *context, u32 tstamp,
struct amdtp_stream *s = private_data;
unsigned int i, packets;
unsigned int payload_length, max_payload_length;
- __be32 *headers = header;
- u32 cycle;
+ __be32 *ctx_header = header;
if (s->packet_index < 0)
return;
/* The number of packets in buffer */
- packets = header_length / IN_PACKET_HEADER_SIZE;
-
- cycle = compute_cycle_count(tstamp);
-
- /* Align to actual cycle count for the last packet. */
- cycle = decrement_cycle_count(cycle, packets);
+ packets = header_length / IR_HEADER_SIZE;
/* For buffer-over-run prevention. */
max_payload_length = s->max_payload_length;
for (i = 0; i < packets; i++) {
- cycle = increment_cycle_count(cycle, 1);
+ u32 iso_header = be32_to_cpu(ctx_header[0]);
+ unsigned int cycle;
+
+ tstamp = be32_to_cpu(ctx_header[1]) & HEADER_TSTAMP_MASK;
+ cycle = compute_cycle_count(tstamp);
/* The number of bytes in this packet */
- payload_length =
- (be32_to_cpu(headers[i]) >> ISO_DATA_LENGTH_SHIFT);
+ payload_length = iso_header >> ISO_DATA_LENGTH_SHIFT;
if (payload_length > max_payload_length) {
dev_err(&s->unit->device,
"Detect jumbo payload: %04x %04x\n",
@@ -777,6 +768,8 @@ static void in_stream_callback(struct fw_iso_context *context, u32 tstamp,
if (s->handle_packet(s, payload_length, cycle, i) < 0)
break;
+
+ ctx_header += IR_HEADER_SIZE / sizeof(__be32);
}
/* Queueing error or detecting invalid payload. */
@@ -797,6 +790,7 @@ static void amdtp_stream_first_callback(struct fw_iso_context *context,
void *header, void *private_data)
{
struct amdtp_stream *s = private_data;
+ __be32 *ctx_header = header;
u32 cycle;
unsigned int packets;
@@ -807,11 +801,10 @@ static void amdtp_stream_first_callback(struct fw_iso_context *context,
s->callbacked = true;
wake_up(&s->callback_wait);
- cycle = compute_cycle_count(tstamp);
-
if (s->direction == AMDTP_IN_STREAM) {
- packets = header_length / IN_PACKET_HEADER_SIZE;
- cycle = decrement_cycle_count(cycle, packets);
+ tstamp = be32_to_cpu(ctx_header[1]) & HEADER_TSTAMP_MASK;
+ cycle = compute_cycle_count(tstamp);
+
context->callback.sc = in_stream_callback;
if (s->flags & CIP_NO_HEADER)
s->handle_packet = handle_in_packet_without_header;
@@ -819,6 +812,7 @@ static void amdtp_stream_first_callback(struct fw_iso_context *context,
s->handle_packet = handle_in_packet;
} else {
packets = header_length / 4;
+ cycle = compute_cycle_count(tstamp);
cycle = increment_cycle_count(cycle, QUEUE_LENGTH - packets);
context->callback.sc = out_stream_callback;
if (s->flags & CIP_NO_HEADER)
@@ -880,7 +874,7 @@ int amdtp_stream_start(struct amdtp_stream *s, int channel, int speed)
if (s->direction == AMDTP_IN_STREAM) {
dir = DMA_FROM_DEVICE;
type = FW_ISO_CONTEXT_RECEIVE;
- header_size = IN_PACKET_HEADER_SIZE;
+ header_size = IR_HEADER_SIZE;
} else {
dir = DMA_TO_DEVICE;
type = FW_ISO_CONTEXT_TRANSMIT;
diff --git a/sound/firewire/motu/amdtp-motu.c b/sound/firewire/motu/amdtp-motu.c
index 6c9b743ea74b..cb0c967dea63 100644
--- a/sound/firewire/motu/amdtp-motu.c
+++ b/sound/firewire/motu/amdtp-motu.c
@@ -412,6 +412,12 @@ int amdtp_motu_init(struct amdtp_stream *s, struct fw_unit *unit,
CIP_HEADER_WITHOUT_EOH;
fmt = CIP_FMT_MOTU_TX_V3;
}
+
+ if (protocol == &snd_motu_protocol_v2) {
+ // 8pre has some quirks.
+ flags |= CIP_WRONG_DBS |
+ CIP_SKIP_DBC_ZERO_CHECK;
+ }
} else {
process_data_blocks = process_rx_data_blocks;
flags |= CIP_DBC_IS_END_EVENT;
diff --git a/sound/firewire/motu/motu-protocol-v2.c b/sound/firewire/motu/motu-protocol-v2.c
index 453fc29fade7..848fffe7387e 100644
--- a/sound/firewire/motu/motu-protocol-v2.c
+++ b/sound/firewire/motu/motu-protocol-v2.c
@@ -15,6 +15,8 @@
#define V2_CLOCK_SRC_SHIFT 0
#define V2_CLOCK_TRAVELER_FETCH_DISABLE 0x04000000
#define V2_CLOCK_TRAVELER_FETCH_ENABLE 0x03000000
+#define V2_CLOCK_8PRE_FETCH_DISABLE 0x02000000
+#define V2_CLOCK_8PRE_FETCH_ENABLE 0x00000000
#define V2_IN_OUT_CONF_OFFSET 0x0c04
#define V2_OPT_OUT_IFACE_MASK 0x00000c00
@@ -132,20 +134,31 @@ static int v2_switch_fetching_mode(struct snd_motu *motu, bool enable)
u32 data;
int err = 0;
- if (motu->spec == &snd_motu_spec_traveler) {
+ if (motu->spec == &snd_motu_spec_traveler ||
+ motu->spec == &snd_motu_spec_8pre) {
err = snd_motu_transaction_read(motu, V2_CLOCK_STATUS_OFFSET,
&reg, sizeof(reg));
if (err < 0)
return err;
data = be32_to_cpu(reg);
- data &= ~(V2_CLOCK_TRAVELER_FETCH_DISABLE |
- V2_CLOCK_TRAVELER_FETCH_ENABLE);
-
- if (enable)
- data |= V2_CLOCK_TRAVELER_FETCH_ENABLE;
- else
- data |= V2_CLOCK_TRAVELER_FETCH_DISABLE;
+ if (motu->spec == &snd_motu_spec_traveler) {
+ data &= ~(V2_CLOCK_TRAVELER_FETCH_DISABLE |
+ V2_CLOCK_TRAVELER_FETCH_ENABLE);
+
+ if (enable)
+ data |= V2_CLOCK_TRAVELER_FETCH_ENABLE;
+ else
+ data |= V2_CLOCK_TRAVELER_FETCH_DISABLE;
+ } else if (motu->spec == &snd_motu_spec_8pre) {
+ data &= ~(V2_CLOCK_8PRE_FETCH_DISABLE |
+ V2_CLOCK_8PRE_FETCH_ENABLE);
+
+ if (enable)
+ data |= V2_CLOCK_8PRE_FETCH_DISABLE;
+ else
+ data |= V2_CLOCK_8PRE_FETCH_ENABLE;
+ }
reg = cpu_to_be32(data);
err = snd_motu_transaction_write(motu, V2_CLOCK_STATUS_OFFSET,
@@ -220,10 +233,16 @@ static void calculate_differed_part(struct snd_motu_packet_format *formats,
* interfaces.
*/
data = (data & mask) >> shift;
- if ((flags & SND_MOTU_SPEC_HAS_OPT_IFACE_A) &&
- data == V2_OPT_IFACE_MODE_ADAT) {
- pcm_chunks[0] += 8;
- pcm_chunks[1] += 4;
+ if (data == V2_OPT_IFACE_MODE_ADAT) {
+ if (flags & SND_MOTU_SPEC_HAS_OPT_IFACE_A) {
+ pcm_chunks[0] += 8;
+ pcm_chunks[1] += 4;
+ }
+ // 8pre has two sets of optical interface and doesn't reduce
+ // chunks for ADAT signals.
+ if (flags & SND_MOTU_SPEC_HAS_OPT_IFACE_B) {
+ pcm_chunks[1] += 4;
+ }
}
/* At mode x4, no data chunks are supported in this part. */
diff --git a/sound/firewire/motu/motu.c b/sound/firewire/motu/motu.c
index 513291ba0ab0..201539d4488c 100644
--- a/sound/firewire/motu/motu.c
+++ b/sound/firewire/motu/motu.c
@@ -203,6 +203,20 @@ const struct snd_motu_spec snd_motu_spec_traveler = {
.analog_out_ports = 8,
};
+const struct snd_motu_spec snd_motu_spec_8pre = {
+ .name = "8pre",
+ .protocol = &snd_motu_protocol_v2,
+ // In tx, use coax chunks for mix-return 1/2. In rx, use coax chunks for
+ // dummy 1/2.
+ .flags = SND_MOTU_SPEC_SUPPORT_CLOCK_X2 |
+ SND_MOTU_SPEC_HAS_OPT_IFACE_A |
+ SND_MOTU_SPEC_HAS_OPT_IFACE_B |
+ SND_MOTU_SPEC_RX_MIDI_2ND_Q |
+ SND_MOTU_SPEC_TX_MIDI_2ND_Q,
+ .analog_in_ports = 8,
+ .analog_out_ports = 2,
+};
+
static const struct snd_motu_spec motu_828mk3 = {
.name = "828mk3",
.protocol = &snd_motu_protocol_v3,
@@ -248,6 +262,7 @@ static const struct snd_motu_spec motu_audio_express = {
static const struct ieee1394_device_id motu_id_table[] = {
SND_MOTU_DEV_ENTRY(0x000003, &motu_828mk2),
SND_MOTU_DEV_ENTRY(0x000009, &snd_motu_spec_traveler),
+ SND_MOTU_DEV_ENTRY(0x00000f, &snd_motu_spec_8pre),
SND_MOTU_DEV_ENTRY(0x000015, &motu_828mk3), /* FireWire only. */
SND_MOTU_DEV_ENTRY(0x000035, &motu_828mk3), /* Hybrid. */
SND_MOTU_DEV_ENTRY(0x000033, &motu_audio_express),
diff --git a/sound/firewire/motu/motu.h b/sound/firewire/motu/motu.h
index fd5327d30ab1..1cd112be7dad 100644
--- a/sound/firewire/motu/motu.h
+++ b/sound/firewire/motu/motu.h
@@ -130,6 +130,7 @@ extern const struct snd_motu_protocol snd_motu_protocol_v2;
extern const struct snd_motu_protocol snd_motu_protocol_v3;
extern const struct snd_motu_spec snd_motu_spec_traveler;
+extern const struct snd_motu_spec snd_motu_spec_8pre;
int amdtp_motu_init(struct amdtp_stream *s, struct fw_unit *unit,
enum amdtp_stream_direction dir,