← Documents Documentation/sound/soc/usb.rst GitHub 원문 ↗

Linux 6.18.37 · Sound / ASoC

ASoC USB 지원

ALSA USB SND와 ASoC가 USB 오디오 오프로딩 구성 정보를 교환하는 구조를 설명합니다. `snd_soc_usb`·`snd_soc_usb_device`, 연결·형식·포트·route API, BE DAI 등록과 hotplug 재발견, card/PCM route kcontrol을 원문 코드와 482개 줄 좌표를 보존해 정리합니다. 원문 예제의 route 값 설명에는 PCM 인덱스 표기상 불일치가 있어 번역에서는 문장을 보존하고 표에서는 실제 출력값 1을 그대로 제시합니다.

Source pathDocumentation/sound/soc/usb.rst
Source versionLinux v6.18.37
TranslationDUJINLABS 전문 번역 + 해설

요약·해설과 원문, 전문 번역을 서로 분리했습니다. API 이름, symbol, source path는 원문 표기를 사용합니다.

1. 요약·해설

원문의 핵심 논리와 kernel programming 관점의 보충 설명입니다. 아래의 전문 번역과는 별도로 작성했습니다.

요약·해설

usb.rst:1-482

ALSA USB SND와 ASoC가 USB 오디오 오프로딩 구성 정보를 교환하는 구조를 설명합니다. `snd_soc_usb`·`snd_soc_usb_device`, 연결·형식·포트·route API, BE DAI 등록과 hotplug 재발견, card/PCM route kcontrol을 원문 코드와 482개 줄 좌표를 보존해 정리합니다. 원문 예제의 route 값 설명에는 PCM 인덱스 표기상 불일치가 있어 번역에서는 문장을 보존하고 표에서는 실제 출력값 1을 그대로 제시합니다.

2. 영어 원문 전체

번역 기준이 된 Linux v6.18.37 원문입니다. 줄 번호는 이 버전의 파일 좌표입니다.

원문 전체 펼치기
1 ================
2 ASoC USB support
3 ================
4
5 Overview
6 ========
7 In order to leverage the existing USB sound device support in ALSA, the
8 ASoC USB APIs are introduced to allow the subsystems to exchange
9 configuration information.
10
11 One potential use case would be to support USB audio offloading, which is
12 an implementation that allows for an alternate power-optimized path in the audio
13 subsystem to handle the transfer of audio data over the USB bus. This would
14 let the main processor to stay in lower power modes for longer duration. The
15 following is an example design of how the ASoC and ALSA pieces can be connected
16 together 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
49 SoC USB driver
50 ==============
51 Structures
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
62 The snd_soc_usb structure can be referenced using the ASoC platform card
63 device, or a USB device (udev->dev). This is created by the ASoC BE DAI
64 link, and the USB sound entity will be able to pass information to the
65 ASoC 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
77 The struct snd_soc_usb_device is created by the USB sound offload driver.
78 This will carry basic parameters/limitations that will be used to
79 determine the possible offloading paths for this USB audio device.
80
81 Functions
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
94 being requested by the external DSP is supported by the USB device.
95
96 Returns 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
107 audio device detection. This can be utilized in the BE DAI
108 driver to keep track of available USB audio devices. This is intended
109 to be called by the USB offload driver residing in USB SND.
110
111 Returns 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
122 audio device removal. This is intended to be called by the USB offload
123 driver 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
133 device.
134
135 Returns 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
147 the platform sound card. This will allow for consistent naming to be used on
148 designs that support USB audio offloading. Additionally, this will enable the
149 jack to notify of changes.
150
151 Returns 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
171 link to fetch the information about the mapped ASoC devices for executing USB audio
172 offload for the device. ``route`` may be a pointer to a kcontrol value output array,
173 which carries values when the kcontrol is read.
174
175 Returns 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
187 parameters that is used for further operations.
188
189 Returns 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.
208 Once 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.
218 After removing a device, any SOC USB operations would not be able to reference the
219 device removed.
220
221 How to Register to SoC USB
222 --------------------------
223 The ASoC DPCM USB BE DAI link is the entity responsible for allocating and
224 registering the SoC USB device on the component bind. Likewise, it will
225 also be responsible for freeing the allocated resources. An example can
226 be 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
262 BE DAI links can pass along vendor specific information as part of the
263 call to allocate the SoC USB device. This will allow any BE DAI link
264 parameters or settings to be accessed by the USB offload driver that
265 resides in USB SND.
266
267 USB Audio Device Connection Flow
268 --------------------------------
269 USB devices can be hotplugged into the USB ports at any point in time.
270 The BE DAI link should be aware of the current state of the physical USB
271 port, i.e. if there are any USB devices with audio interface(s) connected.
272 connection_status_cb() can be used to notify the BE DAI link of any change.
273
274 This is called whenever there is a USB SND interface bind or remove event,
275 using 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
294 In order to account for conditions where driver or device existence is
295 not guaranteed, USB SND exposes snd_usb_rediscover_devices() to resend the
296 connect events for any identified USB audio interfaces. Consider the
297 the 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
308 To ensure connection events are not missed, **snd_usb_rediscover_devices()**
309 is executed when the SoC USB device is registered. Now, when the BE DAI
310 link 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
320 In the case where the USB offload driver is unbound, while USB SND is ready,
321 the **snd_usb_rediscover_devices()** is called during module init. This allows
322 for 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
337 USB Offload Related Kcontrols
338 =============================
339 Details
340 -------
341 A set of kcontrols can be utilized by applications to help select the proper sound
342 devices to enable USB audio offloading. SoC USB exposes the get_offload_dev()
343 callback that designs can use to ensure that the proper indices are returned to the
344 application.
345
346 Implementation
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
395 The 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
397 the available kcontrols for each USB audio device, the following kcontrols lists
398 the 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
404 The kcontrol is indexed, because a USB audio device could potentially have
405 several 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
423 USB Offload Playback Route Kcontrol
424 -----------------------------------
425 In order to allow for vendor specific implementations on audio offloading device
426 selection, 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
436 These are specific for the **USB Offload Playback Card Route PCM#** and **USB
437 Offload PCM Route PCM#** kcontrols.
438
439 When users issue get calls to the kcontrol, the registered SoC USB callbacks will
440 execute 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
459 Existing USB Sound Kcontrol
460 ---------------------------
461 With the introduction of USB offload support, the above USB offload kcontrol
462 will be added to the pre existing list of kcontrols identified by the USB sound
463 framework. These kcontrols are still the main controls that are used to
464 modify 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
481 Since USB audio device controls are handled over the USB control endpoint, use the
482 existing mechanisms present in the USB mixer to set parameters, such as volume.
483

