Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/sound/usb/6fire/pcm.c
29269 views
1
// SPDX-License-Identifier: GPL-2.0-or-later
2
/*
3
* Linux driver for TerraTec DMX 6Fire USB
4
*
5
* PCM driver
6
*
7
* Author: Torsten Schenk <[email protected]>
8
* Created: Jan 01, 2011
9
* Copyright: (C) Torsten Schenk
10
*/
11
12
#include "pcm.h"
13
#include "chip.h"
14
#include "comm.h"
15
#include "control.h"
16
17
enum {
18
OUT_N_CHANNELS = 6, IN_N_CHANNELS = 4
19
};
20
21
/* keep next two synced with
22
* FW_EP_W_MAX_PACKET_SIZE[] and RATES_MAX_PACKET_SIZE
23
* and CONTROL_RATE_XXX in control.h */
24
static const int rates_in_packet_size[] = { 228, 228, 420, 420, 404, 404 };
25
static const int rates_out_packet_size[] = { 228, 228, 420, 420, 604, 604 };
26
static const int rates[] = { 44100, 48000, 88200, 96000, 176400, 192000 };
27
static const int rates_alsaid[] = {
28
SNDRV_PCM_RATE_44100, SNDRV_PCM_RATE_48000,
29
SNDRV_PCM_RATE_88200, SNDRV_PCM_RATE_96000,
30
SNDRV_PCM_RATE_176400, SNDRV_PCM_RATE_192000 };
31
32
enum { /* settings for pcm */
33
OUT_EP = 6, IN_EP = 2, MAX_BUFSIZE = 128 * 1024
34
};
35
36
enum { /* pcm streaming states */
37
STREAM_DISABLED, /* no pcm streaming */
38
STREAM_STARTING, /* pcm streaming requested, waiting to become ready */
39
STREAM_RUNNING, /* pcm streaming running */
40
STREAM_STOPPING
41
};
42
43
static const struct snd_pcm_hardware pcm_hw = {
44
.info = SNDRV_PCM_INFO_MMAP |
45
SNDRV_PCM_INFO_INTERLEAVED |
46
SNDRV_PCM_INFO_BLOCK_TRANSFER |
47
SNDRV_PCM_INFO_MMAP_VALID |
48
SNDRV_PCM_INFO_BATCH,
49
50
.formats = SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE,
51
52
.rates = SNDRV_PCM_RATE_44100 |
53
SNDRV_PCM_RATE_48000 |
54
SNDRV_PCM_RATE_88200 |
55
SNDRV_PCM_RATE_96000 |
56
SNDRV_PCM_RATE_176400 |
57
SNDRV_PCM_RATE_192000,
58
59
.rate_min = 44100,
60
.rate_max = 192000,
61
.channels_min = 1,
62
.channels_max = 0, /* set in pcm_open, depending on capture/playback */
63
.buffer_bytes_max = MAX_BUFSIZE,
64
.period_bytes_min = PCM_N_PACKETS_PER_URB * (PCM_MAX_PACKET_SIZE - 4),
65
.period_bytes_max = MAX_BUFSIZE,
66
.periods_min = 2,
67
.periods_max = 1024
68
};
69
70
static int usb6fire_pcm_set_rate(struct pcm_runtime *rt)
71
{
72
int ret;
73
struct control_runtime *ctrl_rt = rt->chip->control;
74
75
ctrl_rt->usb_streaming = false;
76
ret = ctrl_rt->update_streaming(ctrl_rt);
77
if (ret < 0) {
78
dev_err(&rt->chip->dev->dev,
79
"error stopping streaming while setting samplerate %d.\n",
80
rates[rt->rate]);
81
return ret;
82
}
83
84
ret = ctrl_rt->set_rate(ctrl_rt, rt->rate);
85
if (ret < 0) {
86
dev_err(&rt->chip->dev->dev,
87
"error setting samplerate %d.\n",
88
rates[rt->rate]);
89
return ret;
90
}
91
92
ret = ctrl_rt->set_channels(ctrl_rt, OUT_N_CHANNELS, IN_N_CHANNELS,
93
false, false);
94
if (ret < 0) {
95
dev_err(&rt->chip->dev->dev,
96
"error initializing channels while setting samplerate %d.\n",
97
rates[rt->rate]);
98
return ret;
99
}
100
101
ctrl_rt->usb_streaming = true;
102
ret = ctrl_rt->update_streaming(ctrl_rt);
103
if (ret < 0) {
104
dev_err(&rt->chip->dev->dev,
105
"error starting streaming while setting samplerate %d.\n",
106
rates[rt->rate]);
107
return ret;
108
}
109
110
rt->in_n_analog = IN_N_CHANNELS;
111
rt->out_n_analog = OUT_N_CHANNELS;
112
rt->in_packet_size = rates_in_packet_size[rt->rate];
113
rt->out_packet_size = rates_out_packet_size[rt->rate];
114
return 0;
115
}
116
117
static struct pcm_substream *usb6fire_pcm_get_substream(
118
struct snd_pcm_substream *alsa_sub)
119
{
120
struct pcm_runtime *rt = snd_pcm_substream_chip(alsa_sub);
121
122
if (alsa_sub->stream == SNDRV_PCM_STREAM_PLAYBACK)
123
return &rt->playback;
124
else if (alsa_sub->stream == SNDRV_PCM_STREAM_CAPTURE)
125
return &rt->capture;
126
dev_err(&rt->chip->dev->dev, "error getting pcm substream slot.\n");
127
return NULL;
128
}
129
130
/* call with stream_mutex locked */
131
static void usb6fire_pcm_stream_stop(struct pcm_runtime *rt)
132
{
133
int i;
134
struct control_runtime *ctrl_rt = rt->chip->control;
135
136
if (rt->stream_state != STREAM_DISABLED) {
137
138
rt->stream_state = STREAM_STOPPING;
139
140
for (i = 0; i < PCM_N_URBS; i++) {
141
usb_kill_urb(&rt->in_urbs[i].instance);
142
usb_kill_urb(&rt->out_urbs[i].instance);
143
}
144
ctrl_rt->usb_streaming = false;
145
ctrl_rt->update_streaming(ctrl_rt);
146
rt->stream_state = STREAM_DISABLED;
147
}
148
}
149
150
/* call with stream_mutex locked */
151
static int usb6fire_pcm_stream_start(struct pcm_runtime *rt)
152
{
153
int ret;
154
int i;
155
int k;
156
struct usb_iso_packet_descriptor *packet;
157
158
if (rt->stream_state == STREAM_DISABLED) {
159
/* submit our in urbs */
160
rt->stream_wait_cond = false;
161
rt->stream_state = STREAM_STARTING;
162
for (i = 0; i < PCM_N_URBS; i++) {
163
for (k = 0; k < PCM_N_PACKETS_PER_URB; k++) {
164
packet = &rt->in_urbs[i].packets[k];
165
packet->offset = k * rt->in_packet_size;
166
packet->length = rt->in_packet_size;
167
packet->actual_length = 0;
168
packet->status = 0;
169
}
170
ret = usb_submit_urb(&rt->in_urbs[i].instance,
171
GFP_ATOMIC);
172
if (ret) {
173
usb6fire_pcm_stream_stop(rt);
174
return ret;
175
}
176
}
177
178
/* wait for first out urb to return (sent in urb handler) */
179
wait_event_timeout(rt->stream_wait_queue, rt->stream_wait_cond,
180
HZ);
181
if (rt->stream_wait_cond)
182
rt->stream_state = STREAM_RUNNING;
183
else {
184
usb6fire_pcm_stream_stop(rt);
185
return -EIO;
186
}
187
}
188
return 0;
189
}
190
191
/* call with substream locked */
192
static void usb6fire_pcm_capture(struct pcm_substream *sub, struct pcm_urb *urb)
193
{
194
int i;
195
int frame;
196
int frame_count;
197
unsigned int total_length = 0;
198
struct pcm_runtime *rt = snd_pcm_substream_chip(sub->instance);
199
struct snd_pcm_runtime *alsa_rt = sub->instance->runtime;
200
u32 *src = NULL;
201
u32 *dest = (u32 *) (alsa_rt->dma_area + sub->dma_off
202
* (alsa_rt->frame_bits >> 3));
203
u32 *dest_end = (u32 *) (alsa_rt->dma_area + alsa_rt->buffer_size
204
* (alsa_rt->frame_bits >> 3));
205
int bytes_per_frame = alsa_rt->channels << 2;
206
207
for (i = 0; i < PCM_N_PACKETS_PER_URB; i++) {
208
/* at least 4 header bytes for valid packet.
209
* after that: 32 bits per sample for analog channels */
210
if (urb->packets[i].actual_length > 4)
211
frame_count = (urb->packets[i].actual_length - 4)
212
/ (rt->in_n_analog << 2);
213
else
214
frame_count = 0;
215
216
if (alsa_rt->format == SNDRV_PCM_FORMAT_S24_LE)
217
src = (u32 *) (urb->buffer + total_length);
218
else if (alsa_rt->format == SNDRV_PCM_FORMAT_S32_LE)
219
src = (u32 *) (urb->buffer - 1 + total_length);
220
else
221
return;
222
src++; /* skip leading 4 bytes of every packet */
223
total_length += urb->packets[i].length;
224
for (frame = 0; frame < frame_count; frame++) {
225
memcpy(dest, src, bytes_per_frame);
226
dest += alsa_rt->channels;
227
src += rt->in_n_analog;
228
sub->dma_off++;
229
sub->period_off++;
230
if (dest == dest_end) {
231
sub->dma_off = 0;
232
dest = (u32 *) alsa_rt->dma_area;
233
}
234
}
235
}
236
}
237
238
/* call with substream locked */
239
static void usb6fire_pcm_playback(struct pcm_substream *sub,
240
struct pcm_urb *urb)
241
{
242
int i;
243
int frame;
244
int frame_count;
245
struct pcm_runtime *rt = snd_pcm_substream_chip(sub->instance);
246
struct snd_pcm_runtime *alsa_rt = sub->instance->runtime;
247
u32 *src = (u32 *) (alsa_rt->dma_area + sub->dma_off
248
* (alsa_rt->frame_bits >> 3));
249
u32 *src_end = (u32 *) (alsa_rt->dma_area + alsa_rt->buffer_size
250
* (alsa_rt->frame_bits >> 3));
251
u32 *dest;
252
int bytes_per_frame = alsa_rt->channels << 2;
253
254
if (alsa_rt->format == SNDRV_PCM_FORMAT_S32_LE)
255
dest = (u32 *) (urb->buffer - 1);
256
else if (alsa_rt->format == SNDRV_PCM_FORMAT_S24_LE)
257
dest = (u32 *) (urb->buffer);
258
else {
259
dev_err(&rt->chip->dev->dev, "Unknown sample format.");
260
return;
261
}
262
263
for (i = 0; i < PCM_N_PACKETS_PER_URB; i++) {
264
/* at least 4 header bytes for valid packet.
265
* after that: 32 bits per sample for analog channels */
266
if (urb->packets[i].length > 4)
267
frame_count = (urb->packets[i].length - 4)
268
/ (rt->out_n_analog << 2);
269
else
270
frame_count = 0;
271
dest++; /* skip leading 4 bytes of every frame */
272
for (frame = 0; frame < frame_count; frame++) {
273
memcpy(dest, src, bytes_per_frame);
274
src += alsa_rt->channels;
275
dest += rt->out_n_analog;
276
sub->dma_off++;
277
sub->period_off++;
278
if (src == src_end) {
279
src = (u32 *) alsa_rt->dma_area;
280
sub->dma_off = 0;
281
}
282
}
283
}
284
}
285
286
static void usb6fire_pcm_in_urb_handler(struct urb *usb_urb)
287
{
288
struct pcm_urb *in_urb = usb_urb->context;
289
struct pcm_urb *out_urb = in_urb->peer;
290
struct pcm_runtime *rt = in_urb->chip->pcm;
291
struct pcm_substream *sub;
292
bool period_elapsed;
293
int total_length = 0;
294
int frame_count;
295
int frame;
296
int channel;
297
int i;
298
u8 *dest;
299
300
if (usb_urb->status || rt->panic || rt->stream_state == STREAM_STOPPING)
301
return;
302
for (i = 0; i < PCM_N_PACKETS_PER_URB; i++)
303
if (in_urb->packets[i].status) {
304
rt->panic = true;
305
return;
306
}
307
308
if (rt->stream_state == STREAM_DISABLED) {
309
dev_err(&rt->chip->dev->dev,
310
"internal error: stream disabled in in-urb handler.\n");
311
return;
312
}
313
314
/* receive our capture data */
315
sub = &rt->capture;
316
period_elapsed = false;
317
scoped_guard(spinlock_irqsave, &sub->lock) {
318
if (sub->active) {
319
usb6fire_pcm_capture(sub, in_urb);
320
if (sub->period_off >= sub->instance->runtime->period_size) {
321
sub->period_off %= sub->instance->runtime->period_size;
322
period_elapsed = true;
323
}
324
}
325
}
326
if (period_elapsed)
327
snd_pcm_period_elapsed(sub->instance);
328
329
/* setup out urb structure */
330
for (i = 0; i < PCM_N_PACKETS_PER_URB; i++) {
331
out_urb->packets[i].offset = total_length;
332
out_urb->packets[i].length = (in_urb->packets[i].actual_length
333
- 4) / (rt->in_n_analog << 2)
334
* (rt->out_n_analog << 2) + 4;
335
out_urb->packets[i].status = 0;
336
total_length += out_urb->packets[i].length;
337
}
338
memset(out_urb->buffer, 0, total_length);
339
340
/* now send our playback data (if a free out urb was found) */
341
sub = &rt->playback;
342
period_elapsed = false;
343
scoped_guard(spinlock_irqsave, &sub->lock) {
344
if (sub->active) {
345
usb6fire_pcm_playback(sub, out_urb);
346
if (sub->period_off >= sub->instance->runtime->period_size) {
347
sub->period_off %= sub->instance->runtime->period_size;
348
period_elapsed = true;
349
}
350
}
351
}
352
if (period_elapsed)
353
snd_pcm_period_elapsed(sub->instance);
354
355
/* setup the 4th byte of each sample (0x40 for analog channels) */
356
dest = out_urb->buffer;
357
for (i = 0; i < PCM_N_PACKETS_PER_URB; i++)
358
if (out_urb->packets[i].length >= 4) {
359
frame_count = (out_urb->packets[i].length - 4)
360
/ (rt->out_n_analog << 2);
361
*(dest++) = 0xaa;
362
*(dest++) = 0xaa;
363
*(dest++) = frame_count;
364
*(dest++) = 0x00;
365
for (frame = 0; frame < frame_count; frame++)
366
for (channel = 0;
367
channel < rt->out_n_analog;
368
channel++) {
369
dest += 3; /* skip sample data */
370
*(dest++) = 0x40;
371
}
372
}
373
usb_submit_urb(&out_urb->instance, GFP_ATOMIC);
374
usb_submit_urb(&in_urb->instance, GFP_ATOMIC);
375
}
376
377
static void usb6fire_pcm_out_urb_handler(struct urb *usb_urb)
378
{
379
struct pcm_urb *urb = usb_urb->context;
380
struct pcm_runtime *rt = urb->chip->pcm;
381
382
if (rt->stream_state == STREAM_STARTING) {
383
rt->stream_wait_cond = true;
384
wake_up(&rt->stream_wait_queue);
385
}
386
}
387
388
static int usb6fire_pcm_open(struct snd_pcm_substream *alsa_sub)
389
{
390
struct pcm_runtime *rt = snd_pcm_substream_chip(alsa_sub);
391
struct pcm_substream *sub = NULL;
392
struct snd_pcm_runtime *alsa_rt = alsa_sub->runtime;
393
394
if (rt->panic)
395
return -EPIPE;
396
397
guard(mutex)(&rt->stream_mutex);
398
alsa_rt->hw = pcm_hw;
399
400
if (alsa_sub->stream == SNDRV_PCM_STREAM_PLAYBACK) {
401
if (rt->rate < ARRAY_SIZE(rates))
402
alsa_rt->hw.rates = rates_alsaid[rt->rate];
403
alsa_rt->hw.channels_max = OUT_N_CHANNELS;
404
sub = &rt->playback;
405
} else if (alsa_sub->stream == SNDRV_PCM_STREAM_CAPTURE) {
406
if (rt->rate < ARRAY_SIZE(rates))
407
alsa_rt->hw.rates = rates_alsaid[rt->rate];
408
alsa_rt->hw.channels_max = IN_N_CHANNELS;
409
sub = &rt->capture;
410
}
411
412
if (!sub) {
413
dev_err(&rt->chip->dev->dev, "invalid stream type.\n");
414
return -EINVAL;
415
}
416
417
sub->instance = alsa_sub;
418
sub->active = false;
419
return 0;
420
}
421
422
static int usb6fire_pcm_close(struct snd_pcm_substream *alsa_sub)
423
{
424
struct pcm_runtime *rt = snd_pcm_substream_chip(alsa_sub);
425
struct pcm_substream *sub = usb6fire_pcm_get_substream(alsa_sub);
426
427
if (rt->panic)
428
return 0;
429
430
guard(mutex)(&rt->stream_mutex);
431
if (sub) {
432
/* deactivate substream */
433
scoped_guard(spinlock_irqsave, &sub->lock) {
434
sub->instance = NULL;
435
sub->active = false;
436
}
437
438
/* all substreams closed? if so, stop streaming */
439
if (!rt->playback.instance && !rt->capture.instance) {
440
usb6fire_pcm_stream_stop(rt);
441
rt->rate = ARRAY_SIZE(rates);
442
}
443
}
444
return 0;
445
}
446
447
static int usb6fire_pcm_prepare(struct snd_pcm_substream *alsa_sub)
448
{
449
struct pcm_runtime *rt = snd_pcm_substream_chip(alsa_sub);
450
struct pcm_substream *sub = usb6fire_pcm_get_substream(alsa_sub);
451
struct snd_pcm_runtime *alsa_rt = alsa_sub->runtime;
452
int ret;
453
454
if (rt->panic)
455
return -EPIPE;
456
if (!sub)
457
return -ENODEV;
458
459
guard(mutex)(&rt->stream_mutex);
460
sub->dma_off = 0;
461
sub->period_off = 0;
462
463
if (rt->stream_state == STREAM_DISABLED) {
464
for (rt->rate = 0; rt->rate < ARRAY_SIZE(rates); rt->rate++)
465
if (alsa_rt->rate == rates[rt->rate])
466
break;
467
if (rt->rate == ARRAY_SIZE(rates)) {
468
dev_err(&rt->chip->dev->dev,
469
"invalid rate %d in prepare.\n",
470
alsa_rt->rate);
471
return -EINVAL;
472
}
473
474
ret = usb6fire_pcm_set_rate(rt);
475
if (ret)
476
return ret;
477
ret = usb6fire_pcm_stream_start(rt);
478
if (ret) {
479
dev_err(&rt->chip->dev->dev,
480
"could not start pcm stream.\n");
481
return ret;
482
}
483
}
484
return 0;
485
}
486
487
static int usb6fire_pcm_trigger(struct snd_pcm_substream *alsa_sub, int cmd)
488
{
489
struct pcm_substream *sub = usb6fire_pcm_get_substream(alsa_sub);
490
struct pcm_runtime *rt = snd_pcm_substream_chip(alsa_sub);
491
492
if (rt->panic)
493
return -EPIPE;
494
if (!sub)
495
return -ENODEV;
496
497
guard(spinlock_irqsave)(&sub->lock);
498
switch (cmd) {
499
case SNDRV_PCM_TRIGGER_START:
500
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
501
sub->active = true;
502
return 0;
503
504
case SNDRV_PCM_TRIGGER_STOP:
505
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
506
sub->active = false;
507
return 0;
508
509
default:
510
return -EINVAL;
511
}
512
}
513
514
static snd_pcm_uframes_t usb6fire_pcm_pointer(
515
struct snd_pcm_substream *alsa_sub)
516
{
517
struct pcm_substream *sub = usb6fire_pcm_get_substream(alsa_sub);
518
struct pcm_runtime *rt = snd_pcm_substream_chip(alsa_sub);
519
snd_pcm_uframes_t ret;
520
521
if (rt->panic || !sub)
522
return SNDRV_PCM_POS_XRUN;
523
524
guard(spinlock_irqsave)(&sub->lock);
525
ret = sub->dma_off;
526
return ret;
527
}
528
529
static const struct snd_pcm_ops pcm_ops = {
530
.open = usb6fire_pcm_open,
531
.close = usb6fire_pcm_close,
532
.prepare = usb6fire_pcm_prepare,
533
.trigger = usb6fire_pcm_trigger,
534
.pointer = usb6fire_pcm_pointer,
535
};
536
537
static void usb6fire_pcm_init_urb(struct pcm_urb *urb,
538
struct sfire_chip *chip, bool in, int ep,
539
void (*handler)(struct urb *))
540
{
541
urb->chip = chip;
542
usb_init_urb(&urb->instance);
543
urb->instance.transfer_buffer = urb->buffer;
544
urb->instance.transfer_buffer_length =
545
PCM_N_PACKETS_PER_URB * PCM_MAX_PACKET_SIZE;
546
urb->instance.dev = chip->dev;
547
urb->instance.pipe = in ? usb_rcvisocpipe(chip->dev, ep)
548
: usb_sndisocpipe(chip->dev, ep);
549
urb->instance.interval = 1;
550
urb->instance.complete = handler;
551
urb->instance.context = urb;
552
urb->instance.number_of_packets = PCM_N_PACKETS_PER_URB;
553
}
554
555
static int usb6fire_pcm_buffers_init(struct pcm_runtime *rt)
556
{
557
int i;
558
559
for (i = 0; i < PCM_N_URBS; i++) {
560
rt->out_urbs[i].buffer = kcalloc(PCM_MAX_PACKET_SIZE,
561
PCM_N_PACKETS_PER_URB,
562
GFP_KERNEL);
563
if (!rt->out_urbs[i].buffer)
564
return -ENOMEM;
565
rt->in_urbs[i].buffer = kcalloc(PCM_MAX_PACKET_SIZE,
566
PCM_N_PACKETS_PER_URB,
567
GFP_KERNEL);
568
if (!rt->in_urbs[i].buffer)
569
return -ENOMEM;
570
}
571
return 0;
572
}
573
574
static void usb6fire_pcm_buffers_destroy(struct pcm_runtime *rt)
575
{
576
int i;
577
578
for (i = 0; i < PCM_N_URBS; i++) {
579
kfree(rt->out_urbs[i].buffer);
580
kfree(rt->in_urbs[i].buffer);
581
}
582
}
583
584
int usb6fire_pcm_init(struct sfire_chip *chip)
585
{
586
int i;
587
int ret;
588
struct snd_pcm *pcm;
589
struct pcm_runtime *rt =
590
kzalloc(sizeof(struct pcm_runtime), GFP_KERNEL);
591
592
if (!rt)
593
return -ENOMEM;
594
595
ret = usb6fire_pcm_buffers_init(rt);
596
if (ret) {
597
usb6fire_pcm_buffers_destroy(rt);
598
kfree(rt);
599
return ret;
600
}
601
602
rt->chip = chip;
603
rt->stream_state = STREAM_DISABLED;
604
rt->rate = ARRAY_SIZE(rates);
605
init_waitqueue_head(&rt->stream_wait_queue);
606
mutex_init(&rt->stream_mutex);
607
608
spin_lock_init(&rt->playback.lock);
609
spin_lock_init(&rt->capture.lock);
610
611
for (i = 0; i < PCM_N_URBS; i++) {
612
usb6fire_pcm_init_urb(&rt->in_urbs[i], chip, true, IN_EP,
613
usb6fire_pcm_in_urb_handler);
614
usb6fire_pcm_init_urb(&rt->out_urbs[i], chip, false, OUT_EP,
615
usb6fire_pcm_out_urb_handler);
616
617
rt->in_urbs[i].peer = &rt->out_urbs[i];
618
rt->out_urbs[i].peer = &rt->in_urbs[i];
619
}
620
621
ret = snd_pcm_new(chip->card, "DMX6FireUSB", 0, 1, 1, &pcm);
622
if (ret < 0) {
623
usb6fire_pcm_buffers_destroy(rt);
624
kfree(rt);
625
dev_err(&chip->dev->dev, "cannot create pcm instance.\n");
626
return ret;
627
}
628
629
pcm->private_data = rt;
630
strscpy(pcm->name, "DMX 6Fire USB");
631
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &pcm_ops);
632
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &pcm_ops);
633
snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_VMALLOC, NULL, 0, 0);
634
635
rt->instance = pcm;
636
637
chip->pcm = rt;
638
return 0;
639
}
640
641
void usb6fire_pcm_abort(struct sfire_chip *chip)
642
{
643
struct pcm_runtime *rt = chip->pcm;
644
int i;
645
646
if (rt) {
647
rt->panic = true;
648
649
if (rt->playback.instance)
650
snd_pcm_stop_xrun(rt->playback.instance);
651
652
if (rt->capture.instance)
653
snd_pcm_stop_xrun(rt->capture.instance);
654
655
for (i = 0; i < PCM_N_URBS; i++) {
656
usb_poison_urb(&rt->in_urbs[i].instance);
657
usb_poison_urb(&rt->out_urbs[i].instance);
658
}
659
660
}
661
}
662
663
void usb6fire_pcm_destroy(struct sfire_chip *chip)
664
{
665
struct pcm_runtime *rt = chip->pcm;
666
667
usb6fire_pcm_buffers_destroy(rt);
668
kfree(rt);
669
chip->pcm = NULL;
670
}
671
672