| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * Clock domain and sample rate management functions |
|---|
| 3 | | - * |
|---|
| 4 | | - * This program is free software; you can redistribute it and/or modify |
|---|
| 5 | | - * it under the terms of the GNU General Public License as published by |
|---|
| 6 | | - * the Free Software Foundation; either version 2 of the License, or |
|---|
| 7 | | - * (at your option) any later version. |
|---|
| 8 | | - * |
|---|
| 9 | | - * This program is distributed in the hope that it will be useful, |
|---|
| 10 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 11 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|---|
| 12 | | - * GNU General Public License for more details. |
|---|
| 13 | | - * |
|---|
| 14 | | - * You should have received a copy of the GNU General Public License |
|---|
| 15 | | - * along with this program; if not, write to the Free Software |
|---|
| 16 | | - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|---|
| 17 | | - * |
|---|
| 18 | 4 | */ |
|---|
| 19 | 5 | |
|---|
| 20 | 6 | #include <linux/bitops.h> |
|---|
| .. | .. |
|---|
| 165 | 151 | return ret; |
|---|
| 166 | 152 | } |
|---|
| 167 | 153 | |
|---|
| 168 | | -/* |
|---|
| 169 | | - * Assume the clock is valid if clock source supports only one single sample |
|---|
| 170 | | - * rate, the terminal is connected directly to it (there is no clock selector) |
|---|
| 171 | | - * and clock type is internal. This is to deal with some Denon DJ controllers |
|---|
| 172 | | - * that always reports that clock is invalid. |
|---|
| 173 | | - */ |
|---|
| 174 | 154 | static bool uac_clock_source_is_valid_quirk(struct snd_usb_audio *chip, |
|---|
| 175 | 155 | struct audioformat *fmt, |
|---|
| 176 | 156 | int source_id) |
|---|
| 177 | 157 | { |
|---|
| 158 | + bool ret = false; |
|---|
| 159 | + int count; |
|---|
| 160 | + unsigned char data; |
|---|
| 161 | + struct usb_device *dev = chip->dev; |
|---|
| 162 | + |
|---|
| 178 | 163 | if (fmt->protocol == UAC_VERSION_2) { |
|---|
| 179 | 164 | struct uac_clock_source_descriptor *cs_desc = |
|---|
| 180 | 165 | snd_usb_find_clock_source(chip->ctrl_intf, source_id); |
|---|
| .. | .. |
|---|
| 182 | 167 | if (!cs_desc) |
|---|
| 183 | 168 | return false; |
|---|
| 184 | 169 | |
|---|
| 185 | | - return (fmt->nr_rates == 1 && |
|---|
| 186 | | - (fmt->clock & 0xff) == cs_desc->bClockID && |
|---|
| 187 | | - (cs_desc->bmAttributes & 0x3) != |
|---|
| 188 | | - UAC_CLOCK_SOURCE_TYPE_EXT); |
|---|
| 170 | + /* |
|---|
| 171 | + * Assume the clock is valid if clock source supports only one |
|---|
| 172 | + * single sample rate, the terminal is connected directly to it |
|---|
| 173 | + * (there is no clock selector) and clock type is internal. |
|---|
| 174 | + * This is to deal with some Denon DJ controllers that always |
|---|
| 175 | + * reports that clock is invalid. |
|---|
| 176 | + */ |
|---|
| 177 | + if (fmt->nr_rates == 1 && |
|---|
| 178 | + (fmt->clock & 0xff) == cs_desc->bClockID && |
|---|
| 179 | + (cs_desc->bmAttributes & 0x3) != |
|---|
| 180 | + UAC_CLOCK_SOURCE_TYPE_EXT) |
|---|
| 181 | + return true; |
|---|
| 189 | 182 | } |
|---|
| 190 | 183 | |
|---|
| 191 | | - return false; |
|---|
| 184 | + /* |
|---|
| 185 | + * MOTU MicroBook IIc |
|---|
| 186 | + * Sample rate changes takes more than 2 seconds for this device. Clock |
|---|
| 187 | + * validity request returns false during that period. |
|---|
| 188 | + */ |
|---|
| 189 | + if (chip->usb_id == USB_ID(0x07fd, 0x0004)) { |
|---|
| 190 | + count = 0; |
|---|
| 191 | + |
|---|
| 192 | + while ((!ret) && (count < 50)) { |
|---|
| 193 | + int err; |
|---|
| 194 | + |
|---|
| 195 | + msleep(100); |
|---|
| 196 | + |
|---|
| 197 | + err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC2_CS_CUR, |
|---|
| 198 | + USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN, |
|---|
| 199 | + UAC2_CS_CONTROL_CLOCK_VALID << 8, |
|---|
| 200 | + snd_usb_ctrl_intf(chip) | (source_id << 8), |
|---|
| 201 | + &data, sizeof(data)); |
|---|
| 202 | + if (err < 0) { |
|---|
| 203 | + dev_warn(&dev->dev, |
|---|
| 204 | + "%s(): cannot get clock validity for id %d\n", |
|---|
| 205 | + __func__, source_id); |
|---|
| 206 | + return false; |
|---|
| 207 | + } |
|---|
| 208 | + |
|---|
| 209 | + ret = !!data; |
|---|
| 210 | + count++; |
|---|
| 211 | + } |
|---|
| 212 | + } |
|---|
| 213 | + |
|---|
| 214 | + return ret; |
|---|
| 192 | 215 | } |
|---|
| 193 | 216 | |
|---|
| 194 | 217 | static bool uac_clock_source_is_valid(struct snd_usb_audio *chip, |
|---|
| .. | .. |
|---|
| 641 | 664 | * interface is active. */ |
|---|
| 642 | 665 | if (rate != prev_rate) { |
|---|
| 643 | 666 | usb_set_interface(dev, iface, 0); |
|---|
| 667 | + |
|---|
| 668 | + snd_vendor_set_interface(dev, alts, iface, 0); |
|---|
| 669 | + |
|---|
| 644 | 670 | snd_usb_set_interface_quirk(dev); |
|---|
| 645 | 671 | usb_set_interface(dev, iface, fmt->altsetting); |
|---|
| 672 | + |
|---|
| 673 | + snd_vendor_set_interface(dev, alts, iface, fmt->altsetting); |
|---|
| 646 | 674 | snd_usb_set_interface_quirk(dev); |
|---|
| 647 | 675 | } |
|---|
| 648 | 676 | |
|---|
| .. | .. |
|---|
| 669 | 697 | else |
|---|
| 670 | 698 | return 0; |
|---|
| 671 | 699 | } |
|---|
| 672 | | - /* fall through */ |
|---|
| 700 | + fallthrough; |
|---|
| 673 | 701 | case UAC_VERSION_2: |
|---|
| 674 | 702 | return set_sample_rate_v2v3(chip, iface, alts, fmt, rate); |
|---|
| 675 | 703 | } |
|---|