aboutsummaryrefslogtreecommitdiffstats
path: root/sound/usb
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2010-02-12 04:42:38 -0500
committerTakashi Iwai <tiwai@suse.de>2010-02-12 04:42:38 -0500
commita540e13386e90f8c833c5cd0d16d877b8a277af1 (patch)
treebfa3fa455ac1302e7355122f9979531c7aa476e7 /sound/usb
parentcebe41d4b8f8092359de31e241815fcb4b4dc0be (diff)
parentc3a3e040f01457d2ea4f199f75ca205401001a3b (diff)
Merge remote branch 'alsa/devel' into topic/misc
Diffstat (limited to 'sound/usb')
-rw-r--r--sound/usb/usbmixer.c125
-rw-r--r--sound/usb/usbmixer_maps.c23
2 files changed, 93 insertions, 55 deletions
diff --git a/sound/usb/usbmixer.c b/sound/usb/usbmixer.c
index f5596cfdbde1..dd0c1d7bf3ed 100644
--- a/sound/usb/usbmixer.c
+++ b/sound/usb/usbmixer.c
@@ -123,6 +123,7 @@ struct usb_mixer_elem_info {
123 int channels; 123 int channels;
124 int val_type; 124 int val_type;
125 int min, max, res; 125 int min, max, res;
126 int dBmin, dBmax;
126 int cached; 127 int cached;
127 int cache_val[MAX_CHANNELS]; 128 int cache_val[MAX_CHANNELS];
128 u8 initialized; 129 u8 initialized;
@@ -209,42 +210,50 @@ enum {
209 */ 210 */
210#include "usbmixer_maps.c" 211#include "usbmixer_maps.c"
211 212
212/* get the mapped name if the unit matches */ 213static const struct usbmix_name_map *
213static int check_mapped_name(struct mixer_build *state, int unitid, int control, char *buf, int buflen) 214find_map(struct mixer_build *state, int unitid, int control)
214{ 215{
215 const struct usbmix_name_map *p; 216 const struct usbmix_name_map *p = state->map;
216 217
217 if (! state->map) 218 if (!p)
218 return 0; 219 return NULL;
219 220
220 for (p = state->map; p->id; p++) { 221 for (p = state->map; p->id; p++) {
221 if (p->id == unitid && p->name && 222 if (p->id == unitid &&
222 (! control || ! p->control || control == p->control)) { 223 (!control || !p->control || control == p->control))
223 buflen--; 224 return p;
224 return strlcpy(buf, p->name, buflen);
225 }
226 } 225 }
227 return 0; 226 return NULL;
228} 227}
229 228
230/* check whether the control should be ignored */ 229/* get the mapped name if the unit matches */
231static int check_ignored_ctl(struct mixer_build *state, int unitid, int control) 230static int
231check_mapped_name(const struct usbmix_name_map *p, char *buf, int buflen)
232{ 232{
233 const struct usbmix_name_map *p; 233 if (!p || !p->name)
234 return 0;
234 235
235 if (! state->map) 236 buflen--;
237 return strlcpy(buf, p->name, buflen);
238}
239
240/* check whether the control should be ignored */
241static inline int
242check_ignored_ctl(const struct usbmix_name_map *p)
243{
244 if (!p || p->name || p->dB)
236 return 0; 245 return 0;
237 for (p = state->map; p->id; p++) { 246 return 1;
238 if (p->id == unitid && ! p->name && 247}
239 (! control || ! p->control || control == p->control)) { 248
240 /* 249/* dB mapping */
241 printk(KERN_DEBUG "ignored control %d:%d\n", 250static inline void check_mapped_dB(const struct usbmix_name_map *p,
242 unitid, control); 251 struct usb_mixer_elem_info *cval)
243 */ 252{
244 return 1; 253 if (p && p->dB) {
245 } 254 cval->dBmin = p->dB->min;
255 cval->dBmax = p->dB->max;
246 } 256 }
247 return 0;
248} 257}
249 258
250/* get the mapped selector source name */ 259/* get the mapped selector source name */
@@ -481,20 +490,8 @@ static int mixer_vol_tlv(struct snd_kcontrol *kcontrol, int op_flag,
481 490
482 if (size < sizeof(scale)) 491 if (size < sizeof(scale))
483 return -ENOMEM; 492 return -ENOMEM;
484 /* USB descriptions contain the dB scale in 1/256 dB unit 493 scale[2] = cval->dBmin;
485 * while ALSA TLV contains in 1/100 dB unit 494 scale[3] = cval->dBmax;
486 */
487 scale[2] = (convert_signed_value(cval, cval->min) * 100) / 256;
488 scale[3] = (convert_signed_value(cval, cval->max) * 100) / 256;
489 if (scale[3] <= scale[2]) {
490 /* something is wrong; assume it's either from/to 0dB */
491 if (scale[2] < 0)
492 scale[3] = 0;
493 else if (scale[2] > 0)
494 scale[2] = 0;
495 else /* totally crap, return an error */
496 return -EINVAL;
497 }
498 if (copy_to_user(_tlv, scale, sizeof(scale))) 495 if (copy_to_user(_tlv, scale, sizeof(scale)))
499 return -EFAULT; 496 return -EFAULT;
500 return 0; 497 return 0;
@@ -735,6 +732,7 @@ static int get_min_max(struct usb_mixer_elem_info *cval, int default_min)
735 cval->min = default_min; 732 cval->min = default_min;
736 cval->max = cval->min + 1; 733 cval->max = cval->min + 1;
737 cval->res = 1; 734 cval->res = 1;
735 cval->dBmin = cval->dBmax = 0;
738 736
739 if (cval->val_type == USB_MIXER_BOOLEAN || 737 if (cval->val_type == USB_MIXER_BOOLEAN ||
740 cval->val_type == USB_MIXER_INV_BOOLEAN) { 738 cval->val_type == USB_MIXER_INV_BOOLEAN) {
@@ -802,6 +800,24 @@ static int get_min_max(struct usb_mixer_elem_info *cval, int default_min)
802 800
803 cval->initialized = 1; 801 cval->initialized = 1;
804 } 802 }
803
804 /* USB descriptions contain the dB scale in 1/256 dB unit
805 * while ALSA TLV contains in 1/100 dB unit
806 */
807 cval->dBmin = (convert_signed_value(cval, cval->min) * 100) / 256;
808 cval->dBmax = (convert_signed_value(cval, cval->max) * 100) / 256;
809 if (cval->dBmin > cval->dBmax) {
810 /* something is wrong; assume it's either from/to 0dB */
811 if (cval->dBmin < 0)
812 cval->dBmax = 0;
813 else if (cval->dBmin > 0)
814 cval->dBmin = 0;
815 if (cval->dBmin > cval->dBmax) {
816 /* totally crap, return an error */
817 return -EINVAL;
818 }
819 }
820
805 return 0; 821 return 0;
806} 822}
807 823
@@ -927,6 +943,7 @@ static void build_feature_ctl(struct mixer_build *state, unsigned char *desc,
927 int nameid = desc[desc[0] - 1]; 943 int nameid = desc[desc[0] - 1];
928 struct snd_kcontrol *kctl; 944 struct snd_kcontrol *kctl;
929 struct usb_mixer_elem_info *cval; 945 struct usb_mixer_elem_info *cval;
946 const struct usbmix_name_map *map;
930 947
931 control++; /* change from zero-based to 1-based value */ 948 control++; /* change from zero-based to 1-based value */
932 949
@@ -935,7 +952,8 @@ static void build_feature_ctl(struct mixer_build *state, unsigned char *desc,
935 return; 952 return;
936 } 953 }
937 954
938 if (check_ignored_ctl(state, unitid, control)) 955 map = find_map(state, unitid, control);
956 if (check_ignored_ctl(map))
939 return; 957 return;
940 958
941 cval = kzalloc(sizeof(*cval), GFP_KERNEL); 959 cval = kzalloc(sizeof(*cval), GFP_KERNEL);
@@ -969,10 +987,11 @@ static void build_feature_ctl(struct mixer_build *state, unsigned char *desc,
969 } 987 }
970 kctl->private_free = usb_mixer_elem_free; 988 kctl->private_free = usb_mixer_elem_free;
971 989
972 len = check_mapped_name(state, unitid, control, kctl->id.name, sizeof(kctl->id.name)); 990 len = check_mapped_name(map, kctl->id.name, sizeof(kctl->id.name));
973 mapped_name = len != 0; 991 mapped_name = len != 0;
974 if (! len && nameid) 992 if (! len && nameid)
975 len = snd_usb_copy_string_desc(state, nameid, kctl->id.name, sizeof(kctl->id.name)); 993 len = snd_usb_copy_string_desc(state, nameid,
994 kctl->id.name, sizeof(kctl->id.name));
976 995
977 switch (control) { 996 switch (control) {
978 case USB_FEATURE_MUTE: 997 case USB_FEATURE_MUTE:
@@ -1010,6 +1029,7 @@ static void build_feature_ctl(struct mixer_build *state, unsigned char *desc,
1010 kctl->vd[0].access |= 1029 kctl->vd[0].access |=
1011 SNDRV_CTL_ELEM_ACCESS_TLV_READ | 1030 SNDRV_CTL_ELEM_ACCESS_TLV_READ |
1012 SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK; 1031 SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK;
1032 check_mapped_dB(map, cval);
1013 } 1033 }
1014 break; 1034 break;
1015 1035
@@ -1137,8 +1157,10 @@ static void build_mixer_unit_ctl(struct mixer_build *state, unsigned char *desc,
1137 unsigned int num_outs = desc[5 + input_pins]; 1157 unsigned int num_outs = desc[5 + input_pins];
1138 unsigned int i, len; 1158 unsigned int i, len;
1139 struct snd_kcontrol *kctl; 1159 struct snd_kcontrol *kctl;
1160 const struct usbmix_name_map *map;
1140 1161
1141 if (check_ignored_ctl(state, unitid, 0)) 1162 map = find_map(state, unitid, 0);
1163 if (check_ignored_ctl(map))
1142 return; 1164 return;
1143 1165
1144 cval = kzalloc(sizeof(*cval), GFP_KERNEL); 1166 cval = kzalloc(sizeof(*cval), GFP_KERNEL);
@@ -1167,7 +1189,7 @@ static void build_mixer_unit_ctl(struct mixer_build *state, unsigned char *desc,
1167 } 1189 }
1168 kctl->private_free = usb_mixer_elem_free; 1190 kctl->private_free = usb_mixer_elem_free;
1169 1191
1170 len = check_mapped_name(state, unitid, 0, kctl->id.name, sizeof(kctl->id.name)); 1192 len = check_mapped_name(map, kctl->id.name, sizeof(kctl->id.name));
1171 if (! len) 1193 if (! len)
1172 len = get_term_name(state, iterm, kctl->id.name, sizeof(kctl->id.name), 0); 1194 len = get_term_name(state, iterm, kctl->id.name, sizeof(kctl->id.name), 0);
1173 if (! len) 1195 if (! len)
@@ -1382,6 +1404,7 @@ static int build_audio_procunit(struct mixer_build *state, int unitid, unsigned
1382 int i, err, nameid, type, len; 1404 int i, err, nameid, type, len;
1383 struct procunit_info *info; 1405 struct procunit_info *info;
1384 struct procunit_value_info *valinfo; 1406 struct procunit_value_info *valinfo;
1407 const struct usbmix_name_map *map;
1385 static struct procunit_value_info default_value_info[] = { 1408 static struct procunit_value_info default_value_info[] = {
1386 { 0x01, "Switch", USB_MIXER_BOOLEAN }, 1409 { 0x01, "Switch", USB_MIXER_BOOLEAN },
1387 { 0 } 1410 { 0 }
@@ -1411,7 +1434,8 @@ static int build_audio_procunit(struct mixer_build *state, int unitid, unsigned
1411 /* FIXME: bitmap might be longer than 8bit */ 1434 /* FIXME: bitmap might be longer than 8bit */
1412 if (! (dsc[12 + num_ins] & (1 << (valinfo->control - 1)))) 1435 if (! (dsc[12 + num_ins] & (1 << (valinfo->control - 1))))
1413 continue; 1436 continue;
1414 if (check_ignored_ctl(state, unitid, valinfo->control)) 1437 map = find_map(state, unitid, valinfo->control);
1438 if (check_ignored_ctl(map))
1415 continue; 1439 continue;
1416 cval = kzalloc(sizeof(*cval), GFP_KERNEL); 1440 cval = kzalloc(sizeof(*cval), GFP_KERNEL);
1417 if (! cval) { 1441 if (! cval) {
@@ -1452,8 +1476,9 @@ static int build_audio_procunit(struct mixer_build *state, int unitid, unsigned
1452 } 1476 }
1453 kctl->private_free = usb_mixer_elem_free; 1477 kctl->private_free = usb_mixer_elem_free;
1454 1478
1455 if (check_mapped_name(state, unitid, cval->control, kctl->id.name, sizeof(kctl->id.name))) 1479 if (check_mapped_name(map, kctl->id.name,
1456 ; 1480 sizeof(kctl->id.name)))
1481 /* nothing */ ;
1457 else if (info->name) 1482 else if (info->name)
1458 strlcpy(kctl->id.name, info->name, sizeof(kctl->id.name)); 1483 strlcpy(kctl->id.name, info->name, sizeof(kctl->id.name));
1459 else { 1484 else {
@@ -1592,6 +1617,7 @@ static int parse_audio_selector_unit(struct mixer_build *state, int unitid, unsi
1592 int err; 1617 int err;
1593 struct usb_mixer_elem_info *cval; 1618 struct usb_mixer_elem_info *cval;
1594 struct snd_kcontrol *kctl; 1619 struct snd_kcontrol *kctl;
1620 const struct usbmix_name_map *map;
1595 char **namelist; 1621 char **namelist;
1596 1622
1597 if (! num_ins || desc[0] < 5 + num_ins) { 1623 if (! num_ins || desc[0] < 5 + num_ins) {
@@ -1607,7 +1633,8 @@ static int parse_audio_selector_unit(struct mixer_build *state, int unitid, unsi
1607 if (num_ins == 1) /* only one ? nonsense! */ 1633 if (num_ins == 1) /* only one ? nonsense! */
1608 return 0; 1634 return 0;
1609 1635
1610 if (check_ignored_ctl(state, unitid, 0)) 1636 map = find_map(state, unitid, 0);
1637 if (check_ignored_ctl(map))
1611 return 0; 1638 return 0;
1612 1639
1613 cval = kzalloc(sizeof(*cval), GFP_KERNEL); 1640 cval = kzalloc(sizeof(*cval), GFP_KERNEL);
@@ -1662,7 +1689,7 @@ static int parse_audio_selector_unit(struct mixer_build *state, int unitid, unsi
1662 kctl->private_free = usb_mixer_selector_elem_free; 1689 kctl->private_free = usb_mixer_selector_elem_free;
1663 1690
1664 nameid = desc[desc[0] - 1]; 1691 nameid = desc[desc[0] - 1];
1665 len = check_mapped_name(state, unitid, 0, kctl->id.name, sizeof(kctl->id.name)); 1692 len = check_mapped_name(map, kctl->id.name, sizeof(kctl->id.name));
1666 if (len) 1693 if (len)
1667 ; 1694 ;
1668 else if (nameid) 1695 else if (nameid)
diff --git a/sound/usb/usbmixer_maps.c b/sound/usb/usbmixer_maps.c
index 77c35885e21c..79e903a60862 100644
--- a/sound/usb/usbmixer_maps.c
+++ b/sound/usb/usbmixer_maps.c
@@ -19,11 +19,16 @@
19 * 19 *
20 */ 20 */
21 21
22struct usbmix_dB_map {
23 u32 min;
24 u32 max;
25};
22 26
23struct usbmix_name_map { 27struct usbmix_name_map {
24 int id; 28 int id;
25 const char *name; 29 const char *name;
26 int control; 30 int control;
31 struct usbmix_dB_map *dB;
27}; 32};
28 33
29struct usbmix_selector_map { 34struct usbmix_selector_map {
@@ -72,7 +77,7 @@ static struct usbmix_name_map extigy_map[] = {
72 { 8, "Line Playback" }, /* FU */ 77 { 8, "Line Playback" }, /* FU */
73 /* 9: IT mic */ 78 /* 9: IT mic */
74 { 10, "Mic Playback" }, /* FU */ 79 { 10, "Mic Playback" }, /* FU */
75 { 11, "Capture Input Source" }, /* SU */ 80 { 11, "Capture Source" }, /* SU */
76 { 12, "Capture" }, /* FU */ 81 { 12, "Capture" }, /* FU */
77 /* 13: OT pcm capture */ 82 /* 13: OT pcm capture */
78 /* 14: MU (w/o controls) */ 83 /* 14: MU (w/o controls) */
@@ -102,6 +107,9 @@ static struct usbmix_name_map extigy_map[] = {
102 * e.g. no Master and fake PCM volume 107 * e.g. no Master and fake PCM volume
103 * Pavel Mihaylov <bin@bash.info> 108 * Pavel Mihaylov <bin@bash.info>
104 */ 109 */
110static struct usbmix_dB_map mp3plus_dB_1 = {-4781, 0}; /* just guess */
111static struct usbmix_dB_map mp3plus_dB_2 = {-1781, 618}; /* just guess */
112
105static struct usbmix_name_map mp3plus_map[] = { 113static struct usbmix_name_map mp3plus_map[] = {
106 /* 1: IT pcm */ 114 /* 1: IT pcm */
107 /* 2: IT mic */ 115 /* 2: IT mic */
@@ -110,16 +118,19 @@ static struct usbmix_name_map mp3plus_map[] = {
110 /* 5: OT digital out */ 118 /* 5: OT digital out */
111 /* 6: OT speaker */ 119 /* 6: OT speaker */
112 /* 7: OT pcm capture */ 120 /* 7: OT pcm capture */
113 { 8, "Capture Input Source" }, /* FU, default PCM Capture Source */ 121 { 8, "Capture Source" }, /* FU, default PCM Capture Source */
114 /* (Mic, Input 1 = Line input, Input 2 = Optical input) */ 122 /* (Mic, Input 1 = Line input, Input 2 = Optical input) */
115 { 9, "Master Playback" }, /* FU, default Speaker 1 */ 123 { 9, "Master Playback" }, /* FU, default Speaker 1 */
116 /* { 10, "Mic Capture", 1 }, */ /* FU, Mic Capture */ 124 /* { 10, "Mic Capture", 1 }, */ /* FU, Mic Capture */
117 /* { 10, "Mic Capture", 2 }, */ /* FU, Mic Capture */ 125 { 10, /* "Mic Capture", */ NULL, 2, .dB = &mp3plus_dB_2 },
126 /* FU, Mic Capture */
118 { 10, "Mic Boost", 7 }, /* FU, default Auto Gain Input */ 127 { 10, "Mic Boost", 7 }, /* FU, default Auto Gain Input */
119 { 11, "Line Capture" }, /* FU, default PCM Capture */ 128 { 11, "Line Capture", .dB = &mp3plus_dB_2 },
129 /* FU, default PCM Capture */
120 { 12, "Digital In Playback" }, /* FU, default PCM 1 */ 130 { 12, "Digital In Playback" }, /* FU, default PCM 1 */
121 /* { 13, "Mic Playback" }, */ /* FU, default Mic Playback */ 131 { 13, /* "Mic Playback", */ .dB = &mp3plus_dB_1 },
122 { 14, "Line Playback" }, /* FU, default Speaker */ 132 /* FU, default Mic Playback */
133 { 14, "Line Playback", .dB = &mp3plus_dB_1 }, /* FU, default Speaker */
123 /* 15: MU */ 134 /* 15: MU */
124 { 0 } /* terminator */ 135 { 0 } /* terminator */
125}; 136};