3. 한국어 전문 번역

영어 원문의 문단 순서와 의미를 유지한 전체 번역입니다. 코드, 함수명, symbol과 URL은 원문 표기를 유지합니다.

개요와 USB 오디오 오프로딩 경로

1-48

ALSA에 이미 존재하는 USB 사운드 장치 지원을 활용하기 위해 ASoC USB API가 도입되었다. 이 API를 통해 ALSA USB 사운드 하위 시스템과 ASoC 하위 시스템이 구성 정보를 서로 교환할 수 있다.

가능한 사용 사례 중 하나는 USB 오디오 오프로딩이다. 오디오 하위 시스템에 전력 효율을 높인 대체 경로를 마련해 USB 버스의 오디오 데이터 전송을 처리하는 구현이며, 주 프로세서가 더 오랫동안 저전력 모드에 머물 수 있게 한다.

원문의 예제 설계에서는 USB SND의 `card.c`, 오프로딩 드라이버, `endpoint.c`, XHCI HCD가 USB 쪽을 구성한다. ASoC 쪽에는 플랫폼 카드, BE·FE DAI link, SoC-USB 구성 요소, IPC와 audio DSP가 있으며, 양쪽은 USB 사운드 오프로딩 드라이버와 SoC-USB 사이에서 연결된다.

USB와 ASoC의 구성 요소
영역구성 요소역할
USB SNDcard.c / endpoint.cUSB 사운드 카드와 endpoint 관리
USB offloadUSBSND offldUSB SND와 SoC-USB 사이의 오프로딩 연동
USB hostXHCI HCDUSB 전송을 담당하는 호스트 컨트롤러
ASoC platformPlatform card / BE·FE DAI linkASoC 스트림과 back-end·front-end 연결
ASoC USBSoC-USBUSB 장치 정보와 ASoC 경로 교환
DSPIPC / audio DSP저전력 오디오 처리 경로

원문 ASCII 아키텍처를 책임 영역별로 정리한다.

USB 오디오 오프로딩 전체 경로
USB sound deviceXHCI HCDUSB SND endpoint.cUSBSND offloadSoC-USBASoC BE DAI link
ASoC FE DAI linkIPCaudio DSPASoC BE DAI link
USB SND card.cUSBSND offloadSoC-USB

ASCII 그림의 데이터·제어 연결을 깨끗한 흐름으로 다시 나타낸다.

전력 절감 목표
USB audio streamPower-optimized offload pathAudio DSPMain processor remains in low-power mode longer

USB 데이터 처리를 대체 오디오 경로로 옮겨 주 프로세서의 활성 시간을 줄인다.

================
ASoC USB support
================

Overview
========
In order to leverage the existing USB sound device support in ALSA, the
ASoC USB APIs are introduced to allow the subsystems to exchange
configuration information.

One potential use case would be to support USB audio offloading, which is
an implementation that allows for an alternate power-optimized path in the audio
subsystem to handle the transfer of audio data over the USB bus.  This would
let the main processor to stay in lower power modes for longer duration.  The
following is an example design of how the ASoC and ALSA pieces can be connected
together to achieve this:

::

               USB                   |            ASoC
                                     |  _________________________
                                     | |   ASoC Platform card    |
                                     | |_________________________|
                                     |         |           |
                                     |      ___V____   ____V____
                                     |     |ASoC BE | |ASoC FE  |
                                     |     |DAI LNK | |DAI LNK  |
                                     |     |________| |_________|
                                     |         ^  ^        ^
                                     |         |  |________|
                                     |      ___V____    |
                                     |     |SoC-USB |   |
     ________       ________               |        |   |
    |USB SND |<--->|USBSND  |<------------>|________|   |
    |(card.c)|     |offld   |<----------                |
    |________|     |________|___     | |                |
        ^               ^       |    | |    ____________V_________
        |               |       |    | |   |IPC                   |
     __ V_______________V_____  |    | |   |______________________|
    |USB SND (endpoint.c)     | |    | |              ^
    |_________________________| |    | |              |
                ^               |    | |   ___________V___________
                |               |    | |->|audio DSP              |
     ___________V_____________  |    |    |_______________________|
    |XHCI HCD                 |<-    |
    |_________________________|      |

SoC USB 드라이버 구조체

49-80

`struct snd_soc_usb`는 SoC USB 포트와 ASoC 구성 요소의 연결 상태를 나타낸다. `list`는 SND SoC 구조체 목록의 list head이고, `component`는 ASoC component 참조이며, `connection_status_cb`는 연결 이벤트를 알리는 콜백이다. `update_offload_route_info`는 선택된 USB 사운드 카드와 PCM 장치를 가져오는 콜백이고, `priv_data`는 드라이버 전용 데이터다.

struct snd_soc_usb 필드
필드의미
listSND SoC 구조체 목록의 list head
componentASoC component 참조
connection_status_cbUSB 오디오 연결·해제 이벤트 통지
update_offload_route_info선택된 USB 카드·PCM의 ASoC 오프로딩 매핑 조회
priv_data드라이버 전용 데이터

ASoC와 USB SND 사이의 포트 상태 및 콜백을 담는다.

`snd_soc_usb` 구조체는 ASoC 플랫폼 카드 장치나 USB 장치인 `udev->dev`를 사용해 참조할 수 있다. ASoC BE DAI link가 이 구조체를 만들며, USB 사운드 엔터티는 이 구조체를 통해 ASoC BE DAI link에 정보를 전달할 수 있다.

