.. | .. |
---|
| 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 | } |
---|