Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/sound/usb/hiface/pcm.c
29269 views
1
// SPDX-License-Identifier: GPL-2.0-or-later
2
/*
3
* Linux driver for M2Tech hiFace compatible devices
4
*
5
* Copyright 2012-2013 (C) M2TECH S.r.l and Amarula Solutions B.V.
6
*
7
* Authors: Michael Trimarchi <[email protected]>
8
* Antonio Ospite <[email protected]>
9
*
10
* The driver is based on the work done in TerraTec DMX 6Fire USB
11
*/
12
13
#include <linux/slab.h>
14
#include <sound/pcm.h>
15
16
#include "pcm.h"
17
#include "chip.h"
18
19
#define OUT_EP 0x2
20
#define PCM_N_URBS 8
21
#define PCM_PACKET_SIZE 4096
22
#define PCM_BUFFER_SIZE (2 * PCM_N_URBS * PCM_PACKET_SIZE)
23
24
struct pcm_urb {
25
struct hiface_chip *chip;
26
27
struct urb instance;
28
struct usb_anchor submitted;
29
u8 *buffer;
30
};
31
32
struct pcm_substream {
33
spinlock_t lock;
34
struct snd_pcm_substream *instance;
35
36
bool active;
37
snd_pcm_uframes_t dma_off; /* current position in alsa dma_area */
38
snd_pcm_uframes_t period_off; /* current position in current period */
39
};
40
41
enum { /* pcm streaming states */
42
STREAM_DISABLED, /* no pcm streaming */
43
STREAM_STARTING, /* pcm streaming requested, waiting to become ready */
44
STREAM_RUNNING, /* pcm streaming running */
45
STREAM_STOPPING
46
};
47
48
struct pcm_runtime {
49
struct hiface_chip *chip;
50
struct snd_pcm *instance;
51
52
struct pcm_substream playback;
53
bool panic; /* if set driver won't do anymore pcm on device */
54
55
struct pcm_urb out_urbs[PCM_N_URBS];
56
57
struct mutex stream_mutex;
58
u8 stream_state; /* one of STREAM_XXX */
59
u8 extra_freq;
60
wait_queue_head_t stream_wait_queue;
61
bool stream_wait_cond;
62
};
63
64
static const unsigned int rates[] = { 44100, 48000, 88200, 96000, 176400, 192000,
65
352800, 384000 };
66
static const struct snd_pcm_hw_constraint_list constraints_extra_rates = {
67
.count = ARRAY_SIZE(rates),
68
.list = rates,
69
.mask = 0,
70
};
71
72
static const struct snd_pcm_hardware pcm_hw = {
73
.info = SNDRV_PCM_INFO_MMAP |
74
SNDRV_PCM_INFO_INTERLEAVED |
75
SNDRV_PCM_INFO_BLOCK_TRANSFER |
76
SNDRV_PCM_INFO_PAUSE |
77
SNDRV_PCM_INFO_MMAP_VALID |
78
SNDRV_PCM_INFO_BATCH,
79
80
.formats = SNDRV_PCM_FMTBIT_S32_LE,
81
82
.rates = SNDRV_PCM_RATE_44100 |
83
SNDRV_PCM_RATE_48000 |
84
SNDRV_PCM_RATE_88200 |
85
SNDRV_PCM_RATE_96000 |
86
SNDRV_PCM_RATE_176400 |
87
SNDRV_PCM_RATE_192000,
88
89
.rate_min = 44100,
90
.rate_max = 192000, /* changes in hiface_pcm_open to support extra rates */
91
.channels_min = 2,
92
.channels_max = 2,
93
.buffer_bytes_max = PCM_BUFFER_SIZE,
94
.period_bytes_min = PCM_PACKET_SIZE,
95
.period_bytes_max = PCM_BUFFER_SIZE,
96
.periods_min = 2,
97
.periods_max = 1024
98
};
99
100
/* message values used to change the sample rate */
101
#define HIFACE_SET_RATE_REQUEST 0xb0
102
103
#define HIFACE_RATE_44100 0x43
104
#define HIFACE_RATE_48000 0x4b
105
#define HIFACE_RATE_88200 0x42
106
#define HIFACE_RATE_96000 0x4a
107
#define HIFACE_RATE_176400 0x40
108
#define HIFACE_RATE_192000 0x48
109
#define HIFACE_RATE_352800 0x58
110
#define HIFACE_RATE_384000 0x68
111
112
static int hiface_pcm_set_rate(struct pcm_runtime *rt, unsigned int rate)
113
{
114
struct usb_device *device = rt->chip->dev;
115
u16 rate_value;
116
int ret;
117
118
/* We are already sure that the rate is supported here thanks to
119
* ALSA constraints
120
*/
121
switch (rate) {
122
case 44100:
123
rate_value = HIFACE_RATE_44100;
124
break;
125
case 48000:
126
rate_value = HIFACE_RATE_48000;
127
break;
128
case 88200:
129
rate_value = HIFACE_RATE_88200;
130
break;
131
case 96000:
132
rate_value = HIFACE_RATE_96000;
133
break;
134
case 176400:
135
rate_value = HIFACE_RATE_176400;
136
break;
137
case 192000:
138
rate_value = HIFACE_RATE_192000;
139
break;
140
case 352800:
141
rate_value = HIFACE_RATE_352800;
142
break;
143
case 384000:
144
rate_value = HIFACE_RATE_384000;
145
break;
146
default:
147
dev_err(&device->dev, "Unsupported rate %d\n", rate);
148
return -EINVAL;
149
}
150
151
/*
152
* USBIO: Vendor 0xb0(wValue=0x0043, wIndex=0x0000)
153
* 43 b0 43 00 00 00 00 00
154
* USBIO: Vendor 0xb0(wValue=0x004b, wIndex=0x0000)
155
* 43 b0 4b 00 00 00 00 00
156
* This control message doesn't have any ack from the
157
* other side
158
*/
159
ret = usb_control_msg_send(device, 0,
160
HIFACE_SET_RATE_REQUEST,
161
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER,
162
rate_value, 0, NULL, 0, 100, GFP_KERNEL);
163
if (ret)
164
dev_err(&device->dev, "Error setting samplerate %d.\n", rate);
165
166
return ret;
167
}
168
169
static struct pcm_substream *hiface_pcm_get_substream(struct snd_pcm_substream
170
*alsa_sub)
171
{
172
struct pcm_runtime *rt = snd_pcm_substream_chip(alsa_sub);
173
struct device *device = &rt->chip->dev->dev;
174
175
if (alsa_sub->stream == SNDRV_PCM_STREAM_PLAYBACK)
176
return &rt->playback;
177
178
dev_err(device, "Error getting pcm substream slot.\n");
179
return NULL;
180
}
181
182
/* call with stream_mutex locked */
183
static void hiface_pcm_stream_stop(struct pcm_runtime *rt)
184
{
185
int i, time;
186
187
if (rt->stream_state != STREAM_DISABLED) {
188
rt->stream_state = STREAM_STOPPING;
189
190
for (i = 0; i < PCM_N_URBS; i++) {
191
time = usb_wait_anchor_empty_timeout(
192
&rt->out_urbs[i].submitted, 100);
193
if (!time)
194
usb_kill_anchored_urbs(
195
&rt->out_urbs[i].submitted);
196
usb_kill_urb(&rt->out_urbs[i].instance);
197
}
198
199
rt->stream_state = STREAM_DISABLED;
200
}
201
}
202
203
/* call with stream_mutex locked */
204
static int hiface_pcm_stream_start(struct pcm_runtime *rt)
205
{
206
int ret = 0;
207
int i;
208
209
if (rt->stream_state == STREAM_DISABLED) {
210
211
/* reset panic state when starting a new stream */
212
rt->panic = false;
213
214
/* submit our out urbs zero init */
215
rt->stream_state = STREAM_STARTING;
216
for (i = 0; i < PCM_N_URBS; i++) {
217
memset(rt->out_urbs[i].buffer, 0, PCM_PACKET_SIZE);
218
usb_anchor_urb(&rt->out_urbs[i].instance,
219
&rt->out_urbs[i].submitted);
220
ret = usb_submit_urb(&rt->out_urbs[i].instance,
221
GFP_ATOMIC);
222
if (ret) {
223
hiface_pcm_stream_stop(rt);
224
return ret;
225
}
226
}
227
228
/* wait for first out urb to return (sent in urb handler) */
229
wait_event_timeout(rt->stream_wait_queue, rt->stream_wait_cond,
230
HZ);
231
if (rt->stream_wait_cond) {
232
struct device *device = &rt->chip->dev->dev;
233
dev_dbg(device, "%s: Stream is running wakeup event\n",
234
__func__);
235
rt->stream_state = STREAM_RUNNING;
236
} else {
237
hiface_pcm_stream_stop(rt);
238
return -EIO;
239
}
240
}
241
return ret;
242
}
243
244
/* The hardware wants word-swapped 32-bit values */
245
static void memcpy_swahw32(u8 *dest, u8 *src, unsigned int n)
246
{
247
unsigned int i;
248
249
for (i = 0; i < n / 4; i++)
250
((u32 *)dest)[i] = swahw32(((u32 *)src)[i]);
251
}
252
253
/* call with substream locked */
254
/* returns true if a period elapsed */
255
static bool hiface_pcm_playback(struct pcm_substream *sub, struct pcm_urb *urb)
256
{
257
struct snd_pcm_runtime *alsa_rt = sub->instance->runtime;
258
struct device *device = &urb->chip->dev->dev;
259
u8 *source;
260
unsigned int pcm_buffer_size;
261
262
WARN_ON(alsa_rt->format != SNDRV_PCM_FORMAT_S32_LE);
263
264
pcm_buffer_size = snd_pcm_lib_buffer_bytes(sub->instance);
265
266
if (sub->dma_off + PCM_PACKET_SIZE <= pcm_buffer_size) {
267
dev_dbg(device, "%s: (1) buffer_size %#x dma_offset %#x\n", __func__,
268
(unsigned int) pcm_buffer_size,
269
(unsigned int) sub->dma_off);
270
271
source = alsa_rt->dma_area + sub->dma_off;
272
memcpy_swahw32(urb->buffer, source, PCM_PACKET_SIZE);
273
} else {
274
/* wrap around at end of ring buffer */
275
unsigned int len;
276
277
dev_dbg(device, "%s: (2) buffer_size %#x dma_offset %#x\n", __func__,
278
(unsigned int) pcm_buffer_size,
279
(unsigned int) sub->dma_off);
280
281
len = pcm_buffer_size - sub->dma_off;
282
283
source = alsa_rt->dma_area + sub->dma_off;
284
memcpy_swahw32(urb->buffer, source, len);
285
286
source = alsa_rt->dma_area;
287
memcpy_swahw32(urb->buffer + len, source,
288
PCM_PACKET_SIZE - len);
289
}
290
sub->dma_off += PCM_PACKET_SIZE;
291
if (sub->dma_off >= pcm_buffer_size)
292
sub->dma_off -= pcm_buffer_size;
293
294
sub->period_off += PCM_PACKET_SIZE;
295
if (sub->period_off >= alsa_rt->period_size) {
296
sub->period_off %= alsa_rt->period_size;
297
return true;
298
}
299
return false;
300
}
301
302
static void hiface_pcm_out_urb_handler(struct urb *usb_urb)
303
{
304
struct pcm_urb *out_urb = usb_urb->context;
305
struct pcm_runtime *rt = out_urb->chip->pcm;
306
struct pcm_substream *sub;
307
bool do_period_elapsed = false;
308
int ret;
309
310
if (rt->panic || rt->stream_state == STREAM_STOPPING)
311
return;
312
313
if (unlikely(usb_urb->status == -ENOENT || /* unlinked */
314
usb_urb->status == -ENODEV || /* device removed */
315
usb_urb->status == -ECONNRESET || /* unlinked */
316
usb_urb->status == -ESHUTDOWN)) { /* device disabled */
317
goto out_fail;
318
}
319
320
if (rt->stream_state == STREAM_STARTING) {
321
rt->stream_wait_cond = true;
322
wake_up(&rt->stream_wait_queue);
323
}
324
325
/* now send our playback data (if a free out urb was found) */
326
sub = &rt->playback;
327
scoped_guard(spinlock_irqsave, &sub->lock) {
328
if (sub->active)
329
do_period_elapsed = hiface_pcm_playback(sub, out_urb);
330
else
331
memset(out_urb->buffer, 0, PCM_PACKET_SIZE);
332
}
333
334
if (do_period_elapsed)
335
snd_pcm_period_elapsed(sub->instance);
336
337
ret = usb_submit_urb(&out_urb->instance, GFP_ATOMIC);
338
if (ret < 0)
339
goto out_fail;
340
341
return;
342
343
out_fail:
344
rt->panic = true;
345
}
346
347
static int hiface_pcm_open(struct snd_pcm_substream *alsa_sub)
348
{
349
struct pcm_runtime *rt = snd_pcm_substream_chip(alsa_sub);
350
struct pcm_substream *sub = NULL;
351
struct snd_pcm_runtime *alsa_rt = alsa_sub->runtime;
352
int ret;
353
354
if (rt->panic)
355
return -EPIPE;
356
357
guard(mutex)(&rt->stream_mutex);
358
alsa_rt->hw = pcm_hw;
359
360
if (alsa_sub->stream == SNDRV_PCM_STREAM_PLAYBACK)
361
sub = &rt->playback;
362
363
if (!sub) {
364
struct device *device = &rt->chip->dev->dev;
365
dev_err(device, "Invalid stream type\n");
366
return -EINVAL;
367
}
368
369
if (rt->extra_freq) {
370
alsa_rt->hw.rates |= SNDRV_PCM_RATE_KNOT;
371
alsa_rt->hw.rate_max = 384000;
372
373
/* explicit constraints needed as we added SNDRV_PCM_RATE_KNOT */
374
ret = snd_pcm_hw_constraint_list(alsa_sub->runtime, 0,
375
SNDRV_PCM_HW_PARAM_RATE,
376
&constraints_extra_rates);
377
if (ret < 0)
378
return ret;
379
}
380
381
sub->instance = alsa_sub;
382
sub->active = false;
383
return 0;
384
}
385
386
static int hiface_pcm_close(struct snd_pcm_substream *alsa_sub)
387
{
388
struct pcm_runtime *rt = snd_pcm_substream_chip(alsa_sub);
389
struct pcm_substream *sub = hiface_pcm_get_substream(alsa_sub);
390
391
if (rt->panic)
392
return 0;
393
394
guard(mutex)(&rt->stream_mutex);
395
if (sub) {
396
hiface_pcm_stream_stop(rt);
397
398
/* deactivate substream */
399
guard(spinlock_irqsave)(&sub->lock);
400
sub->instance = NULL;
401
sub->active = false;
402
}
403
return 0;
404
}
405
406
static int hiface_pcm_prepare(struct snd_pcm_substream *alsa_sub)
407
{
408
struct pcm_runtime *rt = snd_pcm_substream_chip(alsa_sub);
409
struct pcm_substream *sub = hiface_pcm_get_substream(alsa_sub);
410
struct snd_pcm_runtime *alsa_rt = alsa_sub->runtime;
411
int ret;
412
413
if (rt->panic)
414
return -EPIPE;
415
if (!sub)
416
return -ENODEV;
417
418
guard(mutex)(&rt->stream_mutex);
419
420
hiface_pcm_stream_stop(rt);
421
422
sub->dma_off = 0;
423
sub->period_off = 0;
424
425
if (rt->stream_state == STREAM_DISABLED) {
426
427
ret = hiface_pcm_set_rate(rt, alsa_rt->rate);
428
if (ret)
429
return ret;
430
ret = hiface_pcm_stream_start(rt);
431
if (ret)
432
return ret;
433
}
434
return 0;
435
}
436
437
static int hiface_pcm_trigger(struct snd_pcm_substream *alsa_sub, int cmd)
438
{
439
struct pcm_substream *sub = hiface_pcm_get_substream(alsa_sub);
440
struct pcm_runtime *rt = snd_pcm_substream_chip(alsa_sub);
441
442
if (rt->panic)
443
return -EPIPE;
444
if (!sub)
445
return -ENODEV;
446
447
switch (cmd) {
448
case SNDRV_PCM_TRIGGER_START:
449
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
450
scoped_guard(spinlock_irq, &sub->lock) {
451
sub->active = true;
452
}
453
return 0;
454
455
case SNDRV_PCM_TRIGGER_STOP:
456
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
457
scoped_guard(spinlock_irq, &sub->lock) {
458
sub->active = false;
459
}
460
return 0;
461
462
default:
463
return -EINVAL;
464
}
465
}
466
467
static snd_pcm_uframes_t hiface_pcm_pointer(struct snd_pcm_substream *alsa_sub)
468
{
469
struct pcm_substream *sub = hiface_pcm_get_substream(alsa_sub);
470
struct pcm_runtime *rt = snd_pcm_substream_chip(alsa_sub);
471
snd_pcm_uframes_t dma_offset;
472
473
if (rt->panic || !sub)
474
return SNDRV_PCM_POS_XRUN;
475
476
guard(spinlock_irqsave)(&sub->lock);
477
dma_offset = sub->dma_off;
478
return bytes_to_frames(alsa_sub->runtime, dma_offset);
479
}
480
481
static const struct snd_pcm_ops pcm_ops = {
482
.open = hiface_pcm_open,
483
.close = hiface_pcm_close,
484
.prepare = hiface_pcm_prepare,
485
.trigger = hiface_pcm_trigger,
486
.pointer = hiface_pcm_pointer,
487
};
488
489
static int hiface_pcm_init_urb(struct pcm_urb *urb,
490
struct hiface_chip *chip,
491
unsigned int ep,
492
void (*handler)(struct urb *))
493
{
494
urb->chip = chip;
495
usb_init_urb(&urb->instance);
496
497
urb->buffer = kzalloc(PCM_PACKET_SIZE, GFP_KERNEL);
498
if (!urb->buffer)
499
return -ENOMEM;
500
501
usb_fill_bulk_urb(&urb->instance, chip->dev,
502
usb_sndbulkpipe(chip->dev, ep), (void *)urb->buffer,
503
PCM_PACKET_SIZE, handler, urb);
504
if (usb_urb_ep_type_check(&urb->instance))
505
return -EINVAL;
506
init_usb_anchor(&urb->submitted);
507
508
return 0;
509
}
510
511
void hiface_pcm_abort(struct hiface_chip *chip)
512
{
513
struct pcm_runtime *rt = chip->pcm;
514
515
if (rt) {
516
rt->panic = true;
517
518
guard(mutex)(&rt->stream_mutex);
519
hiface_pcm_stream_stop(rt);
520
}
521
}
522
523
static void hiface_pcm_destroy(struct hiface_chip *chip)
524
{
525
struct pcm_runtime *rt = chip->pcm;
526
int i;
527
528
for (i = 0; i < PCM_N_URBS; i++)
529
kfree(rt->out_urbs[i].buffer);
530
531
kfree(chip->pcm);
532
chip->pcm = NULL;
533
}
534
535
static void hiface_pcm_free(struct snd_pcm *pcm)
536
{
537
struct pcm_runtime *rt = pcm->private_data;
538
539
if (rt)
540
hiface_pcm_destroy(rt->chip);
541
}
542
543
int hiface_pcm_init(struct hiface_chip *chip, u8 extra_freq)
544
{
545
int i;
546
int ret;
547
struct snd_pcm *pcm;
548
struct pcm_runtime *rt;
549
550
rt = kzalloc(sizeof(*rt), GFP_KERNEL);
551
if (!rt)
552
return -ENOMEM;
553
554
rt->chip = chip;
555
rt->stream_state = STREAM_DISABLED;
556
if (extra_freq)
557
rt->extra_freq = 1;
558
559
init_waitqueue_head(&rt->stream_wait_queue);
560
mutex_init(&rt->stream_mutex);
561
spin_lock_init(&rt->playback.lock);
562
563
for (i = 0; i < PCM_N_URBS; i++) {
564
ret = hiface_pcm_init_urb(&rt->out_urbs[i], chip, OUT_EP,
565
hiface_pcm_out_urb_handler);
566
if (ret < 0)
567
goto error;
568
}
569
570
ret = snd_pcm_new(chip->card, "USB-SPDIF Audio", 0, 1, 0, &pcm);
571
if (ret < 0) {
572
dev_err(&chip->dev->dev, "Cannot create pcm instance\n");
573
goto error;
574
}
575
576
pcm->private_data = rt;
577
pcm->private_free = hiface_pcm_free;
578
579
strscpy(pcm->name, "USB-SPDIF Audio", sizeof(pcm->name));
580
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &pcm_ops);
581
snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_VMALLOC,
582
NULL, 0, 0);
583
584
rt->instance = pcm;
585
586
chip->pcm = rt;
587
return 0;
588
589
error:
590
for (i = 0; i < PCM_N_URBS; i++)
591
kfree(rt->out_urbs[i].buffer);
592
kfree(rt);
593
return ret;
594
}
595
596