`struct snd_soc_usb_device`는 USB 사운드 오프로딩 드라이버가 만드는 장치 능력 설명이다. `card_idx`는 연결된 USB 사운드 장치의 카드 인덱스, `chip_idx`는 USB sound chip 배열 인덱스, `cpcm_idx`와 `ppcm_idx`는 각각 캡처와 재생 PCM 장치 인덱스다. `num_playback`과 `num_capture`는 재생·캡처 스트림 수이며, `list`는 USB 사운드 장치 목록의 list head다.

struct snd_soc_usb_device 필드
필드의미
card_idxUSB 사운드 장치와 연결된 사운드 카드 인덱스
chip_idxUSB sound chip 배열 인덱스
cpcm_idx연결된 캡처 PCM 장치 인덱스
ppcm_idx연결된 재생 PCM 장치 인덱스
num_playback재생 스트림 수
num_capture캡처 스트림 수
listUSB 사운드 장치 목록의 list head

USB 오디오 장치의 기본 인덱스와 스트림 한계를 전달한다.

이 구조체가 전달하는 기본 매개변수와 제한은 해당 USB 오디오 장치에서 가능한 오프로딩 경로를 결정하는 데 사용된다.

구조체를 통한 정보 교환
ASoC BE DAI linkcreate snd_soc_usbConnection and route callbacks
USB sound offload drivercreate snd_soc_usb_deviceCapabilities and limitations
snd_soc_usb_devicesnd_soc_usb callbacksASoC BE DAI link

BE DAI link가 포트를 만들고 USB offload driver가 장치 능력을 채운다.

SoC USB driver
==============
Structures
----------
``struct snd_soc_usb``

  - ``list``: list head for SND SoC struct list
  - ``component``: reference to ASoC component
  - ``connection_status_cb``: callback to notify connection events
  - ``update_offload_route_info``: callback to fetch selected USB sound card/PCM
    device
  - ``priv_data``: driver data

The snd_soc_usb structure can be referenced using the ASoC platform card
device, or a USB device (udev->dev).  This is created by the ASoC BE DAI
link, and the USB sound entity will be able to pass information to the
ASoC BE DAI link using this structure.

``struct snd_soc_usb_device``

  - ``card_idx``: sound card index associated with USB sound device
  - ``chip_idx``: USB sound chip array index
  - ``cpcm_idx``: capture pcm device indexes associated with the USB sound device
  - ``ppcm_idx``: playback pcm device indexes associated with the USB sound device
  - ``num_playback``: number of playback streams
  - ``num_capture``: number of capture streams
  - ``list``: list head for the USB sound device list

The struct snd_soc_usb_device is created by the USB sound offload driver.
This will carry basic parameters/limitations that will be used to
determine the possible offloading paths for this USB audio device.

SoC USB API 함수

81-220

`snd_soc_usb_find_supported_format(int card_idx, struct snd_pcm_hw_params *params, int direction)`은 외부 DSP가 요청한 오디오 프로필을 USB 장치가 지원하는지 확인한다. `card_idx`는 USB sound chip 배열 인덱스, `params`는 USB DPCM BE DAI link가 요청한 PCM 매개변수, `direction`은 캡처 또는 재생 방향이다. 성공하면 0, 실패하면 `-EOPNOTSUPP`를 반환한다.

snd_soc_usb_find_supported_format
항목내용
card_idxUSB sound chip 배열 인덱스
paramsUSB DPCM BE DAI link가 요청한 PCM 매개변수
direction캡처 또는 재생
반환성공 0, 미지원 -EOPNOTSUPP

요청 형식과 USB 장치 능력을 대조한다.

`snd_soc_usb_connect(struct device *usbdev, struct snd_soc_usb_device *sdev)`는 USB 오디오 장치가 감지되었음을 ASoC USB DCPM BE DAI link에 알린다. `usbdev`는 발견된 USB 장치이고 `sdev`는 그 장치의 능력이다. BE DAI 드라이버는 이를 사용해 사용 가능한 USB 오디오 장치를 추적할 수 있다. USB SND 안의 USB offload driver가 호출하도록 설계되었으며, 성공하면 0, 실패하면 음수 오류 코드를 반환한다.

`snd_soc_usb_disconnect(struct device *usbdev, struct snd_soc_usb_device *sdev)`는 USB 오디오 장치가 제거되었음을 ASoC USB DCPM BE DAI link에 알린다. `usbdev`는 제거된 USB 장치이고 `sdev`는 해제할 장치 능력이다. 이 함수 역시 USB SND에 있는 USB offload driver가 호출한다.

USB 장치 연결 수명 주기
USB device discoveredsnd_soc_usb_connect()ASoC USB BE DAI linkDevice available
USB device removedsnd_soc_usb_disconnect()ASoC USB BE DAI linkDevice unavailable

USB offload driver가 감지·제거 이벤트를 ASoC BE DAI link로 전달한다.

`snd_soc_usb_find_priv_data(struct device *usbdev)`는 지정한 USB 장치로 SoC USB 장치를 찾아 그곳에 저장된 private data를 가져온다. `usbdev`가 검색 기준이며, 성공하면 `priv_data` 포인터를, 실패하면 `NULL`을 반환한다.

`snd_soc_usb_setup_offload_jack(struct snd_soc_component *component, struct snd_soc_jack *jack)`은 플랫폼 사운드 카드에 sound jack control을 추가하는 helper다. `component`는 jack을 추가할 ASoC component이고 `jack`은 채울 jack component다. USB 오디오 오프로딩을 지원하는 설계에서 일관된 이름을 사용하게 하며 jack 상태 변경 통지도 가능하게 한다. 성공하면 0, 실패하면 음수를 반환한다.

private data와 offload jack helper
함수입력결과
snd_soc_usb_find_priv_datausbdevpriv_data 포인터 또는 NULL
snd_soc_usb_setup_offload_jackcomponent, jackjack control 등록 및 변경 통지, 성공 0

장치별 상태 조회와 일관된 jack 제어 등록을 제공한다.

`snd_soc_usb_update_offload_route(struct device *dev, int card, int pcm, int direction, enum snd_soc_usb_kctl path, long *route)`는 등록된 USB BE DAI link 콜백을 호출해 특정 USB 장치의 오디오 오프로딩에 매핑된 ASoC 장치 정보를 가져온다. `dev`는 매핑을 찾을 USB 장치, `card`와 `pcm`은 USB 사운드 카드와 PCM 장치 인덱스, `direction`은 조회 방향, `path`는 PCM 장치 또는 카드 인덱스를 선택하는 kcontrol selector다.

