diff options
Diffstat (limited to 'sound/usb/mixer_quirks.c')
-rw-r--r-- | sound/usb/mixer_quirks.c | 174 |
1 files changed, 161 insertions, 13 deletions
diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c index 782f741cd00a..73dcc8256bc0 100644 --- a/sound/usb/mixer_quirks.c +++ b/sound/usb/mixer_quirks.c | |||
@@ -346,6 +346,141 @@ static int snd_xonar_u1_controls_create(struct usb_mixer_interface *mixer) | |||
346 | return 0; | 346 | return 0; |
347 | } | 347 | } |
348 | 348 | ||
349 | /* Native Instruments device quirks */ | ||
350 | |||
351 | #define _MAKE_NI_CONTROL(bRequest,wIndex) ((bRequest) << 16 | (wIndex)) | ||
352 | |||
353 | static int snd_nativeinstruments_control_get(struct snd_kcontrol *kcontrol, | ||
354 | struct snd_ctl_elem_value *ucontrol) | ||
355 | { | ||
356 | struct usb_mixer_interface *mixer = snd_kcontrol_chip(kcontrol); | ||
357 | struct usb_device *dev = mixer->chip->dev; | ||
358 | u8 bRequest = (kcontrol->private_value >> 16) & 0xff; | ||
359 | u16 wIndex = kcontrol->private_value & 0xffff; | ||
360 | u8 tmp; | ||
361 | |||
362 | int ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), bRequest, | ||
363 | USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, | ||
364 | 0, cpu_to_le16(wIndex), | ||
365 | &tmp, sizeof(tmp), 1000); | ||
366 | |||
367 | if (ret < 0) { | ||
368 | snd_printk(KERN_ERR | ||
369 | "unable to issue vendor read request (ret = %d)", ret); | ||
370 | return ret; | ||
371 | } | ||
372 | |||
373 | ucontrol->value.integer.value[0] = tmp; | ||
374 | |||
375 | return 0; | ||
376 | } | ||
377 | |||
378 | static int snd_nativeinstruments_control_put(struct snd_kcontrol *kcontrol, | ||
379 | struct snd_ctl_elem_value *ucontrol) | ||
380 | { | ||
381 | struct usb_mixer_interface *mixer = snd_kcontrol_chip(kcontrol); | ||
382 | struct usb_device *dev = mixer->chip->dev; | ||
383 | u8 bRequest = (kcontrol->private_value >> 16) & 0xff; | ||
384 | u16 wIndex = kcontrol->private_value & 0xffff; | ||
385 | u16 wValue = ucontrol->value.integer.value[0]; | ||
386 | |||
387 | int ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), bRequest, | ||
388 | USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT, | ||
389 | cpu_to_le16(wValue), cpu_to_le16(wIndex), | ||
390 | NULL, 0, 1000); | ||
391 | |||
392 | if (ret < 0) { | ||
393 | snd_printk(KERN_ERR | ||
394 | "unable to issue vendor write request (ret = %d)", ret); | ||
395 | return ret; | ||
396 | } | ||
397 | |||
398 | return 0; | ||
399 | } | ||
400 | |||
401 | static struct snd_kcontrol_new snd_nativeinstruments_ta6_mixers[] = { | ||
402 | { | ||
403 | .name = "Direct Thru Channel A", | ||
404 | .private_value = _MAKE_NI_CONTROL(0x01, 0x03), | ||
405 | }, | ||
406 | { | ||
407 | .name = "Direct Thru Channel B", | ||
408 | .private_value = _MAKE_NI_CONTROL(0x01, 0x05), | ||
409 | }, | ||
410 | { | ||
411 | .name = "Phono Input Channel A", | ||
412 | .private_value = _MAKE_NI_CONTROL(0x02, 0x03), | ||
413 | }, | ||
414 | { | ||
415 | .name = "Phono Input Channel B", | ||
416 | .private_value = _MAKE_NI_CONTROL(0x02, 0x05), | ||
417 | }, | ||
418 | }; | ||
419 | |||
420 | static struct snd_kcontrol_new snd_nativeinstruments_ta10_mixers[] = { | ||
421 | { | ||
422 | .name = "Direct Thru Channel A", | ||
423 | .private_value = _MAKE_NI_CONTROL(0x01, 0x03), | ||
424 | }, | ||
425 | { | ||
426 | .name = "Direct Thru Channel B", | ||
427 | .private_value = _MAKE_NI_CONTROL(0x01, 0x05), | ||
428 | }, | ||
429 | { | ||
430 | .name = "Direct Thru Channel C", | ||
431 | .private_value = _MAKE_NI_CONTROL(0x01, 0x07), | ||
432 | }, | ||
433 | { | ||
434 | .name = "Direct Thru Channel D", | ||
435 | .private_value = _MAKE_NI_CONTROL(0x01, 0x09), | ||
436 | }, | ||
437 | { | ||
438 | .name = "Phono Input Channel A", | ||
439 | .private_value = _MAKE_NI_CONTROL(0x02, 0x03), | ||
440 | }, | ||
441 | { | ||
442 | .name = "Phono Input Channel B", | ||
443 | .private_value = _MAKE_NI_CONTROL(0x02, 0x05), | ||
444 | }, | ||
445 | { | ||
446 | .name = "Phono Input Channel C", | ||
447 | .private_value = _MAKE_NI_CONTROL(0x02, 0x07), | ||
448 | }, | ||
449 | { | ||
450 | .name = "Phono Input Channel D", | ||
451 | .private_value = _MAKE_NI_CONTROL(0x02, 0x09), | ||
452 | }, | ||
453 | }; | ||
454 | |||
455 | static int snd_nativeinstruments_create_mixer(struct usb_mixer_interface *mixer, | ||
456 | const struct snd_kcontrol_new *kc, | ||
457 | unsigned int count) | ||
458 | { | ||
459 | int i, err = 0; | ||
460 | struct snd_kcontrol_new template = { | ||
461 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
462 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, | ||
463 | .get = snd_nativeinstruments_control_get, | ||
464 | .put = snd_nativeinstruments_control_put, | ||
465 | .info = snd_ctl_boolean_mono_info, | ||
466 | }; | ||
467 | |||
468 | for (i = 0; i < count; i++) { | ||
469 | struct snd_kcontrol *c; | ||
470 | |||
471 | template.name = kc[i].name; | ||
472 | template.private_value = kc[i].private_value; | ||
473 | |||
474 | c = snd_ctl_new1(&template, mixer); | ||
475 | err = snd_ctl_add(mixer->chip->card, c); | ||
476 | |||
477 | if (err < 0) | ||
478 | break; | ||
479 | } | ||
480 | |||
481 | return err; | ||
482 | } | ||
483 | |||
349 | void snd_emuusb_set_samplerate(struct snd_usb_audio *chip, | 484 | void snd_emuusb_set_samplerate(struct snd_usb_audio *chip, |
350 | unsigned char samplerate_id) | 485 | unsigned char samplerate_id) |
351 | { | 486 | { |
@@ -367,31 +502,44 @@ void snd_emuusb_set_samplerate(struct snd_usb_audio *chip, | |||
367 | 502 | ||
368 | int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer) | 503 | int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer) |
369 | { | 504 | { |
370 | int err; | 505 | int err = 0; |
371 | struct snd_info_entry *entry; | 506 | struct snd_info_entry *entry; |
372 | 507 | ||
373 | if ((err = snd_usb_soundblaster_remote_init(mixer)) < 0) | 508 | if ((err = snd_usb_soundblaster_remote_init(mixer)) < 0) |
374 | return err; | 509 | return err; |
375 | 510 | ||
376 | if (mixer->chip->usb_id == USB_ID(0x041e, 0x3020) || | 511 | switch (mixer->chip->usb_id) { |
377 | mixer->chip->usb_id == USB_ID(0x041e, 0x3040) || | 512 | case USB_ID(0x041e, 0x3020): |
378 | mixer->chip->usb_id == USB_ID(0x041e, 0x3042) || | 513 | case USB_ID(0x041e, 0x3040): |
379 | mixer->chip->usb_id == USB_ID(0x041e, 0x3048)) { | 514 | case USB_ID(0x041e, 0x3042): |
380 | if ((err = snd_audigy2nx_controls_create(mixer)) < 0) | 515 | case USB_ID(0x041e, 0x3048): |
381 | return err; | 516 | err = snd_audigy2nx_controls_create(mixer); |
517 | if (err < 0) | ||
518 | break; | ||
382 | if (!snd_card_proc_new(mixer->chip->card, "audigy2nx", &entry)) | 519 | if (!snd_card_proc_new(mixer->chip->card, "audigy2nx", &entry)) |
383 | snd_info_set_text_ops(entry, mixer, | 520 | snd_info_set_text_ops(entry, mixer, |
384 | snd_audigy2nx_proc_read); | 521 | snd_audigy2nx_proc_read); |
385 | } | 522 | break; |
386 | 523 | ||
387 | if (mixer->chip->usb_id == USB_ID(0x0b05, 0x1739) || | 524 | case USB_ID(0x0b05, 0x1739): |
388 | mixer->chip->usb_id == USB_ID(0x0b05, 0x1743)) { | 525 | case USB_ID(0x0b05, 0x1743): |
389 | err = snd_xonar_u1_controls_create(mixer); | 526 | err = snd_xonar_u1_controls_create(mixer); |
390 | if (err < 0) | 527 | break; |
391 | return err; | 528 | |
529 | case USB_ID(0x17cc, 0x1011): /* Traktor Audio 6 */ | ||
530 | err = snd_nativeinstruments_create_mixer(mixer, | ||
531 | snd_nativeinstruments_ta6_mixers, | ||
532 | ARRAY_SIZE(snd_nativeinstruments_ta6_mixers)); | ||
533 | break; | ||
534 | |||
535 | case USB_ID(0x17cc, 0x1021): /* Traktor Audio 10 */ | ||
536 | err = snd_nativeinstruments_create_mixer(mixer, | ||
537 | snd_nativeinstruments_ta10_mixers, | ||
538 | ARRAY_SIZE(snd_nativeinstruments_ta10_mixers)); | ||
539 | break; | ||
392 | } | 540 | } |
393 | 541 | ||
394 | return 0; | 542 | return err; |
395 | } | 543 | } |
396 | 544 | ||
397 | void snd_usb_mixer_rc_memory_change(struct usb_mixer_interface *mixer, | 545 | void snd_usb_mixer_rc_memory_change(struct usb_mixer_interface *mixer, |