Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
clock.c
Go to the documentation of this file.
1 /*
2  * 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  */
19 
20 #include <linux/bitops.h>
21 #include <linux/init.h>
22 #include <linux/string.h>
23 #include <linux/usb.h>
24 #include <linux/usb/audio.h>
25 #include <linux/usb/audio-v2.h>
26 
27 #include <sound/core.h>
28 #include <sound/info.h>
29 #include <sound/pcm.h>
30 
31 #include "usbaudio.h"
32 #include "card.h"
33 #include "helper.h"
34 #include "clock.h"
35 
36 static struct uac_clock_source_descriptor *
37  snd_usb_find_clock_source(struct usb_host_interface *ctrl_iface,
38  int clock_id)
39 {
41 
42  while ((cs = snd_usb_find_csint_desc(ctrl_iface->extra,
43  ctrl_iface->extralen,
44  cs, UAC2_CLOCK_SOURCE))) {
45  if (cs->bClockID == clock_id)
46  return cs;
47  }
48 
49  return NULL;
50 }
51 
52 static struct uac_clock_selector_descriptor *
53  snd_usb_find_clock_selector(struct usb_host_interface *ctrl_iface,
54  int clock_id)
55 {
57 
58  while ((cs = snd_usb_find_csint_desc(ctrl_iface->extra,
59  ctrl_iface->extralen,
60  cs, UAC2_CLOCK_SELECTOR))) {
61  if (cs->bClockID == clock_id)
62  return cs;
63  }
64 
65  return NULL;
66 }
67 
68 static struct uac_clock_multiplier_descriptor *
69  snd_usb_find_clock_multiplier(struct usb_host_interface *ctrl_iface,
70  int clock_id)
71 {
73 
74  while ((cs = snd_usb_find_csint_desc(ctrl_iface->extra,
75  ctrl_iface->extralen,
76  cs, UAC2_CLOCK_MULTIPLIER))) {
77  if (cs->bClockID == clock_id)
78  return cs;
79  }
80 
81  return NULL;
82 }
83 
84 static int uac_clock_selector_get_val(struct snd_usb_audio *chip, int selector_id)
85 {
86  unsigned char buf;
87  int ret;
88 
89  ret = snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0),
93  snd_usb_ctrl_intf(chip) | (selector_id << 8),
94  &buf, sizeof(buf));
95 
96  if (ret < 0)
97  return ret;
98 
99  return buf;
100 }
101 
102 static bool uac_clock_source_is_valid(struct snd_usb_audio *chip, int source_id)
103 {
104  int err;
105  unsigned char data;
106  struct usb_device *dev = chip->dev;
107  struct uac_clock_source_descriptor *cs_desc =
108  snd_usb_find_clock_source(chip->ctrl_intf, source_id);
109 
110  if (!cs_desc)
111  return 0;
112 
113  /* If a clock source can't tell us whether it's valid, we assume it is */
114  if (!uac2_control_is_readable(cs_desc->bmControls,
116  return 1;
117 
118  err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC2_CS_CUR,
121  snd_usb_ctrl_intf(chip) | (source_id << 8),
122  &data, sizeof(data));
123 
124  if (err < 0) {
125  snd_printk(KERN_WARNING "%s(): cannot get clock validity for id %d\n",
126  __func__, source_id);
127  return 0;
128  }
129 
130  return !!data;
131 }
132 
133 static int __uac_clock_find_source(struct snd_usb_audio *chip,
134  int entity_id, unsigned long *visited)
135 {
138  struct uac_clock_multiplier_descriptor *multiplier;
139 
140  entity_id &= 0xff;
141 
142  if (test_and_set_bit(entity_id, visited)) {
144  "%s(): recursive clock topology detected, id %d.\n",
145  __func__, entity_id);
146  return -EINVAL;
147  }
148 
149  /* first, see if the ID we're looking for is a clock source already */
150  source = snd_usb_find_clock_source(chip->ctrl_intf, entity_id);
151  if (source)
152  return source->bClockID;
153 
154  selector = snd_usb_find_clock_selector(chip->ctrl_intf, entity_id);
155  if (selector) {
156  int ret;
157 
158  /* the entity ID we are looking for is a selector.
159  * find out what it currently selects */
160  ret = uac_clock_selector_get_val(chip, selector->bClockID);
161  if (ret < 0)
162  return ret;
163 
164  /* Selector values are one-based */
165 
166  if (ret > selector->bNrInPins || ret < 1) {
168  "%s(): selector reported illegal value, id %d, ret %d\n",
169  __func__, selector->bClockID, ret);
170 
171  return -EINVAL;
172  }
173 
174  return __uac_clock_find_source(chip, selector->baCSourceID[ret-1],
175  visited);
176  }
177 
178  /* FIXME: multipliers only act as pass-thru element for now */
179  multiplier = snd_usb_find_clock_multiplier(chip->ctrl_intf, entity_id);
180  if (multiplier)
181  return __uac_clock_find_source(chip, multiplier->bCSourceID,
182  visited);
183 
184  return -EINVAL;
185 }
186 
187 /*
188  * For all kinds of sample rate settings and other device queries,
189  * the clock source (end-leaf) must be used. However, clock selectors,
190  * clock multipliers and sample rate converters may be specified as
191  * clock source input to terminal. This functions walks the clock path
192  * to its end and tries to find the source.
193  *
194  * The 'visited' bitfield is used internally to detect recursive loops.
195  *
196  * Returns the clock source UnitID (>=0) on success, or an error.
197  */
198 int snd_usb_clock_find_source(struct snd_usb_audio *chip, int entity_id)
199 {
200  DECLARE_BITMAP(visited, 256);
201  memset(visited, 0, sizeof(visited));
202  return __uac_clock_find_source(chip, entity_id, visited);
203 }
204 
205 static int set_sample_rate_v1(struct snd_usb_audio *chip, int iface,
206  struct usb_host_interface *alts,
207  struct audioformat *fmt, int rate)
208 {
209  struct usb_device *dev = chip->dev;
210  unsigned int ep;
211  unsigned char data[3];
212  int err, crate;
213 
214  ep = get_endpoint(alts, 0)->bEndpointAddress;
215 
216  /* if endpoint doesn't have sampling rate control, bail out */
218  return 0;
219 
220  data[0] = rate;
221  data[1] = rate >> 8;
222  data[2] = rate >> 16;
223  if ((err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), UAC_SET_CUR,
226  data, sizeof(data))) < 0) {
227  snd_printk(KERN_ERR "%d:%d:%d: cannot set freq %d to ep %#x\n",
228  dev->devnum, iface, fmt->altsetting, rate, ep);
229  return err;
230  }
231 
232  if ((err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC_GET_CUR,
235  data, sizeof(data))) < 0) {
236  snd_printk(KERN_WARNING "%d:%d:%d: cannot get freq at ep %#x\n",
237  dev->devnum, iface, fmt->altsetting, ep);
238  return 0; /* some devices don't support reading */
239  }
240 
241  crate = data[0] | (data[1] << 8) | (data[2] << 16);
242  if (crate != rate) {
243  snd_printd(KERN_WARNING "current rate %d is different from the runtime rate %d\n", crate, rate);
244  // runtime->rate = crate;
245  }
246 
247  return 0;
248 }
249 
250 static int set_sample_rate_v2(struct snd_usb_audio *chip, int iface,
251  struct usb_host_interface *alts,
252  struct audioformat *fmt, int rate)
253 {
254  struct usb_device *dev = chip->dev;
255  unsigned char data[4];
256  int err, crate;
257  int clock = snd_usb_clock_find_source(chip, fmt->clock);
258 
259  if (clock < 0)
260  return clock;
261 
262  if (!uac_clock_source_is_valid(chip, clock)) {
263  /* TODO: should we try to find valid clock setups by ourself? */
264  snd_printk(KERN_ERR "%d:%d:%d: clock source %d is not valid, cannot use\n",
265  dev->devnum, iface, fmt->altsetting, clock);
266  return -ENXIO;
267  }
268 
269  data[0] = rate;
270  data[1] = rate >> 8;
271  data[2] = rate >> 16;
272  data[3] = rate >> 24;
273  if ((err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), UAC2_CS_CUR,
276  snd_usb_ctrl_intf(chip) | (clock << 8),
277  data, sizeof(data))) < 0) {
278  snd_printk(KERN_ERR "%d:%d:%d: cannot set freq %d (v2)\n",
279  dev->devnum, iface, fmt->altsetting, rate);
280  return err;
281  }
282 
283  if ((err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC2_CS_CUR,
286  snd_usb_ctrl_intf(chip) | (clock << 8),
287  data, sizeof(data))) < 0) {
288  snd_printk(KERN_WARNING "%d:%d:%d: cannot get freq (v2)\n",
289  dev->devnum, iface, fmt->altsetting);
290  return err;
291  }
292 
293  crate = data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24);
294  if (crate != rate)
295  snd_printd(KERN_WARNING "current rate %d is different from the runtime rate %d\n", crate, rate);
296 
297  return 0;
298 }
299 
300 int snd_usb_init_sample_rate(struct snd_usb_audio *chip, int iface,
301  struct usb_host_interface *alts,
302  struct audioformat *fmt, int rate)
303 {
304  struct usb_interface_descriptor *altsd = get_iface_desc(alts);
305 
306  switch (altsd->bInterfaceProtocol) {
307  case UAC_VERSION_1:
308  default:
309  return set_sample_rate_v1(chip, iface, alts, fmt, rate);
310 
311  case UAC_VERSION_2:
312  return set_sample_rate_v2(chip, iface, alts, fmt, rate);
313  }
314 }
315