`route`는 오프로딩 경로의 사운드 카드와 PCM 인덱스를 그 순서로 담는 정수 두 개짜리 배열이다. kcontrol 출력 배열로 사용할 수 있으며 kcontrol을 읽을 때 값이 채워진다. 함수는 성공하면 0, 실패하면 음수를 반환한다.

snd_soc_usb_update_offload_route 인수
인수의미
dev오프로딩 경로 매핑을 찾을 USB 장치
cardUSB 사운드 카드 인덱스
pcmUSB 사운드 PCM 장치 인덱스
direction오프로딩 라우팅 정보를 조회할 방향
pathPCM 장치 또는 카드 인덱스를 선택하는 kcontrol selector
routeASoC 카드, PCM 인덱스를 순서대로 담는 두 정수 배열

USB 장치와 ASoC 오프로딩 경로 사이의 카드·PCM 매핑을 조회한다.

`snd_soc_usb_allocate_port(struct snd_soc_component *component, void *data)`는 SoC USB 장치를 할당하고 이후 연산에 쓰이는 표준 매개변수를 채운다. `component`는 DPCM BE DAI link component이고 `data`는 private data다. 성공하면 `struct soc_usb` 포인터를, 오류 시 음수 오류 값을 반환한다.

`snd_soc_usb_free_port(struct snd_soc_usb *usb)`는 지정한 SoC USB 장치를 해제한다. `snd_soc_usb_add_port(struct snd_soc_usb *usb)`는 할당된 장치를 SOC USB framework에 추가하며, 추가된 뒤에는 다른 연산이 이 장치를 참조할 수 있다.

`snd_soc_usb_remove_port(struct snd_soc_usb *usb)`는 SoC USB 장치를 framework에서 제거한다. 제거 뒤에는 어떤 SOC USB 연산도 해당 장치를 참조할 수 없다.

SoC USB 포트 수명 주기
snd_soc_usb_allocate_port()Populate callbacks and private datasnd_soc_usb_add_port()Port available to operations
Port available to operationssnd_soc_usb_remove_port()snd_soc_usb_free_port()

할당·등록과 제거·해제를 짝으로 수행한다.

SoC USB API 반환 규약
함수성공실패
find_supported_format0-EOPNOTSUPP
connect0음수 오류 코드
find_priv_datapriv_data 포인터NULL
setup_offload_jack0음수
update_offload_route0음수
allocate_portstruct soc_usb 포인터음수 오류 값

원문에 명시된 성공과 실패 반환을 한눈에 정리한다.

Functions
---------
.. code-block:: rst

	int snd_soc_usb_find_supported_format(int card_idx,
			struct snd_pcm_hw_params *params, int direction)
..

  - ``card_idx``: the index into the USB sound chip array.
  - ``params``: Requested PCM parameters from the USB DPCM BE DAI link
  - ``direction``: capture or playback

**snd_soc_usb_find_supported_format()** ensures that the requested audio profile
being requested by the external DSP is supported by the USB device.

Returns 0 on success, and -EOPNOTSUPP on failure.

.. code-block:: rst

	int snd_soc_usb_connect(struct device *usbdev, struct snd_soc_usb_device *sdev)
..

  - ``usbdev``: the usb device that was discovered
  - ``sdev``: capabilities of the device

**snd_soc_usb_connect()** notifies the ASoC USB DCPM BE DAI link of a USB
audio device detection.  This can be utilized in the BE DAI
driver to keep track of available USB audio devices.  This is intended
to be called by the USB offload driver residing in USB SND.

Returns 0 on success, negative error code on failure.

.. code-block:: rst

	int snd_soc_usb_disconnect(struct device *usbdev, struct snd_soc_usb_device *sdev)
..

  - ``usbdev``: the usb device that was removed
  - ``sdev``: capabilities to free

**snd_soc_usb_disconnect()** notifies the ASoC USB DCPM BE DAI link of a USB
audio device removal.  This is intended to be called by the USB offload
driver that resides in USB SND.

.. code-block:: rst

	void *snd_soc_usb_find_priv_data(struct device *usbdev)
..

  - ``usbdev``: the usb device to reference to find private data

**snd_soc_usb_find_priv_data()** fetches the private data saved to the SoC USB
device.

Returns pointer to priv_data on success, NULL on failure.

.. code-block:: rst

	int snd_soc_usb_setup_offload_jack(struct snd_soc_component *component,
					struct snd_soc_jack *jack)
..

  - ``component``: ASoC component to add the jack
  - ``jack``: jack component to populate

**snd_soc_usb_setup_offload_jack()** is a helper to add a sound jack control to
the platform sound card.  This will allow for consistent naming to be used on
designs that support USB audio offloading.  Additionally, this will enable the
jack to notify of changes.

Returns 0 on success, negative otherwise.

.. code-block:: rst

	int snd_soc_usb_update_offload_route(struct device *dev, int card, int pcm,
					     int direction, enum snd_soc_usb_kctl path,
					     long *route)
..

  - ``dev``: USB device to look up offload path mapping
  - ``card``: USB sound card index
  - ``pcm``: USB sound PCM device index
  - ``direction``: direction to fetch offload routing information
  - ``path``: kcontrol selector - pcm device or card index
  - ``route``: mapping of sound card and pcm indexes for the offload path.  This is
	       an array of two integers that will carry the card and pcm device indexes
	       in that specific order.  This can be used as the array for the kcontrol
	       output.

**snd_soc_usb_update_offload_route()** calls a registered callback to the USB BE DAI
link to fetch the information about the mapped ASoC devices for executing USB audio
offload for the device. ``route`` may be a pointer to a kcontrol value output array,
which carries values when the kcontrol is read.

Returns 0 on success, negative otherwise.

.. code-block:: rst

	struct snd_soc_usb *snd_soc_usb_allocate_port(struct snd_soc_component *component,
			void *data);
..

  - ``component``: DPCM BE DAI link component
  - ``data``: private data

**snd_soc_usb_allocate_port()** allocates a SoC USB device and populates standard
parameters that is used for further operations.

