]> Git Repo - linux.git/commitdiff
Merge branch 'for-next' into for-linus
authorTakashi Iwai <[email protected]>
Sat, 14 Sep 2019 15:24:57 +0000 (17:24 +0200)
committerTakashi Iwai <[email protected]>
Sat, 14 Sep 2019 15:26:10 +0000 (17:26 +0200)
Signed-off-by: Takashi Iwai <[email protected]>
1  2 
sound/firewire/tascam/tascam-stream.c

index ccfa92fbc1453b90343ac8d30aec55ee143cea7c,9e2dc2fe3271da060beabaa0ae71770783f52e63..adf69a520b800bb68eed64adc00e3d68664412e8
@@@ -8,37 -8,20 +8,37 @@@
  #include <linux/delay.h>
  #include "tascam.h"
  
 +#define CLOCK_STATUS_MASK      0xffff0000
 +#define CLOCK_CONFIG_MASK      0x0000ffff
 +
  #define CALLBACK_TIMEOUT 500
  
  static int get_clock(struct snd_tscm *tscm, u32 *data)
  {
 +      int trial = 0;
        __be32 reg;
        int err;
  
 -      err = snd_fw_transaction(tscm->unit, TCODE_READ_QUADLET_REQUEST,
 -                               TSCM_ADDR_BASE + TSCM_OFFSET_CLOCK_STATUS,
 -                               &reg, sizeof(reg), 0);
 -      if (err >= 0)
 +      while (trial++ < 5) {
 +              err = snd_fw_transaction(tscm->unit, TCODE_READ_QUADLET_REQUEST,
 +                              TSCM_ADDR_BASE + TSCM_OFFSET_CLOCK_STATUS,
 +                              &reg, sizeof(reg), 0);
 +              if (err < 0)
 +                      return err;
 +
                *data = be32_to_cpu(reg);
 +              if (*data & CLOCK_STATUS_MASK)
 +                      break;
  
 -      return err;
 +              // In intermediate state after changing clock status.
 +              msleep(50);
 +      }
 +
 +      // Still in the intermediate state.
 +      if (trial >= 5)
 +              return -EAGAIN;
 +
 +      return 0;
  }
  
  static int set_clock(struct snd_tscm *tscm, unsigned int rate,
@@@ -51,7 -34,7 +51,7 @@@
        err = get_clock(tscm, &data);
        if (err < 0)
                return err;
 -      data &= 0x0000ffff;
 +      data &= CLOCK_CONFIG_MASK;
  
        if (rate > 0) {
                data &= 0x000000ff;
  
  int snd_tscm_stream_get_rate(struct snd_tscm *tscm, unsigned int *rate)
  {
 -      u32 data = 0x0;
 -      unsigned int trials = 0;
 +      u32 data;
        int err;
  
 -      while (data == 0x0 || trials++ < 5) {
 -              err = get_clock(tscm, &data);
 -              if (err < 0)
 -                      return err;
 +      err = get_clock(tscm, &data);
 +      if (err < 0)
 +              return err;
  
 -              data = (data & 0xff000000) >> 24;
 -      }
 +      data = (data & 0xff000000) >> 24;
  
        /* Check base rate. */
        if ((data & 0x0f) == 0x01)
@@@ -194,9 -180,6 +194,6 @@@ static void finish_session(struct snd_t
  {
        __be32 reg;
  
-       amdtp_stream_stop(&tscm->rx_stream);
-       amdtp_stream_stop(&tscm->tx_stream);
        reg = 0;
        snd_fw_transaction(tscm->unit, TCODE_WRITE_QUADLET_REQUEST,
                           TSCM_ADDR_BASE + TSCM_OFFSET_START_STREAMING,
@@@ -301,38 -284,68 +298,68 @@@ static int keep_resources(struct snd_ts
                                fw_parent_device(tscm->unit)->max_speed);
  }
  
int snd_tscm_stream_init_duplex(struct snd_tscm *tscm)
static int init_stream(struct snd_tscm *tscm, struct amdtp_stream *s)
  {
+       struct fw_iso_resources *resources;
+       enum amdtp_stream_direction dir;
        unsigned int pcm_channels;
        int err;
  
-       /* For out-stream. */
-       err = fw_iso_resources_init(&tscm->rx_resources, tscm->unit);
-       if (err < 0)
-               return err;
-       pcm_channels = tscm->spec->pcm_playback_analog_channels;
+       if (s == &tscm->tx_stream) {
+               resources = &tscm->tx_resources;
+               dir = AMDTP_IN_STREAM;
+               pcm_channels = tscm->spec->pcm_capture_analog_channels;
+       } else {
+               resources = &tscm->rx_resources;
+               dir = AMDTP_OUT_STREAM;
+               pcm_channels = tscm->spec->pcm_playback_analog_channels;
+       }
        if (tscm->spec->has_adat)
                pcm_channels += 8;
        if (tscm->spec->has_spdif)
                pcm_channels += 2;
-       err = amdtp_tscm_init(&tscm->rx_stream, tscm->unit, AMDTP_OUT_STREAM,
-                             pcm_channels);
+       err = fw_iso_resources_init(resources, tscm->unit);
        if (err < 0)
                return err;
  
-       /* For in-stream. */
-       err = fw_iso_resources_init(&tscm->tx_resources, tscm->unit);
+       err = amdtp_tscm_init(s, tscm->unit, dir, pcm_channels);
        if (err < 0)
-               return err;
-       pcm_channels = tscm->spec->pcm_capture_analog_channels;
-       if (tscm->spec->has_adat)
-               pcm_channels += 8;
-       if (tscm->spec->has_spdif)
-               pcm_channels += 2;
-       err = amdtp_tscm_init(&tscm->tx_stream, tscm->unit, AMDTP_IN_STREAM,
-                             pcm_channels);
+               fw_iso_resources_free(resources);
+       return err;
+ }
+ static void destroy_stream(struct snd_tscm *tscm, struct amdtp_stream *s)
+ {
+       amdtp_stream_destroy(s);
+       if (s == &tscm->tx_stream)
+               fw_iso_resources_destroy(&tscm->tx_resources);
+       else
+               fw_iso_resources_destroy(&tscm->rx_resources);
+ }
+ int snd_tscm_stream_init_duplex(struct snd_tscm *tscm)
+ {
+       int err;
+       err = init_stream(tscm, &tscm->tx_stream);
        if (err < 0)
-               amdtp_stream_destroy(&tscm->rx_stream);
+               return err;
+       err = init_stream(tscm, &tscm->rx_stream);
+       if (err < 0) {
+               destroy_stream(tscm, &tscm->tx_stream);
+               return err;
+       }
+       err = amdtp_domain_init(&tscm->domain);
+       if (err < 0) {
+               destroy_stream(tscm, &tscm->tx_stream);
+               destroy_stream(tscm, &tscm->rx_stream);
+       }
  
        return err;
  }
  // At bus reset, streaming is stopped and some registers are clear.
  void snd_tscm_stream_update_duplex(struct snd_tscm *tscm)
  {
-       amdtp_stream_pcm_abort(&tscm->tx_stream);
-       amdtp_stream_stop(&tscm->tx_stream);
+       amdtp_domain_stop(&tscm->domain);
  
+       amdtp_stream_pcm_abort(&tscm->tx_stream);
        amdtp_stream_pcm_abort(&tscm->rx_stream);
-       amdtp_stream_stop(&tscm->rx_stream);
  }
  
- /*
-  * This function should be called before starting streams or after stopping
-  * streams.
-  */
+ // This function should be called before starting streams or after stopping
+ // streams.
  void snd_tscm_stream_destroy_duplex(struct snd_tscm *tscm)
  {
-       amdtp_stream_destroy(&tscm->rx_stream);
-       amdtp_stream_destroy(&tscm->tx_stream);
+       amdtp_domain_destroy(&tscm->domain);
  
-       fw_iso_resources_destroy(&tscm->rx_resources);
-       fw_iso_resources_destroy(&tscm->tx_resources);
+       destroy_stream(tscm, &tscm->rx_stream);
+       destroy_stream(tscm, &tscm->tx_stream);
  }
  
  int snd_tscm_stream_reserve_duplex(struct snd_tscm *tscm, unsigned int rate)
                return err;
  
        if (tscm->substreams_counter == 0 || rate != curr_rate) {
+               amdtp_domain_stop(&tscm->domain);
                finish_session(tscm);
  
                fw_iso_resources_free(&tscm->tx_resources);
@@@ -402,8 -413,10 +427,10 @@@ int snd_tscm_stream_start_duplex(struc
                return 0;
  
        if (amdtp_streaming_error(&tscm->rx_stream) ||
-           amdtp_streaming_error(&tscm->tx_stream))
+           amdtp_streaming_error(&tscm->tx_stream)) {
+               amdtp_domain_stop(&tscm->domain);
                finish_session(tscm);
+       }
  
        if (generation != fw_parent_device(tscm->unit)->card->generation) {
                err = fw_iso_resources_update(&tscm->tx_resources);
        }
  
        if (!amdtp_stream_running(&tscm->rx_stream)) {
+               int spd = fw_parent_device(tscm->unit)->max_speed;
                err = set_stream_formats(tscm, rate);
                if (err < 0)
                        goto error;
                if (err < 0)
                        goto error;
  
-               err = amdtp_stream_start(&tscm->rx_stream,
-                               tscm->rx_resources.channel,
-                               fw_parent_device(tscm->unit)->max_speed);
+               err = amdtp_domain_add_stream(&tscm->domain, &tscm->rx_stream,
+                                             tscm->rx_resources.channel, spd);
                if (err < 0)
                        goto error;
  
-               if (!amdtp_stream_wait_callback(&tscm->rx_stream,
-                                               CALLBACK_TIMEOUT)) {
-                       err = -ETIMEDOUT;
+               err = amdtp_domain_add_stream(&tscm->domain, &tscm->tx_stream,
+                                             tscm->tx_resources.channel, spd);
+               if (err < 0)
                        goto error;
-               }
-       }
  
-       if (!amdtp_stream_running(&tscm->tx_stream)) {
-               err = amdtp_stream_start(&tscm->tx_stream,
-                               tscm->tx_resources.channel,
-                               fw_parent_device(tscm->unit)->max_speed);
+               err = amdtp_domain_start(&tscm->domain);
                if (err < 0)
-                       goto error;
+                       return err;
  
-               if (!amdtp_stream_wait_callback(&tscm->tx_stream,
+               if (!amdtp_stream_wait_callback(&tscm->rx_stream,
+                                               CALLBACK_TIMEOUT) ||
+                   !amdtp_stream_wait_callback(&tscm->tx_stream,
                                                CALLBACK_TIMEOUT)) {
                        err = -ETIMEDOUT;
                        goto error;
  
        return 0;
  error:
+       amdtp_domain_stop(&tscm->domain);
        finish_session(tscm);
  
        return err;
  void snd_tscm_stream_stop_duplex(struct snd_tscm *tscm)
  {
        if (tscm->substreams_counter == 0) {
+               amdtp_domain_stop(&tscm->domain);
                finish_session(tscm);
  
                fw_iso_resources_free(&tscm->tx_resources);
This page took 0.070351 seconds and 4 git commands to generate.