Merge tag 'device-for-3.4' of git://git.kernel.org/pub/scm/linux/kernel/git/paulg...
[linux-2.6.git] / sound / core / pcm.c
index 1888a90..1a3070b 100644 (file)
@@ -651,7 +651,7 @@ int snd_pcm_new_stream(struct snd_pcm *pcm, int stream, int substream_count)
        pstr->stream = stream;
        pstr->pcm = pcm;
        pstr->substream_count = substream_count;
-       if (substream_count > 0) {
+       if (substream_count > 0 && !pcm->internal) {
                err = snd_pcm_stream_proc_init(pstr);
                if (err < 0) {
                        snd_printk(KERN_ERR "Error in snd_pcm_stream_proc_init\n");
@@ -675,15 +675,18 @@ int snd_pcm_new_stream(struct snd_pcm *pcm, int stream, int substream_count)
                        pstr->substream = substream;
                else
                        prev->next = substream;
-               err = snd_pcm_substream_proc_init(substream);
-               if (err < 0) {
-                       snd_printk(KERN_ERR "Error in snd_pcm_stream_proc_init\n");
-                       if (prev == NULL)
-                               pstr->substream = NULL;
-                       else
-                               prev->next = NULL;
-                       kfree(substream);
-                       return err;
+
+               if (!pcm->internal) {
+                       err = snd_pcm_substream_proc_init(substream);
+                       if (err < 0) {
+                               snd_printk(KERN_ERR "Error in snd_pcm_stream_proc_init\n");
+                               if (prev == NULL)
+                                       pstr->substream = NULL;
+                               else
+                                       prev->next = NULL;
+                               kfree(substream);
+                               return err;
+                       }
                }
                substream->group = &substream->self_group;
                spin_lock_init(&substream->self_group.lock);
@@ -697,25 +700,9 @@ int snd_pcm_new_stream(struct snd_pcm *pcm, int stream, int substream_count)
 
 EXPORT_SYMBOL(snd_pcm_new_stream);
 
-/**
- * snd_pcm_new - create a new PCM instance
- * @card: the card instance
- * @id: the id string
- * @device: the device index (zero based)
- * @playback_count: the number of substreams for playback
- * @capture_count: the number of substreams for capture
- * @rpcm: the pointer to store the new pcm instance
- *
- * Creates a new PCM instance.
- *
- * The pcm operators have to be set afterwards to the new instance
- * via snd_pcm_set_ops().
- *
- * Returns zero if successful, or a negative error code on failure.
- */
-int snd_pcm_new(struct snd_card *card, const char *id, int device,
-               int playback_count, int capture_count,
-               struct snd_pcm ** rpcm)
+static int _snd_pcm_new(struct snd_card *card, const char *id, int device,
+               int playback_count, int capture_count, bool internal,
+               struct snd_pcm **rpcm)
 {
        struct snd_pcm *pcm;
        int err;
@@ -736,6 +723,7 @@ int snd_pcm_new(struct snd_card *card, const char *id, int device,
        }
        pcm->card = card;
        pcm->device = device;
+       pcm->internal = internal;
        if (id)
                strlcpy(pcm->id, id, sizeof(pcm->id));
        if ((err = snd_pcm_new_stream(pcm, SNDRV_PCM_STREAM_PLAYBACK, playback_count)) < 0) {
@@ -757,8 +745,59 @@ int snd_pcm_new(struct snd_card *card, const char *id, int device,
        return 0;
 }
 
+/**
+ * snd_pcm_new - create a new PCM instance
+ * @card: the card instance
+ * @id: the id string
+ * @device: the device index (zero based)
+ * @playback_count: the number of substreams for playback
+ * @capture_count: the number of substreams for capture
+ * @rpcm: the pointer to store the new pcm instance
+ *
+ * Creates a new PCM instance.
+ *
+ * The pcm operators have to be set afterwards to the new instance
+ * via snd_pcm_set_ops().
+ *
+ * Returns zero if successful, or a negative error code on failure.
+ */
+int snd_pcm_new(struct snd_card *card, const char *id, int device,
+               int playback_count, int capture_count, struct snd_pcm **rpcm)
+{
+       return _snd_pcm_new(card, id, device, playback_count, capture_count,
+                       false, rpcm);
+}
 EXPORT_SYMBOL(snd_pcm_new);
 
+/**
+ * snd_pcm_new_internal - create a new internal PCM instance
+ * @card: the card instance
+ * @id: the id string
+ * @device: the device index (zero based - shared with normal PCMs)
+ * @playback_count: the number of substreams for playback
+ * @capture_count: the number of substreams for capture
+ * @rpcm: the pointer to store the new pcm instance
+ *
+ * Creates a new internal PCM instance with no userspace device or procfs
+ * entries. This is used by ASoC Back End PCMs in order to create a PCM that
+ * will only be used internally by kernel drivers. i.e. it cannot be opened
+ * by userspace. It provides existing ASoC components drivers with a substream
+ * and access to any private data.
+ *
+ * The pcm operators have to be set afterwards to the new instance
+ * via snd_pcm_set_ops().
+ *
+ * Returns zero if successful, or a negative error code on failure.
+ */
+int snd_pcm_new_internal(struct snd_card *card, const char *id, int device,
+       int playback_count, int capture_count,
+       struct snd_pcm **rpcm)
+{
+       return _snd_pcm_new(card, id, device, playback_count, capture_count,
+                       true, rpcm);
+}
+EXPORT_SYMBOL(snd_pcm_new_internal);
+
 static void snd_pcm_free_stream(struct snd_pcm_str * pstr)
 {
        struct snd_pcm_substream *substream, *substream_next;
@@ -995,7 +1034,7 @@ static int snd_pcm_dev_register(struct snd_device *device)
        }
        for (cidx = 0; cidx < 2; cidx++) {
                int devtype = -1;
-               if (pcm->streams[cidx].substream == NULL)
+               if (pcm->streams[cidx].substream == NULL || pcm->internal)
                        continue;
                switch (cidx) {
                case SNDRV_PCM_STREAM_PLAYBACK: