ALSA: firewire-motu: support AMDTP domain
This commit adds AMDTP domain support for ALSA firewire-motu driver. Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp> Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
parent
c281d46a51
commit
ccc6c1b0e6
|
@ -92,9 +92,6 @@ static void finish_session(struct snd_motu *motu)
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
amdtp_stream_stop(&motu->tx_stream);
|
|
||||||
amdtp_stream_stop(&motu->rx_stream);
|
|
||||||
|
|
||||||
err = snd_motu_transaction_read(motu, ISOC_COMM_CONTROL_OFFSET, ®,
|
err = snd_motu_transaction_read(motu, ISOC_COMM_CONTROL_OFFSET, ®,
|
||||||
sizeof(reg));
|
sizeof(reg));
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
|
@ -109,27 +106,6 @@ static void finish_session(struct snd_motu *motu)
|
||||||
sizeof(reg));
|
sizeof(reg));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int start_isoc_ctx(struct snd_motu *motu, struct amdtp_stream *stream)
|
|
||||||
{
|
|
||||||
struct fw_iso_resources *resources;
|
|
||||||
int err;
|
|
||||||
|
|
||||||
if (stream == &motu->rx_stream)
|
|
||||||
resources = &motu->rx_resources;
|
|
||||||
else
|
|
||||||
resources = &motu->tx_resources;
|
|
||||||
|
|
||||||
err = amdtp_stream_start(stream, resources->channel,
|
|
||||||
fw_parent_device(motu->unit)->max_speed);
|
|
||||||
if (err < 0)
|
|
||||||
return err;
|
|
||||||
|
|
||||||
if (!amdtp_stream_wait_callback(stream, CALLBACK_TIMEOUT))
|
|
||||||
return -ETIMEDOUT;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int snd_motu_stream_cache_packet_formats(struct snd_motu *motu)
|
int snd_motu_stream_cache_packet_formats(struct snd_motu *motu)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
|
@ -169,6 +145,7 @@ int snd_motu_stream_reserve_duplex(struct snd_motu *motu, unsigned int rate)
|
||||||
rate = curr_rate;
|
rate = curr_rate;
|
||||||
|
|
||||||
if (motu->substreams_counter == 0 || curr_rate != rate) {
|
if (motu->substreams_counter == 0 || curr_rate != rate) {
|
||||||
|
amdtp_domain_stop(&motu->domain);
|
||||||
finish_session(motu);
|
finish_session(motu);
|
||||||
|
|
||||||
fw_iso_resources_free(&motu->tx_resources);
|
fw_iso_resources_free(&motu->tx_resources);
|
||||||
|
@ -234,8 +211,10 @@ int snd_motu_stream_start_duplex(struct snd_motu *motu)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (amdtp_streaming_error(&motu->rx_stream) ||
|
if (amdtp_streaming_error(&motu->rx_stream) ||
|
||||||
amdtp_streaming_error(&motu->tx_stream))
|
amdtp_streaming_error(&motu->tx_stream)) {
|
||||||
|
amdtp_domain_stop(&motu->domain);
|
||||||
finish_session(motu);
|
finish_session(motu);
|
||||||
|
}
|
||||||
|
|
||||||
if (generation != fw_parent_device(motu->unit)->card->generation) {
|
if (generation != fw_parent_device(motu->unit)->card->generation) {
|
||||||
err = fw_iso_resources_update(&motu->rx_resources);
|
err = fw_iso_resources_update(&motu->rx_resources);
|
||||||
|
@ -248,6 +227,8 @@ int snd_motu_stream_start_duplex(struct snd_motu *motu)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!amdtp_stream_running(&motu->rx_stream)) {
|
if (!amdtp_stream_running(&motu->rx_stream)) {
|
||||||
|
int spd = fw_parent_device(motu->unit)->max_speed;
|
||||||
|
|
||||||
err = ensure_packet_formats(motu);
|
err = ensure_packet_formats(motu);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
|
@ -259,10 +240,25 @@ int snd_motu_stream_start_duplex(struct snd_motu *motu)
|
||||||
goto stop_streams;
|
goto stop_streams;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = start_isoc_ctx(motu, &motu->rx_stream);
|
err = amdtp_domain_add_stream(&motu->domain, &motu->tx_stream,
|
||||||
if (err < 0) {
|
motu->tx_resources.channel, spd);
|
||||||
dev_err(&motu->unit->device,
|
if (err < 0)
|
||||||
"fail to start IT context: %d\n", err);
|
goto stop_streams;
|
||||||
|
|
||||||
|
err = amdtp_domain_add_stream(&motu->domain, &motu->rx_stream,
|
||||||
|
motu->rx_resources.channel, spd);
|
||||||
|
if (err < 0)
|
||||||
|
goto stop_streams;
|
||||||
|
|
||||||
|
err = amdtp_domain_start(&motu->domain);
|
||||||
|
if (err < 0)
|
||||||
|
goto stop_streams;
|
||||||
|
|
||||||
|
if (!amdtp_stream_wait_callback(&motu->tx_stream,
|
||||||
|
CALLBACK_TIMEOUT) ||
|
||||||
|
!amdtp_stream_wait_callback(&motu->rx_stream,
|
||||||
|
CALLBACK_TIMEOUT)) {
|
||||||
|
err = -ETIMEDOUT;
|
||||||
goto stop_streams;
|
goto stop_streams;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -274,18 +270,10 @@ int snd_motu_stream_start_duplex(struct snd_motu *motu)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!amdtp_stream_running(&motu->tx_stream)) {
|
|
||||||
err = start_isoc_ctx(motu, &motu->tx_stream);
|
|
||||||
if (err < 0) {
|
|
||||||
dev_err(&motu->unit->device,
|
|
||||||
"fail to start IR context: %d", err);
|
|
||||||
goto stop_streams;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
stop_streams:
|
stop_streams:
|
||||||
|
amdtp_domain_stop(&motu->domain);
|
||||||
finish_session(motu);
|
finish_session(motu);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
@ -293,6 +281,7 @@ stop_streams:
|
||||||
void snd_motu_stream_stop_duplex(struct snd_motu *motu)
|
void snd_motu_stream_stop_duplex(struct snd_motu *motu)
|
||||||
{
|
{
|
||||||
if (motu->substreams_counter == 0) {
|
if (motu->substreams_counter == 0) {
|
||||||
|
amdtp_domain_stop(&motu->domain);
|
||||||
finish_session(motu);
|
finish_session(motu);
|
||||||
|
|
||||||
fw_iso_resources_free(&motu->tx_resources);
|
fw_iso_resources_free(&motu->tx_resources);
|
||||||
|
@ -344,18 +333,26 @@ int snd_motu_stream_init_duplex(struct snd_motu *motu)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
err = init_stream(motu, &motu->rx_stream);
|
err = init_stream(motu, &motu->rx_stream);
|
||||||
if (err < 0)
|
if (err < 0) {
|
||||||
destroy_stream(motu, &motu->tx_stream);
|
destroy_stream(motu, &motu->tx_stream);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = amdtp_domain_init(&motu->domain);
|
||||||
|
if (err < 0) {
|
||||||
|
destroy_stream(motu, &motu->tx_stream);
|
||||||
|
destroy_stream(motu, &motu->rx_stream);
|
||||||
|
}
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
// This function should be called before starting streams or after stopping
|
||||||
* This function should be called before starting streams or after stopping
|
// streams.
|
||||||
* streams.
|
|
||||||
*/
|
|
||||||
void snd_motu_stream_destroy_duplex(struct snd_motu *motu)
|
void snd_motu_stream_destroy_duplex(struct snd_motu *motu)
|
||||||
{
|
{
|
||||||
|
amdtp_domain_destroy(&motu->domain);
|
||||||
|
|
||||||
destroy_stream(motu, &motu->rx_stream);
|
destroy_stream(motu, &motu->rx_stream);
|
||||||
destroy_stream(motu, &motu->tx_stream);
|
destroy_stream(motu, &motu->tx_stream);
|
||||||
|
|
||||||
|
|
|
@ -69,6 +69,8 @@ struct snd_motu {
|
||||||
int dev_lock_count;
|
int dev_lock_count;
|
||||||
bool dev_lock_changed;
|
bool dev_lock_changed;
|
||||||
wait_queue_head_t hwdep_wait;
|
wait_queue_head_t hwdep_wait;
|
||||||
|
|
||||||
|
struct amdtp_domain domain;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum snd_motu_spec_flags {
|
enum snd_motu_spec_flags {
|
||||||
|
|
Loading…
Reference in New Issue