Skip to content

Commit 55162d2

Browse files
takaswietiwai
authored andcommitted
ALSA: fireface: reserve/release isochronous resources in pcm.hw_params/hw_free callbacks
Once allocated, isochronous resources are available for packet streaming, even if the streaming is cancelled. For this reason, current implementation handles allocation of the resources and starting packet streaming at the same time. However, this brings complicated procedure to start packet streaming. This commit separates the allocation and starting. The allocation is done in pcm.hw_params callback and available till pcm.hw_free callback. Even if any XRUN occurs, pcm.prepare callback is done to restart packet streaming for allocated the resources. There are two points to stop packet streaming; in pcm.hw_params and pcm.prepare callbacks. Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp> Signed-off-by: Takashi Iwai <tiwai@suse.de>
1 parent 60aec49 commit 55162d2

File tree

3 files changed

+57
-30
lines changed

3 files changed

+57
-30
lines changed

sound/firewire/fireface/ff-pcm.c

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -211,8 +211,12 @@ static int pcm_capture_hw_params(struct snd_pcm_substream *substream,
211211
return err;
212212

213213
if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) {
214+
unsigned int rate = params_rate(hw_params);
215+
214216
mutex_lock(&ff->mutex);
215-
ff->substreams_counter++;
217+
err = snd_ff_stream_reserve_duplex(ff, rate);
218+
if (err >= 0)
219+
++ff->substreams_counter;
216220
mutex_unlock(&ff->mutex);
217221
}
218222

@@ -231,8 +235,12 @@ static int pcm_playback_hw_params(struct snd_pcm_substream *substream,
231235
return err;
232236

233237
if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) {
238+
unsigned int rate = params_rate(hw_params);
239+
234240
mutex_lock(&ff->mutex);
235-
ff->substreams_counter++;
241+
err = snd_ff_stream_reserve_duplex(ff, rate);
242+
if (err >= 0)
243+
++ff->substreams_counter;
236244
mutex_unlock(&ff->mutex);
237245
}
238246

@@ -246,9 +254,10 @@ static int pcm_capture_hw_free(struct snd_pcm_substream *substream)
246254
mutex_lock(&ff->mutex);
247255

248256
if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN)
249-
ff->substreams_counter--;
257+
--ff->substreams_counter;
250258

251259
snd_ff_stream_stop_duplex(ff);
260+
snd_ff_stream_release_duplex(ff);
252261

253262
mutex_unlock(&ff->mutex);
254263

@@ -262,9 +271,10 @@ static int pcm_playback_hw_free(struct snd_pcm_substream *substream)
262271
mutex_lock(&ff->mutex);
263272

264273
if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN)
265-
ff->substreams_counter--;
274+
--ff->substreams_counter;
266275

267276
snd_ff_stream_stop_duplex(ff);
277+
snd_ff_stream_release_duplex(ff);
268278

269279
mutex_unlock(&ff->mutex);
270280

sound/firewire/fireface/ff-stream.c

Lines changed: 41 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,6 @@ int snd_ff_stream_get_multiplier_mode(enum cip_sfc sfc,
3131
return 0;
3232
}
3333

34-
static void release_resources(struct snd_ff *ff)
35-
{
36-
fw_iso_resources_free(&ff->tx_resources);
37-
fw_iso_resources_free(&ff->rx_resources);
38-
}
39-
4034
static inline void finish_session(struct snd_ff *ff)
4135
{
4236
ff->spec->protocol->finish_session(ff);
@@ -104,36 +98,27 @@ void snd_ff_stream_destroy_duplex(struct snd_ff *ff)
10498
destroy_stream(ff, AMDTP_OUT_STREAM);
10599
}
106100

