aboutsummaryrefslogtreecommitdiffstats
path: root/sound/usb/clock.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/usb/clock.c')
-rw-r--r--sound/usb/clock.c59
1 files changed, 25 insertions, 34 deletions
diff --git a/sound/usb/clock.c b/sound/usb/clock.c
index b5855114667e..b853f8df794f 100644
--- a/sound/usb/clock.c
+++ b/sound/usb/clock.c
@@ -19,33 +19,19 @@
19 19
20#include <linux/bitops.h> 20#include <linux/bitops.h>
21#include <linux/init.h> 21#include <linux/init.h>
22#include <linux/list.h>
23#include <linux/slab.h>
24#include <linux/string.h> 22#include <linux/string.h>
25#include <linux/usb.h> 23#include <linux/usb.h>
26#include <linux/moduleparam.h>
27#include <linux/mutex.h>
28#include <linux/usb/audio.h> 24#include <linux/usb/audio.h>
29#include <linux/usb/audio-v2.h> 25#include <linux/usb/audio-v2.h>
30 26
31#include <sound/core.h> 27#include <sound/core.h>
32#include <sound/info.h> 28#include <sound/info.h>
33#include <sound/pcm.h> 29#include <sound/pcm.h>
34#include <sound/pcm_params.h>
35#include <sound/initval.h>
36 30
37#include "usbaudio.h" 31#include "usbaudio.h"
38#include "card.h" 32#include "card.h"
39#include "midi.h"
40#include "mixer.h"
41#include "proc.h"
42#include "quirks.h"
43#include "endpoint.h"
44#include "helper.h" 33#include "helper.h"
45#include "debug.h" 34#include "clock.h"
46#include "pcm.h"
47#include "urb.h"
48#include "format.h"
49 35
50static struct uac_clock_source_descriptor * 36static struct uac_clock_source_descriptor *
51 snd_usb_find_clock_source(struct usb_host_interface *ctrl_iface, 37 snd_usb_find_clock_source(struct usb_host_interface *ctrl_iface,
@@ -134,10 +120,7 @@ static bool uac_clock_source_is_valid(struct snd_usb_audio *chip, int source_id)
134 return !!data; 120 return !!data;
135} 121}
136 122
137/* Try to find the clock source ID of a given clock entity */
138
139static int __uac_clock_find_source(struct snd_usb_audio *chip, 123static int __uac_clock_find_source(struct snd_usb_audio *chip,
140 struct usb_host_interface *host_iface,
141 int entity_id, unsigned long *visited) 124 int entity_id, unsigned long *visited)
142{ 125{
143 struct uac_clock_source_descriptor *source; 126 struct uac_clock_source_descriptor *source;
@@ -154,11 +137,11 @@ static int __uac_clock_find_source(struct snd_usb_audio *chip,
154 } 137 }
155 138
156 /* first, see if the ID we're looking for is a clock source already */ 139 /* first, see if the ID we're looking for is a clock source already */
157 source = snd_usb_find_clock_source(host_iface, entity_id); 140 source = snd_usb_find_clock_source(chip->ctrl_intf, entity_id);
158 if (source) 141 if (source)
159 return source->bClockID; 142 return source->bClockID;
160 143
161 selector = snd_usb_find_clock_selector(host_iface, entity_id); 144 selector = snd_usb_find_clock_selector(chip->ctrl_intf, entity_id);
162 if (selector) { 145 if (selector) {
163 int ret; 146 int ret;
164 147
@@ -168,6 +151,8 @@ static int __uac_clock_find_source(struct snd_usb_audio *chip,
168 if (ret < 0) 151 if (ret < 0)
169 return ret; 152 return ret;
170 153
154 /* Selector values are one-based */
155
171 if (ret > selector->bNrInPins || ret < 1) { 156 if (ret > selector->bNrInPins || ret < 1) {
172 printk(KERN_ERR 157 printk(KERN_ERR
173 "%s(): selector reported illegal value, id %d, ret %d\n", 158 "%s(): selector reported illegal value, id %d, ret %d\n",
@@ -176,27 +161,35 @@ static int __uac_clock_find_source(struct snd_usb_audio *chip,
176 return -EINVAL; 161 return -EINVAL;
177 } 162 }
178 163
179 return __uac_clock_find_source(chip, host_iface, 164 return __uac_clock_find_source(chip, selector->baCSourceID[ret-1],
180 selector->baCSourceID[ret-1],
181 visited); 165 visited);
182 } 166 }
183 167
184 /* FIXME: multipliers only act as pass-thru element for now */ 168 /* FIXME: multipliers only act as pass-thru element for now */
185 multiplier = snd_usb_find_clock_multiplier(host_iface, entity_id); 169 multiplier = snd_usb_find_clock_multiplier(chip->ctrl_intf, entity_id);
186 if (multiplier) 170 if (multiplier)
187 return __uac_clock_find_source(chip, host_iface, 171 return __uac_clock_find_source(chip, multiplier->bCSourceID,
188 multiplier->bCSourceID, visited); 172 visited);
189 173
190 return -EINVAL; 174 return -EINVAL;
191} 175}
192 176
193int snd_usb_clock_find_source(struct snd_usb_audio *chip, 177/*
194 struct usb_host_interface *host_iface, 178 * For all kinds of sample rate settings and other device queries,
195 int entity_id) 179 * the clock source (end-leaf) must be used. However, clock selectors,
180 * clock multipliers and sample rate converters may be specified as
181 * clock source input to terminal. This functions walks the clock path
182 * to its end and tries to find the source.
183 *
184 * The 'visited' bitfield is used internally to detect recursive loops.
185 *
186 * Returns the clock source UnitID (>=0) on success, or an error.
187 */
188int snd_usb_clock_find_source(struct snd_usb_audio *chip, int entity_id)
196{ 189{
197 DECLARE_BITMAP(visited, 256); 190 DECLARE_BITMAP(visited, 256);
198 memset(visited, 0, sizeof(visited)); 191 memset(visited, 0, sizeof(visited));
199 return __uac_clock_find_source(chip, host_iface, entity_id, visited); 192 return __uac_clock_find_source(chip, entity_id, visited);
200} 193}
201 194
202static int set_sample_rate_v1(struct snd_usb_audio *chip, int iface, 195static int set_sample_rate_v1(struct snd_usb_audio *chip, int iface,
@@ -211,11 +204,8 @@ static int set_sample_rate_v1(struct snd_usb_audio *chip, int iface,
211 ep = get_endpoint(alts, 0)->bEndpointAddress; 204 ep = get_endpoint(alts, 0)->bEndpointAddress;
212 205
213 /* if endpoint doesn't have sampling rate control, bail out */ 206 /* if endpoint doesn't have sampling rate control, bail out */
214 if (!(fmt->attributes & UAC_EP_CS_ATTR_SAMPLE_RATE)) { 207 if (!(fmt->attributes & UAC_EP_CS_ATTR_SAMPLE_RATE))
215 snd_printk(KERN_WARNING "%d:%d:%d: endpoint lacks sample rate attribute bit, cannot set.\n",
216 dev->devnum, iface, fmt->altsetting);
217 return 0; 208 return 0;
218 }
219 209
220 data[0] = rate; 210 data[0] = rate;
221 data[1] = rate >> 8; 211 data[1] = rate >> 8;
@@ -254,12 +244,13 @@ static int set_sample_rate_v2(struct snd_usb_audio *chip, int iface,
254 struct usb_device *dev = chip->dev; 244 struct usb_device *dev = chip->dev;
255 unsigned char data[4]; 245 unsigned char data[4];
256 int err, crate; 246 int err, crate;
257 int clock = snd_usb_clock_find_source(chip, chip->ctrl_intf, fmt->clock); 247 int clock = snd_usb_clock_find_source(chip, fmt->clock);
258 248
259 if (clock < 0) 249 if (clock < 0)
260 return clock; 250 return clock;
261 251
262 if (!uac_clock_source_is_valid(chip, clock)) { 252 if (!uac_clock_source_is_valid(chip, clock)) {
253 /* TODO: should we try to find valid clock setups by ourself? */
263 snd_printk(KERN_ERR "%d:%d:%d: clock source %d is not valid, cannot use\n", 254 snd_printk(KERN_ERR "%d:%d:%d: clock source %d is not valid, cannot use\n",
264 dev->devnum, iface, fmt->altsetting, clock); 255 dev->devnum, iface, fmt->altsetting, clock);
265 return -ENXIO; 256 return -ENXIO;