diff options
| -rw-r--r-- | sound/usb/endpoint.c | 4 | ||||
| -rw-r--r-- | sound/usb/pcm.c | 173 | ||||
| -rw-r--r-- | sound/usb/pcm.h | 4 | ||||
| -rw-r--r-- | sound/usb/quirks.c | 4 |
4 files changed, 133 insertions, 52 deletions
diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c index d65235c0106a..91850f84cad6 100644 --- a/sound/usb/endpoint.c +++ b/sound/usb/endpoint.c | |||
| @@ -350,8 +350,8 @@ int snd_usb_parse_audio_endpoints(struct snd_usb_audio *chip, int iface_no) | |||
| 350 | } | 350 | } |
| 351 | /* try to set the interface... */ | 351 | /* try to set the interface... */ |
| 352 | usb_set_interface(chip->dev, iface_no, altno); | 352 | usb_set_interface(chip->dev, iface_no, altno); |
| 353 | snd_usb_init_pitch(chip->dev, iface_no, alts, fp); | 353 | snd_usb_init_pitch(chip, iface_no, alts, fp); |
| 354 | snd_usb_init_sample_rate(chip->dev, iface_no, alts, fp, fp->rate_max); | 354 | snd_usb_init_sample_rate(chip, iface_no, alts, fp, fp->rate_max); |
| 355 | } | 355 | } |
| 356 | return 0; | 356 | return 0; |
| 357 | } | 357 | } |
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 | ||
| 110 | static 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 | */ |
| 114 | int snd_usb_init_pitch(struct usb_device *dev, int iface, | 141 | int 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 | |||
| 159 | static 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 | ||
| 137 | int snd_usb_init_sample_rate(struct usb_device *dev, int iface, | 204 | static 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 | |||
| 239 | int 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; |
diff --git a/sound/usb/pcm.h b/sound/usb/pcm.h index 85856016e056..1c931b68f3b5 100644 --- a/sound/usb/pcm.h +++ b/sound/usb/pcm.h | |||
| @@ -3,11 +3,11 @@ | |||
| 3 | 3 | ||
| 4 | void snd_usb_set_pcm_ops(struct snd_pcm *pcm, int stream); | 4 | void snd_usb_set_pcm_ops(struct snd_pcm *pcm, int stream); |
| 5 | 5 | ||
| 6 | int snd_usb_init_pitch(struct usb_device *dev, int iface, | 6 | int snd_usb_init_pitch(struct snd_usb_audio *chip, int iface, |
| 7 | struct usb_host_interface *alts, | 7 | struct usb_host_interface *alts, |
| 8 | struct audioformat *fmt); | 8 | struct audioformat *fmt); |
| 9 | 9 | ||
| 10 | int snd_usb_init_sample_rate(struct usb_device *dev, int iface, | 10 | int snd_usb_init_sample_rate(struct snd_usb_audio *chip, int iface, |
| 11 | struct usb_host_interface *alts, | 11 | struct usb_host_interface *alts, |
| 12 | struct audioformat *fmt, int rate); | 12 | struct audioformat *fmt, int rate); |
| 13 | 13 | ||
diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c index 99a19ba43207..0c0b23b63794 100644 --- a/sound/usb/quirks.c +++ b/sound/usb/quirks.c | |||
| @@ -159,8 +159,8 @@ static int create_fixed_stream_quirk(struct snd_usb_audio *chip, | |||
| 159 | fp->datainterval = snd_usb_parse_datainterval(chip, alts); | 159 | fp->datainterval = snd_usb_parse_datainterval(chip, alts); |
| 160 | fp->maxpacksize = le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize); | 160 | fp->maxpacksize = le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize); |
| 161 | usb_set_interface(chip->dev, fp->iface, 0); | 161 | usb_set_interface(chip->dev, fp->iface, 0); |
| 162 | snd_usb_init_pitch(chip->dev, fp->iface, alts, fp); | 162 | snd_usb_init_pitch(chip, fp->iface, alts, fp); |
| 163 | snd_usb_init_sample_rate(chip->dev, fp->iface, alts, fp, fp->rate_max); | 163 | snd_usb_init_sample_rate(chip, fp->iface, alts, fp, fp->rate_max); |
| 164 | return 0; | 164 | return 0; |
| 165 | } | 165 | } |
| 166 | 166 | ||
