Commit 066624c6a1733a72a67f1d06d35a2153e7d9082b

Authored by Przemek Rudy
Committed by Takashi Iwai
1 parent accaf69da1

ALSA: usb-audio: Add Audio Advantage Micro II

This patch is adding extensive support (beside standard usb audio class)
for Audio Advantage Micro II usb sound card.
Features included:
- Access to AES bits (so now sending the IEC61937 compliant stream is
possible).
- Mixer SPDIF control added to turn on/off the optical transmitter.

Signed-off-by: Przemek Rudy <prudy1@o2.pl>
Signed-off-by: Takashi Iwai <tiwai@suse.de>

Showing 2 changed files with 224 additions and 0 deletions Side-by-side Diff

sound/usb/mixer_quirks.c
... ... @@ -9,6 +9,8 @@
9 9 * Alan Cox (alan@lxorguk.ukuu.org.uk)
10 10 * Thomas Sailer (sailer@ife.ee.ethz.ch)
11 11 *
  12 + * Audio Advantage Micro II support added by:
  13 + * Przemek Rudy (prudy1@o2.pl)
12 14 *
13 15 * This program is free software; you can redistribute it and/or modify
14 16 * it under the terms of the GNU General Public License as published by
... ... @@ -30,6 +32,7 @@
30 32 #include <linux/usb.h>
31 33 #include <linux/usb/audio.h>
32 34  
  35 +#include <sound/asoundef.h>
