diff options
Diffstat (limited to 'sound/usb/pcm.c')
-rw-r--r-- | sound/usb/pcm.c | 270 |
1 files changed, 148 insertions, 122 deletions
diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c index 3cbfae6604f9..78d1cad08a0a 100644 --- a/sound/usb/pcm.c +++ b/sound/usb/pcm.c | |||
@@ -76,10 +76,9 @@ snd_pcm_uframes_t snd_usb_pcm_delay(struct snd_usb_substream *subs, | |||
76 | */ | 76 | */ |
77 | static snd_pcm_uframes_t snd_usb_pcm_pointer(struct snd_pcm_substream *substream) | 77 | static snd_pcm_uframes_t snd_usb_pcm_pointer(struct snd_pcm_substream *substream) |
78 | { | 78 | { |
79 | struct snd_usb_substream *subs; | 79 | struct snd_usb_substream *subs = substream->runtime->private_data; |
80 | unsigned int hwptr_done; | 80 | unsigned int hwptr_done; |
81 | 81 | ||
82 | subs = (struct snd_usb_substream *)substream->runtime->private_data; | ||
83 | if (atomic_read(&subs->stream->chip->shutdown)) | 82 | if (atomic_read(&subs->stream->chip->shutdown)) |
84 | return SNDRV_PCM_POS_XRUN; | 83 | return SNDRV_PCM_POS_XRUN; |
85 | spin_lock(&subs->lock); | 84 | spin_lock(&subs->lock); |
@@ -164,10 +163,11 @@ static int init_pitch_v1(struct snd_usb_audio *chip, int iface, | |||
164 | ep = get_endpoint(alts, 0)->bEndpointAddress; | 163 | ep = get_endpoint(alts, 0)->bEndpointAddress; |
165 | 164 | ||
166 | data[0] = 1; | 165 | data[0] = 1; |
167 | if ((err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), UAC_SET_CUR, | 166 | err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), UAC_SET_CUR, |
168 | USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_OUT, | 167 | USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_OUT, |
169 | UAC_EP_CS_ATTR_PITCH_CONTROL << 8, ep, | 168 | UAC_EP_CS_ATTR_PITCH_CONTROL << 8, ep, |
170 | data, sizeof(data))) < 0) { | 169 | data, sizeof(data)); |
170 | if (err < 0) { | ||
171 | usb_audio_err(chip, "%d:%d: cannot set enable PITCH\n", | 171 | usb_audio_err(chip, "%d:%d: cannot set enable PITCH\n", |
172 | iface, ep); | 172 | iface, ep); |
173 | return err; | 173 | return err; |
@@ -185,10 +185,11 @@ static int init_pitch_v2(struct snd_usb_audio *chip, int iface, | |||
185 | int err; | 185 | int err; |
186 | 186 | ||
187 | data[0] = 1; | 187 | data[0] = 1; |
188 | if ((err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), UAC2_CS_CUR, | 188 | err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), UAC2_CS_CUR, |
189 | USB_TYPE_CLASS | USB_RECIP_ENDPOINT | USB_DIR_OUT, | 189 | USB_TYPE_CLASS | USB_RECIP_ENDPOINT | USB_DIR_OUT, |
190 | UAC2_EP_CS_PITCH << 8, 0, | 190 | UAC2_EP_CS_PITCH << 8, 0, |
191 | data, sizeof(data))) < 0) { | 191 | data, sizeof(data)); |
192 | if (err < 0) { | ||
192 | usb_audio_err(chip, "%d:%d: cannot set enable PITCH (v2)\n", | 193 | usb_audio_err(chip, "%d:%d: cannot set enable PITCH (v2)\n", |
193 | iface, fmt->altsetting); | 194 | iface, fmt->altsetting); |
194 | return err; | 195 | return err; |
@@ -321,6 +322,7 @@ static int set_sync_ep_implicit_fb_quirk(struct snd_usb_substream *subs, | |||
321 | struct usb_host_interface *alts; | 322 | struct usb_host_interface *alts; |
322 | struct usb_interface *iface; | 323 | struct usb_interface *iface; |
323 | unsigned int ep; | 324 | unsigned int ep; |
325 | unsigned int ifnum; | ||
324 | 326 | ||
325 | /* Implicit feedback sync EPs consumers are always playback EPs */ | 327 | /* Implicit feedback sync EPs consumers are always playback EPs */ |
326 | if (subs->direction != SNDRV_PCM_STREAM_PLAYBACK) | 328 | if (subs->direction != SNDRV_PCM_STREAM_PLAYBACK) |
@@ -330,44 +332,27 @@ static int set_sync_ep_implicit_fb_quirk(struct snd_usb_substream *subs, | |||
330 | case USB_ID(0x0763, 0x2030): /* M-Audio Fast Track C400 */ | 332 | case USB_ID(0x0763, 0x2030): /* M-Audio Fast Track C400 */ |
331 | case USB_ID(0x0763, 0x2031): /* M-Audio Fast Track C600 */ | 333 | case USB_ID(0x0763, 0x2031): /* M-Audio Fast Track C600 */ |
332 | ep = 0x81; | 334 | ep = 0x81; |
333 | iface = usb_ifnum_to_if(dev, 3); | 335 | ifnum = 3; |
334 | 336 | goto add_sync_ep_from_ifnum; | |
335 | if (!iface || iface->num_altsetting == 0) | ||
336 | return -EINVAL; | ||
337 | |||
338 | alts = &iface->altsetting[1]; | ||
339 | goto add_sync_ep; | ||
340 | break; | ||
341 | case USB_ID(0x0763, 0x2080): /* M-Audio FastTrack Ultra */ | 337 | case USB_ID(0x0763, 0x2080): /* M-Audio FastTrack Ultra */ |
342 | case USB_ID(0x0763, 0x2081): | 338 | case USB_ID(0x0763, 0x2081): |
343 | ep = 0x81; | 339 | ep = 0x81; |
344 | iface = usb_ifnum_to_if(dev, 2); | 340 | ifnum = 2; |
345 | 341 | goto add_sync_ep_from_ifnum; | |
346 | if (!iface || iface->num_altsetting == 0) | 342 | case USB_ID(0x2466, 0x8003): /* Fractal Audio Axe-Fx II */ |
347 | return -EINVAL; | ||
348 | |||
349 | alts = &iface->altsetting[1]; | ||
350 | goto add_sync_ep; | ||
351 | case USB_ID(0x2466, 0x8003): | ||
352 | ep = 0x86; | 343 | ep = 0x86; |
353 | iface = usb_ifnum_to_if(dev, 2); | 344 | ifnum = 2; |
354 | 345 | goto add_sync_ep_from_ifnum; | |
355 | if (!iface || iface->num_altsetting == 0) | 346 | case USB_ID(0x2466, 0x8010): /* Fractal Audio Axe-Fx III */ |
356 | return -EINVAL; | ||
357 | |||
358 | alts = &iface->altsetting[1]; | ||
359 | goto add_sync_ep; | ||
360 | case USB_ID(0x1397, 0x0002): | ||
361 | ep = 0x81; | 347 | ep = 0x81; |
362 | iface = usb_ifnum_to_if(dev, 1); | 348 | ifnum = 2; |
363 | 349 | goto add_sync_ep_from_ifnum; | |
364 | if (!iface || iface->num_altsetting == 0) | 350 | case USB_ID(0x1397, 0x0002): /* Behringer UFX1204 */ |
365 | return -EINVAL; | 351 | ep = 0x81; |
366 | 352 | ifnum = 1; | |
367 | alts = &iface->altsetting[1]; | 353 | goto add_sync_ep_from_ifnum; |
368 | goto add_sync_ep; | ||
369 | |||
370 | } | 354 | } |
355 | |||
371 | if (attr == USB_ENDPOINT_SYNC_ASYNC && | 356 | if (attr == USB_ENDPOINT_SYNC_ASYNC && |
372 | altsd->bInterfaceClass == USB_CLASS_VENDOR_SPEC && | 357 | altsd->bInterfaceClass == USB_CLASS_VENDOR_SPEC && |
373 | altsd->bInterfaceProtocol == 2 && | 358 | altsd->bInterfaceProtocol == 2 && |
@@ -382,6 +367,14 @@ static int set_sync_ep_implicit_fb_quirk(struct snd_usb_substream *subs, | |||
382 | /* No quirk */ | 367 | /* No quirk */ |
383 | return 0; | 368 | return 0; |
384 | 369 | ||
370 | add_sync_ep_from_ifnum: | ||
371 | iface = usb_ifnum_to_if(dev, ifnum); | ||
372 | |||
373 | if (!iface || iface->num_altsetting == 0) | ||
374 | return -EINVAL; | ||
375 | |||
376 | alts = &iface->altsetting[1]; | ||
377 | |||
385 | add_sync_ep: | 378 | add_sync_ep: |
386 | subs->sync_endpoint = snd_usb_add_endpoint(subs->stream->chip, | 379 | subs->sync_endpoint = snd_usb_add_endpoint(subs->stream->chip, |
387 | alts, ep, !subs->direction, | 380 | alts, ep, !subs->direction, |
@@ -507,7 +500,7 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt) | |||
507 | iface = usb_ifnum_to_if(dev, fmt->iface); | 500 | iface = usb_ifnum_to_if(dev, fmt->iface); |
508 | if (WARN_ON(!iface)) | 501 | if (WARN_ON(!iface)) |
509 | return -EINVAL; | 502 | return -EINVAL; |
510 | alts = &iface->altsetting[fmt->altset_idx]; | 503 | alts = usb_altnum_to_altsetting(iface, fmt->altsetting); |
511 | altsd = get_iface_desc(alts); | 504 | altsd = get_iface_desc(alts); |
512 | if (WARN_ON(altsd->bAlternateSetting != fmt->altsetting)) | 505 | if (WARN_ON(altsd->bAlternateSetting != fmt->altsetting)) |
513 | return -EINVAL; | 506 | return -EINVAL; |
@@ -517,21 +510,21 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt) | |||
517 | 510 | ||
518 | /* close the old interface */ | 511 | /* close the old interface */ |
519 | if (subs->interface >= 0 && subs->interface != fmt->iface) { | 512 | if (subs->interface >= 0 && subs->interface != fmt->iface) { |
520 | err = usb_set_interface(subs->dev, subs->interface, 0); | 513 | if (!subs->stream->chip->keep_iface) { |
521 | if (err < 0) { | 514 | err = usb_set_interface(subs->dev, subs->interface, 0); |
522 | dev_err(&dev->dev, | 515 | if (err < 0) { |
523 | "%d:%d: return to setting 0 failed (%d)\n", | 516 | dev_err(&dev->dev, |
524 | fmt->iface, fmt->altsetting, err); | 517 | "%d:%d: return to setting 0 failed (%d)\n", |
525 | return -EIO; | 518 | fmt->iface, fmt->altsetting, err); |
519 | return -EIO; | ||
520 | } | ||
526 | } | 521 | } |
527 | subs->interface = -1; | 522 | subs->interface = -1; |
528 | subs->altset_idx = 0; | 523 | subs->altset_idx = 0; |
529 | } | 524 | } |
530 | 525 | ||
531 | /* set interface */ | 526 | /* set interface */ |
532 | if (subs->interface != fmt->iface || | 527 | if (iface->cur_altsetting != alts) { |
533 | subs->altset_idx != fmt->altset_idx) { | ||
534 | |||
535 | err = snd_usb_select_mode_quirk(subs, fmt); | 528 | err = snd_usb_select_mode_quirk(subs, fmt); |
536 | if (err < 0) | 529 | if (err < 0) |
537 | return -EIO; | 530 | return -EIO; |
@@ -545,12 +538,11 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt) | |||
545 | } | 538 | } |
546 | dev_dbg(&dev->dev, "setting usb interface %d:%d\n", | 539 | dev_dbg(&dev->dev, "setting usb interface %d:%d\n", |
547 | fmt->iface, fmt->altsetting); | 540 | fmt->iface, fmt->altsetting); |
548 | subs->interface = fmt->iface; | ||
549 | subs->altset_idx = fmt->altset_idx; | ||
550 | |||
551 | snd_usb_set_interface_quirk(dev); | 541 | snd_usb_set_interface_quirk(dev); |
552 | } | 542 | } |
553 | 543 | ||
544 | subs->interface = fmt->iface; | ||
545 | subs->altset_idx = fmt->altset_idx; | ||
554 | subs->data_endpoint = snd_usb_add_endpoint(subs->stream->chip, | 546 | subs->data_endpoint = snd_usb_add_endpoint(subs->stream->chip, |
555 | alts, fmt->endpoint, subs->direction, | 547 | alts, fmt->endpoint, subs->direction, |
556 | SND_USB_ENDPOINT_TYPE_DATA); | 548 | SND_USB_ENDPOINT_TYPE_DATA); |
@@ -736,7 +728,11 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream, | |||
736 | struct audioformat *fmt; | 728 | struct audioformat *fmt; |
737 | int ret; | 729 | int ret; |
738 | 730 | ||
739 | ret = snd_pcm_lib_alloc_vmalloc_buffer(substream, | 731 | if (snd_usb_use_vmalloc) |
732 | ret = snd_pcm_lib_alloc_vmalloc_buffer(substream, | ||
733 | params_buffer_bytes(hw_params)); | ||
734 | else | ||
735 | ret = snd_pcm_lib_malloc_pages(substream, | ||
740 | params_buffer_bytes(hw_params)); | 736 | params_buffer_bytes(hw_params)); |
741 | if (ret < 0) | 737 | if (ret < 0) |
742 | return ret; | 738 | return ret; |
@@ -789,7 +785,11 @@ static int snd_usb_hw_free(struct snd_pcm_substream *substream) | |||
789 | snd_usb_endpoint_deactivate(subs->data_endpoint); | 785 | snd_usb_endpoint_deactivate(subs->data_endpoint); |
790 | snd_usb_unlock_shutdown(subs->stream->chip); | 786 | snd_usb_unlock_shutdown(subs->stream->chip); |
791 | } | 787 | } |
792 | return snd_pcm_lib_free_vmalloc_buffer(substream); | 788 | |
789 | if (snd_usb_use_vmalloc) | ||
790 | return snd_pcm_lib_free_vmalloc_buffer(substream); | ||
791 | else | ||
792 | return snd_pcm_lib_free_pages(substream); | ||
793 | } | 793 | } |
794 | 794 | ||
795 | /* | 795 | /* |
@@ -1181,9 +1181,6 @@ static int setup_hw_info(struct snd_pcm_runtime *runtime, struct snd_usb_substre | |||
1181 | pt = 125 * (1 << fp->datainterval); | 1181 | pt = 125 * (1 << fp->datainterval); |
1182 | ptmin = min(ptmin, pt); | 1182 | ptmin = min(ptmin, pt); |
1183 | } | 1183 | } |
1184 | err = snd_usb_autoresume(subs->stream->chip); | ||
1185 | if (err < 0) | ||
1186 | return err; | ||
1187 | 1184 | ||
1188 | param_period_time_if_needed = SNDRV_PCM_HW_PARAM_PERIOD_TIME; | 1185 | param_period_time_if_needed = SNDRV_PCM_HW_PARAM_PERIOD_TIME; |
1189 | if (subs->speed == USB_SPEED_FULL) | 1186 | if (subs->speed == USB_SPEED_FULL) |
@@ -1192,30 +1189,37 @@ static int setup_hw_info(struct snd_pcm_runtime *runtime, struct snd_usb_substre | |||
1192 | if (ptmin == 1000) | 1189 | if (ptmin == 1000) |
1193 | /* if period time doesn't go below 1 ms, no rules needed */ | 1190 | /* if period time doesn't go below 1 ms, no rules needed */ |
1194 | param_period_time_if_needed = -1; | 1191 | param_period_time_if_needed = -1; |
1195 | snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIOD_TIME, | 1192 | |
1196 | ptmin, UINT_MAX); | 1193 | err = snd_pcm_hw_constraint_minmax(runtime, |
1197 | 1194 | SNDRV_PCM_HW_PARAM_PERIOD_TIME, | |
1198 | if ((err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, | 1195 | ptmin, UINT_MAX); |
1199 | hw_rule_rate, subs, | 1196 | if (err < 0) |
1200 | SNDRV_PCM_HW_PARAM_FORMAT, | 1197 | return err; |
1201 | SNDRV_PCM_HW_PARAM_CHANNELS, | 1198 | |
1202 | param_period_time_if_needed, | 1199 | err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, |
1203 | -1)) < 0) | 1200 | hw_rule_rate, subs, |
1204 | goto rep_err; | 1201 | SNDRV_PCM_HW_PARAM_FORMAT, |
1205 | if ((err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, | 1202 | SNDRV_PCM_HW_PARAM_CHANNELS, |
1206 | hw_rule_channels, subs, | 1203 | param_period_time_if_needed, |
1207 | SNDRV_PCM_HW_PARAM_FORMAT, | 1204 | -1); |
1208 | SNDRV_PCM_HW_PARAM_RATE, | 1205 | if (err < 0) |
1209 | param_period_time_if_needed, | 1206 | return err; |
1210 | -1)) < 0) | 1207 | err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, |
1211 | goto rep_err; | 1208 | hw_rule_channels, subs, |
1212 | if ((err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_FORMAT, | 1209 | SNDRV_PCM_HW_PARAM_FORMAT, |
1213 | hw_rule_format, subs, | 1210 | SNDRV_PCM_HW_PARAM_RATE, |
1214 | SNDRV_PCM_HW_PARAM_RATE, | 1211 | param_period_time_if_needed, |
1215 | SNDRV_PCM_HW_PARAM_CHANNELS, | 1212 | -1); |
1216 | param_period_time_if_needed, | 1213 | if (err < 0) |
1217 | -1)) < 0) | 1214 | return err; |
1218 | goto rep_err; | 1215 | err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_FORMAT, |
1216 | hw_rule_format, subs, | ||
1217 | SNDRV_PCM_HW_PARAM_RATE, | ||
1218 | SNDRV_PCM_HW_PARAM_CHANNELS, | ||
1219 | param_period_time_if_needed, | ||
1220 | -1); | ||
1221 | if (err < 0) | ||
1222 | return err; | ||
1219 | if (param_period_time_if_needed >= 0) { | 1223 | if (param_period_time_if_needed >= 0) { |
1220 | err = snd_pcm_hw_rule_add(runtime, 0, | 1224 | err = snd_pcm_hw_rule_add(runtime, 0, |
1221 | SNDRV_PCM_HW_PARAM_PERIOD_TIME, | 1225 | SNDRV_PCM_HW_PARAM_PERIOD_TIME, |
@@ -1225,19 +1229,18 @@ static int setup_hw_info(struct snd_pcm_runtime *runtime, struct snd_usb_substre | |||
1225 | SNDRV_PCM_HW_PARAM_RATE, | 1229 | SNDRV_PCM_HW_PARAM_RATE, |
1226 | -1); | 1230 | -1); |
1227 | if (err < 0) | 1231 | if (err < 0) |
1228 | goto rep_err; | 1232 | return err; |
1229 | } | 1233 | } |
1230 | if ((err = snd_usb_pcm_check_knot(runtime, subs)) < 0) | 1234 | err = snd_usb_pcm_check_knot(runtime, subs); |
1231 | goto rep_err; | 1235 | if (err < 0) |
1232 | return 0; | 1236 | return err; |
1233 | 1237 | ||
1234 | rep_err: | 1238 | return snd_usb_autoresume(subs->stream->chip); |
1235 | snd_usb_autosuspend(subs->stream->chip); | ||
1236 | return err; | ||
1237 | } | 1239 | } |
1238 | 1240 | ||
1239 | static int snd_usb_pcm_open(struct snd_pcm_substream *substream, int direction) | 1241 | static int snd_usb_pcm_open(struct snd_pcm_substream *substream) |
1240 | { | 1242 | { |
1243 | int direction = substream->stream; | ||
1241 | struct snd_usb_stream *as = snd_pcm_substream_chip(substream); | 1244 | struct snd_usb_stream *as = snd_pcm_substream_chip(substream); |
1242 | struct snd_pcm_runtime *runtime = substream->runtime; | 1245 | struct snd_pcm_runtime *runtime = substream->runtime; |
1243 | struct snd_usb_substream *subs = &as->substream[direction]; | 1246 | struct snd_usb_substream *subs = &as->substream[direction]; |
@@ -1257,14 +1260,16 @@ static int snd_usb_pcm_open(struct snd_pcm_substream *substream, int direction) | |||
1257 | return setup_hw_info(runtime, subs); | 1260 | return setup_hw_info(runtime, subs); |
1258 | } | 1261 | } |
1259 | 1262 | ||
1260 | static int snd_usb_pcm_close(struct snd_pcm_substream *substream, int direction) | 1263 | static int snd_usb_pcm_close(struct snd_pcm_substream *substream) |
1261 | { | 1264 | { |
1265 | int direction = substream->stream; | ||
1262 | struct snd_usb_stream *as = snd_pcm_substream_chip(substream); | 1266 | struct snd_usb_stream *as = snd_pcm_substream_chip(substream); |
1263 | struct snd_usb_substream *subs = &as->substream[direction]; | 1267 | struct snd_usb_substream *subs = &as->substream[direction]; |
1264 | 1268 | ||
1265 | stop_endpoints(subs, true); | 1269 | stop_endpoints(subs, true); |
1266 | 1270 | ||
1267 | if (subs->interface >= 0 && | 1271 | if (!as->chip->keep_iface && |
1272 | subs->interface >= 0 && | ||
1268 | !snd_usb_lock_shutdown(subs->stream->chip)) { | 1273 | !snd_usb_lock_shutdown(subs->stream->chip)) { |
1269 | usb_set_interface(subs->dev, subs->interface, 0); | 1274 | usb_set_interface(subs->dev, subs->interface, 0); |
1270 | subs->interface = -1; | 1275 | subs->interface = -1; |
@@ -1311,7 +1316,7 @@ static void retire_capture_urb(struct snd_usb_substream *subs, | |||
1311 | if (bytes % (runtime->sample_bits >> 3) != 0) { | 1316 | if (bytes % (runtime->sample_bits >> 3) != 0) { |
1312 | int oldbytes = bytes; | 1317 | int oldbytes = bytes; |
1313 | bytes = frames * stride; | 1318 | bytes = frames * stride; |
1314 | dev_warn(&subs->dev->dev, | 1319 | dev_warn_ratelimited(&subs->dev->dev, |
1315 | "Corrected urb data len. %d->%d\n", | 1320 | "Corrected urb data len. %d->%d\n", |
1316 | oldbytes, bytes); | 1321 | oldbytes, bytes); |
1317 | } | 1322 | } |
@@ -1619,26 +1624,6 @@ static void retire_playback_urb(struct snd_usb_substream *subs, | |||
1619 | spin_unlock_irqrestore(&subs->lock, flags); | 1624 | spin_unlock_irqrestore(&subs->lock, flags); |
1620 | } | 1625 | } |
1621 | 1626 | ||
1622 | static int snd_usb_playback_open(struct snd_pcm_substream *substream) | ||
1623 | { | ||
1624 | return snd_usb_pcm_open(substream, SNDRV_PCM_STREAM_PLAYBACK); | ||
1625 | } | ||
1626 | |||
1627 | static int snd_usb_playback_close(struct snd_pcm_substream *substream) | ||
1628 | { | ||
1629 | return snd_usb_pcm_close(substream, SNDRV_PCM_STREAM_PLAYBACK); | ||
1630 | } | ||
1631 | |||
1632 | static int snd_usb_capture_open(struct snd_pcm_substream *substream) | ||
1633 | { | ||
1634 | return snd_usb_pcm_open(substream, SNDRV_PCM_STREAM_CAPTURE); | ||
1635 | } | ||
1636 | |||
1637 | static int snd_usb_capture_close(struct snd_pcm_substream *substream) | ||
1638 | { | ||
1639 | return snd_usb_pcm_close(substream, SNDRV_PCM_STREAM_CAPTURE); | ||
1640 | } | ||
1641 | |||
1642 | static int snd_usb_substream_playback_trigger(struct snd_pcm_substream *substream, | 1627 | static int snd_usb_substream_playback_trigger(struct snd_pcm_substream *substream, |
1643 | int cmd) | 1628 | int cmd) |
1644 | { | 1629 | { |
@@ -1700,8 +1685,8 @@ static int snd_usb_substream_capture_trigger(struct snd_pcm_substream *substream | |||
1700 | } | 1685 | } |
1701 | 1686 | ||
1702 | static const struct snd_pcm_ops snd_usb_playback_ops = { | 1687 | static const struct snd_pcm_ops snd_usb_playback_ops = { |
1703 | .open = snd_usb_playback_open, | 1688 | .open = snd_usb_pcm_open, |
1704 | .close = snd_usb_playback_close, | 1689 | .close = snd_usb_pcm_close, |
1705 | .ioctl = snd_pcm_lib_ioctl, | 1690 | .ioctl = snd_pcm_lib_ioctl, |
1706 | .hw_params = snd_usb_hw_params, | 1691 | .hw_params = snd_usb_hw_params, |
1707 | .hw_free = snd_usb_hw_free, | 1692 | .hw_free = snd_usb_hw_free, |
@@ -1713,8 +1698,8 @@ static const struct snd_pcm_ops snd_usb_playback_ops = { | |||
1713 | }; | 1698 | }; |
1714 | 1699 | ||
1715 | static const struct snd_pcm_ops snd_usb_capture_ops = { | 1700 | static const struct snd_pcm_ops snd_usb_capture_ops = { |
1716 | .open = snd_usb_capture_open, | 1701 | .open = snd_usb_pcm_open, |
1717 | .close = snd_usb_capture_close, | 1702 | .close = snd_usb_pcm_close, |
1718 | .ioctl = snd_pcm_lib_ioctl, | 1703 | .ioctl = snd_pcm_lib_ioctl, |
1719 | .hw_params = snd_usb_hw_params, | 1704 | .hw_params = snd_usb_hw_params, |
1720 | .hw_free = snd_usb_hw_free, | 1705 | .hw_free = snd_usb_hw_free, |
@@ -1725,9 +1710,50 @@ static const struct snd_pcm_ops snd_usb_capture_ops = { | |||
1725 | .mmap = snd_pcm_lib_mmap_vmalloc, | 1710 | .mmap = snd_pcm_lib_mmap_vmalloc, |
1726 | }; | 1711 | }; |
1727 | 1712 | ||
1713 | static const struct snd_pcm_ops snd_usb_playback_dev_ops = { | ||
1714 | .open = snd_usb_pcm_open, | ||
1715 | .close = snd_usb_pcm_close, | ||
1716 | .ioctl = snd_pcm_lib_ioctl, | ||
1717 | .hw_params = snd_usb_hw_params, | ||
1718 | .hw_free = snd_usb_hw_free, | ||
1719 | .prepare = snd_usb_pcm_prepare, | ||
1720 | .trigger = snd_usb_substream_playback_trigger, | ||
1721 | .pointer = snd_usb_pcm_pointer, | ||
1722 | .page = snd_pcm_sgbuf_ops_page, | ||
1723 | }; | ||
1724 | |||
1725 | static const struct snd_pcm_ops snd_usb_capture_dev_ops = { | ||
1726 | .open = snd_usb_pcm_open, | ||
1727 | .close = snd_usb_pcm_close, | ||
1728 | .ioctl = snd_pcm_lib_ioctl, | ||
1729 | .hw_params = snd_usb_hw_params, | ||
1730 | .hw_free = snd_usb_hw_free, | ||
1731 | .prepare = snd_usb_pcm_prepare, | ||
1732 | .trigger = snd_usb_substream_capture_trigger, | ||
1733 | .pointer = snd_usb_pcm_pointer, | ||
1734 | .page = snd_pcm_sgbuf_ops_page, | ||
1735 | }; | ||
1736 | |||
1728 | void snd_usb_set_pcm_ops(struct snd_pcm *pcm, int stream) | 1737 | void snd_usb_set_pcm_ops(struct snd_pcm *pcm, int stream) |
1729 | { | 1738 | { |
1730 | snd_pcm_set_ops(pcm, stream, | 1739 | const struct snd_pcm_ops *ops; |
1731 | stream == SNDRV_PCM_STREAM_PLAYBACK ? | 1740 | |
1732 | &snd_usb_playback_ops : &snd_usb_capture_ops); | 1741 | if (snd_usb_use_vmalloc) |
1742 | ops = stream == SNDRV_PCM_STREAM_PLAYBACK ? | ||
1743 | &snd_usb_playback_ops : &snd_usb_capture_ops; | ||
1744 | else | ||
1745 | ops = stream == SNDRV_PCM_STREAM_PLAYBACK ? | ||
1746 | &snd_usb_playback_dev_ops : &snd_usb_capture_dev_ops; | ||
1747 | snd_pcm_set_ops(pcm, stream, ops); | ||
1748 | } | ||
1749 | |||
1750 | void snd_usb_preallocate_buffer(struct snd_usb_substream *subs) | ||
1751 | { | ||
1752 | struct snd_pcm *pcm = subs->stream->pcm; | ||
1753 | struct snd_pcm_substream *s = pcm->streams[subs->direction].substream; | ||
1754 | struct device *dev = subs->dev->bus->controller; | ||
1755 | |||
1756 | if (!snd_usb_use_vmalloc) | ||
1757 | snd_pcm_lib_preallocate_pages(s, SNDRV_DMA_TYPE_DEV_SG, | ||
1758 | dev, 64*1024, 512*1024); | ||
1733 | } | 1759 | } |