Commit 15a75c8bed591dd23a3d221f5ccd91843c109670

Authored by Clemens Ladisch
1 parent 5ea4018e43

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;