aboutsummaryrefslogtreecommitdiffstats
path: root/sound/core/pcm.c
diff options
context:
space:
mode:
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)
49 struct snd_pcm *pcm; 49 struct snd_pcm *pcm;
50 50
51 list_for_each_entry(pcm, &snd_pcm_devices, list) { 51 list_for_each_entry(pcm, &snd_pcm_devices, list) {
52 if (pcm->internal)
53 continue;
54 if (pcm->card == card && pcm->device == device) 52 if (pcm->card == card && pcm->device == device)
55 return pcm; 53 return pcm;
56 } 54 }
@@ -62,8 +60,6 @@ static int snd_pcm_next(struct snd_card *card, int device)
62 struct snd_pcm *pcm; 60 struct snd_pcm *pcm;
63 61
64 list_for_each_entry(pcm, &snd_pcm_devices, list) { 62 list_for_each_entry(pcm, &snd_pcm_devices, list) {
65 if (pcm->internal)
66 continue;
67 if (pcm->card == card && pcm->device > device) 63 if (pcm->card == card && pcm->device > device)
68 return pcm->device; 64 return pcm->device;
69 else if (pcm->card->number > card->number) 65 else if (pcm->card->number > card->number)
@@ -76,6 +72,9 @@ static int snd_pcm_add(struct snd_pcm *newpcm)
76{ 72{
77 struct snd_pcm *pcm; 73 struct snd_pcm *pcm;
78 74
75 if (newpcm->internal)
76 return 0;
77
79 list_for_each_entry(pcm, &snd_pcm_devices, list) { 78 list_for_each_entry(pcm, &snd_pcm_devices, list) {
80 if (pcm->card == newpcm->card && pcm->device == newpcm->device) 79 if (pcm->card == newpcm->card && pcm->device == newpcm->device)
81 return -EBUSY; 80 return -EBUSY;
@@ -344,11 +343,8 @@ static void snd_pcm_proc_info_read(struct snd_pcm_substream *substream,
344 return; 343 return;
345 344
346 info = kmalloc(sizeof(*info), GFP_KERNEL); 345 info = kmalloc(sizeof(*info), GFP_KERNEL);
347 if (! info) { 346 if (!info)
348 pcm_dbg(substream->pcm,
349 "snd_pcm_proc_info_read: cannot malloc\n");
350 return; 347 return;
351 }
352 348
353 err = snd_pcm_info(substream, info); 349 err = snd_pcm_info(substream, info);
354 if (err < 0) { 350 if (err < 0) {
@@ -718,10 +714,8 @@ int snd_pcm_new_stream(struct snd_pcm *pcm, int stream, int substream_count)
718 prev = NULL; 714 prev = NULL;
719 for (idx = 0, prev = NULL; idx < substream_count; idx++) { 715 for (idx = 0, prev = NULL; idx < substream_count; idx++) {
720 substream = kzalloc(sizeof(*substream), GFP_KERNEL); 716 substream = kzalloc(sizeof(*substream), GFP_KERNEL);
721 if (substream == NULL) { 717 if (!substream)
722 pcm_err(pcm, "Cannot allocate PCM substream\n");
723 return -ENOMEM; 718 return -ENOMEM;
724 }
725 substream->pcm = pcm; 719 substream->pcm = pcm;
726 substream->pstr = pstr; 720 substream->pstr = pstr;
727 substream->number = idx; 721 substream->number = idx;
@@ -775,13 +769,14 @@ static int _snd_pcm_new(struct snd_card *card, const char *id, int device,
775 if (rpcm) 769 if (rpcm)
776 *rpcm = NULL; 770 *rpcm = NULL;
777 pcm = kzalloc(sizeof(*pcm), GFP_KERNEL); 771 pcm = kzalloc(sizeof(*pcm), GFP_KERNEL);
778 if (pcm == NULL) { 772 if (!pcm)
779 dev_err(card->dev, "Cannot allocate PCM\n");
780 return -ENOMEM; 773 return -ENOMEM;
781 }
782 pcm->card = card; 774 pcm->card = card;
783 pcm->device = device; 775 pcm->device = device;
784 pcm->internal = internal; 776 pcm->internal = internal;
777 mutex_init(&pcm->open_mutex);
778 init_waitqueue_head(&pcm->open_wait);
779 INIT_LIST_HEAD(&pcm->list);
785 if (id) 780 if (id)
786 strlcpy(pcm->id, id, sizeof(pcm->id)); 781 strlcpy(pcm->id, id, sizeof(pcm->id));
787 if ((err = snd_pcm_new_stream(pcm, SNDRV_PCM_STREAM_PLAYBACK, playback_count)) < 0) { 782 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,
792 snd_pcm_free(pcm); 787 snd_pcm_free(pcm);
793 return err; 788 return err;
794 } 789 }
795 mutex_init(&pcm->open_mutex);
796 init_waitqueue_head(&pcm->open_wait);
797 if ((err = snd_device_new(card, SNDRV_DEV_PCM, pcm, &ops)) < 0) { 790 if ((err = snd_device_new(card, SNDRV_DEV_PCM, pcm, &ops)) < 0) {
798 snd_pcm_free(pcm); 791 snd_pcm_free(pcm);
799 return err; 792 return err;
@@ -888,8 +881,9 @@ static int snd_pcm_free(struct snd_pcm *pcm)
888 881
889 if (!pcm) 882 if (!pcm)
890 return 0; 883 return 0;
891 list_for_each_entry(notify, &snd_pcm_notify_list, list) { 884 if (!pcm->internal) {
892 notify->n_unregister(pcm); 885 list_for_each_entry(notify, &snd_pcm_notify_list, list)
886 notify->n_unregister(pcm);
893 } 887 }
894 if (pcm->private_free) 888 if (pcm->private_free)
895 pcm->private_free(pcm); 889 pcm->private_free(pcm);
@@ -919,6 +913,9 @@ int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream,
919 913
920 if (snd_BUG_ON(!pcm || !rsubstream)) 914 if (snd_BUG_ON(!pcm || !rsubstream))
921 return -ENXIO; 915 return -ENXIO;
916 if (snd_BUG_ON(stream != SNDRV_PCM_STREAM_PLAYBACK &&
917 stream != SNDRV_PCM_STREAM_CAPTURE))
918 return -EINVAL;
922 *rsubstream = NULL; 919 *rsubstream = NULL;
923 pstr = &pcm->streams[stream]; 920 pstr = &pcm->streams[stream];
924 if (pstr->substream == NULL || pstr->substream_count == 0) 921 if (pstr->substream == NULL || pstr->substream_count == 0)
@@ -927,25 +924,14 @@ int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream,
927 card = pcm->card; 924 card = pcm->card;
928 prefer_subdevice = snd_ctl_get_preferred_subdevice(card, SND_CTL_SUBDEV_PCM); 925 prefer_subdevice = snd_ctl_get_preferred_subdevice(card, SND_CTL_SUBDEV_PCM);
929 926
930 switch (stream) { 927 if (pcm->info_flags & SNDRV_PCM_INFO_HALF_DUPLEX) {
931 case SNDRV_PCM_STREAM_PLAYBACK: 928 int opposite = !stream;
932 if (pcm->info_flags & SNDRV_PCM_INFO_HALF_DUPLEX) { 929
933 for (substream = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream; substream; substream = substream->next) { 930 for (substream = pcm->streams[opposite].substream; substream;
934 if (SUBSTREAM_BUSY(substream)) 931 substream = substream->next) {
935 return -EAGAIN; 932 if (SUBSTREAM_BUSY(substream))
936 } 933 return -EAGAIN;
937 }
938 break;
939 case SNDRV_PCM_STREAM_CAPTURE:
940 if (pcm->info_flags & SNDRV_PCM_INFO_HALF_DUPLEX) {
941 for (substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; substream; substream = substream->next) {
942 if (SUBSTREAM_BUSY(substream))
943 return -EAGAIN;
944 }
945 } 934 }
946 break;
947 default:
948 return -EINVAL;
949 } 935 }
950 936
951 if (file->f_flags & O_APPEND) { 937 if (file->f_flags & O_APPEND) {
@@ -968,15 +954,12 @@ int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream,
968 return 0; 954 return 0;
969 } 955 }
970 956
971 if (prefer_subdevice >= 0) { 957 for (substream = pstr->substream; substream; substream = substream->next) {
972 for (substream = pstr->substream; substream; substream = substream->next) 958 if (!SUBSTREAM_BUSY(substream) &&
973 if (!SUBSTREAM_BUSY(substream) && substream->number == prefer_subdevice) 959 (prefer_subdevice == -1 ||
974 goto __ok; 960 substream->number == prefer_subdevice))
975 }
976 for (substream = pstr->substream; substream; substream = substream->next)
977 if (!SUBSTREAM_BUSY(substream))
978 break; 961 break;
979 __ok: 962 }
980 if (substream == NULL) 963 if (substream == NULL)
981 return -EAGAIN; 964 return -EAGAIN;
982 965
@@ -1086,15 +1069,16 @@ static int snd_pcm_dev_register(struct snd_device *device)
1086 if (snd_BUG_ON(!device || !device->device_data)) 1069 if (snd_BUG_ON(!device || !device->device_data))
1087 return -ENXIO; 1070 return -ENXIO;
1088 pcm = device->device_data; 1071 pcm = device->device_data;
1072 if (pcm->internal)
1073 return 0;
1074
1089 mutex_lock(&register_mutex); 1075 mutex_lock(&register_mutex);
1090 err = snd_pcm_add(pcm); 1076 err = snd_pcm_add(pcm);
1091 if (err) { 1077 if (err)
1092 mutex_unlock(&register_mutex); 1078 goto unlock;
1093 return err;
1094 }
1095 for (cidx = 0; cidx < 2; cidx++) { 1079 for (cidx = 0; cidx < 2; cidx++) {
1096 int devtype = -1; 1080 int devtype = -1;
1097 if (pcm->streams[cidx].substream == NULL || pcm->internal) 1081 if (pcm->streams[cidx].substream == NULL)
1098 continue; 1082 continue;
1099 switch (cidx) { 1083 switch (cidx) {
1100 case SNDRV_PCM_STREAM_PLAYBACK: 1084 case SNDRV_PCM_STREAM_PLAYBACK:
@@ -1109,9 +1093,8 @@ static int snd_pcm_dev_register(struct snd_device *device)
1109 &snd_pcm_f_ops[cidx], pcm, 1093 &snd_pcm_f_ops[cidx], pcm,
1110 &pcm->streams[cidx].dev); 1094 &pcm->streams[cidx].dev);
1111 if (err < 0) { 1095 if (err < 0) {
1112 list_del(&pcm->list); 1096 list_del_init(&pcm->list);
1113 mutex_unlock(&register_mutex); 1097 goto unlock;
1114 return err;
1115 } 1098 }
1116 1099
1117 for (substream = pcm->streams[cidx].substream; substream; substream = substream->next) 1100 for (substream = pcm->streams[cidx].substream; substream; substream = substream->next)
@@ -1121,8 +1104,9 @@ static int snd_pcm_dev_register(struct snd_device *device)
1121 list_for_each_entry(notify, &snd_pcm_notify_list, list) 1104 list_for_each_entry(notify, &snd_pcm_notify_list, list)
1122 notify->n_register(pcm); 1105 notify->n_register(pcm);
1123 1106
1107 unlock:
1124 mutex_unlock(&register_mutex); 1108 mutex_unlock(&register_mutex);
1125 return 0; 1109 return err;
1126} 1110}
1127 1111
1128static int snd_pcm_dev_disconnect(struct snd_device *device) 1112static int snd_pcm_dev_disconnect(struct snd_device *device)
@@ -1133,13 +1117,10 @@ static int snd_pcm_dev_disconnect(struct snd_device *device)
1133 int cidx; 1117 int cidx;
1134 1118
1135 mutex_lock(&register_mutex); 1119 mutex_lock(&register_mutex);
1136 if (list_empty(&pcm->list))
1137 goto unlock;
1138
1139 mutex_lock(&pcm->open_mutex); 1120 mutex_lock(&pcm->open_mutex);
1140 wake_up(&pcm->open_wait); 1121 wake_up(&pcm->open_wait);
1141 list_del_init(&pcm->list); 1122 list_del_init(&pcm->list);
1142 for (cidx = 0; cidx < 2; cidx++) 1123 for (cidx = 0; cidx < 2; cidx++) {
1143 for (substream = pcm->streams[cidx].substream; substream; substream = substream->next) { 1124 for (substream = pcm->streams[cidx].substream; substream; substream = substream->next) {
1144 snd_pcm_stream_lock_irq(substream); 1125 snd_pcm_stream_lock_irq(substream);
1145 if (substream->runtime) { 1126 if (substream->runtime) {
@@ -1149,18 +1130,20 @@ static int snd_pcm_dev_disconnect(struct snd_device *device)
1149 } 1130 }
1150 snd_pcm_stream_unlock_irq(substream); 1131 snd_pcm_stream_unlock_irq(substream);
1151 } 1132 }
1152 list_for_each_entry(notify, &snd_pcm_notify_list, list) { 1133 }
1153 notify->n_disconnect(pcm); 1134 if (!pcm->internal) {
1135 list_for_each_entry(notify, &snd_pcm_notify_list, list)
1136 notify->n_disconnect(pcm);
1154 } 1137 }
1155 for (cidx = 0; cidx < 2; cidx++) { 1138 for (cidx = 0; cidx < 2; cidx++) {
1156 snd_unregister_device(&pcm->streams[cidx].dev); 1139 if (!pcm->internal)
1140 snd_unregister_device(&pcm->streams[cidx].dev);
1157 if (pcm->streams[cidx].chmap_kctl) { 1141 if (pcm->streams[cidx].chmap_kctl) {
1158 snd_ctl_remove(pcm->card, pcm->streams[cidx].chmap_kctl); 1142 snd_ctl_remove(pcm->card, pcm->streams[cidx].chmap_kctl);
1159 pcm->streams[cidx].chmap_kctl = NULL; 1143 pcm->streams[cidx].chmap_kctl = NULL;
1160 } 1144 }
1161 } 1145 }
1162 mutex_unlock(&pcm->open_mutex); 1146 mutex_unlock(&pcm->open_mutex);
1163 unlock:
1164 mutex_unlock(&register_mutex); 1147 mutex_unlock(&register_mutex);
1165 return 0; 1148 return 0;
1166} 1149}