Commit 15a75c8bed591dd23a3d221f5ccd91843c109670
1 parent
5ea4018e43
Exists in
master
and in
16 other branches
ALSA: dice: get rate-dependent parameters
In preparation for sample rate selection support, read the stream parameters that might change when running at different sample rates. Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
Showing 1 changed file with 90 additions and 2 deletions Side-by-side Diff
sound/firewire/dice.c
... | ... | @@ -6,10 +6,12 @@ |
6 | 6 | */ |
7 | 7 | |
8 | 8 | #include <linux/compat.h> |
9 | +#include <linux/completion.h> | |
9 | 10 | #include <linux/delay.h> |
10 | 11 | #include <linux/device.h> |
11 | 12 | #include <linux/firewire.h> |
12 | 13 | #include <linux/firewire-constants.h> |
14 | +#include <linux/jiffies.h> | |
13 | 15 | #include <linux/module.h> |
14 | 16 | #include <linux/mod_devicetable.h> |
15 | 17 | #include <linux/mutex.h> |
16 | 18 | |
... | ... | @@ -37,11 +39,14 @@ |
37 | 39 | unsigned int global_offset; |
38 | 40 | unsigned int rx_offset; |
39 | 41 | unsigned int clock_caps; |
42 | + unsigned int rx_channels[3]; | |
43 | + unsigned int rx_midi_ports[3]; | |
40 | 44 | struct fw_address_handler notification_handler; |
41 | 45 | int owner_generation; |
42 | 46 | int dev_lock_count; /* > 0 driver, < 0 userspace */ |
43 | 47 | bool dev_lock_changed; |
44 | 48 | bool global_enabled; |
49 | + struct completion clock_accepted; | |
45 | 50 | wait_queue_head_t hwdep_wait; |
46 | 51 | u32 notification_bits; |
47 | 52 | struct fw_iso_resources resources; |
48 | 53 | |
49 | 54 | |
50 | 55 | |
... | ... | @@ -53,15 +58,23 @@ |
53 | 58 | MODULE_LICENSE("GPL v2"); |
54 | 59 | |
55 | 60 | static const unsigned int dice_rates[] = { |
61 | + /* mode 0 */ | |
56 | 62 | [0] = 32000, |
57 | 63 | [1] = 44100, |
58 | 64 | [2] = 48000, |
65 | + /* mode 1 */ | |
59 | 66 | [3] = 88200, |
60 | 67 | [4] = 96000, |
68 | + /* mode 2 */ | |
61 | 69 | [5] = 176400, |
62 | 70 | [6] = 192000, |
63 | 71 | }; |
64 | 72 | |
73 | +static unsigned int rate_index_to_mode(unsigned int rate_index) | |
74 | +{ | |
75 | + return ((int)rate_index - 1) / 2; | |
76 | +} | |
77 | + | |
65 | 78 | static void dice_lock_changed(struct dice *dice) |
66 | 79 | { |
67 | 80 | dice->dev_lock_changed = true; |
... | ... | @@ -264,6 +277,7 @@ |
264 | 277 | void *data, size_t length, void *callback_data) |
265 | 278 | { |
266 | 279 | struct dice *dice = callback_data; |
280 | + u32 bits; | |
267 | 281 | unsigned long flags; |
268 | 282 | |
269 | 283 | if (tcode != TCODE_WRITE_QUADLET_REQUEST) { |
270 | 284 | |
271 | 285 | |
272 | 286 | |
... | ... | @@ -274,10 +288,17 @@ |
274 | 288 | fw_send_response(card, request, RCODE_ADDRESS_ERROR); |
275 | 289 | return; |
276 | 290 | } |
291 | + | |
292 | + bits = be32_to_cpup(data); | |
293 | + | |
277 | 294 | spin_lock_irqsave(&dice->lock, flags); |
278 | - dice->notification_bits |= be32_to_cpup(data); | |
295 | + dice->notification_bits |= bits; | |
279 | 296 | spin_unlock_irqrestore(&dice->lock, flags); |
297 | + | |
280 | 298 | fw_send_response(card, request, RCODE_COMPLETE); |
299 | + | |
300 | + if (bits & NOTIFY_CLOCK_ACCEPTED) | |
301 | + complete(&dice->clock_accepted); | |
281 | 302 | wake_up(&dice->hwdep_wait); |
282 | 303 | } |
283 | 304 | |
... | ... | @@ -457,6 +478,26 @@ |
457 | 478 | fw_iso_resources_free(&dice->resources); |
458 | 479 | } |
459 | 480 | |
481 | +static int dice_change_rate(struct dice *dice, unsigned int clock_rate) | |
482 | +{ | |
483 | + __be32 value; | |
484 | + int err; | |
485 | + | |
486 | + INIT_COMPLETION(dice->clock_accepted); | |
487 | + | |
488 | + value = cpu_to_be32(clock_rate | CLOCK_SOURCE_ARX1); | |
489 | + err = snd_fw_transaction(dice->unit, TCODE_WRITE_QUADLET_REQUEST, | |
490 | + global_address(dice, GLOBAL_CLOCK_SELECT), | |
491 | + &value, 4, 0); | |
492 | + if (err < 0) | |
493 | + return err; | |
494 | + | |
495 | + wait_for_completion_timeout(&dice->clock_accepted, | |
496 | + msecs_to_jiffies(100)); | |
497 | + | |
498 | + return 0; | |
499 | +} | |
500 | + | |
460 | 501 | static int dice_hw_params(struct snd_pcm_substream *substream, |
461 | 502 | struct snd_pcm_hw_params *hw_params) |
462 | 503 | { |
463 | 504 | |
... | ... | @@ -831,11 +872,51 @@ |
831 | 872 | return 0; |
832 | 873 | } |
833 | 874 | |
875 | +static int highest_supported_mode_rate(struct dice *dice, unsigned int mode) | |
876 | +{ | |
877 | + int i; | |
878 | + | |
879 | + for (i = ARRAY_SIZE(dice_rates) - 1; i >= 0; --i) | |
880 | + if ((dice->clock_caps & (1 << i)) && | |
881 | + rate_index_to_mode(i) == mode) | |
882 | + return i; | |
883 | + | |
884 | + return -1; | |
885 | +} | |
886 | + | |
887 | +static int dice_read_mode_params(struct dice *dice, unsigned int mode) | |
888 | +{ | |
889 | + __be32 values[2]; | |
890 | + int rate_index, err; | |
891 | + | |
892 | + rate_index = highest_supported_mode_rate(dice, mode); | |
893 | + if (rate_index < 0) { | |
894 | + dice->rx_channels[mode] = 0; | |
895 | + dice->rx_midi_ports[mode] = 0; | |
896 | + return 0; | |
897 | + } | |
898 | + | |
899 | + err = dice_change_rate(dice, rate_index << CLOCK_RATE_SHIFT); | |
900 | + if (err < 0) | |
901 | + return err; | |
902 | + | |
903 | + err = snd_fw_transaction(dice->unit, TCODE_READ_BLOCK_REQUEST, | |
904 | + rx_address(dice, RX_NUMBER_AUDIO), | |
905 | + values, 2 * 4, 0); | |
906 | + if (err < 0) | |
907 | + return err; | |
908 | + | |
909 | + dice->rx_channels[mode] = be32_to_cpu(values[0]); | |
910 | + dice->rx_midi_ports[mode] = be32_to_cpu(values[1]); | |
911 | + | |
912 | + return 0; | |
913 | +} | |
914 | + | |
834 | 915 | static int dice_read_params(struct dice *dice) |
835 | 916 | { |
836 | 917 | __be32 pointers[6]; |
837 | 918 | __be32 value; |
838 | - int err; | |
919 | + int mode, err; | |
839 | 920 | |
840 | 921 | err = snd_fw_transaction(dice->unit, TCODE_READ_BLOCK_REQUEST, |
841 | 922 | DICE_PRIVATE_SPACE, |
... | ... | @@ -863,6 +944,12 @@ |
863 | 944 | CLOCK_CAP_SOURCE_INTERNAL; |
864 | 945 | } |
865 | 946 | |
947 | + for (mode = 2; mode >= 0; --mode) { | |
948 | + err = dice_read_mode_params(dice, mode); | |
949 | + if (err < 0) | |
950 | + return err; | |
951 | + } | |
952 | + | |
866 | 953 | return 0; |
867 | 954 | } |
868 | 955 | |
... | ... | @@ -922,6 +1009,7 @@ |
922 | 1009 | spin_lock_init(&dice->lock); |
923 | 1010 | mutex_init(&dice->mutex); |
924 | 1011 | dice->unit = unit; |
1012 | + init_completion(&dice->clock_accepted); | |
925 | 1013 | init_waitqueue_head(&dice->hwdep_wait); |
926 | 1014 | |
927 | 1015 | dice->notification_handler.length = 4; |