forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-09-20 cf4ce59b3b70238352c7f1729f0f7223214828ad
kernel/sound/firewire/digi00x/digi00x-stream.c
....@@ -1,9 +1,8 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * digi00x-stream.c - a part of driver for Digidesign Digi 002/003 family
34 *
45 * Copyright (c) 2014-2015 Takashi Sakamoto
5
- *
6
- * Licensed under the terms of the GNU General Public License, version 2.
76 */
87
98 #include "digi00x.h"
....@@ -125,11 +124,22 @@
125124
126125 static void finish_session(struct snd_dg00x *dg00x)
127126 {
128
- __be32 data = cpu_to_be32(0x00000003);
127
+ __be32 data;
129128
129
+ data = cpu_to_be32(0x00000003);
130130 snd_fw_transaction(dg00x->unit, TCODE_WRITE_QUADLET_REQUEST,
131131 DG00X_ADDR_BASE + DG00X_OFFSET_STREAMING_SET,
132132 &data, sizeof(data), 0);
133
+
134
+ // Unregister isochronous channels for both direction.
135
+ data = 0;
136
+ snd_fw_transaction(dg00x->unit, TCODE_WRITE_QUADLET_REQUEST,
137
+ DG00X_ADDR_BASE + DG00X_OFFSET_ISOC_CHANNELS,
138
+ &data, sizeof(data), 0);
139
+
140
+ // Just after finishing the session, the device may lost transmitting
141
+ // functionality for a short time.
142
+ msleep(50);
133143 }
134144
135145 static int begin_session(struct snd_dg00x *dg00x)
....@@ -138,11 +148,20 @@
138148 u32 curr;
139149 int err;
140150
151
+ // Register isochronous channels for both direction.
152
+ data = cpu_to_be32((dg00x->tx_resources.channel << 16) |
153
+ dg00x->rx_resources.channel);
154
+ err = snd_fw_transaction(dg00x->unit, TCODE_WRITE_QUADLET_REQUEST,
155
+ DG00X_ADDR_BASE + DG00X_OFFSET_ISOC_CHANNELS,
156
+ &data, sizeof(data), 0);
157
+ if (err < 0)
158
+ return err;
159
+
141160 err = snd_fw_transaction(dg00x->unit, TCODE_READ_QUADLET_REQUEST,
142161 DG00X_ADDR_BASE + DG00X_OFFSET_STREAMING_STATE,
143162 &data, sizeof(data), 0);
144163 if (err < 0)
145
- goto error;
164
+ return err;
146165 curr = be32_to_cpu(data);
147166
148167 if (curr == 0)
....@@ -157,39 +176,23 @@
157176 DG00X_OFFSET_STREAMING_SET,
158177 &data, sizeof(data), 0);
159178 if (err < 0)
160
- goto error;
179
+ break;
161180
162181 msleep(20);
163182 curr--;
164183 }
165184
166
- return 0;
167
-error:
168
- finish_session(dg00x);
169185 return err;
170186 }
171187
172
-static void release_resources(struct snd_dg00x *dg00x)
188
+static int keep_resources(struct snd_dg00x *dg00x, struct amdtp_stream *stream,
189
+ unsigned int rate)
173190 {
174
- __be32 data = 0;
175
-
176
- /* Unregister isochronous channels for both direction. */
177
- snd_fw_transaction(dg00x->unit, TCODE_WRITE_QUADLET_REQUEST,
178
- DG00X_ADDR_BASE + DG00X_OFFSET_ISOC_CHANNELS,
179
- &data, sizeof(data), 0);
180
-
181
- /* Release isochronous resources. */
182
- fw_iso_resources_free(&dg00x->tx_resources);
183
- fw_iso_resources_free(&dg00x->rx_resources);
184
-}
185
-
186
-static int keep_resources(struct snd_dg00x *dg00x, unsigned int rate)
187
-{
188
- unsigned int i;
189
- __be32 data;
191
+ struct fw_iso_resources *resources;
192
+ int i;
190193 int err;
191194
192
- /* Check sampling rate. */
195
+ // Check sampling rate.
193196 for (i = 0; i < SND_DG00X_RATE_COUNT; i++) {
194197 if (snd_dg00x_stream_rates[i] == rate)
195198 break;
....@@ -197,66 +200,76 @@
197200 if (i == SND_DG00X_RATE_COUNT)
198201 return -EINVAL;
199202
200
- /* Keep resources for out-stream. */
201
- err = amdtp_dot_set_parameters(&dg00x->rx_stream, rate,
203
+ if (stream == &dg00x->tx_stream)
204
+ resources = &dg00x->tx_resources;
205
+ else
206
+ resources = &dg00x->rx_resources;
207
+
208
+ err = amdtp_dot_set_parameters(stream, rate,
202209 snd_dg00x_stream_pcm_channels[i]);
203210 if (err < 0)
204211 return err;
205
- err = fw_iso_resources_allocate(&dg00x->rx_resources,
206
- amdtp_stream_get_max_payload(&dg00x->rx_stream),
212
+
213
+ return fw_iso_resources_allocate(resources,
214
+ amdtp_stream_get_max_payload(stream),
207215 fw_parent_device(dg00x->unit)->max_speed);
216
+}
217
+
218
+static int init_stream(struct snd_dg00x *dg00x, struct amdtp_stream *s)
219
+{
220
+ struct fw_iso_resources *resources;
221
+ enum amdtp_stream_direction dir;
222
+ int err;
223
+
224
+ if (s == &dg00x->tx_stream) {
225
+ resources = &dg00x->tx_resources;
226
+ dir = AMDTP_IN_STREAM;
227
+ } else {
228
+ resources = &dg00x->rx_resources;
229
+ dir = AMDTP_OUT_STREAM;
230
+ }
231
+
232
+ err = fw_iso_resources_init(resources, dg00x->unit);
208233 if (err < 0)
209234 return err;
210235
211
- /* Keep resources for in-stream. */
212
- err = amdtp_dot_set_parameters(&dg00x->tx_stream, rate,
213
- snd_dg00x_stream_pcm_channels[i]);
236
+ err = amdtp_dot_init(s, dg00x->unit, dir);
214237 if (err < 0)
215
- return err;
216
- err = fw_iso_resources_allocate(&dg00x->tx_resources,
217
- amdtp_stream_get_max_payload(&dg00x->tx_stream),
218
- fw_parent_device(dg00x->unit)->max_speed);
219
- if (err < 0)
220
- goto error;
238
+ fw_iso_resources_destroy(resources);
221239
222
- /* Register isochronous channels for both direction. */
223
- data = cpu_to_be32((dg00x->tx_resources.channel << 16) |
224
- dg00x->rx_resources.channel);
225
- err = snd_fw_transaction(dg00x->unit, TCODE_WRITE_QUADLET_REQUEST,
226
- DG00X_ADDR_BASE + DG00X_OFFSET_ISOC_CHANNELS,
227
- &data, sizeof(data), 0);
228
- if (err < 0)
229
- goto error;
230
-
231
- return 0;
232
-error:
233
- release_resources(dg00x);
234240 return err;
241
+}
242
+
243
+static void destroy_stream(struct snd_dg00x *dg00x, struct amdtp_stream *s)
244
+{
245
+ amdtp_stream_destroy(s);
246
+
247
+ if (s == &dg00x->tx_stream)
248
+ fw_iso_resources_destroy(&dg00x->tx_resources);
249
+ else
250
+ fw_iso_resources_destroy(&dg00x->rx_resources);
235251 }
236252
237253 int snd_dg00x_stream_init_duplex(struct snd_dg00x *dg00x)
238254 {
239255 int err;
240256
241
- /* For out-stream. */
242
- err = fw_iso_resources_init(&dg00x->rx_resources, dg00x->unit);
257
+ err = init_stream(dg00x, &dg00x->rx_stream);
243258 if (err < 0)
244
- goto error;
245
- err = amdtp_dot_init(&dg00x->rx_stream, dg00x->unit, AMDTP_OUT_STREAM);
246
- if (err < 0)
247
- goto error;
259
+ return err;
248260
249
- /* For in-stream. */
250
- err = fw_iso_resources_init(&dg00x->tx_resources, dg00x->unit);
251
- if (err < 0)
252
- goto error;
253
- err = amdtp_dot_init(&dg00x->tx_stream, dg00x->unit, AMDTP_IN_STREAM);
254
- if (err < 0)
255
- goto error;
261
+ err = init_stream(dg00x, &dg00x->tx_stream);
262
+ if (err < 0) {
263
+ destroy_stream(dg00x, &dg00x->rx_stream);
264
+ return err;
265
+ }
256266
257
- return 0;
258
-error:
259
- snd_dg00x_stream_destroy_duplex(dg00x);
267
+ err = amdtp_domain_init(&dg00x->domain);
268
+ if (err < 0) {
269
+ destroy_stream(dg00x, &dg00x->rx_stream);
270
+ destroy_stream(dg00x, &dg00x->tx_stream);
271
+ }
272
+
260273 return err;
261274 }
262275
....@@ -266,35 +279,81 @@
266279 */
267280 void snd_dg00x_stream_destroy_duplex(struct snd_dg00x *dg00x)
268281 {
269
- amdtp_stream_destroy(&dg00x->rx_stream);
270
- fw_iso_resources_destroy(&dg00x->rx_resources);
282
+ amdtp_domain_destroy(&dg00x->domain);
271283
272
- amdtp_stream_destroy(&dg00x->tx_stream);
273
- fw_iso_resources_destroy(&dg00x->tx_resources);
284
+ destroy_stream(dg00x, &dg00x->rx_stream);
285
+ destroy_stream(dg00x, &dg00x->tx_stream);
274286 }
275287
276
-int snd_dg00x_stream_start_duplex(struct snd_dg00x *dg00x, unsigned int rate)
288
+int snd_dg00x_stream_reserve_duplex(struct snd_dg00x *dg00x, unsigned int rate,
289
+ unsigned int frames_per_period,
290
+ unsigned int frames_per_buffer)
277291 {
278292 unsigned int curr_rate;
293
+ int err;
294
+
295
+ err = snd_dg00x_stream_get_local_rate(dg00x, &curr_rate);
296
+ if (err < 0)
297
+ return err;
298
+ if (rate == 0)
299
+ rate = curr_rate;
300
+
301
+ if (dg00x->substreams_counter == 0 || curr_rate != rate) {
302
+ amdtp_domain_stop(&dg00x->domain);
303
+
304
+ finish_session(dg00x);
305
+
306
+ fw_iso_resources_free(&dg00x->tx_resources);
307
+ fw_iso_resources_free(&dg00x->rx_resources);
308
+
309
+ err = snd_dg00x_stream_set_local_rate(dg00x, rate);
310
+ if (err < 0)
311
+ return err;
312
+
313
+ err = keep_resources(dg00x, &dg00x->rx_stream, rate);
314
+ if (err < 0)
315
+ return err;
316
+
317
+ err = keep_resources(dg00x, &dg00x->tx_stream, rate);
318
+ if (err < 0) {
319
+ fw_iso_resources_free(&dg00x->rx_resources);
320
+ return err;
321
+ }
322
+
323
+ err = amdtp_domain_set_events_per_period(&dg00x->domain,
324
+ frames_per_period, frames_per_buffer);
325
+ if (err < 0) {
326
+ fw_iso_resources_free(&dg00x->rx_resources);
327
+ fw_iso_resources_free(&dg00x->tx_resources);
328
+ return err;
329
+ }
330
+ }
331
+
332
+ return 0;
333
+}
334
+
335
+int snd_dg00x_stream_start_duplex(struct snd_dg00x *dg00x)
336
+{
337
+ unsigned int generation = dg00x->rx_resources.generation;
279338 int err = 0;
280339
281340 if (dg00x->substreams_counter == 0)
282
- goto end;
341
+ return 0;
283342
284
- /* Check current sampling rate. */
285
- err = snd_dg00x_stream_get_local_rate(dg00x, &curr_rate);
286
- if (err < 0)
287
- goto error;
288
- if (rate == 0)
289
- rate = curr_rate;
290
- if (curr_rate != rate ||
291
- amdtp_streaming_error(&dg00x->tx_stream) ||
343
+ if (amdtp_streaming_error(&dg00x->tx_stream) ||
292344 amdtp_streaming_error(&dg00x->rx_stream)) {
345
+ amdtp_domain_stop(&dg00x->domain);
293346 finish_session(dg00x);
347
+ }
294348
295
- amdtp_stream_stop(&dg00x->tx_stream);
296
- amdtp_stream_stop(&dg00x->rx_stream);
297
- release_resources(dg00x);
349
+ if (generation != fw_parent_device(dg00x->unit)->card->generation) {
350
+ err = fw_iso_resources_update(&dg00x->tx_resources);
351
+ if (err < 0)
352
+ goto error;
353
+
354
+ err = fw_iso_resources_update(&dg00x->rx_resources);
355
+ if (err < 0)
356
+ goto error;
298357 }
299358
300359 /*
....@@ -302,75 +361,52 @@
302361 * which source of clock is used.
303362 */
304363 if (!amdtp_stream_running(&dg00x->rx_stream)) {
305
- err = snd_dg00x_stream_set_local_rate(dg00x, rate);
306
- if (err < 0)
307
- goto error;
308
-
309
- err = keep_resources(dg00x, rate);
310
- if (err < 0)
311
- goto error;
364
+ int spd = fw_parent_device(dg00x->unit)->max_speed;
312365
313366 err = begin_session(dg00x);
314367 if (err < 0)
315368 goto error;
316369
317
- err = amdtp_stream_start(&dg00x->rx_stream,
318
- dg00x->rx_resources.channel,
319
- fw_parent_device(dg00x->unit)->max_speed);
370
+ err = amdtp_domain_add_stream(&dg00x->domain, &dg00x->rx_stream,
371
+ dg00x->rx_resources.channel, spd);
372
+ if (err < 0)
373
+ goto error;
374
+
375
+ err = amdtp_domain_add_stream(&dg00x->domain, &dg00x->tx_stream,
376
+ dg00x->tx_resources.channel, spd);
377
+ if (err < 0)
378
+ goto error;
379
+
380
+ err = amdtp_domain_start(&dg00x->domain, 0);
320381 if (err < 0)
321382 goto error;
322383
323384 if (!amdtp_stream_wait_callback(&dg00x->rx_stream,
324
- CALLBACK_TIMEOUT)) {
385
+ CALLBACK_TIMEOUT) ||
386
+ !amdtp_stream_wait_callback(&dg00x->tx_stream,
387
+ CALLBACK_TIMEOUT)) {
325388 err = -ETIMEDOUT;
326389 goto error;
327390 }
328391 }
329392
330
- /*
331
- * The value of SYT field in transmitted packets is always 0x0000. Thus,
332
- * duplex streams with timestamp synchronization cannot be built.
333
- */
334
- if (!amdtp_stream_running(&dg00x->tx_stream)) {
335
- err = amdtp_stream_start(&dg00x->tx_stream,
336
- dg00x->tx_resources.channel,
337
- fw_parent_device(dg00x->unit)->max_speed);
338
- if (err < 0)
339
- goto error;
340
-
341
- if (!amdtp_stream_wait_callback(&dg00x->tx_stream,
342
- CALLBACK_TIMEOUT)) {
343
- err = -ETIMEDOUT;
344
- goto error;
345
- }
346
- }
347
-end:
348
- return err;
393
+ return 0;
349394 error:
395
+ amdtp_domain_stop(&dg00x->domain);
350396 finish_session(dg00x);
351
-
352
- amdtp_stream_stop(&dg00x->tx_stream);
353
- amdtp_stream_stop(&dg00x->rx_stream);
354
- release_resources(dg00x);
355397
356398 return err;
357399 }
358400
359401 void snd_dg00x_stream_stop_duplex(struct snd_dg00x *dg00x)
360402 {
361
- if (dg00x->substreams_counter > 0)
362
- return;
403
+ if (dg00x->substreams_counter == 0) {
404
+ amdtp_domain_stop(&dg00x->domain);
405
+ finish_session(dg00x);
363406
364
- amdtp_stream_stop(&dg00x->tx_stream);
365
- amdtp_stream_stop(&dg00x->rx_stream);
366
- finish_session(dg00x);
367
- release_resources(dg00x);
368
-
369
- /*
370
- * Just after finishing the session, the device may lost transmitting
371
- * functionality for a short time.
372
- */
373
- msleep(50);
407
+ fw_iso_resources_free(&dg00x->tx_resources);
408
+ fw_iso_resources_free(&dg00x->rx_resources);
409
+ }
374410 }
375411
376412 void snd_dg00x_stream_update_duplex(struct snd_dg00x *dg00x)