diff options
Diffstat (limited to 'sound/usb/clock.c')
-rw-r--r-- | sound/usb/clock.c | 59 |
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 | ||
50 | static struct uac_clock_source_descriptor * | 36 | static 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 | |||
139 | static int __uac_clock_find_source(struct snd_usb_audio *chip, | 123 | static 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 | ||
193 | int 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 | */ | ||
188 | int 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 | ||
202 | static int set_sample_rate_v1(struct snd_usb_audio *chip, int iface, | 195 | static 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; |