Commit c738aed1 authored by Takashi Sakamoto's avatar Takashi Sakamoto Committed by Takashi Iwai

ALSA: dice: code refactoring to keep isochronous resources

This commit is a part of preparation to perform allocation/release
of isochronous resources in pcm.hw_params/hw_free callbacks.

This commit adds a helper function to allocate isochronous resources,
separated from operations to start packet streaming, I note that some
dice-based devices have two pair of endpoints for isochronous packet
straeming.
Signed-off-by: default avatarTakashi Sakamoto <o-takashi@sakamocchi.jp>
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent b3480638
...@@ -175,35 +175,22 @@ static void stop_streams(struct snd_dice *dice, enum amdtp_stream_direction dir, ...@@ -175,35 +175,22 @@ static void stop_streams(struct snd_dice *dice, enum amdtp_stream_direction dir,
} }
} }
static int keep_resources(struct snd_dice *dice, static int keep_resources(struct snd_dice *dice, struct amdtp_stream *stream,
enum amdtp_stream_direction dir, unsigned int index, struct fw_iso_resources *resources, unsigned int rate,
unsigned int rate, unsigned int pcm_chs, unsigned int pcm_chs, unsigned int midi_ports)
unsigned int midi_ports)
{ {
struct amdtp_stream *stream;
struct fw_iso_resources *resources;
bool double_pcm_frames; bool double_pcm_frames;
unsigned int i; unsigned int i;
int err; int err;
if (dir == AMDTP_IN_STREAM) { // At 176.4/192.0 kHz, Dice has a quirk to transfer two PCM frames in
stream = &dice->tx_stream[index]; // one data block of AMDTP packet. Thus sampling transfer frequency is
resources = &dice->tx_resources[index]; // a half of PCM sampling frequency, i.e. PCM frames at 192.0 kHz are
} else { // transferred on AMDTP packets at 96 kHz. Two successive samples of a
stream = &dice->rx_stream[index]; // channel are stored consecutively in the packet. This quirk is called
resources = &dice->rx_resources[index]; // as 'Dual Wire'.
} // For this quirk, blocking mode is required and PCM buffer size should
// be aligned to SYT_INTERVAL.
/*
* At 176.4/192.0 kHz, Dice has a quirk to transfer two PCM frames in
* one data block of AMDTP packet. Thus sampling transfer frequency is
* a half of PCM sampling frequency, i.e. PCM frames at 192.0 kHz are
* transferred on AMDTP packets at 96 kHz. Two successive samples of a
* channel are stored consecutively in the packet. This quirk is called
* as 'Dual Wire'.
* For this quirk, blocking mode is required and PCM buffer size should
* be aligned to SYT_INTERVAL.
*/
double_pcm_frames = rate > 96000; double_pcm_frames = rate > 96000;
if (double_pcm_frames) { if (double_pcm_frames) {
rate /= 2; rate /= 2;
...@@ -230,49 +217,40 @@ static int keep_resources(struct snd_dice *dice, ...@@ -230,49 +217,40 @@ static int keep_resources(struct snd_dice *dice,
fw_parent_device(dice->unit)->max_speed); fw_parent_device(dice->unit)->max_speed);
} }
static void finish_session(struct snd_dice *dice, struct reg_params *tx_params, static int keep_dual_resources(struct snd_dice *dice, unsigned int rate,
struct reg_params *rx_params) enum amdtp_stream_direction dir,
struct reg_params *params)
{ {
stop_streams(dice, AMDTP_IN_STREAM, tx_params);
stop_streams(dice, AMDTP_OUT_STREAM, rx_params);
snd_dice_transaction_clear_enable(dice);
}
static int start_streams(struct snd_dice *dice, enum amdtp_stream_direction dir,
unsigned int rate, struct reg_params *params)
{
__be32 reg[2];
enum snd_dice_rate_mode mode; enum snd_dice_rate_mode mode;
unsigned int i, pcm_chs, midi_ports; int i;
struct amdtp_stream *streams; int err;
struct fw_iso_resources *resources;
struct fw_device *fw_dev = fw_parent_device(dice->unit);
int err = 0;
if (dir == AMDTP_IN_STREAM) {
streams = dice->tx_stream;
resources = dice->tx_resources;
} else {
streams = dice->rx_stream;
resources = dice->rx_resources;
}
err = snd_dice_stream_get_rate_mode(dice, rate, &mode); err = snd_dice_stream_get_rate_mode(dice, rate, &mode);
if (err < 0) if (err < 0)
return err; return err;
for (i = 0; i < params->count; i++) { for (i = 0; i < params->count; ++i) {
__be32 reg[2];
struct amdtp_stream *stream;
struct fw_iso_resources *resources;
unsigned int pcm_cache; unsigned int pcm_cache;
unsigned int midi_cache; unsigned int midi_cache;
unsigned int pcm_chs;
unsigned int midi_ports;
if (dir == AMDTP_IN_STREAM) { if (dir == AMDTP_IN_STREAM) {
stream = &dice->tx_stream[i];
resources = &dice->tx_resources[i];
pcm_cache = dice->tx_pcm_chs[i][mode]; pcm_cache = dice->tx_pcm_chs[i][mode];
midi_cache = dice->tx_midi_ports[i]; midi_cache = dice->tx_midi_ports[i];
err = snd_dice_transaction_read_tx(dice, err = snd_dice_transaction_read_tx(dice,
params->size * i + TX_NUMBER_AUDIO, params->size * i + TX_NUMBER_AUDIO,
reg, sizeof(reg)); reg, sizeof(reg));
} else { } else {
stream = &dice->rx_stream[i];
resources = &dice->rx_resources[i];
pcm_cache = dice->rx_pcm_chs[i][mode]; pcm_cache = dice->rx_pcm_chs[i][mode];
midi_cache = dice->rx_midi_ports[i]; midi_cache = dice->rx_midi_ports[i];
err = snd_dice_transaction_read_rx(dice, err = snd_dice_transaction_read_rx(dice,
...@@ -284,7 +262,7 @@ static int start_streams(struct snd_dice *dice, enum amdtp_stream_direction dir, ...@@ -284,7 +262,7 @@ static int start_streams(struct snd_dice *dice, enum amdtp_stream_direction dir,
pcm_chs = be32_to_cpu(reg[0]); pcm_chs = be32_to_cpu(reg[0]);
midi_ports = be32_to_cpu(reg[1]); midi_ports = be32_to_cpu(reg[1]);
/* These are important for developer of this driver. */ // These are important for developer of this driver.
if (pcm_chs != pcm_cache || midi_ports != midi_cache) { if (pcm_chs != pcm_cache || midi_ports != midi_cache) {
dev_info(&dice->unit->device, dev_info(&dice->unit->device,
"cache mismatch: pcm: %u:%u, midi: %u:%u\n", "cache mismatch: pcm: %u:%u, midi: %u:%u\n",
...@@ -292,34 +270,71 @@ static int start_streams(struct snd_dice *dice, enum amdtp_stream_direction dir, ...@@ -292,34 +270,71 @@ static int start_streams(struct snd_dice *dice, enum amdtp_stream_direction dir,
return -EPROTO; return -EPROTO;
} }
err = keep_resources(dice, dir, i, rate, pcm_chs, midi_ports); err = keep_resources(dice, stream, resources, rate, pcm_chs,
midi_ports);
if (err < 0) if (err < 0)
return err; return err;
}
return 0;
}
static void finish_session(struct snd_dice *dice, struct reg_params *tx_params,
struct reg_params *rx_params)
{
stop_streams(dice, AMDTP_IN_STREAM, tx_params);
stop_streams(dice, AMDTP_OUT_STREAM, rx_params);
snd_dice_transaction_clear_enable(dice);
}
static int start_streams(struct snd_dice *dice, enum amdtp_stream_direction dir,
unsigned int rate, struct reg_params *params)
{
unsigned int max_speed = fw_parent_device(dice->unit)->max_speed;
int i;
int err;
err = keep_dual_resources(dice, rate, dir, params);
if (err < 0)
return err;
for (i = 0; i < params->count; i++) {
struct amdtp_stream *stream;
struct fw_iso_resources *resources;
__be32 reg;
if (dir == AMDTP_IN_STREAM) {
stream = dice->tx_stream + i;
resources = dice->tx_resources + i;
} else {
stream = dice->rx_stream + i;
resources = dice->rx_resources + i;
}
reg[0] = cpu_to_be32(resources[i].channel); reg = cpu_to_be32(resources->channel);
if (dir == AMDTP_IN_STREAM) { if (dir == AMDTP_IN_STREAM) {
err = snd_dice_transaction_write_tx(dice, err = snd_dice_transaction_write_tx(dice,
params->size * i + TX_ISOCHRONOUS, params->size * i + TX_ISOCHRONOUS,
reg, sizeof(reg[0])); &reg, sizeof(reg));
} else { } else {
err = snd_dice_transaction_write_rx(dice, err = snd_dice_transaction_write_rx(dice,
params->size * i + RX_ISOCHRONOUS, params->size * i + RX_ISOCHRONOUS,
reg, sizeof(reg[0])); &reg, sizeof(reg));
} }
if (err < 0) if (err < 0)
return err; return err;
if (dir == AMDTP_IN_STREAM) { if (dir == AMDTP_IN_STREAM) {
reg[0] = cpu_to_be32(fw_dev->max_speed); reg = cpu_to_be32(max_speed);
err = snd_dice_transaction_write_tx(dice, err = snd_dice_transaction_write_tx(dice,
params->size * i + TX_SPEED, params->size * i + TX_SPEED,
reg, sizeof(reg[0])); &reg, sizeof(reg));
if (err < 0) if (err < 0)
return err; return err;
} }
err = amdtp_stream_start(&streams[i], resources[i].channel, err = amdtp_stream_start(stream, resources->channel, max_speed);
fw_dev->max_speed);
if (err < 0) if (err < 0)
return err; return err;
} }
......
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