Commit 0eee62e0 authored by Takashi Iwai's avatar Takashi Iwai

Merge branch 'topic/pcm-internal' into for-next

parents 8d085d3c b2022138
...@@ -49,8 +49,6 @@ static struct snd_pcm *snd_pcm_get(struct snd_card *card, int device) ...@@ -49,8 +49,6 @@ static struct snd_pcm *snd_pcm_get(struct snd_card *card, int device)
struct snd_pcm *pcm; struct snd_pcm *pcm;
list_for_each_entry(pcm, &snd_pcm_devices, list) { list_for_each_entry(pcm, &snd_pcm_devices, list) {
if (pcm->internal)
continue;
if (pcm->card == card && pcm->device == device) if (pcm->card == card && pcm->device == device)
return pcm; return pcm;
} }
...@@ -62,8 +60,6 @@ static int snd_pcm_next(struct snd_card *card, int device) ...@@ -62,8 +60,6 @@ static int snd_pcm_next(struct snd_card *card, int device)
struct snd_pcm *pcm; struct snd_pcm *pcm;
list_for_each_entry(pcm, &snd_pcm_devices, list) { list_for_each_entry(pcm, &snd_pcm_devices, list) {
if (pcm->internal)
continue;
if (pcm->card == card && pcm->device > device) if (pcm->card == card && pcm->device > device)
return pcm->device; return pcm->device;
else if (pcm->card->number > card->number) else if (pcm->card->number > card->number)
...@@ -76,6 +72,9 @@ static int snd_pcm_add(struct snd_pcm *newpcm) ...@@ -76,6 +72,9 @@ static int snd_pcm_add(struct snd_pcm *newpcm)
{ {
struct snd_pcm *pcm; struct snd_pcm *pcm;
if (newpcm->internal)
return 0;
list_for_each_entry(pcm, &snd_pcm_devices, list) { list_for_each_entry(pcm, &snd_pcm_devices, list) {
if (pcm->card == newpcm->card && pcm->device == newpcm->device) if (pcm->card == newpcm->card && pcm->device == newpcm->device)
return -EBUSY; return -EBUSY;
...@@ -782,6 +781,9 @@ static int _snd_pcm_new(struct snd_card *card, const char *id, int device, ...@@ -782,6 +781,9 @@ static int _snd_pcm_new(struct snd_card *card, const char *id, int device,
pcm->card = card; pcm->card = card;
pcm->device = device; pcm->device = device;
pcm->internal = internal; pcm->internal = internal;
mutex_init(&pcm->open_mutex);
init_waitqueue_head(&pcm->open_wait);
INIT_LIST_HEAD(&pcm->list);
if (id) if (id)
strlcpy(pcm->id, id, sizeof(pcm->id)); strlcpy(pcm->id, id, sizeof(pcm->id));
if ((err = snd_pcm_new_stream(pcm, SNDRV_PCM_STREAM_PLAYBACK, playback_count)) < 0) { if ((err = snd_pcm_new_stream(pcm, SNDRV_PCM_STREAM_PLAYBACK, playback_count)) < 0) {
...@@ -792,8 +794,6 @@ static int _snd_pcm_new(struct snd_card *card, const char *id, int device, ...@@ -792,8 +794,6 @@ static int _snd_pcm_new(struct snd_card *card, const char *id, int device,
snd_pcm_free(pcm); snd_pcm_free(pcm);
return err; return err;
} }
mutex_init(&pcm->open_mutex);
init_waitqueue_head(&pcm->open_wait);
if ((err = snd_device_new(card, SNDRV_DEV_PCM, pcm, &ops)) < 0) { if ((err = snd_device_new(card, SNDRV_DEV_PCM, pcm, &ops)) < 0) {
snd_pcm_free(pcm); snd_pcm_free(pcm);
return err; return err;
...@@ -888,7 +888,8 @@ static int snd_pcm_free(struct snd_pcm *pcm) ...@@ -888,7 +888,8 @@ static int snd_pcm_free(struct snd_pcm *pcm)
if (!pcm) if (!pcm)
return 0; return 0;
list_for_each_entry(notify, &snd_pcm_notify_list, list) { if (!pcm->internal) {
list_for_each_entry(notify, &snd_pcm_notify_list, list)
notify->n_unregister(pcm); notify->n_unregister(pcm);
} }
if (pcm->private_free) if (pcm->private_free)
...@@ -919,6 +920,9 @@ int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream, ...@@ -919,6 +920,9 @@ int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream,
if (snd_BUG_ON(!pcm || !rsubstream)) if (snd_BUG_ON(!pcm || !rsubstream))
return -ENXIO; return -ENXIO;
if (snd_BUG_ON(stream != SNDRV_PCM_STREAM_PLAYBACK &&
stream != SNDRV_PCM_STREAM_CAPTURE))
return -EINVAL;
*rsubstream = NULL; *rsubstream = NULL;
pstr = &pcm->streams[stream]; pstr = &pcm->streams[stream];
if (pstr->substream == NULL || pstr->substream_count == 0) if (pstr->substream == NULL || pstr->substream_count == 0)
...@@ -927,26 +931,15 @@ int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream, ...@@ -927,26 +931,15 @@ int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream,
card = pcm->card; card = pcm->card;
prefer_subdevice = snd_ctl_get_preferred_subdevice(card, SND_CTL_SUBDEV_PCM); prefer_subdevice = snd_ctl_get_preferred_subdevice(card, SND_CTL_SUBDEV_PCM);
switch (stream) {
case SNDRV_PCM_STREAM_PLAYBACK:
if (pcm->info_flags & SNDRV_PCM_INFO_HALF_DUPLEX) {
for (substream = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream; substream; substream = substream->next) {
if (SUBSTREAM_BUSY(substream))
return -EAGAIN;
}
}
break;
case SNDRV_PCM_STREAM_CAPTURE:
if (pcm->info_flags & SNDRV_PCM_INFO_HALF_DUPLEX) { if (pcm->info_flags & SNDRV_PCM_INFO_HALF_DUPLEX) {
for (substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; substream; substream = substream->next) { int opposite = !stream;
for (substream = pcm->streams[opposite].substream; substream;
substream = substream->next) {
if (SUBSTREAM_BUSY(substream)) if (SUBSTREAM_BUSY(substream))
return -EAGAIN; return -EAGAIN;
} }
} }
break;
default:
return -EINVAL;
}
if (file->f_flags & O_APPEND) { if (file->f_flags & O_APPEND) {
if (prefer_subdevice < 0) { if (prefer_subdevice < 0) {
...@@ -968,15 +961,12 @@ int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream, ...@@ -968,15 +961,12 @@ int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream,
return 0; return 0;
} }
if (prefer_subdevice >= 0) { for (substream = pstr->substream; substream; substream = substream->next) {
for (substream = pstr->substream; substream; substream = substream->next) if (!SUBSTREAM_BUSY(substream) &&
if (!SUBSTREAM_BUSY(substream) && substream->number == prefer_subdevice) (prefer_subdevice == -1 ||
goto __ok; substream->number == prefer_subdevice))
}
for (substream = pstr->substream; substream; substream = substream->next)
if (!SUBSTREAM_BUSY(substream))
break; break;
__ok: }
if (substream == NULL) if (substream == NULL)
return -EAGAIN; return -EAGAIN;
...@@ -1086,15 +1076,16 @@ static int snd_pcm_dev_register(struct snd_device *device) ...@@ -1086,15 +1076,16 @@ static int snd_pcm_dev_register(struct snd_device *device)
if (snd_BUG_ON(!device || !device->device_data)) if (snd_BUG_ON(!device || !device->device_data))
return -ENXIO; return -ENXIO;
pcm = device->device_data; pcm = device->device_data;
if (pcm->internal)
return 0;
mutex_lock(&register_mutex); mutex_lock(&register_mutex);
err = snd_pcm_add(pcm); err = snd_pcm_add(pcm);
if (err) { if (err)
mutex_unlock(&register_mutex); goto unlock;
return err;
}
for (cidx = 0; cidx < 2; cidx++) { for (cidx = 0; cidx < 2; cidx++) {
int devtype = -1; int devtype = -1;
if (pcm->streams[cidx].substream == NULL || pcm->internal) if (pcm->streams[cidx].substream == NULL)
continue; continue;
switch (cidx) { switch (cidx) {
case SNDRV_PCM_STREAM_PLAYBACK: case SNDRV_PCM_STREAM_PLAYBACK:
...@@ -1109,9 +1100,8 @@ static int snd_pcm_dev_register(struct snd_device *device) ...@@ -1109,9 +1100,8 @@ static int snd_pcm_dev_register(struct snd_device *device)
&snd_pcm_f_ops[cidx], pcm, &snd_pcm_f_ops[cidx], pcm,
&pcm->streams[cidx].dev); &pcm->streams[cidx].dev);
if (err < 0) { if (err < 0) {
list_del(&pcm->list); list_del_init(&pcm->list);
mutex_unlock(&register_mutex); goto unlock;
return err;
} }
for (substream = pcm->streams[cidx].substream; substream; substream = substream->next) for (substream = pcm->streams[cidx].substream; substream; substream = substream->next)
...@@ -1121,8 +1111,9 @@ static int snd_pcm_dev_register(struct snd_device *device) ...@@ -1121,8 +1111,9 @@ static int snd_pcm_dev_register(struct snd_device *device)
list_for_each_entry(notify, &snd_pcm_notify_list, list) list_for_each_entry(notify, &snd_pcm_notify_list, list)
notify->n_register(pcm); notify->n_register(pcm);
unlock:
mutex_unlock(&register_mutex); mutex_unlock(&register_mutex);
return 0; return err;
} }
static int snd_pcm_dev_disconnect(struct snd_device *device) static int snd_pcm_dev_disconnect(struct snd_device *device)
...@@ -1133,13 +1124,10 @@ static int snd_pcm_dev_disconnect(struct snd_device *device) ...@@ -1133,13 +1124,10 @@ static int snd_pcm_dev_disconnect(struct snd_device *device)
int cidx; int cidx;
mutex_lock(&register_mutex); mutex_lock(&register_mutex);
if (list_empty(&pcm->list))
goto unlock;
mutex_lock(&pcm->open_mutex); mutex_lock(&pcm->open_mutex);
wake_up(&pcm->open_wait); wake_up(&pcm->open_wait);
list_del_init(&pcm->list); list_del_init(&pcm->list);
for (cidx = 0; cidx < 2; cidx++) for (cidx = 0; cidx < 2; cidx++) {
for (substream = pcm->streams[cidx].substream; substream; substream = substream->next) { for (substream = pcm->streams[cidx].substream; substream; substream = substream->next) {
snd_pcm_stream_lock_irq(substream); snd_pcm_stream_lock_irq(substream);
if (substream->runtime) { if (substream->runtime) {
...@@ -1149,10 +1137,13 @@ static int snd_pcm_dev_disconnect(struct snd_device *device) ...@@ -1149,10 +1137,13 @@ static int snd_pcm_dev_disconnect(struct snd_device *device)
} }
snd_pcm_stream_unlock_irq(substream); snd_pcm_stream_unlock_irq(substream);
} }
list_for_each_entry(notify, &snd_pcm_notify_list, list) { }
if (!pcm->internal) {
list_for_each_entry(notify, &snd_pcm_notify_list, list)
notify->n_disconnect(pcm); notify->n_disconnect(pcm);
} }
for (cidx = 0; cidx < 2; cidx++) { for (cidx = 0; cidx < 2; cidx++) {
if (!pcm->internal)
snd_unregister_device(&pcm->streams[cidx].dev); snd_unregister_device(&pcm->streams[cidx].dev);
if (pcm->streams[cidx].chmap_kctl) { if (pcm->streams[cidx].chmap_kctl) {
snd_ctl_remove(pcm->card, pcm->streams[cidx].chmap_kctl); snd_ctl_remove(pcm->card, pcm->streams[cidx].chmap_kctl);
...@@ -1160,7 +1151,6 @@ static int snd_pcm_dev_disconnect(struct snd_device *device) ...@@ -1160,7 +1151,6 @@ static int snd_pcm_dev_disconnect(struct snd_device *device)
} }
} }
mutex_unlock(&pcm->open_mutex); mutex_unlock(&pcm->open_mutex);
unlock:
mutex_unlock(&register_mutex); mutex_unlock(&register_mutex);
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment