mixer_quirks.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722
  1. /*
  2. * USB Audio Driver for ALSA
  3. *
  4. * Quirks and vendor-specific extensions for mixer interfaces
  5. *
  6. * Copyright (c) 2002 by Takashi Iwai <tiwai@suse.de>
  7. *
  8. * Many codes borrowed from audio.c by
  9. * Alan Cox (alan@lxorguk.ukuu.org.uk)
  10. * Thomas Sailer (sailer@ife.ee.ethz.ch)
  11. *
  12. *
  13. * This program is free software; you can redistribute it and/or modify
  14. * it under the terms of the GNU General Public License as published by
  15. * the Free Software Foundation; either version 2 of the License, or
  16. * (at your option) any later version.
  17. *
  18. * This program is distributed in the hope that it will be useful,
  19. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  20. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  21. * GNU General Public License for more details.
  22. *
  23. * You should have received a copy of the GNU General Public License
  24. * along with this program; if not, write to the Free Software
  25. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  26. */
  27. #include <linux/init.h>
  28. #include <linux/slab.h>
  29. #include <linux/usb.h>
  30. #include <linux/usb/audio.h>
  31. #include <sound/core.h>
  32. #include <sound/control.h>
  33. #include <sound/hwdep.h>
  34. #include <sound/info.h>
  35. #include <sound/tlv.h>
  36. #include "usbaudio.h"
  37. #include "mixer.h"
  38. #include "mixer_quirks.h"
  39. #include "helper.h"
  40. extern struct snd_kcontrol_new *snd_usb_feature_unit_ctl;
  41. /*
  42. * Sound Blaster remote control configuration
  43. *
  44. * format of remote control data:
  45. * Extigy: xx 00
  46. * Audigy 2 NX: 06 80 xx 00 00 00
  47. * Live! 24-bit: 06 80 xx yy 22 83
  48. */
  49. static const struct rc_config {
  50. u32 usb_id;
  51. u8 offset;
  52. u8 length;
  53. u8 packet_length;
  54. u8 min_packet_length; /* minimum accepted length of the URB result */
  55. u8 mute_mixer_id;
  56. u32 mute_code;
  57. } rc_configs[] = {
  58. { USB_ID(0x041e, 0x3000), 0, 1, 2, 1, 18, 0x0013 }, /* Extigy */
  59. { USB_ID(0x041e, 0x3020), 2, 1, 6, 6, 18, 0x0013 }, /* Audigy 2 NX */
  60. { USB_ID(0x041e, 0x3040), 2, 2, 6, 6, 2, 0x6e91 }, /* Live! 24-bit */
  61. { USB_ID(0x041e, 0x3042), 0, 1, 1, 1, 1, 0x000d }, /* Usb X-Fi S51 */
  62. { USB_ID(0x041e, 0x30df), 0, 1, 1, 1, 1, 0x000d }, /* Usb X-Fi S51 Pro */
  63. { USB_ID(0x041e, 0x3237), 0, 1, 1, 1, 1, 0x000d }, /* Usb X-Fi S51 Pro */
  64. { USB_ID(0x041e, 0x3048), 2, 2, 6, 6, 2, 0x6e91 }, /* Toshiba SB0500 */
  65. };
  66. static void snd_usb_soundblaster_remote_complete(struct urb *urb)
  67. {
  68. struct usb_mixer_interface *mixer = urb->context;
  69. const struct rc_config *rc = mixer->rc_cfg;
  70. u32 code;
  71. if (urb->status < 0 || urb->actual_length < rc->min_packet_length)
  72. return;
  73. code = mixer->rc_buffer[rc->offset];
  74. if (rc->length == 2)
  75. code |= mixer->rc_buffer[rc->offset + 1] << 8;
  76. /* the Mute button actually changes the mixer control */
  77. if (code == rc->mute_code)
  78. snd_usb_mixer_notify_id(mixer, rc->mute_mixer_id);
  79. mixer->rc_code = code;
  80. wmb();
  81. wake_up(&mixer->rc_waitq);
  82. }
  83. static long snd_usb_sbrc_hwdep_read(struct snd_hwdep *hw, char __user *buf,
  84. long count, loff_t *offset)
  85. {
  86. struct usb_mixer_interface *mixer = hw->private_data;
  87. int err;
  88. u32 rc_code;
  89. if (count != 1 && count != 4)
  90. return -EINVAL;
  91. err = wait_event_interruptible(mixer->rc_waitq,
  92. (rc_code = xchg(&mixer->rc_code, 0)) != 0);
  93. if (err == 0) {
  94. if (count == 1)
  95. err = put_user(rc_code, buf);
  96. else
  97. err = put_user(rc_code, (u32 __user *)buf);
  98. }
  99. return err < 0 ? err : count;
  100. }
  101. static unsigned int snd_usb_sbrc_hwdep_poll(struct snd_hwdep *hw, struct file *file,
  102. poll_table *wait)
  103. {
  104. struct usb_mixer_interface *mixer = hw->private_data;
  105. poll_wait(file, &mixer->rc_waitq, wait);
  106. return mixer->rc_code ? POLLIN | POLLRDNORM : 0;
  107. }
  108. static int snd_usb_soundblaster_remote_init(struct usb_mixer_interface *mixer)
  109. {
  110. struct snd_hwdep *hwdep;
  111. int err, len, i;
  112. for (i = 0; i < ARRAY_SIZE(rc_configs); ++i)
  113. if (rc_configs[i].usb_id == mixer->chip->usb_id)
  114. break;
  115. if (i >= ARRAY_SIZE(rc_configs))
  116. return 0;
  117. mixer->rc_cfg = &rc_configs[i];
  118. len = mixer->rc_cfg->packet_length;
  119. init_waitqueue_head(&mixer->rc_waitq);
  120. err = snd_hwdep_new(mixer->chip->card, "SB remote control", 0, &hwdep);
  121. if (err < 0)
  122. return err;
  123. snprintf(hwdep->name, sizeof(hwdep->name),
  124. "%s remote control", mixer->chip->card->shortname);
  125. hwdep->iface = SNDRV_HWDEP_IFACE_SB_RC;
  126. hwdep->private_data = mixer;
  127. hwdep->ops.read = snd_usb_sbrc_hwdep_read;
  128. hwdep->ops.poll = snd_usb_sbrc_hwdep_poll;
  129. hwdep->exclusive = 1;
  130. mixer->rc_urb = usb_alloc_urb(0, GFP_KERNEL);
  131. if (!mixer->rc_urb)
  132. return -ENOMEM;
  133. mixer->rc_setup_packet = kmalloc(sizeof(*mixer->rc_setup_packet), GFP_KERNEL);
  134. if (!mixer->rc_setup_packet) {
  135. usb_free_urb(mixer->rc_urb);
  136. mixer->rc_urb = NULL;
  137. return -ENOMEM;
  138. }
  139. mixer->rc_setup_packet->bRequestType =
  140. USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE;
  141. mixer->rc_setup_packet->bRequest = UAC_GET_MEM;
  142. mixer->rc_setup_packet->wValue = cpu_to_le16(0);
  143. mixer->rc_setup_packet->wIndex = cpu_to_le16(0);
  144. mixer->rc_setup_packet->wLength = cpu_to_le16(len);
  145. usb_fill_control_urb(mixer->rc_urb, mixer->chip->dev,
  146. usb_rcvctrlpipe(mixer->chip->dev, 0),
  147. (u8*)mixer->rc_setup_packet, mixer->rc_buffer, len,
  148. snd_usb_soundblaster_remote_complete, mixer);
  149. return 0;
  150. }
  151. #define snd_audigy2nx_led_info snd_ctl_boolean_mono_info
  152. static int snd_audigy2nx_led_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
  153. {
  154. struct usb_mixer_interface *mixer = snd_kcontrol_chip(kcontrol);
  155. int index = kcontrol->private_value;
  156. ucontrol->value.integer.value[0] = mixer->audigy2nx_leds[index];
  157. return 0;
  158. }
  159. static int snd_audigy2nx_led_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
  160. {
  161. struct usb_mixer_interface *mixer = snd_kcontrol_chip(kcontrol);
  162. int index = kcontrol->private_value;
  163. int value = ucontrol->value.integer.value[0];
  164. int err, changed;
  165. if (value > 1)
  166. return -EINVAL;
  167. changed = value != mixer->audigy2nx_leds[index];
  168. down_read(&mixer->chip->shutdown_rwsem);
  169. if (mixer->chip->shutdown) {
  170. err = -ENODEV;
  171. goto out;
  172. }
  173. if (mixer->chip->usb_id == USB_ID(0x041e, 0x3042))
  174. err = snd_usb_ctl_msg(mixer->chip->dev,
  175. usb_sndctrlpipe(mixer->chip->dev, 0), 0x24,
  176. USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER,
  177. !value, 0, NULL, 0);
  178. /* USB X-Fi S51 Pro */
  179. if (mixer->chip->usb_id == USB_ID(0x041e, 0x30df))
  180. err = snd_usb_ctl_msg(mixer->chip->dev,
  181. usb_sndctrlpipe(mixer->chip->dev, 0), 0x24,
  182. USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER,
  183. !value, 0, NULL, 0);
  184. else
  185. err = snd_usb_ctl_msg(mixer->chip->dev,
  186. usb_sndctrlpipe(mixer->chip->dev, 0), 0x24,
  187. USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER,
  188. value, index + 2, NULL, 0);
  189. out:
  190. up_read(&mixer->chip->shutdown_rwsem);
  191. if (err < 0)
  192. return err;
  193. mixer->audigy2nx_leds[index] = value;
  194. return changed;
  195. }
  196. static struct snd_kcontrol_new snd_audigy2nx_controls[] = {
  197. {
  198. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  199. .name = "CMSS LED Switch",
  200. .info = snd_audigy2nx_led_info,
  201. .get = snd_audigy2nx_led_get,
  202. .put = snd_audigy2nx_led_put,
  203. .private_value = 0,
  204. },
  205. {
  206. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  207. .name = "Power LED Switch",
  208. .info = snd_audigy2nx_led_info,
  209. .get = snd_audigy2nx_led_get,
  210. .put = snd_audigy2nx_led_put,
  211. .private_value = 1,
  212. },
  213. {
  214. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  215. .name = "Dolby Digital LED Switch",
  216. .info = snd_audigy2nx_led_info,
  217. .get = snd_audigy2nx_led_get,
  218. .put = snd_audigy2nx_led_put,
  219. .private_value = 2,
  220. },
  221. };
  222. static int snd_audigy2nx_controls_create(struct usb_mixer_interface *mixer)
  223. {
  224. int i, err;
  225. for (i = 0; i < ARRAY_SIZE(snd_audigy2nx_controls); ++i) {
  226. /* USB X-Fi S51 doesn't have a CMSS LED */
  227. if ((mixer->chip->usb_id == USB_ID(0x041e, 0x3042)) && i == 0)
  228. continue;
  229. /* USB X-Fi S51 Pro doesn't have one either */
  230. if ((mixer->chip->usb_id == USB_ID(0x041e, 0x30df)) && i == 0)
  231. continue;
  232. if (i > 1 && /* Live24ext has 2 LEDs only */
  233. (mixer->chip->usb_id == USB_ID(0x041e, 0x3040) ||
  234. mixer->chip->usb_id == USB_ID(0x041e, 0x3042) ||
  235. mixer->chip->usb_id == USB_ID(0x041e, 0x30df) ||
  236. mixer->chip->usb_id == USB_ID(0x041e, 0x3048)))
  237. break;
  238. err = snd_ctl_add(mixer->chip->card,
  239. snd_ctl_new1(&snd_audigy2nx_controls[i], mixer));
  240. if (err < 0)
  241. return err;
  242. }
  243. mixer->audigy2nx_leds[1] = 1; /* Power LED is on by default */
  244. return 0;
  245. }
  246. static void snd_audigy2nx_proc_read(struct snd_info_entry *entry,
  247. struct snd_info_buffer *buffer)
  248. {
  249. static const struct sb_jack {
  250. int unitid;
  251. const char *name;
  252. } jacks_audigy2nx[] = {
  253. {4, "dig in "},
  254. {7, "line in"},
  255. {19, "spk out"},
  256. {20, "hph out"},
  257. {-1, NULL}
  258. }, jacks_live24ext[] = {
  259. {4, "line in"}, /* &1=Line, &2=Mic*/
  260. {3, "hph out"}, /* headphones */
  261. {0, "RC "}, /* last command, 6 bytes see rc_config above */
  262. {-1, NULL}
  263. };
  264. const struct sb_jack *jacks;
  265. struct usb_mixer_interface *mixer = entry->private_data;
  266. int i, err;
  267. u8 buf[3];
  268. snd_iprintf(buffer, "%s jacks\n\n", mixer->chip->card->shortname);
  269. if (mixer->chip->usb_id == USB_ID(0x041e, 0x3020))
  270. jacks = jacks_audigy2nx;
  271. else if (mixer->chip->usb_id == USB_ID(0x041e, 0x3040) ||
  272. mixer->chip->usb_id == USB_ID(0x041e, 0x3048))
  273. jacks = jacks_live24ext;
  274. else
  275. return;
  276. for (i = 0; jacks[i].name; ++i) {
  277. snd_iprintf(buffer, "%s: ", jacks[i].name);
  278. down_read(&mixer->chip->shutdown_rwsem);
  279. if (mixer->chip->shutdown)
  280. err = 0;
  281. else
  282. err = snd_usb_ctl_msg(mixer->chip->dev,
  283. usb_rcvctrlpipe(mixer->chip->dev, 0),
  284. UAC_GET_MEM, USB_DIR_IN | USB_TYPE_CLASS |
  285. USB_RECIP_INTERFACE, 0,
  286. jacks[i].unitid << 8, buf, 3);
  287. up_read(&mixer->chip->shutdown_rwsem);
  288. if (err == 3 && (buf[0] == 3 || buf[0] == 6))
  289. snd_iprintf(buffer, "%02x %02x\n", buf[1], buf[2]);
  290. else
  291. snd_iprintf(buffer, "?\n");
  292. }
  293. }
  294. static int snd_xonar_u1_switch_get(struct snd_kcontrol *kcontrol,
  295. struct snd_ctl_elem_value *ucontrol)
  296. {
  297. struct usb_mixer_interface *mixer = snd_kcontrol_chip(kcontrol);
  298. ucontrol->value.integer.value[0] = !!(mixer->xonar_u1_status & 0x02);
  299. return 0;
  300. }
  301. static int snd_xonar_u1_switch_put(struct snd_kcontrol *kcontrol,
  302. struct snd_ctl_elem_value *ucontrol)
  303. {
  304. struct usb_mixer_interface *mixer = snd_kcontrol_chip(kcontrol);
  305. u8 old_status, new_status;
  306. int err, changed;
  307. old_status = mixer->xonar_u1_status;
  308. if (ucontrol->value.integer.value[0])
  309. new_status = old_status | 0x02;
  310. else
  311. new_status = old_status & ~0x02;
  312. changed = new_status != old_status;
  313. down_read(&mixer->chip->shutdown_rwsem);
  314. if (mixer->chip->shutdown)
  315. err = -ENODEV;
  316. else
  317. err = snd_usb_ctl_msg(mixer->chip->dev,
  318. usb_sndctrlpipe(mixer->chip->dev, 0), 0x08,
  319. USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER,
  320. 50, 0, &new_status, 1);
  321. up_read(&mixer->chip->shutdown_rwsem);
  322. if (err < 0)
  323. return err;
  324. mixer->xonar_u1_status = new_status;
  325. return changed;
  326. }
  327. static struct snd_kcontrol_new snd_xonar_u1_output_switch = {
  328. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  329. .name = "Digital Playback Switch",
  330. .info = snd_ctl_boolean_mono_info,
  331. .get = snd_xonar_u1_switch_get,
  332. .put = snd_xonar_u1_switch_put,
  333. };
  334. static int snd_xonar_u1_controls_create(struct usb_mixer_interface *mixer)
  335. {
  336. int err;
  337. err = snd_ctl_add(mixer->chip->card,
  338. snd_ctl_new1(&snd_xonar_u1_output_switch, mixer));
  339. if (err < 0)
  340. return err;
  341. mixer->xonar_u1_status = 0x05;
  342. return 0;
  343. }
  344. /* Native Instruments device quirks */
  345. #define _MAKE_NI_CONTROL(bRequest,wIndex) ((bRequest) << 16 | (wIndex))
  346. static int snd_nativeinstruments_control_get(struct snd_kcontrol *kcontrol,
  347. struct snd_ctl_elem_value *ucontrol)
  348. {
  349. struct usb_mixer_interface *mixer = snd_kcontrol_chip(kcontrol);
  350. struct usb_device *dev = mixer->chip->dev;
  351. u8 bRequest = (kcontrol->private_value >> 16) & 0xff;
  352. u16 wIndex = kcontrol->private_value & 0xffff;
  353. u8 tmp;
  354. int ret;
  355. down_read(&mixer->chip->shutdown_rwsem);
  356. if (mixer->chip->shutdown)
  357. ret = -ENODEV;
  358. else
  359. ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), bRequest,
  360. USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
  361. 0, wIndex,
  362. &tmp, sizeof(tmp), 1000);
  363. up_read(&mixer->chip->shutdown_rwsem);
  364. if (ret < 0) {
  365. snd_printk(KERN_ERR
  366. "unable to issue vendor read request (ret = %d)", ret);
  367. return ret;
  368. }
  369. ucontrol->value.integer.value[0] = tmp;
  370. return 0;
  371. }
  372. static int snd_nativeinstruments_control_put(struct snd_kcontrol *kcontrol,
  373. struct snd_ctl_elem_value *ucontrol)
  374. {
  375. struct usb_mixer_interface *mixer = snd_kcontrol_chip(kcontrol);
  376. struct usb_device *dev = mixer->chip->dev;
  377. u8 bRequest = (kcontrol->private_value >> 16) & 0xff;
  378. u16 wIndex = kcontrol->private_value & 0xffff;
  379. u16 wValue = ucontrol->value.integer.value[0];
  380. int ret;
  381. down_read(&mixer->chip->shutdown_rwsem);
  382. if (mixer->chip->shutdown)
  383. ret = -ENODEV;
  384. else
  385. ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), bRequest,
  386. USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT,
  387. wValue, wIndex,
  388. NULL, 0, 1000);
  389. up_read(&mixer->chip->shutdown_rwsem);
  390. if (ret < 0) {
  391. snd_printk(KERN_ERR
  392. "unable to issue vendor write request (ret = %d)", ret);
  393. return ret;
  394. }
  395. return 0;
  396. }
  397. static struct snd_kcontrol_new snd_nativeinstruments_ta6_mixers[] = {
  398. {
  399. .name = "Direct Thru Channel A",
  400. .private_value = _MAKE_NI_CONTROL(0x01, 0x03),
  401. },
  402. {
  403. .name = "Direct Thru Channel B",
  404. .private_value = _MAKE_NI_CONTROL(0x01, 0x05),
  405. },
  406. {
  407. .name = "Phono Input Channel A",
  408. .private_value = _MAKE_NI_CONTROL(0x02, 0x03),
  409. },
  410. {
  411. .name = "Phono Input Channel B",
  412. .private_value = _MAKE_NI_CONTROL(0x02, 0x05),
  413. },
  414. };
  415. static struct snd_kcontrol_new snd_nativeinstruments_ta10_mixers[] = {
  416. {
  417. .name = "Direct Thru Channel A",
  418. .private_value = _MAKE_NI_CONTROL(0x01, 0x03),
  419. },
  420. {
  421. .name = "Direct Thru Channel B",
  422. .private_value = _MAKE_NI_CONTROL(0x01, 0x05),
  423. },
  424. {
  425. .name = "Direct Thru Channel C",
  426. .private_value = _MAKE_NI_CONTROL(0x01, 0x07),
  427. },
  428. {
  429. .name = "Direct Thru Channel D",
  430. .private_value = _MAKE_NI_CONTROL(0x01, 0x09),
  431. },
  432. {
  433. .name = "Phono Input Channel A",
  434. .private_value = _MAKE_NI_CONTROL(0x02, 0x03),
  435. },
  436. {
  437. .name = "Phono Input Channel B",
  438. .private_value = _MAKE_NI_CONTROL(0x02, 0x05),
  439. },
  440. {
  441. .name = "Phono Input Channel C",
  442. .private_value = _MAKE_NI_CONTROL(0x02, 0x07),
  443. },
  444. {
  445. .name = "Phono Input Channel D",
  446. .private_value = _MAKE_NI_CONTROL(0x02, 0x09),
  447. },
  448. };
  449. static int snd_nativeinstruments_create_mixer(struct usb_mixer_interface *mixer,
  450. const struct snd_kcontrol_new *kc,
  451. unsigned int count)
  452. {
  453. int i, err = 0;
  454. struct snd_kcontrol_new template = {
  455. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  456. .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
  457. .get = snd_nativeinstruments_control_get,
  458. .put = snd_nativeinstruments_control_put,
  459. .info = snd_ctl_boolean_mono_info,
  460. };
  461. for (i = 0; i < count; i++) {
  462. struct snd_kcontrol *c;
  463. template.name = kc[i].name;
  464. template.private_value = kc[i].private_value;
  465. c = snd_ctl_new1(&template, mixer);
  466. err = snd_ctl_add(mixer->chip->card, c);
  467. if (err < 0)
  468. break;
  469. }
  470. return err;
  471. }
  472. /* M-Audio FastTrack Ultra quirks */
  473. /* private_free callback */
  474. static void usb_mixer_elem_free(struct snd_kcontrol *kctl)
  475. {
  476. kfree(kctl->private_data);
  477. kctl->private_data = NULL;
  478. }
  479. static int snd_maudio_ftu_create_ctl(struct usb_mixer_interface *mixer,
  480. int in, int out, const char *name)
  481. {
  482. struct usb_mixer_elem_info *cval;
  483. struct snd_kcontrol *kctl;
  484. cval = kzalloc(sizeof(*cval), GFP_KERNEL);
  485. if (!cval)
  486. return -ENOMEM;
  487. cval->id = 5;
  488. cval->mixer = mixer;
  489. cval->val_type = USB_MIXER_S16;
  490. cval->channels = 1;
  491. cval->control = out + 1;
  492. cval->cmask = 1 << in;
  493. kctl = snd_ctl_new1(snd_usb_feature_unit_ctl, cval);
  494. if (!kctl) {
  495. kfree(cval);
  496. return -ENOMEM;
  497. }
  498. snprintf(kctl->id.name, sizeof(kctl->id.name), name);
  499. kctl->private_free = usb_mixer_elem_free;
  500. return snd_usb_mixer_add_control(mixer, kctl);
  501. }
  502. static int snd_maudio_ftu_create_mixer(struct usb_mixer_interface *mixer)
  503. {
  504. char name[64];
  505. int in, out, err;
  506. for (out = 0; out < 8; out++) {
  507. for (in = 0; in < 8; in++) {
  508. snprintf(name, sizeof(name),
  509. "AIn%d - Out%d Capture Volume", in + 1, out + 1);
  510. err = snd_maudio_ftu_create_ctl(mixer, in, out, name);
  511. if (err < 0)
  512. return err;
  513. }
  514. for (in = 8; in < 16; in++) {
  515. snprintf(name, sizeof(name),
  516. "DIn%d - Out%d Playback Volume", in - 7, out + 1);
  517. err = snd_maudio_ftu_create_ctl(mixer, in, out, name);
  518. if (err < 0)
  519. return err;
  520. }
  521. }
  522. return 0;
  523. }
  524. void snd_emuusb_set_samplerate(struct snd_usb_audio *chip,
  525. unsigned char samplerate_id)
  526. {
  527. struct usb_mixer_interface *mixer;
  528. struct usb_mixer_elem_info *cval;
  529. int unitid = 12; /* SamleRate ExtensionUnit ID */
  530. list_for_each_entry(mixer, &chip->mixer_list, list) {
  531. cval = mixer->id_elems[unitid];
  532. if (cval) {
  533. snd_usb_mixer_set_ctl_value(cval, UAC_SET_CUR,
  534. cval->control << 8,
  535. samplerate_id);
  536. snd_usb_mixer_notify_id(mixer, unitid);
  537. }
  538. break;
  539. }
  540. }
  541. int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer)
  542. {
  543. int err = 0;
  544. struct snd_info_entry *entry;
  545. if ((err = snd_usb_soundblaster_remote_init(mixer)) < 0)
  546. return err;
  547. switch (mixer->chip->usb_id) {
  548. case USB_ID(0x041e, 0x3020):
  549. case USB_ID(0x041e, 0x3040):
  550. case USB_ID(0x041e, 0x3042):
  551. case USB_ID(0x041e, 0x30df):
  552. case USB_ID(0x041e, 0x3048):
  553. err = snd_audigy2nx_controls_create(mixer);
  554. if (err < 0)
  555. break;
  556. if (!snd_card_proc_new(mixer->chip->card, "audigy2nx", &entry))
  557. snd_info_set_text_ops(entry, mixer,
  558. snd_audigy2nx_proc_read);
  559. break;
  560. case USB_ID(0x0763, 0x2080): /* M-Audio Fast Track Ultra */
  561. case USB_ID(0x0763, 0x2081): /* M-Audio Fast Track Ultra 8R */
  562. err = snd_maudio_ftu_create_mixer(mixer);
  563. break;
  564. case USB_ID(0x0b05, 0x1739):
  565. case USB_ID(0x0b05, 0x1743):
  566. err = snd_xonar_u1_controls_create(mixer);
  567. break;
  568. case USB_ID(0x17cc, 0x1011): /* Traktor Audio 6 */
  569. err = snd_nativeinstruments_create_mixer(mixer,
  570. snd_nativeinstruments_ta6_mixers,
  571. ARRAY_SIZE(snd_nativeinstruments_ta6_mixers));
  572. break;
  573. case USB_ID(0x17cc, 0x1021): /* Traktor Audio 10 */
  574. err = snd_nativeinstruments_create_mixer(mixer,
  575. snd_nativeinstruments_ta10_mixers,
  576. ARRAY_SIZE(snd_nativeinstruments_ta10_mixers));
  577. break;
  578. }
  579. return err;
  580. }
  581. void snd_usb_mixer_rc_memory_change(struct usb_mixer_interface *mixer,
  582. int unitid)
  583. {
  584. if (!mixer->rc_cfg)
  585. return;
  586. /* unit ids specific to Extigy/Audigy 2 NX: */
  587. switch (unitid) {
  588. case 0: /* remote control */
  589. mixer->rc_urb->dev = mixer->chip->dev;
  590. usb_submit_urb(mixer->rc_urb, GFP_ATOMIC);
  591. break;
  592. case 4: /* digital in jack */
  593. case 7: /* line in jacks */
  594. case 19: /* speaker out jacks */
  595. case 20: /* headphones out jack */
  596. break;
  597. /* live24ext: 4 = line-in jack */
  598. case 3: /* hp-out jack (may actuate Mute) */
  599. if (mixer->chip->usb_id == USB_ID(0x041e, 0x3040) ||
  600. mixer->chip->usb_id == USB_ID(0x041e, 0x3048))
  601. snd_usb_mixer_notify_id(mixer, mixer->rc_cfg->mute_mixer_id);
  602. break;
  603. default:
  604. snd_printd(KERN_DEBUG "memory change in unknown unit %d\n", unitid);
  605. break;
  606. }
  607. }
  608. static void snd_dragonfly_quirk_db_scale(struct usb_mixer_interface *mixer,
  609. struct snd_kcontrol *kctl)
  610. {
  611. /* Approximation using 10 ranges based on output measurement on hw v1.2.
  612. * This seems close to the cubic mapping e.g. alsamixer uses. */
  613. static const DECLARE_TLV_DB_RANGE(scale,
  614. 0, 1, TLV_DB_MINMAX_ITEM(-5300, -4970),
  615. 2, 5, TLV_DB_MINMAX_ITEM(-4710, -4160),
  616. 6, 7, TLV_DB_MINMAX_ITEM(-3884, -3710),
  617. 8, 14, TLV_DB_MINMAX_ITEM(-3443, -2560),
  618. 15, 16, TLV_DB_MINMAX_ITEM(-2475, -2324),
  619. 17, 19, TLV_DB_MINMAX_ITEM(-2228, -2031),
  620. 20, 26, TLV_DB_MINMAX_ITEM(-1910, -1393),
  621. 27, 31, TLV_DB_MINMAX_ITEM(-1322, -1032),
  622. 32, 40, TLV_DB_MINMAX_ITEM(-968, -490),
  623. 41, 50, TLV_DB_MINMAX_ITEM(-441, 0),
  624. );
  625. dev_info(&mixer->chip->dev->dev, "applying DragonFly dB scale quirk\n");
  626. kctl->tlv.p = scale;
  627. kctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ;
  628. kctl->vd[0].access &= ~SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK;
  629. }
  630. void snd_usb_mixer_fu_apply_quirk(struct usb_mixer_interface *mixer,
  631. struct usb_mixer_elem_info *cval, int unitid,
  632. struct snd_kcontrol *kctl)
  633. {
  634. switch (mixer->chip->usb_id) {
  635. case USB_ID(0x21b4, 0x0081): /* AudioQuest DragonFly */
  636. if (unitid == 7 && cval->min == 0 && cval->max == 50)
  637. snd_dragonfly_quirk_db_scale(mixer, kctl);
  638. break;
  639. }
  640. }