Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/sound/usb/line6/playback.c
26425 views
1
// SPDX-License-Identifier: GPL-2.0-only
2
/*
3
* Line 6 Linux USB driver
4
*
5
* Copyright (C) 2004-2010 Markus Grabner ([email protected])
6
*/
7
8
#include <linux/slab.h>
9
#include <sound/core.h>
10
#include <sound/pcm.h>
11
#include <sound/pcm_params.h>
12
13
#include "capture.h"
14
#include "driver.h"
15
#include "pcm.h"
16
#include "playback.h"
17
18
/*
19
Software stereo volume control.
20
*/
21
static void change_volume(struct urb *urb_out, int volume[],
22
int bytes_per_frame)
23
{
24
int chn = 0;
25
26
if (volume[0] == 256 && volume[1] == 256)
27
return; /* maximum volume - no change */
28
29
if (bytes_per_frame == 4) {
30
__le16 *p, *buf_end;
31
32
p = (__le16 *)urb_out->transfer_buffer;
33
buf_end = p + urb_out->transfer_buffer_length / sizeof(*p);
34
35
for (; p < buf_end; ++p) {
36
short pv = le16_to_cpu(*p);
37
int val = (pv * volume[chn & 1]) >> 8;
38
pv = clamp(val, -0x8000, 0x7fff);
39
*p = cpu_to_le16(pv);
40
++chn;
41
}
42
} else if (bytes_per_frame == 6) {
43
unsigned char *p, *buf_end;
44
45
p = (unsigned char *)urb_out->transfer_buffer;
46
buf_end = p + urb_out->transfer_buffer_length;
47
48
for (; p < buf_end; p += 3) {
49
int val;
50
51
val = p[0] + (p[1] << 8) + ((signed char)p[2] << 16);
52
val = (val * volume[chn & 1]) >> 8;
53
val = clamp(val, -0x800000, 0x7fffff);
54
p[0] = val;
55
p[1] = val >> 8;
56
p[2] = val >> 16;
57
++chn;
58
}
59
}
60
}
61
62
/*
63
Create signal for impulse response test.
64
*/
65
static void create_impulse_test_signal(struct snd_line6_pcm *line6pcm,
66
struct urb *urb_out, int bytes_per_frame)
67
{
68
int frames = urb_out->transfer_buffer_length / bytes_per_frame;
69
70
if (bytes_per_frame == 4) {
71
int i;
72
short *pi = (short *)line6pcm->prev_fbuf;
73
short *po = (short *)urb_out->transfer_buffer;
74
75
for (i = 0; i < frames; ++i) {
76
po[0] = pi[0];
77
po[1] = 0;
78
pi += 2;
79
po += 2;
80
}
81
} else if (bytes_per_frame == 6) {
82
int i, j;
83
unsigned char *pi = line6pcm->prev_fbuf;
84
unsigned char *po = urb_out->transfer_buffer;
85
86
for (i = 0; i < frames; ++i) {
87
for (j = 0; j < bytes_per_frame / 2; ++j)
88
po[j] = pi[j];
89
90
for (; j < bytes_per_frame; ++j)
91
po[j] = 0;
92
93
pi += bytes_per_frame;
94
po += bytes_per_frame;
95
}
96
}
97
if (--line6pcm->impulse_count <= 0) {
98
((unsigned char *)(urb_out->transfer_buffer))[bytes_per_frame -
99
1] =
100
line6pcm->impulse_volume;
101
line6pcm->impulse_count = line6pcm->impulse_period;
102
}
103
}
104
105
/*
106
Add signal to buffer for software monitoring.
107
*/
108
static void add_monitor_signal(struct urb *urb_out, unsigned char *signal,
109
int volume, int bytes_per_frame)
110
{
111
if (volume == 0)
112
return; /* zero volume - no change */
113
114
if (bytes_per_frame == 4) {
115
__le16 *pi, *po, *buf_end;
116
117
pi = (__le16 *)signal;
118
po = (__le16 *)urb_out->transfer_buffer;
119
buf_end = po + urb_out->transfer_buffer_length / sizeof(*po);
120
121
for (; po < buf_end; ++pi, ++po) {
122
short pov = le16_to_cpu(*po);
123
short piv = le16_to_cpu(*pi);
124
int val = pov + ((piv * volume) >> 8);
125
pov = clamp(val, -0x8000, 0x7fff);
126
*po = cpu_to_le16(pov);
127
}
128
}
129
130
/*
131
We don't need to handle devices with 6 bytes per frame here
132
since they all support hardware monitoring.
133
*/
134
}
135
136
/*
137
Find a free URB, prepare audio data, and submit URB.
138
must be called in line6pcm->out.lock context
139
*/
140
static int submit_audio_out_urb(struct snd_line6_pcm *line6pcm)
141
{
142
int index;
143
int i, urb_size, urb_frames;
144
int ret;
145
const int bytes_per_frame =
146
line6pcm->properties->bytes_per_channel *
147
line6pcm->properties->playback_hw.channels_max;
148
const int frame_increment =
149
line6pcm->properties->rates.rats[0].num_min;
150
const int frame_factor =
151
line6pcm->properties->rates.rats[0].den *
152
(line6pcm->line6->intervals_per_second / LINE6_ISO_INTERVAL);
153
struct urb *urb_out;
154
155
index = find_first_zero_bit(&line6pcm->out.active_urbs,
156
line6pcm->line6->iso_buffers);
157
158
if (index < 0 || index >= line6pcm->line6->iso_buffers) {
159
dev_err(line6pcm->line6->ifcdev, "no free URB found\n");
160
return -EINVAL;
161
}
162
163
urb_out = line6pcm->out.urbs[index];
164
urb_size = 0;
165
166
/* TODO: this may not work for LINE6_ISO_PACKETS != 1 */
167
for (i = 0; i < LINE6_ISO_PACKETS; ++i) {
168
/* compute frame size for given sampling rate */
169
int fsize = 0;
170
struct usb_iso_packet_descriptor *fout =
171
&urb_out->iso_frame_desc[i];
172
173
fsize = line6pcm->prev_fsize;
174
if (fsize == 0) {
175
int n;
176
177
line6pcm->out.count += frame_increment;
178
n = line6pcm->out.count / frame_factor;
179
line6pcm->out.count -= n * frame_factor;
180
fsize = n;
181
}
182
183
fsize *= bytes_per_frame;
184
185
fout->offset = urb_size;
186
fout->length = fsize;
187
urb_size += fsize;
188
}
189
190
if (urb_size == 0) {
191
/* can't determine URB size */
192
dev_err(line6pcm->line6->ifcdev, "driver bug: urb_size = 0\n");
193
return -EINVAL;
194
}
195
196
urb_frames = urb_size / bytes_per_frame;
197
urb_out->transfer_buffer =
198
line6pcm->out.buffer +
199
index * LINE6_ISO_PACKETS * line6pcm->max_packet_size_out;
200
urb_out->transfer_buffer_length = urb_size;
201
urb_out->context = line6pcm;
202
203
if (test_bit(LINE6_STREAM_PCM, &line6pcm->out.running) &&
204
!test_bit(LINE6_FLAG_PAUSE_PLAYBACK, &line6pcm->flags)) {
205
struct snd_pcm_runtime *runtime =
206
get_substream(line6pcm, SNDRV_PCM_STREAM_PLAYBACK)->runtime;
207
208
if (line6pcm->out.pos + urb_frames > runtime->buffer_size) {
209
/*
210
The transferred area goes over buffer boundary,
211
copy the data to the temp buffer.
212
*/
213
int len;
214
215
len = runtime->buffer_size - line6pcm->out.pos;
216
217
if (len > 0) {
218
memcpy(urb_out->transfer_buffer,
219
runtime->dma_area +
220
line6pcm->out.pos * bytes_per_frame,
221
len * bytes_per_frame);
222
memcpy(urb_out->transfer_buffer +
223
len * bytes_per_frame, runtime->dma_area,
224
(urb_frames - len) * bytes_per_frame);
225
} else
226
dev_err(line6pcm->line6->ifcdev, "driver bug: len = %d\n",
227
len);
228
} else {
229
memcpy(urb_out->transfer_buffer,
230
runtime->dma_area +
231
line6pcm->out.pos * bytes_per_frame,
232
urb_out->transfer_buffer_length);
233
}
234
235
line6pcm->out.pos += urb_frames;
236
if (line6pcm->out.pos >= runtime->buffer_size)
237
line6pcm->out.pos -= runtime->buffer_size;
238
239
change_volume(urb_out, line6pcm->volume_playback,
240
bytes_per_frame);
241
} else {
242
memset(urb_out->transfer_buffer, 0,
243
urb_out->transfer_buffer_length);
244
}
245
246
spin_lock_nested(&line6pcm->in.lock, SINGLE_DEPTH_NESTING);
247
if (line6pcm->prev_fbuf) {
248
if (test_bit(LINE6_STREAM_IMPULSE, &line6pcm->out.running)) {
249
create_impulse_test_signal(line6pcm, urb_out,
250
bytes_per_frame);
251
if (test_bit(LINE6_STREAM_PCM, &line6pcm->in.running)) {
252
line6_capture_copy(line6pcm,
253
urb_out->transfer_buffer,
254
urb_out->
255
transfer_buffer_length);
256
line6_capture_check_period(line6pcm,
257
urb_out->transfer_buffer_length);
258
}
259
} else {
260
if (!(line6pcm->line6->properties->capabilities & LINE6_CAP_HWMON)
261
&& line6pcm->out.running && line6pcm->in.running)
262
add_monitor_signal(urb_out, line6pcm->prev_fbuf,
263
line6pcm->volume_monitor,
264
bytes_per_frame);
265
}
266
line6pcm->prev_fbuf = NULL;
267
line6pcm->prev_fsize = 0;
268
}
269
spin_unlock(&line6pcm->in.lock);
270
271
ret = usb_submit_urb(urb_out, GFP_ATOMIC);
272
273
if (ret == 0)
274
set_bit(index, &line6pcm->out.active_urbs);
275
else
276
dev_err(line6pcm->line6->ifcdev,
277
"URB out #%d submission failed (%d)\n", index, ret);
278
279
return 0;
280
}
281
282
/*
283
Submit all currently available playback URBs.
284
must be called in line6pcm->out.lock context
285
*/
286
int line6_submit_audio_out_all_urbs(struct snd_line6_pcm *line6pcm)
287
{
288
int ret = 0, i;
289
290
for (i = 0; i < line6pcm->line6->iso_buffers; ++i) {
291
ret = submit_audio_out_urb(line6pcm);
292
if (ret < 0)
293
break;
294
}
295
296
return ret;
297
}
298
299
/*
300
Callback for completed playback URB.
301
*/
302
static void audio_out_callback(struct urb *urb)
303
{
304
int i, index, length = 0, shutdown = 0;
305
unsigned long flags;
306
struct snd_line6_pcm *line6pcm = (struct snd_line6_pcm *)urb->context;
307
struct snd_pcm_substream *substream =
308
get_substream(line6pcm, SNDRV_PCM_STREAM_PLAYBACK);
309
const int bytes_per_frame =
310
line6pcm->properties->bytes_per_channel *
311
line6pcm->properties->playback_hw.channels_max;
312
313
#if USE_CLEAR_BUFFER_WORKAROUND
314
memset(urb->transfer_buffer, 0, urb->transfer_buffer_length);
315
#endif
316
317
line6pcm->out.last_frame = urb->start_frame;
318
319
/* find index of URB */
320
for (index = 0; index < line6pcm->line6->iso_buffers; index++)
321
if (urb == line6pcm->out.urbs[index])
322
break;
323
324
if (index >= line6pcm->line6->iso_buffers)
325
return; /* URB has been unlinked asynchronously */
326
327
for (i = 0; i < LINE6_ISO_PACKETS; i++)
328
length += urb->iso_frame_desc[i].length;
329
330
spin_lock_irqsave(&line6pcm->out.lock, flags);
331
332
if (test_bit(LINE6_STREAM_PCM, &line6pcm->out.running)) {
333
struct snd_pcm_runtime *runtime = substream->runtime;
334
335
line6pcm->out.pos_done +=
336
length / bytes_per_frame;
337
338
if (line6pcm->out.pos_done >= runtime->buffer_size)
339
line6pcm->out.pos_done -= runtime->buffer_size;
340
}
341
342
clear_bit(index, &line6pcm->out.active_urbs);
343
344
for (i = 0; i < LINE6_ISO_PACKETS; i++)
345
if (urb->iso_frame_desc[i].status == -EXDEV) {
346
shutdown = 1;
347
break;
348
}
349
350
if (test_and_clear_bit(index, &line6pcm->out.unlink_urbs))
351
shutdown = 1;
352
353
if (!shutdown) {
354
submit_audio_out_urb(line6pcm);
355
356
if (test_bit(LINE6_STREAM_PCM, &line6pcm->out.running)) {
357
line6pcm->out.bytes += length;
358
if (line6pcm->out.bytes >= line6pcm->out.period) {
359
line6pcm->out.bytes %= line6pcm->out.period;
360
spin_unlock(&line6pcm->out.lock);
361
snd_pcm_period_elapsed(substream);
362
spin_lock(&line6pcm->out.lock);
363
}
364
}
365
}
366
spin_unlock_irqrestore(&line6pcm->out.lock, flags);
367
}
368
369
/* open playback callback */
370
static int snd_line6_playback_open(struct snd_pcm_substream *substream)
371
{
372
int err;
373
struct snd_pcm_runtime *runtime = substream->runtime;
374
struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream);
375
376
err = snd_pcm_hw_constraint_ratdens(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
377
&line6pcm->properties->rates);
378
if (err < 0)
379
return err;
380
381
runtime->hw = line6pcm->properties->playback_hw;
382
return 0;
383
}
384
385
/* close playback callback */
386
static int snd_line6_playback_close(struct snd_pcm_substream *substream)
387
{
388
return 0;
389
}
390
391
/* playback operators */
392
const struct snd_pcm_ops snd_line6_playback_ops = {
393
.open = snd_line6_playback_open,
394
.close = snd_line6_playback_close,
395
.hw_params = snd_line6_hw_params,
396
.hw_free = snd_line6_hw_free,
397
.prepare = snd_line6_prepare,
398
.trigger = snd_line6_trigger,
399
.pointer = snd_line6_pointer,
400
};
401
402
int line6_create_audio_out_urbs(struct snd_line6_pcm *line6pcm)
403
{
404
struct usb_line6 *line6 = line6pcm->line6;
405
int i;
406
407
line6pcm->out.urbs = kcalloc(line6->iso_buffers, sizeof(struct urb *),
408
GFP_KERNEL);
409
if (line6pcm->out.urbs == NULL)
410
return -ENOMEM;
411
412
/* create audio URBs and fill in constant values: */
413
for (i = 0; i < line6->iso_buffers; ++i) {
414
struct urb *urb;
415
416
/* URB for audio out: */
417
urb = line6pcm->out.urbs[i] =
418
usb_alloc_urb(LINE6_ISO_PACKETS, GFP_KERNEL);
419
420
if (urb == NULL)
421
return -ENOMEM;
422
423
urb->dev = line6->usbdev;
424
urb->pipe =
425
usb_sndisocpipe(line6->usbdev,
426
line6->properties->ep_audio_w &
427
USB_ENDPOINT_NUMBER_MASK);
428
urb->transfer_flags = URB_ISO_ASAP;
429
urb->start_frame = -1;
430
urb->number_of_packets = LINE6_ISO_PACKETS;
431
urb->interval = LINE6_ISO_INTERVAL;
432
urb->error_count = 0;
433
urb->complete = audio_out_callback;
434
if (usb_urb_ep_type_check(urb))
435
return -EINVAL;
436
}
437
438
return 0;
439
}
440
441