aboutsummaryrefslogtreecommitdiffstats
path: root/sound/firewire/dice.c
diff options
context:
space:
mode:
authorClemens Ladisch <clemens@ladisch.de>2011-12-04 16:23:59 -0500
committerClemens Ladisch <clemens@ladisch.de>2013-10-20 16:07:57 -0400
commit15a75c8bed591dd23a3d221f5ccd91843c109670 (patch)
tree0ded272107635d8c6d4f311130091790abe02fcc /sound/firewire/dice.c
parent5ea4018e4321f24e8305ea8a8b0a9c3e270456ae (diff)
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>
Diffstat (limited to 'sound/firewire/dice.c')
-rw-r--r--sound/firewire/dice.c92
1 files changed, 90 insertions, 2 deletions
diff --git a/sound/firewire/dice.c b/sound/firewire/dice.c
index 49b47ba09cdd..e6bba6d32bd8 100644
--- a/sound/firewire/dice.c
+++ b/sound/firewire/dice.c
@@ -6,10 +6,12 @@
6 */ 6 */
7 7
8#include <linux/compat.h> 8#include <linux/compat.h>
9#include <linux/completion.h>
9#include <linux/delay.h> 10#include <linux/delay.h>
10#include <linux/device.h> 11#include <linux/device.h>
11#include <linux/firewire.h> 12#include <linux/firewire.h>
12#include <linux/firewire-constants.h> 13#include <linux/firewire-constants.h>
14#include <linux/jiffies.h>
13#include <linux/module.h> 15#include <linux/module.h>
14#include <linux/mod_devicetable.h> 16#include <linux/mod_devicetable.h>
15#include <linux/mutex.h> 17#include <linux/mutex.h>
@@ -37,11 +39,14 @@ struct dice {
37 unsigned int global_offset; 39 unsigned int global_offset;
38 unsigned int rx_offset; 40 unsigned int rx_offset;
39 unsigned int clock_caps; 41 unsigned int clock_caps;
42 unsigned int rx_channels[3];
43 unsigned int rx_midi_ports[3];
40 struct fw_address_handler notification_handler; 44 struct fw_address_handler notification_handler;
41 int owner_generation; 45 int owner_generation;
42 int dev_lock_count; /* > 0 driver, < 0 userspace */ 46 int dev_lock_count; /* > 0 driver, < 0 userspace */
43 bool dev_lock_changed; 47 bool dev_lock_changed;
44 bool global_enabled; 48 bool global_enabled;
49 struct completion clock_accepted;
45 wait_queue_head_t hwdep_wait; 50 wait_queue_head_t hwdep_wait;
46 u32 notification_bits; 51 u32 notification_bits;
47 struct fw_iso_resources resources; 52 struct fw_iso_resources resources;
@@ -53,15 +58,23 @@ MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>");
53MODULE_LICENSE("GPL v2"); 58MODULE_LICENSE("GPL v2");
54 59
55static const unsigned int dice_rates[] = { 60static const unsigned int dice_rates[] = {
61 /* mode 0 */
56 [0] = 32000, 62 [0] = 32000,
57 [1] = 44100, 63 [1] = 44100,
58 [2] = 48000, 64 [2] = 48000,
65 /* mode 1 */
59 [3] = 88200, 66 [3] = 88200,
60 [4] = 96000, 67 [4] = 96000,
68 /* mode 2 */
61 [5] = 176400, 69 [5] = 176400,
62 [6] = 192000, 70 [6] = 192000,
63}; 71};
64 72
73static unsigned int rate_index_to_mode(unsigned int rate_index)
74{
75 return ((int)rate_index - 1) / 2;
76}
77
65static void dice_lock_changed(struct dice *dice) 78static void dice_lock_changed(struct dice *dice)
66{ 79{
67 dice->dev_lock_changed = true; 80 dice->dev_lock_changed = true;
@@ -264,6 +277,7 @@ static void dice_notification(struct fw_card *card, struct fw_request *request,
264 void *data, size_t length, void *callback_data) 277 void *data, size_t length, void *callback_data)
265{ 278{
266 struct dice *dice = callback_data; 279 struct dice *dice = callback_data;
280 u32 bits;
267 unsigned long flags; 281 unsigned long flags;
268 282
269 if (tcode != TCODE_WRITE_QUADLET_REQUEST) { 283 if (tcode != TCODE_WRITE_QUADLET_REQUEST) {
@@ -274,10 +288,17 @@ static void dice_notification(struct fw_card *card, struct fw_request *request,
274 fw_send_response(card, request, RCODE_ADDRESS_ERROR); 288 fw_send_response(card, request, RCODE_ADDRESS_ERROR);
275 return; 289 return;
276 } 290 }
291
292 bits = be32_to_cpup(data);
293
277 spin_lock_irqsave(&dice->lock, flags); 294 spin_lock_irqsave(&dice->lock, flags);
278 dice->notification_bits |= be32_to_cpup(data); 295 dice->notification_bits |= bits;
279 spin_unlock_irqrestore(&dice->lock, flags); 296 spin_unlock_irqrestore(&dice->lock, flags);
297
280 fw_send_response(card, request, RCODE_COMPLETE); 298 fw_send_response(card, request, RCODE_COMPLETE);
299
300 if (bits & NOTIFY_CLOCK_ACCEPTED)
301 complete(&dice->clock_accepted);
281 wake_up(&dice->hwdep_wait); 302 wake_up(&dice->hwdep_wait);
282} 303}
283 304
@@ -457,6 +478,26 @@ static void dice_stream_stop(struct dice *dice)
457 fw_iso_resources_free(&dice->resources); 478 fw_iso_resources_free(&dice->resources);
458} 479}
459 480
481static 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
460static int dice_hw_params(struct snd_pcm_substream *substream, 501static int dice_hw_params(struct snd_pcm_substream *substream,
461 struct snd_pcm_hw_params *hw_params) 502 struct snd_pcm_hw_params *hw_params)
462{ 503{
@@ -831,11 +872,51 @@ static int dice_interface_check(struct fw_unit *unit)
831 return 0; 872 return 0;
832} 873}
833 874
875static 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
887static 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
834static int dice_read_params(struct dice *dice) 915static int dice_read_params(struct dice *dice)
835{ 916{
836 __be32 pointers[6]; 917 __be32 pointers[6];
837 __be32 value; 918 __be32 value;
838 int err; 919 int mode, err;
839 920
840 err = snd_fw_transaction(dice->unit, TCODE_READ_BLOCK_REQUEST, 921 err = snd_fw_transaction(dice->unit, TCODE_READ_BLOCK_REQUEST,
841 DICE_PRIVATE_SPACE, 922 DICE_PRIVATE_SPACE,
@@ -863,6 +944,12 @@ static int dice_read_params(struct dice *dice)
863 CLOCK_CAP_SOURCE_INTERNAL; 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 return 0; 953 return 0;
867} 954}
868 955
@@ -922,6 +1009,7 @@ static int dice_probe(struct fw_unit *unit, const struct ieee1394_device_id *id)
922 spin_lock_init(&dice->lock); 1009 spin_lock_init(&dice->lock);
923 mutex_init(&dice->mutex); 1010 mutex_init(&dice->mutex);
924 dice->unit = unit; 1011 dice->unit = unit;
1012 init_completion(&dice->clock_accepted);
925 init_waitqueue_head(&dice->hwdep_wait); 1013 init_waitqueue_head(&dice->hwdep_wait);
926 1014
927 dice->notification_handler.length = 4; 1015 dice->notification_handler.length = 4;