forked from ~ljy/RK356X_SDK_RELEASE

hc
2023-12-11 1f93a7dfd1f8d5ff7a5c53246c7534fe2332d6f4
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,74 @@
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);
261
+ err = init_stream(dg00x, &dg00x->tx_stream);
251262 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;
263
+ destroy_stream(dg00x, &dg00x->rx_stream);
256264
257
- return 0;
258
-error:
259
- snd_dg00x_stream_destroy_duplex(dg00x);
265
+ err = amdtp_domain_init(&dg00x->domain);
266
+ if (err < 0) {
267
+ destroy_stream(dg00x, &dg00x->rx_stream);
268
+ destroy_stream(dg00x, &dg00x->tx_stream);
269
+ }
270
+
260271 return err;
261272 }
262273
....@@ -266,35 +277,81 @@
266277 */
267278 void snd_dg00x_stream_destroy_duplex(struct snd_dg00x *dg00x)
268279 {
269
- amdtp_stream_destroy(&dg00x->rx_stream);
270
- fw_iso_resources_destroy(&dg00x->rx_resources);
280
+ amdtp_domain_destroy(&dg00x->domain);
271281
272
- amdtp_stream_destroy(&dg00x->tx_stream);
273
- fw_iso_resources_destroy(&dg00x->tx_resources);
282
+ destroy_stream(dg00x, &dg00x->rx_stream);
283
+ destroy_stream(dg00x, &dg00x->tx_stream);
274284 }
275285
276
-int snd_dg00x_stream_start_duplex(struct snd_dg00x *dg00x, unsigned int rate)
286
+int snd_dg00x_stream_reserve_duplex(struct snd_dg00x *dg00x, unsigned int rate,
287
+ unsigned int frames_per_period,
288
+ unsigned int frames_per_buffer)
277289 {
278290 unsigned int curr_rate;
291
+ int err;
292
+
293
+ err = snd_dg00x_stream_get_local_rate(dg00x, &curr_rate);
294
+ if (err < 0)
295
+ return err;
296
+ if (rate == 0)
297
+ rate = curr_rate;
298
+
299
+ if (dg00x->substreams_counter == 0 || curr_rate != rate) {
300
+ amdtp_domain_stop(&dg00x->domain);
301
+
302
+ finish_session(dg00x);
303
+
304
+ fw_iso_resources_free(&dg00x->tx_resources);
305
+ fw_iso_resources_free(&dg00x->rx_resources);
306
+
307
+ err = snd_dg00x_stream_set_local_rate(dg00x, rate);
308
+ if (err < 0)
309
+ return err;
310
+
311
+ err = keep_resources(dg00x, &dg00x->rx_stream, rate);
312
+ if (err < 0)
313
+ return err;
314
+
315
+ err = keep_resources(dg00x, &dg00x->tx_stream, rate);
316
+ if (err < 0) {
317
+ fw_iso_resources_free(&dg00x->rx_resources);
318
+ return err;
319
+ }
320
+
321
+ err = amdtp_domain_set_events_per_period(&dg00x->domain,
322
+ frames_per_period, frames_per_buffer);
323
+ if (err < 0) {
324
+ fw_iso_resources_free(&dg00x->rx_resources);
325
+ fw_iso_resources_free(&dg00x->tx_resources);
326
+ return err;
327
+ }
328
+ }
329
+
330
+ return 0;
331
+}
332
+
333
+int snd_dg00x_stream_start_duplex(struct snd_dg00x *dg00x)
334
+{
335
+ unsigned int generation = dg00x->rx_resources.generation;
279336 int err = 0;
280337
281338 if (dg00x->substreams_counter == 0)
282
- goto end;
339
+ return 0;
283340
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) ||
341
+ if (amdtp_streaming_error(&dg00x->tx_stream) ||
292342 amdtp_streaming_error(&dg00x->rx_stream)) {
343
+ amdtp_domain_stop(&dg00x->domain);
293344 finish_session(dg00x);
345
+ }
294346
295
- amdtp_stream_stop(&dg00x->tx_stream);
296
- amdtp_stream_stop(&dg00x->rx_stream);
297
- release_resources(dg00x);
347
+ if (generation != fw_parent_device(dg00x->unit)->card->generation) {
348
+ err = fw_iso_resources_update(&dg00x->tx_resources);
349
+ if (err < 0)
350
+ goto error;
351
+
352
+ err = fw_iso_resources_update(&dg00x->rx_resources);
353
+ if (err < 0)
354
+ goto error;
298355 }
299356
300357 /*
....@@ -302,75 +359,52 @@
302359 * which source of clock is used.
303360 */
304361 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;
362
+ int spd = fw_parent_device(dg00x->unit)->max_speed;
312363
313364 err = begin_session(dg00x);
314365 if (err < 0)
315366 goto error;
316367
317
- err = amdtp_stream_start(&dg00x->rx_stream,
318
- dg00x->rx_resources.channel,
319
- fw_parent_device(dg00x->unit)->max_speed);
368
+ err = amdtp_domain_add_stream(&dg00x->domain, &dg00x->rx_stream,
369
+ dg00x->rx_resources.channel, spd);
370
+ if (err < 0)
371
+ goto error;
372
+
373
+ err = amdtp_domain_add_stream(&dg00x->domain, &dg00x->tx_stream,
374
+ dg00x->tx_resources.channel, spd);
375
+ if (err < 0)
376
+ goto error;
377
+
378
+ err = amdtp_domain_start(&dg00x->domain, 0);
320379 if (err < 0)
321380 goto error;
322381
323382 if (!amdtp_stream_wait_callback(&dg00x->rx_stream,
324
- CALLBACK_TIMEOUT)) {
383
+ CALLBACK_TIMEOUT) ||
384
+ !amdtp_stream_wait_callback(&dg00x->tx_stream,
385
+ CALLBACK_TIMEOUT)) {
325386 err = -ETIMEDOUT;
326387 goto error;
327388 }
328389 }
329390
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;
391
+ return 0;
349392 error:
393
+ amdtp_domain_stop(&dg00x->domain);
350394 finish_session(dg00x);
351
-
352
- amdtp_stream_stop(&dg00x->tx_stream);
353
- amdtp_stream_stop(&dg00x->rx_stream);
354
- release_resources(dg00x);
355395
356396 return err;
357397 }
358398
359399 void snd_dg00x_stream_stop_duplex(struct snd_dg00x *dg00x)
360400 {
361
- if (dg00x->substreams_counter > 0)
362
- return;
401
+ if (dg00x->substreams_counter == 0) {
402
+ amdtp_domain_stop(&dg00x->domain);
403
+ finish_session(dg00x);
363404
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);
405
+ fw_iso_resources_free(&dg00x->tx_resources);
406
+ fw_iso_resources_free(&dg00x->rx_resources);
407
+ }
374408 }
375409
376410 void snd_dg00x_stream_update_duplex(struct snd_dg00x *dg00x)