diff options
Diffstat (limited to 'sound/core/pcm.c')
-rw-r--r-- | sound/core/pcm.c | 100 |
1 files changed, 70 insertions, 30 deletions
diff --git a/sound/core/pcm.c b/sound/core/pcm.c index 8928ca871c22..1a3070b4e5b5 100644 --- a/sound/core/pcm.c +++ b/sound/core/pcm.c @@ -24,6 +24,7 @@ #include <linux/module.h> #include <linux/time.h> #include <linux/mutex.h> +#include <linux/device.h> #include <sound/core.h> #include <sound/minors.h> #include <sound/pcm.h> @@ -650,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"); @@ -674,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); @@ -696,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; @@ -735,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) { @@ -756,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; @@ -994,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: |