|
@@ -358,7 +358,7 @@ static int snd_usX2Y_usbpcm_hw_free(struct snd_pcm_substream *substream)
|
|
struct snd_pcm_runtime *runtime = substream->runtime;
|
|
struct snd_pcm_runtime *runtime = substream->runtime;
|
|
struct snd_usX2Y_substream *subs = runtime->private_data,
|
|
struct snd_usX2Y_substream *subs = runtime->private_data,
|
|
*cap_subs2 = subs->usX2Y->subs[SNDRV_PCM_STREAM_CAPTURE + 2];
|
|
*cap_subs2 = subs->usX2Y->subs[SNDRV_PCM_STREAM_CAPTURE + 2];
|
|
- mutex_lock(&subs->usX2Y->prepare_mutex);
|
|
|
|
|
|
+ mutex_lock(&subs->usX2Y->pcm_mutex);
|
|
snd_printdd("snd_usX2Y_usbpcm_hw_free(%p)\n", substream);
|
|
snd_printdd("snd_usX2Y_usbpcm_hw_free(%p)\n", substream);
|
|
|
|
|
|
if (SNDRV_PCM_STREAM_PLAYBACK == substream->stream) {
|
|
if (SNDRV_PCM_STREAM_PLAYBACK == substream->stream) {
|
|
@@ -387,7 +387,7 @@ static int snd_usX2Y_usbpcm_hw_free(struct snd_pcm_substream *substream)
|
|
usX2Y_usbpcm_urbs_release(cap_subs2);
|
|
usX2Y_usbpcm_urbs_release(cap_subs2);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
- mutex_unlock(&subs->usX2Y->prepare_mutex);
|
|
|
|
|
|
+ mutex_unlock(&subs->usX2Y->pcm_mutex);
|
|
return snd_pcm_lib_free_pages(substream);
|
|
return snd_pcm_lib_free_pages(substream);
|
|
}
|
|
}
|
|
|
|
|
|
@@ -493,7 +493,7 @@ static int snd_usX2Y_usbpcm_prepare(struct snd_pcm_substream *substream)
|
|
memset(usX2Y->hwdep_pcm_shm, 0, sizeof(struct snd_usX2Y_hwdep_pcm_shm));
|
|
memset(usX2Y->hwdep_pcm_shm, 0, sizeof(struct snd_usX2Y_hwdep_pcm_shm));
|
|
}
|
|
}
|
|
|
|
|
|
- mutex_lock(&usX2Y->prepare_mutex);
|
|
|
|
|
|
+ mutex_lock(&usX2Y->pcm_mutex);
|
|
usX2Y_subs_prepare(subs);
|
|
usX2Y_subs_prepare(subs);
|
|
// Start hardware streams
|
|
// Start hardware streams
|
|
// SyncStream first....
|
|
// SyncStream first....
|
|
@@ -534,7 +534,7 @@ static int snd_usX2Y_usbpcm_prepare(struct snd_pcm_substream *substream)
|
|
usX2Y->hwdep_pcm_shm->capture_iso_start = -1;
|
|
usX2Y->hwdep_pcm_shm->capture_iso_start = -1;
|
|
|
|
|
|
up_prepare_mutex:
|
|
up_prepare_mutex:
|
|
- mutex_unlock(&usX2Y->prepare_mutex);
|
|
|
|
|
|
+ mutex_unlock(&usX2Y->pcm_mutex);
|
|
return err;
|
|
return err;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -600,59 +600,30 @@ static struct snd_pcm_ops snd_usX2Y_usbpcm_ops =
|
|
};
|
|
};
|
|
|
|
|
|
|
|
|
|
-static int usX2Y_pcms_lock_check(struct snd_card *card)
|
|
|
|
|
|
+static int usX2Y_pcms_busy_check(struct snd_card *card)
|
|
{
|
|
{
|
|
- struct list_head *list;
|
|
|
|
- struct snd_device *dev;
|
|
|
|
- struct snd_pcm *pcm;
|
|
|
|
- int err = 0;
|
|
|
|
- list_for_each(list, &card->devices) {
|
|
|
|
- dev = snd_device(list);
|
|
|
|
- if (dev->type != SNDRV_DEV_PCM)
|
|
|
|
- continue;
|
|
|
|
- pcm = dev->device_data;
|
|
|
|
- mutex_lock(&pcm->open_mutex);
|
|
|
|
- }
|
|
|
|
- list_for_each(list, &card->devices) {
|
|
|
|
- int s;
|
|
|
|
- dev = snd_device(list);
|
|
|
|
- if (dev->type != SNDRV_DEV_PCM)
|
|
|
|
- continue;
|
|
|
|
- pcm = dev->device_data;
|
|
|
|
- for (s = 0; s < 2; ++s) {
|
|
|
|
- struct snd_pcm_substream *substream;
|
|
|
|
- substream = pcm->streams[s].substream;
|
|
|
|
- if (substream && SUBSTREAM_BUSY(substream))
|
|
|
|
- err = -EBUSY;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- return err;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
|
|
+ struct usX2Ydev *dev = usX2Y(card);
|
|
|
|
+ int i;
|
|
|
|
|
|
-static void usX2Y_pcms_unlock(struct snd_card *card)
|
|
|
|
-{
|
|
|
|
- struct list_head *list;
|
|
|
|
- struct snd_device *dev;
|
|
|
|
- struct snd_pcm *pcm;
|
|
|
|
- list_for_each(list, &card->devices) {
|
|
|
|
- dev = snd_device(list);
|
|
|
|
- if (dev->type != SNDRV_DEV_PCM)
|
|
|
|
- continue;
|
|
|
|
- pcm = dev->device_data;
|
|
|
|
- mutex_unlock(&pcm->open_mutex);
|
|
|
|
|
|
+ for (i = 0; i < dev->pcm_devs * 2; i++) {
|
|
|
|
+ struct snd_usX2Y_substream *subs = dev->subs[i];
|
|
|
|
+ if (subs && subs->pcm_substream &&
|
|
|
|
+ SUBSTREAM_BUSY(subs->pcm_substream))
|
|
|
|
+ return -EBUSY;
|
|
}
|
|
}
|
|
|
|
+ return 0;
|
|
}
|
|
}
|
|
|
|
|
|
-
|
|
|
|
static int snd_usX2Y_hwdep_pcm_open(struct snd_hwdep *hw, struct file *file)
|
|
static int snd_usX2Y_hwdep_pcm_open(struct snd_hwdep *hw, struct file *file)
|
|
{
|
|
{
|
|
- // we need to be the first
|
|
|
|
struct snd_card *card = hw->card;
|
|
struct snd_card *card = hw->card;
|
|
- int err = usX2Y_pcms_lock_check(card);
|
|
|
|
- if (0 == err)
|
|
|
|
|
|
+ int err;
|
|
|
|
+
|
|
|
|
+ mutex_lock(&usX2Y(card)->pcm_mutex);
|
|
|
|
+ err = usX2Y_pcms_busy_check(card);
|
|
|
|
+ if (!err)
|
|
usX2Y(card)->chip_status |= USX2Y_STAT_CHIP_MMAP_PCM_URBS;
|
|
usX2Y(card)->chip_status |= USX2Y_STAT_CHIP_MMAP_PCM_URBS;
|
|
- usX2Y_pcms_unlock(card);
|
|
|
|
|
|
+ mutex_unlock(&usX2Y(card)->pcm_mutex);
|
|
return err;
|
|
return err;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -660,10 +631,13 @@ static int snd_usX2Y_hwdep_pcm_open(struct snd_hwdep *hw, struct file *file)
|
|
static int snd_usX2Y_hwdep_pcm_release(struct snd_hwdep *hw, struct file *file)
|
|
static int snd_usX2Y_hwdep_pcm_release(struct snd_hwdep *hw, struct file *file)
|
|
{
|
|
{
|
|
struct snd_card *card = hw->card;
|
|
struct snd_card *card = hw->card;
|
|
- int err = usX2Y_pcms_lock_check(card);
|
|
|
|
- if (0 == err)
|
|
|
|
|
|
+ int err;
|
|
|
|
+
|
|
|
|
+ mutex_lock(&usX2Y(card)->pcm_mutex);
|
|
|
|
+ err = usX2Y_pcms_busy_check(card);
|
|
|
|
+ if (!err)
|
|
usX2Y(hw->card)->chip_status &= ~USX2Y_STAT_CHIP_MMAP_PCM_URBS;
|
|
usX2Y(hw->card)->chip_status &= ~USX2Y_STAT_CHIP_MMAP_PCM_URBS;
|
|
- usX2Y_pcms_unlock(card);
|
|
|
|
|
|
+ mutex_unlock(&usX2Y(card)->pcm_mutex);
|
|
return err;
|
|
return err;
|
|
}
|
|
}
|
|
|
|
|