Returns a pointer to struct soc_usb on success, negative on error.

.. code-block:: rst

	void snd_soc_usb_free_port(struct snd_soc_usb *usb);
..

  - ``usb``: SoC USB device to free

**snd_soc_usb_free_port()** frees a SoC USB device.

.. code-block:: rst

	void snd_soc_usb_add_port(struct snd_soc_usb *usb);
..

  - ``usb``: SoC USB device to add

**snd_soc_usb_add_port()** add an allocated SoC USB device to the SOC USB framework.
Once added, this device can be referenced by further operations.

.. code-block:: rst

	void snd_soc_usb_remove_port(struct snd_soc_usb *usb);
..

  - ``usb``: SoC USB device to remove

**snd_soc_usb_remove_port()** removes a SoC USB device from the SoC USB framework.
After removing a device, any SOC USB operations would not be able to reference the
device removed.

SoC USB 등록과 해제

221-266

ASoC DPCM USB BE DAI link는 component bind 때 SoC USB 장치를 할당하고 등록할 책임이 있다. 같은 link가 할당한 자원을 해제하는 책임도 진다.

예제의 `q6usb_component_probe()`는 `snd_soc_usb_allocate_port()`로 포트를 할당하고 실패 시 `-ENOMEM`을 반환한다. 이어 `connection_status_cb`에 `q6usb_alsa_connection_cb`를 지정하고 `snd_soc_usb_add_port()`로 포트를 등록한다. 등록 실패 시 오류를 기록하고 `free_usb` 정리 경로로 이동한다.

`q6usb_component_remove()`는 `snd_soc_usb_remove_port(data->usb)`로 framework에서 포트를 제거한 뒤 `snd_soc_usb_free_port(data->usb)`로 메모리를 해제한다. `q6usb_dai_component`는 이 probe와 remove callback, 이름 `q6usb-dai-component`를 `struct snd_soc_component_driver`에 연결한다.

component bind 등록 순서
q6usb_component_probesnd_soc_usb_allocate_portSet connection_status_cbsnd_soc_usb_add_portSoC USB port registered

BE DAI component가 포트를 만들고 콜백을 채운 뒤 framework에 공개한다.

component remove 해제 순서
q6usb_component_removesnd_soc_usb_remove_portsnd_soc_usb_free_port

참조 가능 상태를 먼저 제거한 다음 자원을 해제한다.

BE DAI link는 SoC USB 장치를 할당하는 호출에 vendor-specific 정보를 함께 전달할 수 있다. 그러면 USB SND 내부의 USB offload driver가 BE DAI link의 매개변수나 설정에 접근할 수 있다.

등록 주체의 책임
시점작업
component bind포트 할당, private data 전달, 콜백 설정, framework 등록
component removeframework 제거 후 할당 자원 해제

BE DAI link가 bind와 remove에서 수행할 작업을 짝지어 보여 준다.

How to Register to SoC USB
--------------------------
The ASoC DPCM USB BE DAI link is the entity responsible for allocating and
registering the SoC USB device on the component bind.  Likewise, it will
also be responsible for freeing the allocated resources.  An example can
be shown below:

.. code-block:: rst

	static int q6usb_component_probe(struct snd_soc_component *component)
	{
		...
		data->usb = snd_soc_usb_allocate_port(component, 1, &data->priv);
		if (!data->usb)
			return -ENOMEM;

		usb->connection_status_cb = q6usb_alsa_connection_cb;

		ret = snd_soc_usb_add_port(usb);
		if (ret < 0) {
			dev_err(component->dev, "failed to add usb port\n");
			goto free_usb;
		}
		...
	}

	static void q6usb_component_remove(struct snd_soc_component *component)
	{
		...
		snd_soc_usb_remove_port(data->usb);
		snd_soc_usb_free_port(data->usb);
	}

	static const struct snd_soc_component_driver q6usb_dai_component = {
		.probe = q6usb_component_probe,
		.remove = q6usb_component_remove,
		.name = "q6usb-dai-component",
		...
	};
..

BE DAI links can pass along vendor specific information as part of the
call to allocate the SoC USB device.  This will allow any BE DAI link
parameters or settings to be accessed by the USB offload driver that
resides in USB SND.

USB 오디오 장치 연결과 재발견 흐름

267-336

USB 장치는 언제든 USB 포트에 hotplug될 수 있다. 따라서 BE DAI link는 실제 USB 포트에 오디오 인터페이스를 가진 USB 장치가 연결되어 있는지 현재 상태를 알아야 한다. `connection_status_cb()`는 상태 변화를 BE DAI link에 알리는 데 사용된다.

USB SND 인터페이스 bind 또는 remove 이벤트가 생길 때 `snd_soc_usb_connect()` 또는 `snd_soc_usb_disconnect()`를 호출한다. 예제에서 `qc_usb_audio_offload_probe()`는 발견한 장치와 능력을 connect 함수에 전달하고, `qc_usb_audio_offload_disconnect()`는 제거되는 장치와 `sdev`를 disconnect 함수에 전달한다.

정상 hotplug 통지
USB SND interface bindqc_usb_audio_offload_probesnd_soc_usb_connectconnection_status_cbBE DAI link updated
USB SND interface removeqc_usb_audio_offload_disconnectsnd_soc_usb_disconnectconnection_status_cbBE DAI link updated

USB SND의 bind·remove 이벤트가 ASoC 포트 상태로 전파된다.

드라이버나 장치가 항상 존재한다고 보장할 수 없는 상황을 처리하기 위해 USB SND는 `snd_usb_rediscover_devices()`를 제공한다. 이 함수는 이미 식별된 모든 USB 오디오 인터페이스의 connect 이벤트를 다시 보낸다.

첫 번째 누락 시나리오에서는 `usb_audio_probe()`가 USB 오디오 스트림을 할당해 `usb_chip[]`에 저장하고 USB SND의 offload driver로 connect 이벤트를 전달하지만, USB BE DAI link가 아직 준비되지 않아 `snd_soc_usb_connect()`가 종료된다. 나중에 BE DAI link component가 probe되어 SoC USB 포트를 할당해도 앞선 connect 이벤트는 이미 놓친 상태다.

