summaryrefslogtreecommitdiff
path: root/sound/firewire/dice/dice-stream.c
diff options
context:
space:
mode:
authorTakashi Sakamoto <o-takashi@sakamocchi.jp>2018-05-02 19:16:42 +0900
committerTakashi Iwai <tiwai@suse.de>2018-05-02 16:01:54 +0200
commitb60152f750ca22ddee20954228d1bcbf45c936f7 (patch)
tree63bbac659351138217f48eb86d6f6c3e36c75c2c /sound/firewire/dice/dice-stream.c
parentb7fd3d64e763c381de7ed57217fda3c720a98aad (diff)
ALSA: dice: cache stream formats at current mode of sampling transmission frequency
In former commits, proxy structure get members for cache of stream formats. This commit fills the cache with stream formats at current mode of sampling transmission frequency. Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp> Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/firewire/dice/dice-stream.c')
-rw-r--r--sound/firewire/dice/dice-stream.c86
1 files changed, 86 insertions, 0 deletions
diff --git a/sound/firewire/dice/dice-stream.c b/sound/firewire/dice/dice-stream.c
index 8573289c381e..6c859d2b9084 100644
--- a/sound/firewire/dice/dice-stream.c
+++ b/sound/firewire/dice/dice-stream.c
@@ -30,6 +30,34 @@ const unsigned int snd_dice_rates[SND_DICE_RATES_COUNT] = {
[6] = 192000,
};
+int snd_dice_stream_get_rate_mode(struct snd_dice *dice, unsigned int rate,
+ enum snd_dice_rate_mode *mode)
+{
+ /* Corresponding to each entry in snd_dice_rates. */
+ static const enum snd_dice_rate_mode modes[] = {
+ [0] = SND_DICE_RATE_MODE_LOW,
+ [1] = SND_DICE_RATE_MODE_LOW,
+ [2] = SND_DICE_RATE_MODE_LOW,
+ [3] = SND_DICE_RATE_MODE_MIDDLE,
+ [4] = SND_DICE_RATE_MODE_MIDDLE,
+ [5] = SND_DICE_RATE_MODE_HIGH,
+ [6] = SND_DICE_RATE_MODE_HIGH,
+ };
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(snd_dice_rates); i++) {
+ if (!(dice->clock_caps & BIT(i)))
+ continue;
+ if (snd_dice_rates[i] != rate)
+ continue;
+
+ *mode = modes[i];
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
/*
* This operation has an effect to synchronize GLOBAL_STATUS/GLOBAL_SAMPLE_RATE
* to GLOBAL_STATUS. Especially, just after powering on, these are different.
@@ -484,6 +512,64 @@ void snd_dice_stream_update_duplex(struct snd_dice *dice)
}
}
+int snd_dice_stream_detect_current_formats(struct snd_dice *dice)
+{
+ unsigned int rate;
+ enum snd_dice_rate_mode mode;
+ __be32 reg[2];
+ struct reg_params tx_params, rx_params;
+ int i;
+ int err;
+
+ /*
+ * Available stream format is restricted at current mode of sampling
+ * clock.
+ */
+ err = snd_dice_transaction_get_rate(dice, &rate);
+ if (err < 0)
+ return err;
+
+ err = snd_dice_stream_get_rate_mode(dice, rate, &mode);
+ if (err < 0)
+ return err;
+
+ /*
+ * Just after owning the unit (GLOBAL_OWNER), the unit can return
+ * invalid stream formats. Selecting clock parameters have an effect
+ * for the unit to refine it.
+ */
+ err = ensure_phase_lock(dice);
+ if (err < 0)
+ return err;
+
+ err = get_register_params(dice, &tx_params, &rx_params);
+ if (err < 0)
+ return err;
+
+ for (i = 0; i < tx_params.count; ++i) {
+ err = snd_dice_transaction_read_tx(dice,
+ tx_params.size * i + TX_NUMBER_AUDIO,
+ reg, sizeof(reg));
+ if (err < 0)
+ return err;
+ dice->tx_pcm_chs[i][mode] = be32_to_cpu(reg[0]);
+ dice->tx_midi_ports[i] = max_t(unsigned int,
+ be32_to_cpu(reg[1]), dice->tx_midi_ports[i]);
+ }
+ for (i = 0; i < rx_params.count; ++i) {
+ err = snd_dice_transaction_read_rx(dice,
+ rx_params.size * i + RX_NUMBER_AUDIO,
+ reg, sizeof(reg));
+ if (err < 0)
+ return err;
+ dice->rx_pcm_chs[i][mode] = be32_to_cpu(reg[0]);
+ dice->rx_midi_ports[i] = max_t(unsigned int,
+ be32_to_cpu(reg[1]), dice->rx_midi_ports[i]);
+ }
+
+ return 0;
+}
+
static void dice_lock_changed(struct snd_dice *dice)
{
dice->dev_lock_changed = true;