OSDN Git Service

ALSA: dice: cache stream formats at current mode of sampling transmission frequency
authorTakashi Sakamoto <o-takashi@sakamocchi.jp>
Wed, 2 May 2018 10:16:42 +0000 (19:16 +0900)
committerTakashi Iwai <tiwai@suse.de>
Wed, 2 May 2018 14:01:54 +0000 (16:01 +0200)
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>
sound/firewire/dice/dice-stream.c
sound/firewire/dice/dice.c
sound/firewire/dice/dice.h

index 8573289..6c859d2 100644 (file)
@@ -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;
index 96bb01b..002f3f3 100644 (file)
@@ -199,6 +199,10 @@ static void do_registration(struct work_struct *work)
 
        dice_card_strings(dice);
 
+       err = snd_dice_stream_detect_current_formats(dice);
+       if (err < 0)
+               goto error;
+
        err = snd_dice_stream_init_duplex(dice);
        if (err < 0)
                goto error;
index 8f68976..0c044f2 100644 (file)
@@ -201,11 +201,14 @@ void snd_dice_transaction_destroy(struct snd_dice *dice);
 #define SND_DICE_RATES_COUNT   7
 extern const unsigned int snd_dice_rates[SND_DICE_RATES_COUNT];
 
+int snd_dice_stream_get_rate_mode(struct snd_dice *dice, unsigned int rate,
+                                 enum snd_dice_rate_mode *mode);
 int snd_dice_stream_start_duplex(struct snd_dice *dice, unsigned int rate);
 void snd_dice_stream_stop_duplex(struct snd_dice *dice);
 int snd_dice_stream_init_duplex(struct snd_dice *dice);
 void snd_dice_stream_destroy_duplex(struct snd_dice *dice);
 void snd_dice_stream_update_duplex(struct snd_dice *dice);
+int snd_dice_stream_detect_current_formats(struct snd_dice *dice);
 
 int snd_dice_stream_lock_try(struct snd_dice *dice);
 void snd_dice_stream_lock_release(struct snd_dice *dice);