Commit | Line | Data |
---|---|---|
1a59d1b8 | 1 | // SPDX-License-Identifier: GPL-2.0-or-later |
523f1dce | 2 | /* |
8d048841 | 3 | * Copyright (c) 2006-2008 Daniel Mack, Karsten Wiese |
523f1dce DM |
4 | */ |
5 | ||
f1f6b8f6 | 6 | #include <linux/device.h> |
e431cf45 | 7 | #include <linux/spinlock.h> |
5a0e3ad6 | 8 | #include <linux/slab.h> |
523f1dce | 9 | #include <linux/init.h> |
523f1dce | 10 | #include <linux/usb.h> |
523f1dce | 11 | #include <sound/core.h> |
523f1dce | 12 | #include <sound/pcm.h> |
523f1dce | 13 | |
936e7d03 DM |
14 | #include "device.h" |
15 | #include "audio.h" | |
523f1dce DM |
16 | |
17 | #define N_URBS 32 | |
18 | #define CLOCK_DRIFT_TOLERANCE 5 | |
19 | #define FRAMES_PER_URB 8 | |
20 | #define BYTES_PER_FRAME 512 | |
21 | #define CHANNELS_PER_STREAM 2 | |
22 | #define BYTES_PER_SAMPLE 3 | |
23 | #define BYTES_PER_SAMPLE_USB 4 | |
24 | #define MAX_BUFFER_SIZE (128*1024) | |
6e9fc6bd DM |
25 | #define MAX_ENDPOINT_SIZE 512 |
26 | ||
523f1dce DM |
27 | #define ENDPOINT_CAPTURE 2 |
28 | #define ENDPOINT_PLAYBACK 6 | |
29 | ||
1c8470ce DM |
30 | #define MAKE_CHECKBYTE(cdev,stream,i) \ |
31 | (stream << 1) | (~(i / (cdev->n_streams * BYTES_PER_SAMPLE_USB)) & 1) | |
523f1dce | 32 | |
2ead9d08 | 33 | static const struct snd_pcm_hardware snd_usb_caiaq_pcm_hardware = { |
9318dce5 | 34 | .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | |
523f1dce DM |
35 | SNDRV_PCM_INFO_BLOCK_TRANSFER), |
36 | .formats = SNDRV_PCM_FMTBIT_S24_3BE, | |
9318dce5 | 37 | .rates = (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | |
523f1dce DM |
38 | SNDRV_PCM_RATE_96000), |
39 | .rate_min = 44100, | |
40 | .rate_max = 0, /* will overwrite later */ | |
41 | .channels_min = CHANNELS_PER_STREAM, | |
42 | .channels_max = CHANNELS_PER_STREAM, | |
43 | .buffer_bytes_max = MAX_BUFFER_SIZE, | |
09189ac7 | 44 | .period_bytes_min = 128, |
523f1dce DM |
45 | .period_bytes_max = MAX_BUFFER_SIZE, |
46 | .periods_min = 1, | |
47 | .periods_max = 1024, | |
48 | }; | |
49 | ||
50 | static void | |
1c8470ce | 51 | activate_substream(struct snd_usb_caiaqdev *cdev, |
523f1dce DM |
52 | struct snd_pcm_substream *sub) |
53 | { | |
1c8470ce | 54 | spin_lock(&cdev->spinlock); |
ac9dd9d3 | 55 | |
523f1dce | 56 | if (sub->stream == SNDRV_PCM_STREAM_PLAYBACK) |
1c8470ce | 57 | cdev->sub_playback[sub->number] = sub; |
523f1dce | 58 | else |
1c8470ce | 59 | cdev->sub_capture[sub->number] = sub; |
ac9dd9d3 | 60 | |
1c8470ce | 61 | spin_unlock(&cdev->spinlock); |
523f1dce DM |
62 | } |
63 | ||
9318dce5 | 64 | static void |
1c8470ce | 65 | deactivate_substream(struct snd_usb_caiaqdev *cdev, |
523f1dce DM |
66 | struct snd_pcm_substream *sub) |
67 | { | |
8d048841 | 68 | unsigned long flags; |
1c8470ce | 69 | spin_lock_irqsave(&cdev->spinlock, flags); |
8d048841 | 70 | |
523f1dce | 71 | if (sub->stream == SNDRV_PCM_STREAM_PLAYBACK) |
1c8470ce | 72 | cdev->sub_playback[sub->number] = NULL; |
523f1dce | 73 | else |
1c8470ce | 74 | cdev->sub_capture[sub->number] = NULL; |
8d048841 | 75 | |
1c8470ce | 76 | spin_unlock_irqrestore(&cdev->spinlock, flags); |
523f1dce DM |
77 | } |
78 | ||
79 | static int | |
80 | all_substreams_zero(struct snd_pcm_substream **subs) | |
81 | { | |
82 | int i; | |
83 | for (i = 0; i < MAX_STREAMS; i++) | |
84 | if (subs[i] != NULL) | |
85 | return 0; | |
86 | return 1; | |
87 | } | |
88 | ||
1c8470ce | 89 | static int stream_start(struct snd_usb_caiaqdev *cdev) |
523f1dce DM |
90 | { |
91 | int i, ret; | |
f1f6b8f6 | 92 | struct device *dev = caiaqdev_to_dev(cdev); |
523f1dce | 93 | |
f1f6b8f6 | 94 | dev_dbg(dev, "%s(%p)\n", __func__, cdev); |
8d048841 | 95 | |
1c8470ce | 96 | if (cdev->streaming) |
523f1dce | 97 | return -EINVAL; |
523f1dce | 98 | |
1c8470ce DM |
99 | memset(cdev->sub_playback, 0, sizeof(cdev->sub_playback)); |
100 | memset(cdev->sub_capture, 0, sizeof(cdev->sub_capture)); | |
101 | cdev->input_panic = 0; | |
102 | cdev->output_panic = 0; | |
103 | cdev->first_packet = 4; | |
104 | cdev->streaming = 1; | |
105 | cdev->warned = 0; | |
523f1dce DM |
106 | |
107 | for (i = 0; i < N_URBS; i++) { | |
1c8470ce | 108 | ret = usb_submit_urb(cdev->data_urbs_in[i], GFP_ATOMIC); |
523f1dce | 109 | if (ret) { |
f1f6b8f6 DM |
110 | dev_err(dev, "unable to trigger read #%d! (ret %d)\n", |
111 | i, ret); | |
1c8470ce | 112 | cdev->streaming = 0; |
523f1dce DM |
113 | return -EPIPE; |
114 | } | |
115 | } | |
9318dce5 | 116 | |
523f1dce DM |
117 | return 0; |
118 | } | |
119 | ||
1c8470ce | 120 | static void stream_stop(struct snd_usb_caiaqdev *cdev) |
523f1dce DM |
121 | { |
122 | int i; | |
f1f6b8f6 | 123 | struct device *dev = caiaqdev_to_dev(cdev); |
8d048841 | 124 | |
f1f6b8f6 | 125 | dev_dbg(dev, "%s(%p)\n", __func__, cdev); |
1c8470ce | 126 | if (!cdev->streaming) |
523f1dce | 127 | return; |
9318dce5 | 128 | |
1c8470ce | 129 | cdev->streaming = 0; |
8d048841 | 130 | |
523f1dce | 131 | for (i = 0; i < N_URBS; i++) { |
1c8470ce | 132 | usb_kill_urb(cdev->data_urbs_in[i]); |
da6094ea | 133 | |
1c8470ce DM |
134 | if (test_bit(i, &cdev->outurb_active_mask)) |
135 | usb_kill_urb(cdev->data_urbs_out[i]); | |
523f1dce | 136 | } |
da6094ea | 137 | |
1c8470ce | 138 | cdev->outurb_active_mask = 0; |
523f1dce DM |
139 | } |
140 | ||
141 | static int snd_usb_caiaq_substream_open(struct snd_pcm_substream *substream) | |
142 | { | |
1c8470ce | 143 | struct snd_usb_caiaqdev *cdev = snd_pcm_substream_chip(substream); |
f1f6b8f6 DM |
144 | struct device *dev = caiaqdev_to_dev(cdev); |
145 | ||
146 | dev_dbg(dev, "%s(%p)\n", __func__, substream); | |
1c8470ce | 147 | substream->runtime->hw = cdev->pcm_info; |
523f1dce | 148 | snd_pcm_limit_hw_rates(substream->runtime); |
f1f6b8f6 | 149 | |
523f1dce DM |
150 | return 0; |
151 | } | |
152 | ||
153 | static int snd_usb_caiaq_substream_close(struct snd_pcm_substream *substream) | |
154 | { | |
1c8470ce | 155 | struct snd_usb_caiaqdev *cdev = snd_pcm_substream_chip(substream); |
f1f6b8f6 | 156 | struct device *dev = caiaqdev_to_dev(cdev); |
523f1dce | 157 | |
f1f6b8f6 | 158 | dev_dbg(dev, "%s(%p)\n", __func__, substream); |
1c8470ce DM |
159 | if (all_substreams_zero(cdev->sub_playback) && |
160 | all_substreams_zero(cdev->sub_capture)) { | |
9318dce5 | 161 | /* when the last client has stopped streaming, |
523f1dce | 162 | * all sample rates are allowed again */ |
1c8470ce DM |
163 | stream_stop(cdev); |
164 | cdev->pcm_info.rates = cdev->samplerates; | |
523f1dce | 165 | } |
8d048841 | 166 | |
523f1dce DM |
167 | return 0; |
168 | } | |
169 | ||
523f1dce DM |
170 | static int snd_usb_caiaq_pcm_hw_free(struct snd_pcm_substream *sub) |
171 | { | |
1c8470ce | 172 | struct snd_usb_caiaqdev *cdev = snd_pcm_substream_chip(sub); |
1c8470ce | 173 | deactivate_substream(cdev, sub); |
1075b321 | 174 | return 0; |
523f1dce DM |
175 | } |
176 | ||
523f1dce DM |
177 | static int snd_usb_caiaq_pcm_prepare(struct snd_pcm_substream *substream) |
178 | { | |
af1d53b6 | 179 | int bytes_per_sample, bpp, ret; |
523f1dce | 180 | int index = substream->number; |
1c8470ce | 181 | struct snd_usb_caiaqdev *cdev = snd_pcm_substream_chip(substream); |
523f1dce | 182 | struct snd_pcm_runtime *runtime = substream->runtime; |
f1f6b8f6 | 183 | struct device *dev = caiaqdev_to_dev(cdev); |
523f1dce | 184 | |
f1f6b8f6 | 185 | dev_dbg(dev, "%s(%p)\n", __func__, substream); |
9318dce5 | 186 | |
a9b487fa | 187 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { |
15c5ab60 DM |
188 | int out_pos; |
189 | ||
1c8470ce | 190 | switch (cdev->spec.data_alignment) { |
15c5ab60 DM |
191 | case 0: |
192 | case 2: | |
193 | out_pos = BYTES_PER_SAMPLE + 1; | |
194 | break; | |
195 | case 3: | |
196 | default: | |
197 | out_pos = 0; | |
198 | break; | |
199 | } | |
200 | ||
1c8470ce DM |
201 | cdev->period_out_count[index] = out_pos; |
202 | cdev->audio_out_buf_pos[index] = out_pos; | |
a9b487fa | 203 | } else { |
15c5ab60 DM |
204 | int in_pos; |
205 | ||
1c8470ce | 206 | switch (cdev->spec.data_alignment) { |
15c5ab60 DM |
207 | case 0: |
208 | in_pos = BYTES_PER_SAMPLE + 2; | |
209 | break; | |
210 | case 2: | |
211 | in_pos = BYTES_PER_SAMPLE; | |
212 | break; | |
213 | case 3: | |
214 | default: | |
215 | in_pos = 0; | |
216 | break; | |
217 | } | |
218 | ||
1c8470ce DM |
219 | cdev->period_in_count[index] = in_pos; |
220 | cdev->audio_in_buf_pos[index] = in_pos; | |
a9b487fa DM |
221 | } |
222 | ||
1c8470ce | 223 | if (cdev->streaming) |
523f1dce | 224 | return 0; |
9318dce5 | 225 | |
523f1dce DM |
226 | /* the first client that opens a stream defines the sample rate |
227 | * setting for all subsequent calls, until the last client closed. */ | |
e95b9f7f | 228 | cdev->pcm_info.rates = snd_pcm_rate_to_rate_bit(runtime->rate); |
523f1dce DM |
229 | snd_pcm_limit_hw_rates(runtime); |
230 | ||
231 | bytes_per_sample = BYTES_PER_SAMPLE; | |
1c8470ce | 232 | if (cdev->spec.data_alignment >= 2) |
523f1dce | 233 | bytes_per_sample++; |
9318dce5 | 234 | |
523f1dce | 235 | bpp = ((runtime->rate / 8000) + CLOCK_DRIFT_TOLERANCE) |
1c8470ce | 236 | * bytes_per_sample * CHANNELS_PER_STREAM * cdev->n_streams; |
6e9fc6bd DM |
237 | |
238 | if (bpp > MAX_ENDPOINT_SIZE) | |
239 | bpp = MAX_ENDPOINT_SIZE; | |
240 | ||
1c8470ce | 241 | ret = snd_usb_caiaq_set_audio_params(cdev, runtime->rate, |
523f1dce DM |
242 | runtime->sample_bits, bpp); |
243 | if (ret) | |
244 | return ret; | |
245 | ||
1c8470ce | 246 | ret = stream_start(cdev); |
523f1dce DM |
247 | if (ret) |
248 | return ret; | |
9318dce5 | 249 | |
1c8470ce DM |
250 | cdev->output_running = 0; |
251 | wait_event_timeout(cdev->prepare_wait_queue, cdev->output_running, HZ); | |
252 | if (!cdev->output_running) { | |
253 | stream_stop(cdev); | |
523f1dce DM |
254 | return -EPIPE; |
255 | } | |
256 | ||
257 | return 0; | |
258 | } | |
259 | ||
260 | static int snd_usb_caiaq_pcm_trigger(struct snd_pcm_substream *sub, int cmd) | |
261 | { | |
1c8470ce | 262 | struct snd_usb_caiaqdev *cdev = snd_pcm_substream_chip(sub); |
f1f6b8f6 | 263 | struct device *dev = caiaqdev_to_dev(cdev); |
523f1dce | 264 | |
f1f6b8f6 | 265 | dev_dbg(dev, "%s(%p) cmd %d\n", __func__, sub, cmd); |
15c5ab60 | 266 | |
523f1dce DM |
267 | switch (cmd) { |
268 | case SNDRV_PCM_TRIGGER_START: | |
269 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | |
1c8470ce | 270 | activate_substream(cdev, sub); |
523f1dce DM |
271 | break; |
272 | case SNDRV_PCM_TRIGGER_STOP: | |
273 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | |
1c8470ce | 274 | deactivate_substream(cdev, sub); |
523f1dce DM |
275 | break; |
276 | default: | |
277 | return -EINVAL; | |
278 | } | |
279 | ||
280 | return 0; | |
281 | } | |
282 | ||
283 | static snd_pcm_uframes_t | |
284 | snd_usb_caiaq_pcm_pointer(struct snd_pcm_substream *sub) | |
285 | { | |
286 | int index = sub->number; | |
1c8470ce | 287 | struct snd_usb_caiaqdev *cdev = snd_pcm_substream_chip(sub); |
3702b082 MH |
288 | snd_pcm_uframes_t ptr; |
289 | ||
1c8470ce | 290 | spin_lock(&cdev->spinlock); |
523f1dce | 291 | |
1c8470ce | 292 | if (cdev->input_panic || cdev->output_panic) { |
3702b082 | 293 | ptr = SNDRV_PCM_POS_XRUN; |
cb74eb15 MH |
294 | goto unlock; |
295 | } | |
523f1dce DM |
296 | |
297 | if (sub->stream == SNDRV_PCM_STREAM_PLAYBACK) | |
3702b082 | 298 | ptr = bytes_to_frames(sub->runtime, |
1c8470ce | 299 | cdev->audio_out_buf_pos[index]); |
523f1dce | 300 | else |
3702b082 | 301 | ptr = bytes_to_frames(sub->runtime, |
1c8470ce | 302 | cdev->audio_in_buf_pos[index]); |
3702b082 | 303 | |
cb74eb15 | 304 | unlock: |
1c8470ce | 305 | spin_unlock(&cdev->spinlock); |
3702b082 | 306 | return ptr; |
523f1dce DM |
307 | } |
308 | ||
309 | /* operators for both playback and capture */ | |
31cb1fb4 | 310 | static const struct snd_pcm_ops snd_usb_caiaq_ops = { |
523f1dce DM |
311 | .open = snd_usb_caiaq_substream_open, |
312 | .close = snd_usb_caiaq_substream_close, | |
523f1dce DM |
313 | .hw_free = snd_usb_caiaq_pcm_hw_free, |
314 | .prepare = snd_usb_caiaq_pcm_prepare, | |
315 | .trigger = snd_usb_caiaq_pcm_trigger, | |
fc76f863 | 316 | .pointer = snd_usb_caiaq_pcm_pointer, |
523f1dce | 317 | }; |
9318dce5 | 318 | |
1c8470ce | 319 | static void check_for_elapsed_periods(struct snd_usb_caiaqdev *cdev, |
523f1dce DM |
320 | struct snd_pcm_substream **subs) |
321 | { | |
322 | int stream, pb, *cnt; | |
323 | struct snd_pcm_substream *sub; | |
324 | ||
1c8470ce | 325 | for (stream = 0; stream < cdev->n_streams; stream++) { |
523f1dce DM |
326 | sub = subs[stream]; |
327 | if (!sub) | |
328 | continue; | |
329 | ||
a9b487fa | 330 | pb = snd_pcm_lib_period_bytes(sub); |
523f1dce | 331 | cnt = (sub->stream == SNDRV_PCM_STREAM_PLAYBACK) ? |
1c8470ce DM |
332 | &cdev->period_out_count[stream] : |
333 | &cdev->period_in_count[stream]; | |
523f1dce DM |
334 | |
335 | if (*cnt >= pb) { | |
336 | snd_pcm_period_elapsed(sub); | |
337 | *cnt %= pb; | |
338 | } | |
339 | } | |
340 | } | |
341 | ||
1c8470ce | 342 | static void read_in_urb_mode0(struct snd_usb_caiaqdev *cdev, |
523f1dce DM |
343 | const struct urb *urb, |
344 | const struct usb_iso_packet_descriptor *iso) | |
345 | { | |
346 | unsigned char *usb_buf = urb->transfer_buffer + iso->offset; | |
347 | struct snd_pcm_substream *sub; | |
348 | int stream, i; | |
349 | ||
1c8470ce | 350 | if (all_substreams_zero(cdev->sub_capture)) |
523f1dce DM |
351 | return; |
352 | ||
523f1dce | 353 | for (i = 0; i < iso->actual_length;) { |
1c8470ce DM |
354 | for (stream = 0; stream < cdev->n_streams; stream++, i++) { |
355 | sub = cdev->sub_capture[stream]; | |
523f1dce DM |
356 | if (sub) { |
357 | struct snd_pcm_runtime *rt = sub->runtime; | |
358 | char *audio_buf = rt->dma_area; | |
359 | int sz = frames_to_bytes(rt, rt->buffer_size); | |
1c8470ce | 360 | audio_buf[cdev->audio_in_buf_pos[stream]++] |
523f1dce | 361 | = usb_buf[i]; |
1c8470ce DM |
362 | cdev->period_in_count[stream]++; |
363 | if (cdev->audio_in_buf_pos[stream] == sz) | |
364 | cdev->audio_in_buf_pos[stream] = 0; | |
523f1dce DM |
365 | } |
366 | } | |
367 | } | |
523f1dce DM |
368 | } |
369 | ||
1c8470ce | 370 | static void read_in_urb_mode2(struct snd_usb_caiaqdev *cdev, |
523f1dce DM |
371 | const struct urb *urb, |
372 | const struct usb_iso_packet_descriptor *iso) | |
373 | { | |
374 | unsigned char *usb_buf = urb->transfer_buffer + iso->offset; | |
375 | unsigned char check_byte; | |
376 | struct snd_pcm_substream *sub; | |
377 | int stream, i; | |
378 | ||
523f1dce | 379 | for (i = 0; i < iso->actual_length;) { |
1c8470ce | 380 | if (i % (cdev->n_streams * BYTES_PER_SAMPLE_USB) == 0) { |
9318dce5 | 381 | for (stream = 0; |
1c8470ce | 382 | stream < cdev->n_streams; |
523f1dce | 383 | stream++, i++) { |
1c8470ce | 384 | if (cdev->first_packet) |
523f1dce DM |
385 | continue; |
386 | ||
1c8470ce | 387 | check_byte = MAKE_CHECKBYTE(cdev, stream, i); |
9318dce5 | 388 | |
523f1dce | 389 | if ((usb_buf[i] & 0x3f) != check_byte) |
1c8470ce | 390 | cdev->input_panic = 1; |
523f1dce DM |
391 | |
392 | if (usb_buf[i] & 0x80) | |
1c8470ce | 393 | cdev->output_panic = 1; |
523f1dce DM |
394 | } |
395 | } | |
1c8470ce | 396 | cdev->first_packet = 0; |
523f1dce | 397 | |
1c8470ce DM |
398 | for (stream = 0; stream < cdev->n_streams; stream++, i++) { |
399 | sub = cdev->sub_capture[stream]; | |
400 | if (cdev->input_panic) | |
9311c9b4 DM |
401 | usb_buf[i] = 0; |
402 | ||
523f1dce DM |
403 | if (sub) { |
404 | struct snd_pcm_runtime *rt = sub->runtime; | |
405 | char *audio_buf = rt->dma_area; | |
406 | int sz = frames_to_bytes(rt, rt->buffer_size); | |
1c8470ce | 407 | audio_buf[cdev->audio_in_buf_pos[stream]++] = |
a971c3d4 | 408 | usb_buf[i]; |
1c8470ce DM |
409 | cdev->period_in_count[stream]++; |
410 | if (cdev->audio_in_buf_pos[stream] == sz) | |
411 | cdev->audio_in_buf_pos[stream] = 0; | |
523f1dce DM |
412 | } |
413 | } | |
414 | } | |
523f1dce DM |
415 | } |
416 | ||
1c8470ce | 417 | static void read_in_urb_mode3(struct snd_usb_caiaqdev *cdev, |
15c5ab60 DM |
418 | const struct urb *urb, |
419 | const struct usb_iso_packet_descriptor *iso) | |
420 | { | |
421 | unsigned char *usb_buf = urb->transfer_buffer + iso->offset; | |
f1f6b8f6 | 422 | struct device *dev = caiaqdev_to_dev(cdev); |
15c5ab60 DM |
423 | int stream, i; |
424 | ||
425 | /* paranoia check */ | |
426 | if (iso->actual_length % (BYTES_PER_SAMPLE_USB * CHANNELS_PER_STREAM)) | |
427 | return; | |
428 | ||
429 | for (i = 0; i < iso->actual_length;) { | |
1c8470ce DM |
430 | for (stream = 0; stream < cdev->n_streams; stream++) { |
431 | struct snd_pcm_substream *sub = cdev->sub_capture[stream]; | |
15c5ab60 DM |
432 | char *audio_buf = NULL; |
433 | int c, n, sz = 0; | |
434 | ||
1c8470ce | 435 | if (sub && !cdev->input_panic) { |
15c5ab60 DM |
436 | struct snd_pcm_runtime *rt = sub->runtime; |
437 | audio_buf = rt->dma_area; | |
438 | sz = frames_to_bytes(rt, rt->buffer_size); | |
439 | } | |
440 | ||
441 | for (c = 0; c < CHANNELS_PER_STREAM; c++) { | |
442 | /* 3 audio data bytes, followed by 1 check byte */ | |
443 | if (audio_buf) { | |
444 | for (n = 0; n < BYTES_PER_SAMPLE; n++) { | |
1c8470ce | 445 | audio_buf[cdev->audio_in_buf_pos[stream]++] = usb_buf[i+n]; |
15c5ab60 | 446 | |
1c8470ce DM |
447 | if (cdev->audio_in_buf_pos[stream] == sz) |
448 | cdev->audio_in_buf_pos[stream] = 0; | |
15c5ab60 DM |
449 | } |
450 | ||
1c8470ce | 451 | cdev->period_in_count[stream] += BYTES_PER_SAMPLE; |
15c5ab60 DM |
452 | } |
453 | ||
454 | i += BYTES_PER_SAMPLE; | |
455 | ||
456 | if (usb_buf[i] != ((stream << 1) | c) && | |
1c8470ce DM |
457 | !cdev->first_packet) { |
458 | if (!cdev->input_panic) | |
f1f6b8f6 DM |
459 | dev_warn(dev, " EXPECTED: %02x got %02x, c %d, stream %d, i %d\n", |
460 | ((stream << 1) | c), usb_buf[i], c, stream, i); | |
1c8470ce | 461 | cdev->input_panic = 1; |
15c5ab60 DM |
462 | } |
463 | ||
464 | i++; | |
465 | } | |
466 | } | |
467 | } | |
468 | ||
1c8470ce DM |
469 | if (cdev->first_packet > 0) |
470 | cdev->first_packet--; | |
15c5ab60 DM |
471 | } |
472 | ||
1c8470ce | 473 | static void read_in_urb(struct snd_usb_caiaqdev *cdev, |
523f1dce DM |
474 | const struct urb *urb, |
475 | const struct usb_iso_packet_descriptor *iso) | |
476 | { | |
f1f6b8f6 DM |
477 | struct device *dev = caiaqdev_to_dev(cdev); |
478 | ||
1c8470ce | 479 | if (!cdev->streaming) |
523f1dce DM |
480 | return; |
481 | ||
1c8470ce | 482 | if (iso->actual_length < cdev->bpp) |
9311c9b4 DM |
483 | return; |
484 | ||
1c8470ce | 485 | switch (cdev->spec.data_alignment) { |
523f1dce | 486 | case 0: |
1c8470ce | 487 | read_in_urb_mode0(cdev, urb, iso); |
523f1dce DM |
488 | break; |
489 | case 2: | |
1c8470ce | 490 | read_in_urb_mode2(cdev, urb, iso); |
523f1dce | 491 | break; |
15c5ab60 | 492 | case 3: |
1c8470ce | 493 | read_in_urb_mode3(cdev, urb, iso); |
15c5ab60 | 494 | break; |
523f1dce DM |
495 | } |
496 | ||
1c8470ce | 497 | if ((cdev->input_panic || cdev->output_panic) && !cdev->warned) { |
f1f6b8f6 | 498 | dev_warn(dev, "streaming error detected %s %s\n", |
1c8470ce DM |
499 | cdev->input_panic ? "(input)" : "", |
500 | cdev->output_panic ? "(output)" : ""); | |
501 | cdev->warned = 1; | |
523f1dce | 502 | } |
523f1dce DM |
503 | } |
504 | ||
1c8470ce | 505 | static void fill_out_urb_mode_0(struct snd_usb_caiaqdev *cdev, |
15c5ab60 DM |
506 | struct urb *urb, |
507 | const struct usb_iso_packet_descriptor *iso) | |
523f1dce DM |
508 | { |
509 | unsigned char *usb_buf = urb->transfer_buffer + iso->offset; | |
510 | struct snd_pcm_substream *sub; | |
511 | int stream, i; | |
9318dce5 | 512 | |
523f1dce | 513 | for (i = 0; i < iso->length;) { |
1c8470ce DM |
514 | for (stream = 0; stream < cdev->n_streams; stream++, i++) { |
515 | sub = cdev->sub_playback[stream]; | |
523f1dce DM |
516 | if (sub) { |
517 | struct snd_pcm_runtime *rt = sub->runtime; | |
518 | char *audio_buf = rt->dma_area; | |
519 | int sz = frames_to_bytes(rt, rt->buffer_size); | |
a971c3d4 | 520 | usb_buf[i] = |
1c8470ce DM |
521 | audio_buf[cdev->audio_out_buf_pos[stream]]; |
522 | cdev->period_out_count[stream]++; | |
523 | cdev->audio_out_buf_pos[stream]++; | |
524 | if (cdev->audio_out_buf_pos[stream] == sz) | |
525 | cdev->audio_out_buf_pos[stream] = 0; | |
523f1dce | 526 | } else |
a971c3d4 KW |
527 | usb_buf[i] = 0; |
528 | } | |
523f1dce DM |
529 | |
530 | /* fill in the check bytes */ | |
1c8470ce DM |
531 | if (cdev->spec.data_alignment == 2 && |
532 | i % (cdev->n_streams * BYTES_PER_SAMPLE_USB) == | |
533 | (cdev->n_streams * CHANNELS_PER_STREAM)) | |
534 | for (stream = 0; stream < cdev->n_streams; stream++, i++) | |
535 | usb_buf[i] = MAKE_CHECKBYTE(cdev, stream, i); | |
15c5ab60 DM |
536 | } |
537 | } | |
538 | ||
1c8470ce | 539 | static void fill_out_urb_mode_3(struct snd_usb_caiaqdev *cdev, |
15c5ab60 DM |
540 | struct urb *urb, |
541 | const struct usb_iso_packet_descriptor *iso) | |
542 | { | |
543 | unsigned char *usb_buf = urb->transfer_buffer + iso->offset; | |
544 | int stream, i; | |
545 | ||
546 | for (i = 0; i < iso->length;) { | |
1c8470ce DM |
547 | for (stream = 0; stream < cdev->n_streams; stream++) { |
548 | struct snd_pcm_substream *sub = cdev->sub_playback[stream]; | |
15c5ab60 DM |
549 | char *audio_buf = NULL; |
550 | int c, n, sz = 0; | |
551 | ||
552 | if (sub) { | |
553 | struct snd_pcm_runtime *rt = sub->runtime; | |
554 | audio_buf = rt->dma_area; | |
555 | sz = frames_to_bytes(rt, rt->buffer_size); | |
556 | } | |
557 | ||
558 | for (c = 0; c < CHANNELS_PER_STREAM; c++) { | |
559 | for (n = 0; n < BYTES_PER_SAMPLE; n++) { | |
560 | if (audio_buf) { | |
1c8470ce | 561 | usb_buf[i+n] = audio_buf[cdev->audio_out_buf_pos[stream]++]; |
15c5ab60 | 562 | |
1c8470ce DM |
563 | if (cdev->audio_out_buf_pos[stream] == sz) |
564 | cdev->audio_out_buf_pos[stream] = 0; | |
15c5ab60 DM |
565 | } else { |
566 | usb_buf[i+n] = 0; | |
567 | } | |
568 | } | |
569 | ||
570 | if (audio_buf) | |
1c8470ce | 571 | cdev->period_out_count[stream] += BYTES_PER_SAMPLE; |
15c5ab60 DM |
572 | |
573 | i += BYTES_PER_SAMPLE; | |
574 | ||
575 | /* fill in the check byte pattern */ | |
576 | usb_buf[i++] = (stream << 1) | c; | |
577 | } | |
578 | } | |
579 | } | |
580 | } | |
581 | ||
1c8470ce | 582 | static inline void fill_out_urb(struct snd_usb_caiaqdev *cdev, |
15c5ab60 DM |
583 | struct urb *urb, |
584 | const struct usb_iso_packet_descriptor *iso) | |
585 | { | |
1c8470ce | 586 | switch (cdev->spec.data_alignment) { |
15c5ab60 DM |
587 | case 0: |
588 | case 2: | |
1c8470ce | 589 | fill_out_urb_mode_0(cdev, urb, iso); |
15c5ab60 DM |
590 | break; |
591 | case 3: | |
1c8470ce | 592 | fill_out_urb_mode_3(cdev, urb, iso); |
15c5ab60 | 593 | break; |
523f1dce | 594 | } |
523f1dce DM |
595 | } |
596 | ||
597 | static void read_completed(struct urb *urb) | |
598 | { | |
9318dce5 | 599 | struct snd_usb_caiaq_cb_info *info = urb->context; |
1c8470ce | 600 | struct snd_usb_caiaqdev *cdev; |
f1f6b8f6 | 601 | struct device *dev; |
da6094ea DM |
602 | struct urb *out = NULL; |
603 | int i, frame, len, send_it = 0, outframe = 0; | |
9b11233d | 604 | unsigned long flags; |
15439bde | 605 | size_t offset = 0; |
523f1dce DM |
606 | |
607 | if (urb->status || !info) | |
608 | return; | |
609 | ||
1c8470ce | 610 | cdev = info->cdev; |
f1f6b8f6 | 611 | dev = caiaqdev_to_dev(cdev); |
8d048841 | 612 | |
1c8470ce | 613 | if (!cdev->streaming) |
523f1dce DM |
614 | return; |
615 | ||
da6094ea DM |
616 | /* find an unused output urb that is unused */ |
617 | for (i = 0; i < N_URBS; i++) | |
1c8470ce DM |
618 | if (test_and_set_bit(i, &cdev->outurb_active_mask) == 0) { |
619 | out = cdev->data_urbs_out[i]; | |
da6094ea DM |
620 | break; |
621 | } | |
622 | ||
623 | if (!out) { | |
f1f6b8f6 | 624 | dev_err(dev, "Unable to find an output urb to use\n"); |
da6094ea DM |
625 | goto requeue; |
626 | } | |
523f1dce DM |
627 | |
628 | /* read the recently received packet and send back one which has | |
629 | * the same layout */ | |
630 | for (frame = 0; frame < FRAMES_PER_URB; frame++) { | |
631 | if (urb->iso_frame_desc[frame].status) | |
632 | continue; | |
633 | ||
634 | len = urb->iso_frame_desc[outframe].actual_length; | |
635 | out->iso_frame_desc[outframe].length = len; | |
636 | out->iso_frame_desc[outframe].actual_length = 0; | |
15439bde DM |
637 | out->iso_frame_desc[outframe].offset = offset; |
638 | offset += len; | |
9318dce5 | 639 | |
523f1dce | 640 | if (len > 0) { |
9b11233d | 641 | spin_lock_irqsave(&cdev->spinlock, flags); |
1c8470ce DM |
642 | fill_out_urb(cdev, out, &out->iso_frame_desc[outframe]); |
643 | read_in_urb(cdev, urb, &urb->iso_frame_desc[frame]); | |
9b11233d | 644 | spin_unlock_irqrestore(&cdev->spinlock, flags); |
1c8470ce DM |
645 | check_for_elapsed_periods(cdev, cdev->sub_playback); |
646 | check_for_elapsed_periods(cdev, cdev->sub_capture); | |
523f1dce DM |
647 | send_it = 1; |
648 | } | |
649 | ||
650 | outframe++; | |
651 | } | |
652 | ||
653 | if (send_it) { | |
15439bde | 654 | out->number_of_packets = outframe; |
523f1dce | 655 | usb_submit_urb(out, GFP_ATOMIC); |
da6094ea DM |
656 | } else { |
657 | struct snd_usb_caiaq_cb_info *oinfo = out->context; | |
1c8470ce | 658 | clear_bit(oinfo->index, &cdev->outurb_active_mask); |
523f1dce | 659 | } |
9318dce5 | 660 | |
da6094ea | 661 | requeue: |
523f1dce DM |
662 | /* re-submit inbound urb */ |
663 | for (frame = 0; frame < FRAMES_PER_URB; frame++) { | |
664 | urb->iso_frame_desc[frame].offset = BYTES_PER_FRAME * frame; | |
665 | urb->iso_frame_desc[frame].length = BYTES_PER_FRAME; | |
666 | urb->iso_frame_desc[frame].actual_length = 0; | |
667 | } | |
9318dce5 | 668 | |
523f1dce | 669 | urb->number_of_packets = FRAMES_PER_URB; |
523f1dce DM |
670 | usb_submit_urb(urb, GFP_ATOMIC); |
671 | } | |
672 | ||
673 | static void write_completed(struct urb *urb) | |
674 | { | |
675 | struct snd_usb_caiaq_cb_info *info = urb->context; | |
1c8470ce | 676 | struct snd_usb_caiaqdev *cdev = info->cdev; |
523f1dce | 677 | |
1c8470ce DM |
678 | if (!cdev->output_running) { |
679 | cdev->output_running = 1; | |
680 | wake_up(&cdev->prepare_wait_queue); | |
523f1dce | 681 | } |
da6094ea | 682 | |
1c8470ce | 683 | clear_bit(info->index, &cdev->outurb_active_mask); |
523f1dce DM |
684 | } |
685 | ||
1c8470ce | 686 | static struct urb **alloc_urbs(struct snd_usb_caiaqdev *cdev, int dir, int *ret) |
523f1dce DM |
687 | { |
688 | int i, frame; | |
689 | struct urb **urbs; | |
1c8470ce | 690 | struct usb_device *usb_dev = cdev->chip.dev; |
523f1dce DM |
691 | unsigned int pipe; |
692 | ||
9318dce5 | 693 | pipe = (dir == SNDRV_PCM_STREAM_PLAYBACK) ? |
523f1dce DM |
694 | usb_sndisocpipe(usb_dev, ENDPOINT_PLAYBACK) : |
695 | usb_rcvisocpipe(usb_dev, ENDPOINT_CAPTURE); | |
696 | ||
6da2ec56 | 697 | urbs = kmalloc_array(N_URBS, sizeof(*urbs), GFP_KERNEL); |
523f1dce | 698 | if (!urbs) { |
523f1dce DM |
699 | *ret = -ENOMEM; |
700 | return NULL; | |
701 | } | |
702 | ||
703 | for (i = 0; i < N_URBS; i++) { | |
704 | urbs[i] = usb_alloc_urb(FRAMES_PER_URB, GFP_KERNEL); | |
705 | if (!urbs[i]) { | |
523f1dce DM |
706 | *ret = -ENOMEM; |
707 | return urbs; | |
708 | } | |
709 | ||
9318dce5 | 710 | urbs[i]->transfer_buffer = |
6da2ec56 KC |
711 | kmalloc_array(BYTES_PER_FRAME, FRAMES_PER_URB, |
712 | GFP_KERNEL); | |
523f1dce | 713 | if (!urbs[i]->transfer_buffer) { |
523f1dce DM |
714 | *ret = -ENOMEM; |
715 | return urbs; | |
716 | } | |
9318dce5 | 717 | |
523f1dce | 718 | for (frame = 0; frame < FRAMES_PER_URB; frame++) { |
9318dce5 | 719 | struct usb_iso_packet_descriptor *iso = |
523f1dce | 720 | &urbs[i]->iso_frame_desc[frame]; |
9318dce5 | 721 | |
523f1dce DM |
722 | iso->offset = BYTES_PER_FRAME * frame; |
723 | iso->length = BYTES_PER_FRAME; | |
724 | } | |
9318dce5 | 725 | |
523f1dce DM |
726 | urbs[i]->dev = usb_dev; |
727 | urbs[i]->pipe = pipe; | |
9318dce5 | 728 | urbs[i]->transfer_buffer_length = FRAMES_PER_URB |
523f1dce | 729 | * BYTES_PER_FRAME; |
1c8470ce | 730 | urbs[i]->context = &cdev->data_cb_info[i]; |
523f1dce | 731 | urbs[i]->interval = 1; |
523f1dce DM |
732 | urbs[i]->number_of_packets = FRAMES_PER_URB; |
733 | urbs[i]->complete = (dir == SNDRV_PCM_STREAM_CAPTURE) ? | |
734 | read_completed : write_completed; | |
735 | } | |
736 | ||
737 | *ret = 0; | |
738 | return urbs; | |
739 | } | |
740 | ||
741 | static void free_urbs(struct urb **urbs) | |
742 | { | |
743 | int i; | |
744 | ||
745 | if (!urbs) | |
746 | return; | |
747 | ||
748 | for (i = 0; i < N_URBS; i++) { | |
749 | if (!urbs[i]) | |
750 | continue; | |
9318dce5 | 751 | |
523f1dce DM |
752 | usb_kill_urb(urbs[i]); |
753 | kfree(urbs[i]->transfer_buffer); | |
754 | usb_free_urb(urbs[i]); | |
755 | } | |
756 | ||
757 | kfree(urbs); | |
758 | } | |
759 | ||
1c8470ce | 760 | int snd_usb_caiaq_audio_init(struct snd_usb_caiaqdev *cdev) |
523f1dce DM |
761 | { |
762 | int i, ret; | |
f1f6b8f6 | 763 | struct device *dev = caiaqdev_to_dev(cdev); |
523f1dce | 764 | |
1c8470ce DM |
765 | cdev->n_audio_in = max(cdev->spec.num_analog_audio_in, |
766 | cdev->spec.num_digital_audio_in) / | |
523f1dce | 767 | CHANNELS_PER_STREAM; |
1c8470ce DM |
768 | cdev->n_audio_out = max(cdev->spec.num_analog_audio_out, |
769 | cdev->spec.num_digital_audio_out) / | |
523f1dce | 770 | CHANNELS_PER_STREAM; |
1c8470ce | 771 | cdev->n_streams = max(cdev->n_audio_in, cdev->n_audio_out); |
523f1dce | 772 | |
f1f6b8f6 DM |
773 | dev_dbg(dev, "cdev->n_audio_in = %d\n", cdev->n_audio_in); |
774 | dev_dbg(dev, "cdev->n_audio_out = %d\n", cdev->n_audio_out); | |
775 | dev_dbg(dev, "cdev->n_streams = %d\n", cdev->n_streams); | |
523f1dce | 776 | |
1c8470ce | 777 | if (cdev->n_streams > MAX_STREAMS) { |
f1f6b8f6 | 778 | dev_err(dev, "unable to initialize device, too many streams.\n"); |
523f1dce DM |
779 | return -EINVAL; |
780 | } | |
781 | ||
49cdd5b6 | 782 | if (cdev->n_streams < 1) { |
897c329b DM |
783 | dev_err(dev, "bogus number of streams: %d\n", cdev->n_streams); |
784 | return -EINVAL; | |
785 | } | |
786 | ||
1c8470ce DM |
787 | ret = snd_pcm_new(cdev->chip.card, cdev->product_name, 0, |
788 | cdev->n_audio_out, cdev->n_audio_in, &cdev->pcm); | |
523f1dce DM |
789 | |
790 | if (ret < 0) { | |
f1f6b8f6 | 791 | dev_err(dev, "snd_pcm_new() returned %d\n", ret); |
523f1dce DM |
792 | return ret; |
793 | } | |
794 | ||
1c8470ce | 795 | cdev->pcm->private_data = cdev; |
75b1a8f9 | 796 | strscpy(cdev->pcm->name, cdev->product_name, sizeof(cdev->pcm->name)); |
523f1dce | 797 | |
1c8470ce DM |
798 | memset(cdev->sub_playback, 0, sizeof(cdev->sub_playback)); |
799 | memset(cdev->sub_capture, 0, sizeof(cdev->sub_capture)); | |
9318dce5 | 800 | |
1c8470ce | 801 | memcpy(&cdev->pcm_info, &snd_usb_caiaq_pcm_hardware, |
523f1dce DM |
802 | sizeof(snd_usb_caiaq_pcm_hardware)); |
803 | ||
804 | /* setup samplerates */ | |
1c8470ce DM |
805 | cdev->samplerates = cdev->pcm_info.rates; |
806 | switch (cdev->chip.usb_id) { | |
523f1dce | 807 | case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AK1): |
ad1e34b5 | 808 | case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_RIGKONTROL3): |
f3e9d5d1 | 809 | case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_SESSIONIO): |
2165592b | 810 | case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_GUITARRIGMOBILE): |
1c8470ce | 811 | cdev->samplerates |= SNDRV_PCM_RATE_192000; |
e2d413f9 | 812 | fallthrough; |
b30c4947 | 813 | case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO2DJ): |
2165592b | 814 | case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO4DJ): |
523f1dce | 815 | case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO8DJ): |
df8d81a3 | 816 | case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORAUDIO2): |
1c8470ce | 817 | cdev->samplerates |= SNDRV_PCM_RATE_88200; |
523f1dce DM |
818 | break; |
819 | } | |
820 | ||
1c8470ce | 821 | snd_pcm_set_ops(cdev->pcm, SNDRV_PCM_STREAM_PLAYBACK, |
523f1dce | 822 | &snd_usb_caiaq_ops); |
1c8470ce | 823 | snd_pcm_set_ops(cdev->pcm, SNDRV_PCM_STREAM_CAPTURE, |
523f1dce | 824 | &snd_usb_caiaq_ops); |
1075b321 TI |
825 | snd_pcm_set_managed_buffer_all(cdev->pcm, SNDRV_DMA_TYPE_VMALLOC, |
826 | NULL, 0, 0); | |
523f1dce | 827 | |
1c8470ce | 828 | cdev->data_cb_info = |
6da2ec56 | 829 | kmalloc_array(N_URBS, sizeof(struct snd_usb_caiaq_cb_info), |
523f1dce DM |
830 | GFP_KERNEL); |
831 | ||
1c8470ce | 832 | if (!cdev->data_cb_info) |
523f1dce DM |
833 | return -ENOMEM; |
834 | ||
1c8470ce DM |
835 | cdev->outurb_active_mask = 0; |
836 | BUILD_BUG_ON(N_URBS > (sizeof(cdev->outurb_active_mask) * 8)); | |
da6094ea | 837 | |
523f1dce | 838 | for (i = 0; i < N_URBS; i++) { |
1c8470ce DM |
839 | cdev->data_cb_info[i].cdev = cdev; |
840 | cdev->data_cb_info[i].index = i; | |
523f1dce | 841 | } |
9318dce5 | 842 | |
1c8470ce | 843 | cdev->data_urbs_in = alloc_urbs(cdev, SNDRV_PCM_STREAM_CAPTURE, &ret); |
523f1dce | 844 | if (ret < 0) { |
1c8470ce DM |
845 | kfree(cdev->data_cb_info); |
846 | free_urbs(cdev->data_urbs_in); | |
523f1dce DM |
847 | return ret; |
848 | } | |
9318dce5 | 849 | |
1c8470ce | 850 | cdev->data_urbs_out = alloc_urbs(cdev, SNDRV_PCM_STREAM_PLAYBACK, &ret); |
523f1dce | 851 | if (ret < 0) { |
1c8470ce DM |
852 | kfree(cdev->data_cb_info); |
853 | free_urbs(cdev->data_urbs_in); | |
854 | free_urbs(cdev->data_urbs_out); | |
523f1dce DM |
855 | return ret; |
856 | } | |
857 | ||
858 | return 0; | |
859 | } | |
860 | ||
1c8470ce | 861 | void snd_usb_caiaq_audio_free(struct snd_usb_caiaqdev *cdev) |
523f1dce | 862 | { |
f1f6b8f6 DM |
863 | struct device *dev = caiaqdev_to_dev(cdev); |
864 | ||
865 | dev_dbg(dev, "%s(%p)\n", __func__, cdev); | |
1c8470ce DM |
866 | stream_stop(cdev); |
867 | free_urbs(cdev->data_urbs_in); | |
868 | free_urbs(cdev->data_urbs_out); | |
869 | kfree(cdev->data_cb_info); | |
523f1dce DM |
870 | } |
871 |