diff options
| -rw-r--r-- | sound/usb/mixer_quirks.c | 212 | ||||
| -rw-r--r-- | sound/usb/quirks-table.h | 12 |
2 files changed, 224 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 | */ | ||
| 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 | int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer) | 1526 | int 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, |
diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h index 9c636c2d99f6..f5f0595ef9c7 100644 --- a/sound/usb/quirks-table.h +++ b/sound/usb/quirks-table.h | |||
| @@ -3119,4 +3119,16 @@ YAMAHA_DEVICE(0x7010, "UB99"), | |||
| 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 | #undef USB_DEVICE_VENDOR_SPEC | 3134 | #undef USB_DEVICE_VENDOR_SPEC |
