aboutsummaryrefslogtreecommitdiffstats
path: root/sound/core
diff options
context:
space:
mode:
authorLiam Girdwood <lrg@ti.com>2012-02-08 15:33:31 -0500
committerTakashi Iwai <tiwai@suse.de>2012-02-09 03:20:22 -0500
commit945e5038455fef18e73914c149717878d78cb4c0 (patch)
treed3ea8e7c0bd087afda16ed6b7fa145eb8c00bb68 /sound/core
parent62aa2b537c6f5957afd98e29f96897419ed5ebab (diff)
ALSA: PCM - Add PCM creation API for internal PCMs.
The new ASoC dynamic PCM core needs to create PCMs and substreams that are for use by internal ASoC drivers only and not visible to userspace for direct IO. These new PCMs are similar to regular PCMs expect they have no device nodes or procfs entries. The ASoC component drivers use them in exactly the same way as regular PCMs for PCM and DAI operations. The intention is that a dynamic PCM based driver will register both regular PCMs and internal PCMs. The regular PCMs will be used for all IO with userspace however the internal PCMs will be used by the driver to route digital audio through numerous back end DAI links (with potentially a DSP providing different hw_params, DAI formats based on the regular front end PCM params) to devices like CODECs, MODEMs, Bluetooth, FM, DMICs, etc This patch adds a new snd_pcm_new_internal() API call to create the internal PCM without device nodes or procfs. It also adds adds a new internal flag to snd_pcm. [fixed minor coding-style issues by tiwai] Signed-off-by: Liam Girdwood <lrg@ti.com> Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/core')
-rw-r--r--sound/core/pcm.c99
1 files changed, 69 insertions, 30 deletions
diff --git a/sound/core/pcm.c b/sound/core/pcm.c
index 8928ca871c2..6e4bfcc1425 100644
--- a/sound/core/pcm.c
+++ b/sound/core/pcm.c
@@ -650,7 +650,7 @@ int snd_pcm_new_stream(struct snd_pcm *pcm, int stream, int substream_count)
650 pstr->stream = stream; 650 pstr->stream = stream;
651 pstr->pcm = pcm; 651 pstr->pcm = pcm;
652 pstr->substream_count = substream_count; 652 pstr->substream_count = substream_count;
653 if (substream_count > 0) { 653 if (substream_count > 0 && !pcm->internal) {
654 err = snd_pcm_stream_proc_init(pstr); 654 err = snd_pcm_stream_proc_init(pstr);
655 if (err < 0) { 655 if (err < 0) {
656 snd_printk(KERN_ERR "Error in snd_pcm_stream_proc_init\n"); 656 snd_printk(KERN_ERR "Error in snd_pcm_stream_proc_init\n");
@@ -674,15 +674,18 @@ int snd_pcm_new_stream(struct snd_pcm *pcm, int stream, int substream_count)
674 pstr->substream = substream; 674 pstr->substream = substream;
675 else 675 else
676 prev->next = substream; 676 prev->next = substream;
677 err = snd_pcm_substream_proc_init(substream); 677
678 if (err < 0) { 678 if (!pcm->internal) {
679 snd_printk(KERN_ERR "Error in snd_pcm_stream_proc_init\n"); 679 err = snd_pcm_substream_proc_init(substream);
680 if (prev == NULL) 680 if (err < 0) {
681 pstr->substream = NULL; 681 snd_printk(KERN_ERR "Error in snd_pcm_stream_proc_init\n");
682 else 682 if (prev == NULL)
683 prev->next = NULL; 683 pstr->substream = NULL;
684 kfree(substream); 684 else
685 return err; 685 prev->next = NULL;
686 kfree(substream);
687 return err;
688 }
686 } 689 }
687 substream->group = &substream->self_group; 690 substream->group = &substream->self_group;
688 spin_lock_init(&substream->self_group.lock); 691 spin_lock_init(&substream->self_group.lock);
@@ -696,25 +699,9 @@ int snd_pcm_new_stream(struct snd_pcm *pcm, int stream, int substream_count)
696 699
697EXPORT_SYMBOL(snd_pcm_new_stream); 700EXPORT_SYMBOL(snd_pcm_new_stream);
698 701
699/** 702static int _snd_pcm_new(struct snd_card *card, const char *id, int device,
700 * snd_pcm_new - create a new PCM instance 703 int playback_count, int capture_count, bool internal,
701 * @card: the card instance 704 struct snd_pcm **rpcm)
702 * @id: the id string
703 * @device: the device index (zero based)
704 * @playback_count: the number of substreams for playback
705 * @capture_count: the number of substreams for capture
706 * @rpcm: the pointer to store the new pcm instance
707 *
708 * Creates a new PCM instance.
709 *
710 * The pcm operators have to be set afterwards to the new instance
711 * via snd_pcm_set_ops().
712 *
713 * Returns zero if successful, or a negative error code on failure.
714 */
715int snd_pcm_new(struct snd_card *card, const char *id, int device,
716 int playback_count, int capture_count,
717 struct snd_pcm ** rpcm)
718{ 705{
719 struct snd_pcm *pcm; 706 struct snd_pcm *pcm;
720 int err; 707 int err;
@@ -735,6 +722,7 @@ int snd_pcm_new(struct snd_card *card, const char *id, int device,
735 } 722 }
736 pcm->card = card; 723 pcm->card = card;
737 pcm->device = device; 724 pcm->device = device;
725 pcm->internal = internal;
738 if (id) 726 if (id)
739 strlcpy(pcm->id, id, sizeof(pcm->id)); 727 strlcpy(pcm->id, id, sizeof(pcm->id));
740 if ((err = snd_pcm_new_stream(pcm, SNDRV_PCM_STREAM_PLAYBACK, playback_count)) < 0) { 728 if ((err = snd_pcm_new_stream(pcm, SNDRV_PCM_STREAM_PLAYBACK, playback_count)) < 0) {
@@ -756,8 +744,59 @@ int snd_pcm_new(struct snd_card *card, const char *id, int device,
756 return 0; 744 return 0;
757} 745}
758 746
747/**
748 * snd_pcm_new - create a new PCM instance
749 * @card: the card instance
750 * @id: the id string
751 * @device: the device index (zero based)
752 * @playback_count: the number of substreams for playback
753 * @capture_count: the number of substreams for capture
754 * @rpcm: the pointer to store the new pcm instance
755 *
756 * Creates a new PCM instance.
757 *
758 * The pcm operators have to be set afterwards to the new instance
759 * via snd_pcm_set_ops().
760 *
761 * Returns zero if successful, or a negative error code on failure.
762 */
763int snd_pcm_new(struct snd_card *card, const char *id, int device,
764 int playback_count, int capture_count, struct snd_pcm **rpcm)
765{
766 return _snd_pcm_new(card, id, device, playback_count, capture_count,
767 false, rpcm);
768}
759EXPORT_SYMBOL(snd_pcm_new); 769EXPORT_SYMBOL(snd_pcm_new);
760 770
771/**
772 * snd_pcm_new_internal - create a new internal PCM instance
773 * @card: the card instance
774 * @id: the id string
775 * @device: the device index (zero based - shared with normal PCMs)
776 * @playback_count: the number of substreams for playback
777 * @capture_count: the number of substreams for capture
778 * @rpcm: the pointer to store the new pcm instance
779 *
780 * Creates a new internal PCM instance with no userspace device or procfs
781 * entries. This is used by ASoC Back End PCMs in order to create a PCM that
782 * will only be used internally by kernel drivers. i.e. it cannot be opened
783 * by userspace. It provides existing ASoC components drivers with a substream
784 * and access to any private data.
785 *
786 * The pcm operators have to be set afterwards to the new instance
787 * via snd_pcm_set_ops().
788 *
789 * Returns zero if successful, or a negative error code on failure.
790 */
791int snd_pcm_new_internal(struct snd_card *card, const char *id, int device,
792 int playback_count, int capture_count,
793 struct snd_pcm **rpcm)
794{
795 return _snd_pcm_new(card, id, device, playback_count, capture_count,
796 true, rpcm);
797}
798EXPORT_SYMBOL(snd_pcm_new_internal);
799
761static void snd_pcm_free_stream(struct snd_pcm_str * pstr) 800static void snd_pcm_free_stream(struct snd_pcm_str * pstr)
762{ 801{
763 struct snd_pcm_substream *substream, *substream_next; 802 struct snd_pcm_substream *substream, *substream_next;
@@ -994,7 +1033,7 @@ static int snd_pcm_dev_register(struct snd_device *device)
994 } 1033 }
995 for (cidx = 0; cidx < 2; cidx++) { 1034 for (cidx = 0; cidx < 2; cidx++) {
996 int devtype = -1; 1035 int devtype = -1;
997 if (pcm->streams[cidx].substream == NULL) 1036 if (pcm->streams[cidx].substream == NULL || pcm->internal)
998 continue; 1037 continue;
999 switch (cidx) { 1038 switch (cidx) {
1000 case SNDRV_PCM_STREAM_PLAYBACK: 1039 case SNDRV_PCM_STREAM_PLAYBACK: