ALSA: oxfw: configure packet format in pcm.hw_params callback
authorTakashi Sakamoto <o-takashi@sakamocchi.jp>
Wed, 12 Jun 2019 08:44:21 +0000 (17:44 +0900)
committerTakashi Iwai <tiwai@suse.de>
Wed, 12 Jun 2019 13:27:00 +0000 (15:27 +0200)
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 packet format in pcm.hw_params callback.

Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
sound/firewire/oxfw/oxfw-midi.c
sound/firewire/oxfw/oxfw-pcm.c
sound/firewire/oxfw/oxfw-stream.c
sound/firewire/oxfw/oxfw.h

index 092493497f1abc26c8dcd745ea8ba6a423cf9b7e..9ba62778add29b1d91fd6b0ff663bf397ceb3c46 100644 (file)
@@ -19,8 +19,11 @@ static int midi_capture_open(struct snd_rawmidi_substream *substream)
 
        mutex_lock(&oxfw->mutex);
 
-       ++oxfw->substreams_count;
-       err = snd_oxfw_stream_start_duplex(oxfw, &oxfw->tx_stream, 0, 0);
+       err = snd_oxfw_stream_reserve_duplex(oxfw, &oxfw->tx_stream, 0, 0);
+       if (err >= 0) {
+               ++oxfw->substreams_count;
+               err = snd_oxfw_stream_start_duplex(oxfw);
+       }
 
        mutex_unlock(&oxfw->mutex);
 
@@ -41,8 +44,11 @@ static int midi_playback_open(struct snd_rawmidi_substream *substream)
 
        mutex_lock(&oxfw->mutex);
 
-       ++oxfw->substreams_count;
-       err = snd_oxfw_stream_start_duplex(oxfw, &oxfw->rx_stream, 0, 0);
+       err = snd_oxfw_stream_reserve_duplex(oxfw, &oxfw->rx_stream, 0, 0);
+       if (err >= 0) {
+               ++oxfw->substreams_count;
+               err = snd_oxfw_stream_start_duplex(oxfw);
+       }
 
        mutex_unlock(&oxfw->mutex);
 
index 79c8e514bed93b38ad856dc64dfb549a8130ce41..b08b850d53ea7aa276f2b66c7a1d993ca61ac6a5 100644 (file)
@@ -219,12 +219,18 @@ static int pcm_capture_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);
+               unsigned int channels = params_channels(hw_params);
+
                mutex_lock(&oxfw->mutex);
-               ++oxfw->substreams_count;
+               err = snd_oxfw_stream_reserve_duplex(oxfw, &oxfw->tx_stream,
+                                                    rate, channels);
+               if (err >= 0)
+                       ++oxfw->substreams_count;
                mutex_unlock(&oxfw->mutex);
        }
 
-       return 0;
+       return err;
 }
 static int pcm_playback_hw_params(struct snd_pcm_substream *substream,
                                  struct snd_pcm_hw_params *hw_params)
@@ -238,8 +244,14 @@ static int pcm_playback_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);
+               unsigned int channels = params_channels(hw_params);
+
                mutex_lock(&oxfw->mutex);
-               ++oxfw->substreams_count;
+               err = snd_oxfw_stream_reserve_duplex(oxfw, &oxfw->tx_stream,
+                                                    rate, channels);
+               if (err >= 0)
+                       ++oxfw->substreams_count;
                mutex_unlock(&oxfw->mutex);
        }
 
