diff options
author | Takashi Iwai <tiwai@suse.de> | 2015-03-23 08:14:02 -0400 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2015-03-23 08:14:02 -0400 |
commit | 3372dbdd8ca11f51be8c6a30b2bc79eb04c4a902 (patch) | |
tree | d4499bf5a5665b4820ffaf96bce55bf6b895195e /sound/core/pcm.c | |
parent | bc465aa9d045feb0e13b4a8f32cc33c1943f62d6 (diff) | |
parent | 967b1307b69b8ada8b331e01046ad1ef83742e99 (diff) |
Merge branch 'for-next' into topic/hda-core
Diffstat (limited to 'sound/core/pcm.c')
-rw-r--r-- | sound/core/pcm.c | 105 |
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(®ister_mutex); | 1075 | mutex_lock(®ister_mutex); |
1090 | err = snd_pcm_add(pcm); | 1076 | err = snd_pcm_add(pcm); |
1091 | if (err) { | 1077 | if (err) |
1092 | mutex_unlock(®ister_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(®ister_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(®ister_mutex); | 1108 | mutex_unlock(®ister_mutex); |
1125 | return 0; | 1109 | return err; |
1126 | } | 1110 | } |
1127 | 1111 | ||
1128 | static int snd_pcm_dev_disconnect(struct snd_device *device) | 1112 | static 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(®ister_mutex); | 1119 | mutex_lock(®ister_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(®ister_mutex); | 1147 | mutex_unlock(®ister_mutex); |
1165 | return 0; | 1148 | return 0; |
1166 | } | 1149 | } |