blob: c46400be54641b9d9b78c3cbb447a4a435ccd3e1 [file] [log] [blame]
Greg Kroah-Hartman5fd54ac2017-11-03 11:28:30 +01001// SPDX-License-Identifier: GPL-2.0+
Ruslan Bilovoleb9fecb2017-06-18 16:23:52 +03002/*
3 * u_audio.c -- interface to USB gadget "ALSA sound card" utilities
4 *
5 * Copyright (C) 2016
6 * Author: Ruslan Bilovol <ruslan.bilovol@gmail.com>
7 *
8 * Sound card implementation was cut-and-pasted with changes
9 * from f_uac2.c and has:
10 * Copyright (C) 2011
11 * Yadwinder Singh (yadi.brar01@gmail.com)
12 * Jaswinder Singh (jaswinder.singh@linaro.org)
Ruslan Bilovoleb9fecb2017-06-18 16:23:52 +030013 */
14
Ruslan Bilovol02de6982021-07-12 14:55:27 +020015#include <linux/kernel.h>
Ruslan Bilovoleb9fecb2017-06-18 16:23:52 +030016#include <linux/module.h>
17#include <sound/core.h>
18#include <sound/pcm.h>
19#include <sound/pcm_params.h>
Ruslan Bilovole89bb422021-06-04 00:01:04 +020020#include <sound/control.h>
Ruslan Bilovol02de6982021-07-12 14:55:27 +020021#include <sound/tlv.h>
22#include <linux/usb/audio.h>
Ruslan Bilovoleb9fecb2017-06-18 16:23:52 +030023
24#include "u_audio.h"
25
26#define BUFF_SIZE_MAX (PAGE_SIZE * 16)
27#define PRD_SIZE_MAX PAGE_SIZE
28#define MIN_PERIODS 4
29
Ruslan Bilovol02de6982021-07-12 14:55:27 +020030enum {
31 UAC_FBACK_CTRL,
Pavel Hofman6fec0182021-10-13 09:39:34 +020032 UAC_P_PITCH_CTRL,
Ruslan Bilovol02de6982021-07-12 14:55:27 +020033 UAC_MUTE_CTRL,
34 UAC_VOLUME_CTRL,
35};
36
Ruslan Bilovoleb9fecb2017-06-18 16:23:52 +030037/* Runtime data params for one stream */
38struct uac_rtd_params {
39 struct snd_uac_chip *uac; /* parent chip */
40 bool ep_enabled; /* if the ep is enabled */
Ruslan Bilovoleb9fecb2017-06-18 16:23:52 +030041
42 struct snd_pcm_substream *ss;
43
44 /* Ring buffer */
45 ssize_t hw_ptr;
46
47 void *rbuf;
48
Ruslan Bilovole89bb422021-06-04 00:01:04 +020049 unsigned int pitch; /* Stream pitch ratio to 1000000 */
Jonas Stenvallf4408a92019-06-13 11:34:33 +020050 unsigned int max_psize; /* MaxPacketSize of endpoint */
Ruslan Bilovoleb9fecb2017-06-18 16:23:52 +030051
Jerome Brunetd70f7592021-01-18 09:49:31 +010052 struct usb_request **reqs;
Ruslan Bilovol24f779d2021-06-04 00:01:02 +020053
54 struct usb_request *req_fback; /* Feedback endpoint request */
Ruslan Bilovol24f779d2021-06-04 00:01:02 +020055 bool fb_ep_enabled; /* if the ep is enabled */
Ruslan Bilovol02de6982021-07-12 14:55:27 +020056
57 /* Volume/Mute controls and their state */
58 int fu_id; /* Feature Unit ID */
59 struct snd_kcontrol *snd_kctl_volume;
60 struct snd_kcontrol *snd_kctl_mute;
61 s16 volume_min, volume_max, volume_res;
62 s16 volume;
63 int mute;
64
65 spinlock_t lock; /* lock for control transfers */
66
Ruslan Bilovoleb9fecb2017-06-18 16:23:52 +030067};
68
69struct snd_uac_chip {
70 struct g_audio *audio_dev;
71
72 struct uac_rtd_params p_prm;
73 struct uac_rtd_params c_prm;
74
75 struct snd_card *card;
76 struct snd_pcm *pcm;
77
Ruslan Bilovoleb9fecb2017-06-18 16:23:52 +030078 /* pre-calculated values for playback iso completion */
Pavel Hofman6fec0182021-10-13 09:39:34 +020079 unsigned long long p_interval_mil;
80 unsigned long long p_residue_mil;
Ruslan Bilovoleb9fecb2017-06-18 16:23:52 +030081 unsigned int p_framesize;
82};
83
Bhumika Goyal2ab3c342017-08-13 18:13:11 +053084static const struct snd_pcm_hardware uac_pcm_hardware = {
Ruslan Bilovoleb9fecb2017-06-18 16:23:52 +030085 .info = SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER
86 | SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID
87 | SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME,
88 .rates = SNDRV_PCM_RATE_CONTINUOUS,
89 .periods_max = BUFF_SIZE_MAX / PRD_SIZE_MAX,
90 .buffer_bytes_max = BUFF_SIZE_MAX,
91 .period_bytes_max = PRD_SIZE_MAX,
92 .periods_min = MIN_PERIODS,
93};
94
Ruslan Bilovol24f779d2021-06-04 00:01:02 +020095static void u_audio_set_fback_frequency(enum usb_device_speed speed,
Pavel Hofmanf5dfd982021-09-06 15:08:22 +020096 struct usb_ep *out_ep,
Ruslan Bilovole89bb422021-06-04 00:01:04 +020097 unsigned long long freq,
98 unsigned int pitch,
99 void *buf)
Ruslan Bilovol24f779d2021-06-04 00:01:02 +0200100{
101 u32 ff = 0;
Pavel Hofmanf5dfd982021-09-06 15:08:22 +0200102 const struct usb_endpoint_descriptor *ep_desc;
Ruslan Bilovol24f779d2021-06-04 00:01:02 +0200103
Ruslan Bilovole89bb422021-06-04 00:01:04 +0200104 /*
105 * Because the pitch base is 1000000, the final divider here
106 * will be 1000 * 1000000 = 1953125 << 9
107 *
108 * Instead of dealing with big numbers lets fold this 9 left shift
109 */
110
Ruslan Bilovol24f779d2021-06-04 00:01:02 +0200111 if (speed == USB_SPEED_FULL) {
112 /*
113 * Full-speed feedback endpoints report frequency
Ruslan Bilovole89bb422021-06-04 00:01:04 +0200114 * in samples/frame
Ruslan Bilovol24f779d2021-06-04 00:01:02 +0200115 * Format is encoded in Q10.10 left-justified in the 24 bits,
116 * so that it has a Q10.14 format.
Ruslan Bilovole89bb422021-06-04 00:01:04 +0200117 *
118 * ff = (freq << 14) / 1000
Ruslan Bilovol24f779d2021-06-04 00:01:02 +0200119 */
Ruslan Bilovole89bb422021-06-04 00:01:04 +0200120 freq <<= 5;
Ruslan Bilovol24f779d2021-06-04 00:01:02 +0200121 } else {
122 /*
123 * High-speed feedback endpoints report frequency
124 * in samples/microframe.
125 * Format is encoded in Q12.13 fitted into four bytes so that
126 * the binary point is located between the second and the third
127 * byte fromat (that is Q16.16)
Ruslan Bilovole89bb422021-06-04 00:01:04 +0200128 *
129 * ff = (freq << 16) / 8000
Pavel Hofmanf5dfd982021-09-06 15:08:22 +0200130 *
131 * Win10 and OSX UAC2 drivers require number of samples per packet
132 * in order to honor the feedback value.
133 * Linux snd-usb-audio detects the applied bit-shift automatically.
Ruslan Bilovol24f779d2021-06-04 00:01:02 +0200134 */
Pavel Hofmanf5dfd982021-09-06 15:08:22 +0200135 ep_desc = out_ep->desc;
136 freq <<= 4 + (ep_desc->bInterval - 1);
Ruslan Bilovol24f779d2021-06-04 00:01:02 +0200137 }
Ruslan Bilovole89bb422021-06-04 00:01:04 +0200138
139 ff = DIV_ROUND_CLOSEST_ULL((freq * pitch), 1953125);
140
Ruslan Bilovol24f779d2021-06-04 00:01:02 +0200141 *(__le32 *)buf = cpu_to_le32(ff);
142}
143
Ruslan Bilovoleb9fecb2017-06-18 16:23:52 +0300144static void u_audio_iso_complete(struct usb_ep *ep, struct usb_request *req)
145{
Jonas Stenvallf4408a92019-06-13 11:34:33 +0200146 unsigned int pending;
Ruslan Bilovoleb9fecb2017-06-18 16:23:52 +0300147 unsigned int hw_ptr;
Ruslan Bilovoleb9fecb2017-06-18 16:23:52 +0300148 int status = req->status;
Ruslan Bilovoleb9fecb2017-06-18 16:23:52 +0300149 struct snd_pcm_substream *substream;
Vladimir Zapolskiy96afb542018-06-21 17:22:49 +0200150 struct snd_pcm_runtime *runtime;
Jerome Brunet29865112021-01-18 09:46:41 +0100151 struct uac_rtd_params *prm = req->context;
Ruslan Bilovoleb9fecb2017-06-18 16:23:52 +0300152 struct snd_uac_chip *uac = prm->uac;
Pavel Hofman6fec0182021-10-13 09:39:34 +0200153 struct g_audio *audio_dev = uac->audio_dev;
154 struct uac_params *params = &audio_dev->params;
155 unsigned int frames, p_pktsize;
156 unsigned long long pitched_rate_mil, p_pktsize_residue_mil,
157 residue_frames_mil, div_result;
Ruslan Bilovoleb9fecb2017-06-18 16:23:52 +0300158
159 /* i/f shutting down */
Jack Pham7de86812021-01-18 09:46:39 +0100160 if (!prm->ep_enabled) {
161 usb_ep_free_request(ep, req);
162 return;
163 }
164
165 if (req->status == -ESHUTDOWN)
Ruslan Bilovoleb9fecb2017-06-18 16:23:52 +0300166 return;
167
168 /*
169 * We can't really do much about bad xfers.
170 * Afterall, the ISOCH xfers could fail legitimately.
171 */
172 if (status)
173 pr_debug("%s: iso_complete status(%d) %d/%d\n",
174 __func__, status, req->actual, req->length);
175
176 substream = prm->ss;
177
178 /* Do nothing if ALSA isn't active */
179 if (!substream)
180 goto exit;
181
Jerome Brunetd70f7592021-01-18 09:49:31 +0100182 snd_pcm_stream_lock(substream);
Vladimir Zapolskiy56bc6152018-06-21 17:22:52 +0200183
Vladimir Zapolskiy96afb542018-06-21 17:22:49 +0200184 runtime = substream->runtime;
Vladimir Zapolskiy56bc6152018-06-21 17:22:52 +0200185 if (!runtime || !snd_pcm_running(substream)) {
Jerome Brunetd70f7592021-01-18 09:49:31 +0100186 snd_pcm_stream_unlock(substream);
Vladimir Zapolskiy56bc6152018-06-21 17:22:52 +0200187 goto exit;
188 }
189
Ruslan Bilovoleb9fecb2017-06-18 16:23:52 +0300190 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
191 /*
192 * For each IN packet, take the quotient of the current data
193 * rate and the endpoint's interval as the base packet size.
194 * If there is a residue from this division, add it to the
195 * residue accumulator.
196 */
Pavel Hofman6fec0182021-10-13 09:39:34 +0200197 pitched_rate_mil = (unsigned long long)
198 params->p_srate * prm->pitch;
199 div_result = pitched_rate_mil;
200 do_div(div_result, uac->p_interval_mil);
201 frames = (unsigned int) div_result;
202
203 pr_debug("p_srate %d, pitch %d, interval_mil %llu, frames %d\n",
204 params->p_srate, prm->pitch, uac->p_interval_mil, frames);
205
206 p_pktsize = min_t(unsigned int,
207 uac->p_framesize * frames,
208 ep->maxpacket);
209
210 if (p_pktsize < ep->maxpacket) {
211 residue_frames_mil = pitched_rate_mil - frames * uac->p_interval_mil;
212 p_pktsize_residue_mil = uac->p_framesize * residue_frames_mil;
213 } else
214 p_pktsize_residue_mil = 0;
215
216 req->length = p_pktsize;
217 uac->p_residue_mil += p_pktsize_residue_mil;
Ruslan Bilovoleb9fecb2017-06-18 16:23:52 +0300218
219 /*
Pavel Hofman6fec0182021-10-13 09:39:34 +0200220 * Whenever there are more bytes in the accumulator p_residue_mil than we
Ruslan Bilovoleb9fecb2017-06-18 16:23:52 +0300221 * need to add one more sample frame, increase this packet's
222 * size and decrease the accumulator.
223 */
Pavel Hofman6fec0182021-10-13 09:39:34 +0200224 div_result = uac->p_residue_mil;
225 do_div(div_result, uac->p_interval_mil);
226 if ((unsigned int) div_result >= uac->p_framesize) {
Ruslan Bilovoleb9fecb2017-06-18 16:23:52 +0300227 req->length += uac->p_framesize;
Pavel Hofman6fec0182021-10-13 09:39:34 +0200228 uac->p_residue_mil -= uac->p_framesize *
229 uac->p_interval_mil;
230 pr_debug("increased req length to %d\n", req->length);
Ruslan Bilovoleb9fecb2017-06-18 16:23:52 +0300231 }
Pavel Hofman6fec0182021-10-13 09:39:34 +0200232 pr_debug("remains uac->p_residue_mil %llu\n", uac->p_residue_mil);
Ruslan Bilovoleb9fecb2017-06-18 16:23:52 +0300233
234 req->actual = req->length;
235 }
236
Ruslan Bilovoleb9fecb2017-06-18 16:23:52 +0300237 hw_ptr = prm->hw_ptr;
Ruslan Bilovoleb9fecb2017-06-18 16:23:52 +0300238
Ruslan Bilovoleb9fecb2017-06-18 16:23:52 +0300239 /* Pack USB load in ALSA ring buffer */
Vladimir Zapolskiy96afb542018-06-21 17:22:49 +0200240 pending = runtime->dma_bytes - hw_ptr;
Ruslan Bilovoleb9fecb2017-06-18 16:23:52 +0300241
242 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
243 if (unlikely(pending < req->actual)) {
Vladimir Zapolskiy96afb542018-06-21 17:22:49 +0200244 memcpy(req->buf, runtime->dma_area + hw_ptr, pending);
245 memcpy(req->buf + pending, runtime->dma_area,
Ruslan Bilovoleb9fecb2017-06-18 16:23:52 +0300246 req->actual - pending);
247 } else {
Vladimir Zapolskiy96afb542018-06-21 17:22:49 +0200248 memcpy(req->buf, runtime->dma_area + hw_ptr,
249 req->actual);
Ruslan Bilovoleb9fecb2017-06-18 16:23:52 +0300250 }
251 } else {
252 if (unlikely(pending < req->actual)) {
Vladimir Zapolskiy96afb542018-06-21 17:22:49 +0200253 memcpy(runtime->dma_area + hw_ptr, req->buf, pending);
254 memcpy(runtime->dma_area, req->buf + pending,
Ruslan Bilovoleb9fecb2017-06-18 16:23:52 +0300255 req->actual - pending);
256 } else {
Vladimir Zapolskiy96afb542018-06-21 17:22:49 +0200257 memcpy(runtime->dma_area + hw_ptr, req->buf,
258 req->actual);
Ruslan Bilovoleb9fecb2017-06-18 16:23:52 +0300259 }
260 }
261
Joshua Frkuska6b37bd72018-06-21 17:22:48 +0200262 /* update hw_ptr after data is copied to memory */
Vladimir Zapolskiy96afb542018-06-21 17:22:49 +0200263 prm->hw_ptr = (hw_ptr + req->actual) % runtime->dma_bytes;
Vladimir Zapolskiy773e53d2018-06-21 17:22:50 +0200264 hw_ptr = prm->hw_ptr;
Jerome Brunetd70f7592021-01-18 09:49:31 +0100265 snd_pcm_stream_unlock(substream);
Joshua Frkuska6b37bd72018-06-21 17:22:48 +0200266
Vladimir Zapolskiy773e53d2018-06-21 17:22:50 +0200267 if ((hw_ptr % snd_pcm_lib_period_bytes(substream)) < req->actual)
268 snd_pcm_period_elapsed(substream);
269
Ruslan Bilovoleb9fecb2017-06-18 16:23:52 +0300270exit:
271 if (usb_ep_queue(ep, req, GFP_ATOMIC))
272 dev_err(uac->card->dev, "%d Error!\n", __LINE__);
Ruslan Bilovoleb9fecb2017-06-18 16:23:52 +0300273}
274
Ruslan Bilovol24f779d2021-06-04 00:01:02 +0200275static void u_audio_iso_fback_complete(struct usb_ep *ep,
276 struct usb_request *req)
277{
278 struct uac_rtd_params *prm = req->context;
279 struct snd_uac_chip *uac = prm->uac;
280 struct g_audio *audio_dev = uac->audio_dev;
Ruslan Bilovole89bb422021-06-04 00:01:04 +0200281 struct uac_params *params = &audio_dev->params;
Ruslan Bilovol24f779d2021-06-04 00:01:02 +0200282 int status = req->status;
Ruslan Bilovol24f779d2021-06-04 00:01:02 +0200283
284 /* i/f shutting down */
Jerome Brunet75432ba2021-08-27 09:58:53 +0200285 if (!prm->fb_ep_enabled) {
286 kfree(req->buf);
287 usb_ep_free_request(ep, req);
288 return;
289 }
290
291 if (req->status == -ESHUTDOWN)
Ruslan Bilovol24f779d2021-06-04 00:01:02 +0200292 return;
293
294 /*
295 * We can't really do much about bad xfers.
296 * Afterall, the ISOCH xfers could fail legitimately.
297 */
298 if (status)
299 pr_debug("%s: iso_complete status(%d) %d/%d\n",
300 __func__, status, req->actual, req->length);
301
Pavel Hofmanf5dfd982021-09-06 15:08:22 +0200302 u_audio_set_fback_frequency(audio_dev->gadget->speed, audio_dev->out_ep,
Ruslan Bilovole89bb422021-06-04 00:01:04 +0200303 params->c_srate, prm->pitch,
304 req->buf);
Ruslan Bilovol24f779d2021-06-04 00:01:02 +0200305
306 if (usb_ep_queue(ep, req, GFP_ATOMIC))
307 dev_err(uac->card->dev, "%d Error!\n", __LINE__);
308}
309
Ruslan Bilovoleb9fecb2017-06-18 16:23:52 +0300310static int uac_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
311{
312 struct snd_uac_chip *uac = snd_pcm_substream_chip(substream);
313 struct uac_rtd_params *prm;
314 struct g_audio *audio_dev;
315 struct uac_params *params;
Ruslan Bilovoleb9fecb2017-06-18 16:23:52 +0300316 int err = 0;
317
318 audio_dev = uac->audio_dev;
319 params = &audio_dev->params;
320
321 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
322 prm = &uac->p_prm;
323 else
324 prm = &uac->c_prm;
325
Ruslan Bilovoleb9fecb2017-06-18 16:23:52 +0300326 /* Reset */
327 prm->hw_ptr = 0;
328
329 switch (cmd) {
330 case SNDRV_PCM_TRIGGER_START:
331 case SNDRV_PCM_TRIGGER_RESUME:
332 prm->ss = substream;
333 break;
334 case SNDRV_PCM_TRIGGER_STOP:
335 case SNDRV_PCM_TRIGGER_SUSPEND:
336 prm->ss = NULL;
337 break;
338 default:
339 err = -EINVAL;
340 }
341
Ruslan Bilovoleb9fecb2017-06-18 16:23:52 +0300342 /* Clear buffer after Play stops */
343 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && !prm->ss)
344 memset(prm->rbuf, 0, prm->max_psize * params->req_number);
345
346 return err;
347}
348
349static snd_pcm_uframes_t uac_pcm_pointer(struct snd_pcm_substream *substream)
350{
351 struct snd_uac_chip *uac = snd_pcm_substream_chip(substream);
352 struct uac_rtd_params *prm;
353
354 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
355 prm = &uac->p_prm;
356 else
357 prm = &uac->c_prm;
358
359 return bytes_to_frames(substream->runtime, prm->hw_ptr);
360}
361
Jerome Brunet25dbd752021-01-18 09:46:40 +0100362static u64 uac_ssize_to_fmt(int ssize)
363{
364 u64 ret;
365
366 switch (ssize) {
367 case 3:
368 ret = SNDRV_PCM_FMTBIT_S24_3LE;
369 break;
370 case 4:
371 ret = SNDRV_PCM_FMTBIT_S32_LE;
372 break;
373 default:
374 ret = SNDRV_PCM_FMTBIT_S16_LE;
375 break;
376 }
377
378 return ret;
379}
380
Ruslan Bilovoleb9fecb2017-06-18 16:23:52 +0300381static int uac_pcm_open(struct snd_pcm_substream *substream)
382{
383 struct snd_uac_chip *uac = snd_pcm_substream_chip(substream);
384 struct snd_pcm_runtime *runtime = substream->runtime;
385 struct g_audio *audio_dev;
386 struct uac_params *params;
387 int p_ssize, c_ssize;
388 int p_srate, c_srate;
389 int p_chmask, c_chmask;
390
391 audio_dev = uac->audio_dev;
392 params = &audio_dev->params;
393 p_ssize = params->p_ssize;
394 c_ssize = params->c_ssize;
395 p_srate = params->p_srate;
396 c_srate = params->c_srate;
397 p_chmask = params->p_chmask;
398 c_chmask = params->c_chmask;
Pavel Hofman6fec0182021-10-13 09:39:34 +0200399 uac->p_residue_mil = 0;
Ruslan Bilovoleb9fecb2017-06-18 16:23:52 +0300400
401 runtime->hw = uac_pcm_hardware;
402
403 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
Ruslan Bilovoleb9fecb2017-06-18 16:23:52 +0300404 runtime->hw.rate_min = p_srate;
Jerome Brunet25dbd752021-01-18 09:46:40 +0100405 runtime->hw.formats = uac_ssize_to_fmt(p_ssize);
Ruslan Bilovoleb9fecb2017-06-18 16:23:52 +0300406 runtime->hw.channels_min = num_channels(p_chmask);
407 runtime->hw.period_bytes_min = 2 * uac->p_prm.max_psize
408 / runtime->hw.periods_min;
409 } else {
Ruslan Bilovoleb9fecb2017-06-18 16:23:52 +0300410 runtime->hw.rate_min = c_srate;
Jerome Brunet25dbd752021-01-18 09:46:40 +0100411 runtime->hw.formats = uac_ssize_to_fmt(c_ssize);
Ruslan Bilovoleb9fecb2017-06-18 16:23:52 +0300412 runtime->hw.channels_min = num_channels(c_chmask);
413 runtime->hw.period_bytes_min = 2 * uac->c_prm.max_psize
414 / runtime->hw.periods_min;
415 }
416
417 runtime->hw.rate_max = runtime->hw.rate_min;
418 runtime->hw.channels_max = runtime->hw.channels_min;
419
420 snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
421
422 return 0;
423}
424
425/* ALSA cries without these function pointers */
426static int uac_pcm_null(struct snd_pcm_substream *substream)
427{
428 return 0;
429}
430
Arvind Yadav640c0be2017-08-09 13:16:51 +0530431static const struct snd_pcm_ops uac_pcm_ops = {
Ruslan Bilovoleb9fecb2017-06-18 16:23:52 +0300432 .open = uac_pcm_open,
433 .close = uac_pcm_null,
Ruslan Bilovoleb9fecb2017-06-18 16:23:52 +0300434 .trigger = uac_pcm_trigger,
435 .pointer = uac_pcm_pointer,
436 .prepare = uac_pcm_null,
437};
438
439static inline void free_ep(struct uac_rtd_params *prm, struct usb_ep *ep)
440{
441 struct snd_uac_chip *uac = prm->uac;
442 struct g_audio *audio_dev;
443 struct uac_params *params;
444 int i;
445
446 if (!prm->ep_enabled)
447 return;
448
Ruslan Bilovoleb9fecb2017-06-18 16:23:52 +0300449 audio_dev = uac->audio_dev;
450 params = &audio_dev->params;
451
452 for (i = 0; i < params->req_number; i++) {
Jerome Brunet29865112021-01-18 09:46:41 +0100453 if (prm->reqs[i]) {
454 if (usb_ep_dequeue(ep, prm->reqs[i]))
455 usb_ep_free_request(ep, prm->reqs[i]);
Jack Pham7de86812021-01-18 09:46:39 +0100456 /*
457 * If usb_ep_dequeue() cannot successfully dequeue the
458 * request, the request will be freed by the completion
459 * callback.
460 */
461
Jerome Brunet29865112021-01-18 09:46:41 +0100462 prm->reqs[i] = NULL;
Ruslan Bilovoleb9fecb2017-06-18 16:23:52 +0300463 }
464 }
465
Jerome Brunet068fdad2021-08-27 11:29:27 +0200466 prm->ep_enabled = false;
467
Ruslan Bilovoleb9fecb2017-06-18 16:23:52 +0300468 if (usb_ep_disable(ep))
469 dev_err(uac->card->dev, "%s:%d Error!\n", __func__, __LINE__);
470}
471
Ruslan Bilovol24f779d2021-06-04 00:01:02 +0200472static inline void free_ep_fback(struct uac_rtd_params *prm, struct usb_ep *ep)
473{
474 struct snd_uac_chip *uac = prm->uac;
475
476 if (!prm->fb_ep_enabled)
477 return;
478
Ruslan Bilovol24f779d2021-06-04 00:01:02 +0200479 if (prm->req_fback) {
Jerome Brunet75432ba2021-08-27 09:58:53 +0200480 if (usb_ep_dequeue(ep, prm->req_fback)) {
481 kfree(prm->req_fback->buf);
482 usb_ep_free_request(ep, prm->req_fback);
483 }
Ruslan Bilovol24f779d2021-06-04 00:01:02 +0200484 prm->req_fback = NULL;
485 }
486
Jerome Brunet068fdad2021-08-27 11:29:27 +0200487 prm->fb_ep_enabled = false;
488
Ruslan Bilovol24f779d2021-06-04 00:01:02 +0200489 if (usb_ep_disable(ep))
490 dev_err(uac->card->dev, "%s:%d Error!\n", __func__, __LINE__);
491}
Ruslan Bilovoleb9fecb2017-06-18 16:23:52 +0300492
493int u_audio_start_capture(struct g_audio *audio_dev)
494{
495 struct snd_uac_chip *uac = audio_dev->uac;
496 struct usb_gadget *gadget = audio_dev->gadget;
497 struct device *dev = &gadget->dev;
Ruslan Bilovol24f779d2021-06-04 00:01:02 +0200498 struct usb_request *req, *req_fback;
499 struct usb_ep *ep, *ep_fback;
Ruslan Bilovoleb9fecb2017-06-18 16:23:52 +0300500 struct uac_rtd_params *prm;
501 struct uac_params *params = &audio_dev->params;
502 int req_len, i;
503
504 ep = audio_dev->out_ep;
505 prm = &uac->c_prm;
506 config_ep_by_speed(gadget, &audio_dev->func, ep);
John Keeping904967c2020-01-17 10:40:22 +0000507 req_len = ep->maxpacket;
Ruslan Bilovoleb9fecb2017-06-18 16:23:52 +0300508
509 prm->ep_enabled = true;
510 usb_ep_enable(ep);
511
512 for (i = 0; i < params->req_number; i++) {
Jerome Brunet29865112021-01-18 09:46:41 +0100513 if (!prm->reqs[i]) {
Ruslan Bilovoleb9fecb2017-06-18 16:23:52 +0300514 req = usb_ep_alloc_request(ep, GFP_ATOMIC);
515 if (req == NULL)
516 return -ENOMEM;
517
Jerome Brunet29865112021-01-18 09:46:41 +0100518 prm->reqs[i] = req;
Ruslan Bilovoleb9fecb2017-06-18 16:23:52 +0300519
520 req->zero = 0;
Jerome Brunet29865112021-01-18 09:46:41 +0100521 req->context = prm;
Ruslan Bilovoleb9fecb2017-06-18 16:23:52 +0300522 req->length = req_len;
523 req->complete = u_audio_iso_complete;
John Keeping904967c2020-01-17 10:40:22 +0000524 req->buf = prm->rbuf + i * ep->maxpacket;
Ruslan Bilovoleb9fecb2017-06-18 16:23:52 +0300525 }
526
Jerome Brunet29865112021-01-18 09:46:41 +0100527 if (usb_ep_queue(ep, prm->reqs[i], GFP_ATOMIC))
Ruslan Bilovoleb9fecb2017-06-18 16:23:52 +0300528 dev_err(dev, "%s:%d Error!\n", __func__, __LINE__);
529 }
530
Ruslan Bilovol24f779d2021-06-04 00:01:02 +0200531 ep_fback = audio_dev->in_ep_fback;
532 if (!ep_fback)
533 return 0;
534
535 /* Setup feedback endpoint */
536 config_ep_by_speed(gadget, &audio_dev->func, ep_fback);
537 prm->fb_ep_enabled = true;
538 usb_ep_enable(ep_fback);
539 req_len = ep_fback->maxpacket;
540
541 req_fback = usb_ep_alloc_request(ep_fback, GFP_ATOMIC);
542 if (req_fback == NULL)
543 return -ENOMEM;
544
545 prm->req_fback = req_fback;
546 req_fback->zero = 0;
547 req_fback->context = prm;
548 req_fback->length = req_len;
549 req_fback->complete = u_audio_iso_fback_complete;
550
551 req_fback->buf = kzalloc(req_len, GFP_ATOMIC);
552 if (!req_fback->buf)
553 return -ENOMEM;
554
555 /*
556 * Configure the feedback endpoint's reported frequency.
557 * Always start with original frequency since its deviation can't
558 * be meauserd at start of playback
559 */
Ruslan Bilovole89bb422021-06-04 00:01:04 +0200560 prm->pitch = 1000000;
Pavel Hofmanf5dfd982021-09-06 15:08:22 +0200561 u_audio_set_fback_frequency(audio_dev->gadget->speed, ep,
Ruslan Bilovole89bb422021-06-04 00:01:04 +0200562 params->c_srate, prm->pitch,
563 req_fback->buf);
Ruslan Bilovol24f779d2021-06-04 00:01:02 +0200564
565 if (usb_ep_queue(ep_fback, req_fback, GFP_ATOMIC))
566 dev_err(dev, "%s:%d Error!\n", __func__, __LINE__);
567
Ruslan Bilovoleb9fecb2017-06-18 16:23:52 +0300568 return 0;
569}
570EXPORT_SYMBOL_GPL(u_audio_start_capture);
571
572void u_audio_stop_capture(struct g_audio *audio_dev)
573{
574 struct snd_uac_chip *uac = audio_dev->uac;
575
Ruslan Bilovol24f779d2021-06-04 00:01:02 +0200576 if (audio_dev->in_ep_fback)
577 free_ep_fback(&uac->c_prm, audio_dev->in_ep_fback);
Ruslan Bilovoleb9fecb2017-06-18 16:23:52 +0300578 free_ep(&uac->c_prm, audio_dev->out_ep);
579}
580EXPORT_SYMBOL_GPL(u_audio_stop_capture);
581
582int u_audio_start_playback(struct g_audio *audio_dev)
583{
584 struct snd_uac_chip *uac = audio_dev->uac;
585 struct usb_gadget *gadget = audio_dev->gadget;
586 struct device *dev = &gadget->dev;
587 struct usb_request *req;
588 struct usb_ep *ep;
589 struct uac_rtd_params *prm;
590 struct uac_params *params = &audio_dev->params;
John Keeping6b02af32020-01-10 11:28:14 +0000591 unsigned int factor;
Ruslan Bilovoleb9fecb2017-06-18 16:23:52 +0300592 const struct usb_endpoint_descriptor *ep_desc;
593 int req_len, i;
Pavel Hofman6fec0182021-10-13 09:39:34 +0200594 unsigned int p_interval, p_pktsize;
Ruslan Bilovoleb9fecb2017-06-18 16:23:52 +0300595
596 ep = audio_dev->in_ep;
597 prm = &uac->p_prm;
598 config_ep_by_speed(gadget, &audio_dev->func, ep);
599
600 ep_desc = ep->desc;
Pavel Hofman6fec0182021-10-13 09:39:34 +0200601 /*
602 * Always start with original frequency
603 */
604 prm->pitch = 1000000;
Ruslan Bilovoleb9fecb2017-06-18 16:23:52 +0300605
606 /* pre-calculate the playback endpoint's interval */
607 if (gadget->speed == USB_SPEED_FULL)
608 factor = 1000;
609 else
610 factor = 8000;
611
612 /* pre-compute some values for iso_complete() */
613 uac->p_framesize = params->p_ssize *
614 num_channels(params->p_chmask);
Pavel Hofman6fec0182021-10-13 09:39:34 +0200615 p_interval = factor / (1 << (ep_desc->bInterval - 1));
616 uac->p_interval_mil = (unsigned long long) p_interval * 1000000;
617 p_pktsize = min_t(unsigned int,
John Keeping6b02af32020-01-10 11:28:14 +0000618 uac->p_framesize *
Pavel Hofman6fec0182021-10-13 09:39:34 +0200619 (params->p_srate / p_interval),
John Keeping904967c2020-01-17 10:40:22 +0000620 ep->maxpacket);
Ruslan Bilovoleb9fecb2017-06-18 16:23:52 +0300621
Pavel Hofman6fec0182021-10-13 09:39:34 +0200622 req_len = p_pktsize;
623 uac->p_residue_mil = 0;
Ruslan Bilovoleb9fecb2017-06-18 16:23:52 +0300624
625 prm->ep_enabled = true;
626 usb_ep_enable(ep);
627
628 for (i = 0; i < params->req_number; i++) {
Jerome Brunet29865112021-01-18 09:46:41 +0100629 if (!prm->reqs[i]) {
Ruslan Bilovoleb9fecb2017-06-18 16:23:52 +0300630 req = usb_ep_alloc_request(ep, GFP_ATOMIC);
631 if (req == NULL)
632 return -ENOMEM;
633
Jerome Brunet29865112021-01-18 09:46:41 +0100634 prm->reqs[i] = req;
Ruslan Bilovoleb9fecb2017-06-18 16:23:52 +0300635
636 req->zero = 0;
Jerome Brunet29865112021-01-18 09:46:41 +0100637 req->context = prm;
Ruslan Bilovoleb9fecb2017-06-18 16:23:52 +0300638 req->length = req_len;
639 req->complete = u_audio_iso_complete;
John Keeping904967c2020-01-17 10:40:22 +0000640 req->buf = prm->rbuf + i * ep->maxpacket;
Ruslan Bilovoleb9fecb2017-06-18 16:23:52 +0300641 }
642
Jerome Brunet29865112021-01-18 09:46:41 +0100643 if (usb_ep_queue(ep, prm->reqs[i], GFP_ATOMIC))
Ruslan Bilovoleb9fecb2017-06-18 16:23:52 +0300644 dev_err(dev, "%s:%d Error!\n", __func__, __LINE__);
645 }
646
647 return 0;
648}
649EXPORT_SYMBOL_GPL(u_audio_start_playback);
650
651void u_audio_stop_playback(struct g_audio *audio_dev)
652{
653 struct snd_uac_chip *uac = audio_dev->uac;
654
655 free_ep(&uac->p_prm, audio_dev->in_ep);
656}
657EXPORT_SYMBOL_GPL(u_audio_stop_playback);
658
Ruslan Bilovol02de6982021-07-12 14:55:27 +0200659int u_audio_get_volume(struct g_audio *audio_dev, int playback, s16 *val)
660{
661 struct snd_uac_chip *uac = audio_dev->uac;
662 struct uac_rtd_params *prm;
663 unsigned long flags;
664
665 if (playback)
666 prm = &uac->p_prm;
667 else
668 prm = &uac->c_prm;
669
670 spin_lock_irqsave(&prm->lock, flags);
671 *val = prm->volume;
672 spin_unlock_irqrestore(&prm->lock, flags);
673
674 return 0;
675}
676EXPORT_SYMBOL_GPL(u_audio_get_volume);
677
678int u_audio_set_volume(struct g_audio *audio_dev, int playback, s16 val)
679{
680 struct snd_uac_chip *uac = audio_dev->uac;
681 struct uac_rtd_params *prm;
682 unsigned long flags;
683 int change = 0;
684
685 if (playback)
686 prm = &uac->p_prm;
687 else
688 prm = &uac->c_prm;
689
690 spin_lock_irqsave(&prm->lock, flags);
691 val = clamp(val, prm->volume_min, prm->volume_max);
692 if (prm->volume != val) {
693 prm->volume = val;
694 change = 1;
695 }
696 spin_unlock_irqrestore(&prm->lock, flags);
697
698 if (change)
699 snd_ctl_notify(uac->card, SNDRV_CTL_EVENT_MASK_VALUE,
700 &prm->snd_kctl_volume->id);
701
702 return 0;
703}
704EXPORT_SYMBOL_GPL(u_audio_set_volume);
705
706int u_audio_get_mute(struct g_audio *audio_dev, int playback, int *val)
707{
708 struct snd_uac_chip *uac = audio_dev->uac;
709 struct uac_rtd_params *prm;
710 unsigned long flags;
711
712 if (playback)
713 prm = &uac->p_prm;
714 else
715 prm = &uac->c_prm;
716
717 spin_lock_irqsave(&prm->lock, flags);
718 *val = prm->mute;
719 spin_unlock_irqrestore(&prm->lock, flags);
720
721 return 0;
722}
723EXPORT_SYMBOL_GPL(u_audio_get_mute);
724
725int u_audio_set_mute(struct g_audio *audio_dev, int playback, int val)
726{
727 struct snd_uac_chip *uac = audio_dev->uac;
728 struct uac_rtd_params *prm;
729 unsigned long flags;
730 int change = 0;
731 int mute;
732
733 if (playback)
734 prm = &uac->p_prm;
735 else
736 prm = &uac->c_prm;
737
738 mute = val ? 1 : 0;
739
740 spin_lock_irqsave(&prm->lock, flags);
741 if (prm->mute != mute) {
742 prm->mute = mute;
743 change = 1;
744 }
745 spin_unlock_irqrestore(&prm->lock, flags);
746
747 if (change)
748 snd_ctl_notify(uac->card, SNDRV_CTL_EVENT_MASK_VALUE,
749 &prm->snd_kctl_mute->id);
750
751 return 0;
752}
753EXPORT_SYMBOL_GPL(u_audio_set_mute);
754
755
Ruslan Bilovole89bb422021-06-04 00:01:04 +0200756static int u_audio_pitch_info(struct snd_kcontrol *kcontrol,
757 struct snd_ctl_elem_info *uinfo)
758{
759 struct uac_rtd_params *prm = snd_kcontrol_chip(kcontrol);
760 struct snd_uac_chip *uac = prm->uac;
761 struct g_audio *audio_dev = uac->audio_dev;
762 struct uac_params *params = &audio_dev->params;
763 unsigned int pitch_min, pitch_max;
764
765 pitch_min = (1000 - FBACK_SLOW_MAX) * 1000;
766 pitch_max = (1000 + params->fb_max) * 1000;
767
768 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
769 uinfo->count = 1;
770 uinfo->value.integer.min = pitch_min;
771 uinfo->value.integer.max = pitch_max;
772 uinfo->value.integer.step = 1;
773 return 0;
774}
775
776static int u_audio_pitch_get(struct snd_kcontrol *kcontrol,
777 struct snd_ctl_elem_value *ucontrol)
778{
779 struct uac_rtd_params *prm = snd_kcontrol_chip(kcontrol);
780
781 ucontrol->value.integer.value[0] = prm->pitch;
782
783 return 0;
784}
785
786static int u_audio_pitch_put(struct snd_kcontrol *kcontrol,
787 struct snd_ctl_elem_value *ucontrol)
788{
789 struct uac_rtd_params *prm = snd_kcontrol_chip(kcontrol);
790 struct snd_uac_chip *uac = prm->uac;
791 struct g_audio *audio_dev = uac->audio_dev;
792 struct uac_params *params = &audio_dev->params;
793 unsigned int val;
794 unsigned int pitch_min, pitch_max;
795 int change = 0;
796
797 pitch_min = (1000 - FBACK_SLOW_MAX) * 1000;
798 pitch_max = (1000 + params->fb_max) * 1000;
799
800 val = ucontrol->value.integer.value[0];
801
802 if (val < pitch_min)
803 val = pitch_min;
804 if (val > pitch_max)
805 val = pitch_max;
806
807 if (prm->pitch != val) {
808 prm->pitch = val;
809 change = 1;
810 }
811
812 return change;
813}
814
Ruslan Bilovol02de6982021-07-12 14:55:27 +0200815static int u_audio_mute_info(struct snd_kcontrol *kcontrol,
816 struct snd_ctl_elem_info *uinfo)
Ruslan Bilovole89bb422021-06-04 00:01:04 +0200817{
Ruslan Bilovol02de6982021-07-12 14:55:27 +0200818 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
819 uinfo->count = 1;
820 uinfo->value.integer.min = 0;
821 uinfo->value.integer.max = 1;
822 uinfo->value.integer.step = 1;
823
824 return 0;
825}
826
827static int u_audio_mute_get(struct snd_kcontrol *kcontrol,
828 struct snd_ctl_elem_value *ucontrol)
829{
830 struct uac_rtd_params *prm = snd_kcontrol_chip(kcontrol);
831 unsigned long flags;
832
833 spin_lock_irqsave(&prm->lock, flags);
834 ucontrol->value.integer.value[0] = !prm->mute;
835 spin_unlock_irqrestore(&prm->lock, flags);
836
837 return 0;
838}
839
840static int u_audio_mute_put(struct snd_kcontrol *kcontrol,
841 struct snd_ctl_elem_value *ucontrol)
842{
843 struct uac_rtd_params *prm = snd_kcontrol_chip(kcontrol);
844 struct snd_uac_chip *uac = prm->uac;
845 struct g_audio *audio_dev = uac->audio_dev;
846 unsigned int val;
847 unsigned long flags;
848 int change = 0;
849
850 val = !ucontrol->value.integer.value[0];
851
852 spin_lock_irqsave(&prm->lock, flags);
853 if (val != prm->mute) {
854 prm->mute = val;
855 change = 1;
856 }
857 spin_unlock_irqrestore(&prm->lock, flags);
858
859 if (change && audio_dev->notify)
860 audio_dev->notify(audio_dev, prm->fu_id, UAC_FU_MUTE);
861
862 return change;
863}
864
865/*
866 * TLV callback for mixer volume controls
867 */
868static int u_audio_volume_tlv(struct snd_kcontrol *kcontrol, int op_flag,
869 unsigned int size, unsigned int __user *_tlv)
870{
871 struct uac_rtd_params *prm = snd_kcontrol_chip(kcontrol);
872 DECLARE_TLV_DB_MINMAX(scale, 0, 0);
873
874 if (size < sizeof(scale))
875 return -ENOMEM;
876
877 /* UAC volume resolution is 1/256 dB, TLV is 1/100 dB */
878 scale[2] = (prm->volume_min * 100) / 256;
879 scale[3] = (prm->volume_max * 100) / 256;
880 if (copy_to_user(_tlv, scale, sizeof(scale)))
881 return -EFAULT;
882
883 return 0;
884}
885
886static int u_audio_volume_info(struct snd_kcontrol *kcontrol,
887 struct snd_ctl_elem_info *uinfo)
888{
889 struct uac_rtd_params *prm = snd_kcontrol_chip(kcontrol);
890
891 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
892 uinfo->count = 1;
893 uinfo->value.integer.min = 0;
894 uinfo->value.integer.max =
895 (prm->volume_max - prm->volume_min + prm->volume_res - 1)
896 / prm->volume_res;
897 uinfo->value.integer.step = 1;
898
899 return 0;
900}
901
902static int u_audio_volume_get(struct snd_kcontrol *kcontrol,
903 struct snd_ctl_elem_value *ucontrol)
904{
905 struct uac_rtd_params *prm = snd_kcontrol_chip(kcontrol);
906 unsigned long flags;
907
908 spin_lock_irqsave(&prm->lock, flags);
909 ucontrol->value.integer.value[0] =
910 (prm->volume - prm->volume_min) / prm->volume_res;
911 spin_unlock_irqrestore(&prm->lock, flags);
912
913 return 0;
914}
915
916static int u_audio_volume_put(struct snd_kcontrol *kcontrol,
917 struct snd_ctl_elem_value *ucontrol)
918{
919 struct uac_rtd_params *prm = snd_kcontrol_chip(kcontrol);
920 struct snd_uac_chip *uac = prm->uac;
921 struct g_audio *audio_dev = uac->audio_dev;
922 unsigned int val;
923 s16 volume;
924 unsigned long flags;
925 int change = 0;
926
927 val = ucontrol->value.integer.value[0];
928
929 spin_lock_irqsave(&prm->lock, flags);
930 volume = (val * prm->volume_res) + prm->volume_min;
931 volume = clamp(volume, prm->volume_min, prm->volume_max);
932 if (volume != prm->volume) {
933 prm->volume = volume;
934 change = 1;
935 }
936 spin_unlock_irqrestore(&prm->lock, flags);
937
938 if (change && audio_dev->notify)
939 audio_dev->notify(audio_dev, prm->fu_id, UAC_FU_VOLUME);
940
941 return change;
942}
943
944
945static struct snd_kcontrol_new u_audio_controls[] = {
946 [UAC_FBACK_CTRL] {
947 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
948 .name = "Capture Pitch 1000000",
949 .info = u_audio_pitch_info,
950 .get = u_audio_pitch_get,
951 .put = u_audio_pitch_put,
952 },
Pavel Hofman6fec0182021-10-13 09:39:34 +0200953 [UAC_P_PITCH_CTRL] {
954 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
955 .name = "Playback Pitch 1000000",
956 .info = u_audio_pitch_info,
957 .get = u_audio_pitch_get,
958 .put = u_audio_pitch_put,
959 },
Ruslan Bilovol02de6982021-07-12 14:55:27 +0200960 [UAC_MUTE_CTRL] {
961 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
962 .name = "", /* will be filled later */
963 .info = u_audio_mute_info,
964 .get = u_audio_mute_get,
965 .put = u_audio_mute_put,
966 },
967 [UAC_VOLUME_CTRL] {
968 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
969 .name = "", /* will be filled later */
970 .info = u_audio_volume_info,
971 .get = u_audio_volume_get,
972 .put = u_audio_volume_put,
973 },
Ruslan Bilovole89bb422021-06-04 00:01:04 +0200974};
975
Ruslan Bilovoleb9fecb2017-06-18 16:23:52 +0300976int g_audio_setup(struct g_audio *g_audio, const char *pcm_name,
977 const char *card_name)
978{
979 struct snd_uac_chip *uac;
980 struct snd_card *card;
981 struct snd_pcm *pcm;
Ruslan Bilovole89bb422021-06-04 00:01:04 +0200982 struct snd_kcontrol *kctl;
Ruslan Bilovoleb9fecb2017-06-18 16:23:52 +0300983 struct uac_params *params;
984 int p_chmask, c_chmask;
Ruslan Bilovol02de6982021-07-12 14:55:27 +0200985 int i, err;
Ruslan Bilovoleb9fecb2017-06-18 16:23:52 +0300986
987 if (!g_audio)
988 return -EINVAL;
989
990 uac = kzalloc(sizeof(*uac), GFP_KERNEL);
991 if (!uac)
992 return -ENOMEM;
993 g_audio->uac = uac;
994 uac->audio_dev = g_audio;
995
996 params = &g_audio->params;
997 p_chmask = params->p_chmask;
998 c_chmask = params->c_chmask;
999
1000 if (c_chmask) {
1001 struct uac_rtd_params *prm = &uac->c_prm;
1002
Ruslan Bilovol02de6982021-07-12 14:55:27 +02001003 spin_lock_init(&prm->lock);
1004 uac->c_prm.uac = uac;
Ruslan Bilovoleb9fecb2017-06-18 16:23:52 +03001005 prm->max_psize = g_audio->out_ep_maxpsize;
1006
Jerome Brunet29865112021-01-18 09:46:41 +01001007 prm->reqs = kcalloc(params->req_number,
1008 sizeof(struct usb_request *),
1009 GFP_KERNEL);
1010 if (!prm->reqs) {
Ruslan Bilovoleb9fecb2017-06-18 16:23:52 +03001011 err = -ENOMEM;
1012 goto fail;
1013 }
1014
1015 prm->rbuf = kcalloc(params->req_number, prm->max_psize,
1016 GFP_KERNEL);
1017 if (!prm->rbuf) {
1018 prm->max_psize = 0;
1019 err = -ENOMEM;
1020 goto fail;
1021 }
1022 }
1023
1024 if (p_chmask) {
1025 struct uac_rtd_params *prm = &uac->p_prm;
1026
Ruslan Bilovol02de6982021-07-12 14:55:27 +02001027 spin_lock_init(&prm->lock);
Ruslan Bilovoleb9fecb2017-06-18 16:23:52 +03001028 uac->p_prm.uac = uac;
1029 prm->max_psize = g_audio->in_ep_maxpsize;
1030
Jerome Brunet29865112021-01-18 09:46:41 +01001031 prm->reqs = kcalloc(params->req_number,
1032 sizeof(struct usb_request *),
1033 GFP_KERNEL);
1034 if (!prm->reqs) {
Ruslan Bilovoleb9fecb2017-06-18 16:23:52 +03001035 err = -ENOMEM;
1036 goto fail;
1037 }
1038
1039 prm->rbuf = kcalloc(params->req_number, prm->max_psize,
1040 GFP_KERNEL);
1041 if (!prm->rbuf) {
1042 prm->max_psize = 0;
1043 err = -ENOMEM;
1044 goto fail;
1045 }
1046 }
1047
1048 /* Choose any slot, with no id */
1049 err = snd_card_new(&g_audio->gadget->dev,
1050 -1, NULL, THIS_MODULE, 0, &card);
1051 if (err < 0)
1052 goto fail;
1053
1054 uac->card = card;
1055
1056 /*
1057 * Create first PCM device
1058 * Create a substream only for non-zero channel streams
1059 */
1060 err = snd_pcm_new(uac->card, pcm_name, 0,
1061 p_chmask ? 1 : 0, c_chmask ? 1 : 0, &pcm);
1062 if (err < 0)
1063 goto snd_fail;
1064
Ruslan Bilovold23922fc2021-03-01 15:05:36 +02001065 strscpy(pcm->name, pcm_name, sizeof(pcm->name));
Ruslan Bilovoleb9fecb2017-06-18 16:23:52 +03001066 pcm->private_data = uac;
1067 uac->pcm = pcm;
1068
1069 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &uac_pcm_ops);
1070 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &uac_pcm_ops);
1071
Ruslan Bilovol02de6982021-07-12 14:55:27 +02001072 /*
1073 * Create mixer and controls
1074 * Create only if it's required on USB side
1075 */
1076 if ((c_chmask && g_audio->in_ep_fback)
1077 || (p_chmask && params->p_fu.id)
1078 || (c_chmask && params->c_fu.id))
Ruslan Bilovole89bb422021-06-04 00:01:04 +02001079 strscpy(card->mixername, card_name, sizeof(card->driver));
1080
Ruslan Bilovol02de6982021-07-12 14:55:27 +02001081 if (c_chmask && g_audio->in_ep_fback) {
1082 kctl = snd_ctl_new1(&u_audio_controls[UAC_FBACK_CTRL],
1083 &uac->c_prm);
Ruslan Bilovole89bb422021-06-04 00:01:04 +02001084 if (!kctl) {
1085 err = -ENOMEM;
1086 goto snd_fail;
1087 }
1088
1089 kctl->id.device = pcm->device;
1090 kctl->id.subdevice = 0;
1091
1092 err = snd_ctl_add(card, kctl);
1093 if (err < 0)
1094 goto snd_fail;
1095 }
1096
Pavel Hofman6fec0182021-10-13 09:39:34 +02001097 if (p_chmask) {
1098 kctl = snd_ctl_new1(&u_audio_controls[UAC_P_PITCH_CTRL],
1099 &uac->p_prm);
1100 if (!kctl) {
1101 err = -ENOMEM;
1102 goto snd_fail;
1103 }
1104
1105 kctl->id.device = pcm->device;
1106 kctl->id.subdevice = 0;
1107
1108 err = snd_ctl_add(card, kctl);
1109 if (err < 0)
1110 goto snd_fail;
1111 }
1112
Ruslan Bilovol02de6982021-07-12 14:55:27 +02001113 for (i = 0; i <= SNDRV_PCM_STREAM_LAST; i++) {
1114 struct uac_rtd_params *prm;
1115 struct uac_fu_params *fu;
1116 char ctrl_name[24];
1117 char *direction;
1118
1119 if (!pcm->streams[i].substream_count)
1120 continue;
1121
1122 if (i == SNDRV_PCM_STREAM_PLAYBACK) {
1123 prm = &uac->p_prm;
1124 fu = &params->p_fu;
1125 direction = "Playback";
1126 } else {
1127 prm = &uac->c_prm;
1128 fu = &params->c_fu;
1129 direction = "Capture";
1130 }
1131
1132 prm->fu_id = fu->id;
1133
1134 if (fu->mute_present) {
1135 snprintf(ctrl_name, sizeof(ctrl_name),
1136 "PCM %s Switch", direction);
1137
1138 u_audio_controls[UAC_MUTE_CTRL].name = ctrl_name;
1139
1140 kctl = snd_ctl_new1(&u_audio_controls[UAC_MUTE_CTRL],
1141 prm);
1142 if (!kctl) {
1143 err = -ENOMEM;
1144 goto snd_fail;
1145 }
1146
1147 kctl->id.device = pcm->device;
1148 kctl->id.subdevice = i;
1149
1150 err = snd_ctl_add(card, kctl);
1151 if (err < 0)
1152 goto snd_fail;
1153 prm->snd_kctl_mute = kctl;
1154 prm->mute = 0;
1155 }
1156
1157 if (fu->volume_present) {
1158 snprintf(ctrl_name, sizeof(ctrl_name),
1159 "PCM %s Volume", direction);
1160
1161 u_audio_controls[UAC_VOLUME_CTRL].name = ctrl_name;
1162
1163 kctl = snd_ctl_new1(&u_audio_controls[UAC_VOLUME_CTRL],
1164 prm);
1165 if (!kctl) {
1166 err = -ENOMEM;
1167 goto snd_fail;
1168 }
1169
1170 kctl->id.device = pcm->device;
1171 kctl->id.subdevice = i;
1172
1173
1174 kctl->tlv.c = u_audio_volume_tlv;
1175 kctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ |
1176 SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK;
1177
1178 err = snd_ctl_add(card, kctl);
1179 if (err < 0)
1180 goto snd_fail;
1181 prm->snd_kctl_volume = kctl;
1182 prm->volume = fu->volume_max;
1183 prm->volume_max = fu->volume_max;
1184 prm->volume_min = fu->volume_min;
1185 prm->volume_res = fu->volume_res;
1186 }
1187 }
1188
Ruslan Bilovold23922fc2021-03-01 15:05:36 +02001189 strscpy(card->driver, card_name, sizeof(card->driver));
1190 strscpy(card->shortname, card_name, sizeof(card->shortname));
Ruslan Bilovoleb9fecb2017-06-18 16:23:52 +03001191 sprintf(card->longname, "%s %i", card_name, card->dev->id);
1192
Takashi Iwaid27ab1e2019-12-10 15:18:21 +01001193 snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS,
1194 NULL, 0, BUFF_SIZE_MAX);
Ruslan Bilovoleb9fecb2017-06-18 16:23:52 +03001195
1196 err = snd_card_register(card);
1197
1198 if (!err)
1199 return 0;
1200
1201snd_fail:
1202 snd_card_free(card);
1203fail:
Jerome Brunet29865112021-01-18 09:46:41 +01001204 kfree(uac->p_prm.reqs);
1205 kfree(uac->c_prm.reqs);
Ruslan Bilovoleb9fecb2017-06-18 16:23:52 +03001206 kfree(uac->p_prm.rbuf);
1207 kfree(uac->c_prm.rbuf);
1208 kfree(uac);
1209
1210 return err;
1211}
1212EXPORT_SYMBOL_GPL(g_audio_setup);
1213
1214void g_audio_cleanup(struct g_audio *g_audio)
1215{
1216 struct snd_uac_chip *uac;
1217 struct snd_card *card;
1218
1219 if (!g_audio || !g_audio->uac)
1220 return;
1221
1222 uac = g_audio->uac;
1223 card = uac->card;
1224 if (card)
1225 snd_card_free(card);
1226
Jerome Brunet29865112021-01-18 09:46:41 +01001227 kfree(uac->p_prm.reqs);
1228 kfree(uac->c_prm.reqs);
Ruslan Bilovoleb9fecb2017-06-18 16:23:52 +03001229 kfree(uac->p_prm.rbuf);
1230 kfree(uac->c_prm.rbuf);
1231 kfree(uac);
1232}
1233EXPORT_SYMBOL_GPL(g_audio_cleanup);
1234
1235MODULE_LICENSE("GPL");
1236MODULE_DESCRIPTION("USB gadget \"ALSA sound card\" utilities");
1237MODULE_AUTHOR("Ruslan Bilovol");