xref: /linux/Documentation/sound/soc/usb.rst (revision c0c9379f235df33a12ceae94370ad80c5278324d)
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.
483