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:
Родитель
c281d46a51
Коммит
ccc6c1b0e6
|
@ -92,9 +92,6 @@ static void finish_session(struct snd_motu *motu)
|
|||
if (err < 0)
|
||||
return;
|
||||
|
||||
amdtp_stream_stop(&motu->tx_stream);
|
||||
amdtp_stream_stop(&motu->rx_stream);
|
||||
|
||||
err = snd_motu_transaction_read(motu, ISOC_COMM_CONTROL_OFFSET, ®,
|
||||
sizeof(reg));
|
||||
if (err < 0)
|
||||
|
@ -109,27 +106,6 @@ static void finish_session(struct snd_motu *motu)
|
|||
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 err;
|
||||
|
@ -169,6 +145,7 @@ int snd_motu_stream_reserve_duplex(struct snd_motu *motu, unsigned int rate)
|
|||
rate = curr_rate;
|
||||
|
||||
if (motu->substreams_counter == 0 || curr_rate != rate) {
|
||||
amdtp_domain_stop(&motu->domain);
|
||||
finish_session(motu);
|
||||
|
||||
fw_iso_resources_free(&motu->tx_resources);
|
||||
|
@ -234,8 +211,10 @@ int snd_motu_stream_start_duplex(struct snd_motu *motu)
|
|||
return 0;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
if (generation != fw_parent_device(motu->unit)->card->generation) {
|
||||
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)) {
|
||||
int spd = fw_parent_device(motu->unit)->max_speed;
|
||||
|
||||
err = ensure_packet_formats(motu);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
@ -259,10 +240,25 @@ int snd_motu_stream_start_duplex(struct snd_motu *motu)
|
|||
goto stop_streams;
|
||||
}
|
||||
|
||||
err = start_isoc_ctx(motu, &motu->rx_stream);
|
||||
if (err < 0) {
|
||||
dev_err(&motu->unit->device,
|
||||
"fail to start IT context: %d\n", err);
|
||||
err = amdtp_domain_add_stream(&motu->domain, &motu->tx_stream,
|
||||
motu->tx_resources.channel, spd);
|
||||
if (err < 0)
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
||||
stop_streams:
|
||||
amdtp_domain_stop(&motu->domain);
|
||||
finish_session(motu);
|
||||
return err;
|
||||
}
|
||||
|
@ -293,6 +281,7 @@ stop_streams:
|
|||
void snd_motu_stream_stop_duplex(struct snd_motu *motu)
|
||||
{
|
||||
if (motu->substreams_counter == 0) {
|
||||
amdtp_domain_stop(&motu->domain);
|
||||
finish_session(motu);
|
||||
|
||||
fw_iso_resources_free(&motu->tx_resources);
|
||||
|
@ -344,18 +333,26 @@ int snd_motu_stream_init_duplex(struct snd_motu *motu)
|
|||
return err;
|
||||
|
||||
err = init_stream(motu, &motu->rx_stream);
|
||||
if (err < 0)
|
||||
if (err < 0) {
|
||||
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;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function should be called before starting streams or after stopping
|
||||
* streams.
|
||||
*/
|
||||
// This function should be called before starting streams or after stopping
|
||||
// streams.
|
||||
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->tx_stream);
|
||||
|
||||
|
|
|
@ -69,6 +69,8 @@ struct snd_motu {
|
|||
int dev_lock_count;
|
||||
bool dev_lock_changed;
|
||||
wait_queue_head_t hwdep_wait;
|
||||
|
||||
struct amdtp_domain domain;
|
||||
};
|
||||
|
||||
enum snd_motu_spec_flags {
|
||||
|
|
Загрузка…
Ссылка в новой задаче