BE DAI 준비 전 이벤트 누락
usb_audio_probeStreams saved to usb_chip[]snd_soc_usb_connectBE DAI not readyConnect event missed
Later BE DAI component probeSoC USB port allocatedNo earlier event available

장치가 먼저 발견되면 최초 connect 통지를 받을 대상이 아직 없다.

이 누락을 막기 위해 SoC USB 장치를 등록할 때 `snd_usb_rediscover_devices()`를 실행한다. BE DAI link가 probe되고 포트가 할당·추가되면 rediscover 함수가 `usb_chip[]`를 순회하고 `NULL`이 아닌 각 항목에 대해 `connection_status_cb()`를 호출한다.

포트 등록 시 재발견
BE DAI component probeAllocate and add SoC USB portsnd_usb_rediscover_devicesTraverse usb_chip[]connection_status_cb for non-NULL entries

새로 준비된 BE DAI link에 기존 USB 장치를 다시 통지한다.

USB SND는 준비되어 있지만 USB offload driver가 unbind된 경우에는 module init 중 `snd_usb_rediscover_devices()`가 호출된다. `usb_audio_probe()`가 스트림을 저장하고 이벤트를 전달하려 해도 offload driver가 준비되지 않았고, BE DAI link probe에서도 driver가 없어 connect 이벤트를 받을 수 없다. 이후 USB offload driver가 probe되면 `qc_usb_audio_offload_init()`이 rediscover 함수를 호출해 이미 존재하는 장치를 통지한다.

offload driver 지연 로드 복구
usb_audio_probeStreams savedUSB offload driver not ready
BE DAI component probeSoC USB port allocatedNo connect event without offload driver
USB offload driver probeqc_usb_audio_offload_initsnd_usb_rediscover_devicesNotify existing devices

offload driver가 나중에 준비되어도 기존 USB 장치로 오프로딩 경로를 활성화한다.

재발견이 필요한 두 준비 순서
먼저 준비된 항목나중에 준비된 항목복구 시점
USB audio deviceBE DAI linkSoC USB 포트 등록 때 rediscover
USB SND와 BE DAI linkUSB offload driveroffload driver module init 때 rediscover

장치·BE DAI·offload driver의 초기화 순서가 달라도 상태를 복구한다.

USB Audio Device Connection Flow
--------------------------------
USB devices can be hotplugged into the USB ports at any point in time.
The BE DAI link should be aware of the current state of the physical USB
port, i.e. if there are any USB devices with audio interface(s) connected.
connection_status_cb() can be used to notify the BE DAI link of any change.

This is called whenever there is a USB SND interface bind or remove event,
using snd_soc_usb_connect() or snd_soc_usb_disconnect():

.. code-block:: rst

	static void qc_usb_audio_offload_probe(struct snd_usb_audio *chip)
	{
		...
		snd_soc_usb_connect(usb_get_usb_backend(udev), sdev);
		...
	}

	static void qc_usb_audio_offload_disconnect(struct snd_usb_audio *chip)
	{
		...
		snd_soc_usb_disconnect(usb_get_usb_backend(chip->dev), dev->sdev);
		...
	}
..

In order to account for conditions where driver or device existence is
not guaranteed, USB SND exposes snd_usb_rediscover_devices() to resend the
connect events for any identified USB audio interfaces.  Consider the
the following situation:

	**usb_audio_probe()**
	  | --> USB audio streams allocated and saved to usb_chip[]
	  | --> Propagate connect event to USB offload driver in USB SND
	  | --> **snd_soc_usb_connect()** exits as USB BE DAI link is not ready

	BE DAI link component probe
	  | --> DAI link is probed and SoC USB port is allocated
	  | --> The USB audio device connect event is missed

To ensure connection events are not missed, **snd_usb_rediscover_devices()**
is executed when the SoC USB device is registered.  Now, when the BE DAI
link component probe occurs, the following highlights the sequence:

	BE DAI link component probe
	  | --> DAI link is probed and SoC USB port is allocated
	  | --> SoC USB device added, and **snd_usb_rediscover_devices()** runs

	**snd_usb_rediscover_devices()**
	  | --> Traverses through usb_chip[] and for non-NULL entries issue
	  |     **connection_status_cb()**

In the case where the USB offload driver is unbound, while USB SND is ready,
the **snd_usb_rediscover_devices()** is called during module init.  This allows
for the offloading path to also be enabled with the following flow:

	**usb_audio_probe()**
	  | --> USB audio streams allocated and saved to usb_chip[]
	  | --> Propagate connect event to USB offload driver in USB SND
	  | --> USB offload driver **NOT** ready!

	BE DAI link component probe
	  | --> DAI link is probed and SoC USB port is allocated
	  | --> No USB connect event due to missing USB offload driver

	USB offload driver probe
	  | --> **qc_usb_audio_offload_init()**
	  | --> Calls **snd_usb_rediscover_devices()** to notify of devices

USB 오프로딩 kcontrol 개요

337-345

응용 프로그램은 여러 kcontrol을 사용해 USB 오디오 오프로딩에 적합한 사운드 장치를 선택할 수 있다. SoC USB는 설계별 구현이 올바른 인덱스를 응용 프로그램에 반환하도록 `get_offload_dev()` 콜백을 노출한다.

kcontrol 장치 선택
Application reads offload kcontrolSoC USBget_offload_dev callbackMapped ASoC card and PCM indexes

응용 프로그램의 조회가 설계별 콜백을 거쳐 실제 ASoC 경로 인덱스로 변환된다.

USB Offload Related Kcontrols
=============================
Details
-------
A set of kcontrols can be utilized by applications to help select the proper sound
devices to enable USB audio offloading.  SoC USB exposes the get_offload_dev()
callback that designs can use to ensure that the proper indices are returned to the
application.

오프로딩 kcontrol 구현 예제

346-422

예제 시스템에는 ASoC 플랫폼 카드 하나와 USB 사운드 장치 두 개가 있다. 카드 0은 `SM8250MTPWCD938`, 카드 1은 `Plantronics Blackwire 3225 Seri`, 카드 2는 `Plantronics C320-M`이다. PCM 목록에는 플랫폼 카드의 `MultiMedia1` 장치 0과 `MultiMedia2` 장치 1, 각 USB 카드의 `USB Audio` 장치 0이 표시된다.

