diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/usb/gadget/Kconfig | 25 | ||||
-rw-r--r-- | drivers/usb/gadget/audio.c | 20 | ||||
-rw-r--r-- | drivers/usb/gadget/f_uac2.c | 1449 |
3 files changed, 1485 insertions, 9 deletions
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig index 7ecb68a67411..1623b5204da4 100644 --- a/drivers/usb/gadget/Kconfig +++ b/drivers/usb/gadget/Kconfig | |||
@@ -599,16 +599,29 @@ config USB_AUDIO | |||
599 | depends on SND | 599 | depends on SND |
600 | select SND_PCM | 600 | select SND_PCM |
601 | help | 601 | help |
602 | Gadget Audio is compatible with USB Audio Class specification 1.0. | 602 | This Gadget Audio driver is compatible with USB Audio Class |
603 | It will include at least one AudioControl interface, zero or more | 603 | specification 2.0. It implements 1 AudioControl interface, |
604 | AudioStream interface and zero or more MIDIStream interface. | 604 | 1 AudioStreaming Interface each for USB-OUT and USB-IN. |
605 | 605 | Number of channels, sample rate and sample size can be | |
606 | Gadget Audio will use on-board ALSA (CONFIG_SND) audio card to | 606 | specified as module parameters. |
607 | playback or capture audio stream. | 607 | This driver doesn't expect any real Audio codec to be present |
608 | on the device - the audio streams are simply sinked to and | ||
609 | sourced from a virtual ALSA sound card created. The user-space | ||
610 | application may choose to do whatever it wants with the data | ||
611 | received from the USB Host and choose to provide whatever it | ||
612 | wants as audio data to the USB Host. | ||
608 | 613 | ||
609 | Say "y" to link the driver statically, or "m" to build a | 614 | Say "y" to link the driver statically, or "m" to build a |
610 | dynamically linked module called "g_audio". | 615 | dynamically linked module called "g_audio". |
611 | 616 | ||
617 | config GADGET_UAC1 | ||
618 | bool "UAC 1.0 (Legacy)" | ||
619 | depends on USB_AUDIO | ||
620 | help | ||
621 | If you instead want older UAC Spec-1.0 driver that also has audio | ||
622 | paths hardwired to the Audio codec chip on-board and doesn't work | ||
623 | without one. | ||
624 | |||
612 | config USB_ETH | 625 | config USB_ETH |
613 | tristate "Ethernet Gadget (with CDC Ethernet support)" | 626 | tristate "Ethernet Gadget (with CDC Ethernet support)" |
614 | depends on NET | 627 | depends on NET |
diff --git a/drivers/usb/gadget/audio.c b/drivers/usb/gadget/audio.c index 33e9327d6639..98899244860e 100644 --- a/drivers/usb/gadget/audio.c +++ b/drivers/usb/gadget/audio.c | |||
@@ -14,10 +14,8 @@ | |||
14 | #include <linux/kernel.h> | 14 | #include <linux/kernel.h> |
15 | #include <linux/utsname.h> | 15 | #include <linux/utsname.h> |
16 | 16 | ||
17 | #include "u_uac1.h" | ||
18 | |||
19 | #define DRIVER_DESC "Linux USB Audio Gadget" | 17 | #define DRIVER_DESC "Linux USB Audio Gadget" |
20 | #define DRIVER_VERSION "Dec 18, 2008" | 18 | #define DRIVER_VERSION "Feb 2, 2012" |
21 | 19 | ||
22 | /*-------------------------------------------------------------------------*/ | 20 | /*-------------------------------------------------------------------------*/ |
23 | 21 | ||
@@ -56,8 +54,13 @@ static struct usb_gadget_strings *audio_strings[] = { | |||
56 | NULL, | 54 | NULL, |
57 | }; | 55 | }; |
58 | 56 | ||
57 | #ifdef CONFIG_GADGET_UAC1 | ||
58 | #include "u_uac1.h" | ||
59 | #include "u_uac1.c" | 59 | #include "u_uac1.c" |
60 | #include "f_uac1.c" | 60 | #include "f_uac1.c" |
61 | #else | ||
62 | #include "f_uac2.c" | ||
63 | #endif | ||
61 | 64 | ||
62 | /*-------------------------------------------------------------------------*/ | 65 | /*-------------------------------------------------------------------------*/ |
63 | 66 | ||
@@ -77,9 +80,15 @@ static struct usb_device_descriptor device_desc = { | |||
77 | 80 | ||
78 | .bcdUSB = __constant_cpu_to_le16(0x200), | 81 | .bcdUSB = __constant_cpu_to_le16(0x200), |
79 | 82 | ||
83 | #ifdef CONFIG_GADGET_UAC1 | ||
80 | .bDeviceClass = USB_CLASS_PER_INTERFACE, | 84 | .bDeviceClass = USB_CLASS_PER_INTERFACE, |
81 | .bDeviceSubClass = 0, | 85 | .bDeviceSubClass = 0, |
82 | .bDeviceProtocol = 0, | 86 | .bDeviceProtocol = 0, |
87 | #else | ||
88 | .bDeviceClass = USB_CLASS_MISC, | ||
89 | .bDeviceSubClass = 0x02, | ||
90 | .bDeviceProtocol = 0x01, | ||
91 | #endif | ||
83 | /* .bMaxPacketSize0 = f(hardware) */ | 92 | /* .bMaxPacketSize0 = f(hardware) */ |
84 | 93 | ||
85 | /* Vendor and product id defaults change according to what configs | 94 | /* Vendor and product id defaults change according to what configs |
@@ -131,6 +140,9 @@ static struct usb_configuration audio_config_driver = { | |||
131 | .bConfigurationValue = 1, | 140 | .bConfigurationValue = 1, |
132 | /* .iConfiguration = DYNAMIC */ | 141 | /* .iConfiguration = DYNAMIC */ |
133 | .bmAttributes = USB_CONFIG_ATT_SELFPOWER, | 142 | .bmAttributes = USB_CONFIG_ATT_SELFPOWER, |
143 | #ifndef CONFIG_GADGET_UAC1 | ||
144 | .unbind = uac2_unbind_config, | ||
145 | #endif | ||
134 | }; | 146 | }; |
135 | 147 | ||
136 | /*-------------------------------------------------------------------------*/ | 148 | /*-------------------------------------------------------------------------*/ |
@@ -180,7 +192,9 @@ fail: | |||
180 | 192 | ||
181 | static int __exit audio_unbind(struct usb_composite_dev *cdev) | 193 | static int __exit audio_unbind(struct usb_composite_dev *cdev) |
182 | { | 194 | { |
195 | #ifdef CONFIG_GADGET_UAC1 | ||
183 | gaudio_cleanup(); | 196 | gaudio_cleanup(); |
197 | #endif | ||
184 | return 0; | 198 | return 0; |
185 | } | 199 | } |
186 | 200 | ||
diff --git a/drivers/usb/gadget/f_uac2.c b/drivers/usb/gadget/f_uac2.c new file mode 100644 index 000000000000..e7cc4de93e33 --- /dev/null +++ b/drivers/usb/gadget/f_uac2.c | |||
@@ -0,0 +1,1449 @@ | |||
1 | /* | ||
2 | * f_uac2.c -- USB Audio Class 2.0 Function | ||
3 | * | ||
4 | * Copyright (C) 2011 | ||
5 | * Yadwinder Singh (yadi.brar01@gmail.com) | ||
6 | * Jaswinder Singh (jaswinder.singh@linaro.org) | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | */ | ||
13 | |||
14 | #include <linux/usb/audio.h> | ||
15 | #include <linux/usb/audio-v2.h> | ||
16 | #include <linux/platform_device.h> | ||
17 | #include <linux/module.h> | ||
18 | |||
19 | #include <sound/core.h> | ||
20 | #include <sound/pcm.h> | ||
21 | #include <sound/pcm_params.h> | ||
22 | |||
23 | /* Playback(USB-IN) Default Stereo - Fl/Fr */ | ||
24 | static int p_chmask = 0x3; | ||
25 | module_param(p_chmask, uint, S_IRUGO); | ||
26 | MODULE_PARM_DESC(p_chmask, "Playback Channel Mask"); | ||
27 | |||
28 | /* Playback Default 48 KHz */ | ||
29 | static int p_srate = 48000; | ||
30 | module_param(p_srate, uint, S_IRUGO); | ||
31 | MODULE_PARM_DESC(p_srate, "Playback Sampling Rate"); | ||
32 | |||
33 | /* Playback Default 16bits/sample */ | ||
34 | static int p_ssize = 2; | ||
35 | module_param(p_ssize, uint, S_IRUGO); | ||
36 | MODULE_PARM_DESC(p_ssize, "Playback Sample Size(bytes)"); | ||
37 | |||
38 | /* Capture(USB-OUT) Default Stereo - Fl/Fr */ | ||
39 | static int c_chmask = 0x3; | ||
40 | module_param(c_chmask, uint, S_IRUGO); | ||
41 | MODULE_PARM_DESC(c_chmask, "Capture Channel Mask"); | ||
42 | |||
43 | /* Capture Default 64 KHz */ | ||
44 | static int c_srate = 64000; | ||
45 | module_param(c_srate, uint, S_IRUGO); | ||
46 | MODULE_PARM_DESC(c_srate, "Capture Sampling Rate"); | ||
47 | |||
48 | /* Capture Default 16bits/sample */ | ||
49 | static int c_ssize = 2; | ||
50 | module_param(c_ssize, uint, S_IRUGO); | ||
51 | MODULE_PARM_DESC(c_ssize, "Capture Sample Size(bytes)"); | ||
52 | |||
53 | #define DMA_ADDR_INVALID (~(dma_addr_t)0) | ||
54 | |||
55 | #define ALT_SET(x, a) do {(x) &= ~0xff; (x) |= (a); } while (0) | ||
56 | #define ALT_GET(x) ((x) & 0xff) | ||
57 | #define INTF_SET(x, i) do {(x) &= 0xff; (x) |= ((i) << 8); } while (0) | ||
58 | #define INTF_GET(x) ((x >> 8) & 0xff) | ||
59 | |||
60 | /* Keep everyone on toes */ | ||
61 | #define USB_XFERS 2 | ||
62 | |||
63 | /* | ||
64 | * The driver implements a simple UAC_2 topology. | ||
65 | * USB-OUT -> IT_1 -> OT_3 -> ALSA_Capture | ||
66 | * ALSA_Playback -> IT_2 -> OT_4 -> USB-IN | ||
67 | * Capture and Playback sampling rates are independently | ||
68 | * controlled by two clock sources : | ||
69 | * CLK_5 := c_srate, and CLK_6 := p_srate | ||
70 | */ | ||
71 | #define USB_OUT_IT_ID 1 | ||
72 | #define IO_IN_IT_ID 2 | ||
73 | #define IO_OUT_OT_ID 3 | ||
74 | #define USB_IN_OT_ID 4 | ||
75 | #define USB_OUT_CLK_ID 5 | ||
76 | #define USB_IN_CLK_ID 6 | ||
77 | |||
78 | #define CONTROL_ABSENT 0 | ||
79 | #define CONTROL_RDONLY 1 | ||
80 | #define CONTROL_RDWR 3 | ||
81 | |||
82 | #define CLK_FREQ_CTRL 0 | ||
83 | #define CLK_VLD_CTRL 2 | ||
84 | |||
85 | #define COPY_CTRL 0 | ||
86 | #define CONN_CTRL 2 | ||
87 | #define OVRLD_CTRL 4 | ||
88 | #define CLSTR_CTRL 6 | ||
89 | #define UNFLW_CTRL 8 | ||
90 | #define OVFLW_CTRL 10 | ||
91 | |||
92 | const char *uac2_name = "snd_uac2"; | ||
93 | |||
94 | struct uac2_req { | ||
95 | struct uac2_rtd_params *pp; /* parent param */ | ||
96 | struct usb_request *req; | ||
97 | }; | ||
98 | |||
99 | struct uac2_rtd_params { | ||
100 | bool ep_enabled; /* if the ep is enabled */ | ||
101 | /* Size of the ring buffer */ | ||
102 | size_t dma_bytes; | ||
103 | unsigned char *dma_area; | ||
104 | |||
105 | struct snd_pcm_substream *ss; | ||
106 | |||
107 | /* Ring buffer */ | ||
108 | ssize_t hw_ptr; | ||
109 | |||
110 | void *rbuf; | ||
111 | |||
112 | size_t period_size; | ||
113 | |||
114 | unsigned max_psize; | ||
115 | struct uac2_req ureq[USB_XFERS]; | ||
116 | |||
117 | spinlock_t lock; | ||
118 | }; | ||
119 | |||
120 | struct snd_uac2_chip { | ||
121 | struct platform_device pdev; | ||
122 | struct platform_driver pdrv; | ||
123 | |||
124 | struct uac2_rtd_params p_prm; | ||
125 | struct uac2_rtd_params c_prm; | ||
126 | |||
127 | struct snd_card *card; | ||
128 | struct snd_pcm *pcm; | ||
129 | }; | ||
130 | |||
131 | #define BUFF_SIZE_MAX (PAGE_SIZE * 16) | ||
132 | #define PRD_SIZE_MAX PAGE_SIZE | ||
133 | #define MIN_PERIODS 4 | ||
134 | |||
135 | static struct snd_pcm_hardware uac2_pcm_hardware = { | ||
136 | .info = SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | ||
137 | | SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID | ||
138 | | SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME, | ||
139 | .rates = SNDRV_PCM_RATE_CONTINUOUS, | ||
140 | .periods_max = BUFF_SIZE_MAX / PRD_SIZE_MAX, | ||
141 | .buffer_bytes_max = BUFF_SIZE_MAX, | ||
142 | .period_bytes_max = PRD_SIZE_MAX, | ||
143 | .periods_min = MIN_PERIODS, | ||
144 | }; | ||
145 | |||
146 | struct audio_dev { | ||
147 | /* Currently active {Interface[15:8] | AltSettings[7:0]} */ | ||
148 | __u16 ac_alt, as_out_alt, as_in_alt; | ||
149 | |||
150 | struct usb_ep *in_ep, *out_ep; | ||
151 | struct usb_function func; | ||
152 | |||
153 | /* The ALSA Sound Card it represents on the USB-Client side */ | ||
154 | struct snd_uac2_chip uac2; | ||
155 | }; | ||
156 | |||
157 | static struct audio_dev *agdev_g; | ||
158 | |||
159 | static inline | ||
160 | struct audio_dev *func_to_agdev(struct usb_function *f) | ||
161 | { | ||
162 | return container_of(f, struct audio_dev, func); | ||
163 | } | ||
164 | |||
165 | static inline | ||
166 | struct audio_dev *uac2_to_agdev(struct snd_uac2_chip *u) | ||
167 | { | ||
168 | return container_of(u, struct audio_dev, uac2); | ||
169 | } | ||
170 | |||
171 | static inline | ||
172 | struct snd_uac2_chip *pdev_to_uac2(struct platform_device *p) | ||
173 | { | ||
174 | return container_of(p, struct snd_uac2_chip, pdev); | ||
175 | } | ||
176 | |||
177 | static inline | ||
178 | struct snd_uac2_chip *prm_to_uac2(struct uac2_rtd_params *r) | ||
179 | { | ||
180 | struct snd_uac2_chip *uac2 = container_of(r, | ||
181 | struct snd_uac2_chip, c_prm); | ||
182 | |||
183 | if (&uac2->c_prm != r) | ||
184 | uac2 = container_of(r, struct snd_uac2_chip, p_prm); | ||
185 | |||
186 | return uac2; | ||
187 | } | ||
188 | |||
189 | static inline | ||
190 | uint num_channels(uint chanmask) | ||
191 | { | ||
192 | uint num = 0; | ||
193 | |||
194 | while (chanmask) { | ||
195 | num += (chanmask & 1); | ||
196 | chanmask >>= 1; | ||
197 | } | ||
198 | |||
199 | return num; | ||
200 | } | ||
201 | |||
202 | static void | ||
203 | agdev_iso_complete(struct usb_ep *ep, struct usb_request *req) | ||
204 | { | ||
205 | unsigned pending; | ||
206 | unsigned long flags; | ||
207 | bool update_alsa = false; | ||
208 | unsigned char *src, *dst; | ||
209 | int status = req->status; | ||
210 | struct uac2_req *ur = req->context; | ||
211 | struct snd_pcm_substream *substream; | ||
212 | struct uac2_rtd_params *prm = ur->pp; | ||
213 | struct snd_uac2_chip *uac2 = prm_to_uac2(prm); | ||
214 | |||
215 | /* i/f shutting down */ | ||
216 | if (!prm->ep_enabled) | ||
217 | return; | ||
218 | |||
219 | /* | ||
220 | * We can't really do much about bad xfers. | ||
221 | * Afterall, the ISOCH xfers could fail legitimately. | ||
222 | */ | ||
223 | if (status) | ||
224 | pr_debug("%s: iso_complete status(%d) %d/%d\n", | ||
225 | __func__, status, req->actual, req->length); | ||
226 | |||
227 | substream = prm->ss; | ||
228 | |||
229 | /* Do nothing if ALSA isn't active */ | ||
230 | if (!substream) | ||
231 | goto exit; | ||
232 | |||
233 | spin_lock_irqsave(&prm->lock, flags); | ||
234 | |||
235 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | ||
236 | src = prm->dma_area + prm->hw_ptr; | ||
237 | req->actual = req->length; | ||
238 | dst = req->buf; | ||
239 | } else { | ||
240 | dst = prm->dma_area + prm->hw_ptr; | ||
241 | src = req->buf; | ||
242 | } | ||
243 | |||
244 | pending = prm->hw_ptr % prm->period_size; | ||
245 | pending += req->actual; | ||
246 | if (pending >= prm->period_size) | ||
247 | update_alsa = true; | ||
248 | |||
249 | prm->hw_ptr = (prm->hw_ptr + req->actual) % prm->dma_bytes; | ||
250 | |||
251 | spin_unlock_irqrestore(&prm->lock, flags); | ||
252 | |||
253 | /* Pack USB load in ALSA ring buffer */ | ||
254 | memcpy(dst, src, req->actual); | ||
255 | exit: | ||
256 | if (usb_ep_queue(ep, req, GFP_ATOMIC)) | ||
257 | dev_err(&uac2->pdev.dev, "%d Error!\n", __LINE__); | ||
258 | |||
259 | if (update_alsa) | ||
260 | snd_pcm_period_elapsed(substream); | ||
261 | |||
262 | return; | ||
263 | } | ||
264 | |||
265 | static int | ||
266 | uac2_pcm_trigger(struct snd_pcm_substream *substream, int cmd) | ||
267 | { | ||
268 | struct snd_uac2_chip *uac2 = snd_pcm_substream_chip(substream); | ||
269 | struct audio_dev *agdev = uac2_to_agdev(uac2); | ||
270 | struct uac2_rtd_params *prm; | ||
271 | unsigned long flags; | ||
272 | struct usb_ep *ep; | ||
273 | int err = 0; | ||
274 | |||
275 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | ||
276 | ep = agdev->in_ep; | ||
277 | prm = &uac2->p_prm; | ||
278 | } else { | ||
279 | ep = agdev->out_ep; | ||
280 | prm = &uac2->c_prm; | ||
281 | } | ||
282 | |||
283 | spin_lock_irqsave(&prm->lock, flags); | ||
284 | |||
285 | /* Reset */ | ||
286 | prm->hw_ptr = 0; | ||
287 | |||
288 | switch (cmd) { | ||
289 | case SNDRV_PCM_TRIGGER_START: | ||
290 | case SNDRV_PCM_TRIGGER_RESUME: | ||
291 | prm->ss = substream; | ||
292 | break; | ||
293 | case SNDRV_PCM_TRIGGER_STOP: | ||
294 | case SNDRV_PCM_TRIGGER_SUSPEND: | ||
295 | prm->ss = NULL; | ||
296 | break; | ||
297 | default: | ||
298 | err = -EINVAL; | ||
299 | } | ||
300 | |||
301 | spin_unlock_irqrestore(&prm->lock, flags); | ||
302 | |||
303 | /* Clear buffer after Play stops */ | ||
304 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && !prm->ss) | ||
305 | memset(prm->rbuf, 0, prm->max_psize * USB_XFERS); | ||
306 | |||
307 | return err; | ||
308 | } | ||
309 | |||
310 | static snd_pcm_uframes_t uac2_pcm_pointer(struct snd_pcm_substream *substream) | ||
311 | { | ||
312 | struct snd_uac2_chip *uac2 = snd_pcm_substream_chip(substream); | ||
313 | struct uac2_rtd_params *prm; | ||
314 | |||
315 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
316 | prm = &uac2->p_prm; | ||
317 | else | ||
318 | prm = &uac2->c_prm; | ||
319 | |||
320 | return bytes_to_frames(substream->runtime, prm->hw_ptr); | ||
321 | } | ||
322 | |||
323 | static int uac2_pcm_hw_params(struct snd_pcm_substream *substream, | ||
324 | struct snd_pcm_hw_params *hw_params) | ||
325 | { | ||
326 | struct snd_uac2_chip *uac2 = snd_pcm_substream_chip(substream); | ||
327 | struct uac2_rtd_params *prm; | ||
328 | int err; | ||
329 | |||
330 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
331 | prm = &uac2->p_prm; | ||
332 | else | ||
333 | prm = &uac2->c_prm; | ||
334 | |||
335 | err = snd_pcm_lib_malloc_pages(substream, | ||
336 | params_buffer_bytes(hw_params)); | ||
337 | if (err >= 0) { | ||
338 | prm->dma_bytes = substream->runtime->dma_bytes; | ||
339 | prm->dma_area = substream->runtime->dma_area; | ||
340 | prm->period_size = params_period_bytes(hw_params); | ||
341 | } | ||
342 | |||
343 | return err; | ||
344 | } | ||
345 | |||
346 | static int uac2_pcm_hw_free(struct snd_pcm_substream *substream) | ||
347 | { | ||
348 | struct snd_uac2_chip *uac2 = snd_pcm_substream_chip(substream); | ||
349 | struct uac2_rtd_params *prm; | ||
350 | |||
351 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
352 | prm = &uac2->p_prm; | ||
353 | else | ||
354 | prm = &uac2->c_prm; | ||
355 | |||
356 | prm->dma_area = NULL; | ||
357 | prm->dma_bytes = 0; | ||
358 | prm->period_size = 0; | ||
359 | |||
360 | return snd_pcm_lib_free_pages(substream); | ||
361 | } | ||
362 | |||
363 | static int uac2_pcm_open(struct snd_pcm_substream *substream) | ||
364 | { | ||
365 | struct snd_uac2_chip *uac2 = snd_pcm_substream_chip(substream); | ||
366 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
367 | |||
368 | runtime->hw = uac2_pcm_hardware; | ||
369 | |||
370 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | ||
371 | spin_lock_init(&uac2->p_prm.lock); | ||
372 | runtime->hw.rate_min = p_srate; | ||
373 | runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE; /* ! p_ssize ! */ | ||
374 | runtime->hw.channels_min = num_channels(p_chmask); | ||
375 | runtime->hw.period_bytes_min = 2 * uac2->p_prm.max_psize | ||
376 | / runtime->hw.periods_min; | ||
377 | } else { | ||
378 | spin_lock_init(&uac2->c_prm.lock); | ||
379 | runtime->hw.rate_min = c_srate; | ||
380 | runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE; /* ! c_ssize ! */ | ||
381 | runtime->hw.channels_min = num_channels(c_chmask); | ||
382 | runtime->hw.period_bytes_min = 2 * uac2->c_prm.max_psize | ||
383 | / runtime->hw.periods_min; | ||
384 | } | ||
385 | |||
386 | runtime->hw.rate_max = runtime->hw.rate_min; | ||
387 | runtime->hw.channels_max = runtime->hw.channels_min; | ||
388 | |||
389 | snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); | ||
390 | |||
391 | return 0; | ||
392 | } | ||
393 | |||
394 | /* ALSA cries without these function pointers */ | ||
395 | static int uac2_pcm_null(struct snd_pcm_substream *substream) | ||
396 | { | ||
397 | return 0; | ||
398 | } | ||
399 | |||
400 | static struct snd_pcm_ops uac2_pcm_ops = { | ||
401 | .open = uac2_pcm_open, | ||
402 | .close = uac2_pcm_null, | ||
403 | .ioctl = snd_pcm_lib_ioctl, | ||
404 | .hw_params = uac2_pcm_hw_params, | ||
405 | .hw_free = uac2_pcm_hw_free, | ||
406 | .trigger = uac2_pcm_trigger, | ||
407 | .pointer = uac2_pcm_pointer, | ||
408 | .prepare = uac2_pcm_null, | ||
409 | }; | ||
410 | |||
411 | static int __devinit snd_uac2_probe(struct platform_device *pdev) | ||
412 | { | ||
413 | struct snd_uac2_chip *uac2 = pdev_to_uac2(pdev); | ||
414 | struct snd_card *card; | ||
415 | struct snd_pcm *pcm; | ||
416 | int err; | ||
417 | |||
418 | /* Choose any slot, with no id */ | ||
419 | err = snd_card_create(-1, NULL, THIS_MODULE, 0, &card); | ||
420 | if (err < 0) | ||
421 | return err; | ||
422 | |||
423 | uac2->card = card; | ||
424 | |||
425 | /* | ||
426 | * Create first PCM device | ||
427 | * Create a substream only for non-zero channel streams | ||
428 | */ | ||
429 | err = snd_pcm_new(uac2->card, "UAC2 PCM", 0, | ||
430 | p_chmask ? 1 : 0, c_chmask ? 1 : 0, &pcm); | ||
431 | if (err < 0) | ||
432 | goto snd_fail; | ||
433 | |||
434 | strcpy(pcm->name, "UAC2 PCM"); | ||
435 | pcm->private_data = uac2; | ||
436 | |||
437 | uac2->pcm = pcm; | ||
438 | |||
439 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &uac2_pcm_ops); | ||
440 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &uac2_pcm_ops); | ||
441 | |||
442 | strcpy(card->driver, "UAC2_Gadget"); | ||
443 | strcpy(card->shortname, "UAC2_Gadget"); | ||
444 | sprintf(card->longname, "UAC2_Gadget %i", pdev->id); | ||
445 | |||
446 | snd_card_set_dev(card, &pdev->dev); | ||
447 | |||
448 | snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS, | ||
449 | snd_dma_continuous_data(GFP_KERNEL), 0, BUFF_SIZE_MAX); | ||
450 | |||
451 | err = snd_card_register(card); | ||
452 | if (!err) { | ||
453 | platform_set_drvdata(pdev, card); | ||
454 | return 0; | ||
455 | } | ||
456 | |||
457 | snd_fail: | ||
458 | snd_card_free(card); | ||
459 | |||
460 | uac2->pcm = NULL; | ||
461 | uac2->card = NULL; | ||
462 | |||
463 | return err; | ||
464 | } | ||
465 | |||
466 | static int __devexit snd_uac2_remove(struct platform_device *pdev) | ||
467 | { | ||
468 | struct snd_card *card = platform_get_drvdata(pdev); | ||
469 | |||
470 | platform_set_drvdata(pdev, NULL); | ||
471 | |||
472 | if (card) | ||
473 | return snd_card_free(card); | ||
474 | |||
475 | return 0; | ||
476 | } | ||
477 | |||
478 | static int alsa_uac2_init(struct audio_dev *agdev) | ||
479 | { | ||
480 | struct snd_uac2_chip *uac2 = &agdev->uac2; | ||
481 | int err; | ||
482 | |||
483 | uac2->pdrv.probe = snd_uac2_probe; | ||
484 | uac2->pdrv.remove = snd_uac2_remove; | ||
485 | uac2->pdrv.driver.name = uac2_name; | ||
486 | |||
487 | uac2->pdev.id = 0; | ||
488 | uac2->pdev.name = uac2_name; | ||
489 | |||
490 | /* Register snd_uac2 driver */ | ||
491 | err = platform_driver_register(&uac2->pdrv); | ||
492 | if (err) | ||
493 | return err; | ||
494 | |||
495 | /* Register snd_uac2 device */ | ||
496 | err = platform_device_register(&uac2->pdev); | ||
497 | if (err) | ||
498 | platform_driver_unregister(&uac2->pdrv); | ||
499 | |||
500 | return err; | ||
501 | } | ||
502 | |||
503 | static void alsa_uac2_exit(struct audio_dev *agdev) | ||
504 | { | ||
505 | struct snd_uac2_chip *uac2 = &agdev->uac2; | ||
506 | |||
507 | platform_driver_unregister(&uac2->pdrv); | ||
508 | platform_device_unregister(&uac2->pdev); | ||
509 | } | ||
510 | |||
511 | |||
512 | /* --------- USB Function Interface ------------- */ | ||
513 | |||
514 | enum { | ||
515 | STR_ASSOC, | ||
516 | STR_IF_CTRL, | ||
517 | STR_CLKSRC_IN, | ||
518 | STR_CLKSRC_OUT, | ||
519 | STR_USB_IT, | ||
520 | STR_IO_IT, | ||
521 | STR_USB_OT, | ||
522 | STR_IO_OT, | ||
523 | STR_AS_OUT_ALT0, | ||
524 | STR_AS_OUT_ALT1, | ||
525 | STR_AS_IN_ALT0, | ||
526 | STR_AS_IN_ALT1, | ||
527 | }; | ||
528 | |||
529 | static const char ifassoc[] = "Source/Sink"; | ||
530 | static const char ifctrl[] = "Topology Control"; | ||
531 | static char clksrc_in[8]; | ||
532 | static char clksrc_out[8]; | ||
533 | static const char usb_it[] = "USBH Out"; | ||
534 | static const char io_it[] = "USBD Out"; | ||
535 | static const char usb_ot[] = "USBH In"; | ||
536 | static const char io_ot[] = "USBD In"; | ||
537 | static const char out_alt0[] = "Playback Inactive"; | ||
538 | static const char out_alt1[] = "Playback Active"; | ||
539 | static const char in_alt0[] = "Capture Inactive"; | ||
540 | static const char in_alt1[] = "Capture Active"; | ||
541 | |||
542 | static struct usb_string strings_fn[] = { | ||
543 | [STR_ASSOC].s = ifassoc, | ||
544 | [STR_IF_CTRL].s = ifctrl, | ||
545 | [STR_CLKSRC_IN].s = clksrc_in, | ||
546 | [STR_CLKSRC_OUT].s = clksrc_out, | ||
547 | [STR_USB_IT].s = usb_it, | ||
548 | [STR_IO_IT].s = io_it, | ||
549 | [STR_USB_OT].s = usb_ot, | ||
550 | [STR_IO_OT].s = io_ot, | ||
551 | [STR_AS_OUT_ALT0].s = out_alt0, | ||
552 | [STR_AS_OUT_ALT1].s = out_alt1, | ||
553 | [STR_AS_IN_ALT0].s = in_alt0, | ||
554 | [STR_AS_IN_ALT1].s = in_alt1, | ||
555 | { }, | ||
556 | }; | ||
557 | |||
558 | static struct usb_gadget_strings str_fn = { | ||
559 | .language = 0x0409, /* en-us */ | ||
560 | .strings = strings_fn, | ||
561 | }; | ||
562 | |||
563 | static struct usb_gadget_strings *fn_strings[] = { | ||
564 | &str_fn, | ||
565 | NULL, | ||
566 | }; | ||
567 | |||
568 | static struct usb_qualifier_descriptor devqual_desc = { | ||
569 | .bLength = sizeof devqual_desc, | ||
570 | .bDescriptorType = USB_DT_DEVICE_QUALIFIER, | ||
571 | |||
572 | .bcdUSB = cpu_to_le16(0x200), | ||
573 | .bDeviceClass = USB_CLASS_MISC, | ||
574 | .bDeviceSubClass = 0x02, | ||
575 | .bDeviceProtocol = 0x01, | ||
576 | .bNumConfigurations = 1, | ||
577 | .bRESERVED = 0, | ||
578 | }; | ||
579 | |||
580 | static struct usb_interface_assoc_descriptor iad_desc = { | ||
581 | .bLength = sizeof iad_desc, | ||
582 | .bDescriptorType = USB_DT_INTERFACE_ASSOCIATION, | ||
583 | |||
584 | .bFirstInterface = 0, | ||
585 | .bInterfaceCount = 3, | ||
586 | .bFunctionClass = USB_CLASS_AUDIO, | ||
587 | .bFunctionSubClass = UAC2_FUNCTION_SUBCLASS_UNDEFINED, | ||
588 | .bFunctionProtocol = UAC_VERSION_2, | ||
589 | }; | ||
590 | |||
591 | /* Audio Control Interface */ | ||
592 | static struct usb_interface_descriptor std_ac_if_desc = { | ||
593 | .bLength = sizeof std_ac_if_desc, | ||
594 | .bDescriptorType = USB_DT_INTERFACE, | ||
595 | |||
596 | .bAlternateSetting = 0, | ||
597 | .bNumEndpoints = 0, | ||
598 | .bInterfaceClass = USB_CLASS_AUDIO, | ||
599 | .bInterfaceSubClass = USB_SUBCLASS_AUDIOCONTROL, | ||
600 | .bInterfaceProtocol = UAC_VERSION_2, | ||
601 | }; | ||
602 | |||
603 | /* Clock source for IN traffic */ | ||
604 | struct uac_clock_source_descriptor in_clk_src_desc = { | ||
605 | .bLength = sizeof in_clk_src_desc, | ||
606 | .bDescriptorType = USB_DT_CS_INTERFACE, | ||
607 | |||
608 | .bDescriptorSubtype = UAC2_CLOCK_SOURCE, | ||
609 | .bClockID = USB_IN_CLK_ID, | ||
610 | .bmAttributes = UAC_CLOCK_SOURCE_TYPE_INT_FIXED, | ||
611 | .bmControls = (CONTROL_RDONLY << CLK_FREQ_CTRL), | ||
612 | .bAssocTerminal = 0, | ||
613 | }; | ||
614 | |||
615 | /* Clock source for OUT traffic */ | ||
616 | struct uac_clock_source_descriptor out_clk_src_desc = { | ||
617 | .bLength = sizeof out_clk_src_desc, | ||
618 | .bDescriptorType = USB_DT_CS_INTERFACE, | ||
619 | |||
620 | .bDescriptorSubtype = UAC2_CLOCK_SOURCE, | ||
621 | .bClockID = USB_OUT_CLK_ID, | ||
622 | .bmAttributes = UAC_CLOCK_SOURCE_TYPE_INT_FIXED, | ||
623 | .bmControls = (CONTROL_RDONLY << CLK_FREQ_CTRL), | ||
624 | .bAssocTerminal = 0, | ||
625 | }; | ||
626 | |||
627 | /* Input Terminal for USB_OUT */ | ||
628 | struct uac2_input_terminal_descriptor usb_out_it_desc = { | ||
629 | .bLength = sizeof usb_out_it_desc, | ||
630 | .bDescriptorType = USB_DT_CS_INTERFACE, | ||
631 | |||
632 | .bDescriptorSubtype = UAC_INPUT_TERMINAL, | ||
633 | .bTerminalID = USB_OUT_IT_ID, | ||
634 | .wTerminalType = cpu_to_le16(UAC_TERMINAL_STREAMING), | ||
635 | .bAssocTerminal = 0, | ||
636 | .bCSourceID = USB_OUT_CLK_ID, | ||
637 | .iChannelNames = 0, | ||
638 | .bmControls = (CONTROL_RDWR << COPY_CTRL), | ||
639 | }; | ||
640 | |||
641 | /* Input Terminal for I/O-In */ | ||
642 | struct uac2_input_terminal_descriptor io_in_it_desc = { | ||
643 | .bLength = sizeof io_in_it_desc, | ||
644 | .bDescriptorType = USB_DT_CS_INTERFACE, | ||
645 | |||
646 | .bDescriptorSubtype = UAC_INPUT_TERMINAL, | ||
647 | .bTerminalID = IO_IN_IT_ID, | ||
648 | .wTerminalType = cpu_to_le16(UAC_INPUT_TERMINAL_UNDEFINED), | ||
649 | .bAssocTerminal = 0, | ||
650 | .bCSourceID = USB_IN_CLK_ID, | ||
651 | .iChannelNames = 0, | ||
652 | .bmControls = (CONTROL_RDWR << COPY_CTRL), | ||
653 | }; | ||
654 | |||
655 | /* Ouput Terminal for USB_IN */ | ||
656 | struct uac2_output_terminal_descriptor usb_in_ot_desc = { | ||
657 | .bLength = sizeof usb_in_ot_desc, | ||
658 | .bDescriptorType = USB_DT_CS_INTERFACE, | ||
659 | |||
660 | .bDescriptorSubtype = UAC_OUTPUT_TERMINAL, | ||
661 | .bTerminalID = USB_IN_OT_ID, | ||
662 | .wTerminalType = cpu_to_le16(UAC_TERMINAL_STREAMING), | ||
663 | .bAssocTerminal = 0, | ||
664 | .bSourceID = IO_IN_IT_ID, | ||
665 | .bCSourceID = USB_IN_CLK_ID, | ||
666 | .bmControls = (CONTROL_RDWR << COPY_CTRL), | ||
667 | }; | ||
668 | |||
669 | /* Ouput Terminal for I/O-Out */ | ||
670 | struct uac2_output_terminal_descriptor io_out_ot_desc = { | ||
671 | .bLength = sizeof io_out_ot_desc, | ||
672 | .bDescriptorType = USB_DT_CS_INTERFACE, | ||
673 | |||
674 | .bDescriptorSubtype = UAC_OUTPUT_TERMINAL, | ||
675 | .bTerminalID = IO_OUT_OT_ID, | ||
676 | .wTerminalType = cpu_to_le16(UAC_OUTPUT_TERMINAL_UNDEFINED), | ||
677 | .bAssocTerminal = 0, | ||
678 | .bSourceID = USB_OUT_IT_ID, | ||
679 | .bCSourceID = USB_OUT_CLK_ID, | ||
680 | .bmControls = (CONTROL_RDWR << COPY_CTRL), | ||
681 | }; | ||
682 | |||
683 | struct uac2_ac_header_descriptor ac_hdr_desc = { | ||
684 | .bLength = sizeof ac_hdr_desc, | ||
685 | .bDescriptorType = USB_DT_CS_INTERFACE, | ||
686 | |||
687 | .bDescriptorSubtype = UAC_MS_HEADER, | ||
688 | .bcdADC = cpu_to_le16(0x200), | ||
689 | .bCategory = UAC2_FUNCTION_IO_BOX, | ||
690 | .wTotalLength = sizeof in_clk_src_desc + sizeof out_clk_src_desc | ||
691 | + sizeof usb_out_it_desc + sizeof io_in_it_desc | ||
692 | + sizeof usb_in_ot_desc + sizeof io_out_ot_desc, | ||
693 | .bmControls = 0, | ||
694 | }; | ||
695 | |||
696 | /* Audio Streaming OUT Interface - Alt0 */ | ||
697 | static struct usb_interface_descriptor std_as_out_if0_desc = { | ||
698 | .bLength = sizeof std_as_out_if0_desc, | ||
699 | .bDescriptorType = USB_DT_INTERFACE, | ||
700 | |||
701 | .bAlternateSetting = 0, | ||
702 | .bNumEndpoints = 0, | ||
703 | .bInterfaceClass = USB_CLASS_AUDIO, | ||
704 | .bInterfaceSubClass = USB_SUBCLASS_AUDIOSTREAMING, | ||
705 | .bInterfaceProtocol = UAC_VERSION_2, | ||
706 | }; | ||
707 | |||
708 | /* Audio Streaming OUT Interface - Alt1 */ | ||
709 | static struct usb_interface_descriptor std_as_out_if1_desc = { | ||
710 | .bLength = sizeof std_as_out_if1_desc, | ||
711 | .bDescriptorType = USB_DT_INTERFACE, | ||
712 | |||
713 | .bAlternateSetting = 1, | ||
714 | .bNumEndpoints = 1, | ||
715 | .bInterfaceClass = USB_CLASS_AUDIO, | ||
716 | .bInterfaceSubClass = USB_SUBCLASS_AUDIOSTREAMING, | ||
717 | .bInterfaceProtocol = UAC_VERSION_2, | ||
718 | }; | ||
719 | |||
720 | /* Audio Stream OUT Intface Desc */ | ||
721 | struct uac2_as_header_descriptor as_out_hdr_desc = { | ||
722 | .bLength = sizeof as_out_hdr_desc, | ||
723 | .bDescriptorType = USB_DT_CS_INTERFACE, | ||
724 | |||
725 | .bDescriptorSubtype = UAC_AS_GENERAL, | ||
726 | .bTerminalLink = USB_OUT_IT_ID, | ||
727 | .bmControls = 0, | ||
728 | .bFormatType = UAC_FORMAT_TYPE_I, | ||
729 | .bmFormats = cpu_to_le32(UAC_FORMAT_TYPE_I_PCM), | ||
730 | .iChannelNames = 0, | ||
731 | }; | ||
732 | |||
733 | /* Audio USB_OUT Format */ | ||
734 | struct uac2_format_type_i_descriptor as_out_fmt1_desc = { | ||
735 | .bLength = sizeof as_out_fmt1_desc, | ||
736 | .bDescriptorType = USB_DT_CS_INTERFACE, | ||
737 | .bDescriptorSubtype = UAC_FORMAT_TYPE, | ||
738 | .bFormatType = UAC_FORMAT_TYPE_I, | ||
739 | }; | ||
740 | |||
741 | /* STD AS ISO OUT Endpoint */ | ||
742 | struct usb_endpoint_descriptor fs_epout_desc = { | ||
743 | .bLength = USB_DT_ENDPOINT_SIZE, | ||
744 | .bDescriptorType = USB_DT_ENDPOINT, | ||
745 | |||
746 | .bEndpointAddress = USB_DIR_OUT, | ||
747 | .bmAttributes = USB_ENDPOINT_XFER_ISOC | USB_ENDPOINT_SYNC_ASYNC, | ||
748 | .bInterval = 1, | ||
749 | }; | ||
750 | |||
751 | struct usb_endpoint_descriptor hs_epout_desc = { | ||
752 | .bLength = USB_DT_ENDPOINT_SIZE, | ||
753 | .bDescriptorType = USB_DT_ENDPOINT, | ||
754 | |||
755 | .bmAttributes = USB_ENDPOINT_XFER_ISOC | USB_ENDPOINT_SYNC_ASYNC, | ||
756 | .bInterval = 4, | ||
757 | }; | ||
758 | |||
759 | /* CS AS ISO OUT Endpoint */ | ||
760 | static struct uac2_iso_endpoint_descriptor as_iso_out_desc = { | ||
761 | .bLength = sizeof as_iso_out_desc, | ||
762 | .bDescriptorType = USB_DT_CS_ENDPOINT, | ||
763 | |||
764 | .bDescriptorSubtype = UAC_EP_GENERAL, | ||
765 | .bmAttributes = 0, | ||
766 | .bmControls = 0, | ||
767 | .bLockDelayUnits = 0, | ||
768 | .wLockDelay = 0, | ||
769 | }; | ||
770 | |||
771 | /* Audio Streaming IN Interface - Alt0 */ | ||
772 | static struct usb_interface_descriptor std_as_in_if0_desc = { | ||
773 | .bLength = sizeof std_as_in_if0_desc, | ||
774 | .bDescriptorType = USB_DT_INTERFACE, | ||
775 | |||
776 | .bAlternateSetting = 0, | ||
777 | .bNumEndpoints = 0, | ||
778 | .bInterfaceClass = USB_CLASS_AUDIO, | ||
779 | .bInterfaceSubClass = USB_SUBCLASS_AUDIOSTREAMING, | ||
780 | .bInterfaceProtocol = UAC_VERSION_2, | ||
781 | }; | ||
782 | |||
783 | /* Audio Streaming IN Interface - Alt1 */ | ||
784 | static struct usb_interface_descriptor std_as_in_if1_desc = { | ||
785 | .bLength = sizeof std_as_in_if1_desc, | ||
786 | .bDescriptorType = USB_DT_INTERFACE, | ||
787 | |||
788 | .bAlternateSetting = 1, | ||
789 | .bNumEndpoints = 1, | ||
790 | .bInterfaceClass = USB_CLASS_AUDIO, | ||
791 | .bInterfaceSubClass = USB_SUBCLASS_AUDIOSTREAMING, | ||
792 | .bInterfaceProtocol = UAC_VERSION_2, | ||
793 | }; | ||
794 | |||
795 | /* Audio Stream IN Intface Desc */ | ||
796 | struct uac2_as_header_descriptor as_in_hdr_desc = { | ||
797 | .bLength = sizeof as_in_hdr_desc, | ||
798 | .bDescriptorType = USB_DT_CS_INTERFACE, | ||
799 | |||
800 | .bDescriptorSubtype = UAC_AS_GENERAL, | ||
801 | .bTerminalLink = USB_IN_OT_ID, | ||
802 | .bmControls = 0, | ||
803 | .bFormatType = UAC_FORMAT_TYPE_I, | ||
804 | .bmFormats = cpu_to_le32(UAC_FORMAT_TYPE_I_PCM), | ||
805 | .iChannelNames = 0, | ||
806 | }; | ||
807 | |||
808 | /* Audio USB_IN Format */ | ||
809 | struct uac2_format_type_i_descriptor as_in_fmt1_desc = { | ||
810 | .bLength = sizeof as_in_fmt1_desc, | ||
811 | .bDescriptorType = USB_DT_CS_INTERFACE, | ||
812 | .bDescriptorSubtype = UAC_FORMAT_TYPE, | ||
813 | .bFormatType = UAC_FORMAT_TYPE_I, | ||
814 | }; | ||
815 | |||
816 | /* STD AS ISO IN Endpoint */ | ||
817 | struct usb_endpoint_descriptor fs_epin_desc = { | ||
818 | .bLength = USB_DT_ENDPOINT_SIZE, | ||
819 | .bDescriptorType = USB_DT_ENDPOINT, | ||
820 | |||
821 | .bEndpointAddress = USB_DIR_IN, | ||
822 | .bmAttributes = USB_ENDPOINT_XFER_ISOC | USB_ENDPOINT_SYNC_ASYNC, | ||
823 | .bInterval = 1, | ||
824 | }; | ||
825 | |||
826 | struct usb_endpoint_descriptor hs_epin_desc = { | ||
827 | .bLength = USB_DT_ENDPOINT_SIZE, | ||
828 | .bDescriptorType = USB_DT_ENDPOINT, | ||
829 | |||
830 | .bmAttributes = USB_ENDPOINT_XFER_ISOC | USB_ENDPOINT_SYNC_ASYNC, | ||
831 | .bInterval = 4, | ||
832 | }; | ||
833 | |||
834 | /* CS AS ISO IN Endpoint */ | ||
835 | static struct uac2_iso_endpoint_descriptor as_iso_in_desc = { | ||
836 | .bLength = sizeof as_iso_in_desc, | ||
837 | .bDescriptorType = USB_DT_CS_ENDPOINT, | ||
838 | |||
839 | .bDescriptorSubtype = UAC_EP_GENERAL, | ||
840 | .bmAttributes = 0, | ||
841 | .bmControls = 0, | ||
842 | .bLockDelayUnits = 0, | ||
843 | .wLockDelay = 0, | ||
844 | }; | ||
845 | |||
846 | static struct usb_descriptor_header *fs_audio_desc[] = { | ||
847 | (struct usb_descriptor_header *)&iad_desc, | ||
848 | (struct usb_descriptor_header *)&std_ac_if_desc, | ||
849 | |||
850 | (struct usb_descriptor_header *)&ac_hdr_desc, | ||
851 | (struct usb_descriptor_header *)&in_clk_src_desc, | ||
852 | (struct usb_descriptor_header *)&out_clk_src_desc, | ||
853 | (struct usb_descriptor_header *)&usb_out_it_desc, | ||
854 | (struct usb_descriptor_header *)&io_in_it_desc, | ||
855 | (struct usb_descriptor_header *)&usb_in_ot_desc, | ||
856 | (struct usb_descriptor_header *)&io_out_ot_desc, | ||
857 | |||
858 | (struct usb_descriptor_header *)&std_as_out_if0_desc, | ||
859 | (struct usb_descriptor_header *)&std_as_out_if1_desc, | ||
860 | |||
861 | (struct usb_descriptor_header *)&as_out_hdr_desc, | ||
862 | (struct usb_descriptor_header *)&as_out_fmt1_desc, | ||
863 | (struct usb_descriptor_header *)&fs_epout_desc, | ||
864 | (struct usb_descriptor_header *)&as_iso_out_desc, | ||
865 | |||
866 | (struct usb_descriptor_header *)&std_as_in_if0_desc, | ||
867 | (struct usb_descriptor_header *)&std_as_in_if1_desc, | ||
868 | |||
869 | (struct usb_descriptor_header *)&as_in_hdr_desc, | ||
870 | (struct usb_descriptor_header *)&as_in_fmt1_desc, | ||
871 | (struct usb_descriptor_header *)&fs_epin_desc, | ||
872 | (struct usb_descriptor_header *)&as_iso_in_desc, | ||
873 | NULL, | ||
874 | }; | ||
875 | |||
876 | static struct usb_descriptor_header *hs_audio_desc[] = { | ||
877 | (struct usb_descriptor_header *)&iad_desc, | ||
878 | (struct usb_descriptor_header *)&std_ac_if_desc, | ||
879 | |||
880 | (struct usb_descriptor_header *)&ac_hdr_desc, | ||
881 | (struct usb_descriptor_header *)&in_clk_src_desc, | ||
882 | (struct usb_descriptor_header *)&out_clk_src_desc, | ||
883 | (struct usb_descriptor_header *)&usb_out_it_desc, | ||
884 | (struct usb_descriptor_header *)&io_in_it_desc, | ||
885 | (struct usb_descriptor_header *)&usb_in_ot_desc, | ||
886 | (struct usb_descriptor_header *)&io_out_ot_desc, | ||
887 | |||
888 | (struct usb_descriptor_header *)&std_as_out_if0_desc, | ||
889 | (struct usb_descriptor_header *)&std_as_out_if1_desc, | ||
890 | |||
891 | (struct usb_descriptor_header *)&as_out_hdr_desc, | ||
892 | (struct usb_descriptor_header *)&as_out_fmt1_desc, | ||
893 | (struct usb_descriptor_header *)&hs_epout_desc, | ||
894 | (struct usb_descriptor_header *)&as_iso_out_desc, | ||
895 | |||
896 | (struct usb_descriptor_header *)&std_as_in_if0_desc, | ||
897 | (struct usb_descriptor_header *)&std_as_in_if1_desc, | ||
898 | |||
899 | (struct usb_descriptor_header *)&as_in_hdr_desc, | ||
900 | (struct usb_descriptor_header *)&as_in_fmt1_desc, | ||
901 | (struct usb_descriptor_header *)&hs_epin_desc, | ||
902 | (struct usb_descriptor_header *)&as_iso_in_desc, | ||
903 | NULL, | ||
904 | }; | ||
905 | |||
906 | struct cntrl_cur_lay3 { | ||
907 | __u32 dCUR; | ||
908 | }; | ||
909 | |||
910 | struct cntrl_range_lay3 { | ||
911 | __u16 wNumSubRanges; | ||
912 | __u32 dMIN; | ||
913 | __u32 dMAX; | ||
914 | __u32 dRES; | ||
915 | } __packed; | ||
916 | |||
917 | static inline void | ||
918 | free_ep(struct uac2_rtd_params *prm, struct usb_ep *ep) | ||
919 | { | ||
920 | struct snd_uac2_chip *uac2 = prm_to_uac2(prm); | ||
921 | int i; | ||
922 | |||
923 | prm->ep_enabled = false; | ||
924 | |||
925 | for (i = 0; i < USB_XFERS; i++) { | ||
926 | if (prm->ureq[i].req) { | ||
927 | usb_ep_dequeue(ep, prm->ureq[i].req); | ||
928 | usb_ep_free_request(ep, prm->ureq[i].req); | ||
929 | prm->ureq[i].req = NULL; | ||
930 | } | ||
931 | } | ||
932 | |||
933 | if (usb_ep_disable(ep)) | ||
934 | dev_err(&uac2->pdev.dev, | ||
935 | "%s:%d Error!\n", __func__, __LINE__); | ||
936 | } | ||
937 | |||
938 | static int __init | ||
939 | afunc_bind(struct usb_configuration *cfg, struct usb_function *fn) | ||
940 | { | ||
941 | struct audio_dev *agdev = func_to_agdev(fn); | ||
942 | struct snd_uac2_chip *uac2 = &agdev->uac2; | ||
943 | struct usb_composite_dev *cdev = cfg->cdev; | ||
944 | struct usb_gadget *gadget = cdev->gadget; | ||
945 | struct uac2_rtd_params *prm; | ||
946 | int ret; | ||
947 | |||
948 | ret = usb_interface_id(cfg, fn); | ||
949 | if (ret < 0) { | ||
950 | dev_err(&uac2->pdev.dev, | ||
951 | "%s:%d Error!\n", __func__, __LINE__); | ||
952 | return ret; | ||
953 | } | ||
954 | std_ac_if_desc.bInterfaceNumber = ret; | ||
955 | ALT_SET(agdev->ac_alt, 0); | ||
956 | INTF_SET(agdev->ac_alt, ret); | ||
957 | |||
958 | ret = usb_interface_id(cfg, fn); | ||
959 | if (ret < 0) { | ||
960 | dev_err(&uac2->pdev.dev, | ||
961 | "%s:%d Error!\n", __func__, __LINE__); | ||
962 | return ret; | ||
963 | } | ||
964 | std_as_out_if0_desc.bInterfaceNumber = ret; | ||
965 | std_as_out_if1_desc.bInterfaceNumber = ret; | ||
966 | ALT_SET(agdev->as_out_alt, 0); | ||
967 | INTF_SET(agdev->as_out_alt, ret); | ||
968 | |||
969 | ret = usb_interface_id(cfg, fn); | ||
970 | if (ret < 0) { | ||
971 | dev_err(&uac2->pdev.dev, | ||
972 | "%s:%d Error!\n", __func__, __LINE__); | ||
973 | return ret; | ||
974 | } | ||
975 | std_as_in_if0_desc.bInterfaceNumber = ret; | ||
976 | std_as_in_if1_desc.bInterfaceNumber = ret; | ||
977 | ALT_SET(agdev->as_in_alt, 0); | ||
978 | INTF_SET(agdev->as_in_alt, ret); | ||
979 | |||
980 | agdev->out_ep = usb_ep_autoconfig(gadget, &fs_epout_desc); | ||
981 | if (!agdev->out_ep) | ||
982 | dev_err(&uac2->pdev.dev, | ||
983 | "%s:%d Error!\n", __func__, __LINE__); | ||
984 | agdev->out_ep->driver_data = agdev; | ||
985 | |||
986 | agdev->in_ep = usb_ep_autoconfig(gadget, &fs_epin_desc); | ||
987 | if (!agdev->in_ep) | ||
988 | dev_err(&uac2->pdev.dev, | ||
989 | "%s:%d Error!\n", __func__, __LINE__); | ||
990 | agdev->in_ep->driver_data = agdev; | ||
991 | |||
992 | hs_epout_desc.bEndpointAddress = fs_epout_desc.bEndpointAddress; | ||
993 | hs_epout_desc.wMaxPacketSize = fs_epout_desc.wMaxPacketSize; | ||
994 | hs_epin_desc.bEndpointAddress = fs_epin_desc.bEndpointAddress; | ||
995 | hs_epin_desc.wMaxPacketSize = fs_epin_desc.wMaxPacketSize; | ||
996 | |||
997 | fn->descriptors = usb_copy_descriptors(fs_audio_desc); | ||
998 | if (gadget_is_dualspeed(gadget)) | ||
999 | fn->hs_descriptors = usb_copy_descriptors(hs_audio_desc); | ||
1000 | |||
1001 | prm = &agdev->uac2.c_prm; | ||
1002 | prm->max_psize = hs_epout_desc.wMaxPacketSize; | ||
1003 | prm->rbuf = kzalloc(prm->max_psize * USB_XFERS, GFP_KERNEL); | ||
1004 | if (!prm->rbuf) { | ||
1005 | prm->max_psize = 0; | ||
1006 | dev_err(&uac2->pdev.dev, | ||
1007 | "%s:%d Error!\n", __func__, __LINE__); | ||
1008 | } | ||
1009 | |||
1010 | prm = &agdev->uac2.p_prm; | ||
1011 | prm->max_psize = hs_epin_desc.wMaxPacketSize; | ||
1012 | prm->rbuf = kzalloc(prm->max_psize * USB_XFERS, GFP_KERNEL); | ||
1013 | if (!prm->rbuf) { | ||
1014 | prm->max_psize = 0; | ||
1015 | dev_err(&uac2->pdev.dev, | ||
1016 | "%s:%d Error!\n", __func__, __LINE__); | ||
1017 | } | ||
1018 | |||
1019 | return alsa_uac2_init(agdev); | ||
1020 | } | ||
1021 | |||
1022 | static void | ||
1023 | afunc_unbind(struct usb_configuration *cfg, struct usb_function *fn) | ||
1024 | { | ||
1025 | struct audio_dev *agdev = func_to_agdev(fn); | ||
1026 | struct usb_composite_dev *cdev = cfg->cdev; | ||
1027 | struct usb_gadget *gadget = cdev->gadget; | ||
1028 | struct uac2_rtd_params *prm; | ||
1029 | |||
1030 | alsa_uac2_exit(agdev); | ||
1031 | |||
1032 | prm = &agdev->uac2.p_prm; | ||
1033 | kfree(prm->rbuf); | ||
1034 | |||
1035 | prm = &agdev->uac2.c_prm; | ||
1036 | kfree(prm->rbuf); | ||
1037 | |||
1038 | if (gadget_is_dualspeed(gadget)) | ||
1039 | usb_free_descriptors(fn->hs_descriptors); | ||
1040 | usb_free_descriptors(fn->descriptors); | ||
1041 | |||
1042 | if (agdev->in_ep) | ||
1043 | agdev->in_ep->driver_data = NULL; | ||
1044 | if (agdev->out_ep) | ||
1045 | agdev->out_ep->driver_data = NULL; | ||
1046 | } | ||
1047 | |||
1048 | static int | ||
1049 | afunc_set_alt(struct usb_function *fn, unsigned intf, unsigned alt) | ||
1050 | { | ||
1051 | struct usb_composite_dev *cdev = fn->config->cdev; | ||
1052 | struct audio_dev *agdev = func_to_agdev(fn); | ||
1053 | struct snd_uac2_chip *uac2 = &agdev->uac2; | ||
1054 | struct usb_gadget *gadget = cdev->gadget; | ||
1055 | struct usb_request *req; | ||
1056 | struct usb_ep *ep; | ||
1057 | struct uac2_rtd_params *prm; | ||
1058 | int i; | ||
1059 | |||
1060 | /* No i/f has more than 2 alt settings */ | ||
1061 | if (alt > 1) { | ||
1062 | dev_err(&uac2->pdev.dev, | ||
1063 | "%s:%d Error!\n", __func__, __LINE__); | ||
1064 | return -EINVAL; | ||
1065 | } | ||
1066 | |||
1067 | if (intf == INTF_GET(agdev->ac_alt)) { | ||
1068 | /* Control I/f has only 1 AltSetting - 0 */ | ||
1069 | if (alt) { | ||
1070 | dev_err(&uac2->pdev.dev, | ||
1071 | "%s:%d Error!\n", __func__, __LINE__); | ||
1072 | return -EINVAL; | ||
1073 | } | ||
1074 | return 0; | ||
1075 | } | ||
1076 | |||
1077 | if (intf == INTF_GET(agdev->as_out_alt)) { | ||
1078 | ep = agdev->out_ep; | ||
1079 | prm = &uac2->c_prm; | ||
1080 | config_ep_by_speed(gadget, fn, ep); | ||
1081 | ALT_SET(agdev->as_out_alt, alt); | ||
1082 | } else if (intf == INTF_GET(agdev->as_in_alt)) { | ||
1083 | ep = agdev->in_ep; | ||
1084 | prm = &uac2->p_prm; | ||
1085 | config_ep_by_speed(gadget, fn, ep); | ||
1086 | ALT_SET(agdev->as_in_alt, alt); | ||
1087 | } else { | ||
1088 | dev_err(&uac2->pdev.dev, | ||
1089 | "%s:%d Error!\n", __func__, __LINE__); | ||
1090 | return -EINVAL; | ||
1091 | } | ||
1092 | |||
1093 | if (alt == 0) { | ||
1094 | free_ep(prm, ep); | ||
1095 | return 0; | ||
1096 | } | ||
1097 | |||
1098 | prm->ep_enabled = true; | ||
1099 | usb_ep_enable(ep); | ||
1100 | |||
1101 | for (i = 0; i < USB_XFERS; i++) { | ||
1102 | if (prm->ureq[i].req) { | ||
1103 | if (usb_ep_queue(ep, prm->ureq[i].req, GFP_ATOMIC)) | ||
1104 | dev_err(&uac2->pdev.dev, "%d Error!\n", | ||
1105 | __LINE__); | ||
1106 | continue; | ||
1107 | } | ||
1108 | |||
1109 | req = usb_ep_alloc_request(ep, GFP_ATOMIC); | ||
1110 | if (req == NULL) { | ||
1111 | dev_err(&uac2->pdev.dev, | ||
1112 | "%s:%d Error!\n", __func__, __LINE__); | ||
1113 | return -EINVAL; | ||
1114 | } | ||
1115 | |||
1116 | prm->ureq[i].req = req; | ||
1117 | prm->ureq[i].pp = prm; | ||
1118 | |||
1119 | req->zero = 0; | ||
1120 | req->dma = DMA_ADDR_INVALID; | ||
1121 | req->context = &prm->ureq[i]; | ||
1122 | req->length = prm->max_psize; | ||
1123 | req->complete = agdev_iso_complete; | ||
1124 | req->buf = prm->rbuf + i * req->length; | ||
1125 | |||
1126 | if (usb_ep_queue(ep, req, GFP_ATOMIC)) | ||
1127 | dev_err(&uac2->pdev.dev, "%d Error!\n", __LINE__); | ||
1128 | } | ||
1129 | |||
1130 | return 0; | ||
1131 | } | ||
1132 | |||
1133 | static int | ||
1134 | afunc_get_alt(struct usb_function *fn, unsigned intf) | ||
1135 | { | ||
1136 | struct audio_dev *agdev = func_to_agdev(fn); | ||
1137 | struct snd_uac2_chip *uac2 = &agdev->uac2; | ||
1138 | |||
1139 | if (intf == INTF_GET(agdev->ac_alt)) | ||
1140 | return ALT_GET(agdev->ac_alt); | ||
1141 | else if (intf == INTF_GET(agdev->as_out_alt)) | ||
1142 | return ALT_GET(agdev->as_out_alt); | ||
1143 | else if (intf == INTF_GET(agdev->as_in_alt)) | ||
1144 | return ALT_GET(agdev->as_in_alt); | ||
1145 | else | ||
1146 | dev_err(&uac2->pdev.dev, | ||
1147 | "%s:%d Invalid Interface %d!\n", | ||
1148 | __func__, __LINE__, intf); | ||
1149 | |||
1150 | return -EINVAL; | ||
1151 | } | ||
1152 | |||
1153 | static void | ||
1154 | afunc_disable(struct usb_function *fn) | ||
1155 | { | ||
1156 | struct audio_dev *agdev = func_to_agdev(fn); | ||
1157 | struct snd_uac2_chip *uac2 = &agdev->uac2; | ||
1158 | |||
1159 | free_ep(&uac2->p_prm, agdev->in_ep); | ||
1160 | ALT_SET(agdev->as_in_alt, 0); | ||
1161 | |||
1162 | free_ep(&uac2->c_prm, agdev->out_ep); | ||
1163 | ALT_SET(agdev->as_out_alt, 0); | ||
1164 | } | ||
1165 | |||
1166 | static int | ||
1167 | in_rq_cur(struct usb_function *fn, const struct usb_ctrlrequest *cr) | ||
1168 | { | ||
1169 | struct usb_request *req = fn->config->cdev->req; | ||
1170 | struct audio_dev *agdev = func_to_agdev(fn); | ||
1171 | struct snd_uac2_chip *uac2 = &agdev->uac2; | ||
1172 | u16 w_length = le16_to_cpu(cr->wLength); | ||
1173 | u16 w_index = le16_to_cpu(cr->wIndex); | ||
1174 | u16 w_value = le16_to_cpu(cr->wValue); | ||
1175 | u8 entity_id = (w_index >> 8) & 0xff; | ||
1176 | u8 control_selector = w_value >> 8; | ||
1177 | int value = -EOPNOTSUPP; | ||
1178 | |||
1179 | if (control_selector == UAC2_CS_CONTROL_SAM_FREQ) { | ||
1180 | struct cntrl_cur_lay3 c; | ||
1181 | |||
1182 | if (entity_id == USB_IN_CLK_ID) | ||
1183 | c.dCUR = p_srate; | ||
1184 | else if (entity_id == USB_OUT_CLK_ID) | ||
1185 | c.dCUR = c_srate; | ||
1186 | |||
1187 | value = min_t(unsigned, w_length, sizeof c); | ||
1188 | memcpy(req->buf, &c, value); | ||
1189 | } else if (control_selector == UAC2_CS_CONTROL_CLOCK_VALID) { | ||
1190 | *(u8 *)req->buf = 1; | ||
1191 | value = min_t(unsigned, w_length, 1); | ||
1192 | } else { | ||
1193 | dev_err(&uac2->pdev.dev, | ||
1194 | "%s:%d control_selector=%d TODO!\n", | ||
1195 | __func__, __LINE__, control_selector); | ||
1196 | } | ||
1197 | |||
1198 | return value; | ||
1199 | } | ||
1200 | |||
1201 | static int | ||
1202 | in_rq_range(struct usb_function *fn, const struct usb_ctrlrequest *cr) | ||
1203 | { | ||
1204 | struct usb_request *req = fn->config->cdev->req; | ||
1205 | struct audio_dev *agdev = func_to_agdev(fn); | ||
1206 | struct snd_uac2_chip *uac2 = &agdev->uac2; | ||
1207 | u16 w_length = le16_to_cpu(cr->wLength); | ||
1208 | u16 w_index = le16_to_cpu(cr->wIndex); | ||
1209 | u16 w_value = le16_to_cpu(cr->wValue); | ||
1210 | u8 entity_id = (w_index >> 8) & 0xff; | ||
1211 | u8 control_selector = w_value >> 8; | ||
1212 | struct cntrl_range_lay3 r; | ||
1213 | int value = -EOPNOTSUPP; | ||
1214 | |||
1215 | if (control_selector == UAC2_CS_CONTROL_SAM_FREQ) { | ||
1216 | if (entity_id == USB_IN_CLK_ID) | ||
1217 | r.dMIN = p_srate; | ||
1218 | else if (entity_id == USB_OUT_CLK_ID) | ||
1219 | r.dMIN = c_srate; | ||
1220 | else | ||
1221 | return -EOPNOTSUPP; | ||
1222 | |||
1223 | r.dMAX = r.dMIN; | ||
1224 | r.dRES = 0; | ||
1225 | r.wNumSubRanges = 1; | ||
1226 | |||
1227 | value = min_t(unsigned, w_length, sizeof r); | ||
1228 | memcpy(req->buf, &r, value); | ||
1229 | } else { | ||
1230 | dev_err(&uac2->pdev.dev, | ||
1231 | "%s:%d control_selector=%d TODO!\n", | ||
1232 | __func__, __LINE__, control_selector); | ||
1233 | } | ||
1234 | |||
1235 | return value; | ||
1236 | } | ||
1237 | |||
1238 | static int | ||
1239 | ac_rq_in(struct usb_function *fn, const struct usb_ctrlrequest *cr) | ||
1240 | { | ||
1241 | if (cr->bRequest == UAC2_CS_CUR) | ||
1242 | return in_rq_cur(fn, cr); | ||
1243 | else if (cr->bRequest == UAC2_CS_RANGE) | ||
1244 | return in_rq_range(fn, cr); | ||
1245 | else | ||
1246 | return -EOPNOTSUPP; | ||
1247 | } | ||
1248 | |||
1249 | static int | ||
1250 | out_rq_cur(struct usb_function *fn, const struct usb_ctrlrequest *cr) | ||
1251 | { | ||
1252 | u16 w_length = le16_to_cpu(cr->wLength); | ||
1253 | u16 w_value = le16_to_cpu(cr->wValue); | ||
1254 | u8 control_selector = w_value >> 8; | ||
1255 | |||
1256 | if (control_selector == UAC2_CS_CONTROL_SAM_FREQ) | ||
1257 | return w_length; | ||
1258 | |||
1259 | return -EOPNOTSUPP; | ||
1260 | } | ||
1261 | |||
1262 | static int | ||
1263 | setup_rq_inf(struct usb_function *fn, const struct usb_ctrlrequest *cr) | ||
1264 | { | ||
1265 | struct audio_dev *agdev = func_to_agdev(fn); | ||
1266 | struct snd_uac2_chip *uac2 = &agdev->uac2; | ||
1267 | u16 w_index = le16_to_cpu(cr->wIndex); | ||
1268 | u8 intf = w_index & 0xff; | ||
1269 | |||
1270 | if (intf != INTF_GET(agdev->ac_alt)) { | ||
1271 | dev_err(&uac2->pdev.dev, | ||
1272 | "%s:%d Error!\n", __func__, __LINE__); | ||
1273 | return -EOPNOTSUPP; | ||
1274 | } | ||
1275 | |||
1276 | if (cr->bRequestType & USB_DIR_IN) | ||
1277 | return ac_rq_in(fn, cr); | ||
1278 | else if (cr->bRequest == UAC2_CS_CUR) | ||
1279 | return out_rq_cur(fn, cr); | ||
1280 | |||
1281 | return -EOPNOTSUPP; | ||
1282 | } | ||
1283 | |||
1284 | static int | ||
1285 | afunc_setup(struct usb_function *fn, const struct usb_ctrlrequest *cr) | ||
1286 | { | ||
1287 | struct usb_composite_dev *cdev = fn->config->cdev; | ||
1288 | struct audio_dev *agdev = func_to_agdev(fn); | ||
1289 | struct snd_uac2_chip *uac2 = &agdev->uac2; | ||
1290 | struct usb_request *req = cdev->req; | ||
1291 | u16 w_length = le16_to_cpu(cr->wLength); | ||
1292 | int value = -EOPNOTSUPP; | ||
1293 | |||
1294 | /* Only Class specific requests are supposed to reach here */ | ||
1295 | if ((cr->bRequestType & USB_TYPE_MASK) != USB_TYPE_CLASS) | ||
1296 | return -EOPNOTSUPP; | ||
1297 | |||
1298 | if ((cr->bRequestType & USB_RECIP_MASK) == USB_RECIP_INTERFACE) | ||
1299 | value = setup_rq_inf(fn, cr); | ||
1300 | else | ||
1301 | dev_err(&uac2->pdev.dev, "%s:%d Error!\n", __func__, __LINE__); | ||
1302 | |||
1303 | if (value >= 0) { | ||
1304 | req->length = value; | ||
1305 | req->zero = value < w_length; | ||
1306 | value = usb_ep_queue(cdev->gadget->ep0, req, GFP_ATOMIC); | ||
1307 | if (value < 0) { | ||
1308 | dev_err(&uac2->pdev.dev, | ||
1309 | "%s:%d Error!\n", __func__, __LINE__); | ||
1310 | req->status = 0; | ||
1311 | } | ||
1312 | } | ||
1313 | |||
1314 | return value; | ||
1315 | } | ||
1316 | |||
1317 | static int audio_bind_config(struct usb_configuration *cfg) | ||
1318 | { | ||
1319 | int id, res; | ||
1320 | |||
1321 | agdev_g = kzalloc(sizeof *agdev_g, GFP_KERNEL); | ||
1322 | if (agdev_g == NULL) { | ||
1323 | printk(KERN_ERR "Unable to allocate audio gadget\n"); | ||
1324 | return -ENOMEM; | ||
1325 | } | ||
1326 | |||
1327 | id = usb_string_id(cfg->cdev); | ||
1328 | if (id < 0) | ||
1329 | return id; | ||
1330 | |||
1331 | strings_fn[STR_ASSOC].id = id; | ||
1332 | iad_desc.iFunction = id, | ||
1333 | |||
1334 | id = usb_string_id(cfg->cdev); | ||
1335 | if (id < 0) | ||
1336 | return id; | ||
1337 | |||
1338 | strings_fn[STR_IF_CTRL].id = id; | ||
1339 | std_ac_if_desc.iInterface = id, | ||
1340 | |||
1341 | id = usb_string_id(cfg->cdev); | ||
1342 | if (id < 0) | ||
1343 | return id; | ||
1344 | |||
1345 | strings_fn[STR_CLKSRC_IN].id = id; | ||
1346 | in_clk_src_desc.iClockSource = id, | ||
1347 | |||
1348 | id = usb_string_id(cfg->cdev); | ||
1349 | if (id < 0) | ||
1350 | return id; | ||
1351 | |||
1352 | strings_fn[STR_CLKSRC_OUT].id = id; | ||
1353 | out_clk_src_desc.iClockSource = id, | ||
1354 | |||
1355 | id = usb_string_id(cfg->cdev); | ||
1356 | if (id < 0) | ||
1357 | return id; | ||
1358 | |||
1359 | strings_fn[STR_USB_IT].id = id; | ||
1360 | usb_out_it_desc.iTerminal = id, | ||
1361 | |||
1362 | id = usb_string_id(cfg->cdev); | ||
1363 | if (id < 0) | ||
1364 | return id; | ||
1365 | |||
1366 | strings_fn[STR_IO_IT].id = id; | ||
1367 | io_in_it_desc.iTerminal = id; | ||
1368 | |||
1369 | id = usb_string_id(cfg->cdev); | ||
1370 | if (id < 0) | ||
1371 | return id; | ||
1372 | |||
1373 | strings_fn[STR_USB_OT].id = id; | ||
1374 | usb_in_ot_desc.iTerminal = id; | ||
1375 | |||
1376 | id = usb_string_id(cfg->cdev); | ||
1377 | if (id < 0) | ||
1378 | return id; | ||
1379 | |||
1380 | strings_fn[STR_IO_OT].id = id; | ||
1381 | io_out_ot_desc.iTerminal = id; | ||
1382 | |||
1383 | id = usb_string_id(cfg->cdev); | ||
1384 | if (id < 0) | ||
1385 | return id; | ||
1386 | |||
1387 | strings_fn[STR_AS_OUT_ALT0].id = id; | ||
1388 | std_as_out_if0_desc.iInterface = id; | ||
1389 | |||
1390 | id = usb_string_id(cfg->cdev); | ||
1391 | if (id < 0) | ||
1392 | return id; | ||
1393 | |||
1394 | strings_fn[STR_AS_OUT_ALT1].id = id; | ||
1395 | std_as_out_if1_desc.iInterface = id; | ||
1396 | |||
1397 | id = usb_string_id(cfg->cdev); | ||
1398 | if (id < 0) | ||
1399 | return id; | ||
1400 | |||
1401 | strings_fn[STR_AS_IN_ALT0].id = id; | ||
1402 | std_as_in_if0_desc.iInterface = id; | ||
1403 | |||
1404 | id = usb_string_id(cfg->cdev); | ||
1405 | if (id < 0) | ||
1406 | return id; | ||
1407 | |||
1408 | strings_fn[STR_AS_IN_ALT1].id = id; | ||
1409 | std_as_in_if1_desc.iInterface = id; | ||
1410 | |||
1411 | agdev_g->func.name = "uac2_func"; | ||
1412 | agdev_g->func.strings = fn_strings; | ||
1413 | agdev_g->func.bind = afunc_bind; | ||
1414 | agdev_g->func.unbind = afunc_unbind; | ||
1415 | agdev_g->func.set_alt = afunc_set_alt; | ||
1416 | agdev_g->func.get_alt = afunc_get_alt; | ||
1417 | agdev_g->func.disable = afunc_disable; | ||
1418 | agdev_g->func.setup = afunc_setup; | ||
1419 | |||
1420 | /* Initialize the configurable parameters */ | ||
1421 | usb_out_it_desc.bNrChannels = num_channels(c_chmask); | ||
1422 | usb_out_it_desc.bmChannelConfig = cpu_to_le32(c_chmask); | ||
1423 | io_in_it_desc.bNrChannels = num_channels(p_chmask); | ||
1424 | io_in_it_desc.bmChannelConfig = cpu_to_le32(p_chmask); | ||
1425 | as_out_hdr_desc.bNrChannels = num_channels(c_chmask); | ||
1426 | as_out_hdr_desc.bmChannelConfig = cpu_to_le32(c_chmask); | ||
1427 | as_in_hdr_desc.bNrChannels = num_channels(p_chmask); | ||
1428 | as_in_hdr_desc.bmChannelConfig = cpu_to_le32(p_chmask); | ||
1429 | as_out_fmt1_desc.bSubslotSize = c_ssize; | ||
1430 | as_out_fmt1_desc.bBitResolution = c_ssize * 8; | ||
1431 | as_in_fmt1_desc.bSubslotSize = p_ssize; | ||
1432 | as_in_fmt1_desc.bBitResolution = p_ssize * 8; | ||
1433 | |||
1434 | snprintf(clksrc_in, sizeof(clksrc_in), "%uHz", p_srate); | ||
1435 | snprintf(clksrc_out, sizeof(clksrc_out), "%uHz", c_srate); | ||
1436 | |||
1437 | res = usb_add_function(cfg, &agdev_g->func); | ||
1438 | if (res < 0) | ||
1439 | kfree(agdev_g); | ||
1440 | |||
1441 | return res; | ||
1442 | } | ||
1443 | |||
1444 | static void | ||
1445 | uac2_unbind_config(struct usb_configuration *cfg) | ||
1446 | { | ||
1447 | kfree(agdev_g); | ||
1448 | agdev_g = NULL; | ||
1449 | } | ||