Commit 341682cd4f5603fccbf559d201402539880c04a5
1 parent
6abce9e63d
Exists in
master
and in
16 other branches
ALSA: dice: allow all sample rates
Instead of forcing a constant 44.1 kHz, read the current sample rate from the device when opening the PCM device. Actually changing the sample rate requires some separate controller application. Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
Showing 1 changed file with 42 additions and 13 deletions Side-by-side Diff
sound/firewire/dice.c
... | ... | @@ -75,6 +75,7 @@ |
75 | 75 | #define CLOCK_RATE_ANY_MID 0x00000800 |
76 | 76 | #define CLOCK_RATE_ANY_HIGH 0x00000900 |
77 | 77 | #define CLOCK_RATE_NONE 0x00000a00 |
78 | +#define CLOCK_RATE_SHIFT 8 | |
78 | 79 | #define GLOBAL_ENABLE 0x050 |
79 | 80 | #define ENABLE 0x00000001 |
80 | 81 | #define GLOBAL_STATUS 0x054 |
... | ... | @@ -248,6 +249,16 @@ |
248 | 249 | MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>"); |
249 | 250 | MODULE_LICENSE("GPL v2"); |
250 | 251 | |
252 | +static const unsigned int dice_rates[] = { | |
253 | + [0] = 32000, | |
254 | + [1] = 44100, | |
255 | + [2] = 48000, | |
256 | + [3] = 88200, | |
257 | + [4] = 96000, | |
258 | + [5] = 176400, | |
259 | + [6] = 192000, | |
260 | +}; | |
261 | + | |
251 | 262 | static inline u64 global_address(struct dice *dice, unsigned int offset) |
252 | 263 | { |
253 | 264 | return DICE_PRIVATE_SPACE + dice->global_offset + offset; |
... | ... | @@ -508,9 +519,6 @@ |
508 | 519 | SNDRV_PCM_INFO_INTERLEAVED | |
509 | 520 | SNDRV_PCM_INFO_BLOCK_TRANSFER, |
510 | 521 | .formats = AMDTP_OUT_PCM_FORMAT_BITS, |
511 | - .rates = SNDRV_PCM_RATE_44100, | |
512 | - .rate_min = 44100, | |
513 | - .rate_max = 44100, | |
514 | 522 | .buffer_bytes_max = 16 * 1024 * 1024, |
515 | 523 | .period_bytes_min = 1, |
516 | 524 | .period_bytes_max = UINT_MAX, |
517 | 525 | |
... | ... | @@ -519,10 +527,21 @@ |
519 | 527 | }; |
520 | 528 | struct dice *dice = substream->private_data; |
521 | 529 | struct snd_pcm_runtime *runtime = substream->runtime; |
522 | - __be32 number_audio, number_midi; | |
530 | + __be32 clock_sel, number_audio, number_midi; | |
531 | + unsigned int rate; | |
523 | 532 | int err; |
524 | 533 | |
525 | 534 | err = snd_fw_transaction(dice->unit, TCODE_READ_QUADLET_REQUEST, |
535 | + global_address(dice, GLOBAL_CLOCK_SELECT), | |
536 | + &clock_sel, 4); | |
537 | + if (err < 0) | |
538 | + return err; | |
539 | + rate = (be32_to_cpu(clock_sel) & CLOCK_RATE_MASK) >> CLOCK_RATE_SHIFT; | |
540 | + if (rate >= ARRAY_SIZE(dice_rates)) | |
541 | + return -ENXIO; | |
542 | + rate = dice_rates[rate]; | |
543 | + | |
544 | + err = snd_fw_transaction(dice->unit, TCODE_READ_QUADLET_REQUEST, | |
526 | 545 | rx_address(dice, RX_NUMBER_AUDIO), |
527 | 546 | &number_audio, 4); |
528 | 547 | if (err < 0) |
529 | 548 | |
... | ... | @@ -534,10 +553,14 @@ |
534 | 553 | return err; |
535 | 554 | |
536 | 555 | runtime->hw = hardware; |
556 | + | |
557 | + runtime->hw.rates = snd_pcm_rate_to_rate_bit(rate); | |
558 | + snd_pcm_limit_hw_rates(runtime); | |
559 | + | |
537 | 560 | runtime->hw.channels_min = be32_to_cpu(number_audio); |
538 | 561 | runtime->hw.channels_max = be32_to_cpu(number_audio); |
539 | 562 | |
540 | - amdtp_out_stream_set_rate(&dice->stream, 44100); | |
563 | + amdtp_out_stream_set_rate(&dice->stream, rate); | |
541 | 564 | amdtp_out_stream_set_pcm(&dice->stream, be32_to_cpu(number_audio)); |
542 | 565 | amdtp_out_stream_set_midi(&dice->stream, be32_to_cpu(number_midi)); |
543 | 566 | |
544 | 567 | |
... | ... | @@ -746,17 +769,9 @@ |
746 | 769 | .page = snd_pcm_lib_get_vmalloc_page, |
747 | 770 | .mmap = snd_pcm_lib_mmap_vmalloc, |
748 | 771 | }; |
749 | - __be32 clock; | |
750 | 772 | struct snd_pcm *pcm; |
751 | 773 | int err; |
752 | 774 | |
753 | - clock = cpu_to_be32(CLOCK_SOURCE_ARX1 | CLOCK_RATE_44100); | |
754 | - err = snd_fw_transaction(dice->unit, TCODE_WRITE_QUADLET_REQUEST, | |
755 | - global_address(dice, GLOBAL_CLOCK_SELECT), | |
756 | - &clock, 4); | |
757 | - if (err < 0) | |
758 | - return err; | |
759 | - | |
760 | 775 | err = snd_pcm_new(dice->card, "DICE", 0, 1, 0, &pcm); |
761 | 776 | if (err < 0) |
762 | 777 | return err; |
... | ... | @@ -897,6 +912,7 @@ |
897 | 912 | { |
898 | 913 | struct snd_card *card; |
899 | 914 | struct dice *dice; |
915 | + __be32 clock_sel; | |
900 | 916 | int err; |
901 | 917 | |
902 | 918 | err = snd_card_create(-1, NULL, THIS_MODULE, sizeof(*dice), &card); |
... | ... | @@ -937,6 +953,19 @@ |
937 | 953 | card->private_free = dice_card_free; |
938 | 954 | |
939 | 955 | dice_card_strings(dice); |
956 | + | |
957 | + err = snd_fw_transaction(unit, TCODE_READ_QUADLET_REQUEST, | |
958 | + global_address(dice, GLOBAL_CLOCK_SELECT), | |
959 | + &clock_sel, 4); | |
960 | + if (err < 0) | |
961 | + goto error; | |
962 | + clock_sel &= cpu_to_be32(~CLOCK_SOURCE_MASK); | |
963 | + clock_sel |= cpu_to_be32(CLOCK_SOURCE_ARX1); | |
964 | + err = snd_fw_transaction(unit, TCODE_WRITE_QUADLET_REQUEST, | |
965 | + global_address(dice, GLOBAL_CLOCK_SELECT), | |
966 | + &clock_sel, 4); | |
967 | + if (err < 0) | |
968 | + goto error; | |
940 | 969 | |
941 | 970 | err = dice_create_pcm(dice); |
942 | 971 | if (err < 0) |