Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 //
0003 // Special handling for implicit feedback mode
0004 //
0005 
0006 #include <linux/init.h>
0007 #include <linux/usb.h>
0008 #include <linux/usb/audio.h>
0009 #include <linux/usb/audio-v2.h>
0010 
0011 #include <sound/core.h>
0012 #include <sound/pcm.h>
0013 #include <sound/pcm_params.h>
0014 
0015 #include "usbaudio.h"
0016 #include "card.h"
0017 #include "helper.h"
0018 #include "implicit.h"
0019 
0020 enum {
0021     IMPLICIT_FB_NONE,
0022     IMPLICIT_FB_GENERIC,
0023     IMPLICIT_FB_FIXED,
0024     IMPLICIT_FB_BOTH,   /* generic playback + capture (for BOSS) */
0025 };
0026 
0027 struct snd_usb_implicit_fb_match {
0028     unsigned int id;
0029     unsigned int iface_class;
0030     unsigned int ep_num;
0031     unsigned int iface;
0032     int type;
0033 };
0034 
0035 #define IMPLICIT_FB_GENERIC_DEV(vend, prod) \
0036     { .id = USB_ID(vend, prod), .type = IMPLICIT_FB_GENERIC }
0037 #define IMPLICIT_FB_FIXED_DEV(vend, prod, ep, ifnum) \
0038     { .id = USB_ID(vend, prod), .type = IMPLICIT_FB_FIXED, .ep_num = (ep),\
0039         .iface = (ifnum) }
0040 #define IMPLICIT_FB_BOTH_DEV(vend, prod, ep, ifnum) \
0041     { .id = USB_ID(vend, prod), .type = IMPLICIT_FB_BOTH, .ep_num = (ep),\
0042         .iface = (ifnum) }
0043 #define IMPLICIT_FB_SKIP_DEV(vend, prod) \
0044     { .id = USB_ID(vend, prod), .type = IMPLICIT_FB_NONE }
0045 
0046 /* Implicit feedback quirk table for playback */
0047 static const struct snd_usb_implicit_fb_match playback_implicit_fb_quirks[] = {
0048     /* Fixed EP */
0049     /* FIXME: check the availability of generic matching */
0050     IMPLICIT_FB_FIXED_DEV(0x0763, 0x2080, 0x81, 2), /* M-Audio FastTrack Ultra */
0051     IMPLICIT_FB_FIXED_DEV(0x0763, 0x2081, 0x81, 2), /* M-Audio FastTrack Ultra */
0052     IMPLICIT_FB_FIXED_DEV(0x2466, 0x8010, 0x81, 2), /* Fractal Audio Axe-Fx III */
0053     IMPLICIT_FB_FIXED_DEV(0x31e9, 0x0001, 0x81, 2), /* Solid State Logic SSL2 */
0054     IMPLICIT_FB_FIXED_DEV(0x31e9, 0x0002, 0x81, 2), /* Solid State Logic SSL2+ */
0055     IMPLICIT_FB_FIXED_DEV(0x0499, 0x172f, 0x81, 2), /* Steinberg UR22C */
0056     IMPLICIT_FB_FIXED_DEV(0x0d9a, 0x00df, 0x81, 2), /* RTX6001 */
0057     IMPLICIT_FB_FIXED_DEV(0x22f0, 0x0006, 0x81, 3), /* Allen&Heath Qu-16 */
0058     IMPLICIT_FB_FIXED_DEV(0x1686, 0xf029, 0x82, 2), /* Zoom UAC-2 */
0059     IMPLICIT_FB_FIXED_DEV(0x2466, 0x8003, 0x86, 2), /* Fractal Audio Axe-Fx II */
0060     IMPLICIT_FB_FIXED_DEV(0x0499, 0x172a, 0x86, 2), /* Yamaha MODX */
0061 
0062     /* Special matching */
0063     { .id = USB_ID(0x07fd, 0x0004), .iface_class = USB_CLASS_AUDIO,
0064       .type = IMPLICIT_FB_NONE },       /* MicroBook IIc */
0065     /* ep = 0x84, ifnum = 0 */
0066     { .id = USB_ID(0x07fd, 0x0004), .iface_class = USB_CLASS_VENDOR_SPEC,
0067       .type = IMPLICIT_FB_FIXED,
0068       .ep_num = 0x84, .iface = 0 },     /* MOTU MicroBook II */
0069 
0070     {} /* terminator */
0071 };
0072 
0073 /* Implicit feedback quirk table for capture: only FIXED type */
0074 static const struct snd_usb_implicit_fb_match capture_implicit_fb_quirks[] = {
0075     {} /* terminator */
0076 };
0077 
0078 /* set up sync EP information on the audioformat */
0079 static int add_implicit_fb_sync_ep(struct snd_usb_audio *chip,
0080                    struct audioformat *fmt,
0081                    int ep, int ep_idx, int ifnum,
0082                    const struct usb_host_interface *alts)
0083 {
0084     struct usb_interface *iface;
0085 
0086     if (!alts) {
0087         iface = usb_ifnum_to_if(chip->dev, ifnum);
0088         if (!iface || iface->num_altsetting < 2)
0089             return 0;
0090         alts = &iface->altsetting[1];
0091     }
0092 
0093     fmt->sync_ep = ep;
0094     fmt->sync_iface = ifnum;
0095     fmt->sync_altsetting = alts->desc.bAlternateSetting;
0096     fmt->sync_ep_idx = ep_idx;
0097     fmt->implicit_fb = 1;
0098     usb_audio_dbg(chip,
0099               "%d:%d: added %s implicit_fb sync_ep %x, iface %d:%d\n",
0100               fmt->iface, fmt->altsetting,
0101               (ep & USB_DIR_IN) ? "playback" : "capture",
0102               fmt->sync_ep, fmt->sync_iface, fmt->sync_altsetting);
0103     return 1;
0104 }
0105 
0106 /* Check whether the given UAC2 iface:altset points to an implicit fb source */
0107 static int add_generic_uac2_implicit_fb(struct snd_usb_audio *chip,
0108                     struct audioformat *fmt,
0109                     unsigned int ifnum,
0110                     unsigned int altsetting)
0111 {
0112     struct usb_host_interface *alts;
0113     struct usb_endpoint_descriptor *epd;
0114 
0115     alts = snd_usb_get_host_interface(chip, ifnum, altsetting);
0116     if (!alts)
0117         return 0;
0118     if (alts->desc.bInterfaceClass != USB_CLASS_AUDIO ||
0119         alts->desc.bInterfaceSubClass != USB_SUBCLASS_AUDIOSTREAMING ||
0120         alts->desc.bInterfaceProtocol != UAC_VERSION_2 ||
0121         alts->desc.bNumEndpoints < 1)
0122         return 0;
0123     epd = get_endpoint(alts, 0);
0124     if (!usb_endpoint_is_isoc_in(epd) ||
0125         (epd->bmAttributes & USB_ENDPOINT_USAGE_MASK) !=
0126                     USB_ENDPOINT_USAGE_IMPLICIT_FB)
0127         return 0;
0128     return add_implicit_fb_sync_ep(chip, fmt, epd->bEndpointAddress, 0,
0129                        ifnum, alts);
0130 }
0131 
0132 static bool roland_sanity_check_iface(struct usb_host_interface *alts)
0133 {
0134     if (alts->desc.bInterfaceClass != USB_CLASS_VENDOR_SPEC ||
0135         (alts->desc.bInterfaceSubClass != 2 &&
0136          alts->desc.bInterfaceProtocol != 2) ||
0137         alts->desc.bNumEndpoints < 1)
0138         return false;
0139     return true;
0140 }
0141 
0142 /* Like the UAC2 case above, but specific to Roland with vendor class and hack */
0143 static int add_roland_implicit_fb(struct snd_usb_audio *chip,
0144                   struct audioformat *fmt,
0145                   struct usb_host_interface *alts)
0146 {
0147     struct usb_endpoint_descriptor *epd;
0148 
0149     if (!roland_sanity_check_iface(alts))
0150         return 0;
0151     /* only when both streams are with ASYNC type */
0152     epd = get_endpoint(alts, 0);
0153     if (!usb_endpoint_is_isoc_out(epd) ||
0154         (epd->bmAttributes & USB_ENDPOINT_SYNCTYPE) != USB_ENDPOINT_SYNC_ASYNC)
0155         return 0;
0156 
0157     /* check capture EP */
0158     alts = snd_usb_get_host_interface(chip,
0159                       alts->desc.bInterfaceNumber + 1,
0160                       alts->desc.bAlternateSetting);
0161     if (!alts || !roland_sanity_check_iface(alts))
0162         return 0;
0163     epd = get_endpoint(alts, 0);
0164     if (!usb_endpoint_is_isoc_in(epd) ||
0165         (epd->bmAttributes & USB_ENDPOINT_SYNCTYPE) != USB_ENDPOINT_SYNC_ASYNC)
0166         return 0;
0167     chip->quirk_flags |= QUIRK_FLAG_PLAYBACK_FIRST;
0168     return add_implicit_fb_sync_ep(chip, fmt, epd->bEndpointAddress, 0,
0169                        alts->desc.bInterfaceNumber, alts);
0170 }
0171 
0172 /* capture quirk for Roland device; always full-duplex */
0173 static int add_roland_capture_quirk(struct snd_usb_audio *chip,
0174                     struct audioformat *fmt,
0175                     struct usb_host_interface *alts)
0176 {
0177     struct usb_endpoint_descriptor *epd;
0178 
0179     if (!roland_sanity_check_iface(alts))
0180         return 0;
0181     epd = get_endpoint(alts, 0);
0182     if (!usb_endpoint_is_isoc_in(epd) ||
0183         (epd->bmAttributes & USB_ENDPOINT_SYNCTYPE) != USB_ENDPOINT_SYNC_ASYNC)
0184         return 0;
0185 
0186     alts = snd_usb_get_host_interface(chip,
0187                       alts->desc.bInterfaceNumber - 1,
0188                       alts->desc.bAlternateSetting);
0189     if (!alts || !roland_sanity_check_iface(alts))
0190         return 0;
0191     epd = get_endpoint(alts, 0);
0192     if (!usb_endpoint_is_isoc_out(epd))
0193         return 0;
0194     return add_implicit_fb_sync_ep(chip, fmt, epd->bEndpointAddress, 0,
0195                        alts->desc.bInterfaceNumber, alts);
0196 }
0197 
0198 /* Playback and capture EPs on Pioneer devices share the same iface/altset
0199  * for the implicit feedback operation
0200  */
0201 static bool is_pioneer_implicit_fb(struct snd_usb_audio *chip,
0202                    struct usb_host_interface *alts)
0203 
0204 {
0205     struct usb_endpoint_descriptor *epd;
0206 
0207     if (USB_ID_VENDOR(chip->usb_id) != 0x2b73 &&
0208         USB_ID_VENDOR(chip->usb_id) != 0x08e4)
0209         return false;
0210     if (alts->desc.bInterfaceClass != USB_CLASS_VENDOR_SPEC)
0211         return false;
0212     if (alts->desc.bNumEndpoints != 2)
0213         return false;
0214 
0215     epd = get_endpoint(alts, 0);
0216     if (!usb_endpoint_is_isoc_out(epd) ||
0217         (epd->bmAttributes & USB_ENDPOINT_SYNCTYPE) != USB_ENDPOINT_SYNC_ASYNC)
0218         return false;
0219 
0220     epd = get_endpoint(alts, 1);
0221     if (!usb_endpoint_is_isoc_in(epd) ||
0222         (epd->bmAttributes & USB_ENDPOINT_SYNCTYPE) != USB_ENDPOINT_SYNC_ASYNC ||
0223         ((epd->bmAttributes & USB_ENDPOINT_USAGE_MASK) !=
0224          USB_ENDPOINT_USAGE_DATA &&
0225          (epd->bmAttributes & USB_ENDPOINT_USAGE_MASK) !=
0226          USB_ENDPOINT_USAGE_IMPLICIT_FB))
0227         return false;
0228 
0229     return true;
0230 }
0231 
0232 static int __add_generic_implicit_fb(struct snd_usb_audio *chip,
0233                      struct audioformat *fmt,
0234                      int iface, int altset)
0235 {
0236     struct usb_host_interface *alts;
0237     struct usb_endpoint_descriptor *epd;
0238 
0239     alts = snd_usb_get_host_interface(chip, iface, altset);
0240     if (!alts)
0241         return 0;
0242 
0243     if ((alts->desc.bInterfaceClass != USB_CLASS_VENDOR_SPEC &&
0244          alts->desc.bInterfaceClass != USB_CLASS_AUDIO) ||
0245         alts->desc.bNumEndpoints < 1)
0246         return 0;
0247     epd = get_endpoint(alts, 0);
0248     if (!usb_endpoint_is_isoc_in(epd) ||
0249         (epd->bmAttributes & USB_ENDPOINT_SYNCTYPE) != USB_ENDPOINT_SYNC_ASYNC)
0250         return 0;
0251     return add_implicit_fb_sync_ep(chip, fmt, epd->bEndpointAddress, 0,
0252                        iface, alts);
0253 }
0254 
0255 /* More generic quirk: look for the sync EP next to the data EP */
0256 static int add_generic_implicit_fb(struct snd_usb_audio *chip,
0257                    struct audioformat *fmt,
0258                    struct usb_host_interface *alts)
0259 {
0260     if ((fmt->ep_attr & USB_ENDPOINT_SYNCTYPE) != USB_ENDPOINT_SYNC_ASYNC)
0261         return 0;
0262 
0263     if (__add_generic_implicit_fb(chip, fmt,
0264                       alts->desc.bInterfaceNumber + 1,
0265                       alts->desc.bAlternateSetting))
0266         return 1;
0267     return __add_generic_implicit_fb(chip, fmt,
0268                      alts->desc.bInterfaceNumber - 1,
0269                      alts->desc.bAlternateSetting);
0270 }
0271 
0272 static const struct snd_usb_implicit_fb_match *
0273 find_implicit_fb_entry(struct snd_usb_audio *chip,
0274                const struct snd_usb_implicit_fb_match *match,
0275                const struct usb_host_interface *alts)
0276 {
0277     for (; match->id; match++)
0278         if (match->id == chip->usb_id &&
0279             (!match->iface_class ||
0280              (alts->desc.bInterfaceClass == match->iface_class)))
0281             return match;
0282 
0283     return NULL;
0284 }
0285 
0286 /* Setup an implicit feedback endpoint from a quirk. Returns 0 if no quirk
0287  * applies. Returns 1 if a quirk was found.
0288  */
0289 static int audioformat_implicit_fb_quirk(struct snd_usb_audio *chip,
0290                      struct audioformat *fmt,
0291                      struct usb_host_interface *alts)
0292 {
0293     const struct snd_usb_implicit_fb_match *p;
0294     unsigned int attr = fmt->ep_attr & USB_ENDPOINT_SYNCTYPE;
0295 
0296     p = find_implicit_fb_entry(chip, playback_implicit_fb_quirks, alts);
0297     if (p) {
0298         switch (p->type) {
0299         case IMPLICIT_FB_GENERIC:
0300             return add_generic_implicit_fb(chip, fmt, alts);
0301         case IMPLICIT_FB_NONE:
0302             return 0; /* No quirk */
0303         case IMPLICIT_FB_FIXED:
0304             return add_implicit_fb_sync_ep(chip, fmt, p->ep_num, 0,
0305                                p->iface, NULL);
0306         }
0307     }
0308 
0309     /* Special handling for devices with capture quirks */
0310     p = find_implicit_fb_entry(chip, capture_implicit_fb_quirks, alts);
0311     if (p) {
0312         switch (p->type) {
0313         case IMPLICIT_FB_FIXED:
0314             return 0; /* no quirk */
0315         case IMPLICIT_FB_BOTH:
0316             chip->quirk_flags |= QUIRK_FLAG_PLAYBACK_FIRST;
0317             return add_generic_implicit_fb(chip, fmt, alts);
0318         }
0319     }
0320 
0321     /* Generic UAC2 implicit feedback */
0322     if (attr == USB_ENDPOINT_SYNC_ASYNC &&
0323         alts->desc.bInterfaceClass == USB_CLASS_AUDIO &&
0324         alts->desc.bInterfaceProtocol == UAC_VERSION_2 &&
0325         alts->desc.bNumEndpoints == 1) {
0326         if (add_generic_uac2_implicit_fb(chip, fmt,
0327                          alts->desc.bInterfaceNumber + 1,
0328                          alts->desc.bAlternateSetting))
0329             return 1;
0330     }
0331 
0332     /* Roland/BOSS implicit feedback with vendor spec class */
0333     if (USB_ID_VENDOR(chip->usb_id) == 0x0582) {
0334         if (add_roland_implicit_fb(chip, fmt, alts) > 0)
0335             return 1;
0336     }
0337 
0338     /* Pioneer devices with vendor spec class */
0339     if (is_pioneer_implicit_fb(chip, alts)) {
0340         chip->quirk_flags |= QUIRK_FLAG_PLAYBACK_FIRST;
0341         return add_implicit_fb_sync_ep(chip, fmt,
0342                            get_endpoint(alts, 1)->bEndpointAddress,
0343                            1, alts->desc.bInterfaceNumber,
0344                            alts);
0345     }
0346 
0347     /* Try the generic implicit fb if available */
0348     if (chip->generic_implicit_fb ||
0349         (chip->quirk_flags & QUIRK_FLAG_GENERIC_IMPLICIT_FB))
0350         return add_generic_implicit_fb(chip, fmt, alts);
0351 
0352     /* No quirk */
0353     return 0;
0354 }
0355 
0356 /* same for capture, but only handling FIXED entry */
0357 static int audioformat_capture_quirk(struct snd_usb_audio *chip,
0358                      struct audioformat *fmt,
0359                      struct usb_host_interface *alts)
0360 {
0361     const struct snd_usb_implicit_fb_match *p;
0362 
0363     p = find_implicit_fb_entry(chip, capture_implicit_fb_quirks, alts);
0364     if (p && (p->type == IMPLICIT_FB_FIXED || p->type == IMPLICIT_FB_BOTH))
0365         return add_implicit_fb_sync_ep(chip, fmt, p->ep_num, 0,
0366                            p->iface, NULL);
0367 
0368     /* Roland/BOSS need full-duplex streams */
0369     if (USB_ID_VENDOR(chip->usb_id) == 0x0582) {
0370         if (add_roland_capture_quirk(chip, fmt, alts) > 0)
0371             return 1;
0372     }
0373 
0374     if (is_pioneer_implicit_fb(chip, alts))
0375         return 1; /* skip the quirk, also don't handle generic sync EP */
0376     return 0;
0377 }
0378 
0379 /*
0380  * Parse altset and set up implicit feedback endpoint on the audioformat
0381  */
0382 int snd_usb_parse_implicit_fb_quirk(struct snd_usb_audio *chip,
0383                     struct audioformat *fmt,
0384                     struct usb_host_interface *alts)
0385 {
0386     if (chip->quirk_flags & QUIRK_FLAG_SKIP_IMPLICIT_FB)
0387         return 0;
0388     if (fmt->endpoint & USB_DIR_IN)
0389         return audioformat_capture_quirk(chip, fmt, alts);
0390     else
0391         return audioformat_implicit_fb_quirk(chip, fmt, alts);
0392 }
0393 
0394 /*
0395  * Return the score of matching two audioformats.
0396  * Veto the audioformat if:
0397  * - It has no channels for some reason.
0398  * - Requested PCM format is not supported.
0399  * - Requested sample rate is not supported.
0400  */
0401 static int match_endpoint_audioformats(struct snd_usb_substream *subs,
0402                        const struct audioformat *fp,
0403                        int rate, int channels,
0404                        snd_pcm_format_t pcm_format)
0405 {
0406     int i, score;
0407 
0408     if (fp->channels < 1)
0409         return 0;
0410 
0411     if (!(fp->formats & pcm_format_to_bits(pcm_format)))
0412         return 0;
0413 
0414     if (fp->rates & SNDRV_PCM_RATE_CONTINUOUS) {
0415         if (rate < fp->rate_min || rate > fp->rate_max)
0416             return 0;
0417     } else {
0418         for (i = 0; i < fp->nr_rates; i++) {
0419             if (fp->rate_table[i] == rate)
0420                 break;
0421         }
0422         if (i >= fp->nr_rates)
0423             return 0;
0424     }
0425 
0426     score = 1;
0427     if (fp->channels == channels)
0428         score++;
0429 
0430     return score;
0431 }
0432 
0433 static struct snd_usb_substream *
0434 find_matching_substream(struct snd_usb_audio *chip, int stream, int ep_num,
0435             int fmt_type)
0436 {
0437     struct snd_usb_stream *as;
0438     struct snd_usb_substream *subs;
0439 
0440     list_for_each_entry(as, &chip->pcm_list, list) {
0441         subs = &as->substream[stream];
0442         if (as->fmt_type == fmt_type && subs->ep_num == ep_num)
0443             return subs;
0444     }
0445 
0446     return NULL;
0447 }
0448 
0449 /*
0450  * Return the audioformat that is suitable for the implicit fb
0451  */
0452 const struct audioformat *
0453 snd_usb_find_implicit_fb_sync_format(struct snd_usb_audio *chip,
0454                      const struct audioformat *target,
0455                      const struct snd_pcm_hw_params *params,
0456                      int stream)
0457 {
0458     struct snd_usb_substream *subs;
0459     const struct audioformat *fp, *sync_fmt = NULL;
0460     int score, high_score;
0461 
0462     /* Use the original audioformat as fallback for the shared altset */
0463     if (target->iface == target->sync_iface &&
0464         target->altsetting == target->sync_altsetting)
0465         sync_fmt = target;
0466 
0467     subs = find_matching_substream(chip, stream, target->sync_ep,
0468                        target->fmt_type);
0469     if (!subs)
0470         return sync_fmt;
0471 
0472     high_score = 0;
0473     list_for_each_entry(fp, &subs->fmt_list, list) {
0474         score = match_endpoint_audioformats(subs, fp,
0475                             params_rate(params),
0476                             params_channels(params),
0477                             params_format(params));
0478         if (score > high_score) {
0479             sync_fmt = fp;
0480             high_score = score;
0481         }
0482     }
0483 
0484     return sync_fmt;
0485 }
0486