aboutsummaryrefslogtreecommitdiffstats
path: root/sound/usb/pcm.c
diff options
context:
space:
mode:
authorDaniel Mack <daniel@caiaq.de>2010-03-04 13:46:17 -0500
committerTakashi Iwai <tiwai@suse.de>2010-03-05 02:19:17 -0500
commit767d75ad1c08c31646498a13837a5c59db90ccad (patch)
tree2f9196d65f63e7da72904f98a46039946e575401 /sound/usb/pcm.c
parent29088fef3e3f62147c1dd53d764da4f04bf3188d (diff)
ALSA: usb-audio: add support for samplerate setting on v2 devices
Sample rate setting is done with a 4-byte long class request that addresses the interface. Signed-off-by: Daniel Mack <daniel@caiaq.de> Cc: Clemens Ladisch <clemens@ladisch.de> Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/usb/pcm.c')
-rw-r--r--sound/usb/pcm.c173
1 files changed, 127 insertions, 46 deletions
diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c
index bd0f84f3a9d2..e0f3f87f99a0 100644
--- a/sound/usb/pcm.c
+++ b/sound/usb/pcm.c
@@ -107,69 +107,150 @@ static struct audioformat *find_format(struct snd_usb_substream *subs, unsigned
107 return found; 107 return found;
108} 108}
109 109
110static int init_pitch_v1(struct snd_usb_audio *chip, int iface,
111 struct usb_host_interface *alts,
112 struct audioformat *fmt)
113{
114 struct usb_device *dev = chip->dev;
115 unsigned int ep;
116 unsigned char data[1];
117 int err;
118
119 ep = get_endpoint(alts, 0)->bEndpointAddress;
120
121 /* if endpoint doesn't have pitch control, bail out */
122 if (!(fmt->attributes & UAC_EP_CS_ATTR_PITCH_CONTROL))
123 return 0;
124
125 data[0] = 1;
126 if ((err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), UAC_SET_CUR,
127 USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_OUT,
128 UAC_EP_CS_ATTR_PITCH_CONTROL << 8, ep,
129 data, sizeof(data), 1000)) < 0) {
130 snd_printk(KERN_ERR "%d:%d:%d: cannot set enable PITCH\n",
131 dev->devnum, iface, ep);
132 return err;
133 }
134
135 return 0;
136}
110 137
111/* 138/*
112 * initialize the picth control and sample rate 139 * initialize the picth control and sample rate
113 */ 140 */
114int snd_usb_init_pitch(struct usb_device *dev, int iface, 141int snd_usb_init_pitch(struct snd_usb_audio *chip, int iface,
115 struct usb_host_interface *alts, 142 struct usb_host_interface *alts,
116 struct audioformat *fmt) 143 struct audioformat *fmt)
117{ 144{
145 struct usb_interface_descriptor *altsd = get_iface_desc(alts);
146
147 switch (altsd->bInterfaceProtocol) {
148 case UAC_VERSION_1:
149 return init_pitch_v1(chip, iface, alts, fmt);
150
151 case UAC_VERSION_2:
152 /* not implemented yet */
153 return 0;
154 }
155
156 return -EINVAL;
157}
158
159static int set_sample_rate_v1(struct snd_usb_audio *chip, int iface,
160 struct usb_host_interface *alts,
161 struct audioformat *fmt, int rate)
162{
163 struct usb_device *dev = chip->dev;
118 unsigned int ep; 164 unsigned int ep;
119 unsigned char data[1]; 165 unsigned char data[3];
120 int err; 166 int err, crate;
121 167
122 ep = get_endpoint(alts, 0)->bEndpointAddress; 168 ep = get_endpoint(alts, 0)->bEndpointAddress;
123 /* if endpoint has pitch control, enable it */ 169 /* if endpoint doesn't have sampling rate control, bail out */
124 if (fmt->attributes & UAC_EP_CS_ATTR_PITCH_CONTROL) { 170 if (!(fmt->attributes & UAC_EP_CS_ATTR_SAMPLE_RATE)) {
125 data[0] = 1; 171 snd_printk(KERN_WARNING "%d:%d:%d: endpoint lacks sample rate attribute bit, cannot set.\n",
126 if ((err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), UAC_SET_CUR, 172 dev->devnum, iface, fmt->altsetting);
127 USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_OUT, 173 return 0;
128 UAC_EP_CS_ATTR_PITCH_CONTROL << 8, ep, data, 1, 1000)) < 0) { 174 }
129 snd_printk(KERN_ERR "%d:%d:%d: cannot set enable PITCH\n", 175
130 dev->devnum, iface, ep); 176 data[0] = rate;
131 return err; 177 data[1] = rate >> 8;
132 } 178 data[2] = rate >> 16;
179 if ((err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), UAC_SET_CUR,
180 USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_OUT,
181 UAC_EP_CS_ATTR_SAMPLE_RATE << 8, ep,
182 data, sizeof(data), 1000)) < 0) {
183 snd_printk(KERN_ERR "%d:%d:%d: cannot set freq %d to ep %#x\n",
184 dev->devnum, iface, fmt->altsetting, rate, ep);
185 return err;
133 } 186 }
187 if ((err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC_GET_CUR,
188 USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_IN,
189 UAC_EP_CS_ATTR_SAMPLE_RATE << 8, ep,
190 data, sizeof(data), 1000)) < 0) {
191 snd_printk(KERN_WARNING "%d:%d:%d: cannot get freq at ep %#x\n",
192 dev->devnum, iface, fmt->altsetting, ep);
193 return 0; /* some devices don't support reading */
194 }
195 crate = data[0] | (data[1] << 8) | (data[2] << 16);
196 if (crate != rate) {
197 snd_printd(KERN_WARNING "current rate %d is different from the runtime rate %d\n", crate, rate);
198 // runtime->rate = crate;
199 }
200
134 return 0; 201 return 0;
135} 202}
136 203
137int snd_usb_init_sample_rate(struct usb_device *dev, int iface, 204static int set_sample_rate_v2(struct snd_usb_audio *chip, int iface,
205 struct usb_host_interface *alts,
206 struct audioformat *fmt, int rate)
207{
208 struct usb_device *dev = chip->dev;
209 unsigned char data[4];
210 int err, crate;
211
212 data[0] = rate;
213 data[1] = rate >> 8;
214 data[2] = rate >> 16;
215 data[3] = rate >> 24;
216 if ((err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), UAC2_CS_CUR,
217 USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT,
218 0x0100, chip->clock_id << 8,
219 data, sizeof(data), 1000)) < 0) {
220 snd_printk(KERN_ERR "%d:%d:%d: cannot set freq %d (v2)\n",
221 dev->devnum, iface, fmt->altsetting, rate);
222 return err;
223 }
224 if ((err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC2_CS_CUR,
225 USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
226 0x0100, chip->clock_id << 8,
227 data, sizeof(data), 1000)) < 0) {
228 snd_printk(KERN_WARNING "%d:%d:%d: cannot get freq (v2)\n",
229 dev->devnum, iface, fmt->altsetting);
230 return err;
231 }
232 crate = data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24);
233 if (crate != rate)
234 snd_printd(KERN_WARNING "current rate %d is different from the runtime rate %d\n", crate, rate);
235
236 return 0;
237}
238
239int snd_usb_init_sample_rate(struct snd_usb_audio *chip, int iface,
138 struct usb_host_interface *alts, 240 struct usb_host_interface *alts,
139 struct audioformat *fmt, int rate) 241 struct audioformat *fmt, int rate)
140{ 242{
141 unsigned int ep; 243 struct usb_interface_descriptor *altsd = get_iface_desc(alts);
142 unsigned char data[3];
143 int err;
144 244
145 ep = get_endpoint(alts, 0)->bEndpointAddress; 245 switch (altsd->bInterfaceProtocol) {
146 /* if endpoint has sampling rate control, set it */ 246 case UAC_VERSION_1:
147 if (fmt->attributes & UAC_EP_CS_ATTR_SAMPLE_RATE) { 247 return set_sample_rate_v1(chip, iface, alts, fmt, rate);
148 int crate; 248
149 data[0] = rate; 249 case UAC_VERSION_2:
150 data[1] = rate >> 8; 250 return set_sample_rate_v2(chip, iface, alts, fmt, rate);
151 data[2] = rate >> 16;
152 if ((err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), UAC_SET_CUR,
153 USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_OUT,
154 UAC_EP_CS_ATTR_SAMPLE_RATE << 8, ep, data, 3, 1000)) < 0) {
155 snd_printk(KERN_ERR "%d:%d:%d: cannot set freq %d to ep %#x\n",
156 dev->devnum, iface, fmt->altsetting, rate, ep);
157 return err;
158 }
159 if ((err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC_GET_CUR,
160 USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_IN,
161 UAC_EP_CS_ATTR_SAMPLE_RATE << 8, ep, data, 3, 1000)) < 0) {
162 snd_printk(KERN_WARNING "%d:%d:%d: cannot get freq at ep %#x\n",
163 dev->devnum, iface, fmt->altsetting, ep);
164 return 0; /* some devices don't support reading */
165 }
166 crate = data[0] | (data[1] << 8) | (data[2] << 16);
167 if (crate != rate) {
168 snd_printd(KERN_WARNING "current rate %d is different from the runtime rate %d\n", crate, rate);
169 // runtime->rate = crate;
170 }
171 } 251 }
172 return 0; 252
253 return -EINVAL;
173} 254}
174 255
175/* 256/*
@@ -280,7 +361,7 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt)
280 if (fmt->attributes & UAC_EP_CS_ATTR_FILL_MAX) 361 if (fmt->attributes & UAC_EP_CS_ATTR_FILL_MAX)
281 subs->fill_max = 1; 362 subs->fill_max = 1;
282 363
283 if ((err = snd_usb_init_pitch(dev, subs->interface, alts, fmt)) < 0) 364 if ((err = snd_usb_init_pitch(subs->stream->chip, subs->interface, alts, fmt)) < 0)
284 return err; 365 return err;
285 366
286 subs->cur_audiofmt = fmt; 367 subs->cur_audiofmt = fmt;
@@ -343,7 +424,7 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream,
343 struct usb_interface *iface; 424 struct usb_interface *iface;
344 iface = usb_ifnum_to_if(subs->dev, fmt->iface); 425 iface = usb_ifnum_to_if(subs->dev, fmt->iface);
345 alts = &iface->altsetting[fmt->altset_idx]; 426 alts = &iface->altsetting[fmt->altset_idx];
346 ret = snd_usb_init_sample_rate(subs->dev, subs->interface, alts, fmt, rate); 427 ret = snd_usb_init_sample_rate(subs->stream->chip, subs->interface, alts, fmt, rate);
347 if (ret < 0) 428 if (ret < 0)
348 return ret; 429 return ret;
349 subs->cur_rate = rate; 430 subs->cur_rate = rate;