[alsa-devel] [PATCH v2 10/13] ALSA: dice: enable to change current sampling transmission frequency
Takashi Sakamoto
o-takashi at sakamocchi.jp
Sun Apr 29 08:50:29 CEST 2018
This is a preparation for userspace applications to change current sampling
transmission frequency via ALSA PCM interface.
Signed-off-by: Takashi Sakamoto <o-takashi at sakamocchi.jp>
---
sound/firewire/dice/dice-stream.c | 47 +++++++++++++++++++++++++++++++++++----
1 file changed, 43 insertions(+), 4 deletions(-)
diff --git a/sound/firewire/dice/dice-stream.c b/sound/firewire/dice/dice-stream.c
index 6a73528013d3..37c6c5d152dc 100644
--- a/sound/firewire/dice/dice-stream.c
+++ b/sound/firewire/dice/dice-stream.c
@@ -52,9 +52,11 @@ int snd_dice_stream_get_rate_mode(struct snd_dice *dice, unsigned int rate,
* This operation has an effect to synchronize GLOBAL_STATUS/GLOBAL_SAMPLE_RATE
* to GLOBAL_STATUS. Especially, just after powering on, these are different.
*/
-static int ensure_phase_lock(struct snd_dice *dice)
+static int ensure_phase_lock(struct snd_dice *dice, unsigned int rate)
{
__be32 reg, nominal;
+ u32 data;
+ int i;
int err;
err = snd_dice_transaction_read_global(dice, GLOBAL_CLOCK_SELECT,
@@ -62,9 +64,21 @@ static int ensure_phase_lock(struct snd_dice *dice)
if (err < 0)
return err;
+ data = be32_to_cpu(reg);
+
+ data &= ~CLOCK_RATE_MASK;
+ for (i = 0; i < ARRAY_SIZE(snd_dice_rates); ++i) {
+ if (snd_dice_rates[i] == rate)
+ break;
+ }
+ if (i == ARRAY_SIZE(snd_dice_rates))
+ return -EINVAL;
+ data |= i << CLOCK_RATE_SHIFT;
+
if (completion_done(&dice->clock_accepted))
reinit_completion(&dice->clock_accepted);
+ reg = cpu_to_be32(data);
err = snd_dice_transaction_write_global(dice, GLOBAL_CLOCK_SELECT,
®, sizeof(reg));
if (err < 0)
@@ -210,6 +224,7 @@ static int start_streams(struct snd_dice *dice, enum amdtp_stream_direction dir,
unsigned int rate, struct reg_params *params)
{
__be32 reg[2];
+ unsigned int mode;
unsigned int i, pcm_chs, midi_ports;
struct amdtp_stream *streams;
struct fw_iso_resources *resources;
@@ -224,12 +239,23 @@ static int start_streams(struct snd_dice *dice, enum amdtp_stream_direction dir,
resources = dice->rx_resources;
}
+ err = snd_dice_stream_get_rate_mode(dice, rate, &mode);
+ if (err < 0)
+ return err;
+
for (i = 0; i < params->count; i++) {
+ unsigned int pcm_cache;
+ unsigned int midi_cache;
+
if (dir == AMDTP_IN_STREAM) {
+ pcm_cache = dice->tx_pcm_chs[i][mode];
+ midi_cache = dice->tx_midi_ports[i];
err = snd_dice_transaction_read_tx(dice,
params->size * i + TX_NUMBER_AUDIO,
reg, sizeof(reg));
} else {
+ pcm_cache = dice->rx_pcm_chs[i][mode];
+ midi_cache = dice->rx_midi_ports[i];
err = snd_dice_transaction_read_rx(dice,
params->size * i + RX_NUMBER_AUDIO,
reg, sizeof(reg));
@@ -239,6 +265,14 @@ static int start_streams(struct snd_dice *dice, enum amdtp_stream_direction dir,
pcm_chs = be32_to_cpu(reg[0]);
midi_ports = be32_to_cpu(reg[1]);
+ /* These are important for developer of this driver. */
+ if (pcm_chs != pcm_cache || midi_ports != midi_cache) {
+ dev_info(&dice->unit->device,
+ "cache mismatch: pcm: %u:%u, midi: %u:%u\n",
+ pcm_chs, pcm_cache, midi_ports, midi_cache);
+ return -EPROTO;
+ }
+
err = keep_resources(dice, dir, i, rate, pcm_chs, midi_ports);
if (err < 0)
return err;
@@ -290,12 +324,17 @@ static int start_duplex_streams(struct snd_dice *dice, unsigned int rate)
snd_dice_transaction_clear_enable(dice);
release_resources(dice);
- err = ensure_phase_lock(dice);
+ err = ensure_phase_lock(dice, rate);
if (err < 0) {
dev_err(&dice->unit->device, "fail to ensure phase lock\n");
return err;
}
+ /* Likely to have changed stream formats. */
+ err = get_register_params(dice, &tx_params, &rx_params);
+ if (err < 0)
+ return err;
+
/* Start both streams. */
err = start_streams(dice, AMDTP_IN_STREAM, rate, &tx_params);
if (err < 0)
@@ -356,7 +395,7 @@ int snd_dice_stream_start_duplex(struct snd_dice *dice, unsigned int rate)
if (rate == 0)
rate = curr_rate;
if (rate != curr_rate)
- return -EINVAL;
+ goto restart;
/* Check error of packet streaming. */
for (i = 0; i < MAX_STREAMS; ++i) {
@@ -550,7 +589,7 @@ int snd_dice_stream_detect_current_formats(struct snd_dice *dice)
* invalid stream formats. Selecting clock parameters have an effect
* for the unit to refine it.
*/
- err = ensure_phase_lock(dice);
+ err = ensure_phase_lock(dice, rate);
if (err < 0)
return err;
--
2.14.1
More information about the Alsa-devel
mailing list