33 36 #include <sound/core.h>
34 37 #include <sound/control.h>
35 38 #include <sound/hwdep.h>
... ... @@ -1315,6 +1318,211 @@
1315 1318 {}
1316 1319 };
1317 1320  
  1321 +/* Audio Advantage Micro II findings:
  1322 + *
  1323 + * Mapping spdif AES bits to vendor register.bit:
  1324 + * AES0: [0 0 0 0 2.3 2.2 2.1 2.0] - default 0x00
  1325 + * AES1: [3.3 3.2.3.1.3.0 2.7 2.6 2.5 2.4] - default: 0x01
  1326 + * AES2: [0 0 0 0 0 0 0 0]
  1327 + * AES3: [0 0 0 0 0 0 x 0] - 'x' bit is set basing on standard usb request
  1328 + * (UAC_EP_CS_ATTR_SAMPLE_RATE) for Audio Devices
  1329 + *
  1330 + * power on values:
  1331 + * r2: 0x10
  1332 + * r3: 0x20 (b7 is zeroed just before playback (except IEC61937) and set
  1333 + * just after it to 0xa0, presumably it disables/mutes some analog
  1334 + * parts when there is no audio.)
  1335 + * r9: 0x28
  1336 + *
  1337 + * Optical transmitter on/off:
  1338 + * vendor register.bit: 9.1
  1339 + * 0 - on (0x28 register value)
  1340 + * 1 - off (0x2a register value)
  1341 + *
  1342 + */
  1343 +static int snd_microii_spdif_info(struct snd_kcontrol *kcontrol,
  1344 + struct snd_ctl_elem_info *uinfo)
  1345 +{
  1346 + uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
  1347 + uinfo->count = 1;
  1348 + return 0;
  1349 +}
  1350 +
  1351 +static int snd_microii_spdif_default_get(struct snd_kcontrol *kcontrol,
  1352 + struct snd_ctl_elem_value *ucontrol)
  1353 +{
  1354 + struct usb_mixer_interface *mixer = snd_kcontrol_chip(kcontrol);
  1355 + int err;
  1356 + struct usb_interface *iface;
  1357 + struct usb_host_interface *alts;
  1358 + unsigned int ep;
  1359 + unsigned char data[3];
  1360 + int rate;
  1361 +
  1362 + ucontrol->value.iec958.status[0] = kcontrol->private_value & 0xff;
  1363 + ucontrol->value.iec958.status[1] = (kcontrol->private_value >> 8) & 0xff;
  1364 + ucontrol->value.iec958.status[2] = 0x00;
  1365 +
  1366 + /* use known values for that card: interface#1 altsetting#1 */
  1367 + iface = usb_ifnum_to_if(mixer->chip->dev, 1);
  1368 + alts = &iface->altsetting[1];
  1369 + ep = get_endpoint(alts, 0)->bEndpointAddress;
  1370 +
  1371 + err = snd_usb_ctl_msg(mixer->chip->dev,
  1372 + usb_rcvctrlpipe(mixer->chip->dev, 0),
  1373 + UAC_GET_CUR,
  1374 + USB_TYPE_CLASS | USB_RECIP_ENDPOINT | USB_DIR_IN,
  1375 + UAC_EP_CS_ATTR_SAMPLE_RATE << 8,
  1376 + ep,
  1377 + data,
  1378 + sizeof(data));
  1379 + if (err < 0)
  1380 + goto end;
  1381 +
  1382 + rate = data[0] | (data[1] << 8) | (data[2] << 16);
  1383 + ucontrol->value.iec958.status[3] = (rate == 48000) ?
  1384 + IEC958_AES3_CON_FS_48000 : IEC958_AES3_CON_FS_44100;
  1385 +
  1386 + err = 0;
  1387 +end:
  1388 + return err;
  1389 +}
  1390 +
  1391 +static int snd_microii_spdif_default_put(struct snd_kcontrol *kcontrol,
  1392 + struct snd_ctl_elem_value *ucontrol)
  1393 +{
  1394 + struct usb_mixer_interface *mixer = snd_kcontrol_chip(kcontrol);
  1395 + int err;
  1396 + u8 reg;
  1397 + unsigned long priv_backup = kcontrol->private_value;
  1398 +
  1399 + reg = ((ucontrol->value.iec958.status[1] & 0x0f) << 4) |
  1400 + (ucontrol->value.iec958.status[0] & 0x0f);
  1401 + err = snd_usb_ctl_msg(mixer->chip->dev,
  1402 + usb_sndctrlpipe(mixer->chip->dev, 0),
  1403 + UAC_SET_CUR,
  1404 + USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER,
  1405 + reg,
  1406 + 2,
  1407 + NULL,
  1408 + 0);
  1409 + if (err < 0)
  1410 + goto end;
  1411 +
  1412 + kcontrol->private_value &= 0xfffff0f0;
  1413 + kcontrol->private_value |= (ucontrol->value.iec958.status[1] & 0x0f) << 8;
  1414 + kcontrol->private_value |= (ucontrol->value.iec958.status[0] & 0x0f);
  1415 +
  1416 + reg = (ucontrol->value.iec958.status[0] & IEC958_AES0_NONAUDIO) ?
  1417 + 0xa0 : 0x20;
  1418 + reg |= (ucontrol->value.iec958.status[1] >> 4) & 0x0f;
  1419 + err = snd_usb_ctl_msg(mixer->chip->dev,
  1420 + usb_sndctrlpipe(mixer->chip->dev, 0),
  1421 + UAC_SET_CUR,
  1422 + USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER,
  1423 + reg,
  1424 + 3,
  1425 + NULL,
  1426 + 0);
  1427 + if (err < 0)
  1428 + goto end;
  1429 +
  1430 + kcontrol->private_value &= 0xffff0fff;
  1431 + kcontrol->private_value |= (ucontrol->value.iec958.status[1] & 0xf0) << 8;
  1432 +
  1433 + /* The frequency bits in AES3 cannot be set via register access. */
  1434 +
  1435 + /* Silently ignore any bits from the request that cannot be set. */
  1436 +
  1437 + err = (priv_backup != kcontrol->private_value);
  1438 +end:
  1439 + return err;
  1440 +}
  1441 +
  1442 +static int snd_microii_spdif_mask_get(struct snd_kcontrol *kcontrol,
  1443 + struct snd_ctl_elem_value *ucontrol)
  1444 +{
  1445 + ucontrol->value.iec958.status[0] = 0x0f;
  1446 + ucontrol->value.iec958.status[1] = 0xff;
  1447 + ucontrol->value.iec958.status[2] = 0x00;
  1448 + ucontrol->value.iec958.status[3] = 0x00;
  1449 +
  1450 + return 0;
  1451 +}
  1452 +
  1453 +static int snd_microii_spdif_switch_get(struct snd_kcontrol *kcontrol,
  1454 + struct snd_ctl_elem_value *ucontrol)
  1455 +{
  1456 + ucontrol->value.integer.value[0] = !(kcontrol->private_value & 0x02);
  1457 +
  1458 + return 0;
  1459 +}
  1460 +
  1461 +static int snd_microii_spdif_switch_put(struct snd_kcontrol *kcontrol,
  1462 + struct snd_ctl_elem_value *ucontrol)
  1463 +{
  1464 + struct usb_mixer_interface *mixer = snd_kcontrol_chip(kcontrol);
  1465 + int err;
  1466 + u8 reg = ucontrol->value.integer.value[0] ? 0x28 : 0x2a;
  1467 +
  1468 + err = snd_usb_ctl_msg(mixer->chip->dev,
  1469 + usb_sndctrlpipe(mixer->chip->dev, 0),
  1470 + UAC_SET_CUR,
  1471 + USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER,
  1472 + reg,
  1473 + 9,
  1474 + NULL,
  1475 + 0);
  1476 +
  1477 + if (!err) {
  1478 + err = (reg != (kcontrol->private_value & 0x0ff));
  1479 + if (err)
  1480 + kcontrol->private_value = reg;
  1481 + }
  1482 +
  1483 + return err;
  1484 +}
  1485 +
  1486 +static struct snd_kcontrol_new snd_microii_mixer_spdif[] = {
  1487 + {
  1488 + .iface = SNDRV_CTL_ELEM_IFACE_PCM,
  1489 + .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, DEFAULT),
  1490 + .info = snd_microii_spdif_info,
  1491 + .get = snd_microii_spdif_default_get,
  1492 + .put = snd_microii_spdif_default_put,
  1493 + .private_value = 0x00000100UL,/* reset value */
  1494 + },
  1495 + {
  1496 + .access = SNDRV_CTL_ELEM_ACCESS_READ,
  1497 + .iface = SNDRV_CTL_ELEM_IFACE_PCM,
  1498 + .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, MASK),
  1499 + .info = snd_microii_spdif_info,
  1500 + .get = snd_microii_spdif_mask_get,
  1501 + },
  1502 + {
  1503 + .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  1504 + .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, SWITCH),
  1505 + .info = snd_ctl_boolean_mono_info,
  1506 + .get = snd_microii_spdif_switch_get,
  1507 + .put = snd_microii_spdif_switch_put,
  1508 + .private_value = 0x00000028UL,/* reset value */
  1509 + }
  1510 +};
  1511 +
  1512 +static int snd_microii_controls_create(struct usb_mixer_interface *mixer)
  1513 +{
  1514 + int err, i;
  1515 +
  1516 + for (i = 0; i < ARRAY_SIZE(snd_microii_mixer_spdif); ++i) {
  1517 + err = snd_ctl_add(mixer->chip->card,
  1518 + snd_ctl_new1(&snd_microii_mixer_spdif[i], mixer));
  1519 + if (err < 0)
  1520 + return err;
  1521 + }
  1522 +
  1523 + return err;
  1524 +}
  1525 +
