1 // SPDX-License-Identifier: GPL-2.0-or-later
3 // Special handling for implicit feedback mode
6 #include <linux/init.h>
8 #include <linux/usb/audio.h>
9 #include <linux/usb/audio-v2.h>
11 #include <sound/core.h>
12 #include <sound/pcm.h>
13 #include <sound/pcm_params.h>
25 IMPLICIT_FB_BOTH
, /* generic playback + capture (for BOSS) */
28 struct snd_usb_implicit_fb_match
{
30 unsigned int iface_class
;
36 #define IMPLICIT_FB_GENERIC_DEV(vend, prod) \
37 { .id = USB_ID(vend, prod), .type = IMPLICIT_FB_GENERIC }
38 #define IMPLICIT_FB_FIXED_DEV(vend, prod, ep, ifnum) \
39 { .id = USB_ID(vend, prod), .type = IMPLICIT_FB_FIXED, .ep_num = (ep),\
41 #define IMPLICIT_FB_BOTH_DEV(vend, prod, ep, ifnum) \
42 { .id = USB_ID(vend, prod), .type = IMPLICIT_FB_BOTH, .ep_num = (ep),\
44 #define IMPLICIT_FB_SKIP_DEV(vend, prod) \
45 { .id = USB_ID(vend, prod), .type = IMPLICIT_FB_NONE }
47 /* Implicit feedback quirk table for playback */
48 static const struct snd_usb_implicit_fb_match playback_implicit_fb_quirks
[] = {
50 /* FIXME: check the availability of generic matching */
51 IMPLICIT_FB_FIXED_DEV(0x0763, 0x2030, 0x81, 3), /* M-Audio Fast Track C400 */
52 IMPLICIT_FB_FIXED_DEV(0x0763, 0x2031, 0x81, 3), /* M-Audio Fast Track C600 */
53 IMPLICIT_FB_FIXED_DEV(0x0763, 0x2080, 0x81, 2), /* M-Audio FastTrack Ultra */
54 IMPLICIT_FB_FIXED_DEV(0x0763, 0x2081, 0x81, 2), /* M-Audio FastTrack Ultra */
55 IMPLICIT_FB_FIXED_DEV(0x2466, 0x8010, 0x81, 2), /* Fractal Audio Axe-Fx III */
56 IMPLICIT_FB_FIXED_DEV(0x31e9, 0x0001, 0x81, 2), /* Solid State Logic SSL2 */
57 IMPLICIT_FB_FIXED_DEV(0x31e9, 0x0002, 0x81, 2), /* Solid State Logic SSL2+ */
58 IMPLICIT_FB_FIXED_DEV(0x0499, 0x172f, 0x81, 2), /* Steinberg UR22C */
59 IMPLICIT_FB_FIXED_DEV(0x0d9a, 0x00df, 0x81, 2), /* RTX6001 */
60 IMPLICIT_FB_FIXED_DEV(0x22f0, 0x0006, 0x81, 3), /* Allen&Heath Qu-16 */
61 IMPLICIT_FB_FIXED_DEV(0x1686, 0xf029, 0x82, 2), /* Zoom UAC-2 */
62 IMPLICIT_FB_FIXED_DEV(0x2466, 0x8003, 0x86, 2), /* Fractal Audio Axe-Fx II */
63 IMPLICIT_FB_FIXED_DEV(0x0499, 0x172a, 0x86, 2), /* Yamaha MODX */
65 /* Special matching */
66 { .id
= USB_ID(0x07fd, 0x0004), .iface_class
= USB_CLASS_AUDIO
,
67 .type
= IMPLICIT_FB_NONE
}, /* MicroBook IIc */
68 /* ep = 0x84, ifnum = 0 */
69 { .id
= USB_ID(0x07fd, 0x0004), .iface_class
= USB_CLASS_VENDOR_SPEC
,
70 .type
= IMPLICIT_FB_FIXED
,
71 .ep_num
= 0x84, .iface
= 0 }, /* MOTU MicroBook II */
76 /* Implicit feedback quirk table for capture: only FIXED type */
77 static const struct snd_usb_implicit_fb_match capture_implicit_fb_quirks
[] = {
81 /* set up sync EP information on the audioformat */
82 static int add_implicit_fb_sync_ep(struct snd_usb_audio
*chip
,
83 struct audioformat
*fmt
,
84 int ep
, int ep_idx
, int ifnum
,
85 const struct usb_host_interface
*alts
)
87 struct usb_interface
*iface
;
90 iface
= usb_ifnum_to_if(chip
->dev
, ifnum
);
91 if (!iface
|| iface
->num_altsetting
< 2)
93 alts
= &iface
->altsetting
[1];
97 fmt
->sync_iface
= ifnum
;
98 fmt
->sync_altsetting
= alts
->desc
.bAlternateSetting
;
99 fmt
->sync_ep_idx
= ep_idx
;
100 fmt
->implicit_fb
= 1;
102 "%d:%d: added %s implicit_fb sync_ep %x, iface %d:%d\n",
103 fmt
->iface
, fmt
->altsetting
,
104 (ep
& USB_DIR_IN
) ? "playback" : "capture",
105 fmt
->sync_ep
, fmt
->sync_iface
, fmt
->sync_altsetting
);
109 /* Check whether the given UAC2 iface:altset points to an implicit fb source */
110 static int add_generic_uac2_implicit_fb(struct snd_usb_audio
*chip
,
111 struct audioformat
*fmt
,
113 unsigned int altsetting
)
115 struct usb_host_interface
*alts
;
116 struct usb_endpoint_descriptor
*epd
;
118 alts
= snd_usb_get_host_interface(chip
, ifnum
, altsetting
);
121 if (alts
->desc
.bInterfaceClass
!= USB_CLASS_AUDIO
||
122 alts
->desc
.bInterfaceSubClass
!= USB_SUBCLASS_AUDIOSTREAMING
||
123 alts
->desc
.bInterfaceProtocol
!= UAC_VERSION_2
||
124 alts
->desc
.bNumEndpoints
< 1)
126 epd
= get_endpoint(alts
, 0);
127 if (!usb_endpoint_is_isoc_in(epd
) ||
128 (epd
->bmAttributes
& USB_ENDPOINT_USAGE_MASK
) !=
129 USB_ENDPOINT_USAGE_IMPLICIT_FB
)
131 return add_implicit_fb_sync_ep(chip
, fmt
, epd
->bEndpointAddress
, 0,
135 static bool roland_sanity_check_iface(struct usb_host_interface
*alts
)
137 if (alts
->desc
.bInterfaceClass
!= USB_CLASS_VENDOR_SPEC
||
138 (alts
->desc
.bInterfaceSubClass
!= 2 &&
139 alts
->desc
.bInterfaceProtocol
!= 2) ||
140 alts
->desc
.bNumEndpoints
< 1)
145 /* Like the UAC2 case above, but specific to Roland with vendor class and hack */
146 static int add_roland_implicit_fb(struct snd_usb_audio
*chip
,
147 struct audioformat
*fmt
,
148 struct usb_host_interface
*alts
)
150 struct usb_endpoint_descriptor
*epd
;
152 if (!roland_sanity_check_iface(alts
))
154 /* only when both streams are with ASYNC type */
155 epd
= get_endpoint(alts
, 0);
156 if (!usb_endpoint_is_isoc_out(epd
) ||
157 (epd
->bmAttributes
& USB_ENDPOINT_SYNCTYPE
) != USB_ENDPOINT_SYNC_ASYNC
)
160 /* check capture EP */
161 alts
= snd_usb_get_host_interface(chip
,
162 alts
->desc
.bInterfaceNumber
+ 1,
163 alts
->desc
.bAlternateSetting
);
164 if (!alts
|| !roland_sanity_check_iface(alts
))
166 epd
= get_endpoint(alts
, 0);
167 if (!usb_endpoint_is_isoc_in(epd
) ||
168 (epd
->bmAttributes
& USB_ENDPOINT_SYNCTYPE
) != USB_ENDPOINT_SYNC_ASYNC
)
170 chip
->quirk_flags
|= QUIRK_FLAG_PLAYBACK_FIRST
;
171 return add_implicit_fb_sync_ep(chip
, fmt
, epd
->bEndpointAddress
, 0,
172 alts
->desc
.bInterfaceNumber
, alts
);
175 /* capture quirk for Roland device; always full-duplex */
176 static int add_roland_capture_quirk(struct snd_usb_audio
*chip
,
177 struct audioformat
*fmt
,
178 struct usb_host_interface
*alts
)
180 struct usb_endpoint_descriptor
*epd
;
182 if (!roland_sanity_check_iface(alts
))
184 epd
= get_endpoint(alts
, 0);
185 if (!usb_endpoint_is_isoc_in(epd
) ||
186 (epd
->bmAttributes
& USB_ENDPOINT_SYNCTYPE
) != USB_ENDPOINT_SYNC_ASYNC
)
189 alts
= snd_usb_get_host_interface(chip
,
190 alts
->desc
.bInterfaceNumber
- 1,
191 alts
->desc
.bAlternateSetting
);
192 if (!alts
|| !roland_sanity_check_iface(alts
))
194 epd
= get_endpoint(alts
, 0);
195 if (!usb_endpoint_is_isoc_out(epd
))
197 return add_implicit_fb_sync_ep(chip
, fmt
, epd
->bEndpointAddress
, 0,
198 alts
->desc
.bInterfaceNumber
, alts
);
201 /* Playback and capture EPs on Pioneer devices share the same iface/altset
202 * for the implicit feedback operation
204 static bool is_pioneer_implicit_fb(struct snd_usb_audio
*chip
,
205 struct usb_host_interface
*alts
)
208 struct usb_endpoint_descriptor
*epd
;
210 if (USB_ID_VENDOR(chip
->usb_id
) != 0x2b73 &&
211 USB_ID_VENDOR(chip
->usb_id
) != 0x08e4)
213 if (alts
->desc
.bInterfaceClass
!= USB_CLASS_VENDOR_SPEC
)
215 if (alts
->desc
.bNumEndpoints
!= 2)
218 epd
= get_endpoint(alts
, 0);
219 if (!usb_endpoint_is_isoc_out(epd
) ||
220 (epd
->bmAttributes
& USB_ENDPOINT_SYNCTYPE
) != USB_ENDPOINT_SYNC_ASYNC
)
223 epd
= get_endpoint(alts
, 1);
224 if (!usb_endpoint_is_isoc_in(epd
) ||
225 (epd
->bmAttributes
& USB_ENDPOINT_SYNCTYPE
) != USB_ENDPOINT_SYNC_ASYNC
||
226 ((epd
->bmAttributes
& USB_ENDPOINT_USAGE_MASK
) !=
227 USB_ENDPOINT_USAGE_DATA
&&
228 (epd
->bmAttributes
& USB_ENDPOINT_USAGE_MASK
) !=
229 USB_ENDPOINT_USAGE_IMPLICIT_FB
))
235 static int __add_generic_implicit_fb(struct snd_usb_audio
*chip
,
236 struct audioformat
*fmt
,
237 int iface
, int altset
)
239 struct usb_host_interface
*alts
;
240 struct usb_endpoint_descriptor
*epd
;
242 alts
= snd_usb_get_host_interface(chip
, iface
, altset
);
246 if ((alts
->desc
.bInterfaceClass
!= USB_CLASS_VENDOR_SPEC
&&
247 alts
->desc
.bInterfaceClass
!= USB_CLASS_AUDIO
) ||
248 alts
->desc
.bNumEndpoints
< 1)
250 epd
= get_endpoint(alts
, 0);
251 if (!usb_endpoint_is_isoc_in(epd
) ||
252 (epd
->bmAttributes
& USB_ENDPOINT_SYNCTYPE
) != USB_ENDPOINT_SYNC_ASYNC
)
254 return add_implicit_fb_sync_ep(chip
, fmt
, epd
->bEndpointAddress
, 0,
258 /* More generic quirk: look for the sync EP next to the data EP */
259 static int add_generic_implicit_fb(struct snd_usb_audio
*chip
,
260 struct audioformat
*fmt
,
261 struct usb_host_interface
*alts
)
263 if ((fmt
->ep_attr
& USB_ENDPOINT_SYNCTYPE
) != USB_ENDPOINT_SYNC_ASYNC
)
266 if (__add_generic_implicit_fb(chip
, fmt
,
267 alts
->desc
.bInterfaceNumber
+ 1,
268 alts
->desc
.bAlternateSetting
))
270 return __add_generic_implicit_fb(chip
, fmt
,
271 alts
->desc
.bInterfaceNumber
- 1,
272 alts
->desc
.bAlternateSetting
);
275 static const struct snd_usb_implicit_fb_match
*
276 find_implicit_fb_entry(struct snd_usb_audio
*chip
,
277 const struct snd_usb_implicit_fb_match
*match
,
278 const struct usb_host_interface
*alts
)
280 for (; match
->id
; match
++)
281 if (match
->id
== chip
->usb_id
&&
282 (!match
->iface_class
||
283 (alts
->desc
.bInterfaceClass
== match
->iface_class
)))
289 /* Setup an implicit feedback endpoint from a quirk. Returns 0 if no quirk
290 * applies. Returns 1 if a quirk was found.
292 static int audioformat_implicit_fb_quirk(struct snd_usb_audio
*chip
,
293 struct audioformat
*fmt
,
294 struct usb_host_interface
*alts
)
296 const struct snd_usb_implicit_fb_match
*p
;
297 unsigned int attr
= fmt
->ep_attr
& USB_ENDPOINT_SYNCTYPE
;
299 p
= find_implicit_fb_entry(chip
, playback_implicit_fb_quirks
, alts
);
302 case IMPLICIT_FB_GENERIC
:
303 return add_generic_implicit_fb(chip
, fmt
, alts
);
304 case IMPLICIT_FB_NONE
:
305 return 0; /* No quirk */
306 case IMPLICIT_FB_FIXED
:
307 return add_implicit_fb_sync_ep(chip
, fmt
, p
->ep_num
, 0,
312 /* Special handling for devices with capture quirks */
313 p
= find_implicit_fb_entry(chip
, capture_implicit_fb_quirks
, alts
);
316 case IMPLICIT_FB_FIXED
:
317 return 0; /* no quirk */
318 case IMPLICIT_FB_BOTH
:
319 chip
->quirk_flags
|= QUIRK_FLAG_PLAYBACK_FIRST
;
320 return add_generic_implicit_fb(chip
, fmt
, alts
);
324 /* Generic UAC2 implicit feedback */
325 if (attr
== USB_ENDPOINT_SYNC_ASYNC
&&
326 alts
->desc
.bInterfaceClass
== USB_CLASS_AUDIO
&&
327 alts
->desc
.bInterfaceProtocol
== UAC_VERSION_2
&&
328 alts
->desc
.bNumEndpoints
== 1) {
329 if (add_generic_uac2_implicit_fb(chip
, fmt
,
330 alts
->desc
.bInterfaceNumber
+ 1,
331 alts
->desc
.bAlternateSetting
))
335 /* Roland/BOSS implicit feedback with vendor spec class */
336 if (USB_ID_VENDOR(chip
->usb_id
) == 0x0582) {
337 if (add_roland_implicit_fb(chip
, fmt
, alts
) > 0)
341 /* Pioneer devices with vendor spec class */
342 if (is_pioneer_implicit_fb(chip
, alts
)) {
343 chip
->quirk_flags
|= QUIRK_FLAG_PLAYBACK_FIRST
;
344 return add_implicit_fb_sync_ep(chip
, fmt
,
345 get_endpoint(alts
, 1)->bEndpointAddress
,
346 1, alts
->desc
.bInterfaceNumber
,
350 /* Try the generic implicit fb if available */
351 if (chip
->generic_implicit_fb
||
352 (chip
->quirk_flags
& QUIRK_FLAG_GENERIC_IMPLICIT_FB
))
353 return add_generic_implicit_fb(chip
, fmt
, alts
);
359 /* same for capture, but only handling FIXED entry */
360 static int audioformat_capture_quirk(struct snd_usb_audio
*chip
,
361 struct audioformat
*fmt
,
362 struct usb_host_interface
*alts
)
364 const struct snd_usb_implicit_fb_match
*p
;
366 p
= find_implicit_fb_entry(chip
, capture_implicit_fb_quirks
, alts
);
367 if (p
&& (p
->type
== IMPLICIT_FB_FIXED
|| p
->type
== IMPLICIT_FB_BOTH
))
368 return add_implicit_fb_sync_ep(chip
, fmt
, p
->ep_num
, 0,
371 /* Roland/BOSS need full-duplex streams */
372 if (USB_ID_VENDOR(chip
->usb_id
) == 0x0582) {
373 if (add_roland_capture_quirk(chip
, fmt
, alts
) > 0)
377 if (is_pioneer_implicit_fb(chip
, alts
))
378 return 1; /* skip the quirk, also don't handle generic sync EP */
383 * Parse altset and set up implicit feedback endpoint on the audioformat
385 int snd_usb_parse_implicit_fb_quirk(struct snd_usb_audio
*chip
,
386 struct audioformat
*fmt
,
387 struct usb_host_interface
*alts
)
389 if (chip
->quirk_flags
& QUIRK_FLAG_SKIP_IMPLICIT_FB
)
391 if (fmt
->endpoint
& USB_DIR_IN
)
392 return audioformat_capture_quirk(chip
, fmt
, alts
);
394 return audioformat_implicit_fb_quirk(chip
, fmt
, alts
);
398 * Return the score of matching two audioformats.
399 * Veto the audioformat if:
400 * - It has no channels for some reason.
401 * - Requested PCM format is not supported.
402 * - Requested sample rate is not supported.
404 static int match_endpoint_audioformats(struct snd_usb_substream
*subs
,
405 const struct audioformat
*fp
,
406 int rate
, int channels
,
407 snd_pcm_format_t pcm_format
)
411 if (fp
->channels
< 1)
414 if (!(fp
->formats
& pcm_format_to_bits(pcm_format
)))
417 if (fp
->rates
& SNDRV_PCM_RATE_CONTINUOUS
) {
418 if (rate
< fp
->rate_min
|| rate
> fp
->rate_max
)
421 for (i
= 0; i
< fp
->nr_rates
; i
++) {
422 if (fp
->rate_table
[i
] == rate
)
425 if (i
>= fp
->nr_rates
)
430 if (fp
->channels
== channels
)
436 static struct snd_usb_substream
*
437 find_matching_substream(struct snd_usb_audio
*chip
, int stream
, int ep_num
,
440 struct snd_usb_stream
*as
;
441 struct snd_usb_substream
*subs
;
443 list_for_each_entry(as
, &chip
->pcm_list
, list
) {
444 subs
= &as
->substream
[stream
];
445 if (as
->fmt_type
== fmt_type
&& subs
->ep_num
== ep_num
)
453 * Return the audioformat that is suitable for the implicit fb
455 const struct audioformat
*
456 snd_usb_find_implicit_fb_sync_format(struct snd_usb_audio
*chip
,
457 const struct audioformat
*target
,
458 const struct snd_pcm_hw_params
*params
,
462 struct snd_usb_substream
*subs
;
463 const struct audioformat
*fp
, *sync_fmt
= NULL
;
464 int score
, high_score
;
466 /* Use the original audioformat as fallback for the shared altset */
467 if (target
->iface
== target
->sync_iface
&&
468 target
->altsetting
== target
->sync_altsetting
)
471 subs
= find_matching_substream(chip
, stream
, target
->sync_ep
,
477 list_for_each_entry(fp
, &subs
->fmt_list
, list
) {
478 score
= match_endpoint_audioformats(subs
, fp
,
480 params_channels(params
),
481 params_format(params
));
482 if (score
> high_score
) {
490 *fixed_rate
= snd_usb_pcm_has_fixed_rate(subs
);