Commit 15a75c8b authored by Clemens Ladisch's avatar Clemens Ladisch

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: default avatarClemens Ladisch <clemens@ladisch.de>
parent 5ea4018e
...@@ -6,10 +6,12 @@ ...@@ -6,10 +6,12 @@
*/ */
#include <linux/compat.h> #include <linux/compat.h>
#include <linux/completion.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/device.h> #include <linux/device.h>
#include <linux/firewire.h> #include <linux/firewire.h>
#include <linux/firewire-constants.h> #include <linux/firewire-constants.h>
#include <linux/jiffies.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/mod_devicetable.h> #include <linux/mod_devicetable.h>
#include <linux/mutex.h> #include <linux/mutex.h>
...@@ -37,11 +39,14 @@ struct dice { ...@@ -37,11 +39,14 @@ struct dice {
unsigned int global_offset; unsigned int global_offset;
unsigned int rx_offset; unsigned int rx_offset;
unsigned int clock_caps; unsigned int clock_caps;
unsigned int rx_channels[3];
unsigned int rx_midi_ports[3];
struct fw_address_handler notification_handler; struct fw_address_handler notification_handler;
int owner_generation; int owner_generation;
int dev_lock_count; /* > 0 driver, < 0 userspace */ int dev_lock_count; /* > 0 driver, < 0 userspace */
bool dev_lock_changed; bool dev_lock_changed;
bool global_enabled; bool global_enabled;
struct completion clock_accepted;
wait_queue_head_t hwdep_wait; wait_queue_head_t hwdep_wait;
u32 notification_bits; u32 notification_bits;
struct fw_iso_resources resources; struct fw_iso_resources resources;
...@@ -53,15 +58,23 @@ MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>"); ...@@ -53,15 +58,23 @@ MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>");
MODULE_LICENSE("GPL v2"); MODULE_LICENSE("GPL v2");
static const unsigned int dice_rates[] = { static const unsigned int dice_rates[] = {
/* mode 0 */
[0] = 32000, [0] = 32000,
[1] = 44100, [1] = 44100,
[2] = 48000, [2] = 48000,
/* mode 1 */
[3] = 88200, [3] = 88200,
[4] = 96000, [4] = 96000,
/* mode 2 */
[5] = 176400, [5] = 176400,
[6] = 192000, [6] = 192000,
}; };
static unsigned int rate_index_to_mode(unsigned int rate_index)
{
return ((int)rate_index - 1) / 2;
}
static void dice_lock_changed(struct dice *dice) static void dice_lock_changed(struct dice *dice)
{ {
dice->dev_lock_changed = true; dice->dev_lock_changed = true;
...@@ -264,6 +277,7 @@ static void dice_notification(struct fw_card *card, struct fw_request *request, ...@@ -264,6 +277,7 @@ static void dice_notification(struct fw_card *card, struct fw_request *request,
void *data, size_t length, void *callback_data) void *data, size_t length, void *callback_data)
{ {
struct dice *dice = callback_data; struct dice *dice = callback_data;
u32 bits;
unsigned long flags; unsigned long flags;
if (tcode != TCODE_WRITE_QUADLET_REQUEST) { if (tcode != TCODE_WRITE_QUADLET_REQUEST) {
...@@ -274,10 +288,17 @@ static void dice_notification(struct fw_card *card, struct fw_request *request, ...@@ -274,10 +288,17 @@ static void dice_notification(struct fw_card *card, struct fw_request *request,
fw_send_response(card, request, RCODE_ADDRESS_ERROR); fw_send_response(card, request, RCODE_ADDRESS_ERROR);
return; return;
} }
bits = be32_to_cpup(data);
spin_lock_irqsave(&dice->lock, flags); spin_lock_irqsave(&dice->lock, flags);
dice->notification_bits |= be32_to_cpup(data); dice->notification_bits |= bits;
spin_unlock_irqrestore(&dice->lock, flags); spin_unlock_irqrestore(&dice->lock, flags);
fw_send_response(card, request, RCODE_COMPLETE); fw_send_response(card, request, RCODE_COMPLETE);
if (bits & NOTIFY_CLOCK_ACCEPTED)
complete(&dice->clock_accepted);
wake_up(&dice->hwdep_wait); wake_up(&dice->hwdep_wait);
} }
...@@ -457,6 +478,26 @@ static void dice_stream_stop(struct dice *dice) ...@@ -457,6 +478,26 @@ static void dice_stream_stop(struct dice *dice)
fw_iso_resources_free(&dice->resources); fw_iso_resources_free(&dice->resources);
} }
static int dice_change_rate(struct dice *dice, unsigned int clock_rate)
{
__be32 value;
int err;
INIT_COMPLETION(dice->clock_accepted);
value = cpu_to_be32(clock_rate | CLOCK_SOURCE_ARX1);
err = snd_fw_transaction(dice->unit, TCODE_WRITE_QUADLET_REQUEST,
global_address(dice, GLOBAL_CLOCK_SELECT),
&value, 4, 0);
if (err < 0)
return err;
wait_for_completion_timeout(&dice->clock_accepted,
msecs_to_jiffies(100));
return 0;
}
static int dice_hw_params(struct snd_pcm_substream *substream, static int dice_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *hw_params) struct snd_pcm_hw_params *hw_params)
{ {
...@@ -831,11 +872,51 @@ static int dice_interface_check(struct fw_unit *unit) ...@@ -831,11 +872,51 @@ static int dice_interface_check(struct fw_unit *unit)
return 0; return 0;
} }
static int highest_supported_mode_rate(struct dice *dice, unsigned int mode)
{
int i;
for (i = ARRAY_SIZE(dice_rates) - 1; i >= 0; --i)
if ((dice->clock_caps & (1 << i)) &&
rate_index_to_mode(i) == mode)
return i;
return -1;
}
static int dice_read_mode_params(struct dice *dice, unsigned int mode)
{
__be32 values[2];
int rate_index, err;
rate_index = highest_supported_mode_rate(dice, mode);
if (rate_index < 0) {
dice->rx_channels[mode] = 0;
dice->rx_midi_ports[mode] = 0;
return 0;
}
err = dice_change_rate(dice, rate_index << CLOCK_RATE_SHIFT);
if (err < 0)
return err;
err = snd_fw_transaction(dice->unit, TCODE_READ_BLOCK_REQUEST,
rx_address(dice, RX_NUMBER_AUDIO),
values, 2 * 4, 0);
if (err < 0)
return err;
dice->rx_channels[mode] = be32_to_cpu(values[0]);
dice->rx_midi_ports[mode] = be32_to_cpu(values[1]);
return 0;
}
static int dice_read_params(struct dice *dice) static int dice_read_params(struct dice *dice)
{ {
__be32 pointers[6]; __be32 pointers[6];
__be32 value; __be32 value;
int err; int mode, err;
err = snd_fw_transaction(dice->unit, TCODE_READ_BLOCK_REQUEST, err = snd_fw_transaction(dice->unit, TCODE_READ_BLOCK_REQUEST,
DICE_PRIVATE_SPACE, DICE_PRIVATE_SPACE,
...@@ -863,6 +944,12 @@ static int dice_read_params(struct dice *dice) ...@@ -863,6 +944,12 @@ static int dice_read_params(struct dice *dice)
CLOCK_CAP_SOURCE_INTERNAL; CLOCK_CAP_SOURCE_INTERNAL;
} }
for (mode = 2; mode >= 0; --mode) {
err = dice_read_mode_params(dice, mode);
if (err < 0)
return err;
}
return 0; return 0;
} }
...@@ -922,6 +1009,7 @@ static int dice_probe(struct fw_unit *unit, const struct ieee1394_device_id *id) ...@@ -922,6 +1009,7 @@ static int dice_probe(struct fw_unit *unit, const struct ieee1394_device_id *id)
spin_lock_init(&dice->lock); spin_lock_init(&dice->lock);
mutex_init(&dice->mutex); mutex_init(&dice->mutex);
dice->unit = unit; dice->unit = unit;
init_completion(&dice->clock_accepted);
init_waitqueue_head(&dice->hwdep_wait); init_waitqueue_head(&dice->hwdep_wait);
dice->notification_handler.length = 4; dice->notification_handler.length = 4;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment