diff options
Diffstat (limited to 'sound/firewire/fireworks/fireworks_stream.c')
-rw-r--r-- | sound/firewire/fireworks/fireworks_stream.c | 176 |
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); } |