diff options
author | Takashi Sakamoto <o-takashi@sakamocchi.jp> | 2019-06-12 17:44:11 +0900 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2019-06-12 15:26:52 +0200 |
commit | 3d7250667ea96e7f9738caa6d5af85d87982066e (patch) | |
tree | 8268c629a8ff269c6896d0ae7175a03e6d77d8bf /sound/firewire/fireworks | |
parent | fb56eb73c6266164e4b06c9eca9716348420dbf1 (diff) |
ALSA: fireworks: configure sampling transfer frequency in pcm.hw_params callback
This commit is a part of preparation to perform allocation/release
of isochronous resources in pcm.hw_params/hw_free callbacks.
At present, several operations are done in pcm.prepare callback. To
reduce load of the callback, This commit splits out an operation to
set sampling transfer frequency in pcm.hw_params callback.
Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/firewire/fireworks')
-rw-r--r-- | sound/firewire/fireworks/fireworks.h | 3 | ||||
-rw-r--r-- | sound/firewire/fireworks/fireworks_midi.c | 7 | ||||
-rw-r--r-- | sound/firewire/fireworks/fireworks_pcm.c | 14 | ||||
-rw-r--r-- | sound/firewire/fireworks/fireworks_stream.c | 65 |
4 files changed, 57 insertions, 32 deletions
diff --git a/sound/firewire/fireworks/fireworks.h b/sound/firewire/fireworks/fireworks.h index 42a73038ba4d..0c1802aa7923 100644 --- a/sound/firewire/fireworks/fireworks.h +++ b/sound/firewire/fireworks/fireworks.h @@ -206,7 +206,8 @@ int snd_efw_command_get_sampling_rate(struct snd_efw *efw, unsigned int *rate); int snd_efw_command_set_sampling_rate(struct snd_efw *efw, unsigned int rate); int snd_efw_stream_init_duplex(struct snd_efw *efw); -int snd_efw_stream_start_duplex(struct snd_efw *efw, unsigned int rate); +int snd_efw_stream_reserve_duplex(struct snd_efw *efw, unsigned int rate); +int snd_efw_stream_start_duplex(struct snd_efw *efw); void snd_efw_stream_stop_duplex(struct snd_efw *efw); void snd_efw_stream_update_duplex(struct snd_efw *efw); void snd_efw_stream_destroy_duplex(struct snd_efw *efw); diff --git a/sound/firewire/fireworks/fireworks_midi.c b/sound/firewire/fireworks/fireworks_midi.c index ee5dc7be70b6..6d3d942e2dce 100644 --- a/sound/firewire/fireworks/fireworks_midi.c +++ b/sound/firewire/fireworks/fireworks_midi.c @@ -18,8 +18,11 @@ static int midi_open(struct snd_rawmidi_substream *substream) goto end; mutex_lock(&efw->mutex); - ++efw->substreams_counter; - err = snd_efw_stream_start_duplex(efw, 0); + err = snd_efw_stream_reserve_duplex(efw, 0); + if (err >= 0) { + ++efw->substreams_counter; + err = snd_efw_stream_start_duplex(efw); + } mutex_unlock(&efw->mutex); if (err < 0) snd_efw_stream_lock_release(efw); diff --git a/sound/firewire/fireworks/fireworks_pcm.c b/sound/firewire/fireworks/fireworks_pcm.c index 398a6ad04c5f..287fc05d5917 100644 --- a/sound/firewire/fireworks/fireworks_pcm.c +++ b/sound/firewire/fireworks/fireworks_pcm.c @@ -231,12 +231,16 @@ static int pcm_hw_params(struct snd_pcm_substream *substream, return err; if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) { + unsigned int rate = params_rate(hw_params); + mutex_lock(&efw->mutex); - ++efw->substreams_counter; + err = snd_efw_stream_reserve_duplex(efw, rate); + if (err >= 0) + ++efw->substreams_counter; mutex_unlock(&efw->mutex); } - return 0; + return err; } static int pcm_hw_free(struct snd_pcm_substream *substream) @@ -257,10 +261,9 @@ static int pcm_hw_free(struct snd_pcm_substream *substream) static int pcm_capture_prepare(struct snd_pcm_substream *substream) { struct snd_efw *efw = substream->private_data; - struct snd_pcm_runtime *runtime = substream->runtime; int err; - err = snd_efw_stream_start_duplex(efw, runtime->rate); + err = snd_efw_stream_start_duplex(efw); if (err >= 0) amdtp_stream_pcm_prepare(&efw->tx_stream); @@ -269,10 +272,9 @@ static int pcm_capture_prepare(struct snd_pcm_substream *substream) static int pcm_playback_prepare(struct snd_pcm_substream *substream) { struct snd_efw *efw = substream->private_data; - struct snd_pcm_runtime *runtime = substream->runtime; int err; - err = snd_efw_stream_start_duplex(efw, runtime->rate); + err = snd_efw_stream_start_duplex(efw); if (err >= 0) amdtp_stream_pcm_prepare(&efw->rx_stream); diff --git a/sound/firewire/fireworks/fireworks_stream.c b/sound/firewire/fireworks/fireworks_stream.c index 2df39befcde0..e1ebead583e9 100644 --- a/sound/firewire/fireworks/fireworks_stream.c +++ b/sound/firewire/fireworks/fireworks_stream.c @@ -189,47 +189,63 @@ end: return err; } -int snd_efw_stream_start_duplex(struct snd_efw *efw, unsigned int rate) +int snd_efw_stream_reserve_duplex(struct snd_efw *efw, unsigned int rate) { unsigned int curr_rate; - int err = 0; - - // Need no substreams. - if (efw->substreams_counter == 0) - return -EIO; + int err; - /* - * Considering JACK/FFADO streaming: - * TODO: This can be removed hwdep functionality becomes popular. - */ + // Considering JACK/FFADO streaming: + // TODO: This can be removed hwdep functionality becomes popular. err = check_connection_used_by_others(efw, &efw->rx_stream); if (err < 0) - goto end; + return err; - /* stop streams if rate is different */ + // stop streams if rate is different. err = snd_efw_command_get_sampling_rate(efw, &curr_rate); if (err < 0) - goto end; + return err; if (rate == 0) rate = curr_rate; - if (rate != curr_rate || - amdtp_streaming_error(&efw->tx_stream) || - amdtp_streaming_error(&efw->rx_stream)) { + if (rate != curr_rate) { stop_stream(efw, &efw->tx_stream); stop_stream(efw, &efw->rx_stream); } - /* master should be always running */ - if (!amdtp_stream_running(&efw->rx_stream)) { + if (efw->substreams_counter == 0 || rate != curr_rate) { err = snd_efw_command_set_sampling_rate(efw, rate); if (err < 0) - goto end; + return err; + } + + return 0; +} + +int snd_efw_stream_start_duplex(struct snd_efw *efw) +{ + unsigned int rate; + int err = 0; + + // Need no substreams. + 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); + } + + /* master should be always running */ + 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); - goto end; + goto error; } } @@ -238,11 +254,14 @@ int snd_efw_stream_start_duplex(struct snd_efw *efw, unsigned int rate) if (err < 0) { dev_err(&efw->unit->device, "fail to start AMDTP slave stream:%d\n", err); - stop_stream(efw, &efw->tx_stream); - stop_stream(efw, &efw->rx_stream); + goto error; } } -end: + + return 0; +error: + stop_stream(efw, &efw->rx_stream); + stop_stream(efw, &efw->tx_stream); return err; } |