aboutsummaryrefslogtreecommitdiffstats
path: root/sound/firewire/fireworks/fireworks_stream.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/firewire/fireworks/fireworks_stream.c')
-rw-r--r--sound/firewire/fireworks/fireworks_stream.c176
1 files changed, 87 insertions, 89 deletions
diff --git a/sound/firewire/fireworks/fireworks_stream.c b/sound/firewire/fireworks/fireworks_stream.c
index e659a0b89ba5..f2de304d2f26 100644
--- a/sound/firewire/fireworks/fireworks_stream.c
+++ b/sound/firewire/fireworks/fireworks_stream.c
@@ -8,8 +8,7 @@
#define CALLBACK_TIMEOUT 100
-static int
-init_stream(struct snd_efw *efw, struct amdtp_stream *stream)
+static int init_stream(struct snd_efw *efw, struct amdtp_stream *stream)
{
struct cmp_connection *conn;
enum cmp_direction c_dir;
@@ -28,26 +27,38 @@ init_stream(struct snd_efw *efw, struct amdtp_stream *stream)
err = cmp_connection_init(conn, efw->unit, c_dir, 0);
if (err < 0)
- goto end;
+ return err;
err = amdtp_am824_init(stream, efw->unit, s_dir, CIP_BLOCKING);
if (err < 0) {
amdtp_stream_destroy(stream);
cmp_connection_destroy(conn);
+ return err;
}
-end:
- return err;
-}
-static void
-stop_stream(struct snd_efw *efw, struct amdtp_stream *stream)
-{
- amdtp_stream_stop(stream);
+ if (stream == &efw->tx_stream) {
+ // Fireworks transmits NODATA packets with TAG0.
+ efw->tx_stream.flags |= CIP_EMPTY_WITH_TAG0;
+ // Fireworks has its own meaning for dbc.
+ efw->tx_stream.flags |= CIP_DBC_IS_END_EVENT;
+ // Fireworks reset dbc at bus reset.
+ efw->tx_stream.flags |= CIP_SKIP_DBC_ZERO_CHECK;
+ // But Recent firmwares starts packets with non-zero dbc.
+ // Driver version 5.7.6 installs firmware version 5.7.3.
+ if (efw->is_fireworks3 &&
+ (efw->firmware_version == 0x5070000 ||
+ efw->firmware_version == 0x5070300 ||
+ efw->firmware_version == 0x5080000))
+ efw->tx_stream.flags |= CIP_UNALIGHED_DBC;
+ // AudioFire9 always reports wrong dbs.
+ if (efw->is_af9)
+ efw->tx_stream.flags |= CIP_WRONG_DBS;
+ // Firmware version 5.5 reports fixed interval for dbc.
+ if (efw->firmware_version == 0x5050000)
+ efw->tx_stream.ctx_data.tx.dbc_interval = 8;
+ }
- if (stream == &efw->tx_stream)
- cmp_connection_break(&efw->out_conn);
- else
- cmp_connection_break(&efw->in_conn);
+ return err;
}
static int start_stream(struct snd_efw *efw, struct amdtp_stream *stream,
@@ -67,38 +78,26 @@ static int start_stream(struct snd_efw *efw, struct amdtp_stream *stream,
return err;
// Start amdtp stream.
- err = amdtp_stream_start(stream, conn->resources.channel, conn->speed);
+ err = amdtp_domain_add_stream(&efw->domain, stream,
+ conn->resources.channel, conn->speed);
if (err < 0) {
cmp_connection_break(conn);
return err;
}
- // Wait first callback.
- if (!amdtp_stream_wait_callback(stream, CALLBACK_TIMEOUT)) {
- amdtp_stream_stop(stream);
- cmp_connection_break(conn);
- return -ETIMEDOUT;
- }
-
return 0;
}
-/*
- * This function should be called before starting the stream or after stopping
- * the streams.
- */
-static void
-destroy_stream(struct snd_efw *efw, struct amdtp_stream *stream)
+// This function should be called before starting the stream or after stopping
+// the streams.
+static void destroy_stream(struct snd_efw *efw, struct amdtp_stream *stream)
{
- struct cmp_connection *conn;
+ amdtp_stream_destroy(stream);
if (stream == &efw->tx_stream)
- conn = &efw->out_conn;
+ cmp_connection_destroy(&efw->out_conn);
else
- conn = &efw->in_conn;
-
- amdtp_stream_destroy(stream);
- cmp_connection_destroy(conn);
+ cmp_connection_destroy(&efw->in_conn);
}
static int
@@ -131,42 +130,28 @@ int snd_efw_stream_init_duplex(struct snd_efw *efw)
err = init_stream(efw, &efw->tx_stream);
if (err < 0)
- goto end;
- /* Fireworks transmits NODATA packets with TAG0. */
- efw->tx_stream.flags |= CIP_EMPTY_WITH_TAG0;
- /* Fireworks has its own meaning for dbc. */
- efw->tx_stream.flags |= CIP_DBC_IS_END_EVENT;
- /* Fireworks reset dbc at bus reset. */
- efw->tx_stream.flags |= CIP_SKIP_DBC_ZERO_CHECK;
- /*
- * But Recent firmwares starts packets with non-zero dbc.
- * Driver version 5.7.6 installs firmware version 5.7.3.
- */
- if (efw->is_fireworks3 &&
- (efw->firmware_version == 0x5070000 ||
- efw->firmware_version == 0x5070300 ||
- efw->firmware_version == 0x5080000))
- efw->tx_stream.ctx_data.tx.first_dbc = 0x02;
- /* AudioFire9 always reports wrong dbs. */
- if (efw->is_af9)
- efw->tx_stream.flags |= CIP_WRONG_DBS;
- /* Firmware version 5.5 reports fixed interval for dbc. */
- if (efw->firmware_version == 0x5050000)
- efw->tx_stream.ctx_data.tx.dbc_interval = 8;
+ return err;
err = init_stream(efw, &efw->rx_stream);
if (err < 0) {
destroy_stream(efw, &efw->tx_stream);
- goto end;
+ return err;
+ }
+
+ err = amdtp_domain_init(&efw->domain);
+ if (err < 0) {
+ destroy_stream(efw, &efw->tx_stream);
+ destroy_stream(efw, &efw->rx_stream);
+ return err;
}
- /* set IEC61883 compliant mode (actually not fully compliant...) */
+ // set IEC61883 compliant mode (actually not fully compliant...).
err = snd_efw_command_set_tx_mode(efw, SND_EFW_TRANSPORT_MODE_IEC61883);
if (err < 0) {
destroy_stream(efw, &efw->tx_stream);
destroy_stream(efw, &efw->rx_stream);
}
-end:
+
return err;
}
@@ -214,8 +199,10 @@ int snd_efw_stream_reserve_duplex(struct snd_efw *efw, unsigned int rate)
if (rate == 0)
rate = curr_rate;
if (rate != curr_rate) {
- stop_stream(efw, &efw->tx_stream);
- stop_stream(efw, &efw->rx_stream);
+ amdtp_domain_stop(&efw->domain);
+
+ cmp_connection_break(&efw->out_conn);
+ cmp_connection_break(&efw->in_conn);
cmp_connection_release(&efw->out_conn);
cmp_connection_release(&efw->in_conn);
@@ -255,47 +242,57 @@ int snd_efw_stream_start_duplex(struct snd_efw *efw)
if (efw->substreams_counter == 0)
return -EIO;
- err = snd_efw_command_get_sampling_rate(efw, &rate);
- if (err < 0)
- return err;
-
if (amdtp_streaming_error(&efw->rx_stream) ||
amdtp_streaming_error(&efw->tx_stream)) {
- stop_stream(efw, &efw->rx_stream);
- stop_stream(efw, &efw->tx_stream);
+ amdtp_domain_stop(&efw->domain);
+ cmp_connection_break(&efw->out_conn);
+ cmp_connection_break(&efw->in_conn);
}
- /* master should be always running */
+ err = snd_efw_command_get_sampling_rate(efw, &rate);
+ if (err < 0)
+ return err;
+
if (!amdtp_stream_running(&efw->rx_stream)) {
err = start_stream(efw, &efw->rx_stream, rate);
- if (err < 0) {
- dev_err(&efw->unit->device,
- "fail to start AMDTP master stream:%d\n", err);
+ if (err < 0)
goto error;
- }
- }
- if (!amdtp_stream_running(&efw->tx_stream)) {
err = start_stream(efw, &efw->tx_stream, rate);
- if (err < 0) {
- dev_err(&efw->unit->device,
- "fail to start AMDTP slave stream:%d\n", err);
+ if (err < 0)
+ goto error;
+
+ err = amdtp_domain_start(&efw->domain);
+ if (err < 0)
+ goto error;
+
+ // Wait first callback.
+ if (!amdtp_stream_wait_callback(&efw->rx_stream,
+ CALLBACK_TIMEOUT) ||
+ !amdtp_stream_wait_callback(&efw->tx_stream,
+ CALLBACK_TIMEOUT)) {
+ err = -ETIMEDOUT;
goto error;
}
}
return 0;
error:
- stop_stream(efw, &efw->rx_stream);
- stop_stream(efw, &efw->tx_stream);
+ amdtp_domain_stop(&efw->domain);
+
+ cmp_connection_break(&efw->out_conn);
+ cmp_connection_break(&efw->in_conn);
+
return err;
}
void snd_efw_stream_stop_duplex(struct snd_efw *efw)
{
if (efw->substreams_counter == 0) {
- stop_stream(efw, &efw->tx_stream);
- stop_stream(efw, &efw->rx_stream);
+ amdtp_domain_stop(&efw->domain);
+
+ cmp_connection_break(&efw->out_conn);
+ cmp_connection_break(&efw->in_conn);
cmp_connection_release(&efw->out_conn);
cmp_connection_release(&efw->in_conn);
@@ -304,18 +301,19 @@ void snd_efw_stream_stop_duplex(struct snd_efw *efw)
void snd_efw_stream_update_duplex(struct snd_efw *efw)
{
- if (cmp_connection_update(&efw->out_conn) < 0 ||
- cmp_connection_update(&efw->in_conn) < 0) {
- stop_stream(efw, &efw->rx_stream);
- stop_stream(efw, &efw->tx_stream);
- } else {
- amdtp_stream_update(&efw->rx_stream);
- amdtp_stream_update(&efw->tx_stream);
- }
+ amdtp_domain_stop(&efw->domain);
+
+ cmp_connection_break(&efw->out_conn);
+ cmp_connection_break(&efw->in_conn);
+
+ amdtp_stream_pcm_abort(&efw->rx_stream);
+ amdtp_stream_pcm_abort(&efw->tx_stream);
}
void snd_efw_stream_destroy_duplex(struct snd_efw *efw)
{
+ amdtp_domain_destroy(&efw->domain);
+
destroy_stream(efw, &efw->rx_stream);
destroy_stream(efw, &efw->tx_stream);
}