예제 사운드 카드와 PCM
카드종류PCM 장치
card 0ASoC SM8250 platformdevice 0 MultiMedia1, device 1 MultiMedia2
card 1USB Plantronics Blackwire 3225device 0 USB Audio
card 2USB Plantronics C320-Mdevice 0 USB Audio

원문 출력에서 오프로딩 매핑에 참여하는 카드와 PCM을 추린다.

USB 사운드 카드 1의 `USB Offload Playback Card Route PCM#0`과 `USB Offload Playback PCM Route PCM#0` 값은 모두 `-1`이므로 사용 가능한 오프로딩 경로가 없다. USB 사운드 카드 2의 같은 값은 각각 `0`과 `1`이므로 ASoC 플랫폼 카드 0과 PCM 인덱스 1에 매핑된다.

예제 오프로딩 매핑
USB 카드Card RoutePCM Route결과
card 1-1-1오프로딩 경로 없음
card 201ASoC card 0, PCM index 1로 매핑

각 USB 장치의 card route와 PCM route 값을 함께 해석한다.

각 USB 오디오 장치에서 읽는 `USB Offload Playback Card Route PCM#*`와 `USB Offload Playback PCM Route PCM#*` kcontrol은 특정 USB 장치에 매핑된 offload card와 PCM 장치 인덱스를 제공한다. USB 오디오 장치 하나가 여러 PCM 장치를 가질 수 있으므로 kcontrol 이름의 `#` 부분은 PCM별 인덱스다.

`USB Offload Playback Card Route PCM#` 읽기 전용 제어는 매핑된 오프로딩 경로의 ASoC 플랫폼 사운드 카드 인덱스를 반환한다. 값 `0`은 USB SND 장치가 card 0을 통해 사용할 수 있는 오프로딩 경로가 있음을 뜻하고, `-1`은 경로가 없음을 뜻한다. 시스템의 각 USB 오디오 장치마다 이 제어가 존재하며 PCM route 제어와 함께 읽어 현재 오프로딩 상태를 판단한다.

`USB Offload Playback PCM Route PCM#` 읽기 전용 제어는 매핑된 오프로딩 경로의 ASoC 플랫폼 PCM 장치 인덱스를 반환한다. 원문은 값 `1`이 PCM device 0을 통한 경로를 뜻한다고 설명하며, `-1`은 경로가 없음을 뜻한다. 이 제어도 각 USB 오디오 장치마다 존재하며 card route 제어와 함께 해석한다.

두 route kcontrol의 결합
USB Offload Playback Card Route PCM#ASoC card index
USB Offload Playback PCM Route PCM#ASoC PCM index
ASoC card indexCombined offload route
ASoC PCM indexCombined offload route

카드와 PCM 값이 모두 유효해야 실행 가능한 오프로딩 경로가 된다.

route 값 해석
의미
0 이상매핑된 ASoC card 또는 PCM 인덱스
-1해당 USB SND 장치에 사용 가능한 오프로딩 경로 없음

두 kcontrol에서 공통으로 사용하는 유효성 규칙이다.

Implementation
--------------

**Example:**

  **Sound Cards**:

	::

	  0 [SM8250MTPWCD938]: sm8250 - SM8250-MTP-WCD9380-WSA8810-VA-D
						SM8250-MTP-WCD9380-WSA8810-VA-DMIC
	  1 [Seri           ]: USB-Audio - Plantronics Blackwire 3225 Seri
						Plantronics Plantronics Blackwire
						3225 Seri at usb-xhci-hcd.1.auto-1.1,
						full sp
	  2 [C320M          ]: USB-Audio - Plantronics C320-M
                      Plantronics Plantronics C320-M at usb-xhci-hcd.1.auto-1.2, full speed

  **PCM Devices**:

	::

	  card 0: SM8250MTPWCD938 [SM8250-MTP-WCD9380-WSA8810-VA-D], device 0: MultiMedia1 (*) []
	  Subdevices: 1/1
	  Subdevice #0: subdevice #0
	  card 0: SM8250MTPWCD938 [SM8250-MTP-WCD9380-WSA8810-VA-D], device 1: MultiMedia2 (*) []
	  Subdevices: 1/1
	  Subdevice #0: subdevice #0
	  card 1: Seri [Plantronics Blackwire 3225 Seri], device 0: USB Audio [USB Audio]
	  Subdevices: 1/1
	  Subdevice #0: subdevice #0
	  card 2: C320M [Plantronics C320-M], device 0: USB Audio [USB Audio]
	  Subdevices: 1/1
	  Subdevice #0: subdevice #0

  **USB Sound Card** - card#1:

	::

	  USB Offload Playback Card Route PCM#0   -1 (range -1->32)
	  USB Offload Playback PCM Route PCM#0    -1 (range -1->255)

  **USB Sound Card** - card#2:

	::

	  USB Offload Playback Card Route PCM#0   0 (range -1->32)
	  USB Offload Playback PCM Route PCM#0    1 (range -1->255)

