diff options
Diffstat (limited to 'sound/usb/usbaudio.c')
-rw-r--r-- | sound/usb/usbaudio.c | 189 |
1 files changed, 131 insertions, 58 deletions
diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c index 19bdcc74c96c..4dfb91d4398a 100644 --- a/sound/usb/usbaudio.c +++ b/sound/usb/usbaudio.c | |||
@@ -186,6 +186,7 @@ struct snd_usb_substream { | |||
186 | u64 formats; /* format bitmasks (all or'ed) */ | 186 | u64 formats; /* format bitmasks (all or'ed) */ |
187 | unsigned int num_formats; /* number of supported audio formats (list) */ | 187 | unsigned int num_formats; /* number of supported audio formats (list) */ |
188 | struct list_head fmt_list; /* format list */ | 188 | struct list_head fmt_list; /* format list */ |
189 | struct snd_pcm_hw_constraint_list rate_list; /* limited rates */ | ||
189 | spinlock_t lock; | 190 | spinlock_t lock; |
190 | 191 | ||
191 | struct snd_urb_ops ops; /* callbacks (must be filled at init) */ | 192 | struct snd_urb_ops ops; /* callbacks (must be filled at init) */ |
@@ -253,7 +254,7 @@ static int prepare_capture_sync_urb(struct snd_usb_substream *subs, | |||
253 | struct urb *urb) | 254 | struct urb *urb) |
254 | { | 255 | { |
255 | unsigned char *cp = urb->transfer_buffer; | 256 | unsigned char *cp = urb->transfer_buffer; |
256 | struct snd_urb_ctx *ctx = (struct snd_urb_ctx *)urb->context; | 257 | struct snd_urb_ctx *ctx = urb->context; |
257 | 258 | ||
258 | urb->dev = ctx->subs->dev; /* we need to set this at each time */ | 259 | urb->dev = ctx->subs->dev; /* we need to set this at each time */ |
259 | urb->iso_frame_desc[0].length = 3; | 260 | urb->iso_frame_desc[0].length = 3; |
@@ -275,7 +276,7 @@ static int prepare_capture_sync_urb_hs(struct snd_usb_substream *subs, | |||
275 | struct urb *urb) | 276 | struct urb *urb) |
276 | { | 277 | { |
277 | unsigned char *cp = urb->transfer_buffer; | 278 | unsigned char *cp = urb->transfer_buffer; |
278 | struct snd_urb_ctx *ctx = (struct snd_urb_ctx *)urb->context; | 279 | struct snd_urb_ctx *ctx = urb->context; |
279 | 280 | ||
280 | urb->dev = ctx->subs->dev; /* we need to set this at each time */ | 281 | urb->dev = ctx->subs->dev; /* we need to set this at each time */ |
281 | urb->iso_frame_desc[0].length = 4; | 282 | urb->iso_frame_desc[0].length = 4; |
@@ -313,7 +314,7 @@ static int prepare_capture_urb(struct snd_usb_substream *subs, | |||
313 | struct urb *urb) | 314 | struct urb *urb) |
314 | { | 315 | { |
315 | int i, offs; | 316 | int i, offs; |
316 | struct snd_urb_ctx *ctx = (struct snd_urb_ctx *)urb->context; | 317 | struct snd_urb_ctx *ctx = urb->context; |
317 | 318 | ||
318 | offs = 0; | 319 | offs = 0; |
319 | urb->dev = ctx->subs->dev; /* we need to set this at each time */ | 320 | urb->dev = ctx->subs->dev; /* we need to set this at each time */ |
@@ -391,6 +392,16 @@ static int retire_capture_urb(struct snd_usb_substream *subs, | |||
391 | return 0; | 392 | return 0; |
392 | } | 393 | } |
393 | 394 | ||
395 | /* | ||
396 | * Process after capture complete when paused. Nothing to do. | ||
397 | */ | ||
398 | static int retire_paused_capture_urb(struct snd_usb_substream *subs, | ||
399 | struct snd_pcm_runtime *runtime, | ||
400 | struct urb *urb) | ||
401 | { | ||
402 | return 0; | ||
403 | } | ||
404 | |||
394 | 405 | ||
395 | /* | 406 | /* |
396 | * prepare urb for full speed playback sync pipe | 407 | * prepare urb for full speed playback sync pipe |
@@ -402,7 +413,7 @@ static int prepare_playback_sync_urb(struct snd_usb_substream *subs, | |||
402 | struct snd_pcm_runtime *runtime, | 413 | struct snd_pcm_runtime *runtime, |
403 | struct urb *urb) | 414 | struct urb *urb) |
404 | { | 415 | { |
405 | struct snd_urb_ctx *ctx = (struct snd_urb_ctx *)urb->context; | 416 | struct snd_urb_ctx *ctx = urb->context; |
406 | 417 | ||
407 | urb->dev = ctx->subs->dev; /* we need to set this at each time */ | 418 | urb->dev = ctx->subs->dev; /* we need to set this at each time */ |
408 | urb->iso_frame_desc[0].length = 3; | 419 | urb->iso_frame_desc[0].length = 3; |
@@ -420,7 +431,7 @@ static int prepare_playback_sync_urb_hs(struct snd_usb_substream *subs, | |||
420 | struct snd_pcm_runtime *runtime, | 431 | struct snd_pcm_runtime *runtime, |
421 | struct urb *urb) | 432 | struct urb *urb) |
422 | { | 433 | { |
423 | struct snd_urb_ctx *ctx = (struct snd_urb_ctx *)urb->context; | 434 | struct snd_urb_ctx *ctx = urb->context; |
424 | 435 | ||
425 | urb->dev = ctx->subs->dev; /* we need to set this at each time */ | 436 | urb->dev = ctx->subs->dev; /* we need to set this at each time */ |
426 | urb->iso_frame_desc[0].length = 4; | 437 | urb->iso_frame_desc[0].length = 4; |
@@ -493,13 +504,13 @@ static int snd_usb_audio_next_packet_size(struct snd_usb_substream *subs) | |||
493 | } | 504 | } |
494 | 505 | ||
495 | /* | 506 | /* |
496 | * Prepare urb for streaming before playback starts. | 507 | * Prepare urb for streaming before playback starts or when paused. |
497 | * | 508 | * |
498 | * We don't yet have data, so we send a frame of silence. | 509 | * We don't have any data, so we send a frame of silence. |
499 | */ | 510 | */ |
500 | static int prepare_startup_playback_urb(struct snd_usb_substream *subs, | 511 | static int prepare_nodata_playback_urb(struct snd_usb_substream *subs, |
501 | struct snd_pcm_runtime *runtime, | 512 | struct snd_pcm_runtime *runtime, |
502 | struct urb *urb) | 513 | struct urb *urb) |
503 | { | 514 | { |
504 | unsigned int i, offs, counts; | 515 | unsigned int i, offs, counts; |
505 | struct snd_urb_ctx *ctx = urb->context; | 516 | struct snd_urb_ctx *ctx = urb->context; |
@@ -537,7 +548,7 @@ static int prepare_playback_urb(struct snd_usb_substream *subs, | |||
537 | unsigned int counts; | 548 | unsigned int counts; |
538 | unsigned long flags; | 549 | unsigned long flags; |
539 | int period_elapsed = 0; | 550 | int period_elapsed = 0; |
540 | struct snd_urb_ctx *ctx = (struct snd_urb_ctx *)urb->context; | 551 | struct snd_urb_ctx *ctx = urb->context; |
541 | 552 | ||
542 | stride = runtime->frame_bits >> 3; | 553 | stride = runtime->frame_bits >> 3; |
543 | 554 | ||
@@ -622,7 +633,7 @@ static int retire_playback_urb(struct snd_usb_substream *subs, | |||
622 | */ | 633 | */ |
623 | static struct snd_urb_ops audio_urb_ops[2] = { | 634 | static struct snd_urb_ops audio_urb_ops[2] = { |
624 | { | 635 | { |
625 | .prepare = prepare_startup_playback_urb, | 636 | .prepare = prepare_nodata_playback_urb, |
626 | .retire = retire_playback_urb, | 637 | .retire = retire_playback_urb, |
627 | .prepare_sync = prepare_playback_sync_urb, | 638 | .prepare_sync = prepare_playback_sync_urb, |
628 | .retire_sync = retire_playback_sync_urb, | 639 | .retire_sync = retire_playback_sync_urb, |
@@ -637,7 +648,7 @@ static struct snd_urb_ops audio_urb_ops[2] = { | |||
637 | 648 | ||
638 | static struct snd_urb_ops audio_urb_ops_high_speed[2] = { | 649 | static struct snd_urb_ops audio_urb_ops_high_speed[2] = { |
639 | { | 650 | { |
640 | .prepare = prepare_startup_playback_urb, | 651 | .prepare = prepare_nodata_playback_urb, |
641 | .retire = retire_playback_urb, | 652 | .retire = retire_playback_urb, |
642 | .prepare_sync = prepare_playback_sync_urb_hs, | 653 | .prepare_sync = prepare_playback_sync_urb_hs, |
643 | .retire_sync = retire_playback_sync_urb_hs, | 654 | .retire_sync = retire_playback_sync_urb_hs, |
@@ -655,7 +666,7 @@ static struct snd_urb_ops audio_urb_ops_high_speed[2] = { | |||
655 | */ | 666 | */ |
656 | static void snd_complete_urb(struct urb *urb) | 667 | static void snd_complete_urb(struct urb *urb) |
657 | { | 668 | { |
658 | struct snd_urb_ctx *ctx = (struct snd_urb_ctx *)urb->context; | 669 | struct snd_urb_ctx *ctx = urb->context; |
659 | struct snd_usb_substream *subs = ctx->subs; | 670 | struct snd_usb_substream *subs = ctx->subs; |
660 | struct snd_pcm_substream *substream = ctx->subs->pcm_substream; | 671 | struct snd_pcm_substream *substream = ctx->subs->pcm_substream; |
661 | int err = 0; | 672 | int err = 0; |
@@ -678,7 +689,7 @@ static void snd_complete_urb(struct urb *urb) | |||
678 | */ | 689 | */ |
679 | static void snd_complete_sync_urb(struct urb *urb) | 690 | static void snd_complete_sync_urb(struct urb *urb) |
680 | { | 691 | { |
681 | struct snd_urb_ctx *ctx = (struct snd_urb_ctx *)urb->context; | 692 | struct snd_urb_ctx *ctx = urb->context; |
682 | struct snd_usb_substream *subs = ctx->subs; | 693 | struct snd_usb_substream *subs = ctx->subs; |
683 | struct snd_pcm_substream *substream = ctx->subs->pcm_substream; | 694 | struct snd_pcm_substream *substream = ctx->subs->pcm_substream; |
684 | int err = 0; | 695 | int err = 0; |
@@ -925,10 +936,14 @@ static int snd_usb_pcm_playback_trigger(struct snd_pcm_substream *substream, | |||
925 | 936 | ||
926 | switch (cmd) { | 937 | switch (cmd) { |
927 | case SNDRV_PCM_TRIGGER_START: | 938 | case SNDRV_PCM_TRIGGER_START: |
939 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | ||
928 | subs->ops.prepare = prepare_playback_urb; | 940 | subs->ops.prepare = prepare_playback_urb; |
929 | return 0; | 941 | return 0; |
930 | case SNDRV_PCM_TRIGGER_STOP: | 942 | case SNDRV_PCM_TRIGGER_STOP: |
931 | return deactivate_urbs(subs, 0, 0); | 943 | return deactivate_urbs(subs, 0, 0); |
944 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | ||
945 | subs->ops.prepare = prepare_nodata_playback_urb; | ||
946 | return 0; | ||
932 | default: | 947 | default: |
933 | return -EINVAL; | 948 | return -EINVAL; |
934 | } | 949 | } |
@@ -944,9 +959,16 @@ static int snd_usb_pcm_capture_trigger(struct snd_pcm_substream *substream, | |||
944 | 959 | ||
945 | switch (cmd) { | 960 | switch (cmd) { |
946 | case SNDRV_PCM_TRIGGER_START: | 961 | case SNDRV_PCM_TRIGGER_START: |
962 | subs->ops.retire = retire_capture_urb; | ||
947 | return start_urbs(subs, substream->runtime); | 963 | return start_urbs(subs, substream->runtime); |
948 | case SNDRV_PCM_TRIGGER_STOP: | 964 | case SNDRV_PCM_TRIGGER_STOP: |
949 | return deactivate_urbs(subs, 0, 0); | 965 | return deactivate_urbs(subs, 0, 0); |
966 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | ||
967 | subs->ops.retire = retire_paused_capture_urb; | ||
968 | return 0; | ||
969 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | ||
970 | subs->ops.retire = retire_capture_urb; | ||
971 | return 0; | ||
950 | default: | 972 | default: |
951 | return -EINVAL; | 973 | return -EINVAL; |
952 | } | 974 | } |
@@ -1408,7 +1430,7 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt) | |||
1408 | static int snd_usb_hw_params(struct snd_pcm_substream *substream, | 1430 | static int snd_usb_hw_params(struct snd_pcm_substream *substream, |
1409 | struct snd_pcm_hw_params *hw_params) | 1431 | struct snd_pcm_hw_params *hw_params) |
1410 | { | 1432 | { |
1411 | struct snd_usb_substream *subs = (struct snd_usb_substream *)substream->runtime->private_data; | 1433 | struct snd_usb_substream *subs = substream->runtime->private_data; |
1412 | struct audioformat *fmt; | 1434 | struct audioformat *fmt; |
1413 | unsigned int channels, rate, format; | 1435 | unsigned int channels, rate, format; |
1414 | int ret, changed; | 1436 | int ret, changed; |
@@ -1464,7 +1486,7 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream, | |||
1464 | */ | 1486 | */ |
1465 | static int snd_usb_hw_free(struct snd_pcm_substream *substream) | 1487 | static int snd_usb_hw_free(struct snd_pcm_substream *substream) |
1466 | { | 1488 | { |
1467 | struct snd_usb_substream *subs = (struct snd_usb_substream *)substream->runtime->private_data; | 1489 | struct snd_usb_substream *subs = substream->runtime->private_data; |
1468 | 1490 | ||
1469 | subs->cur_audiofmt = NULL; | 1491 | subs->cur_audiofmt = NULL; |
1470 | subs->cur_rate = 0; | 1492 | subs->cur_rate = 0; |
@@ -1505,33 +1527,20 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream) | |||
1505 | /* for playback, submit the URBs now; otherwise, the first hwptr_done | 1527 | /* for playback, submit the URBs now; otherwise, the first hwptr_done |
1506 | * updates for all URBs would happen at the same time when starting */ | 1528 | * updates for all URBs would happen at the same time when starting */ |
1507 | if (subs->direction == SNDRV_PCM_STREAM_PLAYBACK) { | 1529 | if (subs->direction == SNDRV_PCM_STREAM_PLAYBACK) { |
1508 | subs->ops.prepare = prepare_startup_playback_urb; | 1530 | subs->ops.prepare = prepare_nodata_playback_urb; |
1509 | return start_urbs(subs, runtime); | 1531 | return start_urbs(subs, runtime); |
1510 | } else | 1532 | } else |
1511 | return 0; | 1533 | return 0; |
1512 | } | 1534 | } |
1513 | 1535 | ||
1514 | static struct snd_pcm_hardware snd_usb_playback = | 1536 | static struct snd_pcm_hardware snd_usb_hardware = |
1515 | { | 1537 | { |
1516 | .info = SNDRV_PCM_INFO_MMAP | | 1538 | .info = SNDRV_PCM_INFO_MMAP | |
1517 | SNDRV_PCM_INFO_MMAP_VALID | | 1539 | SNDRV_PCM_INFO_MMAP_VALID | |
1518 | SNDRV_PCM_INFO_BATCH | | 1540 | SNDRV_PCM_INFO_BATCH | |
1519 | SNDRV_PCM_INFO_INTERLEAVED | | 1541 | SNDRV_PCM_INFO_INTERLEAVED | |
1520 | SNDRV_PCM_INFO_BLOCK_TRANSFER, | 1542 | SNDRV_PCM_INFO_BLOCK_TRANSFER | |
1521 | .buffer_bytes_max = 1024 * 1024, | 1543 | SNDRV_PCM_INFO_PAUSE, |
1522 | .period_bytes_min = 64, | ||
1523 | .period_bytes_max = 512 * 1024, | ||
1524 | .periods_min = 2, | ||
1525 | .periods_max = 1024, | ||
1526 | }; | ||
1527 | |||
1528 | static struct snd_pcm_hardware snd_usb_capture = | ||
1529 | { | ||
1530 | .info = SNDRV_PCM_INFO_MMAP | | ||
1531 | SNDRV_PCM_INFO_MMAP_VALID | | ||
1532 | SNDRV_PCM_INFO_BATCH | | ||
1533 | SNDRV_PCM_INFO_INTERLEAVED | | ||
1534 | SNDRV_PCM_INFO_BLOCK_TRANSFER, | ||
1535 | .buffer_bytes_max = 1024 * 1024, | 1544 | .buffer_bytes_max = 1024 * 1024, |
1536 | .period_bytes_min = 64, | 1545 | .period_bytes_min = 64, |
1537 | .period_bytes_max = 512 * 1024, | 1546 | .period_bytes_max = 512 * 1024, |
@@ -1810,28 +1819,33 @@ static int check_hw_params_convention(struct snd_usb_substream *subs) | |||
1810 | static int snd_usb_pcm_check_knot(struct snd_pcm_runtime *runtime, | 1819 | static int snd_usb_pcm_check_knot(struct snd_pcm_runtime *runtime, |
1811 | struct snd_usb_substream *subs) | 1820 | struct snd_usb_substream *subs) |
1812 | { | 1821 | { |
1813 | struct list_head *p; | 1822 | struct audioformat *fp; |
1814 | struct snd_pcm_hw_constraint_list constraints_rates; | 1823 | int count = 0, needs_knot = 0; |
1815 | int err; | 1824 | int err; |
1816 | 1825 | ||
1817 | list_for_each(p, &subs->fmt_list) { | 1826 | list_for_each_entry(fp, &subs->fmt_list, list) { |
1818 | struct audioformat *fp; | 1827 | if (fp->rates & SNDRV_PCM_RATE_CONTINUOUS) |
1819 | fp = list_entry(p, struct audioformat, list); | 1828 | return 0; |
1820 | 1829 | count += fp->nr_rates; | |
1821 | if (!fp->needs_knot) | 1830 | if (fp->needs_knot) |
1822 | continue; | 1831 | needs_knot = 1; |
1823 | |||
1824 | constraints_rates.count = fp->nr_rates; | ||
1825 | constraints_rates.list = fp->rate_table; | ||
1826 | constraints_rates.mask = 0; | ||
1827 | |||
1828 | err = snd_pcm_hw_constraint_list(runtime, 0, | ||
1829 | SNDRV_PCM_HW_PARAM_RATE, | ||
1830 | &constraints_rates); | ||
1831 | |||
1832 | if (err < 0) | ||
1833 | return err; | ||
1834 | } | 1832 | } |
1833 | if (!needs_knot) | ||
1834 | return 0; | ||
1835 | |||
1836 | subs->rate_list.count = count; | ||
1837 | subs->rate_list.list = kmalloc(sizeof(int) * count, GFP_KERNEL); | ||
1838 | subs->rate_list.mask = 0; | ||
1839 | count = 0; | ||
1840 | list_for_each_entry(fp, &subs->fmt_list, list) { | ||
1841 | int i; | ||
1842 | for (i = 0; i < fp->nr_rates; i++) | ||
1843 | subs->rate_list.list[count++] = fp->rate_table[i]; | ||
1844 | } | ||
1845 | err = snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, | ||
1846 | &subs->rate_list); | ||
1847 | if (err < 0) | ||
1848 | return err; | ||
1835 | 1849 | ||
1836 | return 0; | 1850 | return 0; |
1837 | } | 1851 | } |
@@ -1904,8 +1918,7 @@ static int setup_hw_info(struct snd_pcm_runtime *runtime, struct snd_usb_substre | |||
1904 | return 0; | 1918 | return 0; |
1905 | } | 1919 | } |
1906 | 1920 | ||
1907 | static int snd_usb_pcm_open(struct snd_pcm_substream *substream, int direction, | 1921 | static int snd_usb_pcm_open(struct snd_pcm_substream *substream, int direction) |
1908 | struct snd_pcm_hardware *hw) | ||
1909 | { | 1922 | { |
1910 | struct snd_usb_stream *as = snd_pcm_substream_chip(substream); | 1923 | struct snd_usb_stream *as = snd_pcm_substream_chip(substream); |
1911 | struct snd_pcm_runtime *runtime = substream->runtime; | 1924 | struct snd_pcm_runtime *runtime = substream->runtime; |
@@ -1913,7 +1926,7 @@ static int snd_usb_pcm_open(struct snd_pcm_substream *substream, int direction, | |||
1913 | 1926 | ||
1914 | subs->interface = -1; | 1927 | subs->interface = -1; |
1915 | subs->format = 0; | 1928 | subs->format = 0; |
1916 | runtime->hw = *hw; | 1929 | runtime->hw = snd_usb_hardware; |
1917 | runtime->private_data = subs; | 1930 | runtime->private_data = subs; |
1918 | subs->pcm_substream = substream; | 1931 | subs->pcm_substream = substream; |
1919 | return setup_hw_info(runtime, subs); | 1932 | return setup_hw_info(runtime, subs); |
@@ -1934,7 +1947,7 @@ static int snd_usb_pcm_close(struct snd_pcm_substream *substream, int direction) | |||
1934 | 1947 | ||
1935 | static int snd_usb_playback_open(struct snd_pcm_substream *substream) | 1948 | static int snd_usb_playback_open(struct snd_pcm_substream *substream) |
1936 | { | 1949 | { |
1937 | return snd_usb_pcm_open(substream, SNDRV_PCM_STREAM_PLAYBACK, &snd_usb_playback); | 1950 | return snd_usb_pcm_open(substream, SNDRV_PCM_STREAM_PLAYBACK); |
1938 | } | 1951 | } |
1939 | 1952 | ||
1940 | static int snd_usb_playback_close(struct snd_pcm_substream *substream) | 1953 | static int snd_usb_playback_close(struct snd_pcm_substream *substream) |
@@ -1944,7 +1957,7 @@ static int snd_usb_playback_close(struct snd_pcm_substream *substream) | |||
1944 | 1957 | ||
1945 | static int snd_usb_capture_open(struct snd_pcm_substream *substream) | 1958 | static int snd_usb_capture_open(struct snd_pcm_substream *substream) |
1946 | { | 1959 | { |
1947 | return snd_usb_pcm_open(substream, SNDRV_PCM_STREAM_CAPTURE, &snd_usb_capture); | 1960 | return snd_usb_pcm_open(substream, SNDRV_PCM_STREAM_CAPTURE); |
1948 | } | 1961 | } |
1949 | 1962 | ||
1950 | static int snd_usb_capture_close(struct snd_pcm_substream *substream) | 1963 | static int snd_usb_capture_close(struct snd_pcm_substream *substream) |
@@ -2231,6 +2244,7 @@ static void free_substream(struct snd_usb_substream *subs) | |||
2231 | kfree(fp->rate_table); | 2244 | kfree(fp->rate_table); |
2232 | kfree(fp); | 2245 | kfree(fp); |
2233 | } | 2246 | } |
2247 | kfree(subs->rate_list.list); | ||
2234 | } | 2248 | } |
2235 | 2249 | ||
2236 | 2250 | ||
@@ -2456,6 +2470,7 @@ static int parse_audio_format_rates(struct snd_usb_audio *chip, struct audioform | |||
2456 | * build the rate table and bitmap flags | 2470 | * build the rate table and bitmap flags |
2457 | */ | 2471 | */ |
2458 | int r, idx, c; | 2472 | int r, idx, c; |
2473 | unsigned int nonzero_rates = 0; | ||
2459 | /* this table corresponds to the SNDRV_PCM_RATE_XXX bit */ | 2474 | /* this table corresponds to the SNDRV_PCM_RATE_XXX bit */ |
2460 | static unsigned int conv_rates[] = { | 2475 | static unsigned int conv_rates[] = { |
2461 | 5512, 8000, 11025, 16000, 22050, 32000, 44100, 48000, | 2476 | 5512, 8000, 11025, 16000, 22050, 32000, 44100, 48000, |
@@ -2478,6 +2493,7 @@ static int parse_audio_format_rates(struct snd_usb_audio *chip, struct audioform | |||
2478 | fp->altsetting == 5 && fp->maxpacksize == 392) | 2493 | fp->altsetting == 5 && fp->maxpacksize == 392) |
2479 | rate = 96000; | 2494 | rate = 96000; |
2480 | fp->rate_table[r] = rate; | 2495 | fp->rate_table[r] = rate; |
2496 | nonzero_rates |= rate; | ||
2481 | if (rate < fp->rate_min) | 2497 | if (rate < fp->rate_min) |
2482 | fp->rate_min = rate; | 2498 | fp->rate_min = rate; |
2483 | else if (rate > fp->rate_max) | 2499 | else if (rate > fp->rate_max) |
@@ -2493,6 +2509,10 @@ static int parse_audio_format_rates(struct snd_usb_audio *chip, struct audioform | |||
2493 | if (!found) | 2509 | if (!found) |
2494 | fp->needs_knot = 1; | 2510 | fp->needs_knot = 1; |
2495 | } | 2511 | } |
2512 | if (!nonzero_rates) { | ||
2513 | hwc_debug("All rates were zero. Skipping format!\n"); | ||
2514 | return -1; | ||
2515 | } | ||
2496 | if (fp->needs_knot) | 2516 | if (fp->needs_knot) |
2497 | fp->rates |= SNDRV_PCM_RATE_KNOT; | 2517 | fp->rates |= SNDRV_PCM_RATE_KNOT; |
2498 | } else { | 2518 | } else { |
@@ -3057,6 +3077,58 @@ static int create_ua1000_quirk(struct snd_usb_audio *chip, | |||
3057 | return 0; | 3077 | return 0; |
3058 | } | 3078 | } |
3059 | 3079 | ||
3080 | /* | ||
3081 | * Create a stream for an Edirol UA-101 interface. | ||
3082 | * Copy, paste and modify from Edirol UA-1000 | ||
3083 | */ | ||
3084 | static int create_ua101_quirk(struct snd_usb_audio *chip, | ||
3085 | struct usb_interface *iface, | ||
3086 | const struct snd_usb_audio_quirk *quirk) | ||
3087 | { | ||
3088 | static const struct audioformat ua101_format = { | ||
3089 | .format = SNDRV_PCM_FORMAT_S32_LE, | ||
3090 | .fmt_type = USB_FORMAT_TYPE_I, | ||
3091 | .altsetting = 1, | ||
3092 | .altset_idx = 1, | ||
3093 | .attributes = 0, | ||
3094 | .rates = SNDRV_PCM_RATE_CONTINUOUS, | ||
3095 | }; | ||
3096 | struct usb_host_interface *alts; | ||
3097 | struct usb_interface_descriptor *altsd; | ||
3098 | struct audioformat *fp; | ||
3099 | int stream, err; | ||
3100 | |||
3101 | if (iface->num_altsetting != 2) | ||
3102 | return -ENXIO; | ||
3103 | alts = &iface->altsetting[1]; | ||
3104 | altsd = get_iface_desc(alts); | ||
3105 | if (alts->extralen != 18 || alts->extra[1] != USB_DT_CS_INTERFACE || | ||
3106 | altsd->bNumEndpoints != 1) | ||
3107 | return -ENXIO; | ||
3108 | |||
3109 | fp = kmemdup(&ua101_format, sizeof(*fp), GFP_KERNEL); | ||
3110 | if (!fp) | ||
3111 | return -ENOMEM; | ||
3112 | |||
3113 | fp->channels = alts->extra[11]; | ||
3114 | fp->iface = altsd->bInterfaceNumber; | ||
3115 | fp->endpoint = get_endpoint(alts, 0)->bEndpointAddress; | ||
3116 | fp->ep_attr = get_endpoint(alts, 0)->bmAttributes; | ||
3117 | fp->maxpacksize = le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize); | ||
3118 | fp->rate_max = fp->rate_min = combine_triple(&alts->extra[15]); | ||
3119 | |||
3120 | stream = (fp->endpoint & USB_DIR_IN) | ||
3121 | ? SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK; | ||
3122 | err = add_audio_endpoint(chip, stream, fp); | ||
3123 | if (err < 0) { | ||
3124 | kfree(fp); | ||
3125 | return err; | ||
3126 | } | ||
3127 | /* FIXME: playback must be synchronized to capture */ | ||
3128 | usb_set_interface(chip->dev, fp->iface, 0); | ||
3129 | return 0; | ||
3130 | } | ||
3131 | |||
3060 | static int snd_usb_create_quirk(struct snd_usb_audio *chip, | 3132 | static int snd_usb_create_quirk(struct snd_usb_audio *chip, |
3061 | struct usb_interface *iface, | 3133 | struct usb_interface *iface, |
3062 | const struct snd_usb_audio_quirk *quirk); | 3134 | const struct snd_usb_audio_quirk *quirk); |
@@ -3238,6 +3310,7 @@ static int snd_usb_create_quirk(struct snd_usb_audio *chip, | |||
3238 | [QUIRK_AUDIO_FIXED_ENDPOINT] = create_fixed_stream_quirk, | 3310 | [QUIRK_AUDIO_FIXED_ENDPOINT] = create_fixed_stream_quirk, |
3239 | [QUIRK_AUDIO_EDIROL_UA700_UA25] = create_ua700_ua25_quirk, | 3311 | [QUIRK_AUDIO_EDIROL_UA700_UA25] = create_ua700_ua25_quirk, |
3240 | [QUIRK_AUDIO_EDIROL_UA1000] = create_ua1000_quirk, | 3312 | [QUIRK_AUDIO_EDIROL_UA1000] = create_ua1000_quirk, |
3313 | [QUIRK_AUDIO_EDIROL_UA101] = create_ua101_quirk, | ||
3241 | }; | 3314 | }; |
3242 | 3315 | ||
3243 | if (quirk->type < QUIRK_TYPE_COUNT) { | 3316 | if (quirk->type < QUIRK_TYPE_COUNT) { |