107-
int snd_ff_stream_start_duplex(struct snd_ff *ff, unsigned int rate)
101+
int snd_ff_stream_reserve_duplex(struct snd_ff *ff, unsigned int rate)
108102
{
109103
unsigned int curr_rate;
110104
enum snd_ff_clock_src src;
111105
int err;
112106

113-
if (ff->substreams_counter == 0)
114-
return 0;
115-
116107
err = ff->spec->protocol->get_clock(ff, &curr_rate, &src);
117108
if (err < 0)
118109
return err;
119-
if (curr_rate != rate ||
120-
amdtp_streaming_error(&ff->tx_stream) ||
121-
amdtp_streaming_error(&ff->rx_stream)) {
122-
finish_session(ff);
110+
111+
if (ff->substreams_counter == 0 || curr_rate != rate) {
112+
enum snd_ff_stream_mode mode;
113+
int i;
123114

124115
amdtp_stream_stop(&ff->tx_stream);
125116
amdtp_stream_stop(&ff->rx_stream);
126117

127-
release_resources(ff);
128-
}
118+
finish_session(ff);
129119

130-
/*
131-
* Regardless of current source of clock signal, drivers transfer some
132-
* packets. Then, the device transfers packets.
133-
*/
134-
if (!amdtp_stream_running(&ff->rx_stream)) {
135-
enum snd_ff_stream_mode mode;
136-
int i;
120+
fw_iso_resources_free(&ff->tx_resources);
121+
fw_iso_resources_free(&ff->rx_resources);
137122

138123
for (i = 0; i < CIP_SFC_COUNT; ++i) {
139124
if (amdtp_rate_table[i] == rate)
@@ -158,8 +143,40 @@ int snd_ff_stream_start_duplex(struct snd_ff *ff, unsigned int rate)
158143

159144
err = ff->spec->protocol->allocate_resources(ff, rate);
160145
if (err < 0)
161-
goto error;
146+
return err;
147+
}
148+
149+
return 0;
150+
}
151+
152+
void snd_ff_stream_release_duplex(struct snd_ff *ff)
153+
{
154+
if (ff->substreams_counter == 0) {
155+
fw_iso_resources_free(&ff->tx_resources);
156+
fw_iso_resources_free(&ff->rx_resources);
157+
}
158+
}
159+
160+
int snd_ff_stream_start_duplex(struct snd_ff *ff, unsigned int rate)
161+
{
162+
int err;
163+
164+
if (ff->substreams_counter == 0)
165+
return 0;
162166

167+
if (amdtp_streaming_error(&ff->tx_stream) ||
168+
amdtp_streaming_error(&ff->rx_stream)) {
169+
amdtp_stream_stop(&ff->tx_stream);
170+
amdtp_stream_stop(&ff->rx_stream);
171+
172+
finish_session(ff);
173+
}
174+
175+
/*
176+
* Regardless of current source of clock signal, drivers transfer some
177+
* packets. Then, the device transfers packets.
178+
*/
179+
if (!amdtp_stream_running(&ff->rx_stream)) {
163180
err = ff->spec->protocol->begin_session(ff, rate);
164181
if (err < 0)
165182
goto error;
@@ -201,7 +218,6 @@ int snd_ff_stream_start_duplex(struct snd_ff *ff, unsigned int rate)
201218
amdtp_stream_stop(&ff->rx_stream);
202219

203220
finish_session(ff);
204-
release_resources(ff);
205221

206222
return err;
207223
}
@@ -214,7 +230,6 @@ void snd_ff_stream_stop_duplex(struct snd_ff *ff)
214230
amdtp_stream_stop(&ff->tx_stream);
215231
amdtp_stream_stop(&ff->rx_stream);
216232
finish_session(ff);
217-
release_resources(ff);
218233
}
219234

220235
void snd_ff_stream_update_duplex(struct snd_ff *ff)

sound/firewire/fireface/ff.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,8 @@ int snd_ff_stream_get_multiplier_mode(enum cip_sfc sfc,
138138
enum snd_ff_stream_mode *mode);
139139
int snd_ff_stream_init_duplex(struct snd_ff *ff);
140140
void snd_ff_stream_destroy_duplex(struct snd_ff *ff);
141+
int snd_ff_stream_reserve_duplex(struct snd_ff *ff, unsigned int rate);
142+
void snd_ff_stream_release_duplex(struct snd_ff *ff);
141143
int snd_ff_stream_start_duplex(struct snd_ff *ff, unsigned int rate);
142144
void snd_ff_stream_stop_duplex(struct snd_ff *ff);
143145
void snd_ff_stream_update_duplex(struct snd_ff *ff);

0 commit comments

Comments
 (0)