The above example shows a scenario where the system has one ASoC platform card
(card#0) and two USB sound devices connected (card#1 and card#2).  When reading
the available kcontrols for each USB audio device, the following kcontrols lists
the mapped offload card and pcm device indexes for the specific USB device:

	``USB Offload Playback Card Route PCM#*``

	``USB Offload Playback PCM Route PCM#*``

The kcontrol is indexed, because a USB audio device could potentially have
several PCM devices.  The above kcontrols are defined as:

  - ``USB Offload Playback Card Route PCM#`` **(R)**: Returns the ASoC platform sound
    card index for a mapped offload path.  The output **"0"** (card index) signifies
    that there is an available offload path for the USB SND device through card#0.
    If **"-1"** is seen, then no offload path is available for the USB SND device.
    This kcontrol exists for each USB audio device that exists in the system, and
    its expected to derive the current status of offload based on the output value
    for the kcontrol along with the PCM route kcontrol.

  - ``USB Offload Playback PCM Route PCM#`` **(R)**: Returns the ASoC platform sound
    PCM device index for a mapped offload path.  The output **"1"** (PCM device index)
    signifies that there is an available offload path for the USB SND device through
    PCM device#0. If **"-1"** is seen, then no offload path is available for the USB\
    SND device.  This kcontrol exists for each USB audio device that exists in the
    system, and its expected to derive the current status of offload based on the
    output value for this kcontrol, in addition to the card route kcontrol.

USB Offload Playback Route 콜백

423-458

오디오 오프로딩 장치 선택을 vendor-specific 방식으로 구현할 수 있도록 SoC USB 계층은 `update_offload_route_info` 콜백을 노출한다. 콜백은 `component`, USB `card`, USB `pcm`, 스트림 `direction`, 카드 또는 PCM 경로를 고르는 `path`, 결과를 넣을 `route`를 받는다.

이 콜백은 `USB Offload Playback Card Route PCM#`과 `USB Offload PCM Route PCM#` kcontrol 전용이다. 사용자가 kcontrol에 get 요청을 보내면 등록된 SoC USB callback이 DPCM BE DAI link의 등록 함수를 실행한다.

등록 예제에서 `q6usb_component_probe()`는 `snd_soc_usb_allocate_port()`로 포트를 할당한 뒤 `connection_status_cb`에 `q6usb_alsa_connection_cb`를, `update_offload_route_info`에 `q6usb_get_offload_dev`를 지정하고 `snd_soc_usb_add_port()`를 호출한다.

update_offload_route_info 콜백 인수
인수역할
componentDPCM BE DAI link component
card / pcm대상 USB 사운드 카드와 PCM 인덱스
direction재생 또는 캡처 방향
pathcard route 또는 PCM route kcontrol 선택
route계산된 매핑 값을 돌려줄 출력

DPCM BE DAI link가 vendor-specific 매핑을 계산하는 데 필요한 입력과 출력이다.

kcontrol get 호출 경로
Application kcontrol getSoC USB kcontrol callbackupdate_offload_route_infoq6usb_get_offload_devroute output

응용 프로그램의 읽기 요청이 BE DAI link의 설계별 함수로 전달된다.

USB Offload Playback Route Kcontrol
-----------------------------------
In order to allow for vendor specific implementations on audio offloading device
selection, the SoC USB layer exposes the following:

.. code-block:: rst

	int (*update_offload_route_info)(struct snd_soc_component *component,
					 int card, int pcm, int direction,
					 enum snd_soc_usb_kctl path,
					 long *route)
..

These are specific for the **USB Offload Playback Card Route PCM#** and **USB
Offload PCM Route PCM#** kcontrols.

When users issue get calls to the kcontrol, the registered SoC USB callbacks will
execute the registered function calls to the DPCM BE DAI link.

**Callback Registration:**

.. code-block:: rst

	static int q6usb_component_probe(struct snd_soc_component *component)
	{
	...
	usb = snd_soc_usb_allocate_port(component, 1, &data->priv);
	if (IS_ERR(usb))
		return -ENOMEM;

	usb->connection_status_cb = q6usb_alsa_connection_cb;
	usb->update_offload_route_info = q6usb_get_offload_dev;

	ret = snd_soc_usb_add_port(usb);
..

기존 USB Sound kcontrol과의 공존

459-482

USB 오프로딩 지원이 도입되면 앞에서 설명한 USB offload kcontrol이 USB sound framework가 이미 식별한 kcontrol 목록에 추가된다. 기존 제어들은 여전히 음량처럼 USB 오디오 장치의 특성을 바꾸는 주요 수단이다.

예제 목록에는 캡처·재생 채널 맵, 헤드셋 캡처 스위치와 음량, sidetone 재생 스위치와 음량, 헤드셋 재생 스위치와 음량이 있다. 여기에 `USB Offload Playback Card Route PCM#0` 값 0과 `USB Offload Playback PCM Route PCM#0` 값 1이 추가되어 총 목록에 오프로딩 매핑이 함께 표시된다.

기존 제어와 추가된 오프로딩 제어
기능군제어 예용도
채널 맵Capture / Playback Channel MapUSB 오디오 채널 배치
캡처Headset Capture Switch / Volume헤드셋 입력 활성화와 음량
SidetoneSidetone Playback Switch / Volume입력 신호 모니터 재생
재생Headset Playback Switch / Volume헤드셋 출력 활성화와 음량
오프로딩Card Route / PCM Route PCM#0ASoC 카드·PCM 경로 매핑 조회

원문 예제의 제어를 기능군별로 정리한다.

USB 오디오 장치 제어는 USB control endpoint를 통해 처리되므로 음량 같은 매개변수를 설정할 때는 USB mixer에 이미 존재하는 메커니즘을 사용한다.

제어 경로의 분담
Volume / switch / channel mapUSB mixerUSB control endpointUSB audio device
Offload route readSoC USB kcontrolDPCM BE DAI mapping

장치 특성 변경은 기존 USB mixer 경로를 유지하고 오프로딩 kcontrol은 경로 매핑을 제공한다.

Existing USB Sound Kcontrol
---------------------------
With the introduction of USB offload support, the above USB offload kcontrol
will be added to the pre existing list of kcontrols identified by the USB sound
framework.  These kcontrols are still the main controls that are used to
modify characteristics pertaining to the USB audio device.

	::

	  Number of controls: 9
	  ctl     type    num     name                                    value
	  0       INT     2       Capture Channel Map                     0, 0 (range 0->36)
	  1       INT     2       Playback Channel Map                    0, 0 (range 0->36)
	  2       BOOL    1       Headset Capture Switch                  On
	  3       INT     1       Headset Capture Volume                  10 (range 0->13)
	  4       BOOL    1       Sidetone Playback Switch                On
	  5       INT     1       Sidetone Playback Volume                4096 (range 0->8192)
	  6       BOOL    1       Headset Playback Switch                 On
	  7       INT     2       Headset Playback Volume                 20, 20 (range 0->24)
	  8       INT     1       USB Offload Playback Card Route PCM#0   0 (range -1->32)
	  9       INT     1       USB Offload Playback PCM Route PCM#0    1 (range -1->255)

Since USB audio device controls are handled over the USB control endpoint, use the
existing mechanisms present in the USB mixer to set parameters, such as volume.