diff options
author | Clemens Ladisch <clemens@ladisch.de> | 2011-09-04 16:12:06 -0400 |
---|---|---|
committer | Clemens Ladisch <clemens@ladisch.de> | 2013-10-20 16:07:57 -0400 |
commit | 341682cd4f5603fccbf559d201402539880c04a5 (patch) | |
tree | 83ae2894e966fda412df2929012231f9ae6d1ce3 /sound/firewire/dice.c | |
parent | 6abce9e63d44e94b16f08794fb6f5ad6d1025c79 (diff) |
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>
Diffstat (limited to 'sound/firewire/dice.c')
-rw-r--r-- | sound/firewire/dice.c | 55 |
1 files changed, 42 insertions, 13 deletions
diff --git a/sound/firewire/dice.c b/sound/firewire/dice.c index b081021064ed..d3f3eb7a546a 100644 --- a/sound/firewire/dice.c +++ b/sound/firewire/dice.c | |||
@@ -75,6 +75,7 @@ | |||
75 | #define CLOCK_RATE_ANY_MID 0x00000800 | 75 | #define CLOCK_RATE_ANY_MID 0x00000800 |
76 | #define CLOCK_RATE_ANY_HIGH 0x00000900 | 76 | #define CLOCK_RATE_ANY_HIGH 0x00000900 |
77 | #define CLOCK_RATE_NONE 0x00000a00 | 77 | #define CLOCK_RATE_NONE 0x00000a00 |
78 | #define CLOCK_RATE_SHIFT 8 | ||
78 | #define GLOBAL_ENABLE 0x050 | 79 | #define GLOBAL_ENABLE 0x050 |
79 | #define ENABLE 0x00000001 | 80 | #define ENABLE 0x00000001 |
80 | #define GLOBAL_STATUS 0x054 | 81 | #define GLOBAL_STATUS 0x054 |
@@ -248,6 +249,16 @@ MODULE_DESCRIPTION("DICE driver"); | |||
248 | MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>"); | 249 | MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>"); |
249 | MODULE_LICENSE("GPL v2"); | 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 | static inline u64 global_address(struct dice *dice, unsigned int offset) | 262 | static inline u64 global_address(struct dice *dice, unsigned int offset) |
252 | { | 263 | { |
253 | return DICE_PRIVATE_SPACE + dice->global_offset + offset; | 264 | return DICE_PRIVATE_SPACE + dice->global_offset + offset; |
@@ -508,9 +519,6 @@ static int dice_open(struct snd_pcm_substream *substream) | |||
508 | SNDRV_PCM_INFO_INTERLEAVED | | 519 | SNDRV_PCM_INFO_INTERLEAVED | |
509 | SNDRV_PCM_INFO_BLOCK_TRANSFER, | 520 | SNDRV_PCM_INFO_BLOCK_TRANSFER, |
510 | .formats = AMDTP_OUT_PCM_FORMAT_BITS, | 521 | .formats = AMDTP_OUT_PCM_FORMAT_BITS, |
511 | .rates = SNDRV_PCM_RATE_44100, | ||
512 | .rate_min = 44100, | ||
513 | .rate_max = 44100, | ||
514 | .buffer_bytes_max = 16 * 1024 * 1024, | 522 | .buffer_bytes_max = 16 * 1024 * 1024, |
515 | .period_bytes_min = 1, | 523 | .period_bytes_min = 1, |
516 | .period_bytes_max = UINT_MAX, | 524 | .period_bytes_max = UINT_MAX, |
@@ -519,10 +527,21 @@ static int dice_open(struct snd_pcm_substream *substream) | |||
519 | }; | 527 | }; |
520 | struct dice *dice = substream->private_data; | 528 | struct dice *dice = substream->private_data; |
521 | struct snd_pcm_runtime *runtime = substream->runtime; | 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 | int err; | 532 | int err; |
524 | 533 | ||
525 | err = snd_fw_transaction(dice->unit, TCODE_READ_QUADLET_REQUEST, | 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 | rx_address(dice, RX_NUMBER_AUDIO), | 545 | rx_address(dice, RX_NUMBER_AUDIO), |
527 | &number_audio, 4); | 546 | &number_audio, 4); |
528 | if (err < 0) | 547 | if (err < 0) |
@@ -534,10 +553,14 @@ static int dice_open(struct snd_pcm_substream *substream) | |||
534 | return err; | 553 | return err; |
535 | 554 | ||
536 | runtime->hw = hardware; | 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 | runtime->hw.channels_min = be32_to_cpu(number_audio); | 560 | runtime->hw.channels_min = be32_to_cpu(number_audio); |
538 | runtime->hw.channels_max = be32_to_cpu(number_audio); | 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 | amdtp_out_stream_set_pcm(&dice->stream, be32_to_cpu(number_audio)); | 564 | amdtp_out_stream_set_pcm(&dice->stream, be32_to_cpu(number_audio)); |
542 | amdtp_out_stream_set_midi(&dice->stream, be32_to_cpu(number_midi)); | 565 | amdtp_out_stream_set_midi(&dice->stream, be32_to_cpu(number_midi)); |
543 | 566 | ||
@@ -746,17 +769,9 @@ static int dice_create_pcm(struct dice *dice) | |||
746 | .page = snd_pcm_lib_get_vmalloc_page, | 769 | .page = snd_pcm_lib_get_vmalloc_page, |
747 | .mmap = snd_pcm_lib_mmap_vmalloc, | 770 | .mmap = snd_pcm_lib_mmap_vmalloc, |
748 | }; | 771 | }; |
749 | __be32 clock; | ||
750 | struct snd_pcm *pcm; | 772 | struct snd_pcm *pcm; |
751 | int err; | 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 | err = snd_pcm_new(dice->card, "DICE", 0, 1, 0, &pcm); | 775 | err = snd_pcm_new(dice->card, "DICE", 0, 1, 0, &pcm); |
761 | if (err < 0) | 776 | if (err < 0) |
762 | return err; | 777 | return err; |
@@ -897,6 +912,7 @@ static int dice_probe(struct fw_unit *unit, const struct ieee1394_device_id *id) | |||
897 | { | 912 | { |
898 | struct snd_card *card; | 913 | struct snd_card *card; |
899 | struct dice *dice; | 914 | struct dice *dice; |
915 | __be32 clock_sel; | ||
900 | int err; | 916 | int err; |
901 | 917 | ||
902 | err = snd_card_create(-1, NULL, THIS_MODULE, sizeof(*dice), &card); | 918 | err = snd_card_create(-1, NULL, THIS_MODULE, sizeof(*dice), &card); |
@@ -938,6 +954,19 @@ static int dice_probe(struct fw_unit *unit, const struct ieee1394_device_id *id) | |||
938 | 954 | ||
939 | dice_card_strings(dice); | 955 | dice_card_strings(dice); |
940 | 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; | ||
969 | |||
941 | err = dice_create_pcm(dice); | 970 | err = dice_create_pcm(dice); |
942 | if (err < 0) | 971 | if (err < 0) |
943 | goto error; | 972 | goto error; |