Commit 36691e1be6ec551eef4a5225f126a281f8c051c2
1 parent
6ab982e8cf
Exists in
smarc-l5.0.0_1.0.0-ga
and in
5 other branches
ALSA: usb-audio: Fix invalid volume resolution for Logitech HD Webcam c310
Just like the previous fix for LogitechHD Webcam c270 in commit 11e7064f35bb87da8f427d1aa4bbd8b7473a3993, c310 model also requires the same workaround for avoiding the kernel warning. Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=59741 Cc: <stable@vger.kernel.org> Signed-off-by: Takashi Iwai <tiwai@suse.de>
Showing 1 changed file with 1 additions and 0 deletions Inline Diff
sound/usb/mixer.c
1 | /* | 1 | /* |
2 | * (Tentative) USB Audio Driver for ALSA | 2 | * (Tentative) USB Audio Driver for ALSA |
3 | * | 3 | * |
4 | * Mixer control part | 4 | * Mixer control part |
5 | * | 5 | * |
6 | * Copyright (c) 2002 by Takashi Iwai <tiwai@suse.de> | 6 | * Copyright (c) 2002 by Takashi Iwai <tiwai@suse.de> |
7 | * | 7 | * |
8 | * Many codes borrowed from audio.c by | 8 | * Many codes borrowed from audio.c by |
9 | * Alan Cox (alan@lxorguk.ukuu.org.uk) | 9 | * Alan Cox (alan@lxorguk.ukuu.org.uk) |
10 | * Thomas Sailer (sailer@ife.ee.ethz.ch) | 10 | * Thomas Sailer (sailer@ife.ee.ethz.ch) |
11 | * | 11 | * |
12 | * | 12 | * |
13 | * This program is free software; you can redistribute it and/or modify | 13 | * This program is free software; you can redistribute it and/or modify |
14 | * it under the terms of the GNU General Public License as published by | 14 | * it under the terms of the GNU General Public License as published by |
15 | * the Free Software Foundation; either version 2 of the License, or | 15 | * the Free Software Foundation; either version 2 of the License, or |
16 | * (at your option) any later version. | 16 | * (at your option) any later version. |
17 | * | 17 | * |
18 | * This program is distributed in the hope that it will be useful, | 18 | * This program is distributed in the hope that it will be useful, |
19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
21 | * GNU General Public License for more details. | 21 | * GNU General Public License for more details. |
22 | * | 22 | * |
23 | * You should have received a copy of the GNU General Public License | 23 | * You should have received a copy of the GNU General Public License |
24 | * along with this program; if not, write to the Free Software | 24 | * along with this program; if not, write to the Free Software |
25 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 25 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
26 | * | 26 | * |
27 | */ | 27 | */ |
28 | 28 | ||
29 | /* | 29 | /* |
30 | * TODOs, for both the mixer and the streaming interfaces: | 30 | * TODOs, for both the mixer and the streaming interfaces: |
31 | * | 31 | * |
32 | * - support for UAC2 effect units | 32 | * - support for UAC2 effect units |
33 | * - support for graphical equalizers | 33 | * - support for graphical equalizers |
34 | * - RANGE and MEM set commands (UAC2) | 34 | * - RANGE and MEM set commands (UAC2) |
35 | * - RANGE and MEM interrupt dispatchers (UAC2) | 35 | * - RANGE and MEM interrupt dispatchers (UAC2) |
36 | * - audio channel clustering (UAC2) | 36 | * - audio channel clustering (UAC2) |
37 | * - audio sample rate converter units (UAC2) | 37 | * - audio sample rate converter units (UAC2) |
38 | * - proper handling of clock multipliers (UAC2) | 38 | * - proper handling of clock multipliers (UAC2) |
39 | * - dispatch clock change notifications (UAC2) | 39 | * - dispatch clock change notifications (UAC2) |
40 | * - stop PCM streams which use a clock that became invalid | 40 | * - stop PCM streams which use a clock that became invalid |
41 | * - stop PCM streams which use a clock selector that has changed | 41 | * - stop PCM streams which use a clock selector that has changed |
42 | * - parse available sample rates again when clock sources changed | 42 | * - parse available sample rates again when clock sources changed |
43 | */ | 43 | */ |
44 | 44 | ||
45 | #include <linux/bitops.h> | 45 | #include <linux/bitops.h> |
46 | #include <linux/init.h> | 46 | #include <linux/init.h> |
47 | #include <linux/list.h> | 47 | #include <linux/list.h> |
48 | #include <linux/slab.h> | 48 | #include <linux/slab.h> |
49 | #include <linux/string.h> | 49 | #include <linux/string.h> |
50 | #include <linux/usb.h> | 50 | #include <linux/usb.h> |
51 | #include <linux/usb/audio.h> | 51 | #include <linux/usb/audio.h> |
52 | #include <linux/usb/audio-v2.h> | 52 | #include <linux/usb/audio-v2.h> |
53 | 53 | ||
54 | #include <sound/core.h> | 54 | #include <sound/core.h> |
55 | #include <sound/control.h> | 55 | #include <sound/control.h> |
56 | #include <sound/hwdep.h> | 56 | #include <sound/hwdep.h> |
57 | #include <sound/info.h> | 57 | #include <sound/info.h> |
58 | #include <sound/tlv.h> | 58 | #include <sound/tlv.h> |
59 | 59 | ||
60 | #include "usbaudio.h" | 60 | #include "usbaudio.h" |
61 | #include "mixer.h" | 61 | #include "mixer.h" |
62 | #include "helper.h" | 62 | #include "helper.h" |
63 | #include "mixer_quirks.h" | 63 | #include "mixer_quirks.h" |
64 | #include "power.h" | 64 | #include "power.h" |
65 | 65 | ||
66 | #define MAX_ID_ELEMS 256 | 66 | #define MAX_ID_ELEMS 256 |
67 | 67 | ||
68 | struct usb_audio_term { | 68 | struct usb_audio_term { |
69 | int id; | 69 | int id; |
70 | int type; | 70 | int type; |
71 | int channels; | 71 | int channels; |
72 | unsigned int chconfig; | 72 | unsigned int chconfig; |
73 | int name; | 73 | int name; |
74 | }; | 74 | }; |
75 | 75 | ||
76 | struct usbmix_name_map; | 76 | struct usbmix_name_map; |
77 | 77 | ||
78 | struct mixer_build { | 78 | struct mixer_build { |
79 | struct snd_usb_audio *chip; | 79 | struct snd_usb_audio *chip; |
80 | struct usb_mixer_interface *mixer; | 80 | struct usb_mixer_interface *mixer; |
81 | unsigned char *buffer; | 81 | unsigned char *buffer; |
82 | unsigned int buflen; | 82 | unsigned int buflen; |
83 | DECLARE_BITMAP(unitbitmap, MAX_ID_ELEMS); | 83 | DECLARE_BITMAP(unitbitmap, MAX_ID_ELEMS); |
84 | struct usb_audio_term oterm; | 84 | struct usb_audio_term oterm; |
85 | const struct usbmix_name_map *map; | 85 | const struct usbmix_name_map *map; |
86 | const struct usbmix_selector_map *selector_map; | 86 | const struct usbmix_selector_map *selector_map; |
87 | }; | 87 | }; |
88 | 88 | ||
89 | /*E-mu 0202/0404/0204 eXtension Unit(XU) control*/ | 89 | /*E-mu 0202/0404/0204 eXtension Unit(XU) control*/ |
90 | enum { | 90 | enum { |
91 | USB_XU_CLOCK_RATE = 0xe301, | 91 | USB_XU_CLOCK_RATE = 0xe301, |
92 | USB_XU_CLOCK_SOURCE = 0xe302, | 92 | USB_XU_CLOCK_SOURCE = 0xe302, |
93 | USB_XU_DIGITAL_IO_STATUS = 0xe303, | 93 | USB_XU_DIGITAL_IO_STATUS = 0xe303, |
94 | USB_XU_DEVICE_OPTIONS = 0xe304, | 94 | USB_XU_DEVICE_OPTIONS = 0xe304, |
95 | USB_XU_DIRECT_MONITORING = 0xe305, | 95 | USB_XU_DIRECT_MONITORING = 0xe305, |
96 | USB_XU_METERING = 0xe306 | 96 | USB_XU_METERING = 0xe306 |
97 | }; | 97 | }; |
98 | enum { | 98 | enum { |
99 | USB_XU_CLOCK_SOURCE_SELECTOR = 0x02, /* clock source*/ | 99 | USB_XU_CLOCK_SOURCE_SELECTOR = 0x02, /* clock source*/ |
100 | USB_XU_CLOCK_RATE_SELECTOR = 0x03, /* clock rate */ | 100 | USB_XU_CLOCK_RATE_SELECTOR = 0x03, /* clock rate */ |
101 | USB_XU_DIGITAL_FORMAT_SELECTOR = 0x01, /* the spdif format */ | 101 | USB_XU_DIGITAL_FORMAT_SELECTOR = 0x01, /* the spdif format */ |
102 | USB_XU_SOFT_LIMIT_SELECTOR = 0x03 /* soft limiter */ | 102 | USB_XU_SOFT_LIMIT_SELECTOR = 0x03 /* soft limiter */ |
103 | }; | 103 | }; |
104 | 104 | ||
105 | /* | 105 | /* |
106 | * manual mapping of mixer names | 106 | * manual mapping of mixer names |
107 | * if the mixer topology is too complicated and the parsed names are | 107 | * if the mixer topology is too complicated and the parsed names are |
108 | * ambiguous, add the entries in usbmixer_maps.c. | 108 | * ambiguous, add the entries in usbmixer_maps.c. |
109 | */ | 109 | */ |
110 | #include "mixer_maps.c" | 110 | #include "mixer_maps.c" |
111 | 111 | ||
112 | static const struct usbmix_name_map * | 112 | static const struct usbmix_name_map * |
113 | find_map(struct mixer_build *state, int unitid, int control) | 113 | find_map(struct mixer_build *state, int unitid, int control) |
114 | { | 114 | { |
115 | const struct usbmix_name_map *p = state->map; | 115 | const struct usbmix_name_map *p = state->map; |
116 | 116 | ||
117 | if (!p) | 117 | if (!p) |
118 | return NULL; | 118 | return NULL; |
119 | 119 | ||
120 | for (p = state->map; p->id; p++) { | 120 | for (p = state->map; p->id; p++) { |
121 | if (p->id == unitid && | 121 | if (p->id == unitid && |
122 | (!control || !p->control || control == p->control)) | 122 | (!control || !p->control || control == p->control)) |
123 | return p; | 123 | return p; |
124 | } | 124 | } |
125 | return NULL; | 125 | return NULL; |
126 | } | 126 | } |
127 | 127 | ||
128 | /* get the mapped name if the unit matches */ | 128 | /* get the mapped name if the unit matches */ |
129 | static int | 129 | static int |
130 | check_mapped_name(const struct usbmix_name_map *p, char *buf, int buflen) | 130 | check_mapped_name(const struct usbmix_name_map *p, char *buf, int buflen) |
131 | { | 131 | { |
132 | if (!p || !p->name) | 132 | if (!p || !p->name) |
133 | return 0; | 133 | return 0; |
134 | 134 | ||
135 | buflen--; | 135 | buflen--; |
136 | return strlcpy(buf, p->name, buflen); | 136 | return strlcpy(buf, p->name, buflen); |
137 | } | 137 | } |
138 | 138 | ||
139 | /* check whether the control should be ignored */ | 139 | /* check whether the control should be ignored */ |
140 | static inline int | 140 | static inline int |
141 | check_ignored_ctl(const struct usbmix_name_map *p) | 141 | check_ignored_ctl(const struct usbmix_name_map *p) |
142 | { | 142 | { |
143 | if (!p || p->name || p->dB) | 143 | if (!p || p->name || p->dB) |
144 | return 0; | 144 | return 0; |
145 | return 1; | 145 | return 1; |
146 | } | 146 | } |
147 | 147 | ||
148 | /* dB mapping */ | 148 | /* dB mapping */ |
149 | static inline void check_mapped_dB(const struct usbmix_name_map *p, | 149 | static inline void check_mapped_dB(const struct usbmix_name_map *p, |
150 | struct usb_mixer_elem_info *cval) | 150 | struct usb_mixer_elem_info *cval) |
151 | { | 151 | { |
152 | if (p && p->dB) { | 152 | if (p && p->dB) { |
153 | cval->dBmin = p->dB->min; | 153 | cval->dBmin = p->dB->min; |
154 | cval->dBmax = p->dB->max; | 154 | cval->dBmax = p->dB->max; |
155 | cval->initialized = 1; | 155 | cval->initialized = 1; |
156 | } | 156 | } |
157 | } | 157 | } |
158 | 158 | ||
159 | /* get the mapped selector source name */ | 159 | /* get the mapped selector source name */ |
160 | static int check_mapped_selector_name(struct mixer_build *state, int unitid, | 160 | static int check_mapped_selector_name(struct mixer_build *state, int unitid, |
161 | int index, char *buf, int buflen) | 161 | int index, char *buf, int buflen) |
162 | { | 162 | { |
163 | const struct usbmix_selector_map *p; | 163 | const struct usbmix_selector_map *p; |
164 | 164 | ||
165 | if (! state->selector_map) | 165 | if (! state->selector_map) |
166 | return 0; | 166 | return 0; |
167 | for (p = state->selector_map; p->id; p++) { | 167 | for (p = state->selector_map; p->id; p++) { |
168 | if (p->id == unitid && index < p->count) | 168 | if (p->id == unitid && index < p->count) |
169 | return strlcpy(buf, p->names[index], buflen); | 169 | return strlcpy(buf, p->names[index], buflen); |
170 | } | 170 | } |
171 | return 0; | 171 | return 0; |
172 | } | 172 | } |
173 | 173 | ||
174 | /* | 174 | /* |
175 | * find an audio control unit with the given unit id | 175 | * find an audio control unit with the given unit id |
176 | */ | 176 | */ |
177 | static void *find_audio_control_unit(struct mixer_build *state, unsigned char unit) | 177 | static void *find_audio_control_unit(struct mixer_build *state, unsigned char unit) |
178 | { | 178 | { |
179 | /* we just parse the header */ | 179 | /* we just parse the header */ |
180 | struct uac_feature_unit_descriptor *hdr = NULL; | 180 | struct uac_feature_unit_descriptor *hdr = NULL; |
181 | 181 | ||
182 | while ((hdr = snd_usb_find_desc(state->buffer, state->buflen, hdr, | 182 | while ((hdr = snd_usb_find_desc(state->buffer, state->buflen, hdr, |
183 | USB_DT_CS_INTERFACE)) != NULL) { | 183 | USB_DT_CS_INTERFACE)) != NULL) { |
184 | if (hdr->bLength >= 4 && | 184 | if (hdr->bLength >= 4 && |
185 | hdr->bDescriptorSubtype >= UAC_INPUT_TERMINAL && | 185 | hdr->bDescriptorSubtype >= UAC_INPUT_TERMINAL && |
186 | hdr->bDescriptorSubtype <= UAC2_SAMPLE_RATE_CONVERTER && | 186 | hdr->bDescriptorSubtype <= UAC2_SAMPLE_RATE_CONVERTER && |
187 | hdr->bUnitID == unit) | 187 | hdr->bUnitID == unit) |
188 | return hdr; | 188 | return hdr; |
189 | } | 189 | } |
190 | 190 | ||
191 | return NULL; | 191 | return NULL; |
192 | } | 192 | } |
193 | 193 | ||
194 | /* | 194 | /* |
195 | * copy a string with the given id | 195 | * copy a string with the given id |
196 | */ | 196 | */ |
197 | static int snd_usb_copy_string_desc(struct mixer_build *state, int index, char *buf, int maxlen) | 197 | static int snd_usb_copy_string_desc(struct mixer_build *state, int index, char *buf, int maxlen) |
198 | { | 198 | { |
199 | int len = usb_string(state->chip->dev, index, buf, maxlen - 1); | 199 | int len = usb_string(state->chip->dev, index, buf, maxlen - 1); |
200 | buf[len] = 0; | 200 | buf[len] = 0; |
201 | return len; | 201 | return len; |
202 | } | 202 | } |
203 | 203 | ||
204 | /* | 204 | /* |
205 | * convert from the byte/word on usb descriptor to the zero-based integer | 205 | * convert from the byte/word on usb descriptor to the zero-based integer |
206 | */ | 206 | */ |
207 | static int convert_signed_value(struct usb_mixer_elem_info *cval, int val) | 207 | static int convert_signed_value(struct usb_mixer_elem_info *cval, int val) |
208 | { | 208 | { |
209 | switch (cval->val_type) { | 209 | switch (cval->val_type) { |
210 | case USB_MIXER_BOOLEAN: | 210 | case USB_MIXER_BOOLEAN: |
211 | return !!val; | 211 | return !!val; |
212 | case USB_MIXER_INV_BOOLEAN: | 212 | case USB_MIXER_INV_BOOLEAN: |
213 | return !val; | 213 | return !val; |
214 | case USB_MIXER_U8: | 214 | case USB_MIXER_U8: |
215 | val &= 0xff; | 215 | val &= 0xff; |
216 | break; | 216 | break; |
217 | case USB_MIXER_S8: | 217 | case USB_MIXER_S8: |
218 | val &= 0xff; | 218 | val &= 0xff; |
219 | if (val >= 0x80) | 219 | if (val >= 0x80) |
220 | val -= 0x100; | 220 | val -= 0x100; |
221 | break; | 221 | break; |
222 | case USB_MIXER_U16: | 222 | case USB_MIXER_U16: |
223 | val &= 0xffff; | 223 | val &= 0xffff; |
224 | break; | 224 | break; |
225 | case USB_MIXER_S16: | 225 | case USB_MIXER_S16: |
226 | val &= 0xffff; | 226 | val &= 0xffff; |
227 | if (val >= 0x8000) | 227 | if (val >= 0x8000) |
228 | val -= 0x10000; | 228 | val -= 0x10000; |
229 | break; | 229 | break; |
230 | } | 230 | } |
231 | return val; | 231 | return val; |
232 | } | 232 | } |
233 | 233 | ||
234 | /* | 234 | /* |
235 | * convert from the zero-based int to the byte/word for usb descriptor | 235 | * convert from the zero-based int to the byte/word for usb descriptor |
236 | */ | 236 | */ |
237 | static int convert_bytes_value(struct usb_mixer_elem_info *cval, int val) | 237 | static int convert_bytes_value(struct usb_mixer_elem_info *cval, int val) |
238 | { | 238 | { |
239 | switch (cval->val_type) { | 239 | switch (cval->val_type) { |
240 | case USB_MIXER_BOOLEAN: | 240 | case USB_MIXER_BOOLEAN: |
241 | return !!val; | 241 | return !!val; |
242 | case USB_MIXER_INV_BOOLEAN: | 242 | case USB_MIXER_INV_BOOLEAN: |
243 | return !val; | 243 | return !val; |
244 | case USB_MIXER_S8: | 244 | case USB_MIXER_S8: |
245 | case USB_MIXER_U8: | 245 | case USB_MIXER_U8: |
246 | return val & 0xff; | 246 | return val & 0xff; |
247 | case USB_MIXER_S16: | 247 | case USB_MIXER_S16: |
248 | case USB_MIXER_U16: | 248 | case USB_MIXER_U16: |
249 | return val & 0xffff; | 249 | return val & 0xffff; |
250 | } | 250 | } |
251 | return 0; /* not reached */ | 251 | return 0; /* not reached */ |
252 | } | 252 | } |
253 | 253 | ||
254 | static int get_relative_value(struct usb_mixer_elem_info *cval, int val) | 254 | static int get_relative_value(struct usb_mixer_elem_info *cval, int val) |
255 | { | 255 | { |
256 | if (! cval->res) | 256 | if (! cval->res) |
257 | cval->res = 1; | 257 | cval->res = 1; |
258 | if (val < cval->min) | 258 | if (val < cval->min) |
259 | return 0; | 259 | return 0; |
260 | else if (val >= cval->max) | 260 | else if (val >= cval->max) |
261 | return (cval->max - cval->min + cval->res - 1) / cval->res; | 261 | return (cval->max - cval->min + cval->res - 1) / cval->res; |
262 | else | 262 | else |
263 | return (val - cval->min) / cval->res; | 263 | return (val - cval->min) / cval->res; |
264 | } | 264 | } |
265 | 265 | ||
266 | static int get_abs_value(struct usb_mixer_elem_info *cval, int val) | 266 | static int get_abs_value(struct usb_mixer_elem_info *cval, int val) |
267 | { | 267 | { |
268 | if (val < 0) | 268 | if (val < 0) |
269 | return cval->min; | 269 | return cval->min; |
270 | if (! cval->res) | 270 | if (! cval->res) |
271 | cval->res = 1; | 271 | cval->res = 1; |
272 | val *= cval->res; | 272 | val *= cval->res; |
273 | val += cval->min; | 273 | val += cval->min; |
274 | if (val > cval->max) | 274 | if (val > cval->max) |
275 | return cval->max; | 275 | return cval->max; |
276 | return val; | 276 | return val; |
277 | } | 277 | } |
278 | 278 | ||
279 | 279 | ||
280 | /* | 280 | /* |
281 | * retrieve a mixer value | 281 | * retrieve a mixer value |
282 | */ | 282 | */ |
283 | 283 | ||
284 | static int get_ctl_value_v1(struct usb_mixer_elem_info *cval, int request, int validx, int *value_ret) | 284 | static int get_ctl_value_v1(struct usb_mixer_elem_info *cval, int request, int validx, int *value_ret) |
285 | { | 285 | { |
286 | struct snd_usb_audio *chip = cval->mixer->chip; | 286 | struct snd_usb_audio *chip = cval->mixer->chip; |
287 | unsigned char buf[2]; | 287 | unsigned char buf[2]; |
288 | int val_len = cval->val_type >= USB_MIXER_S16 ? 2 : 1; | 288 | int val_len = cval->val_type >= USB_MIXER_S16 ? 2 : 1; |
289 | int timeout = 10; | 289 | int timeout = 10; |
290 | int idx = 0, err; | 290 | int idx = 0, err; |
291 | 291 | ||
292 | err = snd_usb_autoresume(cval->mixer->chip); | 292 | err = snd_usb_autoresume(cval->mixer->chip); |
293 | if (err < 0) | 293 | if (err < 0) |
294 | return -EIO; | 294 | return -EIO; |
295 | down_read(&chip->shutdown_rwsem); | 295 | down_read(&chip->shutdown_rwsem); |
296 | while (timeout-- > 0) { | 296 | while (timeout-- > 0) { |
297 | if (chip->shutdown) | 297 | if (chip->shutdown) |
298 | break; | 298 | break; |
299 | idx = snd_usb_ctrl_intf(chip) | (cval->id << 8); | 299 | idx = snd_usb_ctrl_intf(chip) | (cval->id << 8); |
300 | if (snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), request, | 300 | if (snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), request, |
301 | USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, | 301 | USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, |
302 | validx, idx, buf, val_len) >= val_len) { | 302 | validx, idx, buf, val_len) >= val_len) { |
303 | *value_ret = convert_signed_value(cval, snd_usb_combine_bytes(buf, val_len)); | 303 | *value_ret = convert_signed_value(cval, snd_usb_combine_bytes(buf, val_len)); |
304 | err = 0; | 304 | err = 0; |
305 | goto out; | 305 | goto out; |
306 | } | 306 | } |
307 | } | 307 | } |
308 | snd_printdd(KERN_ERR "cannot get ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d\n", | 308 | snd_printdd(KERN_ERR "cannot get ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d\n", |
309 | request, validx, idx, cval->val_type); | 309 | request, validx, idx, cval->val_type); |
310 | err = -EINVAL; | 310 | err = -EINVAL; |
311 | 311 | ||
312 | out: | 312 | out: |
313 | up_read(&chip->shutdown_rwsem); | 313 | up_read(&chip->shutdown_rwsem); |
314 | snd_usb_autosuspend(cval->mixer->chip); | 314 | snd_usb_autosuspend(cval->mixer->chip); |
315 | return err; | 315 | return err; |
316 | } | 316 | } |
317 | 317 | ||
318 | static int get_ctl_value_v2(struct usb_mixer_elem_info *cval, int request, int validx, int *value_ret) | 318 | static int get_ctl_value_v2(struct usb_mixer_elem_info *cval, int request, int validx, int *value_ret) |
319 | { | 319 | { |
320 | struct snd_usb_audio *chip = cval->mixer->chip; | 320 | struct snd_usb_audio *chip = cval->mixer->chip; |
321 | unsigned char buf[2 + 3*sizeof(__u16)]; /* enough space for one range */ | 321 | unsigned char buf[2 + 3*sizeof(__u16)]; /* enough space for one range */ |
322 | unsigned char *val; | 322 | unsigned char *val; |
323 | int idx = 0, ret, size; | 323 | int idx = 0, ret, size; |
324 | __u8 bRequest; | 324 | __u8 bRequest; |
325 | 325 | ||
326 | if (request == UAC_GET_CUR) { | 326 | if (request == UAC_GET_CUR) { |
327 | bRequest = UAC2_CS_CUR; | 327 | bRequest = UAC2_CS_CUR; |
328 | size = sizeof(__u16); | 328 | size = sizeof(__u16); |
329 | } else { | 329 | } else { |
330 | bRequest = UAC2_CS_RANGE; | 330 | bRequest = UAC2_CS_RANGE; |
331 | size = sizeof(buf); | 331 | size = sizeof(buf); |
332 | } | 332 | } |
333 | 333 | ||
334 | memset(buf, 0, sizeof(buf)); | 334 | memset(buf, 0, sizeof(buf)); |
335 | 335 | ||
336 | ret = snd_usb_autoresume(chip) ? -EIO : 0; | 336 | ret = snd_usb_autoresume(chip) ? -EIO : 0; |
337 | if (ret) | 337 | if (ret) |
338 | goto error; | 338 | goto error; |
339 | 339 | ||
340 | down_read(&chip->shutdown_rwsem); | 340 | down_read(&chip->shutdown_rwsem); |
341 | if (chip->shutdown) | 341 | if (chip->shutdown) |
342 | ret = -ENODEV; | 342 | ret = -ENODEV; |
343 | else { | 343 | else { |
344 | idx = snd_usb_ctrl_intf(chip) | (cval->id << 8); | 344 | idx = snd_usb_ctrl_intf(chip) | (cval->id << 8); |
345 | ret = snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), bRequest, | 345 | ret = snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), bRequest, |
346 | USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, | 346 | USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, |
347 | validx, idx, buf, size); | 347 | validx, idx, buf, size); |
348 | } | 348 | } |
349 | up_read(&chip->shutdown_rwsem); | 349 | up_read(&chip->shutdown_rwsem); |
350 | snd_usb_autosuspend(chip); | 350 | snd_usb_autosuspend(chip); |
351 | 351 | ||
352 | if (ret < 0) { | 352 | if (ret < 0) { |
353 | error: | 353 | error: |
354 | snd_printk(KERN_ERR "cannot get ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d\n", | 354 | snd_printk(KERN_ERR "cannot get ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d\n", |
355 | request, validx, idx, cval->val_type); | 355 | request, validx, idx, cval->val_type); |
356 | return ret; | 356 | return ret; |
357 | } | 357 | } |
358 | 358 | ||
359 | /* FIXME: how should we handle multiple triplets here? */ | 359 | /* FIXME: how should we handle multiple triplets here? */ |
360 | 360 | ||
361 | switch (request) { | 361 | switch (request) { |
362 | case UAC_GET_CUR: | 362 | case UAC_GET_CUR: |
363 | val = buf; | 363 | val = buf; |
364 | break; | 364 | break; |
365 | case UAC_GET_MIN: | 365 | case UAC_GET_MIN: |
366 | val = buf + sizeof(__u16); | 366 | val = buf + sizeof(__u16); |
367 | break; | 367 | break; |
368 | case UAC_GET_MAX: | 368 | case UAC_GET_MAX: |
369 | val = buf + sizeof(__u16) * 2; | 369 | val = buf + sizeof(__u16) * 2; |
370 | break; | 370 | break; |
371 | case UAC_GET_RES: | 371 | case UAC_GET_RES: |
372 | val = buf + sizeof(__u16) * 3; | 372 | val = buf + sizeof(__u16) * 3; |
373 | break; | 373 | break; |
374 | default: | 374 | default: |
375 | return -EINVAL; | 375 | return -EINVAL; |
376 | } | 376 | } |
377 | 377 | ||
378 | *value_ret = convert_signed_value(cval, snd_usb_combine_bytes(val, sizeof(__u16))); | 378 | *value_ret = convert_signed_value(cval, snd_usb_combine_bytes(val, sizeof(__u16))); |
379 | 379 | ||
380 | return 0; | 380 | return 0; |
381 | } | 381 | } |
382 | 382 | ||
383 | static int get_ctl_value(struct usb_mixer_elem_info *cval, int request, int validx, int *value_ret) | 383 | static int get_ctl_value(struct usb_mixer_elem_info *cval, int request, int validx, int *value_ret) |
384 | { | 384 | { |
385 | validx += cval->idx_off; | 385 | validx += cval->idx_off; |
386 | 386 | ||
387 | return (cval->mixer->protocol == UAC_VERSION_1) ? | 387 | return (cval->mixer->protocol == UAC_VERSION_1) ? |
388 | get_ctl_value_v1(cval, request, validx, value_ret) : | 388 | get_ctl_value_v1(cval, request, validx, value_ret) : |
389 | get_ctl_value_v2(cval, request, validx, value_ret); | 389 | get_ctl_value_v2(cval, request, validx, value_ret); |
390 | } | 390 | } |
391 | 391 | ||
392 | static int get_cur_ctl_value(struct usb_mixer_elem_info *cval, int validx, int *value) | 392 | static int get_cur_ctl_value(struct usb_mixer_elem_info *cval, int validx, int *value) |
393 | { | 393 | { |
394 | return get_ctl_value(cval, UAC_GET_CUR, validx, value); | 394 | return get_ctl_value(cval, UAC_GET_CUR, validx, value); |
395 | } | 395 | } |
396 | 396 | ||
397 | /* channel = 0: master, 1 = first channel */ | 397 | /* channel = 0: master, 1 = first channel */ |
398 | static inline int get_cur_mix_raw(struct usb_mixer_elem_info *cval, | 398 | static inline int get_cur_mix_raw(struct usb_mixer_elem_info *cval, |
399 | int channel, int *value) | 399 | int channel, int *value) |
400 | { | 400 | { |
401 | return get_ctl_value(cval, UAC_GET_CUR, (cval->control << 8) | channel, value); | 401 | return get_ctl_value(cval, UAC_GET_CUR, (cval->control << 8) | channel, value); |
402 | } | 402 | } |
403 | 403 | ||
404 | static int get_cur_mix_value(struct usb_mixer_elem_info *cval, | 404 | static int get_cur_mix_value(struct usb_mixer_elem_info *cval, |
405 | int channel, int index, int *value) | 405 | int channel, int index, int *value) |
406 | { | 406 | { |
407 | int err; | 407 | int err; |
408 | 408 | ||
409 | if (cval->cached & (1 << channel)) { | 409 | if (cval->cached & (1 << channel)) { |
410 | *value = cval->cache_val[index]; | 410 | *value = cval->cache_val[index]; |
411 | return 0; | 411 | return 0; |
412 | } | 412 | } |
413 | err = get_cur_mix_raw(cval, channel, value); | 413 | err = get_cur_mix_raw(cval, channel, value); |
414 | if (err < 0) { | 414 | if (err < 0) { |
415 | if (!cval->mixer->ignore_ctl_error) | 415 | if (!cval->mixer->ignore_ctl_error) |
416 | snd_printd(KERN_ERR "cannot get current value for control %d ch %d: err = %d\n", | 416 | snd_printd(KERN_ERR "cannot get current value for control %d ch %d: err = %d\n", |
417 | cval->control, channel, err); | 417 | cval->control, channel, err); |
418 | return err; | 418 | return err; |
419 | } | 419 | } |
420 | cval->cached |= 1 << channel; | 420 | cval->cached |= 1 << channel; |
421 | cval->cache_val[index] = *value; | 421 | cval->cache_val[index] = *value; |
422 | return 0; | 422 | return 0; |
423 | } | 423 | } |
424 | 424 | ||
425 | 425 | ||
426 | /* | 426 | /* |
427 | * set a mixer value | 427 | * set a mixer value |
428 | */ | 428 | */ |
429 | 429 | ||
430 | int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval, | 430 | int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval, |
431 | int request, int validx, int value_set) | 431 | int request, int validx, int value_set) |
432 | { | 432 | { |
433 | struct snd_usb_audio *chip = cval->mixer->chip; | 433 | struct snd_usb_audio *chip = cval->mixer->chip; |
434 | unsigned char buf[2]; | 434 | unsigned char buf[2]; |
435 | int idx = 0, val_len, err, timeout = 10; | 435 | int idx = 0, val_len, err, timeout = 10; |
436 | 436 | ||
437 | validx += cval->idx_off; | 437 | validx += cval->idx_off; |
438 | 438 | ||
439 | if (cval->mixer->protocol == UAC_VERSION_1) { | 439 | if (cval->mixer->protocol == UAC_VERSION_1) { |
440 | val_len = cval->val_type >= USB_MIXER_S16 ? 2 : 1; | 440 | val_len = cval->val_type >= USB_MIXER_S16 ? 2 : 1; |
441 | } else { /* UAC_VERSION_2 */ | 441 | } else { /* UAC_VERSION_2 */ |
442 | /* audio class v2 controls are always 2 bytes in size */ | 442 | /* audio class v2 controls are always 2 bytes in size */ |
443 | val_len = sizeof(__u16); | 443 | val_len = sizeof(__u16); |
444 | 444 | ||
445 | /* FIXME */ | 445 | /* FIXME */ |
446 | if (request != UAC_SET_CUR) { | 446 | if (request != UAC_SET_CUR) { |
447 | snd_printdd(KERN_WARNING "RANGE setting not yet supported\n"); | 447 | snd_printdd(KERN_WARNING "RANGE setting not yet supported\n"); |
448 | return -EINVAL; | 448 | return -EINVAL; |
449 | } | 449 | } |
450 | 450 | ||
451 | request = UAC2_CS_CUR; | 451 | request = UAC2_CS_CUR; |
452 | } | 452 | } |
453 | 453 | ||
454 | value_set = convert_bytes_value(cval, value_set); | 454 | value_set = convert_bytes_value(cval, value_set); |
455 | buf[0] = value_set & 0xff; | 455 | buf[0] = value_set & 0xff; |
456 | buf[1] = (value_set >> 8) & 0xff; | 456 | buf[1] = (value_set >> 8) & 0xff; |
457 | err = snd_usb_autoresume(chip); | 457 | err = snd_usb_autoresume(chip); |
458 | if (err < 0) | 458 | if (err < 0) |
459 | return -EIO; | 459 | return -EIO; |
460 | down_read(&chip->shutdown_rwsem); | 460 | down_read(&chip->shutdown_rwsem); |
461 | while (timeout-- > 0) { | 461 | while (timeout-- > 0) { |
462 | if (chip->shutdown) | 462 | if (chip->shutdown) |
463 | break; | 463 | break; |
464 | idx = snd_usb_ctrl_intf(chip) | (cval->id << 8); | 464 | idx = snd_usb_ctrl_intf(chip) | (cval->id << 8); |
465 | if (snd_usb_ctl_msg(chip->dev, | 465 | if (snd_usb_ctl_msg(chip->dev, |
466 | usb_sndctrlpipe(chip->dev, 0), request, | 466 | usb_sndctrlpipe(chip->dev, 0), request, |
467 | USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT, | 467 | USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT, |
468 | validx, idx, buf, val_len) >= 0) { | 468 | validx, idx, buf, val_len) >= 0) { |
469 | err = 0; | 469 | err = 0; |
470 | goto out; | 470 | goto out; |
471 | } | 471 | } |
472 | } | 472 | } |
473 | snd_printdd(KERN_ERR "cannot set ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d, data = %#x/%#x\n", | 473 | snd_printdd(KERN_ERR "cannot set ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d, data = %#x/%#x\n", |
474 | request, validx, idx, cval->val_type, buf[0], buf[1]); | 474 | request, validx, idx, cval->val_type, buf[0], buf[1]); |
475 | err = -EINVAL; | 475 | err = -EINVAL; |
476 | 476 | ||
477 | out: | 477 | out: |
478 | up_read(&chip->shutdown_rwsem); | 478 | up_read(&chip->shutdown_rwsem); |
479 | snd_usb_autosuspend(chip); | 479 | snd_usb_autosuspend(chip); |
480 | return err; | 480 | return err; |
481 | } | 481 | } |
482 | 482 | ||
483 | static int set_cur_ctl_value(struct usb_mixer_elem_info *cval, int validx, int value) | 483 | static int set_cur_ctl_value(struct usb_mixer_elem_info *cval, int validx, int value) |
484 | { | 484 | { |
485 | return snd_usb_mixer_set_ctl_value(cval, UAC_SET_CUR, validx, value); | 485 | return snd_usb_mixer_set_ctl_value(cval, UAC_SET_CUR, validx, value); |
486 | } | 486 | } |
487 | 487 | ||
488 | static int set_cur_mix_value(struct usb_mixer_elem_info *cval, int channel, | 488 | static int set_cur_mix_value(struct usb_mixer_elem_info *cval, int channel, |
489 | int index, int value) | 489 | int index, int value) |
490 | { | 490 | { |
491 | int err; | 491 | int err; |
492 | unsigned int read_only = (channel == 0) ? | 492 | unsigned int read_only = (channel == 0) ? |
493 | cval->master_readonly : | 493 | cval->master_readonly : |
494 | cval->ch_readonly & (1 << (channel - 1)); | 494 | cval->ch_readonly & (1 << (channel - 1)); |
495 | 495 | ||
496 | if (read_only) { | 496 | if (read_only) { |
497 | snd_printdd(KERN_INFO "%s(): channel %d of control %d is read_only\n", | 497 | snd_printdd(KERN_INFO "%s(): channel %d of control %d is read_only\n", |
498 | __func__, channel, cval->control); | 498 | __func__, channel, cval->control); |
499 | return 0; | 499 | return 0; |
500 | } | 500 | } |
501 | 501 | ||
502 | err = snd_usb_mixer_set_ctl_value(cval, UAC_SET_CUR, (cval->control << 8) | channel, | 502 | err = snd_usb_mixer_set_ctl_value(cval, UAC_SET_CUR, (cval->control << 8) | channel, |
503 | value); | 503 | value); |
504 | if (err < 0) | 504 | if (err < 0) |
505 | return err; | 505 | return err; |
506 | cval->cached |= 1 << channel; | 506 | cval->cached |= 1 << channel; |
507 | cval->cache_val[index] = value; | 507 | cval->cache_val[index] = value; |
508 | return 0; | 508 | return 0; |
509 | } | 509 | } |
510 | 510 | ||
511 | /* | 511 | /* |
512 | * TLV callback for mixer volume controls | 512 | * TLV callback for mixer volume controls |
513 | */ | 513 | */ |
514 | int snd_usb_mixer_vol_tlv(struct snd_kcontrol *kcontrol, int op_flag, | 514 | int snd_usb_mixer_vol_tlv(struct snd_kcontrol *kcontrol, int op_flag, |
515 | unsigned int size, unsigned int __user *_tlv) | 515 | unsigned int size, unsigned int __user *_tlv) |
516 | { | 516 | { |
517 | struct usb_mixer_elem_info *cval = kcontrol->private_data; | 517 | struct usb_mixer_elem_info *cval = kcontrol->private_data; |
518 | DECLARE_TLV_DB_MINMAX(scale, 0, 0); | 518 | DECLARE_TLV_DB_MINMAX(scale, 0, 0); |
519 | 519 | ||
520 | if (size < sizeof(scale)) | 520 | if (size < sizeof(scale)) |
521 | return -ENOMEM; | 521 | return -ENOMEM; |
522 | scale[2] = cval->dBmin; | 522 | scale[2] = cval->dBmin; |
523 | scale[3] = cval->dBmax; | 523 | scale[3] = cval->dBmax; |
524 | if (copy_to_user(_tlv, scale, sizeof(scale))) | 524 | if (copy_to_user(_tlv, scale, sizeof(scale))) |
525 | return -EFAULT; | 525 | return -EFAULT; |
526 | return 0; | 526 | return 0; |
527 | } | 527 | } |
528 | 528 | ||
529 | /* | 529 | /* |
530 | * parser routines begin here... | 530 | * parser routines begin here... |
531 | */ | 531 | */ |
532 | 532 | ||
533 | static int parse_audio_unit(struct mixer_build *state, int unitid); | 533 | static int parse_audio_unit(struct mixer_build *state, int unitid); |
534 | 534 | ||
535 | 535 | ||
536 | /* | 536 | /* |
537 | * check if the input/output channel routing is enabled on the given bitmap. | 537 | * check if the input/output channel routing is enabled on the given bitmap. |
538 | * used for mixer unit parser | 538 | * used for mixer unit parser |
539 | */ | 539 | */ |
540 | static int check_matrix_bitmap(unsigned char *bmap, int ich, int och, int num_outs) | 540 | static int check_matrix_bitmap(unsigned char *bmap, int ich, int och, int num_outs) |
541 | { | 541 | { |
542 | int idx = ich * num_outs + och; | 542 | int idx = ich * num_outs + och; |
543 | return bmap[idx >> 3] & (0x80 >> (idx & 7)); | 543 | return bmap[idx >> 3] & (0x80 >> (idx & 7)); |
544 | } | 544 | } |
545 | 545 | ||
546 | 546 | ||
547 | /* | 547 | /* |
548 | * add an alsa control element | 548 | * add an alsa control element |
549 | * search and increment the index until an empty slot is found. | 549 | * search and increment the index until an empty slot is found. |
550 | * | 550 | * |
551 | * if failed, give up and free the control instance. | 551 | * if failed, give up and free the control instance. |
552 | */ | 552 | */ |
553 | 553 | ||
554 | int snd_usb_mixer_add_control(struct usb_mixer_interface *mixer, | 554 | int snd_usb_mixer_add_control(struct usb_mixer_interface *mixer, |
555 | struct snd_kcontrol *kctl) | 555 | struct snd_kcontrol *kctl) |
556 | { | 556 | { |
557 | struct usb_mixer_elem_info *cval = kctl->private_data; | 557 | struct usb_mixer_elem_info *cval = kctl->private_data; |
558 | int err; | 558 | int err; |
559 | 559 | ||
560 | while (snd_ctl_find_id(mixer->chip->card, &kctl->id)) | 560 | while (snd_ctl_find_id(mixer->chip->card, &kctl->id)) |
561 | kctl->id.index++; | 561 | kctl->id.index++; |
562 | if ((err = snd_ctl_add(mixer->chip->card, kctl)) < 0) { | 562 | if ((err = snd_ctl_add(mixer->chip->card, kctl)) < 0) { |
563 | snd_printd(KERN_ERR "cannot add control (err = %d)\n", err); | 563 | snd_printd(KERN_ERR "cannot add control (err = %d)\n", err); |
564 | return err; | 564 | return err; |
565 | } | 565 | } |
566 | cval->elem_id = &kctl->id; | 566 | cval->elem_id = &kctl->id; |
567 | cval->next_id_elem = mixer->id_elems[cval->id]; | 567 | cval->next_id_elem = mixer->id_elems[cval->id]; |
568 | mixer->id_elems[cval->id] = cval; | 568 | mixer->id_elems[cval->id] = cval; |
569 | return 0; | 569 | return 0; |
570 | } | 570 | } |
571 | 571 | ||
572 | 572 | ||
573 | /* | 573 | /* |
574 | * get a terminal name string | 574 | * get a terminal name string |
575 | */ | 575 | */ |
576 | 576 | ||
577 | static struct iterm_name_combo { | 577 | static struct iterm_name_combo { |
578 | int type; | 578 | int type; |
579 | char *name; | 579 | char *name; |
580 | } iterm_names[] = { | 580 | } iterm_names[] = { |
581 | { 0x0300, "Output" }, | 581 | { 0x0300, "Output" }, |
582 | { 0x0301, "Speaker" }, | 582 | { 0x0301, "Speaker" }, |
583 | { 0x0302, "Headphone" }, | 583 | { 0x0302, "Headphone" }, |
584 | { 0x0303, "HMD Audio" }, | 584 | { 0x0303, "HMD Audio" }, |
585 | { 0x0304, "Desktop Speaker" }, | 585 | { 0x0304, "Desktop Speaker" }, |
586 | { 0x0305, "Room Speaker" }, | 586 | { 0x0305, "Room Speaker" }, |
587 | { 0x0306, "Com Speaker" }, | 587 | { 0x0306, "Com Speaker" }, |
588 | { 0x0307, "LFE" }, | 588 | { 0x0307, "LFE" }, |
589 | { 0x0600, "External In" }, | 589 | { 0x0600, "External In" }, |
590 | { 0x0601, "Analog In" }, | 590 | { 0x0601, "Analog In" }, |
591 | { 0x0602, "Digital In" }, | 591 | { 0x0602, "Digital In" }, |
592 | { 0x0603, "Line" }, | 592 | { 0x0603, "Line" }, |
593 | { 0x0604, "Legacy In" }, | 593 | { 0x0604, "Legacy In" }, |
594 | { 0x0605, "IEC958 In" }, | 594 | { 0x0605, "IEC958 In" }, |
595 | { 0x0606, "1394 DA Stream" }, | 595 | { 0x0606, "1394 DA Stream" }, |
596 | { 0x0607, "1394 DV Stream" }, | 596 | { 0x0607, "1394 DV Stream" }, |
597 | { 0x0700, "Embedded" }, | 597 | { 0x0700, "Embedded" }, |
598 | { 0x0701, "Noise Source" }, | 598 | { 0x0701, "Noise Source" }, |
599 | { 0x0702, "Equalization Noise" }, | 599 | { 0x0702, "Equalization Noise" }, |
600 | { 0x0703, "CD" }, | 600 | { 0x0703, "CD" }, |
601 | { 0x0704, "DAT" }, | 601 | { 0x0704, "DAT" }, |
602 | { 0x0705, "DCC" }, | 602 | { 0x0705, "DCC" }, |
603 | { 0x0706, "MiniDisk" }, | 603 | { 0x0706, "MiniDisk" }, |
604 | { 0x0707, "Analog Tape" }, | 604 | { 0x0707, "Analog Tape" }, |
605 | { 0x0708, "Phonograph" }, | 605 | { 0x0708, "Phonograph" }, |
606 | { 0x0709, "VCR Audio" }, | 606 | { 0x0709, "VCR Audio" }, |
607 | { 0x070a, "Video Disk Audio" }, | 607 | { 0x070a, "Video Disk Audio" }, |
608 | { 0x070b, "DVD Audio" }, | 608 | { 0x070b, "DVD Audio" }, |
609 | { 0x070c, "TV Tuner Audio" }, | 609 | { 0x070c, "TV Tuner Audio" }, |
610 | { 0x070d, "Satellite Rec Audio" }, | 610 | { 0x070d, "Satellite Rec Audio" }, |
611 | { 0x070e, "Cable Tuner Audio" }, | 611 | { 0x070e, "Cable Tuner Audio" }, |
612 | { 0x070f, "DSS Audio" }, | 612 | { 0x070f, "DSS Audio" }, |
613 | { 0x0710, "Radio Receiver" }, | 613 | { 0x0710, "Radio Receiver" }, |
614 | { 0x0711, "Radio Transmitter" }, | 614 | { 0x0711, "Radio Transmitter" }, |
615 | { 0x0712, "Multi-Track Recorder" }, | 615 | { 0x0712, "Multi-Track Recorder" }, |
616 | { 0x0713, "Synthesizer" }, | 616 | { 0x0713, "Synthesizer" }, |
617 | { 0 }, | 617 | { 0 }, |
618 | }; | 618 | }; |
619 | 619 | ||
620 | static int get_term_name(struct mixer_build *state, struct usb_audio_term *iterm, | 620 | static int get_term_name(struct mixer_build *state, struct usb_audio_term *iterm, |
621 | unsigned char *name, int maxlen, int term_only) | 621 | unsigned char *name, int maxlen, int term_only) |
622 | { | 622 | { |
623 | struct iterm_name_combo *names; | 623 | struct iterm_name_combo *names; |
624 | 624 | ||
625 | if (iterm->name) | 625 | if (iterm->name) |
626 | return snd_usb_copy_string_desc(state, iterm->name, name, maxlen); | 626 | return snd_usb_copy_string_desc(state, iterm->name, name, maxlen); |
627 | 627 | ||
628 | /* virtual type - not a real terminal */ | 628 | /* virtual type - not a real terminal */ |
629 | if (iterm->type >> 16) { | 629 | if (iterm->type >> 16) { |
630 | if (term_only) | 630 | if (term_only) |
631 | return 0; | 631 | return 0; |
632 | switch (iterm->type >> 16) { | 632 | switch (iterm->type >> 16) { |
633 | case UAC_SELECTOR_UNIT: | 633 | case UAC_SELECTOR_UNIT: |
634 | strcpy(name, "Selector"); return 8; | 634 | strcpy(name, "Selector"); return 8; |
635 | case UAC1_PROCESSING_UNIT: | 635 | case UAC1_PROCESSING_UNIT: |
636 | strcpy(name, "Process Unit"); return 12; | 636 | strcpy(name, "Process Unit"); return 12; |
637 | case UAC1_EXTENSION_UNIT: | 637 | case UAC1_EXTENSION_UNIT: |
638 | strcpy(name, "Ext Unit"); return 8; | 638 | strcpy(name, "Ext Unit"); return 8; |
639 | case UAC_MIXER_UNIT: | 639 | case UAC_MIXER_UNIT: |
640 | strcpy(name, "Mixer"); return 5; | 640 | strcpy(name, "Mixer"); return 5; |
641 | default: | 641 | default: |
642 | return sprintf(name, "Unit %d", iterm->id); | 642 | return sprintf(name, "Unit %d", iterm->id); |
643 | } | 643 | } |
644 | } | 644 | } |
645 | 645 | ||
646 | switch (iterm->type & 0xff00) { | 646 | switch (iterm->type & 0xff00) { |
647 | case 0x0100: | 647 | case 0x0100: |
648 | strcpy(name, "PCM"); return 3; | 648 | strcpy(name, "PCM"); return 3; |
649 | case 0x0200: | 649 | case 0x0200: |
650 | strcpy(name, "Mic"); return 3; | 650 | strcpy(name, "Mic"); return 3; |
651 | case 0x0400: | 651 | case 0x0400: |
652 | strcpy(name, "Headset"); return 7; | 652 | strcpy(name, "Headset"); return 7; |
653 | case 0x0500: | 653 | case 0x0500: |
654 | strcpy(name, "Phone"); return 5; | 654 | strcpy(name, "Phone"); return 5; |
655 | } | 655 | } |
656 | 656 | ||
657 | for (names = iterm_names; names->type; names++) | 657 | for (names = iterm_names; names->type; names++) |
658 | if (names->type == iterm->type) { | 658 | if (names->type == iterm->type) { |
659 | strcpy(name, names->name); | 659 | strcpy(name, names->name); |
660 | return strlen(names->name); | 660 | return strlen(names->name); |
661 | } | 661 | } |
662 | return 0; | 662 | return 0; |
663 | } | 663 | } |
664 | 664 | ||
665 | 665 | ||
666 | /* | 666 | /* |
667 | * parse the source unit recursively until it reaches to a terminal | 667 | * parse the source unit recursively until it reaches to a terminal |
668 | * or a branched unit. | 668 | * or a branched unit. |
669 | */ | 669 | */ |
670 | static int check_input_term(struct mixer_build *state, int id, struct usb_audio_term *term) | 670 | static int check_input_term(struct mixer_build *state, int id, struct usb_audio_term *term) |
671 | { | 671 | { |
672 | int err; | 672 | int err; |
673 | void *p1; | 673 | void *p1; |
674 | 674 | ||
675 | memset(term, 0, sizeof(*term)); | 675 | memset(term, 0, sizeof(*term)); |
676 | while ((p1 = find_audio_control_unit(state, id)) != NULL) { | 676 | while ((p1 = find_audio_control_unit(state, id)) != NULL) { |
677 | unsigned char *hdr = p1; | 677 | unsigned char *hdr = p1; |
678 | term->id = id; | 678 | term->id = id; |
679 | switch (hdr[2]) { | 679 | switch (hdr[2]) { |
680 | case UAC_INPUT_TERMINAL: | 680 | case UAC_INPUT_TERMINAL: |
681 | if (state->mixer->protocol == UAC_VERSION_1) { | 681 | if (state->mixer->protocol == UAC_VERSION_1) { |
682 | struct uac_input_terminal_descriptor *d = p1; | 682 | struct uac_input_terminal_descriptor *d = p1; |
683 | term->type = le16_to_cpu(d->wTerminalType); | 683 | term->type = le16_to_cpu(d->wTerminalType); |
684 | term->channels = d->bNrChannels; | 684 | term->channels = d->bNrChannels; |
685 | term->chconfig = le16_to_cpu(d->wChannelConfig); | 685 | term->chconfig = le16_to_cpu(d->wChannelConfig); |
686 | term->name = d->iTerminal; | 686 | term->name = d->iTerminal; |
687 | } else { /* UAC_VERSION_2 */ | 687 | } else { /* UAC_VERSION_2 */ |
688 | struct uac2_input_terminal_descriptor *d = p1; | 688 | struct uac2_input_terminal_descriptor *d = p1; |
689 | term->type = le16_to_cpu(d->wTerminalType); | 689 | term->type = le16_to_cpu(d->wTerminalType); |
690 | term->channels = d->bNrChannels; | 690 | term->channels = d->bNrChannels; |
691 | term->chconfig = le32_to_cpu(d->bmChannelConfig); | 691 | term->chconfig = le32_to_cpu(d->bmChannelConfig); |
692 | term->name = d->iTerminal; | 692 | term->name = d->iTerminal; |
693 | 693 | ||
694 | /* call recursively to get the clock selectors */ | 694 | /* call recursively to get the clock selectors */ |
695 | err = check_input_term(state, d->bCSourceID, term); | 695 | err = check_input_term(state, d->bCSourceID, term); |
696 | if (err < 0) | 696 | if (err < 0) |
697 | return err; | 697 | return err; |
698 | } | 698 | } |
699 | return 0; | 699 | return 0; |
700 | case UAC_FEATURE_UNIT: { | 700 | case UAC_FEATURE_UNIT: { |
701 | /* the header is the same for v1 and v2 */ | 701 | /* the header is the same for v1 and v2 */ |
702 | struct uac_feature_unit_descriptor *d = p1; | 702 | struct uac_feature_unit_descriptor *d = p1; |
703 | id = d->bSourceID; | 703 | id = d->bSourceID; |
704 | break; /* continue to parse */ | 704 | break; /* continue to parse */ |
705 | } | 705 | } |
706 | case UAC_MIXER_UNIT: { | 706 | case UAC_MIXER_UNIT: { |
707 | struct uac_mixer_unit_descriptor *d = p1; | 707 | struct uac_mixer_unit_descriptor *d = p1; |
708 | term->type = d->bDescriptorSubtype << 16; /* virtual type */ | 708 | term->type = d->bDescriptorSubtype << 16; /* virtual type */ |
709 | term->channels = uac_mixer_unit_bNrChannels(d); | 709 | term->channels = uac_mixer_unit_bNrChannels(d); |
710 | term->chconfig = uac_mixer_unit_wChannelConfig(d, state->mixer->protocol); | 710 | term->chconfig = uac_mixer_unit_wChannelConfig(d, state->mixer->protocol); |
711 | term->name = uac_mixer_unit_iMixer(d); | 711 | term->name = uac_mixer_unit_iMixer(d); |
712 | return 0; | 712 | return 0; |
713 | } | 713 | } |
714 | case UAC_SELECTOR_UNIT: | 714 | case UAC_SELECTOR_UNIT: |
715 | case UAC2_CLOCK_SELECTOR: { | 715 | case UAC2_CLOCK_SELECTOR: { |
716 | struct uac_selector_unit_descriptor *d = p1; | 716 | struct uac_selector_unit_descriptor *d = p1; |
717 | /* call recursively to retrieve the channel info */ | 717 | /* call recursively to retrieve the channel info */ |
718 | err = check_input_term(state, d->baSourceID[0], term); | 718 | err = check_input_term(state, d->baSourceID[0], term); |
719 | if (err < 0) | 719 | if (err < 0) |
720 | return err; | 720 | return err; |
721 | term->type = d->bDescriptorSubtype << 16; /* virtual type */ | 721 | term->type = d->bDescriptorSubtype << 16; /* virtual type */ |
722 | term->id = id; | 722 | term->id = id; |
723 | term->name = uac_selector_unit_iSelector(d); | 723 | term->name = uac_selector_unit_iSelector(d); |
724 | return 0; | 724 | return 0; |
725 | } | 725 | } |
726 | case UAC1_PROCESSING_UNIT: | 726 | case UAC1_PROCESSING_UNIT: |
727 | case UAC1_EXTENSION_UNIT: | 727 | case UAC1_EXTENSION_UNIT: |
728 | /* UAC2_PROCESSING_UNIT_V2 */ | 728 | /* UAC2_PROCESSING_UNIT_V2 */ |
729 | /* UAC2_EFFECT_UNIT */ | 729 | /* UAC2_EFFECT_UNIT */ |
730 | case UAC2_EXTENSION_UNIT_V2: { | 730 | case UAC2_EXTENSION_UNIT_V2: { |
731 | struct uac_processing_unit_descriptor *d = p1; | 731 | struct uac_processing_unit_descriptor *d = p1; |
732 | 732 | ||
733 | if (state->mixer->protocol == UAC_VERSION_2 && | 733 | if (state->mixer->protocol == UAC_VERSION_2 && |
734 | hdr[2] == UAC2_EFFECT_UNIT) { | 734 | hdr[2] == UAC2_EFFECT_UNIT) { |
735 | /* UAC2/UAC1 unit IDs overlap here in an | 735 | /* UAC2/UAC1 unit IDs overlap here in an |
736 | * uncompatible way. Ignore this unit for now. | 736 | * uncompatible way. Ignore this unit for now. |
737 | */ | 737 | */ |
738 | return 0; | 738 | return 0; |
739 | } | 739 | } |
740 | 740 | ||
741 | if (d->bNrInPins) { | 741 | if (d->bNrInPins) { |
742 | id = d->baSourceID[0]; | 742 | id = d->baSourceID[0]; |
743 | break; /* continue to parse */ | 743 | break; /* continue to parse */ |
744 | } | 744 | } |
745 | term->type = d->bDescriptorSubtype << 16; /* virtual type */ | 745 | term->type = d->bDescriptorSubtype << 16; /* virtual type */ |
746 | term->channels = uac_processing_unit_bNrChannels(d); | 746 | term->channels = uac_processing_unit_bNrChannels(d); |
747 | term->chconfig = uac_processing_unit_wChannelConfig(d, state->mixer->protocol); | 747 | term->chconfig = uac_processing_unit_wChannelConfig(d, state->mixer->protocol); |
748 | term->name = uac_processing_unit_iProcessing(d, state->mixer->protocol); | 748 | term->name = uac_processing_unit_iProcessing(d, state->mixer->protocol); |
749 | return 0; | 749 | return 0; |
750 | } | 750 | } |
751 | case UAC2_CLOCK_SOURCE: { | 751 | case UAC2_CLOCK_SOURCE: { |
752 | struct uac_clock_source_descriptor *d = p1; | 752 | struct uac_clock_source_descriptor *d = p1; |
753 | term->type = d->bDescriptorSubtype << 16; /* virtual type */ | 753 | term->type = d->bDescriptorSubtype << 16; /* virtual type */ |
754 | term->id = id; | 754 | term->id = id; |
755 | term->name = d->iClockSource; | 755 | term->name = d->iClockSource; |
756 | return 0; | 756 | return 0; |
757 | } | 757 | } |
758 | default: | 758 | default: |
759 | return -ENODEV; | 759 | return -ENODEV; |
760 | } | 760 | } |
761 | } | 761 | } |
762 | return -ENODEV; | 762 | return -ENODEV; |
763 | } | 763 | } |
764 | 764 | ||
765 | 765 | ||
766 | /* | 766 | /* |
767 | * Feature Unit | 767 | * Feature Unit |
768 | */ | 768 | */ |
769 | 769 | ||
770 | /* feature unit control information */ | 770 | /* feature unit control information */ |
771 | struct usb_feature_control_info { | 771 | struct usb_feature_control_info { |
772 | const char *name; | 772 | const char *name; |
773 | unsigned int type; /* control type (mute, volume, etc.) */ | 773 | unsigned int type; /* control type (mute, volume, etc.) */ |
774 | }; | 774 | }; |
775 | 775 | ||
776 | static struct usb_feature_control_info audio_feature_info[] = { | 776 | static struct usb_feature_control_info audio_feature_info[] = { |
777 | { "Mute", USB_MIXER_INV_BOOLEAN }, | 777 | { "Mute", USB_MIXER_INV_BOOLEAN }, |
778 | { "Volume", USB_MIXER_S16 }, | 778 | { "Volume", USB_MIXER_S16 }, |
779 | { "Tone Control - Bass", USB_MIXER_S8 }, | 779 | { "Tone Control - Bass", USB_MIXER_S8 }, |
780 | { "Tone Control - Mid", USB_MIXER_S8 }, | 780 | { "Tone Control - Mid", USB_MIXER_S8 }, |
781 | { "Tone Control - Treble", USB_MIXER_S8 }, | 781 | { "Tone Control - Treble", USB_MIXER_S8 }, |
782 | { "Graphic Equalizer", USB_MIXER_S8 }, /* FIXME: not implemeted yet */ | 782 | { "Graphic Equalizer", USB_MIXER_S8 }, /* FIXME: not implemeted yet */ |
783 | { "Auto Gain Control", USB_MIXER_BOOLEAN }, | 783 | { "Auto Gain Control", USB_MIXER_BOOLEAN }, |
784 | { "Delay Control", USB_MIXER_U16 }, | 784 | { "Delay Control", USB_MIXER_U16 }, |
785 | { "Bass Boost", USB_MIXER_BOOLEAN }, | 785 | { "Bass Boost", USB_MIXER_BOOLEAN }, |
786 | { "Loudness", USB_MIXER_BOOLEAN }, | 786 | { "Loudness", USB_MIXER_BOOLEAN }, |
787 | /* UAC2 specific */ | 787 | /* UAC2 specific */ |
788 | { "Input Gain Control", USB_MIXER_U16 }, | 788 | { "Input Gain Control", USB_MIXER_U16 }, |
789 | { "Input Gain Pad Control", USB_MIXER_BOOLEAN }, | 789 | { "Input Gain Pad Control", USB_MIXER_BOOLEAN }, |
790 | { "Phase Inverter Control", USB_MIXER_BOOLEAN }, | 790 | { "Phase Inverter Control", USB_MIXER_BOOLEAN }, |
791 | }; | 791 | }; |
792 | 792 | ||
793 | 793 | ||
794 | /* private_free callback */ | 794 | /* private_free callback */ |
795 | static void usb_mixer_elem_free(struct snd_kcontrol *kctl) | 795 | static void usb_mixer_elem_free(struct snd_kcontrol *kctl) |
796 | { | 796 | { |
797 | kfree(kctl->private_data); | 797 | kfree(kctl->private_data); |
798 | kctl->private_data = NULL; | 798 | kctl->private_data = NULL; |
799 | } | 799 | } |
800 | 800 | ||
801 | 801 | ||
802 | /* | 802 | /* |
803 | * interface to ALSA control for feature/mixer units | 803 | * interface to ALSA control for feature/mixer units |
804 | */ | 804 | */ |
805 | 805 | ||
806 | /* volume control quirks */ | 806 | /* volume control quirks */ |
807 | static void volume_control_quirks(struct usb_mixer_elem_info *cval, | 807 | static void volume_control_quirks(struct usb_mixer_elem_info *cval, |
808 | struct snd_kcontrol *kctl) | 808 | struct snd_kcontrol *kctl) |
809 | { | 809 | { |
810 | switch (cval->mixer->chip->usb_id) { | 810 | switch (cval->mixer->chip->usb_id) { |
811 | case USB_ID(0x0763, 0x2030): /* M-Audio Fast Track C400 */ | 811 | case USB_ID(0x0763, 0x2030): /* M-Audio Fast Track C400 */ |
812 | case USB_ID(0x0763, 0x2031): /* M-Audio Fast Track C600 */ | 812 | case USB_ID(0x0763, 0x2031): /* M-Audio Fast Track C600 */ |
813 | if (strcmp(kctl->id.name, "Effect Duration") == 0) { | 813 | if (strcmp(kctl->id.name, "Effect Duration") == 0) { |
814 | cval->min = 0x0000; | 814 | cval->min = 0x0000; |
815 | cval->max = 0xffff; | 815 | cval->max = 0xffff; |
816 | cval->res = 0x00e6; | 816 | cval->res = 0x00e6; |
817 | break; | 817 | break; |
818 | } | 818 | } |
819 | if (strcmp(kctl->id.name, "Effect Volume") == 0 || | 819 | if (strcmp(kctl->id.name, "Effect Volume") == 0 || |
820 | strcmp(kctl->id.name, "Effect Feedback Volume") == 0) { | 820 | strcmp(kctl->id.name, "Effect Feedback Volume") == 0) { |
821 | cval->min = 0x00; | 821 | cval->min = 0x00; |
822 | cval->max = 0xff; | 822 | cval->max = 0xff; |
823 | break; | 823 | break; |
824 | } | 824 | } |
825 | if (strstr(kctl->id.name, "Effect Return") != NULL) { | 825 | if (strstr(kctl->id.name, "Effect Return") != NULL) { |
826 | cval->min = 0xb706; | 826 | cval->min = 0xb706; |
827 | cval->max = 0xff7b; | 827 | cval->max = 0xff7b; |
828 | cval->res = 0x0073; | 828 | cval->res = 0x0073; |
829 | break; | 829 | break; |
830 | } | 830 | } |
831 | if ((strstr(kctl->id.name, "Playback Volume") != NULL) || | 831 | if ((strstr(kctl->id.name, "Playback Volume") != NULL) || |
832 | (strstr(kctl->id.name, "Effect Send") != NULL)) { | 832 | (strstr(kctl->id.name, "Effect Send") != NULL)) { |
833 | cval->min = 0xb5fb; /* -73 dB = 0xb6ff */ | 833 | cval->min = 0xb5fb; /* -73 dB = 0xb6ff */ |
834 | cval->max = 0xfcfe; | 834 | cval->max = 0xfcfe; |
835 | cval->res = 0x0073; | 835 | cval->res = 0x0073; |
836 | } | 836 | } |
837 | break; | 837 | break; |
838 | 838 | ||
839 | case USB_ID(0x0763, 0x2081): /* M-Audio Fast Track Ultra 8R */ | 839 | case USB_ID(0x0763, 0x2081): /* M-Audio Fast Track Ultra 8R */ |
840 | case USB_ID(0x0763, 0x2080): /* M-Audio Fast Track Ultra */ | 840 | case USB_ID(0x0763, 0x2080): /* M-Audio Fast Track Ultra */ |
841 | if (strcmp(kctl->id.name, "Effect Duration") == 0) { | 841 | if (strcmp(kctl->id.name, "Effect Duration") == 0) { |
842 | snd_printk(KERN_INFO | 842 | snd_printk(KERN_INFO |
843 | "usb-audio: set quirk for FTU Effect Duration\n"); | 843 | "usb-audio: set quirk for FTU Effect Duration\n"); |
844 | cval->min = 0x0000; | 844 | cval->min = 0x0000; |
845 | cval->max = 0x7f00; | 845 | cval->max = 0x7f00; |
846 | cval->res = 0x0100; | 846 | cval->res = 0x0100; |
847 | break; | 847 | break; |
848 | } | 848 | } |
849 | if (strcmp(kctl->id.name, "Effect Volume") == 0 || | 849 | if (strcmp(kctl->id.name, "Effect Volume") == 0 || |
850 | strcmp(kctl->id.name, "Effect Feedback Volume") == 0) { | 850 | strcmp(kctl->id.name, "Effect Feedback Volume") == 0) { |
851 | snd_printk(KERN_INFO | 851 | snd_printk(KERN_INFO |
852 | "usb-audio: set quirks for FTU Effect Feedback/Volume\n"); | 852 | "usb-audio: set quirks for FTU Effect Feedback/Volume\n"); |
853 | cval->min = 0x00; | 853 | cval->min = 0x00; |
854 | cval->max = 0x7f; | 854 | cval->max = 0x7f; |
855 | break; | 855 | break; |
856 | } | 856 | } |
857 | break; | 857 | break; |
858 | 858 | ||
859 | case USB_ID(0x0471, 0x0101): | 859 | case USB_ID(0x0471, 0x0101): |
860 | case USB_ID(0x0471, 0x0104): | 860 | case USB_ID(0x0471, 0x0104): |
861 | case USB_ID(0x0471, 0x0105): | 861 | case USB_ID(0x0471, 0x0105): |
862 | case USB_ID(0x0672, 0x1041): | 862 | case USB_ID(0x0672, 0x1041): |
863 | /* quirk for UDA1321/N101. | 863 | /* quirk for UDA1321/N101. |
864 | * note that detection between firmware 2.1.1.7 (N101) | 864 | * note that detection between firmware 2.1.1.7 (N101) |
865 | * and later 2.1.1.21 is not very clear from datasheets. | 865 | * and later 2.1.1.21 is not very clear from datasheets. |
866 | * I hope that the min value is -15360 for newer firmware --jk | 866 | * I hope that the min value is -15360 for newer firmware --jk |
867 | */ | 867 | */ |
868 | if (!strcmp(kctl->id.name, "PCM Playback Volume") && | 868 | if (!strcmp(kctl->id.name, "PCM Playback Volume") && |
869 | cval->min == -15616) { | 869 | cval->min == -15616) { |
870 | snd_printk(KERN_INFO | 870 | snd_printk(KERN_INFO |
871 | "set volume quirk for UDA1321/N101 chip\n"); | 871 | "set volume quirk for UDA1321/N101 chip\n"); |
872 | cval->max = -256; | 872 | cval->max = -256; |
873 | } | 873 | } |
874 | break; | 874 | break; |
875 | 875 | ||
876 | case USB_ID(0x046d, 0x09a4): | 876 | case USB_ID(0x046d, 0x09a4): |
877 | if (!strcmp(kctl->id.name, "Mic Capture Volume")) { | 877 | if (!strcmp(kctl->id.name, "Mic Capture Volume")) { |
878 | snd_printk(KERN_INFO | 878 | snd_printk(KERN_INFO |
879 | "set volume quirk for QuickCam E3500\n"); | 879 | "set volume quirk for QuickCam E3500\n"); |
880 | cval->min = 6080; | 880 | cval->min = 6080; |
881 | cval->max = 8768; | 881 | cval->max = 8768; |
882 | cval->res = 192; | 882 | cval->res = 192; |
883 | } | 883 | } |
884 | break; | 884 | break; |
885 | 885 | ||
886 | case USB_ID(0x046d, 0x0808): | 886 | case USB_ID(0x046d, 0x0808): |
887 | case USB_ID(0x046d, 0x0809): | 887 | case USB_ID(0x046d, 0x0809): |
888 | case USB_ID(0x046d, 0x081b): /* HD Webcam c310 */ | ||
888 | case USB_ID(0x046d, 0x081d): /* HD Webcam c510 */ | 889 | case USB_ID(0x046d, 0x081d): /* HD Webcam c510 */ |
889 | case USB_ID(0x046d, 0x0825): /* HD Webcam c270 */ | 890 | case USB_ID(0x046d, 0x0825): /* HD Webcam c270 */ |
890 | case USB_ID(0x046d, 0x0991): | 891 | case USB_ID(0x046d, 0x0991): |
891 | /* Most audio usb devices lie about volume resolution. | 892 | /* Most audio usb devices lie about volume resolution. |
892 | * Most Logitech webcams have res = 384. | 893 | * Most Logitech webcams have res = 384. |
893 | * Proboly there is some logitech magic behind this number --fishor | 894 | * Proboly there is some logitech magic behind this number --fishor |
894 | */ | 895 | */ |
895 | if (!strcmp(kctl->id.name, "Mic Capture Volume")) { | 896 | if (!strcmp(kctl->id.name, "Mic Capture Volume")) { |
896 | snd_printk(KERN_INFO | 897 | snd_printk(KERN_INFO |
897 | "set resolution quirk: cval->res = 384\n"); | 898 | "set resolution quirk: cval->res = 384\n"); |
898 | cval->res = 384; | 899 | cval->res = 384; |
899 | } | 900 | } |
900 | break; | 901 | break; |
901 | 902 | ||
902 | } | 903 | } |
903 | } | 904 | } |
904 | 905 | ||
905 | /* | 906 | /* |
906 | * retrieve the minimum and maximum values for the specified control | 907 | * retrieve the minimum and maximum values for the specified control |
907 | */ | 908 | */ |
908 | static int get_min_max_with_quirks(struct usb_mixer_elem_info *cval, | 909 | static int get_min_max_with_quirks(struct usb_mixer_elem_info *cval, |
909 | int default_min, struct snd_kcontrol *kctl) | 910 | int default_min, struct snd_kcontrol *kctl) |
910 | { | 911 | { |
911 | /* for failsafe */ | 912 | /* for failsafe */ |
912 | cval->min = default_min; | 913 | cval->min = default_min; |
913 | cval->max = cval->min + 1; | 914 | cval->max = cval->min + 1; |
914 | cval->res = 1; | 915 | cval->res = 1; |
915 | cval->dBmin = cval->dBmax = 0; | 916 | cval->dBmin = cval->dBmax = 0; |
916 | 917 | ||
917 | if (cval->val_type == USB_MIXER_BOOLEAN || | 918 | if (cval->val_type == USB_MIXER_BOOLEAN || |
918 | cval->val_type == USB_MIXER_INV_BOOLEAN) { | 919 | cval->val_type == USB_MIXER_INV_BOOLEAN) { |
919 | cval->initialized = 1; | 920 | cval->initialized = 1; |
920 | } else { | 921 | } else { |
921 | int minchn = 0; | 922 | int minchn = 0; |
922 | if (cval->cmask) { | 923 | if (cval->cmask) { |
923 | int i; | 924 | int i; |
924 | for (i = 0; i < MAX_CHANNELS; i++) | 925 | for (i = 0; i < MAX_CHANNELS; i++) |
925 | if (cval->cmask & (1 << i)) { | 926 | if (cval->cmask & (1 << i)) { |
926 | minchn = i + 1; | 927 | minchn = i + 1; |
927 | break; | 928 | break; |
928 | } | 929 | } |
929 | } | 930 | } |
930 | if (get_ctl_value(cval, UAC_GET_MAX, (cval->control << 8) | minchn, &cval->max) < 0 || | 931 | if (get_ctl_value(cval, UAC_GET_MAX, (cval->control << 8) | minchn, &cval->max) < 0 || |
931 | get_ctl_value(cval, UAC_GET_MIN, (cval->control << 8) | minchn, &cval->min) < 0) { | 932 | get_ctl_value(cval, UAC_GET_MIN, (cval->control << 8) | minchn, &cval->min) < 0) { |
932 | snd_printd(KERN_ERR "%d:%d: cannot get min/max values for control %d (id %d)\n", | 933 | snd_printd(KERN_ERR "%d:%d: cannot get min/max values for control %d (id %d)\n", |
933 | cval->id, snd_usb_ctrl_intf(cval->mixer->chip), cval->control, cval->id); | 934 | cval->id, snd_usb_ctrl_intf(cval->mixer->chip), cval->control, cval->id); |
934 | return -EINVAL; | 935 | return -EINVAL; |
935 | } | 936 | } |
936 | if (get_ctl_value(cval, UAC_GET_RES, (cval->control << 8) | minchn, &cval->res) < 0) { | 937 | if (get_ctl_value(cval, UAC_GET_RES, (cval->control << 8) | minchn, &cval->res) < 0) { |
937 | cval->res = 1; | 938 | cval->res = 1; |
938 | } else { | 939 | } else { |
939 | int last_valid_res = cval->res; | 940 | int last_valid_res = cval->res; |
940 | 941 | ||
941 | while (cval->res > 1) { | 942 | while (cval->res > 1) { |
942 | if (snd_usb_mixer_set_ctl_value(cval, UAC_SET_RES, | 943 | if (snd_usb_mixer_set_ctl_value(cval, UAC_SET_RES, |
943 | (cval->control << 8) | minchn, cval->res / 2) < 0) | 944 | (cval->control << 8) | minchn, cval->res / 2) < 0) |
944 | break; | 945 | break; |
945 | cval->res /= 2; | 946 | cval->res /= 2; |
946 | } | 947 | } |
947 | if (get_ctl_value(cval, UAC_GET_RES, (cval->control << 8) | minchn, &cval->res) < 0) | 948 | if (get_ctl_value(cval, UAC_GET_RES, (cval->control << 8) | minchn, &cval->res) < 0) |
948 | cval->res = last_valid_res; | 949 | cval->res = last_valid_res; |
949 | } | 950 | } |
950 | if (cval->res == 0) | 951 | if (cval->res == 0) |
951 | cval->res = 1; | 952 | cval->res = 1; |
952 | 953 | ||
953 | /* Additional checks for the proper resolution | 954 | /* Additional checks for the proper resolution |
954 | * | 955 | * |
955 | * Some devices report smaller resolutions than actually | 956 | * Some devices report smaller resolutions than actually |
956 | * reacting. They don't return errors but simply clip | 957 | * reacting. They don't return errors but simply clip |
957 | * to the lower aligned value. | 958 | * to the lower aligned value. |
958 | */ | 959 | */ |
959 | if (cval->min + cval->res < cval->max) { | 960 | if (cval->min + cval->res < cval->max) { |
960 | int last_valid_res = cval->res; | 961 | int last_valid_res = cval->res; |
961 | int saved, test, check; | 962 | int saved, test, check; |
962 | get_cur_mix_raw(cval, minchn, &saved); | 963 | get_cur_mix_raw(cval, minchn, &saved); |
963 | for (;;) { | 964 | for (;;) { |
964 | test = saved; | 965 | test = saved; |
965 | if (test < cval->max) | 966 | if (test < cval->max) |
966 | test += cval->res; | 967 | test += cval->res; |
967 | else | 968 | else |
968 | test -= cval->res; | 969 | test -= cval->res; |
969 | if (test < cval->min || test > cval->max || | 970 | if (test < cval->min || test > cval->max || |
970 | set_cur_mix_value(cval, minchn, 0, test) || | 971 | set_cur_mix_value(cval, minchn, 0, test) || |
971 | get_cur_mix_raw(cval, minchn, &check)) { | 972 | get_cur_mix_raw(cval, minchn, &check)) { |
972 | cval->res = last_valid_res; | 973 | cval->res = last_valid_res; |
973 | break; | 974 | break; |
974 | } | 975 | } |
975 | if (test == check) | 976 | if (test == check) |
976 | break; | 977 | break; |
977 | cval->res *= 2; | 978 | cval->res *= 2; |
978 | } | 979 | } |
979 | set_cur_mix_value(cval, minchn, 0, saved); | 980 | set_cur_mix_value(cval, minchn, 0, saved); |
980 | } | 981 | } |
981 | 982 | ||
982 | cval->initialized = 1; | 983 | cval->initialized = 1; |
983 | } | 984 | } |
984 | 985 | ||
985 | if (kctl) | 986 | if (kctl) |
986 | volume_control_quirks(cval, kctl); | 987 | volume_control_quirks(cval, kctl); |
987 | 988 | ||
988 | /* USB descriptions contain the dB scale in 1/256 dB unit | 989 | /* USB descriptions contain the dB scale in 1/256 dB unit |
989 | * while ALSA TLV contains in 1/100 dB unit | 990 | * while ALSA TLV contains in 1/100 dB unit |
990 | */ | 991 | */ |
991 | cval->dBmin = (convert_signed_value(cval, cval->min) * 100) / 256; | 992 | cval->dBmin = (convert_signed_value(cval, cval->min) * 100) / 256; |
992 | cval->dBmax = (convert_signed_value(cval, cval->max) * 100) / 256; | 993 | cval->dBmax = (convert_signed_value(cval, cval->max) * 100) / 256; |
993 | if (cval->dBmin > cval->dBmax) { | 994 | if (cval->dBmin > cval->dBmax) { |
994 | /* something is wrong; assume it's either from/to 0dB */ | 995 | /* something is wrong; assume it's either from/to 0dB */ |
995 | if (cval->dBmin < 0) | 996 | if (cval->dBmin < 0) |
996 | cval->dBmax = 0; | 997 | cval->dBmax = 0; |
997 | else if (cval->dBmin > 0) | 998 | else if (cval->dBmin > 0) |
998 | cval->dBmin = 0; | 999 | cval->dBmin = 0; |
999 | if (cval->dBmin > cval->dBmax) { | 1000 | if (cval->dBmin > cval->dBmax) { |
1000 | /* totally crap, return an error */ | 1001 | /* totally crap, return an error */ |
1001 | return -EINVAL; | 1002 | return -EINVAL; |
1002 | } | 1003 | } |
1003 | } | 1004 | } |
1004 | 1005 | ||
1005 | return 0; | 1006 | return 0; |
1006 | } | 1007 | } |
1007 | 1008 | ||
1008 | #define get_min_max(cval, def) get_min_max_with_quirks(cval, def, NULL) | 1009 | #define get_min_max(cval, def) get_min_max_with_quirks(cval, def, NULL) |
1009 | 1010 | ||
1010 | /* get a feature/mixer unit info */ | 1011 | /* get a feature/mixer unit info */ |
1011 | static int mixer_ctl_feature_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 1012 | static int mixer_ctl_feature_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) |
1012 | { | 1013 | { |
1013 | struct usb_mixer_elem_info *cval = kcontrol->private_data; | 1014 | struct usb_mixer_elem_info *cval = kcontrol->private_data; |
1014 | 1015 | ||
1015 | if (cval->val_type == USB_MIXER_BOOLEAN || | 1016 | if (cval->val_type == USB_MIXER_BOOLEAN || |
1016 | cval->val_type == USB_MIXER_INV_BOOLEAN) | 1017 | cval->val_type == USB_MIXER_INV_BOOLEAN) |
1017 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | 1018 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; |
1018 | else | 1019 | else |
1019 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | 1020 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; |
1020 | uinfo->count = cval->channels; | 1021 | uinfo->count = cval->channels; |
1021 | if (cval->val_type == USB_MIXER_BOOLEAN || | 1022 | if (cval->val_type == USB_MIXER_BOOLEAN || |
1022 | cval->val_type == USB_MIXER_INV_BOOLEAN) { | 1023 | cval->val_type == USB_MIXER_INV_BOOLEAN) { |
1023 | uinfo->value.integer.min = 0; | 1024 | uinfo->value.integer.min = 0; |
1024 | uinfo->value.integer.max = 1; | 1025 | uinfo->value.integer.max = 1; |
1025 | } else { | 1026 | } else { |
1026 | if (!cval->initialized) { | 1027 | if (!cval->initialized) { |
1027 | get_min_max_with_quirks(cval, 0, kcontrol); | 1028 | get_min_max_with_quirks(cval, 0, kcontrol); |
1028 | if (cval->initialized && cval->dBmin >= cval->dBmax) { | 1029 | if (cval->initialized && cval->dBmin >= cval->dBmax) { |
1029 | kcontrol->vd[0].access &= | 1030 | kcontrol->vd[0].access &= |
1030 | ~(SNDRV_CTL_ELEM_ACCESS_TLV_READ | | 1031 | ~(SNDRV_CTL_ELEM_ACCESS_TLV_READ | |
1031 | SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK); | 1032 | SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK); |
1032 | snd_ctl_notify(cval->mixer->chip->card, | 1033 | snd_ctl_notify(cval->mixer->chip->card, |
1033 | SNDRV_CTL_EVENT_MASK_INFO, | 1034 | SNDRV_CTL_EVENT_MASK_INFO, |
1034 | &kcontrol->id); | 1035 | &kcontrol->id); |
1035 | } | 1036 | } |
1036 | } | 1037 | } |
1037 | uinfo->value.integer.min = 0; | 1038 | uinfo->value.integer.min = 0; |
1038 | uinfo->value.integer.max = | 1039 | uinfo->value.integer.max = |
1039 | (cval->max - cval->min + cval->res - 1) / cval->res; | 1040 | (cval->max - cval->min + cval->res - 1) / cval->res; |
1040 | } | 1041 | } |
1041 | return 0; | 1042 | return 0; |
1042 | } | 1043 | } |
1043 | 1044 | ||
1044 | /* get the current value from feature/mixer unit */ | 1045 | /* get the current value from feature/mixer unit */ |
1045 | static int mixer_ctl_feature_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 1046 | static int mixer_ctl_feature_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
1046 | { | 1047 | { |
1047 | struct usb_mixer_elem_info *cval = kcontrol->private_data; | 1048 | struct usb_mixer_elem_info *cval = kcontrol->private_data; |
1048 | int c, cnt, val, err; | 1049 | int c, cnt, val, err; |
1049 | 1050 | ||
1050 | ucontrol->value.integer.value[0] = cval->min; | 1051 | ucontrol->value.integer.value[0] = cval->min; |
1051 | if (cval->cmask) { | 1052 | if (cval->cmask) { |
1052 | cnt = 0; | 1053 | cnt = 0; |
1053 | for (c = 0; c < MAX_CHANNELS; c++) { | 1054 | for (c = 0; c < MAX_CHANNELS; c++) { |
1054 | if (!(cval->cmask & (1 << c))) | 1055 | if (!(cval->cmask & (1 << c))) |
1055 | continue; | 1056 | continue; |
1056 | err = get_cur_mix_value(cval, c + 1, cnt, &val); | 1057 | err = get_cur_mix_value(cval, c + 1, cnt, &val); |
1057 | if (err < 0) | 1058 | if (err < 0) |
1058 | return cval->mixer->ignore_ctl_error ? 0 : err; | 1059 | return cval->mixer->ignore_ctl_error ? 0 : err; |
1059 | val = get_relative_value(cval, val); | 1060 | val = get_relative_value(cval, val); |
1060 | ucontrol->value.integer.value[cnt] = val; | 1061 | ucontrol->value.integer.value[cnt] = val; |
1061 | cnt++; | 1062 | cnt++; |
1062 | } | 1063 | } |
1063 | return 0; | 1064 | return 0; |
1064 | } else { | 1065 | } else { |
1065 | /* master channel */ | 1066 | /* master channel */ |
1066 | err = get_cur_mix_value(cval, 0, 0, &val); | 1067 | err = get_cur_mix_value(cval, 0, 0, &val); |
1067 | if (err < 0) | 1068 | if (err < 0) |
1068 | return cval->mixer->ignore_ctl_error ? 0 : err; | 1069 | return cval->mixer->ignore_ctl_error ? 0 : err; |
1069 | val = get_relative_value(cval, val); | 1070 | val = get_relative_value(cval, val); |
1070 | ucontrol->value.integer.value[0] = val; | 1071 | ucontrol->value.integer.value[0] = val; |
1071 | } | 1072 | } |
1072 | return 0; | 1073 | return 0; |
1073 | } | 1074 | } |
1074 | 1075 | ||
1075 | /* put the current value to feature/mixer unit */ | 1076 | /* put the current value to feature/mixer unit */ |
1076 | static int mixer_ctl_feature_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 1077 | static int mixer_ctl_feature_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
1077 | { | 1078 | { |
1078 | struct usb_mixer_elem_info *cval = kcontrol->private_data; | 1079 | struct usb_mixer_elem_info *cval = kcontrol->private_data; |
1079 | int c, cnt, val, oval, err; | 1080 | int c, cnt, val, oval, err; |
1080 | int changed = 0; | 1081 | int changed = 0; |
1081 | 1082 | ||
1082 | if (cval->cmask) { | 1083 | if (cval->cmask) { |
1083 | cnt = 0; | 1084 | cnt = 0; |
1084 | for (c = 0; c < MAX_CHANNELS; c++) { | 1085 | for (c = 0; c < MAX_CHANNELS; c++) { |
1085 | if (!(cval->cmask & (1 << c))) | 1086 | if (!(cval->cmask & (1 << c))) |
1086 | continue; | 1087 | continue; |
1087 | err = get_cur_mix_value(cval, c + 1, cnt, &oval); | 1088 | err = get_cur_mix_value(cval, c + 1, cnt, &oval); |
1088 | if (err < 0) | 1089 | if (err < 0) |
1089 | return cval->mixer->ignore_ctl_error ? 0 : err; | 1090 | return cval->mixer->ignore_ctl_error ? 0 : err; |
1090 | val = ucontrol->value.integer.value[cnt]; | 1091 | val = ucontrol->value.integer.value[cnt]; |
1091 | val = get_abs_value(cval, val); | 1092 | val = get_abs_value(cval, val); |
1092 | if (oval != val) { | 1093 | if (oval != val) { |
1093 | set_cur_mix_value(cval, c + 1, cnt, val); | 1094 | set_cur_mix_value(cval, c + 1, cnt, val); |
1094 | changed = 1; | 1095 | changed = 1; |
1095 | } | 1096 | } |
1096 | cnt++; | 1097 | cnt++; |
1097 | } | 1098 | } |
1098 | } else { | 1099 | } else { |
1099 | /* master channel */ | 1100 | /* master channel */ |
1100 | err = get_cur_mix_value(cval, 0, 0, &oval); | 1101 | err = get_cur_mix_value(cval, 0, 0, &oval); |
1101 | if (err < 0) | 1102 | if (err < 0) |
1102 | return cval->mixer->ignore_ctl_error ? 0 : err; | 1103 | return cval->mixer->ignore_ctl_error ? 0 : err; |
1103 | val = ucontrol->value.integer.value[0]; | 1104 | val = ucontrol->value.integer.value[0]; |
1104 | val = get_abs_value(cval, val); | 1105 | val = get_abs_value(cval, val); |
1105 | if (val != oval) { | 1106 | if (val != oval) { |
1106 | set_cur_mix_value(cval, 0, 0, val); | 1107 | set_cur_mix_value(cval, 0, 0, val); |
1107 | changed = 1; | 1108 | changed = 1; |
1108 | } | 1109 | } |
1109 | } | 1110 | } |
1110 | return changed; | 1111 | return changed; |
1111 | } | 1112 | } |
1112 | 1113 | ||
1113 | static struct snd_kcontrol_new usb_feature_unit_ctl = { | 1114 | static struct snd_kcontrol_new usb_feature_unit_ctl = { |
1114 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 1115 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
1115 | .name = "", /* will be filled later manually */ | 1116 | .name = "", /* will be filled later manually */ |
1116 | .info = mixer_ctl_feature_info, | 1117 | .info = mixer_ctl_feature_info, |
1117 | .get = mixer_ctl_feature_get, | 1118 | .get = mixer_ctl_feature_get, |
1118 | .put = mixer_ctl_feature_put, | 1119 | .put = mixer_ctl_feature_put, |
1119 | }; | 1120 | }; |
1120 | 1121 | ||
1121 | /* the read-only variant */ | 1122 | /* the read-only variant */ |
1122 | static struct snd_kcontrol_new usb_feature_unit_ctl_ro = { | 1123 | static struct snd_kcontrol_new usb_feature_unit_ctl_ro = { |
1123 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 1124 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
1124 | .name = "", /* will be filled later manually */ | 1125 | .name = "", /* will be filled later manually */ |
1125 | .info = mixer_ctl_feature_info, | 1126 | .info = mixer_ctl_feature_info, |
1126 | .get = mixer_ctl_feature_get, | 1127 | .get = mixer_ctl_feature_get, |
1127 | .put = NULL, | 1128 | .put = NULL, |
1128 | }; | 1129 | }; |
1129 | 1130 | ||
1130 | /* This symbol is exported in order to allow the mixer quirks to | 1131 | /* This symbol is exported in order to allow the mixer quirks to |
1131 | * hook up to the standard feature unit control mechanism */ | 1132 | * hook up to the standard feature unit control mechanism */ |
1132 | struct snd_kcontrol_new *snd_usb_feature_unit_ctl = &usb_feature_unit_ctl; | 1133 | struct snd_kcontrol_new *snd_usb_feature_unit_ctl = &usb_feature_unit_ctl; |
1133 | 1134 | ||
1134 | /* | 1135 | /* |
1135 | * build a feature control | 1136 | * build a feature control |
1136 | */ | 1137 | */ |
1137 | 1138 | ||
1138 | static size_t append_ctl_name(struct snd_kcontrol *kctl, const char *str) | 1139 | static size_t append_ctl_name(struct snd_kcontrol *kctl, const char *str) |
1139 | { | 1140 | { |
1140 | return strlcat(kctl->id.name, str, sizeof(kctl->id.name)); | 1141 | return strlcat(kctl->id.name, str, sizeof(kctl->id.name)); |
1141 | } | 1142 | } |
1142 | 1143 | ||
1143 | /* A lot of headsets/headphones have a "Speaker" mixer. Make sure we | 1144 | /* A lot of headsets/headphones have a "Speaker" mixer. Make sure we |
1144 | rename it to "Headphone". We determine if something is a headphone | 1145 | rename it to "Headphone". We determine if something is a headphone |
1145 | similar to how udev determines form factor. */ | 1146 | similar to how udev determines form factor. */ |
1146 | static void check_no_speaker_on_headset(struct snd_kcontrol *kctl, | 1147 | static void check_no_speaker_on_headset(struct snd_kcontrol *kctl, |
1147 | struct snd_card *card) | 1148 | struct snd_card *card) |
1148 | { | 1149 | { |
1149 | const char *names_to_check[] = { | 1150 | const char *names_to_check[] = { |
1150 | "Headset", "headset", "Headphone", "headphone", NULL}; | 1151 | "Headset", "headset", "Headphone", "headphone", NULL}; |
1151 | const char **s; | 1152 | const char **s; |
1152 | bool found = 0; | 1153 | bool found = 0; |
1153 | 1154 | ||
1154 | if (strcmp("Speaker", kctl->id.name)) | 1155 | if (strcmp("Speaker", kctl->id.name)) |
1155 | return; | 1156 | return; |
1156 | 1157 | ||
1157 | for (s = names_to_check; *s; s++) | 1158 | for (s = names_to_check; *s; s++) |
1158 | if (strstr(card->shortname, *s)) { | 1159 | if (strstr(card->shortname, *s)) { |
1159 | found = 1; | 1160 | found = 1; |
1160 | break; | 1161 | break; |
1161 | } | 1162 | } |
1162 | 1163 | ||
1163 | if (!found) | 1164 | if (!found) |
1164 | return; | 1165 | return; |
1165 | 1166 | ||
1166 | strlcpy(kctl->id.name, "Headphone", sizeof(kctl->id.name)); | 1167 | strlcpy(kctl->id.name, "Headphone", sizeof(kctl->id.name)); |
1167 | } | 1168 | } |
1168 | 1169 | ||
1169 | static void build_feature_ctl(struct mixer_build *state, void *raw_desc, | 1170 | static void build_feature_ctl(struct mixer_build *state, void *raw_desc, |
1170 | unsigned int ctl_mask, int control, | 1171 | unsigned int ctl_mask, int control, |
1171 | struct usb_audio_term *iterm, int unitid, | 1172 | struct usb_audio_term *iterm, int unitid, |
1172 | int readonly_mask) | 1173 | int readonly_mask) |
1173 | { | 1174 | { |
1174 | struct uac_feature_unit_descriptor *desc = raw_desc; | 1175 | struct uac_feature_unit_descriptor *desc = raw_desc; |
1175 | unsigned int len = 0; | 1176 | unsigned int len = 0; |
1176 | int mapped_name = 0; | 1177 | int mapped_name = 0; |
1177 | int nameid = uac_feature_unit_iFeature(desc); | 1178 | int nameid = uac_feature_unit_iFeature(desc); |
1178 | struct snd_kcontrol *kctl; | 1179 | struct snd_kcontrol *kctl; |
1179 | struct usb_mixer_elem_info *cval; | 1180 | struct usb_mixer_elem_info *cval; |
1180 | const struct usbmix_name_map *map; | 1181 | const struct usbmix_name_map *map; |
1181 | unsigned int range; | 1182 | unsigned int range; |
1182 | 1183 | ||
1183 | control++; /* change from zero-based to 1-based value */ | 1184 | control++; /* change from zero-based to 1-based value */ |
1184 | 1185 | ||
1185 | if (control == UAC_FU_GRAPHIC_EQUALIZER) { | 1186 | if (control == UAC_FU_GRAPHIC_EQUALIZER) { |
1186 | /* FIXME: not supported yet */ | 1187 | /* FIXME: not supported yet */ |
1187 | return; | 1188 | return; |
1188 | } | 1189 | } |
1189 | 1190 | ||
1190 | map = find_map(state, unitid, control); | 1191 | map = find_map(state, unitid, control); |
1191 | if (check_ignored_ctl(map)) | 1192 | if (check_ignored_ctl(map)) |
1192 | return; | 1193 | return; |
1193 | 1194 | ||
1194 | cval = kzalloc(sizeof(*cval), GFP_KERNEL); | 1195 | cval = kzalloc(sizeof(*cval), GFP_KERNEL); |
1195 | if (! cval) { | 1196 | if (! cval) { |
1196 | snd_printk(KERN_ERR "cannot malloc kcontrol\n"); | 1197 | snd_printk(KERN_ERR "cannot malloc kcontrol\n"); |
1197 | return; | 1198 | return; |
1198 | } | 1199 | } |
1199 | cval->mixer = state->mixer; | 1200 | cval->mixer = state->mixer; |
1200 | cval->id = unitid; | 1201 | cval->id = unitid; |
1201 | cval->control = control; | 1202 | cval->control = control; |
1202 | cval->cmask = ctl_mask; | 1203 | cval->cmask = ctl_mask; |
1203 | cval->val_type = audio_feature_info[control-1].type; | 1204 | cval->val_type = audio_feature_info[control-1].type; |
1204 | if (ctl_mask == 0) { | 1205 | if (ctl_mask == 0) { |
1205 | cval->channels = 1; /* master channel */ | 1206 | cval->channels = 1; /* master channel */ |
1206 | cval->master_readonly = readonly_mask; | 1207 | cval->master_readonly = readonly_mask; |
1207 | } else { | 1208 | } else { |
1208 | int i, c = 0; | 1209 | int i, c = 0; |
1209 | for (i = 0; i < 16; i++) | 1210 | for (i = 0; i < 16; i++) |
1210 | if (ctl_mask & (1 << i)) | 1211 | if (ctl_mask & (1 << i)) |
1211 | c++; | 1212 | c++; |
1212 | cval->channels = c; | 1213 | cval->channels = c; |
1213 | cval->ch_readonly = readonly_mask; | 1214 | cval->ch_readonly = readonly_mask; |
1214 | } | 1215 | } |
1215 | 1216 | ||
1216 | /* if all channels in the mask are marked read-only, make the control | 1217 | /* if all channels in the mask are marked read-only, make the control |
1217 | * read-only. set_cur_mix_value() will check the mask again and won't | 1218 | * read-only. set_cur_mix_value() will check the mask again and won't |
1218 | * issue write commands to read-only channels. */ | 1219 | * issue write commands to read-only channels. */ |
1219 | if (cval->channels == readonly_mask) | 1220 | if (cval->channels == readonly_mask) |
1220 | kctl = snd_ctl_new1(&usb_feature_unit_ctl_ro, cval); | 1221 | kctl = snd_ctl_new1(&usb_feature_unit_ctl_ro, cval); |
1221 | else | 1222 | else |
1222 | kctl = snd_ctl_new1(&usb_feature_unit_ctl, cval); | 1223 | kctl = snd_ctl_new1(&usb_feature_unit_ctl, cval); |
1223 | 1224 | ||
1224 | if (! kctl) { | 1225 | if (! kctl) { |
1225 | snd_printk(KERN_ERR "cannot malloc kcontrol\n"); | 1226 | snd_printk(KERN_ERR "cannot malloc kcontrol\n"); |
1226 | kfree(cval); | 1227 | kfree(cval); |
1227 | return; | 1228 | return; |
1228 | } | 1229 | } |
1229 | kctl->private_free = usb_mixer_elem_free; | 1230 | kctl->private_free = usb_mixer_elem_free; |
1230 | 1231 | ||
1231 | len = check_mapped_name(map, kctl->id.name, sizeof(kctl->id.name)); | 1232 | len = check_mapped_name(map, kctl->id.name, sizeof(kctl->id.name)); |
1232 | mapped_name = len != 0; | 1233 | mapped_name = len != 0; |
1233 | if (! len && nameid) | 1234 | if (! len && nameid) |
1234 | len = snd_usb_copy_string_desc(state, nameid, | 1235 | len = snd_usb_copy_string_desc(state, nameid, |
1235 | kctl->id.name, sizeof(kctl->id.name)); | 1236 | kctl->id.name, sizeof(kctl->id.name)); |
1236 | 1237 | ||
1237 | switch (control) { | 1238 | switch (control) { |
1238 | case UAC_FU_MUTE: | 1239 | case UAC_FU_MUTE: |
1239 | case UAC_FU_VOLUME: | 1240 | case UAC_FU_VOLUME: |
1240 | /* determine the control name. the rule is: | 1241 | /* determine the control name. the rule is: |
1241 | * - if a name id is given in descriptor, use it. | 1242 | * - if a name id is given in descriptor, use it. |
1242 | * - if the connected input can be determined, then use the name | 1243 | * - if the connected input can be determined, then use the name |
1243 | * of terminal type. | 1244 | * of terminal type. |
1244 | * - if the connected output can be determined, use it. | 1245 | * - if the connected output can be determined, use it. |
1245 | * - otherwise, anonymous name. | 1246 | * - otherwise, anonymous name. |
1246 | */ | 1247 | */ |
1247 | if (! len) { | 1248 | if (! len) { |
1248 | len = get_term_name(state, iterm, kctl->id.name, sizeof(kctl->id.name), 1); | 1249 | len = get_term_name(state, iterm, kctl->id.name, sizeof(kctl->id.name), 1); |
1249 | if (! len) | 1250 | if (! len) |
1250 | len = get_term_name(state, &state->oterm, kctl->id.name, sizeof(kctl->id.name), 1); | 1251 | len = get_term_name(state, &state->oterm, kctl->id.name, sizeof(kctl->id.name), 1); |
1251 | if (! len) | 1252 | if (! len) |
1252 | len = snprintf(kctl->id.name, sizeof(kctl->id.name), | 1253 | len = snprintf(kctl->id.name, sizeof(kctl->id.name), |
1253 | "Feature %d", unitid); | 1254 | "Feature %d", unitid); |
1254 | } | 1255 | } |
1255 | 1256 | ||
1256 | if (!mapped_name) | 1257 | if (!mapped_name) |
1257 | check_no_speaker_on_headset(kctl, state->mixer->chip->card); | 1258 | check_no_speaker_on_headset(kctl, state->mixer->chip->card); |
1258 | 1259 | ||
1259 | /* determine the stream direction: | 1260 | /* determine the stream direction: |
1260 | * if the connected output is USB stream, then it's likely a | 1261 | * if the connected output is USB stream, then it's likely a |
1261 | * capture stream. otherwise it should be playback (hopefully :) | 1262 | * capture stream. otherwise it should be playback (hopefully :) |
1262 | */ | 1263 | */ |
1263 | if (! mapped_name && ! (state->oterm.type >> 16)) { | 1264 | if (! mapped_name && ! (state->oterm.type >> 16)) { |
1264 | if ((state->oterm.type & 0xff00) == 0x0100) { | 1265 | if ((state->oterm.type & 0xff00) == 0x0100) { |
1265 | len = append_ctl_name(kctl, " Capture"); | 1266 | len = append_ctl_name(kctl, " Capture"); |
1266 | } else { | 1267 | } else { |
1267 | len = append_ctl_name(kctl, " Playback"); | 1268 | len = append_ctl_name(kctl, " Playback"); |
1268 | } | 1269 | } |
1269 | } | 1270 | } |
1270 | append_ctl_name(kctl, control == UAC_FU_MUTE ? | 1271 | append_ctl_name(kctl, control == UAC_FU_MUTE ? |
1271 | " Switch" : " Volume"); | 1272 | " Switch" : " Volume"); |
1272 | break; | 1273 | break; |
1273 | default: | 1274 | default: |
1274 | if (! len) | 1275 | if (! len) |
1275 | strlcpy(kctl->id.name, audio_feature_info[control-1].name, | 1276 | strlcpy(kctl->id.name, audio_feature_info[control-1].name, |
1276 | sizeof(kctl->id.name)); | 1277 | sizeof(kctl->id.name)); |
1277 | break; | 1278 | break; |
1278 | } | 1279 | } |
1279 | 1280 | ||
1280 | /* get min/max values */ | 1281 | /* get min/max values */ |
1281 | get_min_max_with_quirks(cval, 0, kctl); | 1282 | get_min_max_with_quirks(cval, 0, kctl); |
1282 | 1283 | ||
1283 | if (control == UAC_FU_VOLUME) { | 1284 | if (control == UAC_FU_VOLUME) { |
1284 | check_mapped_dB(map, cval); | 1285 | check_mapped_dB(map, cval); |
1285 | if (cval->dBmin < cval->dBmax || !cval->initialized) { | 1286 | if (cval->dBmin < cval->dBmax || !cval->initialized) { |
1286 | kctl->tlv.c = snd_usb_mixer_vol_tlv; | 1287 | kctl->tlv.c = snd_usb_mixer_vol_tlv; |
1287 | kctl->vd[0].access |= | 1288 | kctl->vd[0].access |= |
1288 | SNDRV_CTL_ELEM_ACCESS_TLV_READ | | 1289 | SNDRV_CTL_ELEM_ACCESS_TLV_READ | |
1289 | SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK; | 1290 | SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK; |
1290 | } | 1291 | } |
1291 | } | 1292 | } |
1292 | 1293 | ||
1293 | range = (cval->max - cval->min) / cval->res; | 1294 | range = (cval->max - cval->min) / cval->res; |
1294 | /* Are there devices with volume range more than 255? I use a bit more | 1295 | /* Are there devices with volume range more than 255? I use a bit more |
1295 | * to be sure. 384 is a resolution magic number found on Logitech | 1296 | * to be sure. 384 is a resolution magic number found on Logitech |
1296 | * devices. It will definitively catch all buggy Logitech devices. | 1297 | * devices. It will definitively catch all buggy Logitech devices. |
1297 | */ | 1298 | */ |
1298 | if (range > 384) { | 1299 | if (range > 384) { |
1299 | snd_printk(KERN_WARNING "usb_audio: Warning! Unlikely big " | 1300 | snd_printk(KERN_WARNING "usb_audio: Warning! Unlikely big " |
1300 | "volume range (=%u), cval->res is probably wrong.", | 1301 | "volume range (=%u), cval->res is probably wrong.", |
1301 | range); | 1302 | range); |
1302 | snd_printk(KERN_WARNING "usb_audio: [%d] FU [%s] ch = %d, " | 1303 | snd_printk(KERN_WARNING "usb_audio: [%d] FU [%s] ch = %d, " |
1303 | "val = %d/%d/%d", cval->id, | 1304 | "val = %d/%d/%d", cval->id, |
1304 | kctl->id.name, cval->channels, | 1305 | kctl->id.name, cval->channels, |
1305 | cval->min, cval->max, cval->res); | 1306 | cval->min, cval->max, cval->res); |
1306 | } | 1307 | } |
1307 | 1308 | ||
1308 | snd_printdd(KERN_INFO "[%d] FU [%s] ch = %d, val = %d/%d/%d\n", | 1309 | snd_printdd(KERN_INFO "[%d] FU [%s] ch = %d, val = %d/%d/%d\n", |
1309 | cval->id, kctl->id.name, cval->channels, cval->min, cval->max, cval->res); | 1310 | cval->id, kctl->id.name, cval->channels, cval->min, cval->max, cval->res); |
1310 | snd_usb_mixer_add_control(state->mixer, kctl); | 1311 | snd_usb_mixer_add_control(state->mixer, kctl); |
1311 | } | 1312 | } |
1312 | 1313 | ||
1313 | 1314 | ||
1314 | 1315 | ||
1315 | /* | 1316 | /* |
1316 | * parse a feature unit | 1317 | * parse a feature unit |
1317 | * | 1318 | * |
1318 | * most of controls are defined here. | 1319 | * most of controls are defined here. |
1319 | */ | 1320 | */ |
1320 | static int parse_audio_feature_unit(struct mixer_build *state, int unitid, void *_ftr) | 1321 | static int parse_audio_feature_unit(struct mixer_build *state, int unitid, void *_ftr) |
1321 | { | 1322 | { |
1322 | int channels, i, j; | 1323 | int channels, i, j; |
1323 | struct usb_audio_term iterm; | 1324 | struct usb_audio_term iterm; |
1324 | unsigned int master_bits, first_ch_bits; | 1325 | unsigned int master_bits, first_ch_bits; |
1325 | int err, csize; | 1326 | int err, csize; |
1326 | struct uac_feature_unit_descriptor *hdr = _ftr; | 1327 | struct uac_feature_unit_descriptor *hdr = _ftr; |
1327 | __u8 *bmaControls; | 1328 | __u8 *bmaControls; |
1328 | 1329 | ||
1329 | if (state->mixer->protocol == UAC_VERSION_1) { | 1330 | if (state->mixer->protocol == UAC_VERSION_1) { |
1330 | csize = hdr->bControlSize; | 1331 | csize = hdr->bControlSize; |
1331 | if (!csize) { | 1332 | if (!csize) { |
1332 | snd_printdd(KERN_ERR "usbaudio: unit %u: " | 1333 | snd_printdd(KERN_ERR "usbaudio: unit %u: " |
1333 | "invalid bControlSize == 0\n", unitid); | 1334 | "invalid bControlSize == 0\n", unitid); |
1334 | return -EINVAL; | 1335 | return -EINVAL; |
1335 | } | 1336 | } |
1336 | channels = (hdr->bLength - 7) / csize - 1; | 1337 | channels = (hdr->bLength - 7) / csize - 1; |
1337 | bmaControls = hdr->bmaControls; | 1338 | bmaControls = hdr->bmaControls; |
1338 | if (hdr->bLength < 7 + csize) { | 1339 | if (hdr->bLength < 7 + csize) { |
1339 | snd_printk(KERN_ERR "usbaudio: unit %u: " | 1340 | snd_printk(KERN_ERR "usbaudio: unit %u: " |
1340 | "invalid UAC_FEATURE_UNIT descriptor\n", | 1341 | "invalid UAC_FEATURE_UNIT descriptor\n", |
1341 | unitid); | 1342 | unitid); |
1342 | return -EINVAL; | 1343 | return -EINVAL; |
1343 | } | 1344 | } |
1344 | } else { | 1345 | } else { |
1345 | struct uac2_feature_unit_descriptor *ftr = _ftr; | 1346 | struct uac2_feature_unit_descriptor *ftr = _ftr; |
1346 | csize = 4; | 1347 | csize = 4; |
1347 | channels = (hdr->bLength - 6) / 4 - 1; | 1348 | channels = (hdr->bLength - 6) / 4 - 1; |
1348 | bmaControls = ftr->bmaControls; | 1349 | bmaControls = ftr->bmaControls; |
1349 | if (hdr->bLength < 6 + csize) { | 1350 | if (hdr->bLength < 6 + csize) { |
1350 | snd_printk(KERN_ERR "usbaudio: unit %u: " | 1351 | snd_printk(KERN_ERR "usbaudio: unit %u: " |
1351 | "invalid UAC_FEATURE_UNIT descriptor\n", | 1352 | "invalid UAC_FEATURE_UNIT descriptor\n", |
1352 | unitid); | 1353 | unitid); |
1353 | return -EINVAL; | 1354 | return -EINVAL; |
1354 | } | 1355 | } |
1355 | } | 1356 | } |
1356 | 1357 | ||
1357 | /* parse the source unit */ | 1358 | /* parse the source unit */ |
1358 | if ((err = parse_audio_unit(state, hdr->bSourceID)) < 0) | 1359 | if ((err = parse_audio_unit(state, hdr->bSourceID)) < 0) |
1359 | return err; | 1360 | return err; |
1360 | 1361 | ||
1361 | /* determine the input source type and name */ | 1362 | /* determine the input source type and name */ |
1362 | err = check_input_term(state, hdr->bSourceID, &iterm); | 1363 | err = check_input_term(state, hdr->bSourceID, &iterm); |
1363 | if (err < 0) | 1364 | if (err < 0) |
1364 | return err; | 1365 | return err; |
1365 | 1366 | ||
1366 | master_bits = snd_usb_combine_bytes(bmaControls, csize); | 1367 | master_bits = snd_usb_combine_bytes(bmaControls, csize); |
1367 | /* master configuration quirks */ | 1368 | /* master configuration quirks */ |
1368 | switch (state->chip->usb_id) { | 1369 | switch (state->chip->usb_id) { |
1369 | case USB_ID(0x08bb, 0x2702): | 1370 | case USB_ID(0x08bb, 0x2702): |
1370 | snd_printk(KERN_INFO | 1371 | snd_printk(KERN_INFO |
1371 | "usbmixer: master volume quirk for PCM2702 chip\n"); | 1372 | "usbmixer: master volume quirk for PCM2702 chip\n"); |
1372 | /* disable non-functional volume control */ | 1373 | /* disable non-functional volume control */ |
1373 | master_bits &= ~UAC_CONTROL_BIT(UAC_FU_VOLUME); | 1374 | master_bits &= ~UAC_CONTROL_BIT(UAC_FU_VOLUME); |
1374 | break; | 1375 | break; |
1375 | case USB_ID(0x1130, 0xf211): | 1376 | case USB_ID(0x1130, 0xf211): |
1376 | snd_printk(KERN_INFO | 1377 | snd_printk(KERN_INFO |
1377 | "usbmixer: volume control quirk for Tenx TP6911 Audio Headset\n"); | 1378 | "usbmixer: volume control quirk for Tenx TP6911 Audio Headset\n"); |
1378 | /* disable non-functional volume control */ | 1379 | /* disable non-functional volume control */ |
1379 | channels = 0; | 1380 | channels = 0; |
1380 | break; | 1381 | break; |
1381 | 1382 | ||
1382 | } | 1383 | } |
1383 | if (channels > 0) | 1384 | if (channels > 0) |
1384 | first_ch_bits = snd_usb_combine_bytes(bmaControls + csize, csize); | 1385 | first_ch_bits = snd_usb_combine_bytes(bmaControls + csize, csize); |
1385 | else | 1386 | else |
1386 | first_ch_bits = 0; | 1387 | first_ch_bits = 0; |
1387 | 1388 | ||
1388 | if (state->mixer->protocol == UAC_VERSION_1) { | 1389 | if (state->mixer->protocol == UAC_VERSION_1) { |
1389 | /* check all control types */ | 1390 | /* check all control types */ |
1390 | for (i = 0; i < 10; i++) { | 1391 | for (i = 0; i < 10; i++) { |
1391 | unsigned int ch_bits = 0; | 1392 | unsigned int ch_bits = 0; |
1392 | for (j = 0; j < channels; j++) { | 1393 | for (j = 0; j < channels; j++) { |
1393 | unsigned int mask = snd_usb_combine_bytes(bmaControls + csize * (j+1), csize); | 1394 | unsigned int mask = snd_usb_combine_bytes(bmaControls + csize * (j+1), csize); |
1394 | if (mask & (1 << i)) | 1395 | if (mask & (1 << i)) |
1395 | ch_bits |= (1 << j); | 1396 | ch_bits |= (1 << j); |
1396 | } | 1397 | } |
1397 | /* audio class v1 controls are never read-only */ | 1398 | /* audio class v1 controls are never read-only */ |
1398 | if (ch_bits & 1) /* the first channel must be set (for ease of programming) */ | 1399 | if (ch_bits & 1) /* the first channel must be set (for ease of programming) */ |
1399 | build_feature_ctl(state, _ftr, ch_bits, i, &iterm, unitid, 0); | 1400 | build_feature_ctl(state, _ftr, ch_bits, i, &iterm, unitid, 0); |
1400 | if (master_bits & (1 << i)) | 1401 | if (master_bits & (1 << i)) |
1401 | build_feature_ctl(state, _ftr, 0, i, &iterm, unitid, 0); | 1402 | build_feature_ctl(state, _ftr, 0, i, &iterm, unitid, 0); |
1402 | } | 1403 | } |
1403 | } else { /* UAC_VERSION_2 */ | 1404 | } else { /* UAC_VERSION_2 */ |
1404 | for (i = 0; i < ARRAY_SIZE(audio_feature_info); i++) { | 1405 | for (i = 0; i < ARRAY_SIZE(audio_feature_info); i++) { |
1405 | unsigned int ch_bits = 0; | 1406 | unsigned int ch_bits = 0; |
1406 | unsigned int ch_read_only = 0; | 1407 | unsigned int ch_read_only = 0; |
1407 | 1408 | ||
1408 | for (j = 0; j < channels; j++) { | 1409 | for (j = 0; j < channels; j++) { |
1409 | unsigned int mask = snd_usb_combine_bytes(bmaControls + csize * (j+1), csize); | 1410 | unsigned int mask = snd_usb_combine_bytes(bmaControls + csize * (j+1), csize); |
1410 | if (uac2_control_is_readable(mask, i)) { | 1411 | if (uac2_control_is_readable(mask, i)) { |
1411 | ch_bits |= (1 << j); | 1412 | ch_bits |= (1 << j); |
1412 | if (!uac2_control_is_writeable(mask, i)) | 1413 | if (!uac2_control_is_writeable(mask, i)) |
1413 | ch_read_only |= (1 << j); | 1414 | ch_read_only |= (1 << j); |
1414 | } | 1415 | } |
1415 | } | 1416 | } |
1416 | 1417 | ||
1417 | /* NOTE: build_feature_ctl() will mark the control read-only if all channels | 1418 | /* NOTE: build_feature_ctl() will mark the control read-only if all channels |
1418 | * are marked read-only in the descriptors. Otherwise, the control will be | 1419 | * are marked read-only in the descriptors. Otherwise, the control will be |
1419 | * reported as writeable, but the driver will not actually issue a write | 1420 | * reported as writeable, but the driver will not actually issue a write |
1420 | * command for read-only channels */ | 1421 | * command for read-only channels */ |
1421 | if (ch_bits & 1) /* the first channel must be set (for ease of programming) */ | 1422 | if (ch_bits & 1) /* the first channel must be set (for ease of programming) */ |
1422 | build_feature_ctl(state, _ftr, ch_bits, i, &iterm, unitid, ch_read_only); | 1423 | build_feature_ctl(state, _ftr, ch_bits, i, &iterm, unitid, ch_read_only); |
1423 | if (uac2_control_is_readable(master_bits, i)) | 1424 | if (uac2_control_is_readable(master_bits, i)) |
1424 | build_feature_ctl(state, _ftr, 0, i, &iterm, unitid, | 1425 | build_feature_ctl(state, _ftr, 0, i, &iterm, unitid, |
1425 | !uac2_control_is_writeable(master_bits, i)); | 1426 | !uac2_control_is_writeable(master_bits, i)); |
1426 | } | 1427 | } |
1427 | } | 1428 | } |
1428 | 1429 | ||
1429 | return 0; | 1430 | return 0; |
1430 | } | 1431 | } |
1431 | 1432 | ||
1432 | 1433 | ||
1433 | /* | 1434 | /* |
1434 | * Mixer Unit | 1435 | * Mixer Unit |
1435 | */ | 1436 | */ |
1436 | 1437 | ||
1437 | /* | 1438 | /* |
1438 | * build a mixer unit control | 1439 | * build a mixer unit control |
1439 | * | 1440 | * |
1440 | * the callbacks are identical with feature unit. | 1441 | * the callbacks are identical with feature unit. |
1441 | * input channel number (zero based) is given in control field instead. | 1442 | * input channel number (zero based) is given in control field instead. |
1442 | */ | 1443 | */ |
1443 | 1444 | ||
1444 | static void build_mixer_unit_ctl(struct mixer_build *state, | 1445 | static void build_mixer_unit_ctl(struct mixer_build *state, |
1445 | struct uac_mixer_unit_descriptor *desc, | 1446 | struct uac_mixer_unit_descriptor *desc, |
1446 | int in_pin, int in_ch, int unitid, | 1447 | int in_pin, int in_ch, int unitid, |
1447 | struct usb_audio_term *iterm) | 1448 | struct usb_audio_term *iterm) |
1448 | { | 1449 | { |
1449 | struct usb_mixer_elem_info *cval; | 1450 | struct usb_mixer_elem_info *cval; |
1450 | unsigned int num_outs = uac_mixer_unit_bNrChannels(desc); | 1451 | unsigned int num_outs = uac_mixer_unit_bNrChannels(desc); |
1451 | unsigned int i, len; | 1452 | unsigned int i, len; |
1452 | struct snd_kcontrol *kctl; | 1453 | struct snd_kcontrol *kctl; |
1453 | const struct usbmix_name_map *map; | 1454 | const struct usbmix_name_map *map; |
1454 | 1455 | ||
1455 | map = find_map(state, unitid, 0); | 1456 | map = find_map(state, unitid, 0); |
1456 | if (check_ignored_ctl(map)) | 1457 | if (check_ignored_ctl(map)) |
1457 | return; | 1458 | return; |
1458 | 1459 | ||
1459 | cval = kzalloc(sizeof(*cval), GFP_KERNEL); | 1460 | cval = kzalloc(sizeof(*cval), GFP_KERNEL); |
1460 | if (! cval) | 1461 | if (! cval) |
1461 | return; | 1462 | return; |
1462 | 1463 | ||
1463 | cval->mixer = state->mixer; | 1464 | cval->mixer = state->mixer; |
1464 | cval->id = unitid; | 1465 | cval->id = unitid; |
1465 | cval->control = in_ch + 1; /* based on 1 */ | 1466 | cval->control = in_ch + 1; /* based on 1 */ |
1466 | cval->val_type = USB_MIXER_S16; | 1467 | cval->val_type = USB_MIXER_S16; |
1467 | for (i = 0; i < num_outs; i++) { | 1468 | for (i = 0; i < num_outs; i++) { |
1468 | if (check_matrix_bitmap(uac_mixer_unit_bmControls(desc, state->mixer->protocol), in_ch, i, num_outs)) { | 1469 | if (check_matrix_bitmap(uac_mixer_unit_bmControls(desc, state->mixer->protocol), in_ch, i, num_outs)) { |
1469 | cval->cmask |= (1 << i); | 1470 | cval->cmask |= (1 << i); |
1470 | cval->channels++; | 1471 | cval->channels++; |
1471 | } | 1472 | } |
1472 | } | 1473 | } |
1473 | 1474 | ||
1474 | /* get min/max values */ | 1475 | /* get min/max values */ |
1475 | get_min_max(cval, 0); | 1476 | get_min_max(cval, 0); |
1476 | 1477 | ||
1477 | kctl = snd_ctl_new1(&usb_feature_unit_ctl, cval); | 1478 | kctl = snd_ctl_new1(&usb_feature_unit_ctl, cval); |
1478 | if (! kctl) { | 1479 | if (! kctl) { |
1479 | snd_printk(KERN_ERR "cannot malloc kcontrol\n"); | 1480 | snd_printk(KERN_ERR "cannot malloc kcontrol\n"); |
1480 | kfree(cval); | 1481 | kfree(cval); |
1481 | return; | 1482 | return; |
1482 | } | 1483 | } |
1483 | kctl->private_free = usb_mixer_elem_free; | 1484 | kctl->private_free = usb_mixer_elem_free; |
1484 | 1485 | ||
1485 | len = check_mapped_name(map, kctl->id.name, sizeof(kctl->id.name)); | 1486 | len = check_mapped_name(map, kctl->id.name, sizeof(kctl->id.name)); |
1486 | if (! len) | 1487 | if (! len) |
1487 | len = get_term_name(state, iterm, kctl->id.name, sizeof(kctl->id.name), 0); | 1488 | len = get_term_name(state, iterm, kctl->id.name, sizeof(kctl->id.name), 0); |
1488 | if (! len) | 1489 | if (! len) |
1489 | len = sprintf(kctl->id.name, "Mixer Source %d", in_ch + 1); | 1490 | len = sprintf(kctl->id.name, "Mixer Source %d", in_ch + 1); |
1490 | append_ctl_name(kctl, " Volume"); | 1491 | append_ctl_name(kctl, " Volume"); |
1491 | 1492 | ||
1492 | snd_printdd(KERN_INFO "[%d] MU [%s] ch = %d, val = %d/%d\n", | 1493 | snd_printdd(KERN_INFO "[%d] MU [%s] ch = %d, val = %d/%d\n", |
1493 | cval->id, kctl->id.name, cval->channels, cval->min, cval->max); | 1494 | cval->id, kctl->id.name, cval->channels, cval->min, cval->max); |
1494 | snd_usb_mixer_add_control(state->mixer, kctl); | 1495 | snd_usb_mixer_add_control(state->mixer, kctl); |
1495 | } | 1496 | } |
1496 | 1497 | ||
1497 | 1498 | ||
1498 | /* | 1499 | /* |
1499 | * parse a mixer unit | 1500 | * parse a mixer unit |
1500 | */ | 1501 | */ |
1501 | static int parse_audio_mixer_unit(struct mixer_build *state, int unitid, void *raw_desc) | 1502 | static int parse_audio_mixer_unit(struct mixer_build *state, int unitid, void *raw_desc) |
1502 | { | 1503 | { |
1503 | struct uac_mixer_unit_descriptor *desc = raw_desc; | 1504 | struct uac_mixer_unit_descriptor *desc = raw_desc; |
1504 | struct usb_audio_term iterm; | 1505 | struct usb_audio_term iterm; |
1505 | int input_pins, num_ins, num_outs; | 1506 | int input_pins, num_ins, num_outs; |
1506 | int pin, ich, err; | 1507 | int pin, ich, err; |
1507 | 1508 | ||
1508 | if (desc->bLength < 11 || ! (input_pins = desc->bNrInPins) || ! (num_outs = uac_mixer_unit_bNrChannels(desc))) { | 1509 | if (desc->bLength < 11 || ! (input_pins = desc->bNrInPins) || ! (num_outs = uac_mixer_unit_bNrChannels(desc))) { |
1509 | snd_printk(KERN_ERR "invalid MIXER UNIT descriptor %d\n", unitid); | 1510 | snd_printk(KERN_ERR "invalid MIXER UNIT descriptor %d\n", unitid); |
1510 | return -EINVAL; | 1511 | return -EINVAL; |
1511 | } | 1512 | } |
1512 | /* no bmControls field (e.g. Maya44) -> ignore */ | 1513 | /* no bmControls field (e.g. Maya44) -> ignore */ |
1513 | if (desc->bLength <= 10 + input_pins) { | 1514 | if (desc->bLength <= 10 + input_pins) { |
1514 | snd_printdd(KERN_INFO "MU %d has no bmControls field\n", unitid); | 1515 | snd_printdd(KERN_INFO "MU %d has no bmControls field\n", unitid); |
1515 | return 0; | 1516 | return 0; |
1516 | } | 1517 | } |
1517 | 1518 | ||
1518 | num_ins = 0; | 1519 | num_ins = 0; |
1519 | ich = 0; | 1520 | ich = 0; |
1520 | for (pin = 0; pin < input_pins; pin++) { | 1521 | for (pin = 0; pin < input_pins; pin++) { |
1521 | err = parse_audio_unit(state, desc->baSourceID[pin]); | 1522 | err = parse_audio_unit(state, desc->baSourceID[pin]); |
1522 | if (err < 0) | 1523 | if (err < 0) |
1523 | continue; | 1524 | continue; |
1524 | err = check_input_term(state, desc->baSourceID[pin], &iterm); | 1525 | err = check_input_term(state, desc->baSourceID[pin], &iterm); |
1525 | if (err < 0) | 1526 | if (err < 0) |
1526 | return err; | 1527 | return err; |
1527 | num_ins += iterm.channels; | 1528 | num_ins += iterm.channels; |
1528 | for (; ich < num_ins; ++ich) { | 1529 | for (; ich < num_ins; ++ich) { |
1529 | int och, ich_has_controls = 0; | 1530 | int och, ich_has_controls = 0; |
1530 | 1531 | ||
1531 | for (och = 0; och < num_outs; ++och) { | 1532 | for (och = 0; och < num_outs; ++och) { |
1532 | if (check_matrix_bitmap(uac_mixer_unit_bmControls(desc, state->mixer->protocol), | 1533 | if (check_matrix_bitmap(uac_mixer_unit_bmControls(desc, state->mixer->protocol), |
1533 | ich, och, num_outs)) { | 1534 | ich, och, num_outs)) { |
1534 | ich_has_controls = 1; | 1535 | ich_has_controls = 1; |
1535 | break; | 1536 | break; |
1536 | } | 1537 | } |
1537 | } | 1538 | } |
1538 | if (ich_has_controls) | 1539 | if (ich_has_controls) |
1539 | build_mixer_unit_ctl(state, desc, pin, ich, | 1540 | build_mixer_unit_ctl(state, desc, pin, ich, |
1540 | unitid, &iterm); | 1541 | unitid, &iterm); |
1541 | } | 1542 | } |
1542 | } | 1543 | } |
1543 | return 0; | 1544 | return 0; |
1544 | } | 1545 | } |
1545 | 1546 | ||
1546 | 1547 | ||
1547 | /* | 1548 | /* |
1548 | * Processing Unit / Extension Unit | 1549 | * Processing Unit / Extension Unit |
1549 | */ | 1550 | */ |
1550 | 1551 | ||
1551 | /* get callback for processing/extension unit */ | 1552 | /* get callback for processing/extension unit */ |
1552 | static int mixer_ctl_procunit_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 1553 | static int mixer_ctl_procunit_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
1553 | { | 1554 | { |
1554 | struct usb_mixer_elem_info *cval = kcontrol->private_data; | 1555 | struct usb_mixer_elem_info *cval = kcontrol->private_data; |
1555 | int err, val; | 1556 | int err, val; |
1556 | 1557 | ||
1557 | err = get_cur_ctl_value(cval, cval->control << 8, &val); | 1558 | err = get_cur_ctl_value(cval, cval->control << 8, &val); |
1558 | if (err < 0 && cval->mixer->ignore_ctl_error) { | 1559 | if (err < 0 && cval->mixer->ignore_ctl_error) { |
1559 | ucontrol->value.integer.value[0] = cval->min; | 1560 | ucontrol->value.integer.value[0] = cval->min; |
1560 | return 0; | 1561 | return 0; |
1561 | } | 1562 | } |
1562 | if (err < 0) | 1563 | if (err < 0) |
1563 | return err; | 1564 | return err; |
1564 | val = get_relative_value(cval, val); | 1565 | val = get_relative_value(cval, val); |
1565 | ucontrol->value.integer.value[0] = val; | 1566 | ucontrol->value.integer.value[0] = val; |
1566 | return 0; | 1567 | return 0; |
1567 | } | 1568 | } |
1568 | 1569 | ||
1569 | /* put callback for processing/extension unit */ | 1570 | /* put callback for processing/extension unit */ |
1570 | static int mixer_ctl_procunit_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 1571 | static int mixer_ctl_procunit_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
1571 | { | 1572 | { |
1572 | struct usb_mixer_elem_info *cval = kcontrol->private_data; | 1573 | struct usb_mixer_elem_info *cval = kcontrol->private_data; |
1573 | int val, oval, err; | 1574 | int val, oval, err; |
1574 | 1575 | ||
1575 | err = get_cur_ctl_value(cval, cval->control << 8, &oval); | 1576 | err = get_cur_ctl_value(cval, cval->control << 8, &oval); |
1576 | if (err < 0) { | 1577 | if (err < 0) { |
1577 | if (cval->mixer->ignore_ctl_error) | 1578 | if (cval->mixer->ignore_ctl_error) |
1578 | return 0; | 1579 | return 0; |
1579 | return err; | 1580 | return err; |
1580 | } | 1581 | } |
1581 | val = ucontrol->value.integer.value[0]; | 1582 | val = ucontrol->value.integer.value[0]; |
1582 | val = get_abs_value(cval, val); | 1583 | val = get_abs_value(cval, val); |
1583 | if (val != oval) { | 1584 | if (val != oval) { |
1584 | set_cur_ctl_value(cval, cval->control << 8, val); | 1585 | set_cur_ctl_value(cval, cval->control << 8, val); |
1585 | return 1; | 1586 | return 1; |
1586 | } | 1587 | } |
1587 | return 0; | 1588 | return 0; |
1588 | } | 1589 | } |
1589 | 1590 | ||
1590 | /* alsa control interface for processing/extension unit */ | 1591 | /* alsa control interface for processing/extension unit */ |
1591 | static struct snd_kcontrol_new mixer_procunit_ctl = { | 1592 | static struct snd_kcontrol_new mixer_procunit_ctl = { |
1592 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 1593 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
1593 | .name = "", /* will be filled later */ | 1594 | .name = "", /* will be filled later */ |
1594 | .info = mixer_ctl_feature_info, | 1595 | .info = mixer_ctl_feature_info, |
1595 | .get = mixer_ctl_procunit_get, | 1596 | .get = mixer_ctl_procunit_get, |
1596 | .put = mixer_ctl_procunit_put, | 1597 | .put = mixer_ctl_procunit_put, |
1597 | }; | 1598 | }; |
1598 | 1599 | ||
1599 | 1600 | ||
1600 | /* | 1601 | /* |
1601 | * predefined data for processing units | 1602 | * predefined data for processing units |
1602 | */ | 1603 | */ |
1603 | struct procunit_value_info { | 1604 | struct procunit_value_info { |
1604 | int control; | 1605 | int control; |
1605 | char *suffix; | 1606 | char *suffix; |
1606 | int val_type; | 1607 | int val_type; |
1607 | int min_value; | 1608 | int min_value; |
1608 | }; | 1609 | }; |
1609 | 1610 | ||
1610 | struct procunit_info { | 1611 | struct procunit_info { |
1611 | int type; | 1612 | int type; |
1612 | char *name; | 1613 | char *name; |
1613 | struct procunit_value_info *values; | 1614 | struct procunit_value_info *values; |
1614 | }; | 1615 | }; |
1615 | 1616 | ||
1616 | static struct procunit_value_info updown_proc_info[] = { | 1617 | static struct procunit_value_info updown_proc_info[] = { |
1617 | { UAC_UD_ENABLE, "Switch", USB_MIXER_BOOLEAN }, | 1618 | { UAC_UD_ENABLE, "Switch", USB_MIXER_BOOLEAN }, |
1618 | { UAC_UD_MODE_SELECT, "Mode Select", USB_MIXER_U8, 1 }, | 1619 | { UAC_UD_MODE_SELECT, "Mode Select", USB_MIXER_U8, 1 }, |
1619 | { 0 } | 1620 | { 0 } |
1620 | }; | 1621 | }; |
1621 | static struct procunit_value_info prologic_proc_info[] = { | 1622 | static struct procunit_value_info prologic_proc_info[] = { |
1622 | { UAC_DP_ENABLE, "Switch", USB_MIXER_BOOLEAN }, | 1623 | { UAC_DP_ENABLE, "Switch", USB_MIXER_BOOLEAN }, |
1623 | { UAC_DP_MODE_SELECT, "Mode Select", USB_MIXER_U8, 1 }, | 1624 | { UAC_DP_MODE_SELECT, "Mode Select", USB_MIXER_U8, 1 }, |
1624 | { 0 } | 1625 | { 0 } |
1625 | }; | 1626 | }; |
1626 | static struct procunit_value_info threed_enh_proc_info[] = { | 1627 | static struct procunit_value_info threed_enh_proc_info[] = { |
1627 | { UAC_3D_ENABLE, "Switch", USB_MIXER_BOOLEAN }, | 1628 | { UAC_3D_ENABLE, "Switch", USB_MIXER_BOOLEAN }, |
1628 | { UAC_3D_SPACE, "Spaciousness", USB_MIXER_U8 }, | 1629 | { UAC_3D_SPACE, "Spaciousness", USB_MIXER_U8 }, |
1629 | { 0 } | 1630 | { 0 } |
1630 | }; | 1631 | }; |
1631 | static struct procunit_value_info reverb_proc_info[] = { | 1632 | static struct procunit_value_info reverb_proc_info[] = { |
1632 | { UAC_REVERB_ENABLE, "Switch", USB_MIXER_BOOLEAN }, | 1633 | { UAC_REVERB_ENABLE, "Switch", USB_MIXER_BOOLEAN }, |
1633 | { UAC_REVERB_LEVEL, "Level", USB_MIXER_U8 }, | 1634 | { UAC_REVERB_LEVEL, "Level", USB_MIXER_U8 }, |
1634 | { UAC_REVERB_TIME, "Time", USB_MIXER_U16 }, | 1635 | { UAC_REVERB_TIME, "Time", USB_MIXER_U16 }, |
1635 | { UAC_REVERB_FEEDBACK, "Feedback", USB_MIXER_U8 }, | 1636 | { UAC_REVERB_FEEDBACK, "Feedback", USB_MIXER_U8 }, |
1636 | { 0 } | 1637 | { 0 } |
1637 | }; | 1638 | }; |
1638 | static struct procunit_value_info chorus_proc_info[] = { | 1639 | static struct procunit_value_info chorus_proc_info[] = { |
1639 | { UAC_CHORUS_ENABLE, "Switch", USB_MIXER_BOOLEAN }, | 1640 | { UAC_CHORUS_ENABLE, "Switch", USB_MIXER_BOOLEAN }, |
1640 | { UAC_CHORUS_LEVEL, "Level", USB_MIXER_U8 }, | 1641 | { UAC_CHORUS_LEVEL, "Level", USB_MIXER_U8 }, |
1641 | { UAC_CHORUS_RATE, "Rate", USB_MIXER_U16 }, | 1642 | { UAC_CHORUS_RATE, "Rate", USB_MIXER_U16 }, |
1642 | { UAC_CHORUS_DEPTH, "Depth", USB_MIXER_U16 }, | 1643 | { UAC_CHORUS_DEPTH, "Depth", USB_MIXER_U16 }, |
1643 | { 0 } | 1644 | { 0 } |
1644 | }; | 1645 | }; |
1645 | static struct procunit_value_info dcr_proc_info[] = { | 1646 | static struct procunit_value_info dcr_proc_info[] = { |
1646 | { UAC_DCR_ENABLE, "Switch", USB_MIXER_BOOLEAN }, | 1647 | { UAC_DCR_ENABLE, "Switch", USB_MIXER_BOOLEAN }, |
1647 | { UAC_DCR_RATE, "Ratio", USB_MIXER_U16 }, | 1648 | { UAC_DCR_RATE, "Ratio", USB_MIXER_U16 }, |
1648 | { UAC_DCR_MAXAMPL, "Max Amp", USB_MIXER_S16 }, | 1649 | { UAC_DCR_MAXAMPL, "Max Amp", USB_MIXER_S16 }, |
1649 | { UAC_DCR_THRESHOLD, "Threshold", USB_MIXER_S16 }, | 1650 | { UAC_DCR_THRESHOLD, "Threshold", USB_MIXER_S16 }, |
1650 | { UAC_DCR_ATTACK_TIME, "Attack Time", USB_MIXER_U16 }, | 1651 | { UAC_DCR_ATTACK_TIME, "Attack Time", USB_MIXER_U16 }, |
1651 | { UAC_DCR_RELEASE_TIME, "Release Time", USB_MIXER_U16 }, | 1652 | { UAC_DCR_RELEASE_TIME, "Release Time", USB_MIXER_U16 }, |
1652 | { 0 } | 1653 | { 0 } |
1653 | }; | 1654 | }; |
1654 | 1655 | ||
1655 | static struct procunit_info procunits[] = { | 1656 | static struct procunit_info procunits[] = { |
1656 | { UAC_PROCESS_UP_DOWNMIX, "Up Down", updown_proc_info }, | 1657 | { UAC_PROCESS_UP_DOWNMIX, "Up Down", updown_proc_info }, |
1657 | { UAC_PROCESS_DOLBY_PROLOGIC, "Dolby Prologic", prologic_proc_info }, | 1658 | { UAC_PROCESS_DOLBY_PROLOGIC, "Dolby Prologic", prologic_proc_info }, |
1658 | { UAC_PROCESS_STEREO_EXTENDER, "3D Stereo Extender", threed_enh_proc_info }, | 1659 | { UAC_PROCESS_STEREO_EXTENDER, "3D Stereo Extender", threed_enh_proc_info }, |
1659 | { UAC_PROCESS_REVERB, "Reverb", reverb_proc_info }, | 1660 | { UAC_PROCESS_REVERB, "Reverb", reverb_proc_info }, |
1660 | { UAC_PROCESS_CHORUS, "Chorus", chorus_proc_info }, | 1661 | { UAC_PROCESS_CHORUS, "Chorus", chorus_proc_info }, |
1661 | { UAC_PROCESS_DYN_RANGE_COMP, "DCR", dcr_proc_info }, | 1662 | { UAC_PROCESS_DYN_RANGE_COMP, "DCR", dcr_proc_info }, |
1662 | { 0 }, | 1663 | { 0 }, |
1663 | }; | 1664 | }; |
1664 | /* | 1665 | /* |
1665 | * predefined data for extension units | 1666 | * predefined data for extension units |
1666 | */ | 1667 | */ |
1667 | static struct procunit_value_info clock_rate_xu_info[] = { | 1668 | static struct procunit_value_info clock_rate_xu_info[] = { |
1668 | { USB_XU_CLOCK_RATE_SELECTOR, "Selector", USB_MIXER_U8, 0 }, | 1669 | { USB_XU_CLOCK_RATE_SELECTOR, "Selector", USB_MIXER_U8, 0 }, |
1669 | { 0 } | 1670 | { 0 } |
1670 | }; | 1671 | }; |
1671 | static struct procunit_value_info clock_source_xu_info[] = { | 1672 | static struct procunit_value_info clock_source_xu_info[] = { |
1672 | { USB_XU_CLOCK_SOURCE_SELECTOR, "External", USB_MIXER_BOOLEAN }, | 1673 | { USB_XU_CLOCK_SOURCE_SELECTOR, "External", USB_MIXER_BOOLEAN }, |
1673 | { 0 } | 1674 | { 0 } |
1674 | }; | 1675 | }; |
1675 | static struct procunit_value_info spdif_format_xu_info[] = { | 1676 | static struct procunit_value_info spdif_format_xu_info[] = { |
1676 | { USB_XU_DIGITAL_FORMAT_SELECTOR, "SPDIF/AC3", USB_MIXER_BOOLEAN }, | 1677 | { USB_XU_DIGITAL_FORMAT_SELECTOR, "SPDIF/AC3", USB_MIXER_BOOLEAN }, |
1677 | { 0 } | 1678 | { 0 } |
1678 | }; | 1679 | }; |
1679 | static struct procunit_value_info soft_limit_xu_info[] = { | 1680 | static struct procunit_value_info soft_limit_xu_info[] = { |
1680 | { USB_XU_SOFT_LIMIT_SELECTOR, " ", USB_MIXER_BOOLEAN }, | 1681 | { USB_XU_SOFT_LIMIT_SELECTOR, " ", USB_MIXER_BOOLEAN }, |
1681 | { 0 } | 1682 | { 0 } |
1682 | }; | 1683 | }; |
1683 | static struct procunit_info extunits[] = { | 1684 | static struct procunit_info extunits[] = { |
1684 | { USB_XU_CLOCK_RATE, "Clock rate", clock_rate_xu_info }, | 1685 | { USB_XU_CLOCK_RATE, "Clock rate", clock_rate_xu_info }, |
1685 | { USB_XU_CLOCK_SOURCE, "DigitalIn CLK source", clock_source_xu_info }, | 1686 | { USB_XU_CLOCK_SOURCE, "DigitalIn CLK source", clock_source_xu_info }, |
1686 | { USB_XU_DIGITAL_IO_STATUS, "DigitalOut format:", spdif_format_xu_info }, | 1687 | { USB_XU_DIGITAL_IO_STATUS, "DigitalOut format:", spdif_format_xu_info }, |
1687 | { USB_XU_DEVICE_OPTIONS, "AnalogueIn Soft Limit", soft_limit_xu_info }, | 1688 | { USB_XU_DEVICE_OPTIONS, "AnalogueIn Soft Limit", soft_limit_xu_info }, |
1688 | { 0 } | 1689 | { 0 } |
1689 | }; | 1690 | }; |
1690 | /* | 1691 | /* |
1691 | * build a processing/extension unit | 1692 | * build a processing/extension unit |
1692 | */ | 1693 | */ |
1693 | static int build_audio_procunit(struct mixer_build *state, int unitid, void *raw_desc, struct procunit_info *list, char *name) | 1694 | static int build_audio_procunit(struct mixer_build *state, int unitid, void *raw_desc, struct procunit_info *list, char *name) |
1694 | { | 1695 | { |
1695 | struct uac_processing_unit_descriptor *desc = raw_desc; | 1696 | struct uac_processing_unit_descriptor *desc = raw_desc; |
1696 | int num_ins = desc->bNrInPins; | 1697 | int num_ins = desc->bNrInPins; |
1697 | struct usb_mixer_elem_info *cval; | 1698 | struct usb_mixer_elem_info *cval; |
1698 | struct snd_kcontrol *kctl; | 1699 | struct snd_kcontrol *kctl; |
1699 | int i, err, nameid, type, len; | 1700 | int i, err, nameid, type, len; |
1700 | struct procunit_info *info; | 1701 | struct procunit_info *info; |
1701 | struct procunit_value_info *valinfo; | 1702 | struct procunit_value_info *valinfo; |
1702 | const struct usbmix_name_map *map; | 1703 | const struct usbmix_name_map *map; |
1703 | static struct procunit_value_info default_value_info[] = { | 1704 | static struct procunit_value_info default_value_info[] = { |
1704 | { 0x01, "Switch", USB_MIXER_BOOLEAN }, | 1705 | { 0x01, "Switch", USB_MIXER_BOOLEAN }, |
1705 | { 0 } | 1706 | { 0 } |
1706 | }; | 1707 | }; |
1707 | static struct procunit_info default_info = { | 1708 | static struct procunit_info default_info = { |
1708 | 0, NULL, default_value_info | 1709 | 0, NULL, default_value_info |
1709 | }; | 1710 | }; |
1710 | 1711 | ||
1711 | if (desc->bLength < 13 || desc->bLength < 13 + num_ins || | 1712 | if (desc->bLength < 13 || desc->bLength < 13 + num_ins || |
1712 | desc->bLength < num_ins + uac_processing_unit_bControlSize(desc, state->mixer->protocol)) { | 1713 | desc->bLength < num_ins + uac_processing_unit_bControlSize(desc, state->mixer->protocol)) { |
1713 | snd_printk(KERN_ERR "invalid %s descriptor (id %d)\n", name, unitid); | 1714 | snd_printk(KERN_ERR "invalid %s descriptor (id %d)\n", name, unitid); |
1714 | return -EINVAL; | 1715 | return -EINVAL; |
1715 | } | 1716 | } |
1716 | 1717 | ||
1717 | for (i = 0; i < num_ins; i++) { | 1718 | for (i = 0; i < num_ins; i++) { |
1718 | if ((err = parse_audio_unit(state, desc->baSourceID[i])) < 0) | 1719 | if ((err = parse_audio_unit(state, desc->baSourceID[i])) < 0) |
1719 | return err; | 1720 | return err; |
1720 | } | 1721 | } |
1721 | 1722 | ||
1722 | type = le16_to_cpu(desc->wProcessType); | 1723 | type = le16_to_cpu(desc->wProcessType); |
1723 | for (info = list; info && info->type; info++) | 1724 | for (info = list; info && info->type; info++) |
1724 | if (info->type == type) | 1725 | if (info->type == type) |
1725 | break; | 1726 | break; |
1726 | if (! info || ! info->type) | 1727 | if (! info || ! info->type) |
1727 | info = &default_info; | 1728 | info = &default_info; |
1728 | 1729 | ||
1729 | for (valinfo = info->values; valinfo->control; valinfo++) { | 1730 | for (valinfo = info->values; valinfo->control; valinfo++) { |
1730 | __u8 *controls = uac_processing_unit_bmControls(desc, state->mixer->protocol); | 1731 | __u8 *controls = uac_processing_unit_bmControls(desc, state->mixer->protocol); |
1731 | 1732 | ||
1732 | if (! (controls[valinfo->control / 8] & (1 << ((valinfo->control % 8) - 1)))) | 1733 | if (! (controls[valinfo->control / 8] & (1 << ((valinfo->control % 8) - 1)))) |
1733 | continue; | 1734 | continue; |
1734 | map = find_map(state, unitid, valinfo->control); | 1735 | map = find_map(state, unitid, valinfo->control); |
1735 | if (check_ignored_ctl(map)) | 1736 | if (check_ignored_ctl(map)) |
1736 | continue; | 1737 | continue; |
1737 | cval = kzalloc(sizeof(*cval), GFP_KERNEL); | 1738 | cval = kzalloc(sizeof(*cval), GFP_KERNEL); |
1738 | if (! cval) { | 1739 | if (! cval) { |
1739 | snd_printk(KERN_ERR "cannot malloc kcontrol\n"); | 1740 | snd_printk(KERN_ERR "cannot malloc kcontrol\n"); |
1740 | return -ENOMEM; | 1741 | return -ENOMEM; |
1741 | } | 1742 | } |
1742 | cval->mixer = state->mixer; | 1743 | cval->mixer = state->mixer; |
1743 | cval->id = unitid; | 1744 | cval->id = unitid; |
1744 | cval->control = valinfo->control; | 1745 | cval->control = valinfo->control; |
1745 | cval->val_type = valinfo->val_type; | 1746 | cval->val_type = valinfo->val_type; |
1746 | cval->channels = 1; | 1747 | cval->channels = 1; |
1747 | 1748 | ||
1748 | /* get min/max values */ | 1749 | /* get min/max values */ |
1749 | if (type == UAC_PROCESS_UP_DOWNMIX && cval->control == UAC_UD_MODE_SELECT) { | 1750 | if (type == UAC_PROCESS_UP_DOWNMIX && cval->control == UAC_UD_MODE_SELECT) { |
1750 | __u8 *control_spec = uac_processing_unit_specific(desc, state->mixer->protocol); | 1751 | __u8 *control_spec = uac_processing_unit_specific(desc, state->mixer->protocol); |
1751 | /* FIXME: hard-coded */ | 1752 | /* FIXME: hard-coded */ |
1752 | cval->min = 1; | 1753 | cval->min = 1; |
1753 | cval->max = control_spec[0]; | 1754 | cval->max = control_spec[0]; |
1754 | cval->res = 1; | 1755 | cval->res = 1; |
1755 | cval->initialized = 1; | 1756 | cval->initialized = 1; |
1756 | } else { | 1757 | } else { |
1757 | if (type == USB_XU_CLOCK_RATE) { | 1758 | if (type == USB_XU_CLOCK_RATE) { |
1758 | /* E-Mu USB 0404/0202/TrackerPre/0204 | 1759 | /* E-Mu USB 0404/0202/TrackerPre/0204 |
1759 | * samplerate control quirk | 1760 | * samplerate control quirk |
1760 | */ | 1761 | */ |
1761 | cval->min = 0; | 1762 | cval->min = 0; |
1762 | cval->max = 5; | 1763 | cval->max = 5; |
1763 | cval->res = 1; | 1764 | cval->res = 1; |
1764 | cval->initialized = 1; | 1765 | cval->initialized = 1; |
1765 | } else | 1766 | } else |
1766 | get_min_max(cval, valinfo->min_value); | 1767 | get_min_max(cval, valinfo->min_value); |
1767 | } | 1768 | } |
1768 | 1769 | ||
1769 | kctl = snd_ctl_new1(&mixer_procunit_ctl, cval); | 1770 | kctl = snd_ctl_new1(&mixer_procunit_ctl, cval); |
1770 | if (! kctl) { | 1771 | if (! kctl) { |
1771 | snd_printk(KERN_ERR "cannot malloc kcontrol\n"); | 1772 | snd_printk(KERN_ERR "cannot malloc kcontrol\n"); |
1772 | kfree(cval); | 1773 | kfree(cval); |
1773 | return -ENOMEM; | 1774 | return -ENOMEM; |
1774 | } | 1775 | } |
1775 | kctl->private_free = usb_mixer_elem_free; | 1776 | kctl->private_free = usb_mixer_elem_free; |
1776 | 1777 | ||
1777 | if (check_mapped_name(map, kctl->id.name, | 1778 | if (check_mapped_name(map, kctl->id.name, |
1778 | sizeof(kctl->id.name))) | 1779 | sizeof(kctl->id.name))) |
1779 | /* nothing */ ; | 1780 | /* nothing */ ; |
1780 | else if (info->name) | 1781 | else if (info->name) |
1781 | strlcpy(kctl->id.name, info->name, sizeof(kctl->id.name)); | 1782 | strlcpy(kctl->id.name, info->name, sizeof(kctl->id.name)); |
1782 | else { | 1783 | else { |
1783 | nameid = uac_processing_unit_iProcessing(desc, state->mixer->protocol); | 1784 | nameid = uac_processing_unit_iProcessing(desc, state->mixer->protocol); |
1784 | len = 0; | 1785 | len = 0; |
1785 | if (nameid) | 1786 | if (nameid) |
1786 | len = snd_usb_copy_string_desc(state, nameid, kctl->id.name, sizeof(kctl->id.name)); | 1787 | len = snd_usb_copy_string_desc(state, nameid, kctl->id.name, sizeof(kctl->id.name)); |
1787 | if (! len) | 1788 | if (! len) |
1788 | strlcpy(kctl->id.name, name, sizeof(kctl->id.name)); | 1789 | strlcpy(kctl->id.name, name, sizeof(kctl->id.name)); |
1789 | } | 1790 | } |
1790 | append_ctl_name(kctl, " "); | 1791 | append_ctl_name(kctl, " "); |
1791 | append_ctl_name(kctl, valinfo->suffix); | 1792 | append_ctl_name(kctl, valinfo->suffix); |
1792 | 1793 | ||
1793 | snd_printdd(KERN_INFO "[%d] PU [%s] ch = %d, val = %d/%d\n", | 1794 | snd_printdd(KERN_INFO "[%d] PU [%s] ch = %d, val = %d/%d\n", |
1794 | cval->id, kctl->id.name, cval->channels, cval->min, cval->max); | 1795 | cval->id, kctl->id.name, cval->channels, cval->min, cval->max); |
1795 | if ((err = snd_usb_mixer_add_control(state->mixer, kctl)) < 0) | 1796 | if ((err = snd_usb_mixer_add_control(state->mixer, kctl)) < 0) |
1796 | return err; | 1797 | return err; |
1797 | } | 1798 | } |
1798 | return 0; | 1799 | return 0; |
1799 | } | 1800 | } |
1800 | 1801 | ||
1801 | 1802 | ||
1802 | static int parse_audio_processing_unit(struct mixer_build *state, int unitid, void *raw_desc) | 1803 | static int parse_audio_processing_unit(struct mixer_build *state, int unitid, void *raw_desc) |
1803 | { | 1804 | { |
1804 | return build_audio_procunit(state, unitid, raw_desc, procunits, "Processing Unit"); | 1805 | return build_audio_procunit(state, unitid, raw_desc, procunits, "Processing Unit"); |
1805 | } | 1806 | } |
1806 | 1807 | ||
1807 | static int parse_audio_extension_unit(struct mixer_build *state, int unitid, void *raw_desc) | 1808 | static int parse_audio_extension_unit(struct mixer_build *state, int unitid, void *raw_desc) |
1808 | { | 1809 | { |
1809 | /* Note that we parse extension units with processing unit descriptors. | 1810 | /* Note that we parse extension units with processing unit descriptors. |
1810 | * That's ok as the layout is the same */ | 1811 | * That's ok as the layout is the same */ |
1811 | return build_audio_procunit(state, unitid, raw_desc, extunits, "Extension Unit"); | 1812 | return build_audio_procunit(state, unitid, raw_desc, extunits, "Extension Unit"); |
1812 | } | 1813 | } |
1813 | 1814 | ||
1814 | 1815 | ||
1815 | /* | 1816 | /* |
1816 | * Selector Unit | 1817 | * Selector Unit |
1817 | */ | 1818 | */ |
1818 | 1819 | ||
1819 | /* info callback for selector unit | 1820 | /* info callback for selector unit |
1820 | * use an enumerator type for routing | 1821 | * use an enumerator type for routing |
1821 | */ | 1822 | */ |
1822 | static int mixer_ctl_selector_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 1823 | static int mixer_ctl_selector_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) |
1823 | { | 1824 | { |
1824 | struct usb_mixer_elem_info *cval = kcontrol->private_data; | 1825 | struct usb_mixer_elem_info *cval = kcontrol->private_data; |
1825 | const char **itemlist = (const char **)kcontrol->private_value; | 1826 | const char **itemlist = (const char **)kcontrol->private_value; |
1826 | 1827 | ||
1827 | if (snd_BUG_ON(!itemlist)) | 1828 | if (snd_BUG_ON(!itemlist)) |
1828 | return -EINVAL; | 1829 | return -EINVAL; |
1829 | return snd_ctl_enum_info(uinfo, 1, cval->max, itemlist); | 1830 | return snd_ctl_enum_info(uinfo, 1, cval->max, itemlist); |
1830 | } | 1831 | } |
1831 | 1832 | ||
1832 | /* get callback for selector unit */ | 1833 | /* get callback for selector unit */ |
1833 | static int mixer_ctl_selector_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 1834 | static int mixer_ctl_selector_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
1834 | { | 1835 | { |
1835 | struct usb_mixer_elem_info *cval = kcontrol->private_data; | 1836 | struct usb_mixer_elem_info *cval = kcontrol->private_data; |
1836 | int val, err; | 1837 | int val, err; |
1837 | 1838 | ||
1838 | err = get_cur_ctl_value(cval, cval->control << 8, &val); | 1839 | err = get_cur_ctl_value(cval, cval->control << 8, &val); |
1839 | if (err < 0) { | 1840 | if (err < 0) { |
1840 | if (cval->mixer->ignore_ctl_error) { | 1841 | if (cval->mixer->ignore_ctl_error) { |
1841 | ucontrol->value.enumerated.item[0] = 0; | 1842 | ucontrol->value.enumerated.item[0] = 0; |
1842 | return 0; | 1843 | return 0; |
1843 | } | 1844 | } |
1844 | return err; | 1845 | return err; |
1845 | } | 1846 | } |
1846 | val = get_relative_value(cval, val); | 1847 | val = get_relative_value(cval, val); |
1847 | ucontrol->value.enumerated.item[0] = val; | 1848 | ucontrol->value.enumerated.item[0] = val; |
1848 | return 0; | 1849 | return 0; |
1849 | } | 1850 | } |
1850 | 1851 | ||
1851 | /* put callback for selector unit */ | 1852 | /* put callback for selector unit */ |
1852 | static int mixer_ctl_selector_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 1853 | static int mixer_ctl_selector_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
1853 | { | 1854 | { |
1854 | struct usb_mixer_elem_info *cval = kcontrol->private_data; | 1855 | struct usb_mixer_elem_info *cval = kcontrol->private_data; |
1855 | int val, oval, err; | 1856 | int val, oval, err; |
1856 | 1857 | ||
1857 | err = get_cur_ctl_value(cval, cval->control << 8, &oval); | 1858 | err = get_cur_ctl_value(cval, cval->control << 8, &oval); |
1858 | if (err < 0) { | 1859 | if (err < 0) { |
1859 | if (cval->mixer->ignore_ctl_error) | 1860 | if (cval->mixer->ignore_ctl_error) |
1860 | return 0; | 1861 | return 0; |
1861 | return err; | 1862 | return err; |
1862 | } | 1863 | } |
1863 | val = ucontrol->value.enumerated.item[0]; | 1864 | val = ucontrol->value.enumerated.item[0]; |
1864 | val = get_abs_value(cval, val); | 1865 | val = get_abs_value(cval, val); |
1865 | if (val != oval) { | 1866 | if (val != oval) { |
1866 | set_cur_ctl_value(cval, cval->control << 8, val); | 1867 | set_cur_ctl_value(cval, cval->control << 8, val); |
1867 | return 1; | 1868 | return 1; |
1868 | } | 1869 | } |
1869 | return 0; | 1870 | return 0; |
1870 | } | 1871 | } |
1871 | 1872 | ||
1872 | /* alsa control interface for selector unit */ | 1873 | /* alsa control interface for selector unit */ |
1873 | static struct snd_kcontrol_new mixer_selectunit_ctl = { | 1874 | static struct snd_kcontrol_new mixer_selectunit_ctl = { |
1874 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 1875 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
1875 | .name = "", /* will be filled later */ | 1876 | .name = "", /* will be filled later */ |
1876 | .info = mixer_ctl_selector_info, | 1877 | .info = mixer_ctl_selector_info, |
1877 | .get = mixer_ctl_selector_get, | 1878 | .get = mixer_ctl_selector_get, |
1878 | .put = mixer_ctl_selector_put, | 1879 | .put = mixer_ctl_selector_put, |
1879 | }; | 1880 | }; |
1880 | 1881 | ||
1881 | 1882 | ||
1882 | /* private free callback. | 1883 | /* private free callback. |
1883 | * free both private_data and private_value | 1884 | * free both private_data and private_value |
1884 | */ | 1885 | */ |
1885 | static void usb_mixer_selector_elem_free(struct snd_kcontrol *kctl) | 1886 | static void usb_mixer_selector_elem_free(struct snd_kcontrol *kctl) |
1886 | { | 1887 | { |
1887 | int i, num_ins = 0; | 1888 | int i, num_ins = 0; |
1888 | 1889 | ||
1889 | if (kctl->private_data) { | 1890 | if (kctl->private_data) { |
1890 | struct usb_mixer_elem_info *cval = kctl->private_data; | 1891 | struct usb_mixer_elem_info *cval = kctl->private_data; |
1891 | num_ins = cval->max; | 1892 | num_ins = cval->max; |
1892 | kfree(cval); | 1893 | kfree(cval); |
1893 | kctl->private_data = NULL; | 1894 | kctl->private_data = NULL; |
1894 | } | 1895 | } |
1895 | if (kctl->private_value) { | 1896 | if (kctl->private_value) { |
1896 | char **itemlist = (char **)kctl->private_value; | 1897 | char **itemlist = (char **)kctl->private_value; |
1897 | for (i = 0; i < num_ins; i++) | 1898 | for (i = 0; i < num_ins; i++) |
1898 | kfree(itemlist[i]); | 1899 | kfree(itemlist[i]); |
1899 | kfree(itemlist); | 1900 | kfree(itemlist); |
1900 | kctl->private_value = 0; | 1901 | kctl->private_value = 0; |
1901 | } | 1902 | } |
1902 | } | 1903 | } |
1903 | 1904 | ||
1904 | /* | 1905 | /* |
1905 | * parse a selector unit | 1906 | * parse a selector unit |
1906 | */ | 1907 | */ |
1907 | static int parse_audio_selector_unit(struct mixer_build *state, int unitid, void *raw_desc) | 1908 | static int parse_audio_selector_unit(struct mixer_build *state, int unitid, void *raw_desc) |
1908 | { | 1909 | { |
1909 | struct uac_selector_unit_descriptor *desc = raw_desc; | 1910 | struct uac_selector_unit_descriptor *desc = raw_desc; |
1910 | unsigned int i, nameid, len; | 1911 | unsigned int i, nameid, len; |
1911 | int err; | 1912 | int err; |
1912 | struct usb_mixer_elem_info *cval; | 1913 | struct usb_mixer_elem_info *cval; |
1913 | struct snd_kcontrol *kctl; | 1914 | struct snd_kcontrol *kctl; |
1914 | const struct usbmix_name_map *map; | 1915 | const struct usbmix_name_map *map; |
1915 | char **namelist; | 1916 | char **namelist; |
1916 | 1917 | ||
1917 | if (!desc->bNrInPins || desc->bLength < 5 + desc->bNrInPins) { | 1918 | if (!desc->bNrInPins || desc->bLength < 5 + desc->bNrInPins) { |
1918 | snd_printk(KERN_ERR "invalid SELECTOR UNIT descriptor %d\n", unitid); | 1919 | snd_printk(KERN_ERR "invalid SELECTOR UNIT descriptor %d\n", unitid); |
1919 | return -EINVAL; | 1920 | return -EINVAL; |
1920 | } | 1921 | } |
1921 | 1922 | ||
1922 | for (i = 0; i < desc->bNrInPins; i++) { | 1923 | for (i = 0; i < desc->bNrInPins; i++) { |
1923 | if ((err = parse_audio_unit(state, desc->baSourceID[i])) < 0) | 1924 | if ((err = parse_audio_unit(state, desc->baSourceID[i])) < 0) |
1924 | return err; | 1925 | return err; |
1925 | } | 1926 | } |
1926 | 1927 | ||
1927 | if (desc->bNrInPins == 1) /* only one ? nonsense! */ | 1928 | if (desc->bNrInPins == 1) /* only one ? nonsense! */ |
1928 | return 0; | 1929 | return 0; |
1929 | 1930 | ||
1930 | map = find_map(state, unitid, 0); | 1931 | map = find_map(state, unitid, 0); |
1931 | if (check_ignored_ctl(map)) | 1932 | if (check_ignored_ctl(map)) |
1932 | return 0; | 1933 | return 0; |
1933 | 1934 | ||
1934 | cval = kzalloc(sizeof(*cval), GFP_KERNEL); | 1935 | cval = kzalloc(sizeof(*cval), GFP_KERNEL); |
1935 | if (! cval) { | 1936 | if (! cval) { |
1936 | snd_printk(KERN_ERR "cannot malloc kcontrol\n"); | 1937 | snd_printk(KERN_ERR "cannot malloc kcontrol\n"); |
1937 | return -ENOMEM; | 1938 | return -ENOMEM; |
1938 | } | 1939 | } |
1939 | cval->mixer = state->mixer; | 1940 | cval->mixer = state->mixer; |
1940 | cval->id = unitid; | 1941 | cval->id = unitid; |
1941 | cval->val_type = USB_MIXER_U8; | 1942 | cval->val_type = USB_MIXER_U8; |
1942 | cval->channels = 1; | 1943 | cval->channels = 1; |
1943 | cval->min = 1; | 1944 | cval->min = 1; |
1944 | cval->max = desc->bNrInPins; | 1945 | cval->max = desc->bNrInPins; |
1945 | cval->res = 1; | 1946 | cval->res = 1; |
1946 | cval->initialized = 1; | 1947 | cval->initialized = 1; |
1947 | 1948 | ||
1948 | if (desc->bDescriptorSubtype == UAC2_CLOCK_SELECTOR) | 1949 | if (desc->bDescriptorSubtype == UAC2_CLOCK_SELECTOR) |
1949 | cval->control = UAC2_CX_CLOCK_SELECTOR; | 1950 | cval->control = UAC2_CX_CLOCK_SELECTOR; |
1950 | else | 1951 | else |
1951 | cval->control = 0; | 1952 | cval->control = 0; |
1952 | 1953 | ||
1953 | namelist = kmalloc(sizeof(char *) * desc->bNrInPins, GFP_KERNEL); | 1954 | namelist = kmalloc(sizeof(char *) * desc->bNrInPins, GFP_KERNEL); |
1954 | if (! namelist) { | 1955 | if (! namelist) { |
1955 | snd_printk(KERN_ERR "cannot malloc\n"); | 1956 | snd_printk(KERN_ERR "cannot malloc\n"); |
1956 | kfree(cval); | 1957 | kfree(cval); |
1957 | return -ENOMEM; | 1958 | return -ENOMEM; |
1958 | } | 1959 | } |
1959 | #define MAX_ITEM_NAME_LEN 64 | 1960 | #define MAX_ITEM_NAME_LEN 64 |
1960 | for (i = 0; i < desc->bNrInPins; i++) { | 1961 | for (i = 0; i < desc->bNrInPins; i++) { |
1961 | struct usb_audio_term iterm; | 1962 | struct usb_audio_term iterm; |
1962 | len = 0; | 1963 | len = 0; |
1963 | namelist[i] = kmalloc(MAX_ITEM_NAME_LEN, GFP_KERNEL); | 1964 | namelist[i] = kmalloc(MAX_ITEM_NAME_LEN, GFP_KERNEL); |
1964 | if (! namelist[i]) { | 1965 | if (! namelist[i]) { |
1965 | snd_printk(KERN_ERR "cannot malloc\n"); | 1966 | snd_printk(KERN_ERR "cannot malloc\n"); |
1966 | while (i--) | 1967 | while (i--) |
1967 | kfree(namelist[i]); | 1968 | kfree(namelist[i]); |
1968 | kfree(namelist); | 1969 | kfree(namelist); |
1969 | kfree(cval); | 1970 | kfree(cval); |
1970 | return -ENOMEM; | 1971 | return -ENOMEM; |
1971 | } | 1972 | } |
1972 | len = check_mapped_selector_name(state, unitid, i, namelist[i], | 1973 | len = check_mapped_selector_name(state, unitid, i, namelist[i], |
1973 | MAX_ITEM_NAME_LEN); | 1974 | MAX_ITEM_NAME_LEN); |
1974 | if (! len && check_input_term(state, desc->baSourceID[i], &iterm) >= 0) | 1975 | if (! len && check_input_term(state, desc->baSourceID[i], &iterm) >= 0) |
1975 | len = get_term_name(state, &iterm, namelist[i], MAX_ITEM_NAME_LEN, 0); | 1976 | len = get_term_name(state, &iterm, namelist[i], MAX_ITEM_NAME_LEN, 0); |
1976 | if (! len) | 1977 | if (! len) |
1977 | sprintf(namelist[i], "Input %d", i); | 1978 | sprintf(namelist[i], "Input %d", i); |
1978 | } | 1979 | } |
1979 | 1980 | ||
1980 | kctl = snd_ctl_new1(&mixer_selectunit_ctl, cval); | 1981 | kctl = snd_ctl_new1(&mixer_selectunit_ctl, cval); |
1981 | if (! kctl) { | 1982 | if (! kctl) { |
1982 | snd_printk(KERN_ERR "cannot malloc kcontrol\n"); | 1983 | snd_printk(KERN_ERR "cannot malloc kcontrol\n"); |
1983 | kfree(namelist); | 1984 | kfree(namelist); |
1984 | kfree(cval); | 1985 | kfree(cval); |
1985 | return -ENOMEM; | 1986 | return -ENOMEM; |
1986 | } | 1987 | } |
1987 | kctl->private_value = (unsigned long)namelist; | 1988 | kctl->private_value = (unsigned long)namelist; |
1988 | kctl->private_free = usb_mixer_selector_elem_free; | 1989 | kctl->private_free = usb_mixer_selector_elem_free; |
1989 | 1990 | ||
1990 | nameid = uac_selector_unit_iSelector(desc); | 1991 | nameid = uac_selector_unit_iSelector(desc); |
1991 | len = check_mapped_name(map, kctl->id.name, sizeof(kctl->id.name)); | 1992 | len = check_mapped_name(map, kctl->id.name, sizeof(kctl->id.name)); |
1992 | if (len) | 1993 | if (len) |
1993 | ; | 1994 | ; |
1994 | else if (nameid) | 1995 | else if (nameid) |
1995 | snd_usb_copy_string_desc(state, nameid, kctl->id.name, sizeof(kctl->id.name)); | 1996 | snd_usb_copy_string_desc(state, nameid, kctl->id.name, sizeof(kctl->id.name)); |
1996 | else { | 1997 | else { |
1997 | len = get_term_name(state, &state->oterm, | 1998 | len = get_term_name(state, &state->oterm, |
1998 | kctl->id.name, sizeof(kctl->id.name), 0); | 1999 | kctl->id.name, sizeof(kctl->id.name), 0); |
1999 | if (! len) | 2000 | if (! len) |
2000 | strlcpy(kctl->id.name, "USB", sizeof(kctl->id.name)); | 2001 | strlcpy(kctl->id.name, "USB", sizeof(kctl->id.name)); |
2001 | 2002 | ||
2002 | if (desc->bDescriptorSubtype == UAC2_CLOCK_SELECTOR) | 2003 | if (desc->bDescriptorSubtype == UAC2_CLOCK_SELECTOR) |
2003 | append_ctl_name(kctl, " Clock Source"); | 2004 | append_ctl_name(kctl, " Clock Source"); |
2004 | else if ((state->oterm.type & 0xff00) == 0x0100) | 2005 | else if ((state->oterm.type & 0xff00) == 0x0100) |
2005 | append_ctl_name(kctl, " Capture Source"); | 2006 | append_ctl_name(kctl, " Capture Source"); |
2006 | else | 2007 | else |
2007 | append_ctl_name(kctl, " Playback Source"); | 2008 | append_ctl_name(kctl, " Playback Source"); |
2008 | } | 2009 | } |
2009 | 2010 | ||
2010 | snd_printdd(KERN_INFO "[%d] SU [%s] items = %d\n", | 2011 | snd_printdd(KERN_INFO "[%d] SU [%s] items = %d\n", |
2011 | cval->id, kctl->id.name, desc->bNrInPins); | 2012 | cval->id, kctl->id.name, desc->bNrInPins); |
2012 | if ((err = snd_usb_mixer_add_control(state->mixer, kctl)) < 0) | 2013 | if ((err = snd_usb_mixer_add_control(state->mixer, kctl)) < 0) |
2013 | return err; | 2014 | return err; |
2014 | 2015 | ||
2015 | return 0; | 2016 | return 0; |
2016 | } | 2017 | } |
2017 | 2018 | ||
2018 | 2019 | ||
2019 | /* | 2020 | /* |
2020 | * parse an audio unit recursively | 2021 | * parse an audio unit recursively |
2021 | */ | 2022 | */ |
2022 | 2023 | ||
2023 | static int parse_audio_unit(struct mixer_build *state, int unitid) | 2024 | static int parse_audio_unit(struct mixer_build *state, int unitid) |
2024 | { | 2025 | { |
2025 | unsigned char *p1; | 2026 | unsigned char *p1; |
2026 | 2027 | ||
2027 | if (test_and_set_bit(unitid, state->unitbitmap)) | 2028 | if (test_and_set_bit(unitid, state->unitbitmap)) |
2028 | return 0; /* the unit already visited */ | 2029 | return 0; /* the unit already visited */ |
2029 | 2030 | ||
2030 | p1 = find_audio_control_unit(state, unitid); | 2031 | p1 = find_audio_control_unit(state, unitid); |
2031 | if (!p1) { | 2032 | if (!p1) { |
2032 | snd_printk(KERN_ERR "usbaudio: unit %d not found!\n", unitid); | 2033 | snd_printk(KERN_ERR "usbaudio: unit %d not found!\n", unitid); |
2033 | return -EINVAL; | 2034 | return -EINVAL; |
2034 | } | 2035 | } |
2035 | 2036 | ||
2036 | switch (p1[2]) { | 2037 | switch (p1[2]) { |
2037 | case UAC_INPUT_TERMINAL: | 2038 | case UAC_INPUT_TERMINAL: |
2038 | case UAC2_CLOCK_SOURCE: | 2039 | case UAC2_CLOCK_SOURCE: |
2039 | return 0; /* NOP */ | 2040 | return 0; /* NOP */ |
2040 | case UAC_MIXER_UNIT: | 2041 | case UAC_MIXER_UNIT: |
2041 | return parse_audio_mixer_unit(state, unitid, p1); | 2042 | return parse_audio_mixer_unit(state, unitid, p1); |
2042 | case UAC_SELECTOR_UNIT: | 2043 | case UAC_SELECTOR_UNIT: |
2043 | case UAC2_CLOCK_SELECTOR: | 2044 | case UAC2_CLOCK_SELECTOR: |
2044 | return parse_audio_selector_unit(state, unitid, p1); | 2045 | return parse_audio_selector_unit(state, unitid, p1); |
2045 | case UAC_FEATURE_UNIT: | 2046 | case UAC_FEATURE_UNIT: |
2046 | return parse_audio_feature_unit(state, unitid, p1); | 2047 | return parse_audio_feature_unit(state, unitid, p1); |
2047 | case UAC1_PROCESSING_UNIT: | 2048 | case UAC1_PROCESSING_UNIT: |
2048 | /* UAC2_EFFECT_UNIT has the same value */ | 2049 | /* UAC2_EFFECT_UNIT has the same value */ |
2049 | if (state->mixer->protocol == UAC_VERSION_1) | 2050 | if (state->mixer->protocol == UAC_VERSION_1) |
2050 | return parse_audio_processing_unit(state, unitid, p1); | 2051 | return parse_audio_processing_unit(state, unitid, p1); |
2051 | else | 2052 | else |
2052 | return 0; /* FIXME - effect units not implemented yet */ | 2053 | return 0; /* FIXME - effect units not implemented yet */ |
2053 | case UAC1_EXTENSION_UNIT: | 2054 | case UAC1_EXTENSION_UNIT: |
2054 | /* UAC2_PROCESSING_UNIT_V2 has the same value */ | 2055 | /* UAC2_PROCESSING_UNIT_V2 has the same value */ |
2055 | if (state->mixer->protocol == UAC_VERSION_1) | 2056 | if (state->mixer->protocol == UAC_VERSION_1) |
2056 | return parse_audio_extension_unit(state, unitid, p1); | 2057 | return parse_audio_extension_unit(state, unitid, p1); |
2057 | else /* UAC_VERSION_2 */ | 2058 | else /* UAC_VERSION_2 */ |
2058 | return parse_audio_processing_unit(state, unitid, p1); | 2059 | return parse_audio_processing_unit(state, unitid, p1); |
2059 | case UAC2_EXTENSION_UNIT_V2: | 2060 | case UAC2_EXTENSION_UNIT_V2: |
2060 | return parse_audio_extension_unit(state, unitid, p1); | 2061 | return parse_audio_extension_unit(state, unitid, p1); |
2061 | default: | 2062 | default: |
2062 | snd_printk(KERN_ERR "usbaudio: unit %u: unexpected type 0x%02x\n", unitid, p1[2]); | 2063 | snd_printk(KERN_ERR "usbaudio: unit %u: unexpected type 0x%02x\n", unitid, p1[2]); |
2063 | return -EINVAL; | 2064 | return -EINVAL; |
2064 | } | 2065 | } |
2065 | } | 2066 | } |
2066 | 2067 | ||
2067 | static void snd_usb_mixer_free(struct usb_mixer_interface *mixer) | 2068 | static void snd_usb_mixer_free(struct usb_mixer_interface *mixer) |
2068 | { | 2069 | { |
2069 | kfree(mixer->id_elems); | 2070 | kfree(mixer->id_elems); |
2070 | if (mixer->urb) { | 2071 | if (mixer->urb) { |
2071 | kfree(mixer->urb->transfer_buffer); | 2072 | kfree(mixer->urb->transfer_buffer); |
2072 | usb_free_urb(mixer->urb); | 2073 | usb_free_urb(mixer->urb); |
2073 | } | 2074 | } |
2074 | usb_free_urb(mixer->rc_urb); | 2075 | usb_free_urb(mixer->rc_urb); |
2075 | kfree(mixer->rc_setup_packet); | 2076 | kfree(mixer->rc_setup_packet); |
2076 | kfree(mixer); | 2077 | kfree(mixer); |
2077 | } | 2078 | } |
2078 | 2079 | ||
2079 | static int snd_usb_mixer_dev_free(struct snd_device *device) | 2080 | static int snd_usb_mixer_dev_free(struct snd_device *device) |
2080 | { | 2081 | { |
2081 | struct usb_mixer_interface *mixer = device->device_data; | 2082 | struct usb_mixer_interface *mixer = device->device_data; |
2082 | snd_usb_mixer_free(mixer); | 2083 | snd_usb_mixer_free(mixer); |
2083 | return 0; | 2084 | return 0; |
2084 | } | 2085 | } |
2085 | 2086 | ||
2086 | /* | 2087 | /* |
2087 | * create mixer controls | 2088 | * create mixer controls |
2088 | * | 2089 | * |
2089 | * walk through all UAC_OUTPUT_TERMINAL descriptors to search for mixers | 2090 | * walk through all UAC_OUTPUT_TERMINAL descriptors to search for mixers |
2090 | */ | 2091 | */ |
2091 | static int snd_usb_mixer_controls(struct usb_mixer_interface *mixer) | 2092 | static int snd_usb_mixer_controls(struct usb_mixer_interface *mixer) |
2092 | { | 2093 | { |
2093 | struct mixer_build state; | 2094 | struct mixer_build state; |
2094 | int err; | 2095 | int err; |
2095 | const struct usbmix_ctl_map *map; | 2096 | const struct usbmix_ctl_map *map; |
2096 | void *p; | 2097 | void *p; |
2097 | 2098 | ||
2098 | memset(&state, 0, sizeof(state)); | 2099 | memset(&state, 0, sizeof(state)); |
2099 | state.chip = mixer->chip; | 2100 | state.chip = mixer->chip; |
2100 | state.mixer = mixer; | 2101 | state.mixer = mixer; |
2101 | state.buffer = mixer->hostif->extra; | 2102 | state.buffer = mixer->hostif->extra; |
2102 | state.buflen = mixer->hostif->extralen; | 2103 | state.buflen = mixer->hostif->extralen; |
2103 | 2104 | ||
2104 | /* check the mapping table */ | 2105 | /* check the mapping table */ |
2105 | for (map = usbmix_ctl_maps; map->id; map++) { | 2106 | for (map = usbmix_ctl_maps; map->id; map++) { |
2106 | if (map->id == state.chip->usb_id) { | 2107 | if (map->id == state.chip->usb_id) { |
2107 | state.map = map->map; | 2108 | state.map = map->map; |
2108 | state.selector_map = map->selector_map; | 2109 | state.selector_map = map->selector_map; |
2109 | mixer->ignore_ctl_error = map->ignore_ctl_error; | 2110 | mixer->ignore_ctl_error = map->ignore_ctl_error; |
2110 | break; | 2111 | break; |
2111 | } | 2112 | } |
2112 | } | 2113 | } |
2113 | 2114 | ||
2114 | p = NULL; | 2115 | p = NULL; |
2115 | while ((p = snd_usb_find_csint_desc(mixer->hostif->extra, mixer->hostif->extralen, | 2116 | while ((p = snd_usb_find_csint_desc(mixer->hostif->extra, mixer->hostif->extralen, |
2116 | p, UAC_OUTPUT_TERMINAL)) != NULL) { | 2117 | p, UAC_OUTPUT_TERMINAL)) != NULL) { |
2117 | if (mixer->protocol == UAC_VERSION_1) { | 2118 | if (mixer->protocol == UAC_VERSION_1) { |
2118 | struct uac1_output_terminal_descriptor *desc = p; | 2119 | struct uac1_output_terminal_descriptor *desc = p; |
2119 | 2120 | ||
2120 | if (desc->bLength < sizeof(*desc)) | 2121 | if (desc->bLength < sizeof(*desc)) |
2121 | continue; /* invalid descriptor? */ | 2122 | continue; /* invalid descriptor? */ |
2122 | set_bit(desc->bTerminalID, state.unitbitmap); /* mark terminal ID as visited */ | 2123 | set_bit(desc->bTerminalID, state.unitbitmap); /* mark terminal ID as visited */ |
2123 | state.oterm.id = desc->bTerminalID; | 2124 | state.oterm.id = desc->bTerminalID; |
2124 | state.oterm.type = le16_to_cpu(desc->wTerminalType); | 2125 | state.oterm.type = le16_to_cpu(desc->wTerminalType); |
2125 | state.oterm.name = desc->iTerminal; | 2126 | state.oterm.name = desc->iTerminal; |
2126 | err = parse_audio_unit(&state, desc->bSourceID); | 2127 | err = parse_audio_unit(&state, desc->bSourceID); |
2127 | if (err < 0 && err != -EINVAL) | 2128 | if (err < 0 && err != -EINVAL) |
2128 | return err; | 2129 | return err; |
2129 | } else { /* UAC_VERSION_2 */ | 2130 | } else { /* UAC_VERSION_2 */ |
2130 | struct uac2_output_terminal_descriptor *desc = p; | 2131 | struct uac2_output_terminal_descriptor *desc = p; |
2131 | 2132 | ||
2132 | if (desc->bLength < sizeof(*desc)) | 2133 | if (desc->bLength < sizeof(*desc)) |
2133 | continue; /* invalid descriptor? */ | 2134 | continue; /* invalid descriptor? */ |
2134 | set_bit(desc->bTerminalID, state.unitbitmap); /* mark terminal ID as visited */ | 2135 | set_bit(desc->bTerminalID, state.unitbitmap); /* mark terminal ID as visited */ |
2135 | state.oterm.id = desc->bTerminalID; | 2136 | state.oterm.id = desc->bTerminalID; |
2136 | state.oterm.type = le16_to_cpu(desc->wTerminalType); | 2137 | state.oterm.type = le16_to_cpu(desc->wTerminalType); |
2137 | state.oterm.name = desc->iTerminal; | 2138 | state.oterm.name = desc->iTerminal; |
2138 | err = parse_audio_unit(&state, desc->bSourceID); | 2139 | err = parse_audio_unit(&state, desc->bSourceID); |
2139 | if (err < 0 && err != -EINVAL) | 2140 | if (err < 0 && err != -EINVAL) |
2140 | return err; | 2141 | return err; |
2141 | 2142 | ||
2142 | /* for UAC2, use the same approach to also add the clock selectors */ | 2143 | /* for UAC2, use the same approach to also add the clock selectors */ |
2143 | err = parse_audio_unit(&state, desc->bCSourceID); | 2144 | err = parse_audio_unit(&state, desc->bCSourceID); |
2144 | if (err < 0 && err != -EINVAL) | 2145 | if (err < 0 && err != -EINVAL) |
2145 | return err; | 2146 | return err; |
2146 | } | 2147 | } |
2147 | } | 2148 | } |
2148 | 2149 | ||
2149 | return 0; | 2150 | return 0; |
2150 | } | 2151 | } |
2151 | 2152 | ||
2152 | void snd_usb_mixer_notify_id(struct usb_mixer_interface *mixer, int unitid) | 2153 | void snd_usb_mixer_notify_id(struct usb_mixer_interface *mixer, int unitid) |
2153 | { | 2154 | { |
2154 | struct usb_mixer_elem_info *info; | 2155 | struct usb_mixer_elem_info *info; |
2155 | 2156 | ||
2156 | for (info = mixer->id_elems[unitid]; info; info = info->next_id_elem) | 2157 | for (info = mixer->id_elems[unitid]; info; info = info->next_id_elem) |
2157 | snd_ctl_notify(mixer->chip->card, SNDRV_CTL_EVENT_MASK_VALUE, | 2158 | snd_ctl_notify(mixer->chip->card, SNDRV_CTL_EVENT_MASK_VALUE, |
2158 | info->elem_id); | 2159 | info->elem_id); |
2159 | } | 2160 | } |
2160 | 2161 | ||
2161 | static void snd_usb_mixer_dump_cval(struct snd_info_buffer *buffer, | 2162 | static void snd_usb_mixer_dump_cval(struct snd_info_buffer *buffer, |
2162 | int unitid, | 2163 | int unitid, |
2163 | struct usb_mixer_elem_info *cval) | 2164 | struct usb_mixer_elem_info *cval) |
2164 | { | 2165 | { |
2165 | static char *val_types[] = {"BOOLEAN", "INV_BOOLEAN", | 2166 | static char *val_types[] = {"BOOLEAN", "INV_BOOLEAN", |
2166 | "S8", "U8", "S16", "U16"}; | 2167 | "S8", "U8", "S16", "U16"}; |
2167 | snd_iprintf(buffer, " Unit: %i\n", unitid); | 2168 | snd_iprintf(buffer, " Unit: %i\n", unitid); |
2168 | if (cval->elem_id) | 2169 | if (cval->elem_id) |
2169 | snd_iprintf(buffer, " Control: name=\"%s\", index=%i\n", | 2170 | snd_iprintf(buffer, " Control: name=\"%s\", index=%i\n", |
2170 | cval->elem_id->name, cval->elem_id->index); | 2171 | cval->elem_id->name, cval->elem_id->index); |
2171 | snd_iprintf(buffer, " Info: id=%i, control=%i, cmask=0x%x, " | 2172 | snd_iprintf(buffer, " Info: id=%i, control=%i, cmask=0x%x, " |
2172 | "channels=%i, type=\"%s\"\n", cval->id, | 2173 | "channels=%i, type=\"%s\"\n", cval->id, |
2173 | cval->control, cval->cmask, cval->channels, | 2174 | cval->control, cval->cmask, cval->channels, |
2174 | val_types[cval->val_type]); | 2175 | val_types[cval->val_type]); |
2175 | snd_iprintf(buffer, " Volume: min=%i, max=%i, dBmin=%i, dBmax=%i\n", | 2176 | snd_iprintf(buffer, " Volume: min=%i, max=%i, dBmin=%i, dBmax=%i\n", |
2176 | cval->min, cval->max, cval->dBmin, cval->dBmax); | 2177 | cval->min, cval->max, cval->dBmin, cval->dBmax); |
2177 | } | 2178 | } |
2178 | 2179 | ||
2179 | static void snd_usb_mixer_proc_read(struct snd_info_entry *entry, | 2180 | static void snd_usb_mixer_proc_read(struct snd_info_entry *entry, |
2180 | struct snd_info_buffer *buffer) | 2181 | struct snd_info_buffer *buffer) |
2181 | { | 2182 | { |
2182 | struct snd_usb_audio *chip = entry->private_data; | 2183 | struct snd_usb_audio *chip = entry->private_data; |
2183 | struct usb_mixer_interface *mixer; | 2184 | struct usb_mixer_interface *mixer; |
2184 | struct usb_mixer_elem_info *cval; | 2185 | struct usb_mixer_elem_info *cval; |
2185 | int unitid; | 2186 | int unitid; |
2186 | 2187 | ||
2187 | list_for_each_entry(mixer, &chip->mixer_list, list) { | 2188 | list_for_each_entry(mixer, &chip->mixer_list, list) { |
2188 | snd_iprintf(buffer, | 2189 | snd_iprintf(buffer, |
2189 | "USB Mixer: usb_id=0x%08x, ctrlif=%i, ctlerr=%i\n", | 2190 | "USB Mixer: usb_id=0x%08x, ctrlif=%i, ctlerr=%i\n", |
2190 | chip->usb_id, snd_usb_ctrl_intf(chip), | 2191 | chip->usb_id, snd_usb_ctrl_intf(chip), |
2191 | mixer->ignore_ctl_error); | 2192 | mixer->ignore_ctl_error); |
2192 | snd_iprintf(buffer, "Card: %s\n", chip->card->longname); | 2193 | snd_iprintf(buffer, "Card: %s\n", chip->card->longname); |
2193 | for (unitid = 0; unitid < MAX_ID_ELEMS; unitid++) { | 2194 | for (unitid = 0; unitid < MAX_ID_ELEMS; unitid++) { |
2194 | for (cval = mixer->id_elems[unitid]; cval; | 2195 | for (cval = mixer->id_elems[unitid]; cval; |
2195 | cval = cval->next_id_elem) | 2196 | cval = cval->next_id_elem) |
2196 | snd_usb_mixer_dump_cval(buffer, unitid, cval); | 2197 | snd_usb_mixer_dump_cval(buffer, unitid, cval); |
2197 | } | 2198 | } |
2198 | } | 2199 | } |
2199 | } | 2200 | } |
2200 | 2201 | ||
2201 | static void snd_usb_mixer_interrupt_v2(struct usb_mixer_interface *mixer, | 2202 | static void snd_usb_mixer_interrupt_v2(struct usb_mixer_interface *mixer, |
2202 | int attribute, int value, int index) | 2203 | int attribute, int value, int index) |
2203 | { | 2204 | { |
2204 | struct usb_mixer_elem_info *info; | 2205 | struct usb_mixer_elem_info *info; |
2205 | __u8 unitid = (index >> 8) & 0xff; | 2206 | __u8 unitid = (index >> 8) & 0xff; |
2206 | __u8 control = (value >> 8) & 0xff; | 2207 | __u8 control = (value >> 8) & 0xff; |
2207 | __u8 channel = value & 0xff; | 2208 | __u8 channel = value & 0xff; |
2208 | 2209 | ||
2209 | if (channel >= MAX_CHANNELS) { | 2210 | if (channel >= MAX_CHANNELS) { |
2210 | snd_printk(KERN_DEBUG "%s(): bogus channel number %d\n", | 2211 | snd_printk(KERN_DEBUG "%s(): bogus channel number %d\n", |
2211 | __func__, channel); | 2212 | __func__, channel); |
2212 | return; | 2213 | return; |
2213 | } | 2214 | } |
2214 | 2215 | ||
2215 | for (info = mixer->id_elems[unitid]; info; info = info->next_id_elem) { | 2216 | for (info = mixer->id_elems[unitid]; info; info = info->next_id_elem) { |
2216 | if (info->control != control) | 2217 | if (info->control != control) |
2217 | continue; | 2218 | continue; |
2218 | 2219 | ||
2219 | switch (attribute) { | 2220 | switch (attribute) { |
2220 | case UAC2_CS_CUR: | 2221 | case UAC2_CS_CUR: |
2221 | /* invalidate cache, so the value is read from the device */ | 2222 | /* invalidate cache, so the value is read from the device */ |
2222 | if (channel) | 2223 | if (channel) |
2223 | info->cached &= ~(1 << channel); | 2224 | info->cached &= ~(1 << channel); |
2224 | else /* master channel */ | 2225 | else /* master channel */ |
2225 | info->cached = 0; | 2226 | info->cached = 0; |
2226 | 2227 | ||
2227 | snd_ctl_notify(mixer->chip->card, SNDRV_CTL_EVENT_MASK_VALUE, | 2228 | snd_ctl_notify(mixer->chip->card, SNDRV_CTL_EVENT_MASK_VALUE, |
2228 | info->elem_id); | 2229 | info->elem_id); |
2229 | break; | 2230 | break; |
2230 | 2231 | ||
2231 | case UAC2_CS_RANGE: | 2232 | case UAC2_CS_RANGE: |
2232 | /* TODO */ | 2233 | /* TODO */ |
2233 | break; | 2234 | break; |
2234 | 2235 | ||
2235 | case UAC2_CS_MEM: | 2236 | case UAC2_CS_MEM: |
2236 | /* TODO */ | 2237 | /* TODO */ |
2237 | break; | 2238 | break; |
2238 | 2239 | ||
2239 | default: | 2240 | default: |
2240 | snd_printk(KERN_DEBUG "unknown attribute %d in interrupt\n", | 2241 | snd_printk(KERN_DEBUG "unknown attribute %d in interrupt\n", |
2241 | attribute); | 2242 | attribute); |
2242 | break; | 2243 | break; |
2243 | } /* switch */ | 2244 | } /* switch */ |
2244 | } | 2245 | } |
2245 | } | 2246 | } |
2246 | 2247 | ||
2247 | static void snd_usb_mixer_interrupt(struct urb *urb) | 2248 | static void snd_usb_mixer_interrupt(struct urb *urb) |
2248 | { | 2249 | { |
2249 | struct usb_mixer_interface *mixer = urb->context; | 2250 | struct usb_mixer_interface *mixer = urb->context; |
2250 | int len = urb->actual_length; | 2251 | int len = urb->actual_length; |
2251 | int ustatus = urb->status; | 2252 | int ustatus = urb->status; |
2252 | 2253 | ||
2253 | if (ustatus != 0) | 2254 | if (ustatus != 0) |
2254 | goto requeue; | 2255 | goto requeue; |
2255 | 2256 | ||
2256 | if (mixer->protocol == UAC_VERSION_1) { | 2257 | if (mixer->protocol == UAC_VERSION_1) { |
2257 | struct uac1_status_word *status; | 2258 | struct uac1_status_word *status; |
2258 | 2259 | ||
2259 | for (status = urb->transfer_buffer; | 2260 | for (status = urb->transfer_buffer; |
2260 | len >= sizeof(*status); | 2261 | len >= sizeof(*status); |
2261 | len -= sizeof(*status), status++) { | 2262 | len -= sizeof(*status), status++) { |
2262 | snd_printd(KERN_DEBUG "status interrupt: %02x %02x\n", | 2263 | snd_printd(KERN_DEBUG "status interrupt: %02x %02x\n", |
2263 | status->bStatusType, | 2264 | status->bStatusType, |
2264 | status->bOriginator); | 2265 | status->bOriginator); |
2265 | 2266 | ||
2266 | /* ignore any notifications not from the control interface */ | 2267 | /* ignore any notifications not from the control interface */ |
2267 | if ((status->bStatusType & UAC1_STATUS_TYPE_ORIG_MASK) != | 2268 | if ((status->bStatusType & UAC1_STATUS_TYPE_ORIG_MASK) != |
2268 | UAC1_STATUS_TYPE_ORIG_AUDIO_CONTROL_IF) | 2269 | UAC1_STATUS_TYPE_ORIG_AUDIO_CONTROL_IF) |
2269 | continue; | 2270 | continue; |
2270 | 2271 | ||
2271 | if (status->bStatusType & UAC1_STATUS_TYPE_MEM_CHANGED) | 2272 | if (status->bStatusType & UAC1_STATUS_TYPE_MEM_CHANGED) |
2272 | snd_usb_mixer_rc_memory_change(mixer, status->bOriginator); | 2273 | snd_usb_mixer_rc_memory_change(mixer, status->bOriginator); |
2273 | else | 2274 | else |
2274 | snd_usb_mixer_notify_id(mixer, status->bOriginator); | 2275 | snd_usb_mixer_notify_id(mixer, status->bOriginator); |
2275 | } | 2276 | } |
2276 | } else { /* UAC_VERSION_2 */ | 2277 | } else { /* UAC_VERSION_2 */ |
2277 | struct uac2_interrupt_data_msg *msg; | 2278 | struct uac2_interrupt_data_msg *msg; |
2278 | 2279 | ||
2279 | for (msg = urb->transfer_buffer; | 2280 | for (msg = urb->transfer_buffer; |
2280 | len >= sizeof(*msg); | 2281 | len >= sizeof(*msg); |
2281 | len -= sizeof(*msg), msg++) { | 2282 | len -= sizeof(*msg), msg++) { |
2282 | /* drop vendor specific and endpoint requests */ | 2283 | /* drop vendor specific and endpoint requests */ |
2283 | if ((msg->bInfo & UAC2_INTERRUPT_DATA_MSG_VENDOR) || | 2284 | if ((msg->bInfo & UAC2_INTERRUPT_DATA_MSG_VENDOR) || |
2284 | (msg->bInfo & UAC2_INTERRUPT_DATA_MSG_EP)) | 2285 | (msg->bInfo & UAC2_INTERRUPT_DATA_MSG_EP)) |
2285 | continue; | 2286 | continue; |
2286 | 2287 | ||
2287 | snd_usb_mixer_interrupt_v2(mixer, msg->bAttribute, | 2288 | snd_usb_mixer_interrupt_v2(mixer, msg->bAttribute, |
2288 | le16_to_cpu(msg->wValue), | 2289 | le16_to_cpu(msg->wValue), |
2289 | le16_to_cpu(msg->wIndex)); | 2290 | le16_to_cpu(msg->wIndex)); |
2290 | } | 2291 | } |
2291 | } | 2292 | } |
2292 | 2293 | ||
2293 | requeue: | 2294 | requeue: |
2294 | if (ustatus != -ENOENT && ustatus != -ECONNRESET && ustatus != -ESHUTDOWN) { | 2295 | if (ustatus != -ENOENT && ustatus != -ECONNRESET && ustatus != -ESHUTDOWN) { |
2295 | urb->dev = mixer->chip->dev; | 2296 | urb->dev = mixer->chip->dev; |
2296 | usb_submit_urb(urb, GFP_ATOMIC); | 2297 | usb_submit_urb(urb, GFP_ATOMIC); |
2297 | } | 2298 | } |
2298 | } | 2299 | } |
2299 | 2300 | ||
2300 | /* stop any bus activity of a mixer */ | 2301 | /* stop any bus activity of a mixer */ |
2301 | void snd_usb_mixer_inactivate(struct usb_mixer_interface *mixer) | 2302 | void snd_usb_mixer_inactivate(struct usb_mixer_interface *mixer) |
2302 | { | 2303 | { |
2303 | usb_kill_urb(mixer->urb); | 2304 | usb_kill_urb(mixer->urb); |
2304 | usb_kill_urb(mixer->rc_urb); | 2305 | usb_kill_urb(mixer->rc_urb); |
2305 | } | 2306 | } |
2306 | 2307 | ||
2307 | int snd_usb_mixer_activate(struct usb_mixer_interface *mixer) | 2308 | int snd_usb_mixer_activate(struct usb_mixer_interface *mixer) |
2308 | { | 2309 | { |
2309 | int err; | 2310 | int err; |
2310 | 2311 | ||
2311 | if (mixer->urb) { | 2312 | if (mixer->urb) { |
2312 | err = usb_submit_urb(mixer->urb, GFP_NOIO); | 2313 | err = usb_submit_urb(mixer->urb, GFP_NOIO); |
2313 | if (err < 0) | 2314 | if (err < 0) |
2314 | return err; | 2315 | return err; |
2315 | } | 2316 | } |
2316 | 2317 | ||
2317 | return 0; | 2318 | return 0; |
2318 | } | 2319 | } |
2319 | 2320 | ||
2320 | /* create the handler for the optional status interrupt endpoint */ | 2321 | /* create the handler for the optional status interrupt endpoint */ |
2321 | static int snd_usb_mixer_status_create(struct usb_mixer_interface *mixer) | 2322 | static int snd_usb_mixer_status_create(struct usb_mixer_interface *mixer) |
2322 | { | 2323 | { |
2323 | struct usb_endpoint_descriptor *ep; | 2324 | struct usb_endpoint_descriptor *ep; |
2324 | void *transfer_buffer; | 2325 | void *transfer_buffer; |
2325 | int buffer_length; | 2326 | int buffer_length; |
2326 | unsigned int epnum; | 2327 | unsigned int epnum; |
2327 | 2328 | ||
2328 | /* we need one interrupt input endpoint */ | 2329 | /* we need one interrupt input endpoint */ |
2329 | if (get_iface_desc(mixer->hostif)->bNumEndpoints < 1) | 2330 | if (get_iface_desc(mixer->hostif)->bNumEndpoints < 1) |
2330 | return 0; | 2331 | return 0; |
2331 | ep = get_endpoint(mixer->hostif, 0); | 2332 | ep = get_endpoint(mixer->hostif, 0); |
2332 | if (!usb_endpoint_dir_in(ep) || !usb_endpoint_xfer_int(ep)) | 2333 | if (!usb_endpoint_dir_in(ep) || !usb_endpoint_xfer_int(ep)) |
2333 | return 0; | 2334 | return 0; |
2334 | 2335 | ||
2335 | epnum = usb_endpoint_num(ep); | 2336 | epnum = usb_endpoint_num(ep); |
2336 | buffer_length = le16_to_cpu(ep->wMaxPacketSize); | 2337 | buffer_length = le16_to_cpu(ep->wMaxPacketSize); |
2337 | transfer_buffer = kmalloc(buffer_length, GFP_KERNEL); | 2338 | transfer_buffer = kmalloc(buffer_length, GFP_KERNEL); |
2338 | if (!transfer_buffer) | 2339 | if (!transfer_buffer) |
2339 | return -ENOMEM; | 2340 | return -ENOMEM; |
2340 | mixer->urb = usb_alloc_urb(0, GFP_KERNEL); | 2341 | mixer->urb = usb_alloc_urb(0, GFP_KERNEL); |
2341 | if (!mixer->urb) { | 2342 | if (!mixer->urb) { |
2342 | kfree(transfer_buffer); | 2343 | kfree(transfer_buffer); |
2343 | return -ENOMEM; | 2344 | return -ENOMEM; |
2344 | } | 2345 | } |
2345 | usb_fill_int_urb(mixer->urb, mixer->chip->dev, | 2346 | usb_fill_int_urb(mixer->urb, mixer->chip->dev, |
2346 | usb_rcvintpipe(mixer->chip->dev, epnum), | 2347 | usb_rcvintpipe(mixer->chip->dev, epnum), |
2347 | transfer_buffer, buffer_length, | 2348 | transfer_buffer, buffer_length, |
2348 | snd_usb_mixer_interrupt, mixer, ep->bInterval); | 2349 | snd_usb_mixer_interrupt, mixer, ep->bInterval); |
2349 | usb_submit_urb(mixer->urb, GFP_KERNEL); | 2350 | usb_submit_urb(mixer->urb, GFP_KERNEL); |
2350 | return 0; | 2351 | return 0; |
2351 | } | 2352 | } |
2352 | 2353 | ||
2353 | int snd_usb_create_mixer(struct snd_usb_audio *chip, int ctrlif, | 2354 | int snd_usb_create_mixer(struct snd_usb_audio *chip, int ctrlif, |
2354 | int ignore_error) | 2355 | int ignore_error) |
2355 | { | 2356 | { |
2356 | static struct snd_device_ops dev_ops = { | 2357 | static struct snd_device_ops dev_ops = { |
2357 | .dev_free = snd_usb_mixer_dev_free | 2358 | .dev_free = snd_usb_mixer_dev_free |
2358 | }; | 2359 | }; |
2359 | struct usb_mixer_interface *mixer; | 2360 | struct usb_mixer_interface *mixer; |
2360 | struct snd_info_entry *entry; | 2361 | struct snd_info_entry *entry; |
2361 | int err; | 2362 | int err; |
2362 | 2363 | ||
2363 | strcpy(chip->card->mixername, "USB Mixer"); | 2364 | strcpy(chip->card->mixername, "USB Mixer"); |
2364 | 2365 | ||
2365 | mixer = kzalloc(sizeof(*mixer), GFP_KERNEL); | 2366 | mixer = kzalloc(sizeof(*mixer), GFP_KERNEL); |
2366 | if (!mixer) | 2367 | if (!mixer) |
2367 | return -ENOMEM; | 2368 | return -ENOMEM; |
2368 | mixer->chip = chip; | 2369 | mixer->chip = chip; |
2369 | mixer->ignore_ctl_error = ignore_error; | 2370 | mixer->ignore_ctl_error = ignore_error; |
2370 | mixer->id_elems = kcalloc(MAX_ID_ELEMS, sizeof(*mixer->id_elems), | 2371 | mixer->id_elems = kcalloc(MAX_ID_ELEMS, sizeof(*mixer->id_elems), |
2371 | GFP_KERNEL); | 2372 | GFP_KERNEL); |
2372 | if (!mixer->id_elems) { | 2373 | if (!mixer->id_elems) { |
2373 | kfree(mixer); | 2374 | kfree(mixer); |
2374 | return -ENOMEM; | 2375 | return -ENOMEM; |
2375 | } | 2376 | } |
2376 | 2377 | ||
2377 | mixer->hostif = &usb_ifnum_to_if(chip->dev, ctrlif)->altsetting[0]; | 2378 | mixer->hostif = &usb_ifnum_to_if(chip->dev, ctrlif)->altsetting[0]; |
2378 | switch (get_iface_desc(mixer->hostif)->bInterfaceProtocol) { | 2379 | switch (get_iface_desc(mixer->hostif)->bInterfaceProtocol) { |
2379 | case UAC_VERSION_1: | 2380 | case UAC_VERSION_1: |
2380 | default: | 2381 | default: |
2381 | mixer->protocol = UAC_VERSION_1; | 2382 | mixer->protocol = UAC_VERSION_1; |
2382 | break; | 2383 | break; |
2383 | case UAC_VERSION_2: | 2384 | case UAC_VERSION_2: |
2384 | mixer->protocol = UAC_VERSION_2; | 2385 | mixer->protocol = UAC_VERSION_2; |
2385 | break; | 2386 | break; |
2386 | } | 2387 | } |
2387 | 2388 | ||
2388 | if ((err = snd_usb_mixer_controls(mixer)) < 0 || | 2389 | if ((err = snd_usb_mixer_controls(mixer)) < 0 || |
2389 | (err = snd_usb_mixer_status_create(mixer)) < 0) | 2390 | (err = snd_usb_mixer_status_create(mixer)) < 0) |
2390 | goto _error; | 2391 | goto _error; |
2391 | 2392 | ||
2392 | snd_usb_mixer_apply_create_quirk(mixer); | 2393 | snd_usb_mixer_apply_create_quirk(mixer); |
2393 | 2394 | ||
2394 | err = snd_device_new(chip->card, SNDRV_DEV_LOWLEVEL, mixer, &dev_ops); | 2395 | err = snd_device_new(chip->card, SNDRV_DEV_LOWLEVEL, mixer, &dev_ops); |
2395 | if (err < 0) | 2396 | if (err < 0) |
2396 | goto _error; | 2397 | goto _error; |
2397 | 2398 | ||
2398 | if (list_empty(&chip->mixer_list) && | 2399 | if (list_empty(&chip->mixer_list) && |
2399 | !snd_card_proc_new(chip->card, "usbmixer", &entry)) | 2400 | !snd_card_proc_new(chip->card, "usbmixer", &entry)) |
2400 | snd_info_set_text_ops(entry, chip, snd_usb_mixer_proc_read); | 2401 | snd_info_set_text_ops(entry, chip, snd_usb_mixer_proc_read); |
2401 | 2402 | ||
2402 | list_add(&mixer->list, &chip->mixer_list); | 2403 | list_add(&mixer->list, &chip->mixer_list); |
2403 | return 0; | 2404 | return 0; |
2404 | 2405 | ||
2405 | _error: | 2406 | _error: |
2406 | snd_usb_mixer_free(mixer); | 2407 | snd_usb_mixer_free(mixer); |
2407 | return err; | 2408 | return err; |
2408 | } | 2409 | } |
2409 | 2410 | ||
2410 | void snd_usb_mixer_disconnect(struct list_head *p) | 2411 | void snd_usb_mixer_disconnect(struct list_head *p) |
2411 | { | 2412 | { |
2412 | struct usb_mixer_interface *mixer; | 2413 | struct usb_mixer_interface *mixer; |
2413 | 2414 | ||
2414 | mixer = list_entry(p, struct usb_mixer_interface, list); | 2415 | mixer = list_entry(p, struct usb_mixer_interface, list); |
2415 | usb_kill_urb(mixer->urb); | 2416 | usb_kill_urb(mixer->urb); |
2416 | usb_kill_urb(mixer->rc_urb); | 2417 | usb_kill_urb(mixer->rc_urb); |
2417 | } | 2418 | } |
2418 | 2419 |