diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-10-28 17:25:01 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-10-28 17:25:01 -0400 |
commit | 68d99b2c8efcb6ed3807a55569300c53b5f88be5 (patch) | |
tree | f189c8f2132d3668a2f0e503f5c3f8695b26a1c8 /sound/core | |
parent | 0e59e7e7feb5a12938fbf9135147eeda3238c6c4 (diff) | |
parent | 8128c9f21509f9a8b6da94ac432d845dda458406 (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: (549 commits)
ALSA: hda - Fix ADC input-amp handling for Cx20549 codec
ALSA: hda - Keep EAPD turned on for old Conexant chips
ALSA: hda/realtek - Fix missing volume controls with ALC260
ASoC: wm8940: Properly set codec->dapm.bias_level
ALSA: hda - Fix pin-config for ASUS W90V
ALSA: hda - Fix surround/CLFE headphone and speaker pins order
ALSA: hda - Fix typo
ALSA: Update the sound git tree URL
ALSA: HDA: Add new revision for ALC662
ASoC: max98095: Convert codec->hw_write to snd_soc_write
ASoC: keep pointer to resource so it can be freed
ASoC: sgtl5000: Fix wrong mask in some snd_soc_update_bits calls
ASoC: wm8996: Fix wrong mask for setting WM8996_AIF_CLOCKING_2
ASoC: da7210: Add support for line out and DAC
ASoC: da7210: Add support for DAPM
ALSA: hda/realtek - Fix DAC assignments of multiple speakers
ASoC: Use SGTL5000_LINREG_VDDD_MASK instead of hardcoded mask value
ASoC: Set sgtl5000->ldo in ldo_regulator_register
ASoC: wm8996: Use SND_SOC_DAPM_AIF_OUT for AIF2 Capture
ASoC: wm8994: Use SND_SOC_DAPM_AIF_OUT for AIF3 Capture
...
Diffstat (limited to 'sound/core')
-rw-r--r-- | sound/core/control.c | 84 | ||||
-rw-r--r-- | sound/core/control_compat.c | 4 | ||||
-rw-r--r-- | sound/core/jack.c | 1 | ||||
-rw-r--r-- | sound/core/oss/mixer_oss.c | 2 | ||||
-rw-r--r-- | sound/core/pcm_lib.c | 26 | ||||
-rw-r--r-- | sound/core/pcm_native.c | 19 |
6 files changed, 117 insertions, 19 deletions
diff --git a/sound/core/control.c b/sound/core/control.c index f8c5be464510..978fe1a8e9f0 100644 --- a/sound/core/control.c +++ b/sound/core/control.c | |||
@@ -989,7 +989,6 @@ struct user_element { | |||
989 | void *tlv_data; /* TLV data */ | 989 | void *tlv_data; /* TLV data */ |
990 | unsigned long tlv_data_size; /* TLV data size */ | 990 | unsigned long tlv_data_size; /* TLV data size */ |
991 | void *priv_data; /* private data (like strings for enumerated type) */ | 991 | void *priv_data; /* private data (like strings for enumerated type) */ |
992 | unsigned long priv_data_size; /* size of private data in bytes */ | ||
993 | }; | 992 | }; |
994 | 993 | ||
995 | static int snd_ctl_elem_user_info(struct snd_kcontrol *kcontrol, | 994 | static int snd_ctl_elem_user_info(struct snd_kcontrol *kcontrol, |
@@ -1001,6 +1000,28 @@ static int snd_ctl_elem_user_info(struct snd_kcontrol *kcontrol, | |||
1001 | return 0; | 1000 | return 0; |
1002 | } | 1001 | } |
1003 | 1002 | ||
1003 | static int snd_ctl_elem_user_enum_info(struct snd_kcontrol *kcontrol, | ||
1004 | struct snd_ctl_elem_info *uinfo) | ||
1005 | { | ||
1006 | struct user_element *ue = kcontrol->private_data; | ||
1007 | const char *names; | ||
1008 | unsigned int item; | ||
1009 | |||
1010 | item = uinfo->value.enumerated.item; | ||
1011 | |||
1012 | *uinfo = ue->info; | ||
1013 | |||
1014 | item = min(item, uinfo->value.enumerated.items - 1); | ||
1015 | uinfo->value.enumerated.item = item; | ||
1016 | |||
1017 | names = ue->priv_data; | ||
1018 | for (; item > 0; --item) | ||
1019 | names += strlen(names) + 1; | ||
1020 | strcpy(uinfo->value.enumerated.name, names); | ||
1021 | |||
1022 | return 0; | ||
1023 | } | ||
1024 | |||
1004 | static int snd_ctl_elem_user_get(struct snd_kcontrol *kcontrol, | 1025 | static int snd_ctl_elem_user_get(struct snd_kcontrol *kcontrol, |
1005 | struct snd_ctl_elem_value *ucontrol) | 1026 | struct snd_ctl_elem_value *ucontrol) |
1006 | { | 1027 | { |
@@ -1055,11 +1076,46 @@ static int snd_ctl_elem_user_tlv(struct snd_kcontrol *kcontrol, | |||
1055 | return change; | 1076 | return change; |
1056 | } | 1077 | } |
1057 | 1078 | ||
1079 | static int snd_ctl_elem_init_enum_names(struct user_element *ue) | ||
1080 | { | ||
1081 | char *names, *p; | ||
1082 | size_t buf_len, name_len; | ||
1083 | unsigned int i; | ||
1084 | |||
1085 | if (ue->info.value.enumerated.names_length > 64 * 1024) | ||
1086 | return -EINVAL; | ||
1087 | |||
1088 | names = memdup_user( | ||
1089 | (const void __user *)ue->info.value.enumerated.names_ptr, | ||
1090 | ue->info.value.enumerated.names_length); | ||
1091 | if (IS_ERR(names)) | ||
1092 | return PTR_ERR(names); | ||
1093 | |||
1094 | /* check that there are enough valid names */ | ||
1095 | buf_len = ue->info.value.enumerated.names_length; | ||
1096 | p = names; | ||
1097 | for (i = 0; i < ue->info.value.enumerated.items; ++i) { | ||
1098 | name_len = strnlen(p, buf_len); | ||
1099 | if (name_len == 0 || name_len >= 64 || name_len == buf_len) { | ||
1100 | kfree(names); | ||
1101 | return -EINVAL; | ||
1102 | } | ||
1103 | p += name_len + 1; | ||
1104 | buf_len -= name_len + 1; | ||
1105 | } | ||
1106 | |||
1107 | ue->priv_data = names; | ||
1108 | ue->info.value.enumerated.names_ptr = 0; | ||
1109 | |||
1110 | return 0; | ||
1111 | } | ||
1112 | |||
1058 | static void snd_ctl_elem_user_free(struct snd_kcontrol *kcontrol) | 1113 | static void snd_ctl_elem_user_free(struct snd_kcontrol *kcontrol) |
1059 | { | 1114 | { |
1060 | struct user_element *ue = kcontrol->private_data; | 1115 | struct user_element *ue = kcontrol->private_data; |
1061 | if (ue->tlv_data) | 1116 | |
1062 | kfree(ue->tlv_data); | 1117 | kfree(ue->tlv_data); |
1118 | kfree(ue->priv_data); | ||
1063 | kfree(ue); | 1119 | kfree(ue); |
1064 | } | 1120 | } |
1065 | 1121 | ||
@@ -1072,8 +1128,8 @@ static int snd_ctl_elem_add(struct snd_ctl_file *file, | |||
1072 | long private_size; | 1128 | long private_size; |
1073 | struct user_element *ue; | 1129 | struct user_element *ue; |
1074 | int idx, err; | 1130 | int idx, err; |
1075 | 1131 | ||
1076 | if (card->user_ctl_count >= MAX_USER_CONTROLS) | 1132 | if (!replace && card->user_ctl_count >= MAX_USER_CONTROLS) |
1077 | return -ENOMEM; | 1133 | return -ENOMEM; |
1078 | if (info->count < 1) | 1134 | if (info->count < 1) |
1079 | return -EINVAL; | 1135 | return -EINVAL; |
@@ -1101,7 +1157,10 @@ static int snd_ctl_elem_add(struct snd_ctl_file *file, | |||
1101 | memcpy(&kctl.id, &info->id, sizeof(info->id)); | 1157 | memcpy(&kctl.id, &info->id, sizeof(info->id)); |
1102 | kctl.count = info->owner ? info->owner : 1; | 1158 | kctl.count = info->owner ? info->owner : 1; |
1103 | access |= SNDRV_CTL_ELEM_ACCESS_USER; | 1159 | access |= SNDRV_CTL_ELEM_ACCESS_USER; |
1104 | kctl.info = snd_ctl_elem_user_info; | 1160 | if (info->type == SNDRV_CTL_ELEM_TYPE_ENUMERATED) |
1161 | kctl.info = snd_ctl_elem_user_enum_info; | ||
1162 | else | ||
1163 | kctl.info = snd_ctl_elem_user_info; | ||
1105 | if (access & SNDRV_CTL_ELEM_ACCESS_READ) | 1164 | if (access & SNDRV_CTL_ELEM_ACCESS_READ) |
1106 | kctl.get = snd_ctl_elem_user_get; | 1165 | kctl.get = snd_ctl_elem_user_get; |
1107 | if (access & SNDRV_CTL_ELEM_ACCESS_WRITE) | 1166 | if (access & SNDRV_CTL_ELEM_ACCESS_WRITE) |
@@ -1122,6 +1181,11 @@ static int snd_ctl_elem_add(struct snd_ctl_file *file, | |||
1122 | if (info->count > 64) | 1181 | if (info->count > 64) |
1123 | return -EINVAL; | 1182 | return -EINVAL; |
1124 | break; | 1183 | break; |
1184 | case SNDRV_CTL_ELEM_TYPE_ENUMERATED: | ||
1185 | private_size = sizeof(unsigned int); | ||
1186 | if (info->count > 128 || info->value.enumerated.items == 0) | ||
1187 | return -EINVAL; | ||
1188 | break; | ||
1125 | case SNDRV_CTL_ELEM_TYPE_BYTES: | 1189 | case SNDRV_CTL_ELEM_TYPE_BYTES: |
1126 | private_size = sizeof(unsigned char); | 1190 | private_size = sizeof(unsigned char); |
1127 | if (info->count > 512) | 1191 | if (info->count > 512) |
@@ -1143,9 +1207,17 @@ static int snd_ctl_elem_add(struct snd_ctl_file *file, | |||
1143 | ue->info.access = 0; | 1207 | ue->info.access = 0; |
1144 | ue->elem_data = (char *)ue + sizeof(*ue); | 1208 | ue->elem_data = (char *)ue + sizeof(*ue); |
1145 | ue->elem_data_size = private_size; | 1209 | ue->elem_data_size = private_size; |
1210 | if (ue->info.type == SNDRV_CTL_ELEM_TYPE_ENUMERATED) { | ||
1211 | err = snd_ctl_elem_init_enum_names(ue); | ||
1212 | if (err < 0) { | ||
1213 | kfree(ue); | ||
1214 | return err; | ||
1215 | } | ||
1216 | } | ||
1146 | kctl.private_free = snd_ctl_elem_user_free; | 1217 | kctl.private_free = snd_ctl_elem_user_free; |
1147 | _kctl = snd_ctl_new(&kctl, access); | 1218 | _kctl = snd_ctl_new(&kctl, access); |
1148 | if (_kctl == NULL) { | 1219 | if (_kctl == NULL) { |
1220 | kfree(ue->priv_data); | ||
1149 | kfree(ue); | 1221 | kfree(ue); |
1150 | return -ENOMEM; | 1222 | return -ENOMEM; |
1151 | } | 1223 | } |
diff --git a/sound/core/control_compat.c b/sound/core/control_compat.c index 426874429a5e..2bb95a7a8809 100644 --- a/sound/core/control_compat.c +++ b/sound/core/control_compat.c | |||
@@ -83,6 +83,8 @@ struct snd_ctl_elem_info32 { | |||
83 | u32 items; | 83 | u32 items; |
84 | u32 item; | 84 | u32 item; |
85 | char name[64]; | 85 | char name[64]; |
86 | u64 names_ptr; | ||
87 | u32 names_length; | ||
86 | } enumerated; | 88 | } enumerated; |
87 | unsigned char reserved[128]; | 89 | unsigned char reserved[128]; |
88 | } value; | 90 | } value; |
@@ -372,6 +374,8 @@ static int snd_ctl_elem_add_compat(struct snd_ctl_file *file, | |||
372 | &data32->value.enumerated, | 374 | &data32->value.enumerated, |
373 | sizeof(data->value.enumerated))) | 375 | sizeof(data->value.enumerated))) |
374 | goto error; | 376 | goto error; |
377 | data->value.enumerated.names_ptr = | ||
378 | (uintptr_t)compat_ptr(data->value.enumerated.names_ptr); | ||
375 | break; | 379 | break; |
376 | default: | 380 | default: |
377 | break; | 381 | break; |
diff --git a/sound/core/jack.c b/sound/core/jack.c index 53b53e97c896..240a3e13470d 100644 --- a/sound/core/jack.c +++ b/sound/core/jack.c | |||
@@ -30,6 +30,7 @@ static int jack_switch_types[] = { | |||
30 | SW_LINEOUT_INSERT, | 30 | SW_LINEOUT_INSERT, |
31 | SW_JACK_PHYSICAL_INSERT, | 31 | SW_JACK_PHYSICAL_INSERT, |
32 | SW_VIDEOOUT_INSERT, | 32 | SW_VIDEOOUT_INSERT, |
33 | SW_LINEIN_INSERT, | ||
33 | }; | 34 | }; |
34 | 35 | ||
35 | static int snd_jack_dev_free(struct snd_device *device) | 36 | static int snd_jack_dev_free(struct snd_device *device) |
diff --git a/sound/core/oss/mixer_oss.c b/sound/core/oss/mixer_oss.c index d8359cfeca15..1b5e0c49a0ad 100644 --- a/sound/core/oss/mixer_oss.c +++ b/sound/core/oss/mixer_oss.c | |||
@@ -499,7 +499,7 @@ static struct snd_kcontrol *snd_mixer_oss_test_id(struct snd_mixer_oss *mixer, c | |||
499 | 499 | ||
500 | memset(&id, 0, sizeof(id)); | 500 | memset(&id, 0, sizeof(id)); |
501 | id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; | 501 | id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; |
502 | strcpy(id.name, name); | 502 | strlcpy(id.name, name, sizeof(id.name)); |
503 | id.index = index; | 503 | id.index = index; |
504 | return snd_ctl_find_id(card, &id); | 504 | return snd_ctl_find_id(card, &id); |
505 | } | 505 | } |
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c index 62e90b862a0d..95d1e789715f 100644 --- a/sound/core/pcm_lib.c +++ b/sound/core/pcm_lib.c | |||
@@ -1399,6 +1399,32 @@ int snd_pcm_hw_constraint_pow2(struct snd_pcm_runtime *runtime, | |||
1399 | 1399 | ||
1400 | EXPORT_SYMBOL(snd_pcm_hw_constraint_pow2); | 1400 | EXPORT_SYMBOL(snd_pcm_hw_constraint_pow2); |
1401 | 1401 | ||
1402 | static int snd_pcm_hw_rule_noresample_func(struct snd_pcm_hw_params *params, | ||
1403 | struct snd_pcm_hw_rule *rule) | ||
1404 | { | ||
1405 | unsigned int base_rate = (unsigned int)(uintptr_t)rule->private; | ||
1406 | struct snd_interval *rate; | ||
1407 | |||
1408 | rate = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); | ||
1409 | return snd_interval_list(rate, 1, &base_rate, 0); | ||
1410 | } | ||
1411 | |||
1412 | /** | ||
1413 | * snd_pcm_hw_rule_noresample - add a rule to allow disabling hw resampling | ||
1414 | * @runtime: PCM runtime instance | ||
1415 | * @base_rate: the rate at which the hardware does not resample | ||
1416 | */ | ||
1417 | int snd_pcm_hw_rule_noresample(struct snd_pcm_runtime *runtime, | ||
1418 | unsigned int base_rate) | ||
1419 | { | ||
1420 | return snd_pcm_hw_rule_add(runtime, SNDRV_PCM_HW_PARAMS_NORESAMPLE, | ||
1421 | SNDRV_PCM_HW_PARAM_RATE, | ||
1422 | snd_pcm_hw_rule_noresample_func, | ||
1423 | (void *)(uintptr_t)base_rate, | ||
1424 | SNDRV_PCM_HW_PARAM_RATE, -1); | ||
1425 | } | ||
1426 | EXPORT_SYMBOL(snd_pcm_hw_rule_noresample); | ||
1427 | |||
1402 | static void _snd_pcm_hw_param_any(struct snd_pcm_hw_params *params, | 1428 | static void _snd_pcm_hw_param_any(struct snd_pcm_hw_params *params, |
1403 | snd_pcm_hw_param_t var) | 1429 | snd_pcm_hw_param_t var) |
1404 | { | 1430 | { |
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index c74e228731ed..d7d2179c0363 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c | |||
@@ -2058,16 +2058,12 @@ EXPORT_SYMBOL(snd_pcm_open_substream); | |||
2058 | 2058 | ||
2059 | static int snd_pcm_open_file(struct file *file, | 2059 | static int snd_pcm_open_file(struct file *file, |
2060 | struct snd_pcm *pcm, | 2060 | struct snd_pcm *pcm, |
2061 | int stream, | 2061 | int stream) |
2062 | struct snd_pcm_file **rpcm_file) | ||
2063 | { | 2062 | { |
2064 | struct snd_pcm_file *pcm_file; | 2063 | struct snd_pcm_file *pcm_file; |
2065 | struct snd_pcm_substream *substream; | 2064 | struct snd_pcm_substream *substream; |
2066 | int err; | 2065 | int err; |
2067 | 2066 | ||
2068 | if (rpcm_file) | ||
2069 | *rpcm_file = NULL; | ||
2070 | |||
2071 | err = snd_pcm_open_substream(pcm, stream, file, &substream); | 2067 | err = snd_pcm_open_substream(pcm, stream, file, &substream); |
2072 | if (err < 0) | 2068 | if (err < 0) |
2073 | return err; | 2069 | return err; |
@@ -2083,8 +2079,7 @@ static int snd_pcm_open_file(struct file *file, | |||
2083 | substream->pcm_release = pcm_release_private; | 2079 | substream->pcm_release = pcm_release_private; |
2084 | } | 2080 | } |
2085 | file->private_data = pcm_file; | 2081 | file->private_data = pcm_file; |
2086 | if (rpcm_file) | 2082 | |
2087 | *rpcm_file = pcm_file; | ||
2088 | return 0; | 2083 | return 0; |
2089 | } | 2084 | } |
2090 | 2085 | ||
@@ -2113,7 +2108,6 @@ static int snd_pcm_capture_open(struct inode *inode, struct file *file) | |||
2113 | static int snd_pcm_open(struct file *file, struct snd_pcm *pcm, int stream) | 2108 | static int snd_pcm_open(struct file *file, struct snd_pcm *pcm, int stream) |
2114 | { | 2109 | { |
2115 | int err; | 2110 | int err; |
2116 | struct snd_pcm_file *pcm_file; | ||
2117 | wait_queue_t wait; | 2111 | wait_queue_t wait; |
2118 | 2112 | ||
2119 | if (pcm == NULL) { | 2113 | if (pcm == NULL) { |
@@ -2131,7 +2125,7 @@ static int snd_pcm_open(struct file *file, struct snd_pcm *pcm, int stream) | |||
2131 | add_wait_queue(&pcm->open_wait, &wait); | 2125 | add_wait_queue(&pcm->open_wait, &wait); |
2132 | mutex_lock(&pcm->open_mutex); | 2126 | mutex_lock(&pcm->open_mutex); |
2133 | while (1) { | 2127 | while (1) { |
2134 | err = snd_pcm_open_file(file, pcm, stream, &pcm_file); | 2128 | err = snd_pcm_open_file(file, pcm, stream); |
2135 | if (err >= 0) | 2129 | if (err >= 0) |
2136 | break; | 2130 | break; |
2137 | if (err == -EAGAIN) { | 2131 | if (err == -EAGAIN) { |
@@ -3156,8 +3150,8 @@ static const struct vm_operations_struct snd_pcm_vm_ops_data_fault = { | |||
3156 | /* | 3150 | /* |
3157 | * mmap the DMA buffer on RAM | 3151 | * mmap the DMA buffer on RAM |
3158 | */ | 3152 | */ |
3159 | static int snd_pcm_default_mmap(struct snd_pcm_substream *substream, | 3153 | int snd_pcm_lib_default_mmap(struct snd_pcm_substream *substream, |
3160 | struct vm_area_struct *area) | 3154 | struct vm_area_struct *area) |
3161 | { | 3155 | { |
3162 | area->vm_flags |= VM_RESERVED; | 3156 | area->vm_flags |= VM_RESERVED; |
3163 | #ifdef ARCH_HAS_DMA_MMAP_COHERENT | 3157 | #ifdef ARCH_HAS_DMA_MMAP_COHERENT |
@@ -3177,6 +3171,7 @@ static int snd_pcm_default_mmap(struct snd_pcm_substream *substream, | |||
3177 | area->vm_ops = &snd_pcm_vm_ops_data_fault; | 3171 | area->vm_ops = &snd_pcm_vm_ops_data_fault; |
3178 | return 0; | 3172 | return 0; |
3179 | } | 3173 | } |
3174 | EXPORT_SYMBOL_GPL(snd_pcm_lib_default_mmap); | ||
3180 | 3175 | ||
3181 | /* | 3176 | /* |
3182 | * mmap the DMA buffer on I/O memory area | 3177 | * mmap the DMA buffer on I/O memory area |
@@ -3242,7 +3237,7 @@ int snd_pcm_mmap_data(struct snd_pcm_substream *substream, struct file *file, | |||
3242 | if (substream->ops->mmap) | 3237 | if (substream->ops->mmap) |
3243 | err = substream->ops->mmap(substream, area); | 3238 | err = substream->ops->mmap(substream, area); |
3244 | else | 3239 | else |
3245 | err = snd_pcm_default_mmap(substream, area); | 3240 | err = snd_pcm_lib_default_mmap(substream, area); |
3246 | if (!err) | 3241 | if (!err) |
3247 | atomic_inc(&substream->mmap_count); | 3242 | atomic_inc(&substream->mmap_count); |
3248 | return err; | 3243 | return err; |