lkml.org 
[lkml]   [2020]   [Jul]   [20]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 5.4 080/215] ALSA: usb-audio: Add support for MOTU MicroBook IIc
    Date
    From: Alexander Tsoy <alexander@tsoy.me>

    [ Upstream commit 2edb84e3047b93da2f2b234219cdc304df042d9e ]

    MicroBook IIc operates in UAC2 mode by default. This patch addresses
    several issues with it:

    - MicroBook II and IIc shares the same USB ID. We can distinguish them
    by interface class.
    - MaxPacketsOnly attribute is erroneously set in endpoint descriptors.
    As a result this card produces noise with all sample rates other than
    96 KHz. This also causes issues like IOMMU page faults and other
    problems with host controller.
    - Sample rate changes takes more than 2 seconds for this device. Clock
    validity request returns false during that period, so the clock validity
    quirk is required.

    Signed-off-by: Alexander Tsoy <alexander@tsoy.me>
    Link: https://lore.kernel.org/r/20200229151815.14199-1-alexander@tsoy.me
    Signed-off-by: Takashi Iwai <tiwai@suse.de>
    Signed-off-by: Sasha Levin <sashal@kernel.org>
    ---
    sound/usb/clock.c | 59 ++++++++++++++++++++++++++++++++--------
    sound/usb/pcm.c | 7 ++++-
    sound/usb/quirks-table.h | 2 +-
    sound/usb/quirks.c | 18 +++++++++++-
    4 files changed, 72 insertions(+), 14 deletions(-)

    diff --git a/sound/usb/clock.c b/sound/usb/clock.c
    index a48313dfa967a..b118cf97607f3 100644
    --- a/sound/usb/clock.c
    +++ b/sound/usb/clock.c
    @@ -151,16 +151,15 @@ static int uac_clock_selector_set_val(struct snd_usb_audio *chip, int selector_i
    return ret;
    }

    -/*
    - * Assume the clock is valid if clock source supports only one single sample
    - * rate, the terminal is connected directly to it (there is no clock selector)
    - * and clock type is internal. This is to deal with some Denon DJ controllers
    - * that always reports that clock is invalid.
    - */
    static bool uac_clock_source_is_valid_quirk(struct snd_usb_audio *chip,
    struct audioformat *fmt,
    int source_id)
    {
    + bool ret = false;
    + int count;
    + unsigned char data;
    + struct usb_device *dev = chip->dev;
    +
    if (fmt->protocol == UAC_VERSION_2) {
    struct uac_clock_source_descriptor *cs_desc =
    snd_usb_find_clock_source(chip->ctrl_intf, source_id);
    @@ -168,13 +167,51 @@ static bool uac_clock_source_is_valid_quirk(struct snd_usb_audio *chip,
    if (!cs_desc)
    return false;

    - return (fmt->nr_rates == 1 &&
    - (fmt->clock & 0xff) == cs_desc->bClockID &&
    - (cs_desc->bmAttributes & 0x3) !=
    - UAC_CLOCK_SOURCE_TYPE_EXT);
    + /*
    + * Assume the clock is valid if clock source supports only one
    + * single sample rate, the terminal is connected directly to it
    + * (there is no clock selector) and clock type is internal.
    + * This is to deal with some Denon DJ controllers that always
    + * reports that clock is invalid.
    + */
    + if (fmt->nr_rates == 1 &&
    + (fmt->clock & 0xff) == cs_desc->bClockID &&
    + (cs_desc->bmAttributes & 0x3) !=
    + UAC_CLOCK_SOURCE_TYPE_EXT)
    + return true;
    + }
    +
    + /*
    + * MOTU MicroBook IIc
    + * Sample rate changes takes more than 2 seconds for this device. Clock
    + * validity request returns false during that period.
    + */
    + if (chip->usb_id == USB_ID(0x07fd, 0x0004)) {
    + count = 0;
    +
    + while ((!ret) && (count < 50)) {
    + int err;
    +
    + msleep(100);
    +
    + err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC2_CS_CUR,
    + USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
    + UAC2_CS_CONTROL_CLOCK_VALID << 8,
    + snd_usb_ctrl_intf(chip) | (source_id << 8),
    + &data, sizeof(data));
    + if (err < 0) {
    + dev_warn(&dev->dev,
    + "%s(): cannot get clock validity for id %d\n",
    + __func__, source_id);
    + return false;
    + }
    +
    + ret = !!data;
    + count++;
    + }
    }

    - return false;
    + return ret;
    }

    static bool uac_clock_source_is_valid(struct snd_usb_audio *chip,
    diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c
    index d5706b8b68a1c..086244c707433 100644
    --- a/sound/usb/pcm.c
    +++ b/sound/usb/pcm.c
    @@ -344,7 +344,12 @@ static int set_sync_ep_implicit_fb_quirk(struct snd_usb_substream *subs,
    ep = 0x81;
    ifnum = 1;
    goto add_sync_ep_from_ifnum;
    - case USB_ID(0x07fd, 0x0004): /* MOTU MicroBook II */
    + case USB_ID(0x07fd, 0x0004): /* MOTU MicroBook II/IIc */
    + /* MicroBook IIc */
    + if (altsd->bInterfaceClass == USB_CLASS_AUDIO)
    + return 0;
    +
    + /* MicroBook II */
    ep = 0x84;
    ifnum = 0;
    goto add_sync_ep_from_ifnum;
    diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h
    index 8d1805d9e5a78..5089f2de2f02d 100644
    --- a/sound/usb/quirks-table.h
    +++ b/sound/usb/quirks-table.h
    @@ -3492,7 +3492,7 @@ AU0828_DEVICE(0x2040, 0x7270, "Hauppauge", "HVR-950Q"),
    },
    /* MOTU Microbook II */
    {
    - USB_DEVICE(0x07fd, 0x0004),
    + USB_DEVICE_VENDOR_SPEC(0x07fd, 0x0004),
    .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) {
    .vendor_name = "MOTU",
    .product_name = "MicroBookII",
    diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c
    index bf5083a20b6d5..9d11ff742e5f5 100644
    --- a/sound/usb/quirks.c
    +++ b/sound/usb/quirks.c
    @@ -1316,7 +1316,15 @@ int snd_usb_apply_boot_quirk(struct usb_device *dev,
    case USB_ID(0x2466, 0x8010): /* Fractal Audio Axe-Fx 3 */
    return snd_usb_axefx3_boot_quirk(dev);
    case USB_ID(0x07fd, 0x0004): /* MOTU MicroBook II */
    - return snd_usb_motu_microbookii_boot_quirk(dev);
    + /*
    + * For some reason interface 3 with vendor-spec class is
    + * detected on MicroBook IIc.
    + */
    + if (get_iface_desc(intf->altsetting)->bInterfaceClass ==
    + USB_CLASS_VENDOR_SPEC &&
    + get_iface_desc(intf->altsetting)->bInterfaceNumber < 3)
    + return snd_usb_motu_microbookii_boot_quirk(dev);
    + break;
    }

    return 0;
    @@ -1764,5 +1772,13 @@ void snd_usb_audioformat_attributes_quirk(struct snd_usb_audio *chip,
    else
    fp->ep_attr |= USB_ENDPOINT_SYNC_SYNC;
    break;
    + case USB_ID(0x07fd, 0x0004): /* MOTU MicroBook IIc */
    + /*
    + * MaxPacketsOnly attribute is erroneously set in endpoint
    + * descriptors. As a result this card produces noise with
    + * all sample rates other than 96 KHz.
    + */
    + fp->attributes &= ~UAC_EP_CS_ATTR_FILL_MAX;
    + break;
    }
    }
    --
    2.25.1


    \
     
     \ /
      Last update: 2020-07-20 18:40    [W:3.246 / U:0.848 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site