summaryrefslogtreecommitdiff
path: root/sound/core/pcm.c
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2015-04-20 11:32:26 +1000
committerDave Airlie <airlied@redhat.com>2015-04-20 13:05:20 +1000
commit2c33ce009ca2389dbf0535d0672214d09738e35e (patch)
tree6186a6458c3c160385d794a23eaf07c786a9e61b /sound/core/pcm.c
parentcec32a47010647e8b0603726ebb75b990a4057a4 (diff)
parent09d51602cf84a1264946711dd4ea0dddbac599a1 (diff)
Merge Linus master into drm-next
The merge is clean, but the arm build fails afterwards, due to API changes in the regulator tree. I've included the patch into the merge to fix the build. Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'sound/core/pcm.c')
-rw-r--r--sound/core/pcm.c105
1 files changed, 44 insertions, 61 deletions
diff --git a/sound/core/pcm.c b/sound/core/pcm.c
index 0345e53a340c..b25bcf5b8644 100644
--- a/sound/core/pcm.c
+++ b/sound/core/pcm.c
@@ -49,8 +49,6 @@ static struct snd_pcm *snd_pcm_get(struct snd_card *card, int device)
struct snd_pcm *pcm;
list_for_each_entry(pcm, &snd_pcm_devices, list) {
- if (pcm->internal)
- continue;
if (pcm->card == card && pcm->device == device)
return pcm;
}
@@ -62,8 +60,6 @@ static int snd_pcm_next(struct snd_card *card, int device)
struct snd_pcm *pcm;
list_for_each_entry(pcm, &snd_pcm_devices, list) {
- if (pcm->internal)
- continue;
if (pcm->card == card && pcm->device > device)
return pcm->device;
else if (pcm->card->number > card->number)
@@ -76,6 +72,9 @@ static int snd_pcm_add(struct snd_pcm *newpcm)
{
struct snd_pcm *pcm;
+ if (newpcm->internal)
+ return 0;
+
list_for_each_entry(pcm, &snd_pcm_devices, list) {
if (pcm->card == newpcm->card && pcm->device == newpcm->device)
return -EBUSY;
@@ -344,11 +343,8 @@ static void snd_pcm_proc_info_read(struct snd_pcm_substream *substream,
return;
info = kmalloc(sizeof(*info), GFP_KERNEL);
- if (! info) {
- pcm_dbg(substream->pcm,
- "snd_pcm_proc_info_read: cannot malloc\n");
+ if (!info)
return;
- }
err = snd_pcm_info(substream, info);
if (err < 0) {
@@ -718,10 +714,8 @@ int snd_pcm_new_stream(struct snd_pcm *pcm, int stream, int substream_count)
prev = NULL;
for (idx = 0, prev = NULL; idx < substream_count; idx++) {
substream = kzalloc(sizeof(*substream), GFP_KERNEL);
- if (substream == NULL) {
- pcm_err(pcm, "Cannot allocate PCM substream\n");
+ if (!substream)
return -ENOMEM;
- }
substream->pcm = pcm;
substream->pstr = pstr;
substream->number = idx;
@@ -775,13 +769,14 @@ static int _snd_pcm_new(struct snd_card *card, const char *id, int device,
if (rpcm)
*rpcm = NULL;
pcm = kzalloc(sizeof(*pcm), GFP_KERNEL);
- if (pcm == NULL) {
- dev_err(card->dev, "Cannot allocate PCM\n");
+ if (!pcm)
return -ENOMEM;
- }
pcm->card = card;
pcm->device = device;
pcm->internal = internal;
+ mutex_init(&pcm->open_mutex);
+ init_waitqueue_head(&pcm->open_wait);
+ INIT_LIST_HEAD(&pcm->list);
if (id)
strlcpy(pcm->id, id, sizeof(pcm->id));
if ((err = snd_pcm_new_stream(pcm, SNDRV_PCM_STREAM_PLAYBACK, playback_count)) < 0) {
@@ -792,8 +787,6 @@ static int _snd_pcm_new(struct snd_card *card, const char *id, int device,
snd_pcm_free(pcm);
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) {
snd_pcm_free(pcm);
return err;
@@ -888,8 +881,9 @@ static int snd_pcm_free(struct snd_pcm *pcm)
if (!pcm)
return 0;
- list_for_each_entry(notify, &snd_pcm_notify_list, list) {
- notify->n_unregister(pcm);
+ if (!pcm->internal) {
+ list_for_each_entry(notify, &snd_pcm_notify_list, list)
+ notify->n_unregister(pcm);
}
if (pcm->private_free)
pcm->private_free(pcm);
@@ -919,6 +913,9 @@ int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream,
if (snd_BUG_ON(!pcm || !rsubstream))
return -ENXIO;
+ if (snd_BUG_ON(stream != SNDRV_PCM_STREAM_PLAYBACK &&
+ stream != SNDRV_PCM_STREAM_CAPTURE))
+ return -EINVAL;
*rsubstream = NULL;
pstr = &pcm->streams[stream];
if (pstr->substream == NULL || pstr->substream_count == 0)
@@ -927,25 +924,14 @@ int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream,
card = pcm->card;
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) {
- for (substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; substream; substream = substream->next) {
- if (SUBSTREAM_BUSY(substream))
- return -EAGAIN;
- }
+ if (pcm->info_flags & SNDRV_PCM_INFO_HALF_DUPLEX) {
+ int opposite = !stream;
+
+ for (substream = pcm->streams[opposite].substream; substream;
+ substream = substream->next) {
+ if (SUBSTREAM_BUSY(substream))
+ return -EAGAIN;
}
- break;
- default:
- return -EINVAL;
}
if (file->f_flags & O_APPEND) {
@@ -968,15 +954,12 @@ int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream,
return 0;
}
- if (prefer_subdevice >= 0) {
- for (substream = pstr->substream; substream; substream = substream->next)
- if (!SUBSTREAM_BUSY(substream) && substream->number == prefer_subdevice)
- goto __ok;
- }
- for (substream = pstr->substream; substream; substream = substream->next)
- if (!SUBSTREAM_BUSY(substream))
+ for (substream = pstr->substream; substream; substream = substream->next) {
+ if (!SUBSTREAM_BUSY(substream) &&
+ (prefer_subdevice == -1 ||
+ substream->number == prefer_subdevice))
break;
- __ok:
+ }
if (substream == NULL)
return -EAGAIN;
@@ -1086,15 +1069,16 @@ static int snd_pcm_dev_register(struct snd_device *device)
if (snd_BUG_ON(!device || !device->device_data))
return -ENXIO;
pcm = device->device_data;
+ if (pcm->internal)
+ return 0;
+
mutex_lock(&register_mutex);
err = snd_pcm_add(pcm);
- if (err) {
- mutex_unlock(&register_mutex);
- return err;
- }
+ if (err)
+ goto unlock;
for (cidx = 0; cidx < 2; cidx++) {
int devtype = -1;
- if (pcm->streams[cidx].substream == NULL || pcm->internal)
+ if (pcm->streams[cidx].substream == NULL)
continue;
switch (cidx) {
case SNDRV_PCM_STREAM_PLAYBACK:
@@ -1109,9 +1093,8 @@ static int snd_pcm_dev_register(struct snd_device *device)
&snd_pcm_f_ops[cidx], pcm,
&pcm->streams[cidx].dev);
if (err < 0) {
- list_del(&pcm->list);
- mutex_unlock(&register_mutex);
- return err;
+ list_del_init(&pcm->list);
+ goto unlock;
}
for (substream = pcm->streams[cidx].substream; substream; substream = substream->next)
@@ -1121,8 +1104,9 @@ static int snd_pcm_dev_register(struct snd_device *device)
list_for_each_entry(notify, &snd_pcm_notify_list, list)
notify->n_register(pcm);
+ unlock:
mutex_unlock(&register_mutex);
- return 0;
+ return err;
}
static int snd_pcm_dev_disconnect(struct snd_device *device)
@@ -1133,13 +1117,10 @@ static int snd_pcm_dev_disconnect(struct snd_device *device)
int cidx;
mutex_lock(&register_mutex);
- if (list_empty(&pcm->list))
- goto unlock;
-
mutex_lock(&pcm->open_mutex);
wake_up(&pcm->open_wait);
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) {
snd_pcm_stream_lock_irq(substream);
if (substream->runtime) {
@@ -1149,18 +1130,20 @@ static int snd_pcm_dev_disconnect(struct snd_device *device)
}
snd_pcm_stream_unlock_irq(substream);
}
- list_for_each_entry(notify, &snd_pcm_notify_list, list) {
- notify->n_disconnect(pcm);
+ }
+ if (!pcm->internal) {
+ list_for_each_entry(notify, &snd_pcm_notify_list, list)
+ notify->n_disconnect(pcm);
}
for (cidx = 0; cidx < 2; cidx++) {
- snd_unregister_device(&pcm->streams[cidx].dev);
+ if (!pcm->internal)
+ snd_unregister_device(&pcm->streams[cidx].dev);
if (pcm->streams[cidx].chmap_kctl) {
snd_ctl_remove(pcm->card, pcm->streams[cidx].chmap_kctl);
pcm->streams[cidx].chmap_kctl = NULL;
}
}
mutex_unlock(&pcm->open_mutex);
- unlock:
mutex_unlock(&register_mutex);
return 0;
}