Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
1================
2ASoC USB support
3================
4
5Overview
6========
7In order to leverage the existing USB sound device support in ALSA, the
8ASoC USB APIs are introduced to allow the subsystems to exchange
9configuration information.
10
11One potential use case would be to support USB audio offloading, which is
12an implementation that allows for an alternate power-optimized path in the audio
13subsystem to handle the transfer of audio data over the USB bus. This would
14let the main processor to stay in lower power modes for longer duration. The
15following is an example design of how the ASoC and ALSA pieces can be connected
16together to achieve this:
17
18::
19
20 USB | ASoC
21 | _________________________
22 | | ASoC Platform card |
23 | |_________________________|
24 | | |
25 | ___V____ ____V____
26 | |ASoC BE | |ASoC FE |
27 | |DAI LNK | |DAI LNK |
28 | |________| |_________|
29 | ^ ^ ^
30 | | |________|
31 | ___V____ |
32 | |SoC-USB | |
33 ________ ________ | | |
34 |USB SND |<--->|USBSND |<------------>|________| |
35 |(card.c)| |offld |<---------- |
36 |________| |________|___ | | |
37 ^ ^ | | | ____________V_________
38 | | | | | |IPC |
39 __ V_______________V_____ | | | |______________________|
40 |USB SND (endpoint.c) | | | | ^
41 |_________________________| | | | |
42 ^ | | | ___________V___________
43 | | | |->|audio DSP |
44 ___________V_____________ | | |_______________________|
45 |XHCI HCD |<- |
46 |_________________________| |
47
48
49SoC USB driver
50==============
51Structures
52----------
53``struct snd_soc_usb``
54
55 - ``list``: list head for SND SoC struct list
56 - ``component``: reference to ASoC component
57 - ``connection_status_cb``: callback to notify connection events
58 - ``update_offload_route_info``: callback to fetch selected USB sound card/PCM
59 device
60 - ``priv_data``: driver data
61
62The snd_soc_usb structure can be referenced using the ASoC platform card
63device, or a USB device (udev->dev). This is created by the ASoC BE DAI
64link, and the USB sound entity will be able to pass information to the
65ASoC BE DAI link using this structure.
66
67``struct snd_soc_usb_device``
68
69 - ``card_idx``: sound card index associated with USB sound device
70 - ``chip_idx``: USB sound chip array index
71 - ``cpcm_idx``: capture pcm device indexes associated with the USB sound device
72 - ``ppcm_idx``: playback pcm device indexes associated with the USB sound device
73 - ``num_playback``: number of playback streams
74 - ``num_capture``: number of capture streams
75 - ``list``: list head for the USB sound device list
76
77The struct snd_soc_usb_device is created by the USB sound offload driver.
78This will carry basic parameters/limitations that will be used to
79determine the possible offloading paths for this USB audio device.
80
81Functions
82---------
83.. code-block:: rst
84
85 int snd_soc_usb_find_supported_format(int card_idx,
86 struct snd_pcm_hw_params *params, int direction)
87..
88
89 - ``card_idx``: the index into the USB sound chip array.
90 - ``params``: Requested PCM parameters from the USB DPCM BE DAI link
91 - ``direction``: capture or playback
92
93**snd_soc_usb_find_supported_format()** ensures that the requested audio profile
94being requested by the external DSP is supported by the USB device.
95
96Returns 0 on success, and -EOPNOTSUPP on failure.
97
98.. code-block:: rst
99
100 int snd_soc_usb_connect(struct device *usbdev, struct snd_soc_usb_device *sdev)
101..
102
103 - ``usbdev``: the usb device that was discovered
104 - ``sdev``: capabilities of the device
105
106**snd_soc_usb_connect()** notifies the ASoC USB DCPM BE DAI link of a USB
107audio device detection. This can be utilized in the BE DAI
108driver to keep track of available USB audio devices. This is intended
109to be called by the USB offload driver residing in USB SND.
110
111Returns 0 on success, negative error code on failure.
112
113.. code-block:: rst
114
115 int snd_soc_usb_disconnect(struct device *usbdev, struct snd_soc_usb_device *sdev)
116..
117
118 - ``usbdev``: the usb device that was removed
119 - ``sdev``: capabilities to free
120
121**snd_soc_usb_disconnect()** notifies the ASoC USB DCPM BE DAI link of a USB
122audio device removal. This is intended to be called by the USB offload
123driver that resides in USB SND.
124
125.. code-block:: rst
126
127 void *snd_soc_usb_find_priv_data(struct device *usbdev)
128..
129
130 - ``usbdev``: the usb device to reference to find private data
131
132**snd_soc_usb_find_priv_data()** fetches the private data saved to the SoC USB
133device.
134
135Returns pointer to priv_data on success, NULL on failure.
136
137.. code-block:: rst
138
139 int snd_soc_usb_setup_offload_jack(struct snd_soc_component *component,
140 struct snd_soc_jack *jack)
141..
142
143 - ``component``: ASoC component to add the jack
144 - ``jack``: jack component to populate
145
146**snd_soc_usb_setup_offload_jack()** is a helper to add a sound jack control to
147the platform sound card. This will allow for consistent naming to be used on
148designs that support USB audio offloading. Additionally, this will enable the
149jack to notify of changes.
150
151Returns 0 on success, negative otherwise.
152
153.. code-block:: rst
154
155 int snd_soc_usb_update_offload_route(struct device *dev, int card, int pcm,
156 int direction, enum snd_soc_usb_kctl path,
157 long *route)
158..
159
160 - ``dev``: USB device to look up offload path mapping
161 - ``card``: USB sound card index
162 - ``pcm``: USB sound PCM device index
163 - ``direction``: direction to fetch offload routing information
164 - ``path``: kcontrol selector - pcm device or card index
165 - ``route``: mapping of sound card and pcm indexes for the offload path. This is
166 an array of two integers that will carry the card and pcm device indexes
167 in that specific order. This can be used as the array for the kcontrol
168 output.
169
170**snd_soc_usb_update_offload_route()** calls a registered callback to the USB BE DAI
171link to fetch the information about the mapped ASoC devices for executing USB audio
172offload for the device. ``route`` may be a pointer to a kcontrol value output array,
173which carries values when the kcontrol is read.
174
175Returns 0 on success, negative otherwise.
176
177.. code-block:: rst
178
179 struct snd_soc_usb *snd_soc_usb_allocate_port(struct snd_soc_component *component,
180 void *data);
181..
182
183 - ``component``: DPCM BE DAI link component
184 - ``data``: private data
185
186**snd_soc_usb_allocate_port()** allocates a SoC USB device and populates standard
187parameters that is used for further operations.
188
189Returns a pointer to struct soc_usb on success, negative on error.
190
191.. code-block:: rst
192
193 void snd_soc_usb_free_port(struct snd_soc_usb *usb);
194..
195
196 - ``usb``: SoC USB device to free
197
198**snd_soc_usb_free_port()** frees a SoC USB device.
199
200.. code-block:: rst
201
202 void snd_soc_usb_add_port(struct snd_soc_usb *usb);
203..
204
205 - ``usb``: SoC USB device to add
206
207**snd_soc_usb_add_port()** add an allocated SoC USB device to the SOC USB framework.
208Once added, this device can be referenced by further operations.
209
210.. code-block:: rst
211
212 void snd_soc_usb_remove_port(struct snd_soc_usb *usb);
213..
214
215 - ``usb``: SoC USB device to remove
216
217**snd_soc_usb_remove_port()** removes a SoC USB device from the SoC USB framework.
218After removing a device, any SOC USB operations would not be able to reference the
219device removed.
220
221How to Register to SoC USB
222--------------------------
223The ASoC DPCM USB BE DAI link is the entity responsible for allocating and
224registering the SoC USB device on the component bind. Likewise, it will
225also be responsible for freeing the allocated resources. An example can
226be shown below:
227
228.. code-block:: rst
229
230 static int q6usb_component_probe(struct snd_soc_component *component)
231 {
232 ...
233 data->usb = snd_soc_usb_allocate_port(component, 1, &data->priv);
234 if (!data->usb)
235 return -ENOMEM;
236
237 usb->connection_status_cb = q6usb_alsa_connection_cb;
238
239 ret = snd_soc_usb_add_port(usb);
240 if (ret < 0) {
241 dev_err(component->dev, "failed to add usb port\n");
242 goto free_usb;
243 }
244 ...
245 }
246
247 static void q6usb_component_remove(struct snd_soc_component *component)
248 {
249 ...
250 snd_soc_usb_remove_port(data->usb);
251 snd_soc_usb_free_port(data->usb);
252 }
253
254 static const struct snd_soc_component_driver q6usb_dai_component = {
255 .probe = q6usb_component_probe,
256 .remove = q6usb_component_remove,
257 .name = "q6usb-dai-component",
258 ...
259 };
260..
261
262BE DAI links can pass along vendor specific information as part of the
263call to allocate the SoC USB device. This will allow any BE DAI link
264parameters or settings to be accessed by the USB offload driver that
265resides in USB SND.
266
267USB Audio Device Connection Flow
268--------------------------------
269USB devices can be hotplugged into the USB ports at any point in time.
270The BE DAI link should be aware of the current state of the physical USB
271port, i.e. if there are any USB devices with audio interface(s) connected.
272connection_status_cb() can be used to notify the BE DAI link of any change.
273
274This is called whenever there is a USB SND interface bind or remove event,
275using snd_soc_usb_connect() or snd_soc_usb_disconnect():
276
277.. code-block:: rst
278
279 static void qc_usb_audio_offload_probe(struct snd_usb_audio *chip)
280 {
281 ...
282 snd_soc_usb_connect(usb_get_usb_backend(udev), sdev);
283 ...
284 }
285
286 static void qc_usb_audio_offload_disconnect(struct snd_usb_audio *chip)
287 {
288 ...
289 snd_soc_usb_disconnect(usb_get_usb_backend(chip->dev), dev->sdev);
290 ...
291 }
292..
293
294In order to account for conditions where driver or device existence is
295not guaranteed, USB SND exposes snd_usb_rediscover_devices() to resend the
296connect events for any identified USB audio interfaces. Consider the
297the following situation:
298
299 **usb_audio_probe()**
300 | --> USB audio streams allocated and saved to usb_chip[]
301 | --> Propagate connect event to USB offload driver in USB SND
302 | --> **snd_soc_usb_connect()** exits as USB BE DAI link is not ready
303
304 BE DAI link component probe
305 | --> DAI link is probed and SoC USB port is allocated
306 | --> The USB audio device connect event is missed
307
308To ensure connection events are not missed, **snd_usb_rediscover_devices()**
309is executed when the SoC USB device is registered. Now, when the BE DAI
310link component probe occurs, the following highlights the sequence:
311
312 BE DAI link component probe
313 | --> DAI link is probed and SoC USB port is allocated
314 | --> SoC USB device added, and **snd_usb_rediscover_devices()** runs
315
316 **snd_usb_rediscover_devices()**
317 | --> Traverses through usb_chip[] and for non-NULL entries issue
318 | **connection_status_cb()**
319
320In the case where the USB offload driver is unbound, while USB SND is ready,
321the **snd_usb_rediscover_devices()** is called during module init. This allows
322for the offloading path to also be enabled with the following flow:
323
324 **usb_audio_probe()**
325 | --> USB audio streams allocated and saved to usb_chip[]
326 | --> Propagate connect event to USB offload driver in USB SND
327 | --> USB offload driver **NOT** ready!
328
329 BE DAI link component probe
330 | --> DAI link is probed and SoC USB port is allocated
331 | --> No USB connect event due to missing USB offload driver
332
333 USB offload driver probe
334 | --> **qc_usb_audio_offload_init()**
335 | --> Calls **snd_usb_rediscover_devices()** to notify of devices
336
337USB Offload Related Kcontrols
338=============================
339Details
340-------
341A set of kcontrols can be utilized by applications to help select the proper sound
342devices to enable USB audio offloading. SoC USB exposes the get_offload_dev()
343callback that designs can use to ensure that the proper indices are returned to the
344application.
345
346Implementation
347--------------
348
349**Example:**
350
351 **Sound Cards**:
352
353 ::
354
355 0 [SM8250MTPWCD938]: sm8250 - SM8250-MTP-WCD9380-WSA8810-VA-D
356 SM8250-MTP-WCD9380-WSA8810-VA-DMIC
357 1 [Seri ]: USB-Audio - Plantronics Blackwire 3225 Seri
358 Plantronics Plantronics Blackwire
359 3225 Seri at usb-xhci-hcd.1.auto-1.1,
360 full sp
361 2 [C320M ]: USB-Audio - Plantronics C320-M
362 Plantronics Plantronics C320-M at usb-xhci-hcd.1.auto-1.2, full speed
363
364 **PCM Devices**:
365
366 ::
367
368 card 0: SM8250MTPWCD938 [SM8250-MTP-WCD9380-WSA8810-VA-D], device 0: MultiMedia1 (*) []
369 Subdevices: 1/1
370 Subdevice #0: subdevice #0
371 card 0: SM8250MTPWCD938 [SM8250-MTP-WCD9380-WSA8810-VA-D], device 1: MultiMedia2 (*) []
372 Subdevices: 1/1
373 Subdevice #0: subdevice #0
374 card 1: Seri [Plantronics Blackwire 3225 Seri], device 0: USB Audio [USB Audio]
375 Subdevices: 1/1
376 Subdevice #0: subdevice #0
377 card 2: C320M [Plantronics C320-M], device 0: USB Audio [USB Audio]
378 Subdevices: 1/1
379 Subdevice #0: subdevice #0
380
381 **USB Sound Card** - card#1:
382
383 ::
384
385 USB Offload Playback Card Route PCM#0 -1 (range -1->32)
386 USB Offload Playback PCM Route PCM#0 -1 (range -1->255)
387
388 **USB Sound Card** - card#2:
389
390 ::
391
392 USB Offload Playback Card Route PCM#0 0 (range -1->32)
393 USB Offload Playback PCM Route PCM#0 1 (range -1->255)
394
395The above example shows a scenario where the system has one ASoC platform card
396(card#0) and two USB sound devices connected (card#1 and card#2). When reading
397the available kcontrols for each USB audio device, the following kcontrols lists
398the mapped offload card and pcm device indexes for the specific USB device:
399
400 ``USB Offload Playback Card Route PCM#*``
401
402 ``USB Offload Playback PCM Route PCM#*``
403
404The kcontrol is indexed, because a USB audio device could potentially have
405several PCM devices. The above kcontrols are defined as:
406
407 - ``USB Offload Playback Card Route PCM#`` **(R)**: Returns the ASoC platform sound
408 card index for a mapped offload path. The output **"0"** (card index) signifies
409 that there is an available offload path for the USB SND device through card#0.
410 If **"-1"** is seen, then no offload path is available for the USB SND device.
411 This kcontrol exists for each USB audio device that exists in the system, and
412 its expected to derive the current status of offload based on the output value
413 for the kcontrol along with the PCM route kcontrol.
414
415 - ``USB Offload Playback PCM Route PCM#`` **(R)**: Returns the ASoC platform sound
416 PCM device index for a mapped offload path. The output **"1"** (PCM device index)
417 signifies that there is an available offload path for the USB SND device through
418 PCM device#0. If **"-1"** is seen, then no offload path is available for the USB\
419 SND device. This kcontrol exists for each USB audio device that exists in the
420 system, and its expected to derive the current status of offload based on the
421 output value for this kcontrol, in addition to the card route kcontrol.
422
423USB Offload Playback Route Kcontrol
424-----------------------------------
425In order to allow for vendor specific implementations on audio offloading device
426selection, the SoC USB layer exposes the following:
427
428.. code-block:: rst
429
430 int (*update_offload_route_info)(struct snd_soc_component *component,
431 int card, int pcm, int direction,
432 enum snd_soc_usb_kctl path,
433 long *route)
434..
435
436These are specific for the **USB Offload Playback Card Route PCM#** and **USB
437Offload PCM Route PCM#** kcontrols.
438
439When users issue get calls to the kcontrol, the registered SoC USB callbacks will
440execute the registered function calls to the DPCM BE DAI link.
441
442**Callback Registration:**
443
444.. code-block:: rst
445
446 static int q6usb_component_probe(struct snd_soc_component *component)
447 {
448 ...
449 usb = snd_soc_usb_allocate_port(component, 1, &data->priv);
450 if (IS_ERR(usb))
451 return -ENOMEM;
452
453 usb->connection_status_cb = q6usb_alsa_connection_cb;
454 usb->update_offload_route_info = q6usb_get_offload_dev;
455
456 ret = snd_soc_usb_add_port(usb);
457..
458
459Existing USB Sound Kcontrol
460---------------------------
461With the introduction of USB offload support, the above USB offload kcontrol
462will be added to the pre existing list of kcontrols identified by the USB sound
463framework. These kcontrols are still the main controls that are used to
464modify characteristics pertaining to the USB audio device.
465
466 ::
467
468 Number of controls: 9
469 ctl type num name value
470 0 INT 2 Capture Channel Map 0, 0 (range 0->36)
471 1 INT 2 Playback Channel Map 0, 0 (range 0->36)
472 2 BOOL 1 Headset Capture Switch On
473 3 INT 1 Headset Capture Volume 10 (range 0->13)
474 4 BOOL 1 Sidetone Playback Switch On
475 5 INT 1 Sidetone Playback Volume 4096 (range 0->8192)
476 6 BOOL 1 Headset Playback Switch On
477 7 INT 2 Headset Playback Volume 20, 20 (range 0->24)
478 8 INT 1 USB Offload Playback Card Route PCM#0 0 (range -1->32)
479 9 INT 1 USB Offload Playback PCM Route PCM#0 1 (range -1->255)
480
481Since USB audio device controls are handled over the USB control endpoint, use the
482existing mechanisms present in the USB mixer to set parameters, such as volume.