aboutsummaryrefslogtreecommitdiffstats
path: root/sound/usb/mixer_quirks.c
diff options
context:
space:
mode:
authorPrzemek Rudy <prudy1@o2.pl>2013-06-27 17:52:33 -0400
committerTakashi Iwai <tiwai@suse.de>2013-06-28 07:37:12 -0400
commit066624c6a1733a72a67f1d06d35a2153e7d9082b (patch)
tree03f63fc387e78592968a1f04ee4e173ca32fec20 /sound/usb/mixer_quirks.c
parentaccaf69da1d1e64bd77ac0caad77e4cfc3b654c7 (diff)
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>
Diffstat (limited to 'sound/usb/mixer_quirks.c')
-rw-r--r--sound/usb/mixer_quirks.c212
1 files changed, 212 insertions, 0 deletions
diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c
index ebe91440a068..d42a584cf829 100644
--- a/sound/usb/mixer_quirks.c
+++ b/sound/usb/mixer_quirks.c
@@ -9,6 +9,8 @@
9 * Alan Cox (alan@lxorguk.ukuu.org.uk) 9 * Alan Cox (alan@lxorguk.ukuu.org.uk)
10 * Thomas Sailer (sailer@ife.ee.ethz.ch) 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 * This program is free software; you can redistribute it and/or modify 15 * 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 16 * it under the terms of the GNU General Public License as published by
@@ -30,6 +32,7 @@
30#include <linux/usb.h> 32#include <linux/usb.h>
31#include <linux/usb/audio.h> 33#include <linux/usb/audio.h>
32 34
35#include <sound/asoundef.h>
33#include <sound/core.h> 36#include <sound/core.h>
34#include <sound/control.h> 37#include <sound/control.h>
35#include <sound/hwdep.h> 38#include <sound/hwdep.h>
@@ -1315,6 +1318,211 @@ static struct std_mono_table ebox44_table[] = {
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 */
1343static 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
1351static 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;
1387end:
1388 return err;
1389}
1390
1391static 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);
1438end:
1439 return err;
1440}
1441
1442static 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
1453static 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
1461static 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
1486static 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
1512static 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
1318int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer) 1526int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer)
1319{ 1527{
1320 int err = 0; 1528 int err = 0;
@@ -1353,6 +1561,10 @@ int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer)
1353 err = snd_xonar_u1_controls_create(mixer); 1561 err = snd_xonar_u1_controls_create(mixer);
1354 break; 1562 break;
1355 1563
1564 case USB_ID(0x0d8c, 0x0103): /* Audio Advantage Micro II */
1565 err = snd_microii_controls_create(mixer);
1566 break;
1567
1356 case USB_ID(0x17cc, 0x1011): /* Traktor Audio 6 */ 1568 case USB_ID(0x17cc, 0x1011): /* Traktor Audio 6 */
1357 err = snd_nativeinstruments_create_mixer(mixer, 1569 err = snd_nativeinstruments_create_mixer(mixer,
1358 snd_nativeinstruments_ta6_mixers, 1570 snd_nativeinstruments_ta6_mixers,