aboutsummaryrefslogtreecommitdiffstats
path: root/sound/usb/mixer.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/usb/mixer.c')
-rw-r--r--sound/usb/mixer.c156
1 files changed, 86 insertions, 70 deletions
diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c
index a4fbfff63191..41650d5b93b7 100644
--- a/sound/usb/mixer.c
+++ b/sound/usb/mixer.c
@@ -138,7 +138,7 @@ check_mapped_name(const struct usbmix_name_map *p, char *buf, int buflen)
138 138
139/* ignore the error value if ignore_ctl_error flag is set */ 139/* ignore the error value if ignore_ctl_error flag is set */
140#define filter_error(cval, err) \ 140#define filter_error(cval, err) \
141 ((cval)->mixer->ignore_ctl_error ? 0 : (err)) 141 ((cval)->head.mixer->ignore_ctl_error ? 0 : (err))
142 142
143/* check whether the control should be ignored */ 143/* check whether the control should be ignored */
144static inline int 144static inline int
@@ -290,13 +290,13 @@ static int get_abs_value(struct usb_mixer_elem_info *cval, int val)
290static int get_ctl_value_v1(struct usb_mixer_elem_info *cval, int request, 290static int get_ctl_value_v1(struct usb_mixer_elem_info *cval, int request,
291 int validx, int *value_ret) 291 int validx, int *value_ret)
292{ 292{
293 struct snd_usb_audio *chip = cval->mixer->chip; 293 struct snd_usb_audio *chip = cval->head.mixer->chip;
294 unsigned char buf[2]; 294 unsigned char buf[2];
295 int val_len = cval->val_type >= USB_MIXER_S16 ? 2 : 1; 295 int val_len = cval->val_type >= USB_MIXER_S16 ? 2 : 1;
296 int timeout = 10; 296 int timeout = 10;
297 int idx = 0, err; 297 int idx = 0, err;
298 298
299 err = snd_usb_autoresume(cval->mixer->chip); 299 err = snd_usb_autoresume(chip);
300 if (err < 0) 300 if (err < 0)
301 return -EIO; 301 return -EIO;
302 302
@@ -304,7 +304,7 @@ static int get_ctl_value_v1(struct usb_mixer_elem_info *cval, int request,
304 while (timeout-- > 0) { 304 while (timeout-- > 0) {
305 if (chip->shutdown) 305 if (chip->shutdown)
306 break; 306 break;
307 idx = snd_usb_ctrl_intf(chip) | (cval->id << 8); 307 idx = snd_usb_ctrl_intf(chip) | (cval->head.id << 8);
308 if (snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), request, 308 if (snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), request,
309 USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, 309 USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
310 validx, idx, buf, val_len) >= val_len) { 310 validx, idx, buf, val_len) >= val_len) {
@@ -320,14 +320,14 @@ static int get_ctl_value_v1(struct usb_mixer_elem_info *cval, int request,
320 320
321 out: 321 out:
322 up_read(&chip->shutdown_rwsem); 322 up_read(&chip->shutdown_rwsem);
323 snd_usb_autosuspend(cval->mixer->chip); 323 snd_usb_autosuspend(chip);
324 return err; 324 return err;
325} 325}
326 326
327static int get_ctl_value_v2(struct usb_mixer_elem_info *cval, int request, 327static int get_ctl_value_v2(struct usb_mixer_elem_info *cval, int request,
328 int validx, int *value_ret) 328 int validx, int *value_ret)
329{ 329{
330 struct snd_usb_audio *chip = cval->mixer->chip; 330 struct snd_usb_audio *chip = cval->head.mixer->chip;
331 unsigned char buf[2 + 3 * sizeof(__u16)]; /* enough space for one range */ 331 unsigned char buf[2 + 3 * sizeof(__u16)]; /* enough space for one range */
332 unsigned char *val; 332 unsigned char *val;
333 int idx = 0, ret, size; 333 int idx = 0, ret, size;
@@ -351,7 +351,7 @@ static int get_ctl_value_v2(struct usb_mixer_elem_info *cval, int request,
351 if (chip->shutdown) { 351 if (chip->shutdown) {
352 ret = -ENODEV; 352 ret = -ENODEV;
353 } else { 353 } else {
354 idx = snd_usb_ctrl_intf(chip) | (cval->id << 8); 354 idx = snd_usb_ctrl_intf(chip) | (cval->head.id << 8);
355 ret = snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), bRequest, 355 ret = snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), bRequest,
356 USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, 356 USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
357 validx, idx, buf, size); 357 validx, idx, buf, size);
@@ -396,7 +396,7 @@ static int get_ctl_value(struct usb_mixer_elem_info *cval, int request,
396{ 396{
397 validx += cval->idx_off; 397 validx += cval->idx_off;
398 398
399 return (cval->mixer->protocol == UAC_VERSION_1) ? 399 return (cval->head.mixer->protocol == UAC_VERSION_1) ?
400 get_ctl_value_v1(cval, request, validx, value_ret) : 400 get_ctl_value_v1(cval, request, validx, value_ret) :
401 get_ctl_value_v2(cval, request, validx, value_ret); 401 get_ctl_value_v2(cval, request, validx, value_ret);
402} 402}
@@ -427,8 +427,8 @@ int snd_usb_get_cur_mix_value(struct usb_mixer_elem_info *cval,
427 } 427 }
428 err = get_cur_mix_raw(cval, channel, value); 428 err = get_cur_mix_raw(cval, channel, value);
429 if (err < 0) { 429 if (err < 0) {
430 if (!cval->mixer->ignore_ctl_error) 430 if (!cval->head.mixer->ignore_ctl_error)
431 usb_audio_dbg(cval->mixer->chip, 431 usb_audio_dbg(cval->head.mixer->chip,
432 "cannot get current value for control %d ch %d: err = %d\n", 432 "cannot get current value for control %d ch %d: err = %d\n",
433 cval->control, channel, err); 433 cval->control, channel, err);
434 return err; 434 return err;
@@ -445,13 +445,13 @@ int snd_usb_get_cur_mix_value(struct usb_mixer_elem_info *cval,
445int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval, 445int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval,
446 int request, int validx, int value_set) 446 int request, int validx, int value_set)
447{ 447{
448 struct snd_usb_audio *chip = cval->mixer->chip; 448 struct snd_usb_audio *chip = cval->head.mixer->chip;
449 unsigned char buf[2]; 449 unsigned char buf[2];
450 int idx = 0, val_len, err, timeout = 10; 450 int idx = 0, val_len, err, timeout = 10;
451 451
452 validx += cval->idx_off; 452 validx += cval->idx_off;
453 453
454 if (cval->mixer->protocol == UAC_VERSION_1) { 454 if (cval->head.mixer->protocol == UAC_VERSION_1) {
455 val_len = cval->val_type >= USB_MIXER_S16 ? 2 : 1; 455 val_len = cval->val_type >= USB_MIXER_S16 ? 2 : 1;
456 } else { /* UAC_VERSION_2 */ 456 } else { /* UAC_VERSION_2 */
457 /* audio class v2 controls are always 2 bytes in size */ 457 /* audio class v2 controls are always 2 bytes in size */
@@ -476,7 +476,7 @@ int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval,
476 while (timeout-- > 0) { 476 while (timeout-- > 0) {
477 if (chip->shutdown) 477 if (chip->shutdown)
478 break; 478 break;
479 idx = snd_usb_ctrl_intf(chip) | (cval->id << 8); 479 idx = snd_usb_ctrl_intf(chip) | (cval->head.id << 8);
480 if (snd_usb_ctl_msg(chip->dev, 480 if (snd_usb_ctl_msg(chip->dev,
481 usb_sndctrlpipe(chip->dev, 0), request, 481 usb_sndctrlpipe(chip->dev, 0), request,
482 USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT, 482 USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT,
@@ -510,7 +510,7 @@ int snd_usb_set_cur_mix_value(struct usb_mixer_elem_info *cval, int channel,
510 cval->ch_readonly & (1 << (channel - 1)); 510 cval->ch_readonly & (1 << (channel - 1));
511 511
512 if (read_only) { 512 if (read_only) {
513 usb_audio_dbg(cval->mixer->chip, 513 usb_audio_dbg(cval->head.mixer->chip,
514 "%s(): channel %d of control %d is read_only\n", 514 "%s(): channel %d of control %d is read_only\n",
515 __func__, channel, cval->control); 515 __func__, channel, cval->control);
516 return 0; 516 return 0;
@@ -569,10 +569,10 @@ static int check_matrix_bitmap(unsigned char *bmap,
569 * if failed, give up and free the control instance. 569 * if failed, give up and free the control instance.
570 */ 570 */
571 571
572int snd_usb_mixer_add_control(struct usb_mixer_interface *mixer, 572int snd_usb_mixer_add_control(struct usb_mixer_elem_list *list,
573 struct snd_kcontrol *kctl) 573 struct snd_kcontrol *kctl)
574{ 574{
575 struct usb_mixer_elem_info *cval = kctl->private_data; 575 struct usb_mixer_interface *mixer = list->mixer;
576 int err; 576 int err;
577 577
578 while (snd_ctl_find_id(mixer->chip->card, &kctl->id)) 578 while (snd_ctl_find_id(mixer->chip->card, &kctl->id))
@@ -582,9 +582,9 @@ int snd_usb_mixer_add_control(struct usb_mixer_interface *mixer,
582 err); 582 err);
583 return err; 583 return err;
584 } 584 }
585 cval->elem_id = &kctl->id; 585 list->kctl = kctl;
586 cval->next_id_elem = mixer->id_elems[cval->id]; 586 list->next_id_elem = mixer->id_elems[list->id];
587 mixer->id_elems[cval->id] = cval; 587 mixer->id_elems[list->id] = list;
588 return 0; 588 return 0;
589} 589}
590 590
@@ -833,7 +833,7 @@ void snd_usb_mixer_elem_free(struct snd_kcontrol *kctl)
833static void volume_control_quirks(struct usb_mixer_elem_info *cval, 833static void volume_control_quirks(struct usb_mixer_elem_info *cval,
834 struct snd_kcontrol *kctl) 834 struct snd_kcontrol *kctl)
835{ 835{
836 struct snd_usb_audio *chip = cval->mixer->chip; 836 struct snd_usb_audio *chip = cval->head.mixer->chip;
837 switch (chip->usb_id) { 837 switch (chip->usb_id) {
838 case USB_ID(0x0763, 0x2030): /* M-Audio Fast Track C400 */ 838 case USB_ID(0x0763, 0x2030): /* M-Audio Fast Track C400 */
839 case USB_ID(0x0763, 0x2031): /* M-Audio Fast Track C600 */ 839 case USB_ID(0x0763, 0x2031): /* M-Audio Fast Track C600 */
@@ -958,10 +958,10 @@ static int get_min_max_with_quirks(struct usb_mixer_elem_info *cval,
958 } 958 }
959 if (get_ctl_value(cval, UAC_GET_MAX, (cval->control << 8) | minchn, &cval->max) < 0 || 959 if (get_ctl_value(cval, UAC_GET_MAX, (cval->control << 8) | minchn, &cval->max) < 0 ||
960 get_ctl_value(cval, UAC_GET_MIN, (cval->control << 8) | minchn, &cval->min) < 0) { 960 get_ctl_value(cval, UAC_GET_MIN, (cval->control << 8) | minchn, &cval->min) < 0) {
961 usb_audio_err(cval->mixer->chip, 961 usb_audio_err(cval->head.mixer->chip,
962 "%d:%d: cannot get min/max values for control %d (id %d)\n", 962 "%d:%d: cannot get min/max values for control %d (id %d)\n",
963 cval->id, snd_usb_ctrl_intf(cval->mixer->chip), 963 cval->head.id, snd_usb_ctrl_intf(cval->head.mixer->chip),
964 cval->control, cval->id); 964 cval->control, cval->head.id);
965 return -EINVAL; 965 return -EINVAL;
966 } 966 }
967 if (get_ctl_value(cval, UAC_GET_RES, 967 if (get_ctl_value(cval, UAC_GET_RES,
@@ -1065,7 +1065,7 @@ static int mixer_ctl_feature_info(struct snd_kcontrol *kcontrol,
1065 kcontrol->vd[0].access &= 1065 kcontrol->vd[0].access &=
1066 ~(SNDRV_CTL_ELEM_ACCESS_TLV_READ | 1066 ~(SNDRV_CTL_ELEM_ACCESS_TLV_READ |
1067 SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK); 1067 SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK);
1068 snd_ctl_notify(cval->mixer->chip->card, 1068 snd_ctl_notify(cval->head.mixer->chip->card,
1069 SNDRV_CTL_EVENT_MASK_INFO, 1069 SNDRV_CTL_EVENT_MASK_INFO,
1070 &kcontrol->id); 1070 &kcontrol->id);
1071 } 1071 }
@@ -1235,8 +1235,7 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc,
1235 cval = kzalloc(sizeof(*cval), GFP_KERNEL); 1235 cval = kzalloc(sizeof(*cval), GFP_KERNEL);
1236 if (!cval) 1236 if (!cval)
1237 return; 1237 return;
1238 cval->mixer = state->mixer; 1238 snd_usb_mixer_elem_init_std(&cval->head, state->mixer, unitid);
1239 cval->id = unitid;
1240 cval->control = control; 1239 cval->control = control;
1241 cval->cmask = ctl_mask; 1240 cval->cmask = ctl_mask;
1242 cval->val_type = audio_feature_info[control-1].type; 1241 cval->val_type = audio_feature_info[control-1].type;
@@ -1347,14 +1346,14 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc,
1347 range); 1346 range);
1348 usb_audio_warn(state->chip, 1347 usb_audio_warn(state->chip,
1349 "[%d] FU [%s] ch = %d, val = %d/%d/%d", 1348 "[%d] FU [%s] ch = %d, val = %d/%d/%d",
1350 cval->id, kctl->id.name, cval->channels, 1349 cval->head.id, kctl->id.name, cval->channels,
1351 cval->min, cval->max, cval->res); 1350 cval->min, cval->max, cval->res);
1352 } 1351 }
1353 1352
1354 usb_audio_dbg(state->chip, "[%d] FU [%s] ch = %d, val = %d/%d/%d\n", 1353 usb_audio_dbg(state->chip, "[%d] FU [%s] ch = %d, val = %d/%d/%d\n",
1355 cval->id, kctl->id.name, cval->channels, 1354 cval->head.id, kctl->id.name, cval->channels,
1356 cval->min, cval->max, cval->res); 1355 cval->min, cval->max, cval->res);
1357 snd_usb_mixer_add_control(state->mixer, kctl); 1356 snd_usb_mixer_add_control(&cval->head, kctl);
1358} 1357}
1359 1358
1360/* 1359/*
@@ -1528,8 +1527,7 @@ static void build_mixer_unit_ctl(struct mixer_build *state,
1528 if (!cval) 1527 if (!cval)
1529 return; 1528 return;
1530 1529
1531 cval->mixer = state->mixer; 1530 snd_usb_mixer_elem_init_std(&cval->head, state->mixer, unitid);
1532 cval->id = unitid;
1533 cval->control = in_ch + 1; /* based on 1 */ 1531 cval->control = in_ch + 1; /* based on 1 */
1534 cval->val_type = USB_MIXER_S16; 1532 cval->val_type = USB_MIXER_S16;
1535 for (i = 0; i < num_outs; i++) { 1533 for (i = 0; i < num_outs; i++) {
@@ -1561,8 +1559,8 @@ static void build_mixer_unit_ctl(struct mixer_build *state,
1561 append_ctl_name(kctl, " Volume"); 1559 append_ctl_name(kctl, " Volume");
1562 1560
1563 usb_audio_dbg(state->chip, "[%d] MU [%s] ch = %d, val = %d/%d\n", 1561 usb_audio_dbg(state->chip, "[%d] MU [%s] ch = %d, val = %d/%d\n",
1564 cval->id, kctl->id.name, cval->channels, cval->min, cval->max); 1562 cval->head.id, kctl->id.name, cval->channels, cval->min, cval->max);
1565 snd_usb_mixer_add_control(state->mixer, kctl); 1563 snd_usb_mixer_add_control(&cval->head, kctl);
1566} 1564}
1567 1565
1568/* 1566/*
@@ -1812,8 +1810,7 @@ static int build_audio_procunit(struct mixer_build *state, int unitid,
1812 cval = kzalloc(sizeof(*cval), GFP_KERNEL); 1810 cval = kzalloc(sizeof(*cval), GFP_KERNEL);
1813 if (!cval) 1811 if (!cval)
1814 return -ENOMEM; 1812 return -ENOMEM;
1815 cval->mixer = state->mixer; 1813 snd_usb_mixer_elem_init_std(&cval->head, state->mixer, unitid);
1816 cval->id = unitid;
1817 cval->control = valinfo->control; 1814 cval->control = valinfo->control;
1818 cval->val_type = valinfo->val_type; 1815 cval->val_type = valinfo->val_type;
1819 cval->channels = 1; 1816 cval->channels = 1;
@@ -1866,10 +1863,10 @@ static int build_audio_procunit(struct mixer_build *state, int unitid,
1866 1863
1867 usb_audio_dbg(state->chip, 1864 usb_audio_dbg(state->chip,
1868 "[%d] PU [%s] ch = %d, val = %d/%d\n", 1865 "[%d] PU [%s] ch = %d, val = %d/%d\n",
1869 cval->id, kctl->id.name, cval->channels, 1866 cval->head.id, kctl->id.name, cval->channels,
1870 cval->min, cval->max); 1867 cval->min, cval->max);
1871 1868
1872 err = snd_usb_mixer_add_control(state->mixer, kctl); 1869 err = snd_usb_mixer_add_control(&cval->head, kctl);
1873 if (err < 0) 1870 if (err < 0)
1874 return err; 1871 return err;
1875 } 1872 }
@@ -2016,8 +2013,7 @@ static int parse_audio_selector_unit(struct mixer_build *state, int unitid,
2016 cval = kzalloc(sizeof(*cval), GFP_KERNEL); 2013 cval = kzalloc(sizeof(*cval), GFP_KERNEL);
2017 if (!cval) 2014 if (!cval)
2018 return -ENOMEM; 2015 return -ENOMEM;
2019 cval->mixer = state->mixer; 2016 snd_usb_mixer_elem_init_std(&cval->head, state->mixer, unitid);
2020 cval->id = unitid;
2021 cval->val_type = USB_MIXER_U8; 2017 cval->val_type = USB_MIXER_U8;
2022 cval->channels = 1; 2018 cval->channels = 1;
2023 cval->min = 1; 2019 cval->min = 1;
@@ -2088,11 +2084,8 @@ static int parse_audio_selector_unit(struct mixer_build *state, int unitid,
2088 } 2084 }
2089 2085
2090 usb_audio_dbg(state->chip, "[%d] SU [%s] items = %d\n", 2086 usb_audio_dbg(state->chip, "[%d] SU [%s] items = %d\n",
2091 cval->id, kctl->id.name, desc->bNrInPins); 2087 cval->head.id, kctl->id.name, desc->bNrInPins);
2092 if ((err = snd_usb_mixer_add_control(state->mixer, kctl)) < 0) 2088 return snd_usb_mixer_add_control(&cval->head, kctl);
2093 return err;
2094
2095 return 0;
2096} 2089}
2097 2090
2098/* 2091/*
@@ -2237,25 +2230,21 @@ static int snd_usb_mixer_controls(struct usb_mixer_interface *mixer)
2237 2230
2238void snd_usb_mixer_notify_id(struct usb_mixer_interface *mixer, int unitid) 2231void snd_usb_mixer_notify_id(struct usb_mixer_interface *mixer, int unitid)
2239{ 2232{
2240 struct usb_mixer_elem_info *info; 2233 struct usb_mixer_elem_list *list;
2241 2234
2242 for (info = mixer->id_elems[unitid]; info; info = info->next_id_elem) 2235 for (list = mixer->id_elems[unitid]; list; list = list->next_id_elem)
2243 snd_ctl_notify(mixer->chip->card, SNDRV_CTL_EVENT_MASK_VALUE, 2236 snd_ctl_notify(mixer->chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
2244 info->elem_id); 2237 &list->kctl->id);
2245} 2238}
2246 2239
2247static void snd_usb_mixer_dump_cval(struct snd_info_buffer *buffer, 2240static void snd_usb_mixer_dump_cval(struct snd_info_buffer *buffer,
2248 int unitid, 2241 struct usb_mixer_elem_list *list)
2249 struct usb_mixer_elem_info *cval)
2250{ 2242{
2243 struct usb_mixer_elem_info *cval = (struct usb_mixer_elem_info *)list;
2251 static char *val_types[] = {"BOOLEAN", "INV_BOOLEAN", 2244 static char *val_types[] = {"BOOLEAN", "INV_BOOLEAN",
2252 "S8", "U8", "S16", "U16"}; 2245 "S8", "U8", "S16", "U16"};
2253 snd_iprintf(buffer, " Unit: %i\n", unitid);
2254 if (cval->elem_id)
2255 snd_iprintf(buffer, " Control: name=\"%s\", index=%i\n",
2256 cval->elem_id->name, cval->elem_id->index);
2257 snd_iprintf(buffer, " Info: id=%i, control=%i, cmask=0x%x, " 2246 snd_iprintf(buffer, " Info: id=%i, control=%i, cmask=0x%x, "
2258 "channels=%i, type=\"%s\"\n", cval->id, 2247 "channels=%i, type=\"%s\"\n", cval->head.id,
2259 cval->control, cval->cmask, cval->channels, 2248 cval->control, cval->cmask, cval->channels,
2260 val_types[cval->val_type]); 2249 val_types[cval->val_type]);
2261 snd_iprintf(buffer, " Volume: min=%i, max=%i, dBmin=%i, dBmax=%i\n", 2250 snd_iprintf(buffer, " Volume: min=%i, max=%i, dBmin=%i, dBmax=%i\n",
@@ -2267,7 +2256,7 @@ static void snd_usb_mixer_proc_read(struct snd_info_entry *entry,
2267{ 2256{
2268 struct snd_usb_audio *chip = entry->private_data; 2257 struct snd_usb_audio *chip = entry->private_data;
2269 struct usb_mixer_interface *mixer; 2258 struct usb_mixer_interface *mixer;
2270 struct usb_mixer_elem_info *cval; 2259 struct usb_mixer_elem_list *list;
2271 int unitid; 2260 int unitid;
2272 2261
2273 list_for_each_entry(mixer, &chip->mixer_list, list) { 2262 list_for_each_entry(mixer, &chip->mixer_list, list) {
@@ -2277,9 +2266,17 @@ static void snd_usb_mixer_proc_read(struct snd_info_entry *entry,
2277 mixer->ignore_ctl_error); 2266 mixer->ignore_ctl_error);
2278 snd_iprintf(buffer, "Card: %s\n", chip->card->longname); 2267 snd_iprintf(buffer, "Card: %s\n", chip->card->longname);
2279 for (unitid = 0; unitid < MAX_ID_ELEMS; unitid++) { 2268 for (unitid = 0; unitid < MAX_ID_ELEMS; unitid++) {
2280 for (cval = mixer->id_elems[unitid]; cval; 2269 for (list = mixer->id_elems[unitid]; list;
2281 cval = cval->next_id_elem) 2270 list = list->next_id_elem) {
2282 snd_usb_mixer_dump_cval(buffer, unitid, cval); 2271 snd_iprintf(buffer, " Unit: %i\n", list->id);
2272 if (list->kctl)
2273 snd_iprintf(buffer,
2274 " Control: name=\"%s\", index=%i\n",
2275 list->kctl->id.name,
2276 list->kctl->id.index);
2277 if (list->dump)
2278 list->dump(buffer, list);
2279 }
2283 } 2280 }
2284 } 2281 }
2285} 2282}
@@ -2287,7 +2284,7 @@ static void snd_usb_mixer_proc_read(struct snd_info_entry *entry,
2287static void snd_usb_mixer_interrupt_v2(struct usb_mixer_interface *mixer, 2284static void snd_usb_mixer_interrupt_v2(struct usb_mixer_interface *mixer,
2288 int attribute, int value, int index) 2285 int attribute, int value, int index)
2289{ 2286{
2290 struct usb_mixer_elem_info *info; 2287 struct usb_mixer_elem_list *list;
2291 __u8 unitid = (index >> 8) & 0xff; 2288 __u8 unitid = (index >> 8) & 0xff;
2292 __u8 control = (value >> 8) & 0xff; 2289 __u8 control = (value >> 8) & 0xff;
2293 __u8 channel = value & 0xff; 2290 __u8 channel = value & 0xff;
@@ -2299,7 +2296,13 @@ static void snd_usb_mixer_interrupt_v2(struct usb_mixer_interface *mixer,
2299 return; 2296 return;
2300 } 2297 }
2301 2298
2302 for (info = mixer->id_elems[unitid]; info; info = info->next_id_elem) { 2299 for (list = mixer->id_elems[unitid]; list; list = list->next_id_elem) {
2300 struct usb_mixer_elem_info *info;
2301
2302 if (!list->kctl)
2303 continue;
2304
2305 info = (struct usb_mixer_elem_info *)list;
2303 if (info->control != control) 2306 if (info->control != control)
2304 continue; 2307 continue;
2305 2308
@@ -2312,7 +2315,7 @@ static void snd_usb_mixer_interrupt_v2(struct usb_mixer_interface *mixer,
2312 info->cached = 0; 2315 info->cached = 0;
2313 2316
2314 snd_ctl_notify(mixer->chip->card, SNDRV_CTL_EVENT_MASK_VALUE, 2317 snd_ctl_notify(mixer->chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
2315 info->elem_id); 2318 &info->head.kctl->id);
2316 break; 2319 break;
2317 2320
2318 case UAC2_CS_RANGE: 2321 case UAC2_CS_RANGE:
@@ -2510,8 +2513,9 @@ int snd_usb_mixer_suspend(struct usb_mixer_interface *mixer)
2510 return 0; 2513 return 0;
2511} 2514}
2512 2515
2513static int restore_mixer_value(struct usb_mixer_elem_info *cval) 2516static int restore_mixer_value(struct usb_mixer_elem_list *list)
2514{ 2517{
2518 struct usb_mixer_elem_info *cval = (struct usb_mixer_elem_info *)list;
2515 int c, err, idx; 2519 int c, err, idx;
2516 2520
2517 if (cval->cmask) { 2521 if (cval->cmask) {
@@ -2541,19 +2545,19 @@ static int restore_mixer_value(struct usb_mixer_elem_info *cval)
2541 2545
2542int snd_usb_mixer_resume(struct usb_mixer_interface *mixer, bool reset_resume) 2546int snd_usb_mixer_resume(struct usb_mixer_interface *mixer, bool reset_resume)
2543{ 2547{
2544 struct usb_mixer_elem_info *cval; 2548 struct usb_mixer_elem_list *list;
2545 int id, err; 2549 int id, err;
2546 2550
2547 /* FIXME: any mixer quirks? */
2548
2549 if (reset_resume) { 2551 if (reset_resume) {
2550 /* restore cached mixer values */ 2552 /* restore cached mixer values */
2551 for (id = 0; id < MAX_ID_ELEMS; id++) { 2553 for (id = 0; id < MAX_ID_ELEMS; id++) {
2552 for (cval = mixer->id_elems[id]; cval; 2554 for (list = mixer->id_elems[id]; list;
2553 cval = cval->next_id_elem) { 2555 list = list->next_id_elem) {
2554 err = restore_mixer_value(cval); 2556 if (list->resume) {
2555 if (err < 0) 2557 err = list->resume(list);
2556 return err; 2558 if (err < 0)
2559 return err;
2560 }
2557 } 2561 }
2558 } 2562 }
2559 } 2563 }
@@ -2561,3 +2565,15 @@ int snd_usb_mixer_resume(struct usb_mixer_interface *mixer, bool reset_resume)
2561 return snd_usb_mixer_activate(mixer); 2565 return snd_usb_mixer_activate(mixer);
2562} 2566}
2563#endif 2567#endif
2568
2569void snd_usb_mixer_elem_init_std(struct usb_mixer_elem_list *list,
2570 struct usb_mixer_interface *mixer,
2571 int unitid)
2572{
2573 list->mixer = mixer;
2574 list->id = unitid;
2575 list->dump = snd_usb_mixer_dump_cval;
2576#ifdef CONFIG_PM
2577 list->resume = restore_mixer_value;
2578#endif
2579}