1318 1526 int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer)
1319 1527 {
1320 1528 int err = 0;
... ... @@ -1351,6 +1559,10 @@
1351 1559 case USB_ID(0x0b05, 0x1743): /* ASUS Xonar U1 (2) */
1352 1560 case USB_ID(0x0b05, 0x17a0): /* ASUS Xonar U3 */
1353 1561 err = snd_xonar_u1_controls_create(mixer);
  1562 + break;
  1563 +
  1564 + case USB_ID(0x0d8c, 0x0103): /* Audio Advantage Micro II */
  1565 + err = snd_microii_controls_create(mixer);
1354 1566 break;
1355 1567  
1356 1568 case USB_ID(0x17cc, 0x1011): /* Traktor Audio 6 */
sound/usb/quirks-table.h
... ... @@ -3119,5 +3119,17 @@
3119 3119 }
3120 3120 },
3121 3121  
  3122 +{
  3123 + /*
  3124 + * The original product_name is "USB Sound Device", however this name
  3125 + * is also used by the CM106 based cards, so make it unique.
  3126 + */
  3127 + USB_DEVICE(0x0d8c, 0x0103),
  3128 + .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) {
  3129 + .product_name = "Audio Advantage MicroII",
  3130 + .ifnum = QUIRK_NO_INTERFACE
  3131 + }
  3132 +},
  3133 +
3122 3134 #undef USB_DEVICE_VENDOR_SPEC