diff options
author | Takashi Iwai <tiwai@suse.de> | 2014-12-08 05:33:24 -0500 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2014-12-08 05:33:24 -0500 |
commit | 77de61c3975da6f2200935c341e84018ece6ce36 (patch) | |
tree | 36508cf93ef62a80c988fa18c86eda1274e03877 /sound/usb | |
parent | 66139a48cee1530c91f37c145384b4ee7043f0b7 (diff) | |
parent | 048184540171672a724ab8f8bada7fcc0762f5c6 (diff) |
Merge branch 'for-next' into for-linus
Diffstat (limited to 'sound/usb')
-rw-r--r-- | sound/usb/6fire/control.c | 22 | ||||
-rw-r--r-- | sound/usb/6fire/firmware.c | 2 | ||||
-rw-r--r-- | sound/usb/6fire/pcm.c | 17 | ||||
-rw-r--r-- | sound/usb/Makefile | 1 | ||||
-rw-r--r-- | sound/usb/card.c | 109 | ||||
-rw-r--r-- | sound/usb/endpoint.c | 16 | ||||
-rw-r--r-- | sound/usb/endpoint.h | 2 | ||||
-rw-r--r-- | sound/usb/misc/ua101.c | 18 | ||||
-rw-r--r-- | sound/usb/mixer.c | 241 | ||||
-rw-r--r-- | sound/usb/mixer.h | 40 | ||||
-rw-r--r-- | sound/usb/mixer_maps.c | 9 | ||||
-rw-r--r-- | sound/usb/mixer_quirks.c | 920 | ||||
-rw-r--r-- | sound/usb/mixer_scarlett.c | 1004 | ||||
-rw-r--r-- | sound/usb/mixer_scarlett.h | 6 | ||||
-rw-r--r-- | sound/usb/pcm.c | 5 | ||||
-rw-r--r-- | sound/usb/quirks-table.h | 132 | ||||
-rw-r--r-- | sound/usb/quirks.c | 72 | ||||
-rw-r--r-- | sound/usb/quirks.h | 3 | ||||
-rw-r--r-- | sound/usb/usx2y/usbusx2yaudio.c | 9 |
19 files changed, 1915 insertions, 713 deletions
diff --git a/sound/usb/6fire/control.c b/sound/usb/6fire/control.c index 184e3987ac24..54656eed6e2e 100644 --- a/sound/usb/6fire/control.c +++ b/sound/usb/6fire/control.c | |||
@@ -25,8 +25,8 @@ | |||
25 | #include "comm.h" | 25 | #include "comm.h" |
26 | #include "chip.h" | 26 | #include "chip.h" |
27 | 27 | ||
28 | static char *opt_coax_texts[2] = { "Optical", "Coax" }; | 28 | static const char * const opt_coax_texts[2] = { "Optical", "Coax" }; |
29 | static char *line_phono_texts[2] = { "Line", "Phono" }; | 29 | static const char * const line_phono_texts[2] = { "Line", "Phono" }; |
30 | 30 | ||
31 | /* | 31 | /* |
32 | * data that needs to be sent to device. sets up card internal stuff. | 32 | * data that needs to be sent to device. sets up card internal stuff. |
@@ -327,14 +327,7 @@ static int usb6fire_control_input_vol_get(struct snd_kcontrol *kcontrol, | |||
327 | static int usb6fire_control_line_phono_info(struct snd_kcontrol *kcontrol, | 327 | static int usb6fire_control_line_phono_info(struct snd_kcontrol *kcontrol, |
328 | struct snd_ctl_elem_info *uinfo) | 328 | struct snd_ctl_elem_info *uinfo) |
329 | { | 329 | { |
330 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | 330 | return snd_ctl_enum_info(uinfo, 1, 2, line_phono_texts); |
331 | uinfo->count = 1; | ||
332 | uinfo->value.enumerated.items = 2; | ||
333 | if (uinfo->value.enumerated.item > 1) | ||
334 | uinfo->value.enumerated.item = 1; | ||
335 | strcpy(uinfo->value.enumerated.name, | ||
336 | line_phono_texts[uinfo->value.enumerated.item]); | ||
337 | return 0; | ||
338 | } | 331 | } |
339 | 332 | ||
340 | static int usb6fire_control_line_phono_put(struct snd_kcontrol *kcontrol, | 333 | static int usb6fire_control_line_phono_put(struct snd_kcontrol *kcontrol, |
@@ -361,14 +354,7 @@ static int usb6fire_control_line_phono_get(struct snd_kcontrol *kcontrol, | |||
361 | static int usb6fire_control_opt_coax_info(struct snd_kcontrol *kcontrol, | 354 | static int usb6fire_control_opt_coax_info(struct snd_kcontrol *kcontrol, |
362 | struct snd_ctl_elem_info *uinfo) | 355 | struct snd_ctl_elem_info *uinfo) |
363 | { | 356 | { |
364 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | 357 | return snd_ctl_enum_info(uinfo, 1, 2, opt_coax_texts); |
365 | uinfo->count = 1; | ||
366 | uinfo->value.enumerated.items = 2; | ||
367 | if (uinfo->value.enumerated.item > 1) | ||
368 | uinfo->value.enumerated.item = 1; | ||
369 | strcpy(uinfo->value.enumerated.name, | ||
370 | opt_coax_texts[uinfo->value.enumerated.item]); | ||
371 | return 0; | ||
372 | } | 358 | } |
373 | 359 | ||
374 | static int usb6fire_control_opt_coax_put(struct snd_kcontrol *kcontrol, | 360 | static int usb6fire_control_opt_coax_put(struct snd_kcontrol *kcontrol, |
diff --git a/sound/usb/6fire/firmware.c b/sound/usb/6fire/firmware.c index 3b02e54b8f6d..62c25e74f0e5 100644 --- a/sound/usb/6fire/firmware.c +++ b/sound/usb/6fire/firmware.c | |||
@@ -316,7 +316,7 @@ static int usb6fire_fw_fpga_upload( | |||
316 | 316 | ||
317 | while (c != end) { | 317 | while (c != end) { |
318 | for (i = 0; c != end && i < FPGA_BUFSIZE; i++, c++) | 318 | for (i = 0; c != end && i < FPGA_BUFSIZE; i++, c++) |
319 | buffer[i] = byte_rev_table[(u8) *c]; | 319 | buffer[i] = bitrev8((u8)*c); |
320 | 320 | ||
321 | ret = usb6fire_fw_fpga_write(device, buffer, i); | 321 | ret = usb6fire_fw_fpga_write(device, buffer, i); |
322 | if (ret < 0) { | 322 | if (ret < 0) { |
diff --git a/sound/usb/6fire/pcm.c b/sound/usb/6fire/pcm.c index ba40489b2de4..36f4115eb1cd 100644 --- a/sound/usb/6fire/pcm.c +++ b/sound/usb/6fire/pcm.c | |||
@@ -679,25 +679,16 @@ int usb6fire_pcm_init(struct sfire_chip *chip) | |||
679 | void usb6fire_pcm_abort(struct sfire_chip *chip) | 679 | void usb6fire_pcm_abort(struct sfire_chip *chip) |
680 | { | 680 | { |
681 | struct pcm_runtime *rt = chip->pcm; | 681 | struct pcm_runtime *rt = chip->pcm; |
682 | unsigned long flags; | ||
683 | int i; | 682 | int i; |
684 | 683 | ||
685 | if (rt) { | 684 | if (rt) { |
686 | rt->panic = true; | 685 | rt->panic = true; |
687 | 686 | ||
688 | if (rt->playback.instance) { | 687 | if (rt->playback.instance) |
689 | snd_pcm_stream_lock_irqsave(rt->playback.instance, flags); | 688 | snd_pcm_stop_xrun(rt->playback.instance); |
690 | snd_pcm_stop(rt->playback.instance, | ||
691 | SNDRV_PCM_STATE_XRUN); | ||
692 | snd_pcm_stream_unlock_irqrestore(rt->playback.instance, flags); | ||
693 | } | ||
694 | 689 | ||
695 | if (rt->capture.instance) { | 690 | if (rt->capture.instance) |
696 | snd_pcm_stream_lock_irqsave(rt->capture.instance, flags); | 691 | snd_pcm_stop_xrun(rt->capture.instance); |
697 | snd_pcm_stop(rt->capture.instance, | ||
698 | SNDRV_PCM_STATE_XRUN); | ||
699 | snd_pcm_stream_unlock_irqrestore(rt->capture.instance, flags); | ||
700 | } | ||
701 | 692 | ||
702 | for (i = 0; i < PCM_N_URBS; i++) { | 693 | for (i = 0; i < PCM_N_URBS; i++) { |
703 | usb_poison_urb(&rt->in_urbs[i].instance); | 694 | usb_poison_urb(&rt->in_urbs[i].instance); |
diff --git a/sound/usb/Makefile b/sound/usb/Makefile index 2b92f0dcbc4c..bcee4060fd18 100644 --- a/sound/usb/Makefile +++ b/sound/usb/Makefile | |||
@@ -9,6 +9,7 @@ snd-usb-audio-objs := card.o \ | |||
9 | helper.o \ | 9 | helper.o \ |
10 | mixer.o \ | 10 | mixer.o \ |
11 | mixer_quirks.o \ | 11 | mixer_quirks.o \ |
12 | mixer_scarlett.o \ | ||
12 | pcm.o \ | 13 | pcm.o \ |
13 | proc.o \ | 14 | proc.o \ |
14 | quirks.o \ | 15 | quirks.o \ |
diff --git a/sound/usb/card.c b/sound/usb/card.c index f61ebb17cc64..1fab9778807a 100644 --- a/sound/usb/card.c +++ b/sound/usb/card.c | |||
@@ -112,15 +112,13 @@ static struct usb_driver usb_audio_driver; | |||
112 | 112 | ||
113 | /* | 113 | /* |
114 | * disconnect streams | 114 | * disconnect streams |
115 | * called from snd_usb_audio_disconnect() | 115 | * called from usb_audio_disconnect() |
116 | */ | 116 | */ |
117 | static void snd_usb_stream_disconnect(struct list_head *head) | 117 | static void snd_usb_stream_disconnect(struct snd_usb_stream *as) |
118 | { | 118 | { |
119 | int idx; | 119 | int idx; |
120 | struct snd_usb_stream *as; | ||
121 | struct snd_usb_substream *subs; | 120 | struct snd_usb_substream *subs; |
122 | 121 | ||
123 | as = list_entry(head, struct snd_usb_stream, list); | ||
124 | for (idx = 0; idx < 2; idx++) { | 122 | for (idx = 0; idx < 2; idx++) { |
125 | subs = &as->substream[idx]; | 123 | subs = &as->substream[idx]; |
126 | if (!subs->num_formats) | 124 | if (!subs->num_formats) |
@@ -307,10 +305,10 @@ static int snd_usb_create_streams(struct snd_usb_audio *chip, int ctrlif) | |||
307 | 305 | ||
308 | static int snd_usb_audio_free(struct snd_usb_audio *chip) | 306 | static int snd_usb_audio_free(struct snd_usb_audio *chip) |
309 | { | 307 | { |
310 | struct list_head *p, *n; | 308 | struct snd_usb_endpoint *ep, *n; |
311 | 309 | ||
312 | list_for_each_safe(p, n, &chip->ep_list) | 310 | list_for_each_entry_safe(ep, n, &chip->ep_list, list) |
313 | snd_usb_endpoint_free(p); | 311 | snd_usb_endpoint_free(ep); |
314 | 312 | ||
315 | mutex_destroy(&chip->mutex); | 313 | mutex_destroy(&chip->mutex); |
316 | kfree(chip); | 314 | kfree(chip); |
@@ -323,16 +321,6 @@ static int snd_usb_audio_dev_free(struct snd_device *device) | |||
323 | return snd_usb_audio_free(chip); | 321 | return snd_usb_audio_free(chip); |
324 | } | 322 | } |
325 | 323 | ||
326 | static void remove_trailing_spaces(char *str) | ||
327 | { | ||
328 | char *p; | ||
329 | |||
330 | if (!*str) | ||
331 | return; | ||
332 | for (p = str + strlen(str) - 1; p >= str && isspace(*p); p--) | ||
333 | *p = 0; | ||
334 | } | ||
335 | |||
336 | /* | 324 | /* |
337 | * create a chip instance and set its names. | 325 | * create a chip instance and set its names. |
338 | */ | 326 | */ |
@@ -416,7 +404,7 @@ static int snd_usb_audio_create(struct usb_interface *intf, | |||
416 | USB_ID_PRODUCT(chip->usb_id)); | 404 | USB_ID_PRODUCT(chip->usb_id)); |
417 | } | 405 | } |
418 | } | 406 | } |
419 | remove_trailing_spaces(card->shortname); | 407 | strim(card->shortname); |
420 | 408 | ||
421 | /* retrieve the vendor and device strings as longname */ | 409 | /* retrieve the vendor and device strings as longname */ |
422 | if (quirk && quirk->vendor_name && *quirk->vendor_name) { | 410 | if (quirk && quirk->vendor_name && *quirk->vendor_name) { |
@@ -430,7 +418,7 @@ static int snd_usb_audio_create(struct usb_interface *intf, | |||
430 | /* we don't really care if there isn't any vendor string */ | 418 | /* we don't really care if there isn't any vendor string */ |
431 | } | 419 | } |
432 | if (len > 0) { | 420 | if (len > 0) { |
433 | remove_trailing_spaces(card->longname); | 421 | strim(card->longname); |
434 | if (*card->longname) | 422 | if (*card->longname) |
435 | strlcat(card->longname, " ", sizeof(card->longname)); | 423 | strlcat(card->longname, " ", sizeof(card->longname)); |
436 | } | 424 | } |
@@ -475,14 +463,14 @@ static int snd_usb_audio_create(struct usb_interface *intf, | |||
475 | * only at the first time. the successive calls of this function will | 463 | * only at the first time. the successive calls of this function will |
476 | * append the pcm interface to the corresponding card. | 464 | * append the pcm interface to the corresponding card. |
477 | */ | 465 | */ |
478 | static struct snd_usb_audio * | 466 | static int usb_audio_probe(struct usb_interface *intf, |
479 | snd_usb_audio_probe(struct usb_device *dev, | 467 | const struct usb_device_id *usb_id) |
480 | struct usb_interface *intf, | ||
481 | const struct usb_device_id *usb_id) | ||
482 | { | 468 | { |
483 | const struct snd_usb_audio_quirk *quirk = (const struct snd_usb_audio_quirk *)usb_id->driver_info; | 469 | struct usb_device *dev = interface_to_usbdev(intf); |
484 | int i, err; | 470 | const struct snd_usb_audio_quirk *quirk = |
471 | (const struct snd_usb_audio_quirk *)usb_id->driver_info; | ||
485 | struct snd_usb_audio *chip; | 472 | struct snd_usb_audio *chip; |
473 | int i, err; | ||
486 | struct usb_host_interface *alts; | 474 | struct usb_host_interface *alts; |
487 | int ifnum; | 475 | int ifnum; |
488 | u32 id; | 476 | u32 id; |
@@ -492,10 +480,11 @@ snd_usb_audio_probe(struct usb_device *dev, | |||
492 | id = USB_ID(le16_to_cpu(dev->descriptor.idVendor), | 480 | id = USB_ID(le16_to_cpu(dev->descriptor.idVendor), |
493 | le16_to_cpu(dev->descriptor.idProduct)); | 481 | le16_to_cpu(dev->descriptor.idProduct)); |
494 | if (quirk && quirk->ifnum >= 0 && ifnum != quirk->ifnum) | 482 | if (quirk && quirk->ifnum >= 0 && ifnum != quirk->ifnum) |
495 | goto __err_val; | 483 | return -ENXIO; |
496 | 484 | ||
497 | if (snd_usb_apply_boot_quirk(dev, intf, quirk) < 0) | 485 | err = snd_usb_apply_boot_quirk(dev, intf, quirk); |
498 | goto __err_val; | 486 | if (err < 0) |
487 | return err; | ||
499 | 488 | ||
500 | /* | 489 | /* |
501 | * found a config. now register to ALSA | 490 | * found a config. now register to ALSA |
@@ -508,6 +497,7 @@ snd_usb_audio_probe(struct usb_device *dev, | |||
508 | if (usb_chip[i] && usb_chip[i]->dev == dev) { | 497 | if (usb_chip[i] && usb_chip[i]->dev == dev) { |
509 | if (usb_chip[i]->shutdown) { | 498 | if (usb_chip[i]->shutdown) { |
510 | dev_err(&dev->dev, "USB device is in the shutdown state, cannot create a card instance\n"); | 499 | dev_err(&dev->dev, "USB device is in the shutdown state, cannot create a card instance\n"); |
500 | err = -EIO; | ||
511 | goto __error; | 501 | goto __error; |
512 | } | 502 | } |
513 | chip = usb_chip[i]; | 503 | chip = usb_chip[i]; |
@@ -523,15 +513,16 @@ snd_usb_audio_probe(struct usb_device *dev, | |||
523 | if (enable[i] && ! usb_chip[i] && | 513 | if (enable[i] && ! usb_chip[i] && |
524 | (vid[i] == -1 || vid[i] == USB_ID_VENDOR(id)) && | 514 | (vid[i] == -1 || vid[i] == USB_ID_VENDOR(id)) && |
525 | (pid[i] == -1 || pid[i] == USB_ID_PRODUCT(id))) { | 515 | (pid[i] == -1 || pid[i] == USB_ID_PRODUCT(id))) { |
526 | if (snd_usb_audio_create(intf, dev, i, quirk, | 516 | err = snd_usb_audio_create(intf, dev, i, quirk, |
527 | &chip) < 0) { | 517 | &chip); |
518 | if (err < 0) | ||
528 | goto __error; | 519 | goto __error; |
529 | } | ||
530 | chip->pm_intf = intf; | 520 | chip->pm_intf = intf; |
531 | break; | 521 | break; |
532 | } | 522 | } |
533 | if (!chip) { | 523 | if (!chip) { |
534 | dev_err(&dev->dev, "no available usb audio device\n"); | 524 | dev_err(&dev->dev, "no available usb audio device\n"); |
525 | err = -ENODEV; | ||
535 | goto __error; | 526 | goto __error; |
536 | } | 527 | } |
537 | } | 528 | } |
@@ -548,28 +539,32 @@ snd_usb_audio_probe(struct usb_device *dev, | |||
548 | err = 1; /* continue */ | 539 | err = 1; /* continue */ |
549 | if (quirk && quirk->ifnum != QUIRK_NO_INTERFACE) { | 540 | if (quirk && quirk->ifnum != QUIRK_NO_INTERFACE) { |
550 | /* need some special handlings */ | 541 | /* need some special handlings */ |
551 | if ((err = snd_usb_create_quirk(chip, intf, &usb_audio_driver, quirk)) < 0) | 542 | err = snd_usb_create_quirk(chip, intf, &usb_audio_driver, quirk); |
543 | if (err < 0) | ||
552 | goto __error; | 544 | goto __error; |
553 | } | 545 | } |
554 | 546 | ||
555 | if (err > 0) { | 547 | if (err > 0) { |
556 | /* create normal USB audio interfaces */ | 548 | /* create normal USB audio interfaces */ |
557 | if (snd_usb_create_streams(chip, ifnum) < 0 || | 549 | err = snd_usb_create_streams(chip, ifnum); |
558 | snd_usb_create_mixer(chip, ifnum, ignore_ctl_error) < 0) { | 550 | if (err < 0) |
551 | goto __error; | ||
552 | err = snd_usb_create_mixer(chip, ifnum, ignore_ctl_error); | ||
553 | if (err < 0) | ||
559 | goto __error; | 554 | goto __error; |
560 | } | ||
561 | } | 555 | } |
562 | 556 | ||
563 | /* we are allowed to call snd_card_register() many times */ | 557 | /* we are allowed to call snd_card_register() many times */ |
564 | if (snd_card_register(chip->card) < 0) { | 558 | err = snd_card_register(chip->card); |
559 | if (err < 0) | ||
565 | goto __error; | 560 | goto __error; |
566 | } | ||
567 | 561 | ||
568 | usb_chip[chip->index] = chip; | 562 | usb_chip[chip->index] = chip; |
569 | chip->num_interfaces++; | 563 | chip->num_interfaces++; |
570 | chip->probing = 0; | 564 | chip->probing = 0; |
565 | usb_set_intfdata(intf, chip); | ||
571 | mutex_unlock(®ister_mutex); | 566 | mutex_unlock(®ister_mutex); |
572 | return chip; | 567 | return 0; |
573 | 568 | ||
574 | __error: | 569 | __error: |
575 | if (chip) { | 570 | if (chip) { |
@@ -578,17 +573,16 @@ snd_usb_audio_probe(struct usb_device *dev, | |||
578 | chip->probing = 0; | 573 | chip->probing = 0; |
579 | } | 574 | } |
580 | mutex_unlock(®ister_mutex); | 575 | mutex_unlock(®ister_mutex); |
581 | __err_val: | 576 | return err; |
582 | return NULL; | ||
583 | } | 577 | } |
584 | 578 | ||
585 | /* | 579 | /* |
586 | * we need to take care of counter, since disconnection can be called also | 580 | * we need to take care of counter, since disconnection can be called also |
587 | * many times as well as usb_audio_probe(). | 581 | * many times as well as usb_audio_probe(). |
588 | */ | 582 | */ |
589 | static void snd_usb_audio_disconnect(struct usb_device *dev, | 583 | static void usb_audio_disconnect(struct usb_interface *intf) |
590 | struct snd_usb_audio *chip) | ||
591 | { | 584 | { |
585 | struct snd_usb_audio *chip = usb_get_intfdata(intf); | ||
592 | struct snd_card *card; | 586 | struct snd_card *card; |
593 | struct list_head *p; | 587 | struct list_head *p; |
594 | bool was_shutdown; | 588 | bool was_shutdown; |
@@ -604,12 +598,14 @@ static void snd_usb_audio_disconnect(struct usb_device *dev, | |||
604 | 598 | ||
605 | mutex_lock(®ister_mutex); | 599 | mutex_lock(®ister_mutex); |
606 | if (!was_shutdown) { | 600 | if (!was_shutdown) { |
601 | struct snd_usb_stream *as; | ||
607 | struct snd_usb_endpoint *ep; | 602 | struct snd_usb_endpoint *ep; |
603 | struct usb_mixer_interface *mixer; | ||
608 | 604 | ||
609 | snd_card_disconnect(card); | 605 | snd_card_disconnect(card); |
610 | /* release the pcm resources */ | 606 | /* release the pcm resources */ |
611 | list_for_each(p, &chip->pcm_list) { | 607 | list_for_each_entry(as, &chip->pcm_list, list) { |
612 | snd_usb_stream_disconnect(p); | 608 | snd_usb_stream_disconnect(as); |
613 | } | 609 | } |
614 | /* release the endpoint resources */ | 610 | /* release the endpoint resources */ |
615 | list_for_each_entry(ep, &chip->ep_list, list) { | 611 | list_for_each_entry(ep, &chip->ep_list, list) { |
@@ -620,8 +616,8 @@ static void snd_usb_audio_disconnect(struct usb_device *dev, | |||
620 | snd_usbmidi_disconnect(p); | 616 | snd_usbmidi_disconnect(p); |
621 | } | 617 | } |
622 | /* release mixer resources */ | 618 | /* release mixer resources */ |
623 | list_for_each(p, &chip->mixer_list) { | 619 | list_for_each_entry(mixer, &chip->mixer_list, list) { |
624 | snd_usb_mixer_disconnect(p); | 620 | snd_usb_mixer_disconnect(mixer); |
625 | } | 621 | } |
626 | } | 622 | } |
627 | 623 | ||
@@ -635,27 +631,6 @@ static void snd_usb_audio_disconnect(struct usb_device *dev, | |||
635 | } | 631 | } |
636 | } | 632 | } |
637 | 633 | ||
638 | /* | ||
639 | * new 2.5 USB kernel API | ||
640 | */ | ||
641 | static int usb_audio_probe(struct usb_interface *intf, | ||
642 | const struct usb_device_id *id) | ||
643 | { | ||
644 | struct snd_usb_audio *chip; | ||
645 | chip = snd_usb_audio_probe(interface_to_usbdev(intf), intf, id); | ||
646 | if (chip) { | ||
647 | usb_set_intfdata(intf, chip); | ||
648 | return 0; | ||
649 | } else | ||
650 | return -EIO; | ||
651 | } | ||
652 | |||
653 | static void usb_audio_disconnect(struct usb_interface *intf) | ||
654 | { | ||
655 | snd_usb_audio_disconnect(interface_to_usbdev(intf), | ||
656 | usb_get_intfdata(intf)); | ||
657 | } | ||
658 | |||
659 | #ifdef CONFIG_PM | 634 | #ifdef CONFIG_PM |
660 | 635 | ||
661 | int snd_usb_autoresume(struct snd_usb_audio *chip) | 636 | int snd_usb_autoresume(struct snd_usb_audio *chip) |
diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c index 114e3e7ff511..03b074419964 100644 --- a/sound/usb/endpoint.c +++ b/sound/usb/endpoint.c | |||
@@ -348,6 +348,8 @@ static void snd_complete_urb(struct urb *urb) | |||
348 | { | 348 | { |
349 | struct snd_urb_ctx *ctx = urb->context; | 349 | struct snd_urb_ctx *ctx = urb->context; |
350 | struct snd_usb_endpoint *ep = ctx->ep; | 350 | struct snd_usb_endpoint *ep = ctx->ep; |
351 | struct snd_pcm_substream *substream; | ||
352 | unsigned long flags; | ||
351 | int err; | 353 | int err; |
352 | 354 | ||
353 | if (unlikely(urb->status == -ENOENT || /* unlinked */ | 355 | if (unlikely(urb->status == -ENOENT || /* unlinked */ |
@@ -364,8 +366,6 @@ static void snd_complete_urb(struct urb *urb) | |||
364 | goto exit_clear; | 366 | goto exit_clear; |
365 | 367 | ||
366 | if (snd_usb_endpoint_implicit_feedback_sink(ep)) { | 368 | if (snd_usb_endpoint_implicit_feedback_sink(ep)) { |
367 | unsigned long flags; | ||
368 | |||
369 | spin_lock_irqsave(&ep->lock, flags); | 369 | spin_lock_irqsave(&ep->lock, flags); |
370 | list_add_tail(&ctx->ready_list, &ep->ready_playback_urbs); | 370 | list_add_tail(&ctx->ready_list, &ep->ready_playback_urbs); |
371 | spin_unlock_irqrestore(&ep->lock, flags); | 371 | spin_unlock_irqrestore(&ep->lock, flags); |
@@ -389,7 +389,10 @@ static void snd_complete_urb(struct urb *urb) | |||
389 | return; | 389 | return; |
390 | 390 | ||
391 | usb_audio_err(ep->chip, "cannot submit urb (err = %d)\n", err); | 391 | usb_audio_err(ep->chip, "cannot submit urb (err = %d)\n", err); |
392 | //snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN); | 392 | if (ep->data_subs && ep->data_subs->pcm_substream) { |
393 | substream = ep->data_subs->pcm_substream; | ||
394 | snd_pcm_stop_xrun(substream); | ||
395 | } | ||
393 | 396 | ||
394 | exit_clear: | 397 | exit_clear: |
395 | clear_bit(ctx->index, &ep->active_mask); | 398 | clear_bit(ctx->index, &ep->active_mask); |
@@ -1002,15 +1005,12 @@ void snd_usb_endpoint_release(struct snd_usb_endpoint *ep) | |||
1002 | /** | 1005 | /** |
1003 | * snd_usb_endpoint_free: Free the resources of an snd_usb_endpoint | 1006 | * snd_usb_endpoint_free: Free the resources of an snd_usb_endpoint |
1004 | * | 1007 | * |
1005 | * @ep: the list header of the endpoint to free | 1008 | * @ep: the endpoint to free |
1006 | * | 1009 | * |
1007 | * This free all resources of the given ep. | 1010 | * This free all resources of the given ep. |
1008 | */ | 1011 | */ |
1009 | void snd_usb_endpoint_free(struct list_head *head) | 1012 | void snd_usb_endpoint_free(struct snd_usb_endpoint *ep) |
1010 | { | 1013 | { |
1011 | struct snd_usb_endpoint *ep; | ||
1012 | |||
1013 | ep = list_entry(head, struct snd_usb_endpoint, list); | ||
1014 | kfree(ep); | 1014 | kfree(ep); |
1015 | } | 1015 | } |
1016 | 1016 | ||
diff --git a/sound/usb/endpoint.h b/sound/usb/endpoint.h index e61ee5c356a3..6428392d8f62 100644 --- a/sound/usb/endpoint.h +++ b/sound/usb/endpoint.h | |||
@@ -24,7 +24,7 @@ void snd_usb_endpoint_sync_pending_stop(struct snd_usb_endpoint *ep); | |||
24 | int snd_usb_endpoint_activate(struct snd_usb_endpoint *ep); | 24 | int snd_usb_endpoint_activate(struct snd_usb_endpoint *ep); |
25 | void snd_usb_endpoint_deactivate(struct snd_usb_endpoint *ep); | 25 | void snd_usb_endpoint_deactivate(struct snd_usb_endpoint *ep); |
26 | void snd_usb_endpoint_release(struct snd_usb_endpoint *ep); | 26 | void snd_usb_endpoint_release(struct snd_usb_endpoint *ep); |
27 | void snd_usb_endpoint_free(struct list_head *head); | 27 | void snd_usb_endpoint_free(struct snd_usb_endpoint *ep); |
28 | 28 | ||
29 | int snd_usb_endpoint_implicit_feedback_sink(struct snd_usb_endpoint *ep); | 29 | int snd_usb_endpoint_implicit_feedback_sink(struct snd_usb_endpoint *ep); |
30 | int snd_usb_endpoint_next_packet_size(struct snd_usb_endpoint *ep); | 30 | int snd_usb_endpoint_next_packet_size(struct snd_usb_endpoint *ep); |
diff --git a/sound/usb/misc/ua101.c b/sound/usb/misc/ua101.c index a1bab149df4d..9581089c28c5 100644 --- a/sound/usb/misc/ua101.c +++ b/sound/usb/misc/ua101.c | |||
@@ -613,24 +613,14 @@ static int start_usb_playback(struct ua101 *ua) | |||
613 | 613 | ||
614 | static void abort_alsa_capture(struct ua101 *ua) | 614 | static void abort_alsa_capture(struct ua101 *ua) |
615 | { | 615 | { |
616 | unsigned long flags; | 616 | if (test_bit(ALSA_CAPTURE_RUNNING, &ua->states)) |
617 | 617 | snd_pcm_stop_xrun(ua->capture.substream); | |
618 | if (test_bit(ALSA_CAPTURE_RUNNING, &ua->states)) { | ||
619 | snd_pcm_stream_lock_irqsave(ua->capture.substream, flags); | ||
620 | snd_pcm_stop(ua->capture.substream, SNDRV_PCM_STATE_XRUN); | ||
621 | snd_pcm_stream_unlock_irqrestore(ua->capture.substream, flags); | ||
622 | } | ||
623 | } | 618 | } |
624 | 619 | ||
625 | static void abort_alsa_playback(struct ua101 *ua) | 620 | static void abort_alsa_playback(struct ua101 *ua) |
626 | { | 621 | { |
627 | unsigned long flags; | 622 | if (test_bit(ALSA_PLAYBACK_RUNNING, &ua->states)) |
628 | 623 | snd_pcm_stop_xrun(ua->playback.substream); | |
629 | if (test_bit(ALSA_PLAYBACK_RUNNING, &ua->states)) { | ||
630 | snd_pcm_stream_lock_irqsave(ua->playback.substream, flags); | ||
631 | snd_pcm_stop(ua->playback.substream, SNDRV_PCM_STATE_XRUN); | ||
632 | snd_pcm_stream_unlock_irqrestore(ua->playback.substream, flags); | ||
633 | } | ||
634 | } | 624 | } |
635 | 625 | ||
636 | static int set_stream_hw(struct ua101 *ua, struct snd_pcm_substream *substream, | 626 | static int set_stream_hw(struct ua101 *ua, struct snd_pcm_substream *substream, |
diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c index 6e354d326858..41650d5b93b7 100644 --- a/sound/usb/mixer.c +++ b/sound/usb/mixer.c | |||
@@ -136,6 +136,10 @@ check_mapped_name(const struct usbmix_name_map *p, char *buf, int buflen) | |||
136 | return strlcpy(buf, p->name, buflen); | 136 | return strlcpy(buf, p->name, buflen); |
137 | } | 137 | } |
138 | 138 | ||
139 | /* ignore the error value if ignore_ctl_error flag is set */ | ||
140 | #define filter_error(cval, err) \ | ||
141 | ((cval)->head.mixer->ignore_ctl_error ? 0 : (err)) | ||
142 | |||
139 | /* check whether the control should be ignored */ | 143 | /* check whether the control should be ignored */ |
140 | static inline int | 144 | static inline int |
141 | check_ignored_ctl(const struct usbmix_name_map *p) | 145 | check_ignored_ctl(const struct usbmix_name_map *p) |
@@ -286,13 +290,13 @@ static int get_abs_value(struct usb_mixer_elem_info *cval, int val) | |||
286 | static int get_ctl_value_v1(struct usb_mixer_elem_info *cval, int request, | 290 | static int get_ctl_value_v1(struct usb_mixer_elem_info *cval, int request, |
287 | int validx, int *value_ret) | 291 | int validx, int *value_ret) |
288 | { | 292 | { |
289 | struct snd_usb_audio *chip = cval->mixer->chip; | 293 | struct snd_usb_audio *chip = cval->head.mixer->chip; |
290 | unsigned char buf[2]; | 294 | unsigned char buf[2]; |
291 | int val_len = cval->val_type >= USB_MIXER_S16 ? 2 : 1; | 295 | int val_len = cval->val_type >= USB_MIXER_S16 ? 2 : 1; |
292 | int timeout = 10; | 296 | int timeout = 10; |
293 | int idx = 0, err; | 297 | int idx = 0, err; |
294 | 298 | ||
295 | err = snd_usb_autoresume(cval->mixer->chip); | 299 | err = snd_usb_autoresume(chip); |
296 | if (err < 0) | 300 | if (err < 0) |
297 | return -EIO; | 301 | return -EIO; |
298 | 302 | ||
@@ -300,7 +304,7 @@ static int get_ctl_value_v1(struct usb_mixer_elem_info *cval, int request, | |||
300 | while (timeout-- > 0) { | 304 | while (timeout-- > 0) { |
301 | if (chip->shutdown) | 305 | if (chip->shutdown) |
302 | break; | 306 | break; |
303 | idx = snd_usb_ctrl_intf(chip) | (cval->id << 8); | 307 | idx = snd_usb_ctrl_intf(chip) | (cval->head.id << 8); |
304 | 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, |
305 | USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, | 309 | USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, |
306 | validx, idx, buf, val_len) >= val_len) { | 310 | validx, idx, buf, val_len) >= val_len) { |
@@ -316,14 +320,14 @@ static int get_ctl_value_v1(struct usb_mixer_elem_info *cval, int request, | |||
316 | 320 | ||
317 | out: | 321 | out: |
318 | up_read(&chip->shutdown_rwsem); | 322 | up_read(&chip->shutdown_rwsem); |
319 | snd_usb_autosuspend(cval->mixer->chip); | 323 | snd_usb_autosuspend(chip); |
320 | return err; | 324 | return err; |
321 | } | 325 | } |
322 | 326 | ||
323 | static int get_ctl_value_v2(struct usb_mixer_elem_info *cval, int request, | 327 | static int get_ctl_value_v2(struct usb_mixer_elem_info *cval, int request, |
324 | int validx, int *value_ret) | 328 | int validx, int *value_ret) |
325 | { | 329 | { |
326 | struct snd_usb_audio *chip = cval->mixer->chip; | 330 | struct snd_usb_audio *chip = cval->head.mixer->chip; |
327 | 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 */ |
328 | unsigned char *val; | 332 | unsigned char *val; |
329 | int idx = 0, ret, size; | 333 | int idx = 0, ret, size; |
@@ -347,7 +351,7 @@ static int get_ctl_value_v2(struct usb_mixer_elem_info *cval, int request, | |||
347 | if (chip->shutdown) { | 351 | if (chip->shutdown) { |
348 | ret = -ENODEV; | 352 | ret = -ENODEV; |
349 | } else { | 353 | } else { |
350 | idx = snd_usb_ctrl_intf(chip) | (cval->id << 8); | 354 | idx = snd_usb_ctrl_intf(chip) | (cval->head.id << 8); |
351 | 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, |
352 | USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, | 356 | USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, |
353 | validx, idx, buf, size); | 357 | validx, idx, buf, size); |
@@ -392,7 +396,7 @@ static int get_ctl_value(struct usb_mixer_elem_info *cval, int request, | |||
392 | { | 396 | { |
393 | validx += cval->idx_off; | 397 | validx += cval->idx_off; |
394 | 398 | ||
395 | return (cval->mixer->protocol == UAC_VERSION_1) ? | 399 | return (cval->head.mixer->protocol == UAC_VERSION_1) ? |
396 | get_ctl_value_v1(cval, request, validx, value_ret) : | 400 | get_ctl_value_v1(cval, request, validx, value_ret) : |
397 | get_ctl_value_v2(cval, request, validx, value_ret); | 401 | get_ctl_value_v2(cval, request, validx, value_ret); |
398 | } | 402 | } |
@@ -412,7 +416,7 @@ static inline int get_cur_mix_raw(struct usb_mixer_elem_info *cval, | |||
412 | value); | 416 | value); |
413 | } | 417 | } |
414 | 418 | ||
415 | static int get_cur_mix_value(struct usb_mixer_elem_info *cval, | 419 | int snd_usb_get_cur_mix_value(struct usb_mixer_elem_info *cval, |
416 | int channel, int index, int *value) | 420 | int channel, int index, int *value) |
417 | { | 421 | { |
418 | int err; | 422 | int err; |
@@ -423,8 +427,8 @@ static int get_cur_mix_value(struct usb_mixer_elem_info *cval, | |||
423 | } | 427 | } |
424 | err = get_cur_mix_raw(cval, channel, value); | 428 | err = get_cur_mix_raw(cval, channel, value); |
425 | if (err < 0) { | 429 | if (err < 0) { |
426 | if (!cval->mixer->ignore_ctl_error) | 430 | if (!cval->head.mixer->ignore_ctl_error) |
427 | usb_audio_dbg(cval->mixer->chip, | 431 | usb_audio_dbg(cval->head.mixer->chip, |
428 | "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", |
429 | cval->control, channel, err); | 433 | cval->control, channel, err); |
430 | return err; | 434 | return err; |
@@ -441,13 +445,13 @@ static int get_cur_mix_value(struct usb_mixer_elem_info *cval, | |||
441 | int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval, | 445 | int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval, |
442 | int request, int validx, int value_set) | 446 | int request, int validx, int value_set) |
443 | { | 447 | { |
444 | struct snd_usb_audio *chip = cval->mixer->chip; | 448 | struct snd_usb_audio *chip = cval->head.mixer->chip; |
445 | unsigned char buf[2]; | 449 | unsigned char buf[2]; |
446 | int idx = 0, val_len, err, timeout = 10; | 450 | int idx = 0, val_len, err, timeout = 10; |
447 | 451 | ||
448 | validx += cval->idx_off; | 452 | validx += cval->idx_off; |
449 | 453 | ||
450 | if (cval->mixer->protocol == UAC_VERSION_1) { | 454 | if (cval->head.mixer->protocol == UAC_VERSION_1) { |
451 | val_len = cval->val_type >= USB_MIXER_S16 ? 2 : 1; | 455 | val_len = cval->val_type >= USB_MIXER_S16 ? 2 : 1; |
452 | } else { /* UAC_VERSION_2 */ | 456 | } else { /* UAC_VERSION_2 */ |
453 | /* audio class v2 controls are always 2 bytes in size */ | 457 | /* audio class v2 controls are always 2 bytes in size */ |
@@ -472,7 +476,7 @@ int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval, | |||
472 | while (timeout-- > 0) { | 476 | while (timeout-- > 0) { |
473 | if (chip->shutdown) | 477 | if (chip->shutdown) |
474 | break; | 478 | break; |
475 | idx = snd_usb_ctrl_intf(chip) | (cval->id << 8); | 479 | idx = snd_usb_ctrl_intf(chip) | (cval->head.id << 8); |
476 | if (snd_usb_ctl_msg(chip->dev, | 480 | if (snd_usb_ctl_msg(chip->dev, |
477 | usb_sndctrlpipe(chip->dev, 0), request, | 481 | usb_sndctrlpipe(chip->dev, 0), request, |
478 | USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT, | 482 | USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT, |
@@ -497,7 +501,7 @@ static int set_cur_ctl_value(struct usb_mixer_elem_info *cval, | |||
497 | return snd_usb_mixer_set_ctl_value(cval, UAC_SET_CUR, validx, value); | 501 | return snd_usb_mixer_set_ctl_value(cval, UAC_SET_CUR, validx, value); |
498 | } | 502 | } |
499 | 503 | ||
500 | static int set_cur_mix_value(struct usb_mixer_elem_info *cval, int channel, | 504 | int snd_usb_set_cur_mix_value(struct usb_mixer_elem_info *cval, int channel, |
501 | int index, int value) | 505 | int index, int value) |
502 | { | 506 | { |
503 | int err; | 507 | int err; |
@@ -506,7 +510,7 @@ static int set_cur_mix_value(struct usb_mixer_elem_info *cval, int channel, | |||
506 | cval->ch_readonly & (1 << (channel - 1)); | 510 | cval->ch_readonly & (1 << (channel - 1)); |
507 | 511 | ||
508 | if (read_only) { | 512 | if (read_only) { |
509 | usb_audio_dbg(cval->mixer->chip, | 513 | usb_audio_dbg(cval->head.mixer->chip, |
510 | "%s(): channel %d of control %d is read_only\n", | 514 | "%s(): channel %d of control %d is read_only\n", |
511 | __func__, channel, cval->control); | 515 | __func__, channel, cval->control); |
512 | return 0; | 516 | return 0; |
@@ -565,10 +569,10 @@ static int check_matrix_bitmap(unsigned char *bmap, | |||
565 | * if failed, give up and free the control instance. | 569 | * if failed, give up and free the control instance. |
566 | */ | 570 | */ |
567 | 571 | ||
568 | int snd_usb_mixer_add_control(struct usb_mixer_interface *mixer, | 572 | int snd_usb_mixer_add_control(struct usb_mixer_elem_list *list, |
569 | struct snd_kcontrol *kctl) | 573 | struct snd_kcontrol *kctl) |
570 | { | 574 | { |
571 | struct usb_mixer_elem_info *cval = kctl->private_data; | 575 | struct usb_mixer_interface *mixer = list->mixer; |
572 | int err; | 576 | int err; |
573 | 577 | ||
574 | while (snd_ctl_find_id(mixer->chip->card, &kctl->id)) | 578 | while (snd_ctl_find_id(mixer->chip->card, &kctl->id)) |
@@ -578,9 +582,9 @@ int snd_usb_mixer_add_control(struct usb_mixer_interface *mixer, | |||
578 | err); | 582 | err); |
579 | return err; | 583 | return err; |
580 | } | 584 | } |
581 | cval->elem_id = &kctl->id; | 585 | list->kctl = kctl; |
582 | cval->next_id_elem = mixer->id_elems[cval->id]; | 586 | list->next_id_elem = mixer->id_elems[list->id]; |
583 | mixer->id_elems[cval->id] = cval; | 587 | mixer->id_elems[list->id] = list; |
584 | return 0; | 588 | return 0; |
585 | } | 589 | } |
586 | 590 | ||
@@ -815,7 +819,7 @@ static struct usb_feature_control_info audio_feature_info[] = { | |||
815 | }; | 819 | }; |
816 | 820 | ||
817 | /* private_free callback */ | 821 | /* private_free callback */ |
818 | static void usb_mixer_elem_free(struct snd_kcontrol *kctl) | 822 | void snd_usb_mixer_elem_free(struct snd_kcontrol *kctl) |
819 | { | 823 | { |
820 | kfree(kctl->private_data); | 824 | kfree(kctl->private_data); |
821 | kctl->private_data = NULL; | 825 | kctl->private_data = NULL; |
@@ -829,7 +833,7 @@ static void usb_mixer_elem_free(struct snd_kcontrol *kctl) | |||
829 | static void volume_control_quirks(struct usb_mixer_elem_info *cval, | 833 | static void volume_control_quirks(struct usb_mixer_elem_info *cval, |
830 | struct snd_kcontrol *kctl) | 834 | struct snd_kcontrol *kctl) |
831 | { | 835 | { |
832 | struct snd_usb_audio *chip = cval->mixer->chip; | 836 | struct snd_usb_audio *chip = cval->head.mixer->chip; |
833 | switch (chip->usb_id) { | 837 | switch (chip->usb_id) { |
834 | case USB_ID(0x0763, 0x2030): /* M-Audio Fast Track C400 */ | 838 | case USB_ID(0x0763, 0x2030): /* M-Audio Fast Track C400 */ |
835 | case USB_ID(0x0763, 0x2031): /* M-Audio Fast Track C600 */ | 839 | case USB_ID(0x0763, 0x2031): /* M-Audio Fast Track C600 */ |
@@ -954,10 +958,10 @@ static int get_min_max_with_quirks(struct usb_mixer_elem_info *cval, | |||
954 | } | 958 | } |
955 | 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 || |
956 | 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) { |
957 | usb_audio_err(cval->mixer->chip, | 961 | usb_audio_err(cval->head.mixer->chip, |
958 | "%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", |
959 | cval->id, snd_usb_ctrl_intf(cval->mixer->chip), | 963 | cval->head.id, snd_usb_ctrl_intf(cval->head.mixer->chip), |
960 | cval->control, cval->id); | 964 | cval->control, cval->head.id); |
961 | return -EINVAL; | 965 | return -EINVAL; |
962 | } | 966 | } |
963 | if (get_ctl_value(cval, UAC_GET_RES, | 967 | if (get_ctl_value(cval, UAC_GET_RES, |
@@ -998,7 +1002,7 @@ static int get_min_max_with_quirks(struct usb_mixer_elem_info *cval, | |||
998 | else | 1002 | else |
999 | test -= cval->res; | 1003 | test -= cval->res; |
1000 | if (test < cval->min || test > cval->max || | 1004 | if (test < cval->min || test > cval->max || |
1001 | set_cur_mix_value(cval, minchn, 0, test) || | 1005 | snd_usb_set_cur_mix_value(cval, minchn, 0, test) || |
1002 | get_cur_mix_raw(cval, minchn, &check)) { | 1006 | get_cur_mix_raw(cval, minchn, &check)) { |
1003 | cval->res = last_valid_res; | 1007 | cval->res = last_valid_res; |
1004 | break; | 1008 | break; |
@@ -1007,7 +1011,7 @@ static int get_min_max_with_quirks(struct usb_mixer_elem_info *cval, | |||
1007 | break; | 1011 | break; |
1008 | cval->res *= 2; | 1012 | cval->res *= 2; |
1009 | } | 1013 | } |
1010 | set_cur_mix_value(cval, minchn, 0, saved); | 1014 | snd_usb_set_cur_mix_value(cval, minchn, 0, saved); |
1011 | } | 1015 | } |
1012 | 1016 | ||
1013 | cval->initialized = 1; | 1017 | cval->initialized = 1; |
@@ -1061,7 +1065,7 @@ static int mixer_ctl_feature_info(struct snd_kcontrol *kcontrol, | |||
1061 | kcontrol->vd[0].access &= | 1065 | kcontrol->vd[0].access &= |
1062 | ~(SNDRV_CTL_ELEM_ACCESS_TLV_READ | | 1066 | ~(SNDRV_CTL_ELEM_ACCESS_TLV_READ | |
1063 | SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK); | 1067 | SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK); |
1064 | snd_ctl_notify(cval->mixer->chip->card, | 1068 | snd_ctl_notify(cval->head.mixer->chip->card, |
1065 | SNDRV_CTL_EVENT_MASK_INFO, | 1069 | SNDRV_CTL_EVENT_MASK_INFO, |
1066 | &kcontrol->id); | 1070 | &kcontrol->id); |
1067 | } | 1071 | } |
@@ -1086,9 +1090,9 @@ static int mixer_ctl_feature_get(struct snd_kcontrol *kcontrol, | |||
1086 | for (c = 0; c < MAX_CHANNELS; c++) { | 1090 | for (c = 0; c < MAX_CHANNELS; c++) { |
1087 | if (!(cval->cmask & (1 << c))) | 1091 | if (!(cval->cmask & (1 << c))) |
1088 | continue; | 1092 | continue; |
1089 | err = get_cur_mix_value(cval, c + 1, cnt, &val); | 1093 | err = snd_usb_get_cur_mix_value(cval, c + 1, cnt, &val); |
1090 | if (err < 0) | 1094 | if (err < 0) |
1091 | return cval->mixer->ignore_ctl_error ? 0 : err; | 1095 | return filter_error(cval, err); |
1092 | val = get_relative_value(cval, val); | 1096 | val = get_relative_value(cval, val); |
1093 | ucontrol->value.integer.value[cnt] = val; | 1097 | ucontrol->value.integer.value[cnt] = val; |
1094 | cnt++; | 1098 | cnt++; |
@@ -1096,9 +1100,9 @@ static int mixer_ctl_feature_get(struct snd_kcontrol *kcontrol, | |||
1096 | return 0; | 1100 | return 0; |
1097 | } else { | 1101 | } else { |
1098 | /* master channel */ | 1102 | /* master channel */ |
1099 | err = get_cur_mix_value(cval, 0, 0, &val); | 1103 | err = snd_usb_get_cur_mix_value(cval, 0, 0, &val); |
1100 | if (err < 0) | 1104 | if (err < 0) |
1101 | return cval->mixer->ignore_ctl_error ? 0 : err; | 1105 | return filter_error(cval, err); |
1102 | val = get_relative_value(cval, val); | 1106 | val = get_relative_value(cval, val); |
1103 | ucontrol->value.integer.value[0] = val; | 1107 | ucontrol->value.integer.value[0] = val; |
1104 | } | 1108 | } |
@@ -1118,26 +1122,26 @@ static int mixer_ctl_feature_put(struct snd_kcontrol *kcontrol, | |||
1118 | for (c = 0; c < MAX_CHANNELS; c++) { | 1122 | for (c = 0; c < MAX_CHANNELS; c++) { |
1119 | if (!(cval->cmask & (1 << c))) | 1123 | if (!(cval->cmask & (1 << c))) |
1120 | continue; | 1124 | continue; |
1121 | err = get_cur_mix_value(cval, c + 1, cnt, &oval); | 1125 | err = snd_usb_get_cur_mix_value(cval, c + 1, cnt, &oval); |
1122 | if (err < 0) | 1126 | if (err < 0) |
1123 | return cval->mixer->ignore_ctl_error ? 0 : err; | 1127 | return filter_error(cval, err); |
1124 | val = ucontrol->value.integer.value[cnt]; | 1128 | val = ucontrol->value.integer.value[cnt]; |
1125 | val = get_abs_value(cval, val); | 1129 | val = get_abs_value(cval, val); |
1126 | if (oval != val) { | 1130 | if (oval != val) { |
1127 | set_cur_mix_value(cval, c + 1, cnt, val); | 1131 | snd_usb_set_cur_mix_value(cval, c + 1, cnt, val); |
1128 | changed = 1; | 1132 | changed = 1; |
1129 | } | 1133 | } |
1130 | cnt++; | 1134 | cnt++; |
1131 | } | 1135 | } |
1132 | } else { | 1136 | } else { |
1133 | /* master channel */ | 1137 | /* master channel */ |
1134 | err = get_cur_mix_value(cval, 0, 0, &oval); | 1138 | err = snd_usb_get_cur_mix_value(cval, 0, 0, &oval); |
1135 | if (err < 0) | 1139 | if (err < 0) |
1136 | return cval->mixer->ignore_ctl_error ? 0 : err; | 1140 | return filter_error(cval, err); |
1137 | val = ucontrol->value.integer.value[0]; | 1141 | val = ucontrol->value.integer.value[0]; |
1138 | val = get_abs_value(cval, val); | 1142 | val = get_abs_value(cval, val); |
1139 | if (val != oval) { | 1143 | if (val != oval) { |
1140 | set_cur_mix_value(cval, 0, 0, val); | 1144 | snd_usb_set_cur_mix_value(cval, 0, 0, val); |
1141 | changed = 1; | 1145 | changed = 1; |
1142 | } | 1146 | } |
1143 | } | 1147 | } |
@@ -1231,8 +1235,7 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc, | |||
1231 | cval = kzalloc(sizeof(*cval), GFP_KERNEL); | 1235 | cval = kzalloc(sizeof(*cval), GFP_KERNEL); |
1232 | if (!cval) | 1236 | if (!cval) |
1233 | return; | 1237 | return; |
1234 | cval->mixer = state->mixer; | 1238 | snd_usb_mixer_elem_init_std(&cval->head, state->mixer, unitid); |
1235 | cval->id = unitid; | ||
1236 | cval->control = control; | 1239 | cval->control = control; |
1237 | cval->cmask = ctl_mask; | 1240 | cval->cmask = ctl_mask; |
1238 | cval->val_type = audio_feature_info[control-1].type; | 1241 | cval->val_type = audio_feature_info[control-1].type; |
@@ -1250,7 +1253,7 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc, | |||
1250 | 1253 | ||
1251 | /* | 1254 | /* |
1252 | * If all channels in the mask are marked read-only, make the control | 1255 | * If all channels in the mask are marked read-only, make the control |
1253 | * read-only. set_cur_mix_value() will check the mask again and won't | 1256 | * read-only. snd_usb_set_cur_mix_value() will check the mask again and won't |
1254 | * issue write commands to read-only channels. | 1257 | * issue write commands to read-only channels. |
1255 | */ | 1258 | */ |
1256 | if (cval->channels == readonly_mask) | 1259 | if (cval->channels == readonly_mask) |
@@ -1263,7 +1266,7 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc, | |||
1263 | kfree(cval); | 1266 | kfree(cval); |
1264 | return; | 1267 | return; |
1265 | } | 1268 | } |
1266 | kctl->private_free = usb_mixer_elem_free; | 1269 | kctl->private_free = snd_usb_mixer_elem_free; |
1267 | 1270 | ||
1268 | len = check_mapped_name(map, kctl->id.name, sizeof(kctl->id.name)); | 1271 | len = check_mapped_name(map, kctl->id.name, sizeof(kctl->id.name)); |
1269 | mapped_name = len != 0; | 1272 | mapped_name = len != 0; |
@@ -1290,9 +1293,8 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc, | |||
1290 | kctl->id.name, | 1293 | kctl->id.name, |
1291 | sizeof(kctl->id.name), 1); | 1294 | sizeof(kctl->id.name), 1); |
1292 | if (!len) | 1295 | if (!len) |
1293 | len = snprintf(kctl->id.name, | 1296 | snprintf(kctl->id.name, sizeof(kctl->id.name), |
1294 | sizeof(kctl->id.name), | 1297 | "Feature %d", unitid); |
1295 | "Feature %d", unitid); | ||
1296 | } | 1298 | } |
1297 | 1299 | ||
1298 | if (!mapped_name) | 1300 | if (!mapped_name) |
@@ -1305,9 +1307,9 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc, | |||
1305 | */ | 1307 | */ |
1306 | if (!mapped_name && !(state->oterm.type >> 16)) { | 1308 | if (!mapped_name && !(state->oterm.type >> 16)) { |
1307 | if ((state->oterm.type & 0xff00) == 0x0100) | 1309 | if ((state->oterm.type & 0xff00) == 0x0100) |
1308 | len = append_ctl_name(kctl, " Capture"); | 1310 | append_ctl_name(kctl, " Capture"); |
1309 | else | 1311 | else |
1310 | len = append_ctl_name(kctl, " Playback"); | 1312 | append_ctl_name(kctl, " Playback"); |
1311 | } | 1313 | } |
1312 | append_ctl_name(kctl, control == UAC_FU_MUTE ? | 1314 | append_ctl_name(kctl, control == UAC_FU_MUTE ? |
1313 | " Switch" : " Volume"); | 1315 | " Switch" : " Volume"); |
@@ -1344,14 +1346,14 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc, | |||
1344 | range); | 1346 | range); |
1345 | usb_audio_warn(state->chip, | 1347 | usb_audio_warn(state->chip, |
1346 | "[%d] FU [%s] ch = %d, val = %d/%d/%d", | 1348 | "[%d] FU [%s] ch = %d, val = %d/%d/%d", |
1347 | cval->id, kctl->id.name, cval->channels, | 1349 | cval->head.id, kctl->id.name, cval->channels, |
1348 | cval->min, cval->max, cval->res); | 1350 | cval->min, cval->max, cval->res); |
1349 | } | 1351 | } |
1350 | 1352 | ||
1351 | 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", |
1352 | cval->id, kctl->id.name, cval->channels, | 1354 | cval->head.id, kctl->id.name, cval->channels, |
1353 | cval->min, cval->max, cval->res); | 1355 | cval->min, cval->max, cval->res); |
1354 | snd_usb_mixer_add_control(state->mixer, kctl); | 1356 | snd_usb_mixer_add_control(&cval->head, kctl); |
1355 | } | 1357 | } |
1356 | 1358 | ||
1357 | /* | 1359 | /* |
@@ -1525,8 +1527,7 @@ static void build_mixer_unit_ctl(struct mixer_build *state, | |||
1525 | if (!cval) | 1527 | if (!cval) |
1526 | return; | 1528 | return; |
1527 | 1529 | ||
1528 | cval->mixer = state->mixer; | 1530 | snd_usb_mixer_elem_init_std(&cval->head, state->mixer, unitid); |
1529 | cval->id = unitid; | ||
1530 | cval->control = in_ch + 1; /* based on 1 */ | 1531 | cval->control = in_ch + 1; /* based on 1 */ |
1531 | cval->val_type = USB_MIXER_S16; | 1532 | cval->val_type = USB_MIXER_S16; |
1532 | for (i = 0; i < num_outs; i++) { | 1533 | for (i = 0; i < num_outs; i++) { |
@@ -1547,7 +1548,7 @@ static void build_mixer_unit_ctl(struct mixer_build *state, | |||
1547 | kfree(cval); | 1548 | kfree(cval); |
1548 | return; | 1549 | return; |
1549 | } | 1550 | } |
1550 | kctl->private_free = usb_mixer_elem_free; | 1551 | kctl->private_free = snd_usb_mixer_elem_free; |
1551 | 1552 | ||
1552 | len = check_mapped_name(map, kctl->id.name, sizeof(kctl->id.name)); | 1553 | len = check_mapped_name(map, kctl->id.name, sizeof(kctl->id.name)); |
1553 | if (!len) | 1554 | if (!len) |
@@ -1558,8 +1559,8 @@ static void build_mixer_unit_ctl(struct mixer_build *state, | |||
1558 | append_ctl_name(kctl, " Volume"); | 1559 | append_ctl_name(kctl, " Volume"); |
1559 | 1560 | ||
1560 | 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", |
1561 | cval->id, kctl->id.name, cval->channels, cval->min, cval->max); | 1562 | cval->head.id, kctl->id.name, cval->channels, cval->min, cval->max); |
1562 | snd_usb_mixer_add_control(state->mixer, kctl); | 1563 | snd_usb_mixer_add_control(&cval->head, kctl); |
1563 | } | 1564 | } |
1564 | 1565 | ||
1565 | /* | 1566 | /* |
@@ -1629,12 +1630,10 @@ static int mixer_ctl_procunit_get(struct snd_kcontrol *kcontrol, | |||
1629 | int err, val; | 1630 | int err, val; |
1630 | 1631 | ||
1631 | err = get_cur_ctl_value(cval, cval->control << 8, &val); | 1632 | err = get_cur_ctl_value(cval, cval->control << 8, &val); |
1632 | if (err < 0 && cval->mixer->ignore_ctl_error) { | 1633 | if (err < 0) { |
1633 | ucontrol->value.integer.value[0] = cval->min; | 1634 | ucontrol->value.integer.value[0] = cval->min; |
1634 | return 0; | 1635 | return filter_error(cval, err); |
1635 | } | 1636 | } |
1636 | if (err < 0) | ||
1637 | return err; | ||
1638 | val = get_relative_value(cval, val); | 1637 | val = get_relative_value(cval, val); |
1639 | ucontrol->value.integer.value[0] = val; | 1638 | ucontrol->value.integer.value[0] = val; |
1640 | return 0; | 1639 | return 0; |
@@ -1648,11 +1647,8 @@ static int mixer_ctl_procunit_put(struct snd_kcontrol *kcontrol, | |||
1648 | int val, oval, err; | 1647 | int val, oval, err; |
1649 | 1648 | ||
1650 | err = get_cur_ctl_value(cval, cval->control << 8, &oval); | 1649 | err = get_cur_ctl_value(cval, cval->control << 8, &oval); |
1651 | if (err < 0) { | 1650 | if (err < 0) |
1652 | if (cval->mixer->ignore_ctl_error) | 1651 | return filter_error(cval, err); |
1653 | return 0; | ||
1654 | return err; | ||
1655 | } | ||
1656 | val = ucontrol->value.integer.value[0]; | 1652 | val = ucontrol->value.integer.value[0]; |
1657 | val = get_abs_value(cval, val); | 1653 | val = get_abs_value(cval, val); |
1658 | if (val != oval) { | 1654 | if (val != oval) { |
@@ -1814,8 +1810,7 @@ static int build_audio_procunit(struct mixer_build *state, int unitid, | |||
1814 | cval = kzalloc(sizeof(*cval), GFP_KERNEL); | 1810 | cval = kzalloc(sizeof(*cval), GFP_KERNEL); |
1815 | if (!cval) | 1811 | if (!cval) |
1816 | return -ENOMEM; | 1812 | return -ENOMEM; |
1817 | cval->mixer = state->mixer; | 1813 | snd_usb_mixer_elem_init_std(&cval->head, state->mixer, unitid); |
1818 | cval->id = unitid; | ||
1819 | cval->control = valinfo->control; | 1814 | cval->control = valinfo->control; |
1820 | cval->val_type = valinfo->val_type; | 1815 | cval->val_type = valinfo->val_type; |
1821 | cval->channels = 1; | 1816 | cval->channels = 1; |
@@ -1847,7 +1842,7 @@ static int build_audio_procunit(struct mixer_build *state, int unitid, | |||
1847 | kfree(cval); | 1842 | kfree(cval); |
1848 | return -ENOMEM; | 1843 | return -ENOMEM; |
1849 | } | 1844 | } |
1850 | kctl->private_free = usb_mixer_elem_free; | 1845 | kctl->private_free = snd_usb_mixer_elem_free; |
1851 | 1846 | ||
1852 | if (check_mapped_name(map, kctl->id.name, sizeof(kctl->id.name))) { | 1847 | if (check_mapped_name(map, kctl->id.name, sizeof(kctl->id.name))) { |
1853 | /* nothing */ ; | 1848 | /* nothing */ ; |
@@ -1868,10 +1863,10 @@ static int build_audio_procunit(struct mixer_build *state, int unitid, | |||
1868 | 1863 | ||
1869 | usb_audio_dbg(state->chip, | 1864 | usb_audio_dbg(state->chip, |
1870 | "[%d] PU [%s] ch = %d, val = %d/%d\n", | 1865 | "[%d] PU [%s] ch = %d, val = %d/%d\n", |
1871 | cval->id, kctl->id.name, cval->channels, | 1866 | cval->head.id, kctl->id.name, cval->channels, |
1872 | cval->min, cval->max); | 1867 | cval->min, cval->max); |
1873 | 1868 | ||
1874 | err = snd_usb_mixer_add_control(state->mixer, kctl); | 1869 | err = snd_usb_mixer_add_control(&cval->head, kctl); |
1875 | if (err < 0) | 1870 | if (err < 0) |
1876 | return err; | 1871 | return err; |
1877 | } | 1872 | } |
@@ -1924,11 +1919,8 @@ static int mixer_ctl_selector_get(struct snd_kcontrol *kcontrol, | |||
1924 | 1919 | ||
1925 | err = get_cur_ctl_value(cval, cval->control << 8, &val); | 1920 | err = get_cur_ctl_value(cval, cval->control << 8, &val); |
1926 | if (err < 0) { | 1921 | if (err < 0) { |
1927 | if (cval->mixer->ignore_ctl_error) { | 1922 | ucontrol->value.enumerated.item[0] = 0; |
1928 | ucontrol->value.enumerated.item[0] = 0; | 1923 | return filter_error(cval, err); |
1929 | return 0; | ||
1930 | } | ||
1931 | return err; | ||
1932 | } | 1924 | } |
1933 | val = get_relative_value(cval, val); | 1925 | val = get_relative_value(cval, val); |
1934 | ucontrol->value.enumerated.item[0] = val; | 1926 | ucontrol->value.enumerated.item[0] = val; |
@@ -1943,11 +1935,8 @@ static int mixer_ctl_selector_put(struct snd_kcontrol *kcontrol, | |||
1943 | int val, oval, err; | 1935 | int val, oval, err; |
1944 | 1936 | ||
1945 | err = get_cur_ctl_value(cval, cval->control << 8, &oval); | 1937 | err = get_cur_ctl_value(cval, cval->control << 8, &oval); |
1946 | if (err < 0) { | 1938 | if (err < 0) |
1947 | if (cval->mixer->ignore_ctl_error) | 1939 | return filter_error(cval, err); |
1948 | return 0; | ||
1949 | return err; | ||
1950 | } | ||
1951 | val = ucontrol->value.enumerated.item[0]; | 1940 | val = ucontrol->value.enumerated.item[0]; |
1952 | val = get_abs_value(cval, val); | 1941 | val = get_abs_value(cval, val); |
1953 | if (val != oval) { | 1942 | if (val != oval) { |
@@ -2024,8 +2013,7 @@ static int parse_audio_selector_unit(struct mixer_build *state, int unitid, | |||
2024 | cval = kzalloc(sizeof(*cval), GFP_KERNEL); | 2013 | cval = kzalloc(sizeof(*cval), GFP_KERNEL); |
2025 | if (!cval) | 2014 | if (!cval) |
2026 | return -ENOMEM; | 2015 | return -ENOMEM; |
2027 | cval->mixer = state->mixer; | 2016 | snd_usb_mixer_elem_init_std(&cval->head, state->mixer, unitid); |
2028 | cval->id = unitid; | ||
2029 | cval->val_type = USB_MIXER_U8; | 2017 | cval->val_type = USB_MIXER_U8; |
2030 | cval->channels = 1; | 2018 | cval->channels = 1; |
2031 | cval->min = 1; | 2019 | cval->min = 1; |
@@ -2096,11 +2084,8 @@ static int parse_audio_selector_unit(struct mixer_build *state, int unitid, | |||
2096 | } | 2084 | } |
2097 | 2085 | ||
2098 | usb_audio_dbg(state->chip, "[%d] SU [%s] items = %d\n", | 2086 | usb_audio_dbg(state->chip, "[%d] SU [%s] items = %d\n", |
2099 | cval->id, kctl->id.name, desc->bNrInPins); | 2087 | cval->head.id, kctl->id.name, desc->bNrInPins); |
2100 | if ((err = snd_usb_mixer_add_control(state->mixer, kctl)) < 0) | 2088 | return snd_usb_mixer_add_control(&cval->head, kctl); |
2101 | return err; | ||
2102 | |||
2103 | return 0; | ||
2104 | } | 2089 | } |
2105 | 2090 | ||
2106 | /* | 2091 | /* |
@@ -2245,25 +2230,21 @@ static int snd_usb_mixer_controls(struct usb_mixer_interface *mixer) | |||
2245 | 2230 | ||
2246 | void snd_usb_mixer_notify_id(struct usb_mixer_interface *mixer, int unitid) | 2231 | void snd_usb_mixer_notify_id(struct usb_mixer_interface *mixer, int unitid) |
2247 | { | 2232 | { |
2248 | struct usb_mixer_elem_info *info; | 2233 | struct usb_mixer_elem_list *list; |
2249 | 2234 | ||
2250 | 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) |
2251 | snd_ctl_notify(mixer->chip->card, SNDRV_CTL_EVENT_MASK_VALUE, | 2236 | snd_ctl_notify(mixer->chip->card, SNDRV_CTL_EVENT_MASK_VALUE, |
2252 | info->elem_id); | 2237 | &list->kctl->id); |
2253 | } | 2238 | } |
2254 | 2239 | ||
2255 | static void snd_usb_mixer_dump_cval(struct snd_info_buffer *buffer, | 2240 | static void snd_usb_mixer_dump_cval(struct snd_info_buffer *buffer, |
2256 | int unitid, | 2241 | struct usb_mixer_elem_list *list) |
2257 | struct usb_mixer_elem_info *cval) | ||
2258 | { | 2242 | { |
2243 | struct usb_mixer_elem_info *cval = (struct usb_mixer_elem_info *)list; | ||
2259 | static char *val_types[] = {"BOOLEAN", "INV_BOOLEAN", | 2244 | static char *val_types[] = {"BOOLEAN", "INV_BOOLEAN", |
2260 | "S8", "U8", "S16", "U16"}; | 2245 | "S8", "U8", "S16", "U16"}; |
2261 | snd_iprintf(buffer, " Unit: %i\n", unitid); | ||
2262 | if (cval->elem_id) | ||
2263 | snd_iprintf(buffer, " Control: name=\"%s\", index=%i\n", | ||
2264 | cval->elem_id->name, cval->elem_id->index); | ||
2265 | snd_iprintf(buffer, " Info: id=%i, control=%i, cmask=0x%x, " | 2246 | snd_iprintf(buffer, " Info: id=%i, control=%i, cmask=0x%x, " |
2266 | "channels=%i, type=\"%s\"\n", cval->id, | 2247 | "channels=%i, type=\"%s\"\n", cval->head.id, |
2267 | cval->control, cval->cmask, cval->channels, | 2248 | cval->control, cval->cmask, cval->channels, |
2268 | val_types[cval->val_type]); | 2249 | val_types[cval->val_type]); |
2269 | 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", |
@@ -2275,7 +2256,7 @@ static void snd_usb_mixer_proc_read(struct snd_info_entry *entry, | |||
2275 | { | 2256 | { |
2276 | struct snd_usb_audio *chip = entry->private_data; | 2257 | struct snd_usb_audio *chip = entry->private_data; |
2277 | struct usb_mixer_interface *mixer; | 2258 | struct usb_mixer_interface *mixer; |
2278 | struct usb_mixer_elem_info *cval; | 2259 | struct usb_mixer_elem_list *list; |
2279 | int unitid; | 2260 | int unitid; |
2280 | 2261 | ||
2281 | list_for_each_entry(mixer, &chip->mixer_list, list) { | 2262 | list_for_each_entry(mixer, &chip->mixer_list, list) { |
@@ -2285,9 +2266,17 @@ static void snd_usb_mixer_proc_read(struct snd_info_entry *entry, | |||
2285 | mixer->ignore_ctl_error); | 2266 | mixer->ignore_ctl_error); |
2286 | snd_iprintf(buffer, "Card: %s\n", chip->card->longname); | 2267 | snd_iprintf(buffer, "Card: %s\n", chip->card->longname); |
2287 | for (unitid = 0; unitid < MAX_ID_ELEMS; unitid++) { | 2268 | for (unitid = 0; unitid < MAX_ID_ELEMS; unitid++) { |
2288 | for (cval = mixer->id_elems[unitid]; cval; | 2269 | for (list = mixer->id_elems[unitid]; list; |
2289 | cval = cval->next_id_elem) | 2270 | list = list->next_id_elem) { |
2290 | 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 | } | ||
2291 | } | 2280 | } |
2292 | } | 2281 | } |
2293 | } | 2282 | } |
@@ -2295,7 +2284,7 @@ static void snd_usb_mixer_proc_read(struct snd_info_entry *entry, | |||
2295 | static void snd_usb_mixer_interrupt_v2(struct usb_mixer_interface *mixer, | 2284 | static void snd_usb_mixer_interrupt_v2(struct usb_mixer_interface *mixer, |
2296 | int attribute, int value, int index) | 2285 | int attribute, int value, int index) |
2297 | { | 2286 | { |
2298 | struct usb_mixer_elem_info *info; | 2287 | struct usb_mixer_elem_list *list; |
2299 | __u8 unitid = (index >> 8) & 0xff; | 2288 | __u8 unitid = (index >> 8) & 0xff; |
2300 | __u8 control = (value >> 8) & 0xff; | 2289 | __u8 control = (value >> 8) & 0xff; |
2301 | __u8 channel = value & 0xff; | 2290 | __u8 channel = value & 0xff; |
@@ -2307,7 +2296,13 @@ static void snd_usb_mixer_interrupt_v2(struct usb_mixer_interface *mixer, | |||
2307 | return; | 2296 | return; |
2308 | } | 2297 | } |
2309 | 2298 | ||
2310 | 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; | ||
2311 | if (info->control != control) | 2306 | if (info->control != control) |
2312 | continue; | 2307 | continue; |
2313 | 2308 | ||
@@ -2320,7 +2315,7 @@ static void snd_usb_mixer_interrupt_v2(struct usb_mixer_interface *mixer, | |||
2320 | info->cached = 0; | 2315 | info->cached = 0; |
2321 | 2316 | ||
2322 | snd_ctl_notify(mixer->chip->card, SNDRV_CTL_EVENT_MASK_VALUE, | 2317 | snd_ctl_notify(mixer->chip->card, SNDRV_CTL_EVENT_MASK_VALUE, |
2323 | info->elem_id); | 2318 | &info->head.kctl->id); |
2324 | break; | 2319 | break; |
2325 | 2320 | ||
2326 | case UAC2_CS_RANGE: | 2321 | case UAC2_CS_RANGE: |
@@ -2485,11 +2480,8 @@ _error: | |||
2485 | return err; | 2480 | return err; |
2486 | } | 2481 | } |
2487 | 2482 | ||
2488 | void snd_usb_mixer_disconnect(struct list_head *p) | 2483 | void snd_usb_mixer_disconnect(struct usb_mixer_interface *mixer) |
2489 | { | 2484 | { |
2490 | struct usb_mixer_interface *mixer; | ||
2491 | |||
2492 | mixer = list_entry(p, struct usb_mixer_interface, list); | ||
2493 | usb_kill_urb(mixer->urb); | 2485 | usb_kill_urb(mixer->urb); |
2494 | usb_kill_urb(mixer->rc_urb); | 2486 | usb_kill_urb(mixer->rc_urb); |
2495 | } | 2487 | } |
@@ -2521,8 +2513,9 @@ int snd_usb_mixer_suspend(struct usb_mixer_interface *mixer) | |||
2521 | return 0; | 2513 | return 0; |
2522 | } | 2514 | } |
2523 | 2515 | ||
2524 | static int restore_mixer_value(struct usb_mixer_elem_info *cval) | 2516 | static int restore_mixer_value(struct usb_mixer_elem_list *list) |
2525 | { | 2517 | { |
2518 | struct usb_mixer_elem_info *cval = (struct usb_mixer_elem_info *)list; | ||
2526 | int c, err, idx; | 2519 | int c, err, idx; |
2527 | 2520 | ||
2528 | if (cval->cmask) { | 2521 | if (cval->cmask) { |
@@ -2531,7 +2524,7 @@ static int restore_mixer_value(struct usb_mixer_elem_info *cval) | |||
2531 | if (!(cval->cmask & (1 << c))) | 2524 | if (!(cval->cmask & (1 << c))) |
2532 | continue; | 2525 | continue; |
2533 | if (cval->cached & (1 << c)) { | 2526 | if (cval->cached & (1 << c)) { |
2534 | err = set_cur_mix_value(cval, c + 1, idx, | 2527 | err = snd_usb_set_cur_mix_value(cval, c + 1, idx, |
2535 | cval->cache_val[idx]); | 2528 | cval->cache_val[idx]); |
2536 | if (err < 0) | 2529 | if (err < 0) |
2537 | return err; | 2530 | return err; |
@@ -2541,7 +2534,7 @@ static int restore_mixer_value(struct usb_mixer_elem_info *cval) | |||
2541 | } else { | 2534 | } else { |
2542 | /* master */ | 2535 | /* master */ |
2543 | if (cval->cached) { | 2536 | if (cval->cached) { |
2544 | err = set_cur_mix_value(cval, 0, 0, *cval->cache_val); | 2537 | err = snd_usb_set_cur_mix_value(cval, 0, 0, *cval->cache_val); |
2545 | if (err < 0) | 2538 | if (err < 0) |
2546 | return err; | 2539 | return err; |
2547 | } | 2540 | } |
@@ -2552,19 +2545,19 @@ static int restore_mixer_value(struct usb_mixer_elem_info *cval) | |||
2552 | 2545 | ||
2553 | int snd_usb_mixer_resume(struct usb_mixer_interface *mixer, bool reset_resume) | 2546 | int snd_usb_mixer_resume(struct usb_mixer_interface *mixer, bool reset_resume) |
2554 | { | 2547 | { |
2555 | struct usb_mixer_elem_info *cval; | 2548 | struct usb_mixer_elem_list *list; |
2556 | int id, err; | 2549 | int id, err; |
2557 | 2550 | ||
2558 | /* FIXME: any mixer quirks? */ | ||
2559 | |||
2560 | if (reset_resume) { | 2551 | if (reset_resume) { |
2561 | /* restore cached mixer values */ | 2552 | /* restore cached mixer values */ |
2562 | for (id = 0; id < MAX_ID_ELEMS; id++) { | 2553 | for (id = 0; id < MAX_ID_ELEMS; id++) { |
2563 | for (cval = mixer->id_elems[id]; cval; | 2554 | for (list = mixer->id_elems[id]; list; |
2564 | cval = cval->next_id_elem) { | 2555 | list = list->next_id_elem) { |
2565 | err = restore_mixer_value(cval); | 2556 | if (list->resume) { |
2566 | if (err < 0) | 2557 | err = list->resume(list); |
2567 | return err; | 2558 | if (err < 0) |
2559 | return err; | ||
2560 | } | ||
2568 | } | 2561 | } |
2569 | } | 2562 | } |
2570 | } | 2563 | } |
@@ -2572,3 +2565,15 @@ int snd_usb_mixer_resume(struct usb_mixer_interface *mixer, bool reset_resume) | |||
2572 | return snd_usb_mixer_activate(mixer); | 2565 | return snd_usb_mixer_activate(mixer); |
2573 | } | 2566 | } |
2574 | #endif | 2567 | #endif |
2568 | |||
2569 | void 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 | } | ||
diff --git a/sound/usb/mixer.h b/sound/usb/mixer.h index 73b1f649447b..d3268f0ee2b3 100644 --- a/sound/usb/mixer.h +++ b/sound/usb/mixer.h | |||
@@ -1,6 +1,8 @@ | |||
1 | #ifndef __USBMIXER_H | 1 | #ifndef __USBMIXER_H |
2 | #define __USBMIXER_H | 2 | #define __USBMIXER_H |
3 | 3 | ||
4 | #include <sound/info.h> | ||
5 | |||
4 | struct usb_mixer_interface { | 6 | struct usb_mixer_interface { |
5 | struct snd_usb_audio *chip; | 7 | struct snd_usb_audio *chip; |
6 | struct usb_host_interface *hostif; | 8 | struct usb_host_interface *hostif; |
@@ -8,7 +10,7 @@ struct usb_mixer_interface { | |||
8 | unsigned int ignore_ctl_error; | 10 | unsigned int ignore_ctl_error; |
9 | struct urb *urb; | 11 | struct urb *urb; |
10 | /* array[MAX_ID_ELEMS], indexed by unit id */ | 12 | /* array[MAX_ID_ELEMS], indexed by unit id */ |
11 | struct usb_mixer_elem_info **id_elems; | 13 | struct usb_mixer_elem_list **id_elems; |
12 | 14 | ||
13 | /* the usb audio specification version this interface complies to */ | 15 | /* the usb audio specification version this interface complies to */ |
14 | int protocol; | 16 | int protocol; |
@@ -20,9 +22,6 @@ struct usb_mixer_interface { | |||
20 | struct urb *rc_urb; | 22 | struct urb *rc_urb; |
21 | struct usb_ctrlrequest *rc_setup_packet; | 23 | struct usb_ctrlrequest *rc_setup_packet; |
22 | u8 rc_buffer[6]; | 24 | u8 rc_buffer[6]; |
23 | |||
24 | u8 audigy2nx_leds[3]; | ||
25 | u8 xonar_u1_status; | ||
26 | }; | 25 | }; |
27 | 26 | ||
28 | #define MAX_CHANNELS 16 /* max logical channels */ | 27 | #define MAX_CHANNELS 16 /* max logical channels */ |
@@ -36,11 +35,21 @@ enum { | |||
36 | USB_MIXER_U16, | 35 | USB_MIXER_U16, |
37 | }; | 36 | }; |
38 | 37 | ||
39 | struct usb_mixer_elem_info { | 38 | typedef void (*usb_mixer_elem_dump_func_t)(struct snd_info_buffer *buffer, |
39 | struct usb_mixer_elem_list *list); | ||
40 | typedef int (*usb_mixer_elem_resume_func_t)(struct usb_mixer_elem_list *elem); | ||
41 | |||
42 | struct usb_mixer_elem_list { | ||
40 | struct usb_mixer_interface *mixer; | 43 | struct usb_mixer_interface *mixer; |
41 | struct usb_mixer_elem_info *next_id_elem; /* list of controls with same id */ | 44 | struct usb_mixer_elem_list *next_id_elem; /* list of controls with same id */ |
42 | struct snd_ctl_elem_id *elem_id; | 45 | struct snd_kcontrol *kctl; |
43 | unsigned int id; | 46 | unsigned int id; |
47 | usb_mixer_elem_dump_func_t dump; | ||
48 | usb_mixer_elem_resume_func_t resume; | ||
49 | }; | ||
50 | |||
51 | struct usb_mixer_elem_info { | ||
52 | struct usb_mixer_elem_list head; | ||
44 | unsigned int control; /* CS or ICN (high byte) */ | 53 | unsigned int control; /* CS or ICN (high byte) */ |
45 | unsigned int cmask; /* channel mask bitmap: 0 = master */ | 54 | unsigned int cmask; /* channel mask bitmap: 0 = master */ |
46 | unsigned int idx_off; /* Control index offset */ | 55 | unsigned int idx_off; /* Control index offset */ |
@@ -53,20 +62,25 @@ struct usb_mixer_elem_info { | |||
53 | int cached; | 62 | int cached; |
54 | int cache_val[MAX_CHANNELS]; | 63 | int cache_val[MAX_CHANNELS]; |
55 | u8 initialized; | 64 | u8 initialized; |
65 | void *private_data; | ||
56 | }; | 66 | }; |
57 | 67 | ||
58 | int snd_usb_create_mixer(struct snd_usb_audio *chip, int ctrlif, | 68 | int snd_usb_create_mixer(struct snd_usb_audio *chip, int ctrlif, |
59 | int ignore_error); | 69 | int ignore_error); |
60 | void snd_usb_mixer_disconnect(struct list_head *p); | 70 | void snd_usb_mixer_disconnect(struct usb_mixer_interface *mixer); |
61 | 71 | ||
62 | void snd_usb_mixer_notify_id(struct usb_mixer_interface *mixer, int unitid); | 72 | void snd_usb_mixer_notify_id(struct usb_mixer_interface *mixer, int unitid); |
63 | 73 | ||
64 | int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval, | 74 | int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval, |
65 | int request, int validx, int value_set); | 75 | int request, int validx, int value_set); |
66 | 76 | ||
67 | int snd_usb_mixer_add_control(struct usb_mixer_interface *mixer, | 77 | int snd_usb_mixer_add_control(struct usb_mixer_elem_list *list, |
68 | struct snd_kcontrol *kctl); | 78 | struct snd_kcontrol *kctl); |
69 | 79 | ||
80 | void snd_usb_mixer_elem_init_std(struct usb_mixer_elem_list *list, | ||
81 | struct usb_mixer_interface *mixer, | ||
82 | int unitid); | ||
83 | |||
70 | int snd_usb_mixer_vol_tlv(struct snd_kcontrol *kcontrol, int op_flag, | 84 | int snd_usb_mixer_vol_tlv(struct snd_kcontrol *kcontrol, int op_flag, |
71 | unsigned int size, unsigned int __user *_tlv); | 85 | unsigned int size, unsigned int __user *_tlv); |
72 | 86 | ||
@@ -75,4 +89,12 @@ int snd_usb_mixer_suspend(struct usb_mixer_interface *mixer); | |||
75 | int snd_usb_mixer_resume(struct usb_mixer_interface *mixer, bool reset_resume); | 89 | int snd_usb_mixer_resume(struct usb_mixer_interface *mixer, bool reset_resume); |
76 | #endif | 90 | #endif |
77 | 91 | ||
92 | int snd_usb_set_cur_mix_value(struct usb_mixer_elem_info *cval, int channel, | ||
93 | int index, int value); | ||
94 | |||
95 | int snd_usb_get_cur_mix_value(struct usb_mixer_elem_info *cval, | ||
96 | int channel, int index, int *value); | ||
97 | |||
98 | extern void snd_usb_mixer_elem_free(struct snd_kcontrol *kctl); | ||
99 | |||
78 | #endif /* __USBMIXER_H */ | 100 | #endif /* __USBMIXER_H */ |
diff --git a/sound/usb/mixer_maps.c b/sound/usb/mixer_maps.c index d1d72ff50347..1994d41348f8 100644 --- a/sound/usb/mixer_maps.c +++ b/sound/usb/mixer_maps.c | |||
@@ -179,6 +179,11 @@ static struct usbmix_name_map audigy2nx_map[] = { | |||
179 | { 0 } /* terminator */ | 179 | { 0 } /* terminator */ |
180 | }; | 180 | }; |
181 | 181 | ||
182 | static struct usbmix_name_map mbox1_map[] = { | ||
183 | { 1, "Clock" }, | ||
184 | { 0 } /* terminator */ | ||
185 | }; | ||
186 | |||
182 | static struct usbmix_selector_map c400_selectors[] = { | 187 | static struct usbmix_selector_map c400_selectors[] = { |
183 | { | 188 | { |
184 | .id = 0x80, | 189 | .id = 0x80, |
@@ -416,6 +421,10 @@ static struct usbmix_ctl_map usbmix_ctl_maps[] = { | |||
416 | .map = aureon_51_2_map, | 421 | .map = aureon_51_2_map, |
417 | }, | 422 | }, |
418 | { | 423 | { |
424 | .id = USB_ID(0x0dba, 0x1000), | ||
425 | .map = mbox1_map, | ||
426 | }, | ||
427 | { | ||
419 | .id = USB_ID(0x13e5, 0x0001), | 428 | .id = USB_ID(0x13e5, 0x0001), |
420 | .map = scratch_live_map, | 429 | .map = scratch_live_map, |
421 | .ignore_ctl_error = 1, | 430 | .ignore_ctl_error = 1, |
diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c index 8c9bf4b7aaf0..dc9df007d3e3 100644 --- a/sound/usb/mixer_quirks.c +++ b/sound/usb/mixer_quirks.c | |||
@@ -41,6 +41,7 @@ | |||
41 | #include "usbaudio.h" | 41 | #include "usbaudio.h" |
42 | #include "mixer.h" | 42 | #include "mixer.h" |
43 | #include "mixer_quirks.h" | 43 | #include "mixer_quirks.h" |
44 | #include "mixer_scarlett.h" | ||
44 | #include "helper.h" | 45 | #include "helper.h" |
45 | 46 | ||
46 | extern struct snd_kcontrol_new *snd_usb_feature_unit_ctl; | 47 | extern struct snd_kcontrol_new *snd_usb_feature_unit_ctl; |
@@ -52,13 +53,6 @@ struct std_mono_table { | |||
52 | snd_kcontrol_tlv_rw_t *tlv_callback; | 53 | snd_kcontrol_tlv_rw_t *tlv_callback; |
53 | }; | 54 | }; |
54 | 55 | ||
55 | /* private_free callback */ | ||
56 | static void usb_mixer_elem_free(struct snd_kcontrol *kctl) | ||
57 | { | ||
58 | kfree(kctl->private_data); | ||
59 | kctl->private_data = NULL; | ||
60 | } | ||
61 | |||
62 | /* This function allows for the creation of standard UAC controls. | 56 | /* This function allows for the creation of standard UAC controls. |
63 | * See the quirks for M-Audio FTUs or Ebox-44. | 57 | * See the quirks for M-Audio FTUs or Ebox-44. |
64 | * If you don't want to set a TLV callback pass NULL. | 58 | * If you don't want to set a TLV callback pass NULL. |
@@ -75,7 +69,6 @@ static int snd_create_std_mono_ctl_offset(struct usb_mixer_interface *mixer, | |||
75 | const char *name, | 69 | const char *name, |
76 | snd_kcontrol_tlv_rw_t *tlv_callback) | 70 | snd_kcontrol_tlv_rw_t *tlv_callback) |
77 | { | 71 | { |
78 | int err; | ||
79 | struct usb_mixer_elem_info *cval; | 72 | struct usb_mixer_elem_info *cval; |
80 | struct snd_kcontrol *kctl; | 73 | struct snd_kcontrol *kctl; |
81 | 74 | ||
@@ -83,8 +76,7 @@ static int snd_create_std_mono_ctl_offset(struct usb_mixer_interface *mixer, | |||
83 | if (!cval) | 76 | if (!cval) |
84 | return -ENOMEM; | 77 | return -ENOMEM; |
85 | 78 | ||
86 | cval->id = unitid; | 79 | snd_usb_mixer_elem_init_std(&cval->head, mixer, unitid); |
87 | cval->mixer = mixer; | ||
88 | cval->val_type = val_type; | 80 | cval->val_type = val_type; |
89 | cval->channels = 1; | 81 | cval->channels = 1; |
90 | cval->control = control; | 82 | cval->control = control; |
@@ -108,7 +100,7 @@ static int snd_create_std_mono_ctl_offset(struct usb_mixer_interface *mixer, | |||
108 | 100 | ||
109 | /* Set name */ | 101 | /* Set name */ |
110 | snprintf(kctl->id.name, sizeof(kctl->id.name), name); | 102 | snprintf(kctl->id.name, sizeof(kctl->id.name), name); |
111 | kctl->private_free = usb_mixer_elem_free; | 103 | kctl->private_free = snd_usb_mixer_elem_free; |
112 | 104 | ||
113 | /* set TLV */ | 105 | /* set TLV */ |
114 | if (tlv_callback) { | 106 | if (tlv_callback) { |
@@ -118,11 +110,7 @@ static int snd_create_std_mono_ctl_offset(struct usb_mixer_interface *mixer, | |||
118 | SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK; | 110 | SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK; |
119 | } | 111 | } |
120 | /* Add control to mixer */ | 112 | /* Add control to mixer */ |
121 | err = snd_usb_mixer_add_control(mixer, kctl); | 113 | return snd_usb_mixer_add_control(&cval->head, kctl); |
122 | if (err < 0) | ||
123 | return err; | ||
124 | |||
125 | return 0; | ||
126 | } | 114 | } |
127 | 115 | ||
128 | static int snd_create_std_mono_ctl(struct usb_mixer_interface *mixer, | 116 | static int snd_create_std_mono_ctl(struct usb_mixer_interface *mixer, |
@@ -156,6 +144,32 @@ static int snd_create_std_mono_table(struct usb_mixer_interface *mixer, | |||
156 | return 0; | 144 | return 0; |
157 | } | 145 | } |
158 | 146 | ||
147 | static int add_single_ctl_with_resume(struct usb_mixer_interface *mixer, | ||
148 | int id, | ||
149 | usb_mixer_elem_resume_func_t resume, | ||
150 | const struct snd_kcontrol_new *knew, | ||
151 | struct usb_mixer_elem_list **listp) | ||
152 | { | ||
153 | struct usb_mixer_elem_list *list; | ||
154 | struct snd_kcontrol *kctl; | ||
155 | |||
156 | list = kzalloc(sizeof(*list), GFP_KERNEL); | ||
157 | if (!list) | ||
158 | return -ENOMEM; | ||
159 | if (listp) | ||
160 | *listp = list; | ||
161 | list->mixer = mixer; | ||
162 | list->id = id; | ||
163 | list->resume = resume; | ||
164 | kctl = snd_ctl_new1(knew, list); | ||
165 | if (!kctl) { | ||
166 | kfree(list); | ||
167 | return -ENOMEM; | ||
168 | } | ||
169 | kctl->private_free = snd_usb_mixer_elem_free; | ||
170 | return snd_usb_mixer_add_control(list, kctl); | ||
171 | } | ||
172 | |||
159 | /* | 173 | /* |
160 | * Sound Blaster remote control configuration | 174 | * Sound Blaster remote control configuration |
161 | * | 175 | * |
@@ -283,84 +297,90 @@ static int snd_usb_soundblaster_remote_init(struct usb_mixer_interface *mixer) | |||
283 | 297 | ||
284 | static int snd_audigy2nx_led_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 298 | static int snd_audigy2nx_led_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
285 | { | 299 | { |
286 | struct usb_mixer_interface *mixer = snd_kcontrol_chip(kcontrol); | 300 | ucontrol->value.integer.value[0] = kcontrol->private_value >> 8; |
287 | int index = kcontrol->private_value; | ||
288 | |||
289 | ucontrol->value.integer.value[0] = mixer->audigy2nx_leds[index]; | ||
290 | return 0; | 301 | return 0; |
291 | } | 302 | } |
292 | 303 | ||
293 | static int snd_audigy2nx_led_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 304 | static int snd_audigy2nx_led_update(struct usb_mixer_interface *mixer, |
305 | int value, int index) | ||
294 | { | 306 | { |
295 | struct usb_mixer_interface *mixer = snd_kcontrol_chip(kcontrol); | 307 | struct snd_usb_audio *chip = mixer->chip; |
296 | int index = kcontrol->private_value; | 308 | int err; |
297 | int value = ucontrol->value.integer.value[0]; | ||
298 | int err, changed; | ||
299 | 309 | ||
300 | if (value > 1) | 310 | down_read(&chip->shutdown_rwsem); |
301 | return -EINVAL; | 311 | if (chip->shutdown) { |
302 | changed = value != mixer->audigy2nx_leds[index]; | ||
303 | down_read(&mixer->chip->shutdown_rwsem); | ||
304 | if (mixer->chip->shutdown) { | ||
305 | err = -ENODEV; | 312 | err = -ENODEV; |
306 | goto out; | 313 | goto out; |
307 | } | 314 | } |
308 | if (mixer->chip->usb_id == USB_ID(0x041e, 0x3042)) | 315 | if (chip->usb_id == USB_ID(0x041e, 0x3042)) |
309 | err = snd_usb_ctl_msg(mixer->chip->dev, | 316 | err = snd_usb_ctl_msg(chip->dev, |
310 | usb_sndctrlpipe(mixer->chip->dev, 0), 0x24, | 317 | usb_sndctrlpipe(chip->dev, 0), 0x24, |
311 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER, | 318 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER, |
312 | !value, 0, NULL, 0); | 319 | !value, 0, NULL, 0); |
313 | /* USB X-Fi S51 Pro */ | 320 | /* USB X-Fi S51 Pro */ |
314 | if (mixer->chip->usb_id == USB_ID(0x041e, 0x30df)) | 321 | if (chip->usb_id == USB_ID(0x041e, 0x30df)) |
315 | err = snd_usb_ctl_msg(mixer->chip->dev, | 322 | err = snd_usb_ctl_msg(chip->dev, |
316 | usb_sndctrlpipe(mixer->chip->dev, 0), 0x24, | 323 | usb_sndctrlpipe(chip->dev, 0), 0x24, |
317 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER, | 324 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER, |
318 | !value, 0, NULL, 0); | 325 | !value, 0, NULL, 0); |
319 | else | 326 | else |
320 | err = snd_usb_ctl_msg(mixer->chip->dev, | 327 | err = snd_usb_ctl_msg(chip->dev, |
321 | usb_sndctrlpipe(mixer->chip->dev, 0), 0x24, | 328 | usb_sndctrlpipe(chip->dev, 0), 0x24, |
322 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER, | 329 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER, |
323 | value, index + 2, NULL, 0); | 330 | value, index + 2, NULL, 0); |
324 | out: | 331 | out: |
325 | up_read(&mixer->chip->shutdown_rwsem); | 332 | up_read(&chip->shutdown_rwsem); |
326 | if (err < 0) | 333 | return err; |
327 | return err; | ||
328 | mixer->audigy2nx_leds[index] = value; | ||
329 | return changed; | ||
330 | } | 334 | } |
331 | 335 | ||
332 | static struct snd_kcontrol_new snd_audigy2nx_controls[] = { | 336 | static int snd_audigy2nx_led_put(struct snd_kcontrol *kcontrol, |
333 | { | 337 | struct snd_ctl_elem_value *ucontrol) |
334 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 338 | { |
335 | .name = "CMSS LED Switch", | 339 | struct usb_mixer_elem_list *list = snd_kcontrol_chip(kcontrol); |
336 | .info = snd_audigy2nx_led_info, | 340 | struct usb_mixer_interface *mixer = list->mixer; |
337 | .get = snd_audigy2nx_led_get, | 341 | int index = kcontrol->private_value & 0xff; |
338 | .put = snd_audigy2nx_led_put, | 342 | int value = ucontrol->value.integer.value[0]; |
339 | .private_value = 0, | 343 | int old_value = kcontrol->private_value >> 8; |
340 | }, | 344 | int err; |
341 | { | 345 | |
342 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 346 | if (value > 1) |
343 | .name = "Power LED Switch", | 347 | return -EINVAL; |
344 | .info = snd_audigy2nx_led_info, | 348 | if (value == old_value) |
345 | .get = snd_audigy2nx_led_get, | 349 | return 0; |
346 | .put = snd_audigy2nx_led_put, | 350 | kcontrol->private_value = (value << 8) | index; |
347 | .private_value = 1, | 351 | err = snd_audigy2nx_led_update(mixer, value, index); |
348 | }, | 352 | return err < 0 ? err : 1; |
349 | { | 353 | } |
350 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 354 | |
351 | .name = "Dolby Digital LED Switch", | 355 | static int snd_audigy2nx_led_resume(struct usb_mixer_elem_list *list) |
352 | .info = snd_audigy2nx_led_info, | 356 | { |
353 | .get = snd_audigy2nx_led_get, | 357 | int priv_value = list->kctl->private_value; |
354 | .put = snd_audigy2nx_led_put, | 358 | |
355 | .private_value = 2, | 359 | return snd_audigy2nx_led_update(list->mixer, priv_value >> 8, |
356 | }, | 360 | priv_value & 0xff); |
361 | } | ||
362 | |||
363 | /* name and private_value are set dynamically */ | ||
364 | static struct snd_kcontrol_new snd_audigy2nx_control = { | ||
365 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
366 | .info = snd_audigy2nx_led_info, | ||
367 | .get = snd_audigy2nx_led_get, | ||
368 | .put = snd_audigy2nx_led_put, | ||
369 | }; | ||
370 | |||
371 | static const char * const snd_audigy2nx_led_names[] = { | ||
372 | "CMSS LED Switch", | ||
373 | "Power LED Switch", | ||
374 | "Dolby Digital LED Switch", | ||
357 | }; | 375 | }; |
358 | 376 | ||
359 | static int snd_audigy2nx_controls_create(struct usb_mixer_interface *mixer) | 377 | static int snd_audigy2nx_controls_create(struct usb_mixer_interface *mixer) |
360 | { | 378 | { |
361 | int i, err; | 379 | int i, err; |
362 | 380 | ||
363 | for (i = 0; i < ARRAY_SIZE(snd_audigy2nx_controls); ++i) { | 381 | for (i = 0; i < ARRAY_SIZE(snd_audigy2nx_led_names); ++i) { |
382 | struct snd_kcontrol_new knew; | ||
383 | |||
364 | /* USB X-Fi S51 doesn't have a CMSS LED */ | 384 | /* USB X-Fi S51 doesn't have a CMSS LED */ |
365 | if ((mixer->chip->usb_id == USB_ID(0x041e, 0x3042)) && i == 0) | 385 | if ((mixer->chip->usb_id == USB_ID(0x041e, 0x3042)) && i == 0) |
366 | continue; | 386 | continue; |
@@ -373,12 +393,16 @@ static int snd_audigy2nx_controls_create(struct usb_mixer_interface *mixer) | |||
373 | mixer->chip->usb_id == USB_ID(0x041e, 0x30df) || | 393 | mixer->chip->usb_id == USB_ID(0x041e, 0x30df) || |
374 | mixer->chip->usb_id == USB_ID(0x041e, 0x3048))) | 394 | mixer->chip->usb_id == USB_ID(0x041e, 0x3048))) |
375 | break; | 395 | break; |
376 | err = snd_ctl_add(mixer->chip->card, | 396 | |
377 | snd_ctl_new1(&snd_audigy2nx_controls[i], mixer)); | 397 | knew = snd_audigy2nx_control; |
398 | knew.name = snd_audigy2nx_led_names[i]; | ||
399 | knew.private_value = (1 << 8) | i; /* LED on as default */ | ||
400 | err = add_single_ctl_with_resume(mixer, 0, | ||
401 | snd_audigy2nx_led_resume, | ||
402 | &knew, NULL); | ||
378 | if (err < 0) | 403 | if (err < 0) |
379 | return err; | 404 | return err; |
380 | } | 405 | } |
381 | mixer->audigy2nx_leds[1] = 1; /* Power LED is on by default */ | ||
382 | return 0; | 406 | return 0; |
383 | } | 407 | } |
384 | 408 | ||
@@ -437,19 +461,9 @@ static void snd_audigy2nx_proc_read(struct snd_info_entry *entry, | |||
437 | static int snd_emu0204_ch_switch_info(struct snd_kcontrol *kcontrol, | 461 | static int snd_emu0204_ch_switch_info(struct snd_kcontrol *kcontrol, |
438 | struct snd_ctl_elem_info *uinfo) | 462 | struct snd_ctl_elem_info *uinfo) |
439 | { | 463 | { |
440 | static const char *texts[2] = {"1/2", | 464 | static const char * const texts[2] = {"1/2", "3/4"}; |
441 | "3/4" | ||
442 | }; | ||
443 | 465 | ||
444 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | 466 | return snd_ctl_enum_info(uinfo, 1, ARRAY_SIZE(texts), texts); |
445 | uinfo->count = 1; | ||
446 | uinfo->value.enumerated.items = 2; | ||
447 | if (uinfo->value.enumerated.item > 1) | ||
448 | uinfo->value.enumerated.item = 1; | ||
449 | strcpy(uinfo->value.enumerated.name, | ||
450 | texts[uinfo->value.enumerated.item]); | ||
451 | |||
452 | return 0; | ||
453 | } | 467 | } |
454 | 468 | ||
455 | static int snd_emu0204_ch_switch_get(struct snd_kcontrol *kcontrol, | 469 | static int snd_emu0204_ch_switch_get(struct snd_kcontrol *kcontrol, |
@@ -459,100 +473,122 @@ static int snd_emu0204_ch_switch_get(struct snd_kcontrol *kcontrol, | |||
459 | return 0; | 473 | return 0; |
460 | } | 474 | } |
461 | 475 | ||
462 | static int snd_emu0204_ch_switch_put(struct snd_kcontrol *kcontrol, | 476 | static int snd_emu0204_ch_switch_update(struct usb_mixer_interface *mixer, |
463 | struct snd_ctl_elem_value *ucontrol) | 477 | int value) |
464 | { | 478 | { |
465 | struct usb_mixer_interface *mixer = snd_kcontrol_chip(kcontrol); | 479 | struct snd_usb_audio *chip = mixer->chip; |
466 | unsigned int value = ucontrol->value.enumerated.item[0]; | 480 | int err; |
467 | int err, changed; | ||
468 | unsigned char buf[2]; | 481 | unsigned char buf[2]; |
469 | 482 | ||
470 | if (value > 1) | 483 | down_read(&chip->shutdown_rwsem); |
471 | return -EINVAL; | ||
472 | |||
473 | buf[0] = 0x01; | ||
474 | buf[1] = value ? 0x02 : 0x01; | ||
475 | |||
476 | changed = value != kcontrol->private_value; | ||
477 | down_read(&mixer->chip->shutdown_rwsem); | ||
478 | if (mixer->chip->shutdown) { | 484 | if (mixer->chip->shutdown) { |
479 | err = -ENODEV; | 485 | err = -ENODEV; |
480 | goto out; | 486 | goto out; |
481 | } | 487 | } |
482 | err = snd_usb_ctl_msg(mixer->chip->dev, | 488 | |
483 | usb_sndctrlpipe(mixer->chip->dev, 0), UAC_SET_CUR, | 489 | buf[0] = 0x01; |
490 | buf[1] = value ? 0x02 : 0x01; | ||
491 | err = snd_usb_ctl_msg(chip->dev, | ||
492 | usb_sndctrlpipe(chip->dev, 0), UAC_SET_CUR, | ||
484 | USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT, | 493 | USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT, |
485 | 0x0400, 0x0e00, buf, 2); | 494 | 0x0400, 0x0e00, buf, 2); |
486 | out: | 495 | out: |
487 | up_read(&mixer->chip->shutdown_rwsem); | 496 | up_read(&chip->shutdown_rwsem); |
488 | if (err < 0) | 497 | return err; |
489 | return err; | 498 | } |
499 | |||
500 | static int snd_emu0204_ch_switch_put(struct snd_kcontrol *kcontrol, | ||
501 | struct snd_ctl_elem_value *ucontrol) | ||
502 | { | ||
503 | struct usb_mixer_elem_list *list = snd_kcontrol_chip(kcontrol); | ||
504 | struct usb_mixer_interface *mixer = list->mixer; | ||
505 | unsigned int value = ucontrol->value.enumerated.item[0]; | ||
506 | int err; | ||
507 | |||
508 | if (value > 1) | ||
509 | return -EINVAL; | ||
510 | |||
511 | if (value == kcontrol->private_value) | ||
512 | return 0; | ||
513 | |||
490 | kcontrol->private_value = value; | 514 | kcontrol->private_value = value; |
491 | return changed; | 515 | err = snd_emu0204_ch_switch_update(mixer, value); |
516 | return err < 0 ? err : 1; | ||
492 | } | 517 | } |
493 | 518 | ||
519 | static int snd_emu0204_ch_switch_resume(struct usb_mixer_elem_list *list) | ||
520 | { | ||
521 | return snd_emu0204_ch_switch_update(list->mixer, | ||
522 | list->kctl->private_value); | ||
523 | } | ||
494 | 524 | ||
495 | static struct snd_kcontrol_new snd_emu0204_controls[] = { | 525 | static struct snd_kcontrol_new snd_emu0204_control = { |
496 | { | 526 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
497 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 527 | .name = "Front Jack Channels", |
498 | .name = "Front Jack Channels", | 528 | .info = snd_emu0204_ch_switch_info, |
499 | .info = snd_emu0204_ch_switch_info, | 529 | .get = snd_emu0204_ch_switch_get, |
500 | .get = snd_emu0204_ch_switch_get, | 530 | .put = snd_emu0204_ch_switch_put, |
501 | .put = snd_emu0204_ch_switch_put, | 531 | .private_value = 0, |
502 | .private_value = 0, | ||
503 | }, | ||
504 | }; | 532 | }; |
505 | 533 | ||
506 | static int snd_emu0204_controls_create(struct usb_mixer_interface *mixer) | 534 | static int snd_emu0204_controls_create(struct usb_mixer_interface *mixer) |
507 | { | 535 | { |
508 | int i, err; | 536 | return add_single_ctl_with_resume(mixer, 0, |
509 | 537 | snd_emu0204_ch_switch_resume, | |
510 | for (i = 0; i < ARRAY_SIZE(snd_emu0204_controls); ++i) { | 538 | &snd_emu0204_control, NULL); |
511 | err = snd_ctl_add(mixer->chip->card, | ||
512 | snd_ctl_new1(&snd_emu0204_controls[i], mixer)); | ||
513 | if (err < 0) | ||
514 | return err; | ||
515 | } | ||
516 | |||
517 | return 0; | ||
518 | } | 539 | } |
540 | |||
519 | /* ASUS Xonar U1 / U3 controls */ | 541 | /* ASUS Xonar U1 / U3 controls */ |
520 | 542 | ||
521 | static int snd_xonar_u1_switch_get(struct snd_kcontrol *kcontrol, | 543 | static int snd_xonar_u1_switch_get(struct snd_kcontrol *kcontrol, |
522 | struct snd_ctl_elem_value *ucontrol) | 544 | struct snd_ctl_elem_value *ucontrol) |
523 | { | 545 | { |
524 | struct usb_mixer_interface *mixer = snd_kcontrol_chip(kcontrol); | 546 | ucontrol->value.integer.value[0] = !!(kcontrol->private_value & 0x02); |
525 | |||
526 | ucontrol->value.integer.value[0] = !!(mixer->xonar_u1_status & 0x02); | ||
527 | return 0; | 547 | return 0; |
528 | } | 548 | } |
529 | 549 | ||
550 | static int snd_xonar_u1_switch_update(struct usb_mixer_interface *mixer, | ||
551 | unsigned char status) | ||
552 | { | ||
553 | struct snd_usb_audio *chip = mixer->chip; | ||
554 | int err; | ||
555 | |||
556 | down_read(&chip->shutdown_rwsem); | ||
557 | if (chip->shutdown) | ||
558 | err = -ENODEV; | ||
559 | else | ||
560 | err = snd_usb_ctl_msg(chip->dev, | ||
561 | usb_sndctrlpipe(chip->dev, 0), 0x08, | ||
562 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER, | ||
563 | 50, 0, &status, 1); | ||
564 | up_read(&chip->shutdown_rwsem); | ||
565 | return err; | ||
566 | } | ||
567 | |||
530 | static int snd_xonar_u1_switch_put(struct snd_kcontrol *kcontrol, | 568 | static int snd_xonar_u1_switch_put(struct snd_kcontrol *kcontrol, |
531 | struct snd_ctl_elem_value *ucontrol) | 569 | struct snd_ctl_elem_value *ucontrol) |
532 | { | 570 | { |
533 | struct usb_mixer_interface *mixer = snd_kcontrol_chip(kcontrol); | 571 | struct usb_mixer_elem_list *list = snd_kcontrol_chip(kcontrol); |
534 | u8 old_status, new_status; | 572 | u8 old_status, new_status; |
535 | int err, changed; | 573 | int err; |
536 | 574 | ||
537 | old_status = mixer->xonar_u1_status; | 575 | old_status = kcontrol->private_value; |
538 | if (ucontrol->value.integer.value[0]) | 576 | if (ucontrol->value.integer.value[0]) |
539 | new_status = old_status | 0x02; | 577 | new_status = old_status | 0x02; |
540 | else | 578 | else |
541 | new_status = old_status & ~0x02; | 579 | new_status = old_status & ~0x02; |
542 | changed = new_status != old_status; | 580 | if (new_status == old_status) |
543 | down_read(&mixer->chip->shutdown_rwsem); | 581 | return 0; |
544 | if (mixer->chip->shutdown) | 582 | |
545 | err = -ENODEV; | 583 | kcontrol->private_value = new_status; |
546 | else | 584 | err = snd_xonar_u1_switch_update(list->mixer, new_status); |
547 | err = snd_usb_ctl_msg(mixer->chip->dev, | 585 | return err < 0 ? err : 1; |
548 | usb_sndctrlpipe(mixer->chip->dev, 0), 0x08, | 586 | } |
549 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER, | 587 | |
550 | 50, 0, &new_status, 1); | 588 | static int snd_xonar_u1_switch_resume(struct usb_mixer_elem_list *list) |
551 | up_read(&mixer->chip->shutdown_rwsem); | 589 | { |
552 | if (err < 0) | 590 | return snd_xonar_u1_switch_update(list->mixer, |
553 | return err; | 591 | list->kctl->private_value); |
554 | mixer->xonar_u1_status = new_status; | ||
555 | return changed; | ||
556 | } | 592 | } |
557 | 593 | ||
558 | static struct snd_kcontrol_new snd_xonar_u1_output_switch = { | 594 | static struct snd_kcontrol_new snd_xonar_u1_output_switch = { |
@@ -561,82 +597,213 @@ static struct snd_kcontrol_new snd_xonar_u1_output_switch = { | |||
561 | .info = snd_ctl_boolean_mono_info, | 597 | .info = snd_ctl_boolean_mono_info, |
562 | .get = snd_xonar_u1_switch_get, | 598 | .get = snd_xonar_u1_switch_get, |
563 | .put = snd_xonar_u1_switch_put, | 599 | .put = snd_xonar_u1_switch_put, |
600 | .private_value = 0x05, | ||
564 | }; | 601 | }; |
565 | 602 | ||
566 | static int snd_xonar_u1_controls_create(struct usb_mixer_interface *mixer) | 603 | static int snd_xonar_u1_controls_create(struct usb_mixer_interface *mixer) |
567 | { | 604 | { |
605 | return add_single_ctl_with_resume(mixer, 0, | ||
606 | snd_xonar_u1_switch_resume, | ||
607 | &snd_xonar_u1_output_switch, NULL); | ||
608 | } | ||
609 | |||
610 | /* Digidesign Mbox 1 clock source switch (internal/spdif) */ | ||
611 | |||
612 | static int snd_mbox1_switch_get(struct snd_kcontrol *kctl, | ||
613 | struct snd_ctl_elem_value *ucontrol) | ||
614 | { | ||
615 | ucontrol->value.enumerated.item[0] = kctl->private_value; | ||
616 | return 0; | ||
617 | } | ||
618 | |||
619 | static int snd_mbox1_switch_update(struct usb_mixer_interface *mixer, int val) | ||
620 | { | ||
621 | struct snd_usb_audio *chip = mixer->chip; | ||
568 | int err; | 622 | int err; |
623 | unsigned char buff[3]; | ||
624 | |||
625 | down_read(&chip->shutdown_rwsem); | ||
626 | if (chip->shutdown) { | ||
627 | err = -ENODEV; | ||
628 | goto err; | ||
629 | } | ||
569 | 630 | ||
570 | err = snd_ctl_add(mixer->chip->card, | 631 | /* Prepare for magic command to toggle clock source */ |
571 | snd_ctl_new1(&snd_xonar_u1_output_switch, mixer)); | 632 | err = snd_usb_ctl_msg(chip->dev, |
633 | usb_rcvctrlpipe(chip->dev, 0), 0x81, | ||
634 | USB_DIR_IN | | ||
635 | USB_TYPE_CLASS | | ||
636 | USB_RECIP_INTERFACE, 0x00, 0x500, buff, 1); | ||
572 | if (err < 0) | 637 | if (err < 0) |
573 | return err; | 638 | goto err; |
574 | mixer->xonar_u1_status = 0x05; | 639 | err = snd_usb_ctl_msg(chip->dev, |
575 | return 0; | 640 | usb_rcvctrlpipe(chip->dev, 0), 0x81, |
641 | USB_DIR_IN | | ||
642 | USB_TYPE_CLASS | | ||
643 | USB_RECIP_ENDPOINT, 0x100, 0x81, buff, 3); | ||
644 | if (err < 0) | ||
645 | goto err; | ||
646 | |||
647 | /* 2 possibilities: Internal -> send sample rate | ||
648 | * S/PDIF sync -> send zeroes | ||
649 | * NB: Sample rate locked to 48kHz on purpose to | ||
650 | * prevent user from resetting the sample rate | ||
651 | * while S/PDIF sync is enabled and confusing | ||
652 | * this configuration. | ||
653 | */ | ||
654 | if (val == 0) { | ||
655 | buff[0] = 0x80; | ||
656 | buff[1] = 0xbb; | ||
657 | buff[2] = 0x00; | ||
658 | } else { | ||
659 | buff[0] = buff[1] = buff[2] = 0x00; | ||
660 | } | ||
661 | |||
662 | /* Send the magic command to toggle the clock source */ | ||
663 | err = snd_usb_ctl_msg(chip->dev, | ||
664 | usb_sndctrlpipe(chip->dev, 0), 0x1, | ||
665 | USB_TYPE_CLASS | | ||
666 | USB_RECIP_ENDPOINT, 0x100, 0x81, buff, 3); | ||
667 | if (err < 0) | ||
668 | goto err; | ||
669 | err = snd_usb_ctl_msg(chip->dev, | ||
670 | usb_rcvctrlpipe(chip->dev, 0), 0x81, | ||
671 | USB_DIR_IN | | ||
672 | USB_TYPE_CLASS | | ||
673 | USB_RECIP_ENDPOINT, 0x100, 0x81, buff, 3); | ||
674 | if (err < 0) | ||
675 | goto err; | ||
676 | err = snd_usb_ctl_msg(chip->dev, | ||
677 | usb_rcvctrlpipe(chip->dev, 0), 0x81, | ||
678 | USB_DIR_IN | | ||
679 | USB_TYPE_CLASS | | ||
680 | USB_RECIP_ENDPOINT, 0x100, 0x2, buff, 3); | ||
681 | if (err < 0) | ||
682 | goto err; | ||
683 | |||
684 | err: | ||
685 | up_read(&chip->shutdown_rwsem); | ||
686 | return err; | ||
687 | } | ||
688 | |||
689 | static int snd_mbox1_switch_put(struct snd_kcontrol *kctl, | ||
690 | struct snd_ctl_elem_value *ucontrol) | ||
691 | { | ||
692 | struct usb_mixer_elem_list *list = snd_kcontrol_chip(kctl); | ||
693 | struct usb_mixer_interface *mixer = list->mixer; | ||
694 | int err; | ||
695 | bool cur_val, new_val; | ||
696 | |||
697 | cur_val = kctl->private_value; | ||
698 | new_val = ucontrol->value.enumerated.item[0]; | ||
699 | if (cur_val == new_val) | ||
700 | return 0; | ||
701 | |||
702 | kctl->private_value = new_val; | ||
703 | err = snd_mbox1_switch_update(mixer, new_val); | ||
704 | return err < 0 ? err : 1; | ||
705 | } | ||
706 | |||
707 | static int snd_mbox1_switch_info(struct snd_kcontrol *kcontrol, | ||
708 | struct snd_ctl_elem_info *uinfo) | ||
709 | { | ||
710 | static const char *const texts[2] = { | ||
711 | "Internal", | ||
712 | "S/PDIF" | ||
713 | }; | ||
714 | |||
715 | return snd_ctl_enum_info(uinfo, 1, ARRAY_SIZE(texts), texts); | ||
716 | } | ||
717 | |||
718 | static int snd_mbox1_switch_resume(struct usb_mixer_elem_list *list) | ||
719 | { | ||
720 | return snd_mbox1_switch_update(list->mixer, list->kctl->private_value); | ||
721 | } | ||
722 | |||
723 | static struct snd_kcontrol_new snd_mbox1_switch = { | ||
724 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
725 | .name = "Clock Source", | ||
726 | .index = 0, | ||
727 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, | ||
728 | .info = snd_mbox1_switch_info, | ||
729 | .get = snd_mbox1_switch_get, | ||
730 | .put = snd_mbox1_switch_put, | ||
731 | .private_value = 0 | ||
732 | }; | ||
733 | |||
734 | static int snd_mbox1_create_sync_switch(struct usb_mixer_interface *mixer) | ||
735 | { | ||
736 | return add_single_ctl_with_resume(mixer, 0, | ||
737 | snd_mbox1_switch_resume, | ||
738 | &snd_mbox1_switch, NULL); | ||
576 | } | 739 | } |
577 | 740 | ||
578 | /* Native Instruments device quirks */ | 741 | /* Native Instruments device quirks */ |
579 | 742 | ||
580 | #define _MAKE_NI_CONTROL(bRequest,wIndex) ((bRequest) << 16 | (wIndex)) | 743 | #define _MAKE_NI_CONTROL(bRequest,wIndex) ((bRequest) << 16 | (wIndex)) |
581 | 744 | ||
582 | static int snd_nativeinstruments_control_get(struct snd_kcontrol *kcontrol, | 745 | static int snd_ni_control_init_val(struct usb_mixer_interface *mixer, |
583 | struct snd_ctl_elem_value *ucontrol) | 746 | struct snd_kcontrol *kctl) |
584 | { | 747 | { |
585 | struct usb_mixer_interface *mixer = snd_kcontrol_chip(kcontrol); | ||
586 | struct usb_device *dev = mixer->chip->dev; | 748 | struct usb_device *dev = mixer->chip->dev; |
587 | u8 bRequest = (kcontrol->private_value >> 16) & 0xff; | 749 | unsigned int pval = kctl->private_value; |
588 | u16 wIndex = kcontrol->private_value & 0xffff; | 750 | u8 value; |
589 | u8 tmp; | 751 | int err; |
590 | int ret; | ||
591 | |||
592 | down_read(&mixer->chip->shutdown_rwsem); | ||
593 | if (mixer->chip->shutdown) | ||
594 | ret = -ENODEV; | ||
595 | else | ||
596 | ret = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), bRequest, | ||
597 | USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, | ||
598 | 0, wIndex, | ||
599 | &tmp, sizeof(tmp)); | ||
600 | up_read(&mixer->chip->shutdown_rwsem); | ||
601 | 752 | ||
602 | if (ret < 0) { | 753 | err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), |
754 | (pval >> 16) & 0xff, | ||
755 | USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, | ||
756 | 0, pval & 0xffff, &value, 1); | ||
757 | if (err < 0) { | ||
603 | dev_err(&dev->dev, | 758 | dev_err(&dev->dev, |
604 | "unable to issue vendor read request (ret = %d)", ret); | 759 | "unable to issue vendor read request (ret = %d)", err); |
605 | return ret; | 760 | return err; |
606 | } | 761 | } |
607 | 762 | ||
608 | ucontrol->value.integer.value[0] = tmp; | 763 | kctl->private_value |= (value << 24); |
764 | return 0; | ||
765 | } | ||
609 | 766 | ||
767 | static int snd_nativeinstruments_control_get(struct snd_kcontrol *kcontrol, | ||
768 | struct snd_ctl_elem_value *ucontrol) | ||
769 | { | ||
770 | ucontrol->value.integer.value[0] = kcontrol->private_value >> 24; | ||
610 | return 0; | 771 | return 0; |
611 | } | 772 | } |
612 | 773 | ||
774 | static int snd_ni_update_cur_val(struct usb_mixer_elem_list *list) | ||
775 | { | ||
776 | struct snd_usb_audio *chip = list->mixer->chip; | ||
777 | unsigned int pval = list->kctl->private_value; | ||
778 | int err; | ||
779 | |||
780 | down_read(&chip->shutdown_rwsem); | ||
781 | if (chip->shutdown) | ||
782 | err = -ENODEV; | ||
783 | else | ||
784 | err = usb_control_msg(chip->dev, usb_sndctrlpipe(chip->dev, 0), | ||
785 | (pval >> 16) & 0xff, | ||
786 | USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT, | ||
787 | pval >> 24, pval & 0xffff, NULL, 0, 1000); | ||
788 | up_read(&chip->shutdown_rwsem); | ||
789 | return err; | ||
790 | } | ||
791 | |||
613 | static int snd_nativeinstruments_control_put(struct snd_kcontrol *kcontrol, | 792 | static int snd_nativeinstruments_control_put(struct snd_kcontrol *kcontrol, |
614 | struct snd_ctl_elem_value *ucontrol) | 793 | struct snd_ctl_elem_value *ucontrol) |
615 | { | 794 | { |
616 | struct usb_mixer_interface *mixer = snd_kcontrol_chip(kcontrol); | 795 | struct usb_mixer_elem_list *list = snd_kcontrol_chip(kcontrol); |
617 | struct usb_device *dev = mixer->chip->dev; | 796 | u8 oldval = (kcontrol->private_value >> 24) & 0xff; |
618 | u8 bRequest = (kcontrol->private_value >> 16) & 0xff; | 797 | u8 newval = ucontrol->value.integer.value[0]; |
619 | u16 wIndex = kcontrol->private_value & 0xffff; | 798 | int err; |
620 | u16 wValue = ucontrol->value.integer.value[0]; | ||
621 | int ret; | ||
622 | |||
623 | down_read(&mixer->chip->shutdown_rwsem); | ||
624 | if (mixer->chip->shutdown) | ||
625 | ret = -ENODEV; | ||
626 | else | ||
627 | ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), bRequest, | ||
628 | USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT, | ||
629 | wValue, wIndex, | ||
630 | NULL, 0, 1000); | ||
631 | up_read(&mixer->chip->shutdown_rwsem); | ||
632 | 799 | ||
633 | if (ret < 0) { | 800 | if (oldval == newval) |
634 | dev_err(&dev->dev, | 801 | return 0; |
635 | "unable to issue vendor write request (ret = %d)", ret); | ||
636 | return ret; | ||
637 | } | ||
638 | 802 | ||
639 | return 0; | 803 | kcontrol->private_value &= ~(0xff << 24); |
804 | kcontrol->private_value |= newval; | ||
805 | err = snd_ni_update_cur_val(list); | ||
806 | return err < 0 ? err : 1; | ||
640 | } | 807 | } |
641 | 808 | ||
642 | static struct snd_kcontrol_new snd_nativeinstruments_ta6_mixers[] = { | 809 | static struct snd_kcontrol_new snd_nativeinstruments_ta6_mixers[] = { |
@@ -707,16 +874,17 @@ static int snd_nativeinstruments_create_mixer(struct usb_mixer_interface *mixer, | |||
707 | }; | 874 | }; |
708 | 875 | ||
709 | for (i = 0; i < count; i++) { | 876 | for (i = 0; i < count; i++) { |
710 | struct snd_kcontrol *c; | 877 | struct usb_mixer_elem_list *list; |
711 | 878 | ||
712 | template.name = kc[i].name; | 879 | template.name = kc[i].name; |
713 | template.private_value = kc[i].private_value; | 880 | template.private_value = kc[i].private_value; |
714 | 881 | ||
715 | c = snd_ctl_new1(&template, mixer); | 882 | err = add_single_ctl_with_resume(mixer, 0, |
716 | err = snd_ctl_add(mixer->chip->card, c); | 883 | snd_ni_update_cur_val, |
717 | 884 | &template, &list); | |
718 | if (err < 0) | 885 | if (err < 0) |
719 | break; | 886 | break; |
887 | snd_ni_control_init_val(mixer, list->kctl); | ||
720 | } | 888 | } |
721 | 889 | ||
722 | return err; | 890 | return err; |
@@ -724,170 +892,88 @@ static int snd_nativeinstruments_create_mixer(struct usb_mixer_interface *mixer, | |||
724 | 892 | ||
725 | /* M-Audio FastTrack Ultra quirks */ | 893 | /* M-Audio FastTrack Ultra quirks */ |
726 | /* FTU Effect switch (also used by C400/C600) */ | 894 | /* FTU Effect switch (also used by C400/C600) */ |
727 | struct snd_ftu_eff_switch_priv_val { | ||
728 | struct usb_mixer_interface *mixer; | ||
729 | int cached_value; | ||
730 | int is_cached; | ||
731 | int bUnitID; | ||
732 | int validx; | ||
733 | }; | ||
734 | |||
735 | static int snd_ftu_eff_switch_info(struct snd_kcontrol *kcontrol, | 895 | static int snd_ftu_eff_switch_info(struct snd_kcontrol *kcontrol, |
736 | struct snd_ctl_elem_info *uinfo) | 896 | struct snd_ctl_elem_info *uinfo) |
737 | { | 897 | { |
738 | static const char *texts[8] = {"Room 1", | 898 | static const char *const texts[8] = { |
739 | "Room 2", | 899 | "Room 1", "Room 2", "Room 3", "Hall 1", |
740 | "Room 3", | 900 | "Hall 2", "Plate", "Delay", "Echo" |
741 | "Hall 1", | ||
742 | "Hall 2", | ||
743 | "Plate", | ||
744 | "Delay", | ||
745 | "Echo" | ||
746 | }; | 901 | }; |
747 | 902 | ||
748 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | 903 | return snd_ctl_enum_info(uinfo, 1, ARRAY_SIZE(texts), texts); |
749 | uinfo->count = 1; | ||
750 | uinfo->value.enumerated.items = 8; | ||
751 | if (uinfo->value.enumerated.item > 7) | ||
752 | uinfo->value.enumerated.item = 7; | ||
753 | strcpy(uinfo->value.enumerated.name, | ||
754 | texts[uinfo->value.enumerated.item]); | ||
755 | |||
756 | return 0; | ||
757 | } | 904 | } |
758 | 905 | ||
759 | static int snd_ftu_eff_switch_get(struct snd_kcontrol *kctl, | 906 | static int snd_ftu_eff_switch_init(struct usb_mixer_interface *mixer, |
760 | struct snd_ctl_elem_value *ucontrol) | 907 | struct snd_kcontrol *kctl) |
761 | { | 908 | { |
762 | struct snd_usb_audio *chip; | 909 | struct usb_device *dev = mixer->chip->dev; |
763 | struct usb_mixer_interface *mixer; | 910 | unsigned int pval = kctl->private_value; |
764 | struct snd_ftu_eff_switch_priv_val *pval; | ||
765 | int err; | 911 | int err; |
766 | unsigned char value[2]; | 912 | unsigned char value[2]; |
767 | int id, validx; | ||
768 | |||
769 | const int val_len = 2; | ||
770 | 913 | ||
771 | value[0] = 0x00; | 914 | value[0] = 0x00; |
772 | value[1] = 0x00; | 915 | value[1] = 0x00; |
773 | 916 | ||
774 | pval = (struct snd_ftu_eff_switch_priv_val *) | 917 | err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC_GET_CUR, |
775 | kctl->private_value; | 918 | USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, |
919 | pval & 0xff00, | ||
920 | snd_usb_ctrl_intf(mixer->chip) | ((pval & 0xff) << 8), | ||
921 | value, 2); | ||
922 | if (err < 0) | ||
923 | return err; | ||
776 | 924 | ||
777 | if (pval->is_cached) { | 925 | kctl->private_value |= value[0] << 24; |
778 | ucontrol->value.enumerated.item[0] = pval->cached_value; | 926 | return 0; |
779 | return 0; | 927 | } |
780 | } | ||
781 | 928 | ||
782 | mixer = (struct usb_mixer_interface *) pval->mixer; | 929 | static int snd_ftu_eff_switch_get(struct snd_kcontrol *kctl, |
783 | if (snd_BUG_ON(!mixer)) | 930 | struct snd_ctl_elem_value *ucontrol) |
784 | return -EINVAL; | 931 | { |
932 | ucontrol->value.enumerated.item[0] = kctl->private_value >> 24; | ||
933 | return 0; | ||
934 | } | ||
785 | 935 | ||
786 | chip = (struct snd_usb_audio *) mixer->chip; | 936 | static int snd_ftu_eff_switch_update(struct usb_mixer_elem_list *list) |
787 | if (snd_BUG_ON(!chip)) | 937 | { |
788 | return -EINVAL; | 938 | struct snd_usb_audio *chip = list->mixer->chip; |
939 | unsigned int pval = list->kctl->private_value; | ||
940 | unsigned char value[2]; | ||
941 | int err; | ||
789 | 942 | ||
790 | id = pval->bUnitID; | 943 | value[0] = pval >> 24; |
791 | validx = pval->validx; | 944 | value[1] = 0; |
792 | 945 | ||
793 | down_read(&mixer->chip->shutdown_rwsem); | 946 | down_read(&chip->shutdown_rwsem); |
794 | if (mixer->chip->shutdown) | 947 | if (chip->shutdown) |
795 | err = -ENODEV; | 948 | err = -ENODEV; |
796 | else | 949 | else |
797 | err = snd_usb_ctl_msg(chip->dev, | 950 | err = snd_usb_ctl_msg(chip->dev, |
798 | usb_rcvctrlpipe(chip->dev, 0), UAC_GET_CUR, | 951 | usb_sndctrlpipe(chip->dev, 0), |
799 | USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, | 952 | UAC_SET_CUR, |
800 | validx << 8, snd_usb_ctrl_intf(chip) | (id << 8), | 953 | USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT, |
801 | value, val_len); | 954 | pval & 0xff00, |
802 | up_read(&mixer->chip->shutdown_rwsem); | 955 | snd_usb_ctrl_intf(chip) | ((pval & 0xff) << 8), |
803 | if (err < 0) | 956 | value, 2); |
804 | return err; | 957 | up_read(&chip->shutdown_rwsem); |
805 | 958 | return err; | |
806 | ucontrol->value.enumerated.item[0] = value[0]; | ||
807 | pval->cached_value = value[0]; | ||
808 | pval->is_cached = 1; | ||
809 | |||
810 | return 0; | ||
811 | } | 959 | } |
812 | 960 | ||
813 | static int snd_ftu_eff_switch_put(struct snd_kcontrol *kctl, | 961 | static int snd_ftu_eff_switch_put(struct snd_kcontrol *kctl, |
814 | struct snd_ctl_elem_value *ucontrol) | 962 | struct snd_ctl_elem_value *ucontrol) |
815 | { | 963 | { |
816 | struct snd_usb_audio *chip; | 964 | struct usb_mixer_elem_list *list = snd_kcontrol_chip(kctl); |
817 | struct snd_ftu_eff_switch_priv_val *pval; | 965 | unsigned int pval = list->kctl->private_value; |
966 | int cur_val, err, new_val; | ||
818 | 967 | ||
819 | struct usb_mixer_interface *mixer; | 968 | cur_val = pval >> 24; |
820 | int changed, cur_val, err, new_val; | ||
821 | unsigned char value[2]; | ||
822 | int id, validx; | ||
823 | |||
824 | const int val_len = 2; | ||
825 | |||
826 | changed = 0; | ||
827 | |||
828 | pval = (struct snd_ftu_eff_switch_priv_val *) | ||
829 | kctl->private_value; | ||
830 | cur_val = pval->cached_value; | ||
831 | new_val = ucontrol->value.enumerated.item[0]; | 969 | new_val = ucontrol->value.enumerated.item[0]; |
970 | if (cur_val == new_val) | ||
971 | return 0; | ||
832 | 972 | ||
833 | mixer = (struct usb_mixer_interface *) pval->mixer; | 973 | kctl->private_value &= ~(0xff << 24); |
834 | if (snd_BUG_ON(!mixer)) | 974 | kctl->private_value |= new_val << 24; |
835 | return -EINVAL; | 975 | err = snd_ftu_eff_switch_update(list); |
836 | 976 | return err < 0 ? err : 1; | |
837 | chip = (struct snd_usb_audio *) mixer->chip; | ||
838 | if (snd_BUG_ON(!chip)) | ||
839 | return -EINVAL; | ||
840 | |||
841 | id = pval->bUnitID; | ||
842 | validx = pval->validx; | ||
843 | |||
844 | if (!pval->is_cached) { | ||
845 | /* Read current value */ | ||
846 | down_read(&mixer->chip->shutdown_rwsem); | ||
847 | if (mixer->chip->shutdown) | ||
848 | err = -ENODEV; | ||
849 | else | ||
850 | err = snd_usb_ctl_msg(chip->dev, | ||
851 | usb_rcvctrlpipe(chip->dev, 0), UAC_GET_CUR, | ||
852 | USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, | ||
853 | validx << 8, snd_usb_ctrl_intf(chip) | (id << 8), | ||
854 | value, val_len); | ||
855 | up_read(&mixer->chip->shutdown_rwsem); | ||
856 | if (err < 0) | ||
857 | return err; | ||
858 | |||
859 | cur_val = value[0]; | ||
860 | pval->cached_value = cur_val; | ||
861 | pval->is_cached = 1; | ||
862 | } | ||
863 | /* update value if needed */ | ||
864 | if (cur_val != new_val) { | ||
865 | value[0] = new_val; | ||
866 | value[1] = 0; | ||
867 | down_read(&mixer->chip->shutdown_rwsem); | ||
868 | if (mixer->chip->shutdown) | ||
869 | err = -ENODEV; | ||
870 | else | ||
871 | err = snd_usb_ctl_msg(chip->dev, | ||
872 | usb_sndctrlpipe(chip->dev, 0), UAC_SET_CUR, | ||
873 | USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT, | ||
874 | validx << 8, snd_usb_ctrl_intf(chip) | (id << 8), | ||
875 | value, val_len); | ||
876 | up_read(&mixer->chip->shutdown_rwsem); | ||
877 | if (err < 0) | ||
878 | return err; | ||
879 | |||
880 | pval->cached_value = new_val; | ||
881 | pval->is_cached = 1; | ||
882 | changed = 1; | ||
883 | } | ||
884 | |||
885 | return changed; | ||
886 | } | ||
887 | |||
888 | static void kctl_private_value_free(struct snd_kcontrol *kctl) | ||
889 | { | ||
890 | kfree((void *)kctl->private_value); | ||
891 | } | 977 | } |
892 | 978 | ||
893 | static int snd_ftu_create_effect_switch(struct usb_mixer_interface *mixer, | 979 | static int snd_ftu_create_effect_switch(struct usb_mixer_interface *mixer, |
@@ -902,33 +988,16 @@ static int snd_ftu_create_effect_switch(struct usb_mixer_interface *mixer, | |||
902 | .get = snd_ftu_eff_switch_get, | 988 | .get = snd_ftu_eff_switch_get, |
903 | .put = snd_ftu_eff_switch_put | 989 | .put = snd_ftu_eff_switch_put |
904 | }; | 990 | }; |
905 | 991 | struct usb_mixer_elem_list *list; | |
906 | int err; | 992 | int err; |
907 | struct snd_kcontrol *kctl; | ||
908 | struct snd_ftu_eff_switch_priv_val *pval; | ||
909 | |||
910 | pval = kzalloc(sizeof(*pval), GFP_KERNEL); | ||
911 | if (!pval) | ||
912 | return -ENOMEM; | ||
913 | |||
914 | pval->cached_value = 0; | ||
915 | pval->is_cached = 0; | ||
916 | pval->mixer = mixer; | ||
917 | pval->bUnitID = bUnitID; | ||
918 | pval->validx = validx; | ||
919 | |||
920 | template.private_value = (unsigned long) pval; | ||
921 | kctl = snd_ctl_new1(&template, mixer->chip); | ||
922 | if (!kctl) { | ||
923 | kfree(pval); | ||
924 | return -ENOMEM; | ||
925 | } | ||
926 | 993 | ||
927 | kctl->private_free = kctl_private_value_free; | 994 | err = add_single_ctl_with_resume(mixer, bUnitID, |
928 | err = snd_ctl_add(mixer->chip->card, kctl); | 995 | snd_ftu_eff_switch_update, |
996 | &template, &list); | ||
929 | if (err < 0) | 997 | if (err < 0) |
930 | return err; | 998 | return err; |
931 | 999 | list->kctl->private_value = (validx << 8) | bUnitID; | |
1000 | snd_ftu_eff_switch_init(mixer, list->kctl); | ||
932 | return 0; | 1001 | return 0; |
933 | } | 1002 | } |
934 | 1003 | ||
@@ -1110,7 +1179,7 @@ void snd_emuusb_set_samplerate(struct snd_usb_audio *chip, | |||
1110 | int unitid = 12; /* SamleRate ExtensionUnit ID */ | 1179 | int unitid = 12; /* SamleRate ExtensionUnit ID */ |
1111 | 1180 | ||
1112 | list_for_each_entry(mixer, &chip->mixer_list, list) { | 1181 | list_for_each_entry(mixer, &chip->mixer_list, list) { |
1113 | cval = mixer->id_elems[unitid]; | 1182 | cval = (struct usb_mixer_elem_info *)mixer->id_elems[unitid]; |
1114 | if (cval) { | 1183 | if (cval) { |
1115 | snd_usb_mixer_set_ctl_value(cval, UAC_SET_CUR, | 1184 | snd_usb_mixer_set_ctl_value(cval, UAC_SET_CUR, |
1116 | cval->control << 8, | 1185 | cval->control << 8, |
@@ -1440,7 +1509,8 @@ static int snd_microii_spdif_info(struct snd_kcontrol *kcontrol, | |||
1440 | static int snd_microii_spdif_default_get(struct snd_kcontrol *kcontrol, | 1509 | static int snd_microii_spdif_default_get(struct snd_kcontrol *kcontrol, |
1441 | struct snd_ctl_elem_value *ucontrol) | 1510 | struct snd_ctl_elem_value *ucontrol) |
1442 | { | 1511 | { |
1443 | struct usb_mixer_interface *mixer = snd_kcontrol_chip(kcontrol); | 1512 | struct usb_mixer_elem_list *list = snd_kcontrol_chip(kcontrol); |
1513 | struct snd_usb_audio *chip = list->mixer->chip; | ||
1444 | int err; | 1514 | int err; |
1445 | struct usb_interface *iface; | 1515 | struct usb_interface *iface; |
1446 | struct usb_host_interface *alts; | 1516 | struct usb_host_interface *alts; |
@@ -1448,17 +1518,23 @@ static int snd_microii_spdif_default_get(struct snd_kcontrol *kcontrol, | |||
1448 | unsigned char data[3]; | 1518 | unsigned char data[3]; |
1449 | int rate; | 1519 | int rate; |
1450 | 1520 | ||
1521 | down_read(&chip->shutdown_rwsem); | ||
1522 | if (chip->shutdown) { | ||
1523 | err = -ENODEV; | ||
1524 | goto end; | ||
1525 | } | ||
1526 | |||
1451 | ucontrol->value.iec958.status[0] = kcontrol->private_value & 0xff; | 1527 | ucontrol->value.iec958.status[0] = kcontrol->private_value & 0xff; |
1452 | ucontrol->value.iec958.status[1] = (kcontrol->private_value >> 8) & 0xff; | 1528 | ucontrol->value.iec958.status[1] = (kcontrol->private_value >> 8) & 0xff; |
1453 | ucontrol->value.iec958.status[2] = 0x00; | 1529 | ucontrol->value.iec958.status[2] = 0x00; |
1454 | 1530 | ||
1455 | /* use known values for that card: interface#1 altsetting#1 */ | 1531 | /* use known values for that card: interface#1 altsetting#1 */ |
1456 | iface = usb_ifnum_to_if(mixer->chip->dev, 1); | 1532 | iface = usb_ifnum_to_if(chip->dev, 1); |
1457 | alts = &iface->altsetting[1]; | 1533 | alts = &iface->altsetting[1]; |
1458 | ep = get_endpoint(alts, 0)->bEndpointAddress; | 1534 | ep = get_endpoint(alts, 0)->bEndpointAddress; |
1459 | 1535 | ||
1460 | err = snd_usb_ctl_msg(mixer->chip->dev, | 1536 | err = snd_usb_ctl_msg(chip->dev, |
1461 | usb_rcvctrlpipe(mixer->chip->dev, 0), | 1537 | usb_rcvctrlpipe(chip->dev, 0), |
1462 | UAC_GET_CUR, | 1538 | UAC_GET_CUR, |
1463 | USB_TYPE_CLASS | USB_RECIP_ENDPOINT | USB_DIR_IN, | 1539 | USB_TYPE_CLASS | USB_RECIP_ENDPOINT | USB_DIR_IN, |
1464 | UAC_EP_CS_ATTR_SAMPLE_RATE << 8, | 1540 | UAC_EP_CS_ATTR_SAMPLE_RATE << 8, |
@@ -1473,22 +1549,27 @@ static int snd_microii_spdif_default_get(struct snd_kcontrol *kcontrol, | |||
1473 | IEC958_AES3_CON_FS_48000 : IEC958_AES3_CON_FS_44100; | 1549 | IEC958_AES3_CON_FS_48000 : IEC958_AES3_CON_FS_44100; |
1474 | 1550 | ||
1475 | err = 0; | 1551 | err = 0; |
1476 | end: | 1552 | end: |
1553 | up_read(&chip->shutdown_rwsem); | ||
1477 | return err; | 1554 | return err; |
1478 | } | 1555 | } |
1479 | 1556 | ||
1480 | static int snd_microii_spdif_default_put(struct snd_kcontrol *kcontrol, | 1557 | static int snd_microii_spdif_default_update(struct usb_mixer_elem_list *list) |
1481 | struct snd_ctl_elem_value *ucontrol) | ||
1482 | { | 1558 | { |
1483 | struct usb_mixer_interface *mixer = snd_kcontrol_chip(kcontrol); | 1559 | struct snd_usb_audio *chip = list->mixer->chip; |
1484 | int err; | 1560 | unsigned int pval = list->kctl->private_value; |
1485 | u8 reg; | 1561 | u8 reg; |
1486 | unsigned long priv_backup = kcontrol->private_value; | 1562 | int err; |
1487 | 1563 | ||
1488 | reg = ((ucontrol->value.iec958.status[1] & 0x0f) << 4) | | 1564 | down_read(&chip->shutdown_rwsem); |
1489 | (ucontrol->value.iec958.status[0] & 0x0f); | 1565 | if (chip->shutdown) { |
1490 | err = snd_usb_ctl_msg(mixer->chip->dev, | 1566 | err = -ENODEV; |
1491 | usb_sndctrlpipe(mixer->chip->dev, 0), | 1567 | goto end; |
1568 | } | ||
1569 | |||
1570 | reg = ((pval >> 4) & 0xf0) | (pval & 0x0f); | ||
1571 | err = snd_usb_ctl_msg(chip->dev, | ||
1572 | usb_sndctrlpipe(chip->dev, 0), | ||
1492 | UAC_SET_CUR, | 1573 | UAC_SET_CUR, |
1493 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER, | 1574 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER, |
1494 | reg, | 1575 | reg, |
@@ -1498,15 +1579,10 @@ static int snd_microii_spdif_default_put(struct snd_kcontrol *kcontrol, | |||
1498 | if (err < 0) | 1579 | if (err < 0) |
1499 | goto end; | 1580 | goto end; |
1500 | 1581 | ||
1501 | kcontrol->private_value &= 0xfffff0f0; | 1582 | reg = (pval & IEC958_AES0_NONAUDIO) ? 0xa0 : 0x20; |
1502 | kcontrol->private_value |= (ucontrol->value.iec958.status[1] & 0x0f) << 8; | 1583 | reg |= (pval >> 12) & 0x0f; |
1503 | kcontrol->private_value |= (ucontrol->value.iec958.status[0] & 0x0f); | 1584 | err = snd_usb_ctl_msg(chip->dev, |
1504 | 1585 | usb_sndctrlpipe(chip->dev, 0), | |
1505 | reg = (ucontrol->value.iec958.status[0] & IEC958_AES0_NONAUDIO) ? | ||
1506 | 0xa0 : 0x20; | ||
1507 | reg |= (ucontrol->value.iec958.status[1] >> 4) & 0x0f; | ||
1508 | err = snd_usb_ctl_msg(mixer->chip->dev, | ||
1509 | usb_sndctrlpipe(mixer->chip->dev, 0), | ||
1510 | UAC_SET_CUR, | 1586 | UAC_SET_CUR, |
1511 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER, | 1587 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER, |
1512 | reg, | 1588 | reg, |
@@ -1516,16 +1592,36 @@ static int snd_microii_spdif_default_put(struct snd_kcontrol *kcontrol, | |||
1516 | if (err < 0) | 1592 | if (err < 0) |
1517 | goto end; | 1593 | goto end; |
1518 | 1594 | ||
1519 | kcontrol->private_value &= 0xffff0fff; | 1595 | end: |
1520 | kcontrol->private_value |= (ucontrol->value.iec958.status[1] & 0xf0) << 8; | 1596 | up_read(&chip->shutdown_rwsem); |
1597 | return err; | ||
1598 | } | ||
1599 | |||
1600 | static int snd_microii_spdif_default_put(struct snd_kcontrol *kcontrol, | ||
1601 | struct snd_ctl_elem_value *ucontrol) | ||
1602 | { | ||
1603 | struct usb_mixer_elem_list *list = snd_kcontrol_chip(kcontrol); | ||
1604 | unsigned int pval, pval_old; | ||
1605 | int err; | ||
1606 | |||
1607 | pval = pval_old = kcontrol->private_value; | ||
1608 | pval &= 0xfffff0f0; | ||
1609 | pval |= (ucontrol->value.iec958.status[1] & 0x0f) << 8; | ||
1610 | pval |= (ucontrol->value.iec958.status[0] & 0x0f); | ||
1611 | |||
1612 | pval &= 0xffff0fff; | ||
1613 | pval |= (ucontrol->value.iec958.status[1] & 0xf0) << 8; | ||
1521 | 1614 | ||
1522 | /* The frequency bits in AES3 cannot be set via register access. */ | 1615 | /* The frequency bits in AES3 cannot be set via register access. */ |
1523 | 1616 | ||
1524 | /* Silently ignore any bits from the request that cannot be set. */ | 1617 | /* Silently ignore any bits from the request that cannot be set. */ |
1525 | 1618 | ||
1526 | err = (priv_backup != kcontrol->private_value); | 1619 | if (pval == pval_old) |
1527 | end: | 1620 | return 0; |
1528 | return err; | 1621 | |
1622 | kcontrol->private_value = pval; | ||
1623 | err = snd_microii_spdif_default_update(list); | ||
1624 | return err < 0 ? err : 1; | ||
1529 | } | 1625 | } |
1530 | 1626 | ||
1531 | static int snd_microii_spdif_mask_get(struct snd_kcontrol *kcontrol, | 1627 | static int snd_microii_spdif_mask_get(struct snd_kcontrol *kcontrol, |
@@ -1547,15 +1643,20 @@ static int snd_microii_spdif_switch_get(struct snd_kcontrol *kcontrol, | |||
1547 | return 0; | 1643 | return 0; |
1548 | } | 1644 | } |
1549 | 1645 | ||
1550 | static int snd_microii_spdif_switch_put(struct snd_kcontrol *kcontrol, | 1646 | static int snd_microii_spdif_switch_update(struct usb_mixer_elem_list *list) |
1551 | struct snd_ctl_elem_value *ucontrol) | ||
1552 | { | 1647 | { |
1553 | struct usb_mixer_interface *mixer = snd_kcontrol_chip(kcontrol); | 1648 | struct snd_usb_audio *chip = list->mixer->chip; |
1649 | u8 reg = list->kctl->private_value; | ||
1554 | int err; | 1650 | int err; |
1555 | u8 reg = ucontrol->value.integer.value[0] ? 0x28 : 0x2a; | ||
1556 | 1651 | ||
1557 | err = snd_usb_ctl_msg(mixer->chip->dev, | 1652 | down_read(&chip->shutdown_rwsem); |
1558 | usb_sndctrlpipe(mixer->chip->dev, 0), | 1653 | if (chip->shutdown) { |
1654 | err = -ENODEV; | ||
1655 | goto end; | ||
1656 | } | ||
1657 | |||
1658 | err = snd_usb_ctl_msg(chip->dev, | ||
1659 | usb_sndctrlpipe(chip->dev, 0), | ||
1559 | UAC_SET_CUR, | 1660 | UAC_SET_CUR, |
1560 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER, | 1661 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER, |
1561 | reg, | 1662 | reg, |
@@ -1563,15 +1664,27 @@ static int snd_microii_spdif_switch_put(struct snd_kcontrol *kcontrol, | |||
1563 | NULL, | 1664 | NULL, |
1564 | 0); | 1665 | 0); |
1565 | 1666 | ||
1566 | if (!err) { | 1667 | end: |
1567 | err = (reg != (kcontrol->private_value & 0x0ff)); | 1668 | up_read(&chip->shutdown_rwsem); |
1568 | if (err) | ||
1569 | kcontrol->private_value = reg; | ||
1570 | } | ||
1571 | |||
1572 | return err; | 1669 | return err; |
1573 | } | 1670 | } |
1574 | 1671 | ||
1672 | static int snd_microii_spdif_switch_put(struct snd_kcontrol *kcontrol, | ||
1673 | struct snd_ctl_elem_value *ucontrol) | ||
1674 | { | ||
1675 | struct usb_mixer_elem_list *list = snd_kcontrol_chip(kcontrol); | ||
1676 | u8 reg; | ||
1677 | int err; | ||
1678 | |||
1679 | reg = ucontrol->value.integer.value[0] ? 0x28 : 0x2a; | ||
1680 | if (reg != list->kctl->private_value) | ||
1681 | return 0; | ||
1682 | |||
1683 | kcontrol->private_value = reg; | ||
1684 | err = snd_microii_spdif_switch_update(list); | ||
1685 | return err < 0 ? err : 1; | ||
1686 | } | ||
1687 | |||
1575 | static struct snd_kcontrol_new snd_microii_mixer_spdif[] = { | 1688 | static struct snd_kcontrol_new snd_microii_mixer_spdif[] = { |
1576 | { | 1689 | { |
1577 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, | 1690 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, |
@@ -1601,10 +1714,17 @@ static struct snd_kcontrol_new snd_microii_mixer_spdif[] = { | |||
1601 | static int snd_microii_controls_create(struct usb_mixer_interface *mixer) | 1714 | static int snd_microii_controls_create(struct usb_mixer_interface *mixer) |
1602 | { | 1715 | { |
1603 | int err, i; | 1716 | int err, i; |
1717 | static usb_mixer_elem_resume_func_t resume_funcs[] = { | ||
1718 | snd_microii_spdif_default_update, | ||
1719 | NULL, | ||
1720 | snd_microii_spdif_switch_update | ||
1721 | }; | ||
1604 | 1722 | ||
1605 | for (i = 0; i < ARRAY_SIZE(snd_microii_mixer_spdif); ++i) { | 1723 | for (i = 0; i < ARRAY_SIZE(snd_microii_mixer_spdif); ++i) { |
1606 | err = snd_ctl_add(mixer->chip->card, | 1724 | err = add_single_ctl_with_resume(mixer, 0, |
1607 | snd_ctl_new1(&snd_microii_mixer_spdif[i], mixer)); | 1725 | resume_funcs[i], |
1726 | &snd_microii_mixer_spdif[i], | ||
1727 | NULL); | ||
1608 | if (err < 0) | 1728 | if (err < 0) |
1609 | return err; | 1729 | return err; |
1610 | } | 1730 | } |
@@ -1661,6 +1781,10 @@ int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer) | |||
1661 | err = snd_microii_controls_create(mixer); | 1781 | err = snd_microii_controls_create(mixer); |
1662 | break; | 1782 | break; |
1663 | 1783 | ||
1784 | case USB_ID(0x0dba, 0x1000): /* Digidesign Mbox 1 */ | ||
1785 | err = snd_mbox1_create_sync_switch(mixer); | ||
1786 | break; | ||
1787 | |||
1664 | case USB_ID(0x17cc, 0x1011): /* Traktor Audio 6 */ | 1788 | case USB_ID(0x17cc, 0x1011): /* Traktor Audio 6 */ |
1665 | err = snd_nativeinstruments_create_mixer(mixer, | 1789 | err = snd_nativeinstruments_create_mixer(mixer, |
1666 | snd_nativeinstruments_ta6_mixers, | 1790 | snd_nativeinstruments_ta6_mixers, |
@@ -1677,6 +1801,14 @@ int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer) | |||
1677 | /* detection is disabled in mixer_maps.c */ | 1801 | /* detection is disabled in mixer_maps.c */ |
1678 | err = snd_create_std_mono_table(mixer, ebox44_table); | 1802 | err = snd_create_std_mono_table(mixer, ebox44_table); |
1679 | break; | 1803 | break; |
1804 | |||
1805 | case USB_ID(0x1235, 0x8012): /* Focusrite Scarlett 6i6 */ | ||
1806 | case USB_ID(0x1235, 0x8002): /* Focusrite Scarlett 8i6 */ | ||
1807 | case USB_ID(0x1235, 0x8004): /* Focusrite Scarlett 18i6 */ | ||
1808 | case USB_ID(0x1235, 0x8014): /* Focusrite Scarlett 18i8 */ | ||
1809 | case USB_ID(0x1235, 0x800c): /* Focusrite Scarlett 18i20 */ | ||
1810 | err = snd_scarlett_controls_create(mixer); | ||
1811 | break; | ||
1680 | } | 1812 | } |
1681 | 1813 | ||
1682 | return err; | 1814 | return err; |
diff --git a/sound/usb/mixer_scarlett.c b/sound/usb/mixer_scarlett.c new file mode 100644 index 000000000000..9109652b88b9 --- /dev/null +++ b/sound/usb/mixer_scarlett.c | |||
@@ -0,0 +1,1004 @@ | |||
1 | /* | ||
2 | * Scarlett Driver for ALSA | ||
3 | * | ||
4 | * Copyright (c) 2013 by Tobias Hoffmann | ||
5 | * Copyright (c) 2013 by Robin Gareus <robin at gareus.org> | ||
6 | * Copyright (c) 2002 by Takashi Iwai <tiwai at suse.de> | ||
7 | * Copyright (c) 2014 by Chris J Arges <chris.j.arges at canonical.com> | ||
8 | * | ||
9 | * Many codes borrowed from audio.c by | ||
10 | * Alan Cox (alan at lxorguk.ukuu.org.uk) | ||
11 | * Thomas Sailer (sailer at ife.ee.ethz.ch) | ||
12 | * | ||
13 | * Code cleanup: | ||
14 | * David Henningsson <david.henningsson at canonical.com> | ||
15 | * | ||
16 | * This program is free software; you can redistribute it and/or modify | ||
17 | * it under the terms of the GNU General Public License as published by | ||
18 | * the Free Software Foundation; either version 2 of the License, or | ||
19 | * (at your option) any later version. | ||
20 | * | ||
21 | * This program is distributed in the hope that it will be useful, | ||
22 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
23 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
24 | * GNU General Public License for more details. | ||
25 | * | ||
26 | */ | ||
27 | |||
28 | /* | ||
29 | * Rewritten and extended to support more models, e.g. Scarlett 18i8. | ||
30 | * | ||
31 | * Auto-detection via UAC2 is not feasible to properly discover the vast | ||
32 | * majority of features. It's related to both Linux/ALSA's UAC2 as well as | ||
33 | * Focusrite's implementation of it. Eventually quirks may be sufficient but | ||
34 | * right now it's a major headache to work arount these things. | ||
35 | * | ||
36 | * NB. Neither the OSX nor the win driver provided by Focusrite performs | ||
37 | * discovery, they seem to operate the same as this driver. | ||
38 | */ | ||
39 | |||
40 | /* Mixer Interface for the Focusrite Scarlett 18i6 audio interface. | ||
41 | * | ||
42 | * The protocol was reverse engineered by looking at communication between | ||
43 | * Scarlett MixControl (v 1.2.128.0) and the Focusrite(R) Scarlett 18i6 | ||
44 | * (firmware v305) using wireshark and usbmon in January 2013. | ||
45 | * Extended in July 2013. | ||
46 | * | ||
47 | * this mixer gives complete access to all features of the device: | ||
48 | * - change Impedance of inputs (Line-in, Mic / Instrument, Hi-Z) | ||
49 | * - select clock source | ||
50 | * - dynamic input to mixer-matrix assignment | ||
51 | * - 18 x 6 mixer-matrix gain stages | ||
52 | * - bus routing & volume control | ||
53 | * - automatic re-initialization on connect if device was power-cycled | ||
54 | * | ||
55 | * USB URB commands overview (bRequest = 0x01 = UAC2_CS_CUR) | ||
56 | * wIndex | ||
57 | * 0x01 Analog Input line/instrument impedance switch, wValue=0x0901 + | ||
58 | * channel, data=Line/Inst (2bytes) | ||
59 | * pad (-10dB) switch, wValue=0x0b01 + channel, data=Off/On (2bytes) | ||
60 | * ?? wValue=0x0803/04, ?? (2bytes) | ||
61 | * 0x0a Master Volume, wValue=0x0200+bus[0:all + only 1..4?] data(2bytes) | ||
62 | * Bus Mute/Unmute wValue=0x0100+bus[0:all + only 1..4?], data(2bytes) | ||
63 | * 0x28 Clock source, wValue=0x0100, data={1:int,2:spdif,3:adat} (1byte) | ||
64 | * 0x29 Set Sample-rate, wValue=0x0100, data=sample-rate(4bytes) | ||
65 | * 0x32 Mixer mux, wValue=0x0600 + mixer-channel, data=input-to-connect(2bytes) | ||
66 | * 0x33 Output mux, wValue=bus, data=input-to-connect(2bytes) | ||
67 | * 0x34 Capture mux, wValue=0...18, data=input-to-connect(2bytes) | ||
68 | * 0x3c Matrix Mixer gains, wValue=mixer-node data=gain(2bytes) | ||
69 | * ?? [sometimes](4bytes, e.g 0x000003be 0x000003bf ...03ff) | ||
70 | * | ||
71 | * USB reads: (i.e. actually issued by original software) | ||
72 | * 0x01 wValue=0x0901+channel (1byte!!), wValue=0x0b01+channed (1byte!!) | ||
73 | * 0x29 wValue=0x0100 sample-rate(4bytes) | ||
74 | * wValue=0x0200 ?? 1byte (only once) | ||
75 | * 0x2a wValue=0x0100 ?? 4bytes, sample-rate2 ?? | ||
76 | * | ||
77 | * USB reads with bRequest = 0x03 = UAC2_CS_MEM | ||
78 | * 0x3c wValue=0x0002 1byte: sync status (locked=1) | ||
79 | * wValue=0x0000 18*2byte: peak meter (inputs) | ||
80 | * wValue=0x0001 8(?)*2byte: peak meter (mix) | ||
81 | * wValue=0x0003 6*2byte: peak meter (pcm/daw) | ||
82 | * | ||
83 | * USB write with bRequest = 0x03 | ||
84 | * 0x3c Save settings to hardware: wValue=0x005a, data=0xa5 | ||
85 | * | ||
86 | * | ||
87 | * <ditaa> | ||
88 | * /--------------\ 18chn 6chn /--------------\ | ||
89 | * | Hardware in +--+-------\ /------+--+ ALSA PCM out | | ||
90 | * \--------------/ | | | | \--------------/ | ||
91 | * | | | | | ||
92 | * | v v | | ||
93 | * | +---------------+ | | ||
94 | * | \ Matrix Mux / | | ||
95 | * | +-----+-----+ | | ||
96 | * | | | | ||
97 | * | | 18chn | | ||
98 | * | v | | ||
99 | * | +-----------+ | | ||
100 | * | | Mixer | | | ||
101 | * | | Matrix | | | ||
102 | * | | | | | ||
103 | * | | 18x6 Gain | | | ||
104 | * | | stages | | | ||
105 | * | +-----+-----+ | | ||
106 | * | | | | ||
107 | * | | | | ||
108 | * | 18chn | 6chn | 6chn | ||
109 | * v v v | ||
110 | * ========================= | ||
111 | * +---------------+ +--—------------+ | ||
112 | * \ Output Mux / \ Capture Mux / | ||
113 | * +-----+-----+ +-----+-----+ | ||
114 | * | | | ||
115 | * | 6chn | | ||
116 | * v | | ||
117 | * +-------------+ | | ||
118 | * | Master Gain | | | ||
119 | * +------+------+ | | ||
120 | * | | | ||
121 | * | 6chn | 18chn | ||
122 | * | (3 stereo pairs) | | ||
123 | * /--------------\ | | /--------------\ | ||
124 | * | Hardware out |<--/ \-->| ALSA PCM in | | ||
125 | * \--------------/ \--------------/ | ||
126 | * </ditaa> | ||
127 | * | ||
128 | */ | ||
129 | |||
130 | #include <linux/slab.h> | ||
131 | #include <linux/usb.h> | ||
132 | #include <linux/usb/audio-v2.h> | ||
133 | |||
134 | #include <sound/core.h> | ||
135 | #include <sound/control.h> | ||
136 | #include <sound/tlv.h> | ||
137 | |||
138 | #include "usbaudio.h" | ||
139 | #include "mixer.h" | ||
140 | #include "helper.h" | ||
141 | #include "power.h" | ||
142 | |||
143 | #include "mixer_scarlett.h" | ||
144 | |||
145 | /* some gui mixers can't handle negative ctl values */ | ||
146 | #define SND_SCARLETT_LEVEL_BIAS 128 | ||
147 | #define SND_SCARLETT_MATRIX_IN_MAX 18 | ||
148 | #define SND_SCARLETT_CONTROLS_MAX 10 | ||
149 | #define SND_SCARLETT_OFFSETS_MAX 5 | ||
150 | |||
151 | enum { | ||
152 | SCARLETT_OUTPUTS, | ||
153 | SCARLETT_SWITCH_IMPEDANCE, | ||
154 | SCARLETT_SWITCH_PAD, | ||
155 | }; | ||
156 | |||
157 | enum { | ||
158 | SCARLETT_OFFSET_PCM = 0, | ||
159 | SCARLETT_OFFSET_ANALOG = 1, | ||
160 | SCARLETT_OFFSET_SPDIF = 2, | ||
161 | SCARLETT_OFFSET_ADAT = 3, | ||
162 | SCARLETT_OFFSET_MIX = 4, | ||
163 | }; | ||
164 | |||
165 | struct scarlett_mixer_elem_enum_info { | ||
166 | int start; | ||
167 | int len; | ||
168 | int offsets[SND_SCARLETT_OFFSETS_MAX]; | ||
169 | char const * const *names; | ||
170 | }; | ||
171 | |||
172 | struct scarlett_mixer_control { | ||
173 | unsigned char num; | ||
174 | unsigned char type; | ||
175 | const char *name; | ||
176 | }; | ||
177 | |||
178 | struct scarlett_device_info { | ||
179 | int matrix_in; | ||
180 | int matrix_out; | ||
181 | int input_len; | ||
182 | int output_len; | ||
183 | |||
184 | struct scarlett_mixer_elem_enum_info opt_master; | ||
185 | struct scarlett_mixer_elem_enum_info opt_matrix; | ||
186 | |||
187 | /* initial values for matrix mux */ | ||
188 | int matrix_mux_init[SND_SCARLETT_MATRIX_IN_MAX]; | ||
189 | |||
190 | int num_controls; /* number of items in controls */ | ||
191 | const struct scarlett_mixer_control controls[SND_SCARLETT_CONTROLS_MAX]; | ||
192 | }; | ||
193 | |||
194 | /********************** Enum Strings *************************/ | ||
195 | |||
196 | static const struct scarlett_mixer_elem_enum_info opt_pad = { | ||
197 | .start = 0, | ||
198 | .len = 2, | ||
199 | .offsets = {}, | ||
200 | .names = (char const * const []){ | ||
201 | "0dB", "-10dB" | ||
202 | } | ||
203 | }; | ||
204 | |||
205 | static const struct scarlett_mixer_elem_enum_info opt_impedance = { | ||
206 | .start = 0, | ||
207 | .len = 2, | ||
208 | .offsets = {}, | ||
209 | .names = (char const * const []){ | ||
210 | "Line", "Hi-Z" | ||
211 | } | ||
212 | }; | ||
213 | |||
214 | static const struct scarlett_mixer_elem_enum_info opt_clock = { | ||
215 | .start = 1, | ||
216 | .len = 3, | ||
217 | .offsets = {}, | ||
218 | .names = (char const * const []){ | ||
219 | "Internal", "SPDIF", "ADAT" | ||
220 | } | ||
221 | }; | ||
222 | |||
223 | static const struct scarlett_mixer_elem_enum_info opt_sync = { | ||
224 | .start = 0, | ||
225 | .len = 2, | ||
226 | .offsets = {}, | ||
227 | .names = (char const * const []){ | ||
228 | "No Lock", "Locked" | ||
229 | } | ||
230 | }; | ||
231 | |||
232 | static int scarlett_ctl_switch_info(struct snd_kcontrol *kctl, | ||
233 | struct snd_ctl_elem_info *uinfo) | ||
234 | { | ||
235 | struct usb_mixer_elem_info *elem = kctl->private_data; | ||
236 | |||
237 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
238 | uinfo->count = elem->channels; | ||
239 | uinfo->value.integer.min = 0; | ||
240 | uinfo->value.integer.max = 1; | ||
241 | return 0; | ||
242 | } | ||
243 | |||
244 | static int scarlett_ctl_switch_get(struct snd_kcontrol *kctl, | ||
245 | struct snd_ctl_elem_value *ucontrol) | ||
246 | { | ||
247 | struct usb_mixer_elem_info *elem = kctl->private_data; | ||
248 | int i, err, val; | ||
249 | |||
250 | for (i = 0; i < elem->channels; i++) { | ||
251 | err = snd_usb_get_cur_mix_value(elem, i, i, &val); | ||
252 | if (err < 0) | ||
253 | return err; | ||
254 | |||
255 | val = !val; /* invert mute logic for mixer */ | ||
256 | ucontrol->value.integer.value[i] = val; | ||
257 | } | ||
258 | |||
259 | return 0; | ||
260 | } | ||
261 | |||
262 | static int scarlett_ctl_switch_put(struct snd_kcontrol *kctl, | ||
263 | struct snd_ctl_elem_value *ucontrol) | ||
264 | { | ||
265 | struct usb_mixer_elem_info *elem = kctl->private_data; | ||
266 | int i, changed = 0; | ||
267 | int err, oval, val; | ||
268 | |||
269 | for (i = 0; i < elem->channels; i++) { | ||
270 | err = snd_usb_get_cur_mix_value(elem, i, i, &oval); | ||
271 | if (err < 0) | ||
272 | return err; | ||
273 | |||
274 | val = ucontrol->value.integer.value[i]; | ||
275 | val = !val; | ||
276 | if (oval != val) { | ||
277 | err = snd_usb_set_cur_mix_value(elem, i, i, val); | ||
278 | if (err < 0) | ||
279 | return err; | ||
280 | |||
281 | changed = 1; | ||
282 | } | ||
283 | } | ||
284 | |||
285 | return changed; | ||
286 | } | ||
287 | |||
288 | static int scarlett_ctl_resume(struct usb_mixer_elem_list *list) | ||
289 | { | ||
290 | struct usb_mixer_elem_info *elem = | ||
291 | container_of(list, struct usb_mixer_elem_info, head); | ||
292 | int i; | ||
293 | |||
294 | for (i = 0; i < elem->channels; i++) | ||
295 | if (elem->cached & (1 << i)) | ||
296 | snd_usb_set_cur_mix_value(elem, i, i, | ||
297 | elem->cache_val[i]); | ||
298 | return 0; | ||
299 | } | ||
300 | |||
301 | static int scarlett_ctl_info(struct snd_kcontrol *kctl, | ||
302 | struct snd_ctl_elem_info *uinfo) | ||
303 | { | ||
304 | struct usb_mixer_elem_info *elem = kctl->private_data; | ||
305 | |||
306 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | ||
307 | uinfo->count = elem->channels; | ||
308 | uinfo->value.integer.min = 0; | ||
309 | uinfo->value.integer.max = (int)kctl->private_value + | ||
310 | SND_SCARLETT_LEVEL_BIAS; | ||
311 | uinfo->value.integer.step = 1; | ||
312 | return 0; | ||
313 | } | ||
314 | |||
315 | static int scarlett_ctl_get(struct snd_kcontrol *kctl, | ||
316 | struct snd_ctl_elem_value *ucontrol) | ||
317 | { | ||
318 | struct usb_mixer_elem_info *elem = kctl->private_data; | ||
319 | int i, err, val; | ||
320 | |||
321 | for (i = 0; i < elem->channels; i++) { | ||
322 | err = snd_usb_get_cur_mix_value(elem, i, i, &val); | ||
323 | if (err < 0) | ||
324 | return err; | ||
325 | |||
326 | val = clamp(val / 256, -128, (int)kctl->private_value) + | ||
327 | SND_SCARLETT_LEVEL_BIAS; | ||
328 | ucontrol->value.integer.value[i] = val; | ||
329 | } | ||
330 | |||
331 | return 0; | ||
332 | } | ||
333 | |||
334 | static int scarlett_ctl_put(struct snd_kcontrol *kctl, | ||
335 | struct snd_ctl_elem_value *ucontrol) | ||
336 | { | ||
337 | struct usb_mixer_elem_info *elem = kctl->private_data; | ||
338 | int i, changed = 0; | ||
339 | int err, oval, val; | ||
340 | |||
341 | for (i = 0; i < elem->channels; i++) { | ||
342 | err = snd_usb_get_cur_mix_value(elem, i, i, &oval); | ||
343 | if (err < 0) | ||
344 | return err; | ||
345 | |||
346 | val = ucontrol->value.integer.value[i] - | ||
347 | SND_SCARLETT_LEVEL_BIAS; | ||
348 | val = val * 256; | ||
349 | if (oval != val) { | ||
350 | err = snd_usb_set_cur_mix_value(elem, i, i, val); | ||
351 | if (err < 0) | ||
352 | return err; | ||
353 | |||
354 | changed = 1; | ||
355 | } | ||
356 | } | ||
357 | |||
358 | return changed; | ||
359 | } | ||
360 | |||
361 | static void scarlett_generate_name(int i, char *dst, int offsets[]) | ||
362 | { | ||
363 | if (i > offsets[SCARLETT_OFFSET_MIX]) | ||
364 | sprintf(dst, "Mix %c", | ||
365 | 'A'+(i - offsets[SCARLETT_OFFSET_MIX] - 1)); | ||
366 | else if (i > offsets[SCARLETT_OFFSET_ADAT]) | ||
367 | sprintf(dst, "ADAT %d", i - offsets[SCARLETT_OFFSET_ADAT]); | ||
368 | else if (i > offsets[SCARLETT_OFFSET_SPDIF]) | ||
369 | sprintf(dst, "SPDIF %d", i - offsets[SCARLETT_OFFSET_SPDIF]); | ||
370 | else if (i > offsets[SCARLETT_OFFSET_ANALOG]) | ||
371 | sprintf(dst, "Analog %d", i - offsets[SCARLETT_OFFSET_ANALOG]); | ||
372 | else if (i > offsets[SCARLETT_OFFSET_PCM]) | ||
373 | sprintf(dst, "PCM %d", i - offsets[SCARLETT_OFFSET_PCM]); | ||
374 | else | ||
375 | sprintf(dst, "Off"); | ||
376 | } | ||
377 | |||
378 | static int scarlett_ctl_enum_dynamic_info(struct snd_kcontrol *kctl, | ||
379 | struct snd_ctl_elem_info *uinfo) | ||
380 | { | ||
381 | struct usb_mixer_elem_info *elem = kctl->private_data; | ||
382 | struct scarlett_mixer_elem_enum_info *opt = elem->private_data; | ||
383 | unsigned int items = opt->len; | ||
384 | |||
385 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | ||
386 | uinfo->count = elem->channels; | ||
387 | uinfo->value.enumerated.items = items; | ||
388 | |||
389 | if (uinfo->value.enumerated.item >= items) | ||
390 | uinfo->value.enumerated.item = items - 1; | ||
391 | |||
392 | /* generate name dynamically based on item number and offset info */ | ||
393 | scarlett_generate_name(uinfo->value.enumerated.item, | ||
394 | uinfo->value.enumerated.name, | ||
395 | opt->offsets); | ||
396 | |||
397 | return 0; | ||
398 | } | ||
399 | |||
400 | static int scarlett_ctl_enum_info(struct snd_kcontrol *kctl, | ||
401 | struct snd_ctl_elem_info *uinfo) | ||
402 | { | ||
403 | struct usb_mixer_elem_info *elem = kctl->private_data; | ||
404 | struct scarlett_mixer_elem_enum_info *opt = elem->private_data; | ||
405 | |||
406 | return snd_ctl_enum_info(uinfo, elem->channels, opt->len, | ||
407 | (const char * const *)opt->names); | ||
408 | } | ||
409 | |||
410 | static int scarlett_ctl_enum_get(struct snd_kcontrol *kctl, | ||
411 | struct snd_ctl_elem_value *ucontrol) | ||
412 | { | ||
413 | struct usb_mixer_elem_info *elem = kctl->private_data; | ||
414 | struct scarlett_mixer_elem_enum_info *opt = elem->private_data; | ||
415 | int err, val; | ||
416 | |||
417 | err = snd_usb_get_cur_mix_value(elem, 0, 0, &val); | ||
418 | if (err < 0) | ||
419 | return err; | ||
420 | |||
421 | val = clamp(val - opt->start, 0, opt->len-1); | ||
422 | |||
423 | ucontrol->value.enumerated.item[0] = val; | ||
424 | |||
425 | return 0; | ||
426 | } | ||
427 | |||
428 | static int scarlett_ctl_enum_put(struct snd_kcontrol *kctl, | ||
429 | struct snd_ctl_elem_value *ucontrol) | ||
430 | { | ||
431 | struct usb_mixer_elem_info *elem = kctl->private_data; | ||
432 | struct scarlett_mixer_elem_enum_info *opt = elem->private_data; | ||
433 | int err, oval, val; | ||
434 | |||
435 | err = snd_usb_get_cur_mix_value(elem, 0, 0, &oval); | ||
436 | if (err < 0) | ||
437 | return err; | ||
438 | |||
439 | val = ucontrol->value.integer.value[0]; | ||
440 | val = val + opt->start; | ||
441 | if (val != oval) { | ||
442 | snd_usb_set_cur_mix_value(elem, 0, 0, val); | ||
443 | return 1; | ||
444 | } | ||
445 | return 0; | ||
446 | } | ||
447 | |||
448 | static int scarlett_ctl_enum_resume(struct usb_mixer_elem_list *list) | ||
449 | { | ||
450 | struct usb_mixer_elem_info *elem = | ||
451 | container_of(list, struct usb_mixer_elem_info, head); | ||
452 | |||
453 | if (elem->cached) | ||
454 | snd_usb_set_cur_mix_value(elem, 0, 0, *elem->cache_val); | ||
455 | return 0; | ||
456 | } | ||
457 | |||
458 | static int scarlett_ctl_meter_get(struct snd_kcontrol *kctl, | ||
459 | struct snd_ctl_elem_value *ucontrol) | ||
460 | { | ||
461 | struct usb_mixer_elem_info *elem = kctl->private_data; | ||
462 | struct snd_usb_audio *chip = elem->head.mixer->chip; | ||
463 | unsigned char buf[2 * MAX_CHANNELS] = {0, }; | ||
464 | int wValue = (elem->control << 8) | elem->idx_off; | ||
465 | int idx = snd_usb_ctrl_intf(chip) | (elem->head.id << 8); | ||
466 | int err; | ||
467 | |||
468 | err = snd_usb_ctl_msg(chip->dev, | ||
469 | usb_rcvctrlpipe(chip->dev, 0), | ||
470 | UAC2_CS_MEM, | ||
471 | USB_RECIP_INTERFACE | USB_TYPE_CLASS | | ||
472 | USB_DIR_IN, wValue, idx, buf, elem->channels); | ||
473 | if (err < 0) | ||
474 | return err; | ||
475 | |||
476 | ucontrol->value.enumerated.item[0] = clamp((int)buf[0], 0, 1); | ||
477 | return 0; | ||
478 | } | ||
479 | |||
480 | static struct snd_kcontrol_new usb_scarlett_ctl_switch = { | ||
481 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
482 | .name = "", | ||
483 | .info = scarlett_ctl_switch_info, | ||
484 | .get = scarlett_ctl_switch_get, | ||
485 | .put = scarlett_ctl_switch_put, | ||
486 | }; | ||
487 | |||
488 | static const DECLARE_TLV_DB_SCALE(db_scale_scarlett_gain, -12800, 100, 0); | ||
489 | |||
490 | static struct snd_kcontrol_new usb_scarlett_ctl = { | ||
491 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
492 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | | ||
493 | SNDRV_CTL_ELEM_ACCESS_TLV_READ, | ||
494 | .name = "", | ||
495 | .info = scarlett_ctl_info, | ||
496 | .get = scarlett_ctl_get, | ||
497 | .put = scarlett_ctl_put, | ||
498 | .private_value = 6, /* max value */ | ||
499 | .tlv = { .p = db_scale_scarlett_gain } | ||
500 | }; | ||
501 | |||
502 | static struct snd_kcontrol_new usb_scarlett_ctl_master = { | ||
503 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
504 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | | ||
505 | SNDRV_CTL_ELEM_ACCESS_TLV_READ, | ||
506 | .name = "", | ||
507 | .info = scarlett_ctl_info, | ||
508 | .get = scarlett_ctl_get, | ||
509 | .put = scarlett_ctl_put, | ||
510 | .private_value = 6, /* max value */ | ||
511 | .tlv = { .p = db_scale_scarlett_gain } | ||
512 | }; | ||
513 | |||
514 | static struct snd_kcontrol_new usb_scarlett_ctl_enum = { | ||
515 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
516 | .name = "", | ||
517 | .info = scarlett_ctl_enum_info, | ||
518 | .get = scarlett_ctl_enum_get, | ||
519 | .put = scarlett_ctl_enum_put, | ||
520 | }; | ||
521 | |||
522 | static struct snd_kcontrol_new usb_scarlett_ctl_dynamic_enum = { | ||
523 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
524 | .name = "", | ||
525 | .info = scarlett_ctl_enum_dynamic_info, | ||
526 | .get = scarlett_ctl_enum_get, | ||
527 | .put = scarlett_ctl_enum_put, | ||
528 | }; | ||
529 | |||
530 | static struct snd_kcontrol_new usb_scarlett_ctl_sync = { | ||
531 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
532 | .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, | ||
533 | .name = "", | ||
534 | .info = scarlett_ctl_enum_info, | ||
535 | .get = scarlett_ctl_meter_get, | ||
536 | }; | ||
537 | |||
538 | static int add_new_ctl(struct usb_mixer_interface *mixer, | ||
539 | const struct snd_kcontrol_new *ncontrol, | ||
540 | usb_mixer_elem_resume_func_t resume, | ||
541 | int index, int offset, int num, | ||
542 | int val_type, int channels, const char *name, | ||
543 | const struct scarlett_mixer_elem_enum_info *opt, | ||
544 | struct usb_mixer_elem_info **elem_ret | ||
545 | ) | ||
546 | { | ||
547 | struct snd_kcontrol *kctl; | ||
548 | struct usb_mixer_elem_info *elem; | ||
549 | int err; | ||
550 | |||
551 | elem = kzalloc(sizeof(*elem), GFP_KERNEL); | ||
552 | if (!elem) | ||
553 | return -ENOMEM; | ||
554 | |||
555 | elem->head.mixer = mixer; | ||
556 | elem->head.resume = resume; | ||
557 | elem->control = offset; | ||
558 | elem->idx_off = num; | ||
559 | elem->head.id = index; | ||
560 | elem->val_type = val_type; | ||
561 | |||
562 | elem->channels = channels; | ||
563 | |||
564 | /* add scarlett_mixer_elem_enum_info struct */ | ||
565 | elem->private_data = (void *)opt; | ||
566 | |||
567 | kctl = snd_ctl_new1(ncontrol, elem); | ||
568 | if (!kctl) { | ||
569 | kfree(elem); | ||
570 | return -ENOMEM; | ||
571 | } | ||
572 | kctl->private_free = snd_usb_mixer_elem_free; | ||
573 | |||
574 | strlcpy(kctl->id.name, name, sizeof(kctl->id.name)); | ||
575 | |||
576 | err = snd_usb_mixer_add_control(&elem->head, kctl); | ||
577 | if (err < 0) | ||
578 | return err; | ||
579 | |||
580 | if (elem_ret) | ||
581 | *elem_ret = elem; | ||
582 | |||
583 | return 0; | ||
584 | } | ||
585 | |||
586 | static int add_output_ctls(struct usb_mixer_interface *mixer, | ||
587 | int index, const char *name, | ||
588 | const struct scarlett_device_info *info) | ||
589 | { | ||
590 | int err; | ||
591 | char mx[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; | ||
592 | struct usb_mixer_elem_info *elem; | ||
593 | |||
594 | /* Add mute switch */ | ||
595 | snprintf(mx, sizeof(mx), "Master %d (%s) Playback Switch", | ||
596 | index + 1, name); | ||
597 | err = add_new_ctl(mixer, &usb_scarlett_ctl_switch, | ||
598 | scarlett_ctl_resume, 0x0a, 0x01, | ||
599 | 2*index+1, USB_MIXER_S16, 2, mx, NULL, &elem); | ||
600 | if (err < 0) | ||
601 | return err; | ||
602 | |||
603 | /* Add volume control and initialize to 0 */ | ||
604 | snprintf(mx, sizeof(mx), "Master %d (%s) Playback Volume", | ||
605 | index + 1, name); | ||
606 | err = add_new_ctl(mixer, &usb_scarlett_ctl_master, | ||
607 | scarlett_ctl_resume, 0x0a, 0x02, | ||
608 | 2*index+1, USB_MIXER_S16, 2, mx, NULL, &elem); | ||
609 | if (err < 0) | ||
610 | return err; | ||
611 | |||
612 | /* Add L channel source playback enumeration */ | ||
613 | snprintf(mx, sizeof(mx), "Master %dL (%s) Source Playback Enum", | ||
614 | index + 1, name); | ||
615 | err = add_new_ctl(mixer, &usb_scarlett_ctl_dynamic_enum, | ||
616 | scarlett_ctl_enum_resume, 0x33, 0x00, | ||
617 | 2*index, USB_MIXER_S16, 1, mx, &info->opt_master, | ||
618 | &elem); | ||
619 | if (err < 0) | ||
620 | return err; | ||
621 | |||
622 | /* Add R channel source playback enumeration */ | ||
623 | snprintf(mx, sizeof(mx), "Master %dR (%s) Source Playback Enum", | ||
624 | index + 1, name); | ||
625 | err = add_new_ctl(mixer, &usb_scarlett_ctl_dynamic_enum, | ||
626 | scarlett_ctl_enum_resume, 0x33, 0x00, | ||
627 | 2*index+1, USB_MIXER_S16, 1, mx, &info->opt_master, | ||
628 | &elem); | ||
629 | if (err < 0) | ||
630 | return err; | ||
631 | |||
632 | return 0; | ||
633 | } | ||
634 | |||
635 | /********************** device-specific config *************************/ | ||
636 | |||
637 | /* untested... */ | ||
638 | static struct scarlett_device_info s6i6_info = { | ||
639 | .matrix_in = 18, | ||
640 | .matrix_out = 8, | ||
641 | .input_len = 6, | ||
642 | .output_len = 6, | ||
643 | |||
644 | .opt_master = { | ||
645 | .start = -1, | ||
646 | .len = 27, | ||
647 | .offsets = {0, 12, 16, 18, 18}, | ||
648 | .names = NULL | ||
649 | }, | ||
650 | |||
651 | .opt_matrix = { | ||
652 | .start = -1, | ||
653 | .len = 19, | ||
654 | .offsets = {0, 12, 16, 18, 18}, | ||
655 | .names = NULL | ||
656 | }, | ||
657 | |||
658 | .num_controls = 0, | ||
659 | .controls = { | ||
660 | { .num = 0, .type = SCARLETT_OUTPUTS, .name = "Monitor" }, | ||
661 | { .num = 1, .type = SCARLETT_OUTPUTS, .name = "Headphone" }, | ||
662 | { .num = 2, .type = SCARLETT_OUTPUTS, .name = "SPDIF" }, | ||
663 | { .num = 1, .type = SCARLETT_SWITCH_IMPEDANCE, .name = NULL}, | ||
664 | { .num = 1, .type = SCARLETT_SWITCH_PAD, .name = NULL}, | ||
665 | { .num = 2, .type = SCARLETT_SWITCH_IMPEDANCE, .name = NULL}, | ||
666 | { .num = 2, .type = SCARLETT_SWITCH_PAD, .name = NULL}, | ||
667 | { .num = 3, .type = SCARLETT_SWITCH_PAD, .name = NULL}, | ||
668 | { .num = 4, .type = SCARLETT_SWITCH_PAD, .name = NULL}, | ||
669 | }, | ||
670 | |||
671 | .matrix_mux_init = { | ||
672 | 12, 13, 14, 15, /* Analog -> 1..4 */ | ||
673 | 16, 17, /* SPDIF -> 5,6 */ | ||
674 | 0, 1, 2, 3, 4, 5, 6, 7, /* PCM[1..12] -> 7..18 */ | ||
675 | 8, 9, 10, 11 | ||
676 | } | ||
677 | }; | ||
678 | |||
679 | /* untested... */ | ||
680 | static struct scarlett_device_info s8i6_info = { | ||
681 | .matrix_in = 18, | ||
682 | .matrix_out = 6, | ||
683 | .input_len = 8, | ||
684 | .output_len = 6, | ||
685 | |||
686 | .opt_master = { | ||
687 | .start = -1, | ||
688 | .len = 25, | ||
689 | .offsets = {0, 12, 16, 18, 18}, | ||
690 | .names = NULL | ||
691 | }, | ||
692 | |||
693 | .opt_matrix = { | ||
694 | .start = -1, | ||
695 | .len = 19, | ||
696 | .offsets = {0, 12, 16, 18, 18}, | ||
697 | .names = NULL | ||
698 | }, | ||
699 | |||
700 | .num_controls = 7, | ||
701 | .controls = { | ||
702 | { .num = 0, .type = SCARLETT_OUTPUTS, .name = "Monitor" }, | ||
703 | { .num = 1, .type = SCARLETT_OUTPUTS, .name = "Headphone" }, | ||
704 | { .num = 2, .type = SCARLETT_OUTPUTS, .name = "SPDIF" }, | ||
705 | { .num = 1, .type = SCARLETT_SWITCH_IMPEDANCE, .name = NULL}, | ||
706 | { .num = 2, .type = SCARLETT_SWITCH_IMPEDANCE, .name = NULL}, | ||
707 | { .num = 3, .type = SCARLETT_SWITCH_PAD, .name = NULL}, | ||
708 | { .num = 4, .type = SCARLETT_SWITCH_PAD, .name = NULL}, | ||
709 | }, | ||
710 | |||
711 | .matrix_mux_init = { | ||
712 | 12, 13, 14, 15, /* Analog -> 1..4 */ | ||
713 | 16, 17, /* SPDIF -> 5,6 */ | ||
714 | 0, 1, 2, 3, 4, 5, 6, 7, /* PCM[1..12] -> 7..18 */ | ||
715 | 8, 9, 10, 11 | ||
716 | } | ||
717 | }; | ||
718 | |||
719 | static struct scarlett_device_info s18i6_info = { | ||
720 | .matrix_in = 18, | ||
721 | .matrix_out = 6, | ||
722 | .input_len = 18, | ||
723 | .output_len = 6, | ||
724 | |||
725 | .opt_master = { | ||
726 | .start = -1, | ||
727 | .len = 31, | ||
728 | .offsets = {0, 6, 14, 16, 24}, | ||
729 | .names = NULL, | ||
730 | }, | ||
731 | |||
732 | .opt_matrix = { | ||
733 | .start = -1, | ||
734 | .len = 25, | ||
735 | .offsets = {0, 6, 14, 16, 24}, | ||
736 | .names = NULL, | ||
737 | }, | ||
738 | |||
739 | .num_controls = 5, | ||
740 | .controls = { | ||
741 | { .num = 0, .type = SCARLETT_OUTPUTS, .name = "Monitor" }, | ||
742 | { .num = 1, .type = SCARLETT_OUTPUTS, .name = "Headphone" }, | ||
743 | { .num = 2, .type = SCARLETT_OUTPUTS, .name = "SPDIF" }, | ||
744 | { .num = 1, .type = SCARLETT_SWITCH_IMPEDANCE, .name = NULL}, | ||
745 | { .num = 2, .type = SCARLETT_SWITCH_IMPEDANCE, .name = NULL}, | ||
746 | }, | ||
747 | |||
748 | .matrix_mux_init = { | ||
749 | 6, 7, 8, 9, 10, 11, 12, 13, /* Analog -> 1..8 */ | ||
750 | 16, 17, 18, 19, 20, 21, /* ADAT[1..6] -> 9..14 */ | ||
751 | 14, 15, /* SPDIF -> 15,16 */ | ||
752 | 0, 1 /* PCM[1,2] -> 17,18 */ | ||
753 | } | ||
754 | }; | ||
755 | |||
756 | static struct scarlett_device_info s18i8_info = { | ||
757 | .matrix_in = 18, | ||
758 | .matrix_out = 8, | ||
759 | .input_len = 18, | ||
760 | .output_len = 8, | ||
761 | |||
762 | .opt_master = { | ||
763 | .start = -1, | ||
764 | .len = 35, | ||
765 | .offsets = {0, 8, 16, 18, 26}, | ||
766 | .names = NULL | ||
767 | }, | ||
768 | |||
769 | .opt_matrix = { | ||
770 | .start = -1, | ||
771 | .len = 27, | ||
772 | .offsets = {0, 8, 16, 18, 26}, | ||
773 | .names = NULL | ||
774 | }, | ||
775 | |||
776 | .num_controls = 10, | ||
777 | .controls = { | ||
778 | { .num = 0, .type = SCARLETT_OUTPUTS, .name = "Monitor" }, | ||
779 | { .num = 1, .type = SCARLETT_OUTPUTS, .name = "Headphone 1" }, | ||
780 | { .num = 2, .type = SCARLETT_OUTPUTS, .name = "Headphone 2" }, | ||
781 | { .num = 3, .type = SCARLETT_OUTPUTS, .name = "SPDIF" }, | ||
782 | { .num = 1, .type = SCARLETT_SWITCH_IMPEDANCE, .name = NULL}, | ||
783 | { .num = 1, .type = SCARLETT_SWITCH_PAD, .name = NULL}, | ||
784 | { .num = 2, .type = SCARLETT_SWITCH_IMPEDANCE, .name = NULL}, | ||
785 | { .num = 2, .type = SCARLETT_SWITCH_PAD, .name = NULL}, | ||
786 | { .num = 3, .type = SCARLETT_SWITCH_PAD, .name = NULL}, | ||
787 | { .num = 4, .type = SCARLETT_SWITCH_PAD, .name = NULL}, | ||
788 | }, | ||
789 | |||
790 | .matrix_mux_init = { | ||
791 | 8, 9, 10, 11, 12, 13, 14, 15, /* Analog -> 1..8 */ | ||
792 | 18, 19, 20, 21, 22, 23, /* ADAT[1..6] -> 9..14 */ | ||
793 | 16, 17, /* SPDIF -> 15,16 */ | ||
794 | 0, 1 /* PCM[1,2] -> 17,18 */ | ||
795 | } | ||
796 | }; | ||
797 | |||
798 | static struct scarlett_device_info s18i20_info = { | ||
799 | .matrix_in = 18, | ||
800 | .matrix_out = 8, | ||
801 | .input_len = 18, | ||
802 | .output_len = 20, | ||
803 | |||
804 | .opt_master = { | ||
805 | .start = -1, | ||
806 | .len = 47, | ||
807 | .offsets = {0, 20, 28, 30, 38}, | ||
808 | .names = NULL | ||
809 | }, | ||
810 | |||
811 | .opt_matrix = { | ||
812 | .start = -1, | ||
813 | .len = 39, | ||
814 | .offsets = {0, 20, 28, 30, 38}, | ||
815 | .names = NULL | ||
816 | }, | ||
817 | |||
818 | .num_controls = 10, | ||
819 | .controls = { | ||
820 | { .num = 0, .type = SCARLETT_OUTPUTS, .name = "Monitor" }, | ||
821 | { .num = 1, .type = SCARLETT_OUTPUTS, .name = "Line 3/4" }, | ||
822 | { .num = 2, .type = SCARLETT_OUTPUTS, .name = "Line 5/6" }, | ||
823 | { .num = 3, .type = SCARLETT_OUTPUTS, .name = "Line 7/8" }, | ||
824 | { .num = 4, .type = SCARLETT_OUTPUTS, .name = "Line 9/10" }, | ||
825 | { .num = 5, .type = SCARLETT_OUTPUTS, .name = "SPDIF" }, | ||
826 | { .num = 6, .type = SCARLETT_OUTPUTS, .name = "ADAT 1/2" }, | ||
827 | { .num = 7, .type = SCARLETT_OUTPUTS, .name = "ADAT 3/4" }, | ||
828 | { .num = 8, .type = SCARLETT_OUTPUTS, .name = "ADAT 5/6" }, | ||
829 | { .num = 9, .type = SCARLETT_OUTPUTS, .name = "ADAT 7/8" }, | ||
830 | /*{ .num = 1, .type = SCARLETT_SWITCH_IMPEDANCE, .name = NULL}, | ||
831 | { .num = 1, .type = SCARLETT_SWITCH_PAD, .name = NULL}, | ||
832 | { .num = 2, .type = SCARLETT_SWITCH_IMPEDANCE, .name = NULL}, | ||
833 | { .num = 2, .type = SCARLETT_SWITCH_PAD, .name = NULL}, | ||
834 | { .num = 3, .type = SCARLETT_SWITCH_PAD, .name = NULL}, | ||
835 | { .num = 4, .type = SCARLETT_SWITCH_PAD, .name = NULL},*/ | ||
836 | }, | ||
837 | |||
838 | .matrix_mux_init = { | ||
839 | 20, 21, 22, 23, 24, 25, 26, 27, /* Analog -> 1..8 */ | ||
840 | 30, 31, 32, 33, 34, 35, /* ADAT[1..6] -> 9..14 */ | ||
841 | 28, 29, /* SPDIF -> 15,16 */ | ||
842 | 0, 1 /* PCM[1,2] -> 17,18 */ | ||
843 | } | ||
844 | }; | ||
845 | |||
846 | |||
847 | static int scarlett_controls_create_generic(struct usb_mixer_interface *mixer, | ||
848 | struct scarlett_device_info *info) | ||
849 | { | ||
850 | int i, err; | ||
851 | char mx[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; | ||
852 | const struct scarlett_mixer_control *ctl; | ||
853 | struct usb_mixer_elem_info *elem; | ||
854 | |||
855 | /* create master switch and playback volume */ | ||
856 | err = add_new_ctl(mixer, &usb_scarlett_ctl_switch, | ||
857 | scarlett_ctl_resume, 0x0a, 0x01, 0, | ||
858 | USB_MIXER_S16, 1, "Master Playback Switch", NULL, | ||
859 | &elem); | ||
860 | if (err < 0) | ||
861 | return err; | ||
862 | |||
863 | err = add_new_ctl(mixer, &usb_scarlett_ctl_master, | ||
864 | scarlett_ctl_resume, 0x0a, 0x02, 0, | ||
865 | USB_MIXER_S16, 1, "Master Playback Volume", NULL, | ||
866 | &elem); | ||
867 | if (err < 0) | ||
868 | return err; | ||
869 | |||
870 | /* iterate through controls in info struct and create each one */ | ||
871 | for (i = 0; i < info->num_controls; i++) { | ||
872 | ctl = &info->controls[i]; | ||
873 | |||
874 | switch (ctl->type) { | ||
875 | case SCARLETT_OUTPUTS: | ||
876 | err = add_output_ctls(mixer, ctl->num, ctl->name, info); | ||
877 | if (err < 0) | ||
878 | return err; | ||
879 | break; | ||
880 | case SCARLETT_SWITCH_IMPEDANCE: | ||
881 | sprintf(mx, "Input %d Impedance Switch", ctl->num); | ||
882 | err = add_new_ctl(mixer, &usb_scarlett_ctl_enum, | ||
883 | scarlett_ctl_enum_resume, 0x01, | ||
884 | 0x09, ctl->num, USB_MIXER_S16, 1, mx, | ||
885 | &opt_impedance, &elem); | ||
886 | if (err < 0) | ||
887 | return err; | ||
888 | break; | ||
889 | case SCARLETT_SWITCH_PAD: | ||
890 | sprintf(mx, "Input %d Pad Switch", ctl->num); | ||
891 | err = add_new_ctl(mixer, &usb_scarlett_ctl_enum, | ||
892 | scarlett_ctl_enum_resume, 0x01, | ||
893 | 0x0b, ctl->num, USB_MIXER_S16, 1, mx, | ||
894 | &opt_pad, &elem); | ||
895 | if (err < 0) | ||
896 | return err; | ||
897 | break; | ||
898 | } | ||
899 | } | ||
900 | |||
901 | return 0; | ||
902 | } | ||
903 | |||
904 | /* | ||
905 | * Create and initialize a mixer for the Focusrite(R) Scarlett | ||
906 | */ | ||
907 | int snd_scarlett_controls_create(struct usb_mixer_interface *mixer) | ||
908 | { | ||
909 | int err, i, o; | ||
910 | char mx[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; | ||
911 | struct scarlett_device_info *info; | ||
912 | struct usb_mixer_elem_info *elem; | ||
913 | static char sample_rate_buffer[4] = { '\x80', '\xbb', '\x00', '\x00' }; | ||
914 | |||
915 | /* only use UAC_VERSION_2 */ | ||
916 | if (!mixer->protocol) | ||
917 | return 0; | ||
918 | |||
919 | switch (mixer->chip->usb_id) { | ||
920 | case USB_ID(0x1235, 0x8012): | ||
921 | info = &s6i6_info; | ||
922 | break; | ||
923 | case USB_ID(0x1235, 0x8002): | ||
924 | info = &s8i6_info; | ||
925 | break; | ||
926 | case USB_ID(0x1235, 0x8004): | ||
927 | info = &s18i6_info; | ||
928 | break; | ||
929 | case USB_ID(0x1235, 0x8014): | ||
930 | info = &s18i8_info; | ||
931 | break; | ||
932 | case USB_ID(0x1235, 0x800c): | ||
933 | info = &s18i20_info; | ||
934 | break; | ||
935 | default: /* device not (yet) supported */ | ||
936 | return -EINVAL; | ||
937 | } | ||
938 | |||
939 | /* generic function to create controls */ | ||
940 | err = scarlett_controls_create_generic(mixer, info); | ||
941 | if (err < 0) | ||
942 | return err; | ||
943 | |||
944 | /* setup matrix controls */ | ||
945 | for (i = 0; i < info->matrix_in; i++) { | ||
946 | snprintf(mx, sizeof(mx), "Matrix %02d Input Playback Route", | ||
947 | i+1); | ||
948 | err = add_new_ctl(mixer, &usb_scarlett_ctl_dynamic_enum, | ||
949 | scarlett_ctl_enum_resume, 0x32, | ||
950 | 0x06, i, USB_MIXER_S16, 1, mx, | ||
951 | &info->opt_matrix, &elem); | ||
952 | if (err < 0) | ||
953 | return err; | ||
954 | |||
955 | for (o = 0; o < info->matrix_out; o++) { | ||
956 | sprintf(mx, "Matrix %02d Mix %c Playback Volume", i+1, | ||
957 | o+'A'); | ||
958 | err = add_new_ctl(mixer, &usb_scarlett_ctl, | ||
959 | scarlett_ctl_resume, 0x3c, 0x00, | ||
960 | (i << 3) + (o & 0x07), USB_MIXER_S16, | ||
961 | 1, mx, NULL, &elem); | ||
962 | if (err < 0) | ||
963 | return err; | ||
964 | |||
965 | } | ||
966 | } | ||
967 | |||
968 | for (i = 0; i < info->input_len; i++) { | ||
969 | snprintf(mx, sizeof(mx), "Input Source %02d Capture Route", | ||
970 | i+1); | ||
971 | err = add_new_ctl(mixer, &usb_scarlett_ctl_dynamic_enum, | ||
972 | scarlett_ctl_enum_resume, 0x34, | ||
973 | 0x00, i, USB_MIXER_S16, 1, mx, | ||
974 | &info->opt_master, &elem); | ||
975 | if (err < 0) | ||
976 | return err; | ||
977 | } | ||
978 | |||
979 | /* val_len == 1 needed here */ | ||
980 | err = add_new_ctl(mixer, &usb_scarlett_ctl_enum, | ||
981 | scarlett_ctl_enum_resume, 0x28, 0x01, 0, | ||
982 | USB_MIXER_U8, 1, "Sample Clock Source", | ||
983 | &opt_clock, &elem); | ||
984 | if (err < 0) | ||
985 | return err; | ||
986 | |||
987 | /* val_len == 1 and UAC2_CS_MEM */ | ||
988 | err = add_new_ctl(mixer, &usb_scarlett_ctl_sync, NULL, 0x3c, 0x00, 2, | ||
989 | USB_MIXER_U8, 1, "Sample Clock Sync Status", | ||
990 | &opt_sync, &elem); | ||
991 | if (err < 0) | ||
992 | return err; | ||
993 | |||
994 | /* initialize sampling rate to 48000 */ | ||
995 | err = snd_usb_ctl_msg(mixer->chip->dev, | ||
996 | usb_sndctrlpipe(mixer->chip->dev, 0), UAC2_CS_CUR, | ||
997 | USB_RECIP_INTERFACE | USB_TYPE_CLASS | | ||
998 | USB_DIR_OUT, 0x0100, snd_usb_ctrl_intf(mixer->chip) | | ||
999 | (0x29 << 8), sample_rate_buffer, 4); | ||
1000 | if (err < 0) | ||
1001 | return err; | ||
1002 | |||
1003 | return err; | ||
1004 | } | ||
diff --git a/sound/usb/mixer_scarlett.h b/sound/usb/mixer_scarlett.h new file mode 100644 index 000000000000..19c592ab0332 --- /dev/null +++ b/sound/usb/mixer_scarlett.h | |||
@@ -0,0 +1,6 @@ | |||
1 | #ifndef __USB_MIXER_SCARLETT_H | ||
2 | #define __USB_MIXER_SCARLETT_H | ||
3 | |||
4 | int snd_scarlett_controls_create(struct usb_mixer_interface *mixer); | ||
5 | |||
6 | #endif /* __USB_MIXER_SCARLETT_H */ | ||
diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c index c62a1659106d..0d8aba5fe1a8 100644 --- a/sound/usb/pcm.c +++ b/sound/usb/pcm.c | |||
@@ -482,6 +482,11 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt) | |||
482 | /* set interface */ | 482 | /* set interface */ |
483 | if (subs->interface != fmt->iface || | 483 | if (subs->interface != fmt->iface || |
484 | subs->altset_idx != fmt->altset_idx) { | 484 | subs->altset_idx != fmt->altset_idx) { |
485 | |||
486 | err = snd_usb_select_mode_quirk(subs, fmt); | ||
487 | if (err < 0) | ||
488 | return -EIO; | ||
489 | |||
485 | err = usb_set_interface(dev, fmt->iface, fmt->altsetting); | 490 | err = usb_set_interface(dev, fmt->iface, fmt->altsetting); |
486 | if (err < 0) { | 491 | if (err < 0) { |
487 | dev_err(&dev->dev, | 492 | dev_err(&dev->dev, |
diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h index c657752a420c..73d2ba47cc31 100644 --- a/sound/usb/quirks-table.h +++ b/sound/usb/quirks-table.h | |||
@@ -2667,57 +2667,6 @@ YAMAHA_DEVICE(0x7010, "UB99"), | |||
2667 | .type = QUIRK_MIDI_NOVATION | 2667 | .type = QUIRK_MIDI_NOVATION |
2668 | } | 2668 | } |
2669 | }, | 2669 | }, |
2670 | { | ||
2671 | /* | ||
2672 | * Focusrite Scarlett 18i6 | ||
2673 | * | ||
2674 | * Avoid mixer creation, which otherwise fails because some of | ||
2675 | * the interface descriptor subtypes for interface 0 are | ||
2676 | * unknown. That should be fixed or worked-around but this at | ||
2677 | * least allows the device to be used successfully with a DAW | ||
2678 | * and an external mixer. See comments below about other | ||
2679 | * ignored interfaces. | ||
2680 | */ | ||
2681 | USB_DEVICE(0x1235, 0x8004), | ||
2682 | .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { | ||
2683 | .vendor_name = "Focusrite", | ||
2684 | .product_name = "Scarlett 18i6", | ||
2685 | .ifnum = QUIRK_ANY_INTERFACE, | ||
2686 | .type = QUIRK_COMPOSITE, | ||
2687 | .data = & (const struct snd_usb_audio_quirk[]) { | ||
2688 | { | ||
2689 | /* InterfaceSubClass 1 (Control Device) */ | ||
2690 | .ifnum = 0, | ||
2691 | .type = QUIRK_IGNORE_INTERFACE | ||
2692 | }, | ||
2693 | { | ||
2694 | .ifnum = 1, | ||
2695 | .type = QUIRK_AUDIO_STANDARD_INTERFACE | ||
2696 | }, | ||
2697 | { | ||
2698 | .ifnum = 2, | ||
2699 | .type = QUIRK_AUDIO_STANDARD_INTERFACE | ||
2700 | }, | ||
2701 | { | ||
2702 | /* InterfaceSubClass 1 (Control Device) */ | ||
2703 | .ifnum = 3, | ||
2704 | .type = QUIRK_IGNORE_INTERFACE | ||
2705 | }, | ||
2706 | { | ||
2707 | .ifnum = 4, | ||
2708 | .type = QUIRK_MIDI_STANDARD_INTERFACE | ||
2709 | }, | ||
2710 | { | ||
2711 | /* InterfaceSubClass 1 (Device Firmware Update) */ | ||
2712 | .ifnum = 5, | ||
2713 | .type = QUIRK_IGNORE_INTERFACE | ||
2714 | }, | ||
2715 | { | ||
2716 | .ifnum = -1 | ||
2717 | } | ||
2718 | } | ||
2719 | } | ||
2720 | }, | ||
2721 | 2670 | ||
2722 | /* Access Music devices */ | 2671 | /* Access Music devices */ |
2723 | { | 2672 | { |
@@ -2944,7 +2893,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), | |||
2944 | .data = (const struct snd_usb_audio_quirk[]){ | 2893 | .data = (const struct snd_usb_audio_quirk[]){ |
2945 | { | 2894 | { |
2946 | .ifnum = 0, | 2895 | .ifnum = 0, |
2947 | .type = QUIRK_IGNORE_INTERFACE, | 2896 | .type = QUIRK_AUDIO_STANDARD_MIXER, |
2948 | }, | 2897 | }, |
2949 | { | 2898 | { |
2950 | .ifnum = 1, | 2899 | .ifnum = 1, |
@@ -2955,16 +2904,40 @@ YAMAHA_DEVICE(0x7010, "UB99"), | |||
2955 | .iface = 1, | 2904 | .iface = 1, |
2956 | .altsetting = 1, | 2905 | .altsetting = 1, |
2957 | .altset_idx = 1, | 2906 | .altset_idx = 1, |
2958 | .attributes = UAC_EP_CS_ATTR_SAMPLE_RATE, | 2907 | .attributes = 0x4, |
2959 | .endpoint = 0x02, | 2908 | .endpoint = 0x02, |
2960 | .ep_attr = 0x01, | 2909 | .ep_attr = USB_ENDPOINT_XFER_ISOC | |
2961 | .rates = SNDRV_PCM_RATE_44100 | | 2910 | USB_ENDPOINT_SYNC_SYNC, |
2962 | SNDRV_PCM_RATE_48000, | 2911 | .maxpacksize = 0x130, |
2963 | .rate_min = 44100, | 2912 | .rates = SNDRV_PCM_RATE_48000, |
2913 | .rate_min = 48000, | ||
2964 | .rate_max = 48000, | 2914 | .rate_max = 48000, |
2965 | .nr_rates = 2, | 2915 | .nr_rates = 1, |
2966 | .rate_table = (unsigned int[]) { | 2916 | .rate_table = (unsigned int[]) { |
2967 | 44100, 48000 | 2917 | 48000 |
2918 | } | ||
2919 | } | ||
2920 | }, | ||
2921 | { | ||
2922 | .ifnum = 1, | ||
2923 | .type = QUIRK_AUDIO_FIXED_ENDPOINT, | ||
2924 | .data = &(const struct audioformat) { | ||
2925 | .formats = SNDRV_PCM_FMTBIT_S24_3BE, | ||
2926 | .channels = 2, | ||
2927 | .iface = 1, | ||
2928 | .altsetting = 1, | ||
2929 | .altset_idx = 1, | ||
2930 | .attributes = 0x4, | ||
2931 | .endpoint = 0x81, | ||
2932 | .ep_attr = USB_ENDPOINT_XFER_ISOC | | ||
2933 | USB_ENDPOINT_SYNC_ASYNC, | ||
2934 | .maxpacksize = 0x130, | ||
2935 | .rates = SNDRV_PCM_RATE_48000, | ||
2936 | .rate_min = 48000, | ||
2937 | .rate_max = 48000, | ||
2938 | .nr_rates = 1, | ||
2939 | .rate_table = (unsigned int[]) { | ||
2940 | 48000 | ||
2968 | } | 2941 | } |
2969 | } | 2942 | } |
2970 | }, | 2943 | }, |
@@ -2972,7 +2945,6 @@ YAMAHA_DEVICE(0x7010, "UB99"), | |||
2972 | .ifnum = -1 | 2945 | .ifnum = -1 |
2973 | } | 2946 | } |
2974 | } | 2947 | } |
2975 | |||
2976 | } | 2948 | } |
2977 | }, | 2949 | }, |
2978 | 2950 | ||
@@ -3203,6 +3175,46 @@ YAMAHA_DEVICE(0x7010, "UB99"), | |||
3203 | 3175 | ||
3204 | { | 3176 | { |
3205 | /* | 3177 | /* |
3178 | * ZOOM R16/24 in audio interface mode. | ||
3179 | * Mixer descriptors are garbage, further quirks will be needed | ||
3180 | * to make any of it functional, thus disabled for now. | ||
3181 | * Playback stream appears to start and run fine but no sound | ||
3182 | * is produced, so also disabled for now. | ||
3183 | */ | ||
3184 | USB_DEVICE(0x1686, 0x00dd), | ||
3185 | .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { | ||
3186 | .ifnum = QUIRK_ANY_INTERFACE, | ||
3187 | .type = QUIRK_COMPOSITE, | ||
3188 | .data = (const struct snd_usb_audio_quirk[]) { | ||
3189 | { | ||
3190 | /* Mixer */ | ||
3191 | .ifnum = 0, | ||
3192 | .type = QUIRK_IGNORE_INTERFACE, | ||
3193 | }, | ||
3194 | { | ||
3195 | /* Playback */ | ||
3196 | .ifnum = 1, | ||
3197 | .type = QUIRK_IGNORE_INTERFACE, | ||
3198 | }, | ||
3199 | { | ||
3200 | /* Capture */ | ||
3201 | .ifnum = 2, | ||
3202 | .type = QUIRK_AUDIO_STANDARD_INTERFACE, | ||
3203 | }, | ||
3204 | { | ||
3205 | /* Midi */ | ||
3206 | .ifnum = 3, | ||
3207 | .type = QUIRK_MIDI_STANDARD_INTERFACE | ||
3208 | }, | ||
3209 | { | ||
3210 | .ifnum = -1 | ||
3211 | }, | ||
3212 | } | ||
3213 | } | ||
3214 | }, | ||
3215 | |||
3216 | { | ||
3217 | /* | ||
3206 | * Some USB MIDI devices don't have an audio control interface, | 3218 | * Some USB MIDI devices don't have an audio control interface, |
3207 | * so we have to grab MIDI streaming interfaces here. | 3219 | * so we have to grab MIDI streaming interfaces here. |
3208 | */ | 3220 | */ |
diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c index 60dfe0d28771..4dbfb3d18ee2 100644 --- a/sound/usb/quirks.c +++ b/sound/usb/quirks.c | |||
@@ -43,12 +43,13 @@ | |||
43 | static int create_composite_quirk(struct snd_usb_audio *chip, | 43 | static int create_composite_quirk(struct snd_usb_audio *chip, |
44 | struct usb_interface *iface, | 44 | struct usb_interface *iface, |
45 | struct usb_driver *driver, | 45 | struct usb_driver *driver, |
46 | const struct snd_usb_audio_quirk *quirk) | 46 | const struct snd_usb_audio_quirk *quirk_comp) |
47 | { | 47 | { |
48 | int probed_ifnum = get_iface_desc(iface->altsetting)->bInterfaceNumber; | 48 | int probed_ifnum = get_iface_desc(iface->altsetting)->bInterfaceNumber; |
49 | const struct snd_usb_audio_quirk *quirk; | ||
49 | int err; | 50 | int err; |
50 | 51 | ||
51 | for (quirk = quirk->data; quirk->ifnum >= 0; ++quirk) { | 52 | for (quirk = quirk_comp->data; quirk->ifnum >= 0; ++quirk) { |
52 | iface = usb_ifnum_to_if(chip->dev, quirk->ifnum); | 53 | iface = usb_ifnum_to_if(chip->dev, quirk->ifnum); |
53 | if (!iface) | 54 | if (!iface) |
54 | continue; | 55 | continue; |
@@ -58,9 +59,17 @@ static int create_composite_quirk(struct snd_usb_audio *chip, | |||
58 | err = snd_usb_create_quirk(chip, iface, driver, quirk); | 59 | err = snd_usb_create_quirk(chip, iface, driver, quirk); |
59 | if (err < 0) | 60 | if (err < 0) |
60 | return err; | 61 | return err; |
61 | if (quirk->ifnum != probed_ifnum) | 62 | } |
63 | |||
64 | for (quirk = quirk_comp->data; quirk->ifnum >= 0; ++quirk) { | ||
65 | iface = usb_ifnum_to_if(chip->dev, quirk->ifnum); | ||
66 | if (!iface) | ||
67 | continue; | ||
68 | if (quirk->ifnum != probed_ifnum && | ||
69 | !usb_interface_claimed(iface)) | ||
62 | usb_driver_claim_interface(driver, iface, (void *)-1L); | 70 | usb_driver_claim_interface(driver, iface, (void *)-1L); |
63 | } | 71 | } |
72 | |||
64 | return 0; | 73 | return 0; |
65 | } | 74 | } |
66 | 75 | ||
@@ -1102,6 +1111,44 @@ void snd_usb_set_format_quirk(struct snd_usb_substream *subs, | |||
1102 | } | 1111 | } |
1103 | } | 1112 | } |
1104 | 1113 | ||
1114 | |||
1115 | /* Marantz/Denon USB DACs need a vendor cmd to switch | ||
1116 | * between PCM and native DSD mode | ||
1117 | */ | ||
1118 | int snd_usb_select_mode_quirk(struct snd_usb_substream *subs, | ||
1119 | struct audioformat *fmt) | ||
1120 | { | ||
1121 | struct usb_device *dev = subs->dev; | ||
1122 | int err; | ||
1123 | |||
1124 | switch (subs->stream->chip->usb_id) { | ||
1125 | case USB_ID(0x154e, 0x3005): /* Marantz HD-DAC1 */ | ||
1126 | case USB_ID(0x154e, 0x3006): /* Marantz SA-14S1 */ | ||
1127 | |||
1128 | /* First switch to alt set 0, otherwise the mode switch cmd | ||
1129 | * will not be accepted by the DAC | ||
1130 | */ | ||
1131 | err = usb_set_interface(dev, fmt->iface, 0); | ||
1132 | if (err < 0) | ||
1133 | return err; | ||
1134 | |||
1135 | mdelay(20); /* Delay needed after setting the interface */ | ||
1136 | |||
1137 | switch (fmt->altsetting) { | ||
1138 | case 2: /* DSD mode requested */ | ||
1139 | case 1: /* PCM mode requested */ | ||
1140 | err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), 0, | ||
1141 | USB_DIR_OUT|USB_TYPE_VENDOR|USB_RECIP_INTERFACE, | ||
1142 | fmt->altsetting - 1, 1, NULL, 0); | ||
1143 | if (err < 0) | ||
1144 | return err; | ||
1145 | break; | ||
1146 | } | ||
1147 | mdelay(20); | ||
1148 | } | ||
1149 | return 0; | ||
1150 | } | ||
1151 | |||
1105 | void snd_usb_endpoint_start_quirk(struct snd_usb_endpoint *ep) | 1152 | void snd_usb_endpoint_start_quirk(struct snd_usb_endpoint *ep) |
1106 | { | 1153 | { |
1107 | /* | 1154 | /* |
@@ -1160,6 +1207,14 @@ void snd_usb_ctl_msg_quirk(struct usb_device *dev, unsigned int pipe, | |||
1160 | break; | 1207 | break; |
1161 | } | 1208 | } |
1162 | } | 1209 | } |
1210 | |||
1211 | /* Zoom R16/24 needs a tiny delay here, otherwise requests like | ||
1212 | * get/set frequency return as failed despite actually succeeding. | ||
1213 | */ | ||
1214 | if ((le16_to_cpu(dev->descriptor.idVendor) == 0x1686) && | ||
1215 | (le16_to_cpu(dev->descriptor.idProduct) == 0x00dd) && | ||
1216 | (requesttype & USB_TYPE_MASK) == USB_TYPE_CLASS) | ||
1217 | mdelay(1); | ||
1163 | } | 1218 | } |
1164 | 1219 | ||
1165 | /* | 1220 | /* |
@@ -1204,5 +1259,16 @@ u64 snd_usb_interface_dsd_format_quirks(struct snd_usb_audio *chip, | |||
1204 | break; | 1259 | break; |
1205 | } | 1260 | } |
1206 | 1261 | ||
1262 | /* Denon/Marantz devices with USB DAC functionality */ | ||
1263 | switch (chip->usb_id) { | ||
1264 | case USB_ID(0x154e, 0x3005): /* Marantz HD-DAC1 */ | ||
1265 | case USB_ID(0x154e, 0x3006): /* Marantz SA-14S1 */ | ||
1266 | if (fp->altsetting == 2) | ||
1267 | return SNDRV_PCM_FMTBIT_DSD_U32_BE; | ||
1268 | break; | ||
1269 | default: | ||
1270 | break; | ||
1271 | } | ||
1272 | |||
1207 | return 0; | 1273 | return 0; |
1208 | } | 1274 | } |
diff --git a/sound/usb/quirks.h b/sound/usb/quirks.h index 665e972a1b40..1b862386577d 100644 --- a/sound/usb/quirks.h +++ b/sound/usb/quirks.h | |||
@@ -31,6 +31,9 @@ void snd_usb_ctl_msg_quirk(struct usb_device *dev, unsigned int pipe, | |||
31 | __u8 request, __u8 requesttype, __u16 value, | 31 | __u8 request, __u8 requesttype, __u16 value, |
32 | __u16 index, void *data, __u16 size); | 32 | __u16 index, void *data, __u16 size); |
33 | 33 | ||
34 | int snd_usb_select_mode_quirk(struct snd_usb_substream *subs, | ||
35 | struct audioformat *fmt); | ||
36 | |||
34 | u64 snd_usb_interface_dsd_format_quirks(struct snd_usb_audio *chip, | 37 | u64 snd_usb_interface_dsd_format_quirks(struct snd_usb_audio *chip, |
35 | struct audioformat *fp, | 38 | struct audioformat *fp, |
36 | unsigned int sample_bytes); | 39 | unsigned int sample_bytes); |
diff --git a/sound/usb/usx2y/usbusx2yaudio.c b/sound/usb/usx2y/usbusx2yaudio.c index a63330dd1407..61d5dc2a3421 100644 --- a/sound/usb/usx2y/usbusx2yaudio.c +++ b/sound/usb/usx2y/usbusx2yaudio.c | |||
@@ -272,13 +272,8 @@ static void usX2Y_clients_stop(struct usX2Ydev *usX2Y) | |||
272 | for (s = 0; s < 4; s++) { | 272 | for (s = 0; s < 4; s++) { |
273 | struct snd_usX2Y_substream *subs = usX2Y->subs[s]; | 273 | struct snd_usX2Y_substream *subs = usX2Y->subs[s]; |
274 | if (subs) { | 274 | if (subs) { |
275 | if (atomic_read(&subs->state) >= state_PRERUNNING) { | 275 | if (atomic_read(&subs->state) >= state_PRERUNNING) |
276 | unsigned long flags; | 276 | snd_pcm_stop_xrun(subs->pcm_substream); |
277 | |||
278 | snd_pcm_stream_lock_irqsave(subs->pcm_substream, flags); | ||
279 | snd_pcm_stop(subs->pcm_substream, SNDRV_PCM_STATE_XRUN); | ||
280 | snd_pcm_stream_unlock_irqrestore(subs->pcm_substream, flags); | ||
281 | } | ||
282 | for (u = 0; u < NRURBS; u++) { | 277 | for (u = 0; u < NRURBS; u++) { |
283 | struct urb *urb = subs->urb[u]; | 278 | struct urb *urb = subs->urb[u]; |
284 | if (NULL != urb) | 279 | if (NULL != urb) |