@@ -280,12 +292,10 @@ static int pcm_playback_hw_free(struct snd_pcm_substream *substream)
 static int pcm_capture_prepare(struct snd_pcm_substream *substream)
 {
        struct snd_oxfw *oxfw = substream->private_data;
-       struct snd_pcm_runtime *runtime = substream->runtime;
        int err;
 
        mutex_lock(&oxfw->mutex);
-       err = snd_oxfw_stream_start_duplex(oxfw, &oxfw->tx_stream,
-                                          runtime->rate, runtime->channels);
+       err = snd_oxfw_stream_start_duplex(oxfw);
        mutex_unlock(&oxfw->mutex);
        if (err < 0)
                goto end;
@@ -297,12 +307,10 @@ end:
 static int pcm_playback_prepare(struct snd_pcm_substream *substream)
 {
        struct snd_oxfw *oxfw = substream->private_data;
-       struct snd_pcm_runtime *runtime = substream->runtime;
        int err;
 
        mutex_lock(&oxfw->mutex);
-       err = snd_oxfw_stream_start_duplex(oxfw, &oxfw->rx_stream,
-                                          runtime->rate, runtime->channels);
+       err = snd_oxfw_stream_start_duplex(oxfw);
        mutex_unlock(&oxfw->mutex);
        if (err < 0)
                goto end;
index ebfe0777773b676be0c8a880e1cf20978307440d..373154d8ee0e23779dd1bc80d0ac87bec4f385fa 100644 (file)
@@ -236,16 +236,13 @@ static int init_stream(struct snd_oxfw *oxfw, struct amdtp_stream *stream)
        return 0;
 }
 
-int snd_oxfw_stream_start_duplex(struct snd_oxfw *oxfw,
-                                struct amdtp_stream *stream,
-                                unsigned int rate, unsigned int pcm_channels)
+int snd_oxfw_stream_reserve_duplex(struct snd_oxfw *oxfw,
+                                  struct amdtp_stream *stream,
+                                  unsigned int rate, unsigned int pcm_channels)
 {
        struct snd_oxfw_stream_formation formation;
        enum avc_general_plug_dir dir;
-       int err = 0;
-
-       if (oxfw->substreams_count == 0)
-               return -EIO;
+       int err;
 
        // Considering JACK/FFADO streaming:
        // TODO: This can be removed hwdep functionality becomes popular.
@@ -266,14 +263,11 @@ int snd_oxfw_stream_start_duplex(struct snd_oxfw *oxfw,
        err = snd_oxfw_stream_get_current_formation(oxfw, dir, &formation);
        if (err < 0)
                return err;
-       if (rate == 0)
+       if (rate == 0) {
                rate = formation.rate;
-       if (pcm_channels == 0)
                pcm_channels = formation.pcm;
-
-       if (formation.rate != rate || formation.pcm != pcm_channels ||
-           amdtp_streaming_error(&oxfw->rx_stream) ||
-           amdtp_streaming_error(&oxfw->tx_stream)) {
+       }
+       if (formation.rate != rate || formation.pcm != pcm_channels) {
                amdtp_stream_stop(&oxfw->rx_stream);
                cmp_connection_break(&oxfw->in_conn);
 
@@ -281,7 +275,10 @@ int snd_oxfw_stream_start_duplex(struct snd_oxfw *oxfw,
                        amdtp_stream_stop(&oxfw->tx_stream);
                        cmp_connection_break(&oxfw->out_conn);
                }
+       }
 
+       if (oxfw->substreams_count == 0 ||
+           formation.rate != rate || formation.pcm != pcm_channels) {
                err = set_stream_format(oxfw, stream, rate, pcm_channels);
                if (err < 0) {
                        dev_err(&oxfw->unit->device,
@@ -290,6 +287,27 @@ int snd_oxfw_stream_start_duplex(struct snd_oxfw *oxfw,
                }
        }
 
+       return 0;
+}
+
+int snd_oxfw_stream_start_duplex(struct snd_oxfw *oxfw)
+{
+       int err;
+
+       if (oxfw->substreams_count == 0)
+               return -EIO;
+
+       if (amdtp_streaming_error(&oxfw->rx_stream) ||
+           amdtp_streaming_error(&oxfw->tx_stream)) {
+               amdtp_stream_stop(&oxfw->rx_stream);
+               cmp_connection_break(&oxfw->in_conn);
+
+               if (oxfw->has_output) {
+                       amdtp_stream_stop(&oxfw->tx_stream);
+                       cmp_connection_break(&oxfw->out_conn);
+               }
+       }
+
        if (!amdtp_stream_running(&oxfw->rx_stream)) {
                err = start_stream(oxfw, &oxfw->rx_stream);
                if (err < 0) {
index e0c825288a240f054363c0e0d917f968b7a1dd98..d4d4926c28cfe96f0077e36e7fe3826b732048b9 100644 (file)
@@ -99,9 +99,10 @@ int avc_general_inquiry_sig_fmt(struct fw_unit *unit, unsigned int rate,
                                unsigned short pid);
 
 int snd_oxfw_stream_init_duplex(struct snd_oxfw *oxfw);
-int snd_oxfw_stream_start_duplex(struct snd_oxfw *oxfw,
-                                 struct amdtp_stream *stream,
-                                 unsigned int rate, unsigned int pcm_channels);
+int snd_oxfw_stream_reserve_duplex(struct snd_oxfw *oxfw,
+                                  struct amdtp_stream *stream,
+                                  unsigned int rate, unsigned int pcm_channels);
+int snd_oxfw_stream_start_duplex(struct snd_oxfw *oxfw);
 void snd_oxfw_stream_stop_duplex(struct snd_oxfw *oxfw);
 void snd_oxfw_stream_destroy_duplex(struct snd_oxfw *oxfw);
 void snd_oxfw_stream_update_duplex(struct snd_oxfw *oxfw);