aboutsummaryrefslogtreecommitdiff
path: root/sound/usb
diff options
context:
space:
mode:
Diffstat (limited to 'sound/usb')
-rw-r--r--sound/usb/6fire/chip.c10
-rw-r--r--sound/usb/caiaq/audio.c10
-rw-r--r--sound/usb/caiaq/audio.h1
-rw-r--r--sound/usb/caiaq/device.c19
-rw-r--r--sound/usb/caiaq/input.c12
-rw-r--r--sound/usb/caiaq/input.h1
-rw-r--r--sound/usb/mixer.c61
-rw-r--r--sound/usb/mixer_quirks.c68
-rw-r--r--sound/usb/mixer_scarlett2.c220
-rw-r--r--sound/usb/quirks-table.h57
-rw-r--r--sound/usb/quirks.c31
-rw-r--r--sound/usb/usbaudio.h4
-rw-r--r--sound/usb/usx2y/us122l.c21
-rw-r--r--sound/usb/usx2y/us122l.h2
-rw-r--r--sound/usb/usx2y/usbusx2y.c2
15 files changed, 374 insertions, 145 deletions
diff --git a/sound/usb/6fire/chip.c b/sound/usb/6fire/chip.c
index 33e962178c93..d562a30b087f 100644
--- a/sound/usb/6fire/chip.c
+++ b/sound/usb/6fire/chip.c
@@ -61,8 +61,10 @@ static void usb6fire_chip_abort(struct sfire_chip *chip)
}
}
-static void usb6fire_chip_destroy(struct sfire_chip *chip)
+static void usb6fire_card_free(struct snd_card *card)
{
+ struct sfire_chip *chip = card->private_data;
+
if (chip) {
if (chip->pcm)
usb6fire_pcm_destroy(chip);
@@ -72,8 +74,6 @@ static void usb6fire_chip_destroy(struct sfire_chip *chip)
usb6fire_comm_destroy(chip);
if (chip->control)
usb6fire_control_destroy(chip);
- if (chip->card)
- snd_card_free(chip->card);
}
}
@@ -136,6 +136,7 @@ static int usb6fire_chip_probe(struct usb_interface *intf,
chip->regidx = regidx;
chip->intf_count = 1;
chip->card = card;
+ card->private_free = usb6fire_card_free;
ret = usb6fire_comm_init(chip);
if (ret < 0)
@@ -162,7 +163,7 @@ static int usb6fire_chip_probe(struct usb_interface *intf,
return 0;
destroy_chip:
- usb6fire_chip_destroy(chip);
+ snd_card_free(card);
return ret;
}
@@ -181,7 +182,6 @@ static void usb6fire_chip_disconnect(struct usb_interface *intf)
chip->shutdown = true;
usb6fire_chip_abort(chip);
- usb6fire_chip_destroy(chip);
}
}
}
diff --git a/sound/usb/caiaq/audio.c b/sound/usb/caiaq/audio.c
index 772c0ecb7077..05f964347ed6 100644
--- a/sound/usb/caiaq/audio.c
+++ b/sound/usb/caiaq/audio.c
@@ -858,14 +858,20 @@ int snd_usb_caiaq_audio_init(struct snd_usb_caiaqdev *cdev)
return 0;
}
-void snd_usb_caiaq_audio_free(struct snd_usb_caiaqdev *cdev)
+void snd_usb_caiaq_audio_disconnect(struct snd_usb_caiaqdev *cdev)
{
struct device *dev = caiaqdev_to_dev(cdev);
dev_dbg(dev, "%s(%p)\n", __func__, cdev);
stream_stop(cdev);
+}
+
+void snd_usb_caiaq_audio_free(struct snd_usb_caiaqdev *cdev)
+{
+ struct device *dev = caiaqdev_to_dev(cdev);
+
+ dev_dbg(dev, "%s(%p)\n", __func__, cdev);
free_urbs(cdev->data_urbs_in);
free_urbs(cdev->data_urbs_out);
kfree(cdev->data_cb_info);
}
-
diff --git a/sound/usb/caiaq/audio.h b/sound/usb/caiaq/audio.h
index 869bf6264d6a..07f5d064456c 100644
--- a/sound/usb/caiaq/audio.h
+++ b/sound/usb/caiaq/audio.h
@@ -3,6 +3,7 @@
#define CAIAQ_AUDIO_H
int snd_usb_caiaq_audio_init(struct snd_usb_caiaqdev *cdev);
+void snd_usb_caiaq_audio_disconnect(struct snd_usb_caiaqdev *cdev);
void snd_usb_caiaq_audio_free(struct snd_usb_caiaqdev *cdev);
#endif /* CAIAQ_AUDIO_H */
diff --git a/sound/usb/caiaq/device.c b/sound/usb/caiaq/device.c
index b5cbf1f195c4..dfd820483849 100644
--- a/sound/usb/caiaq/device.c
+++ b/sound/usb/caiaq/device.c
@@ -376,6 +376,17 @@ static void setup_card(struct snd_usb_caiaqdev *cdev)
dev_err(dev, "Unable to set up control system (ret=%d)\n", ret);
}
+static void card_free(struct snd_card *card)
+{
+ struct snd_usb_caiaqdev *cdev = caiaqdev(card);
+
+#ifdef CONFIG_SND_USB_CAIAQ_INPUT
+ snd_usb_caiaq_input_free(cdev);
+#endif
+ snd_usb_caiaq_audio_free(cdev);
+ usb_reset_device(cdev->chip.dev);
+}
+
static int create_card(struct usb_device *usb_dev,
struct usb_interface *intf,
struct snd_card **cardp)
@@ -489,6 +500,7 @@ static int init_card(struct snd_usb_caiaqdev *cdev)
cdev->vendor_name, cdev->product_name, usbpath);
setup_card(cdev);
+ card->private_free = card_free;
return 0;
err_kill_urb:
@@ -534,15 +546,14 @@ static void snd_disconnect(struct usb_interface *intf)
snd_card_disconnect(card);
#ifdef CONFIG_SND_USB_CAIAQ_INPUT
- snd_usb_caiaq_input_free(cdev);
+ snd_usb_caiaq_input_disconnect(cdev);
#endif
- snd_usb_caiaq_audio_free(cdev);
+ snd_usb_caiaq_audio_disconnect(cdev);
usb_kill_urb(&cdev->ep1_in_urb);
usb_kill_urb(&cdev->midi_out_urb);
- snd_card_free(card);
- usb_reset_device(interface_to_usbdev(intf));
+ snd_card_free_when_closed(card);
}
diff --git a/sound/usb/caiaq/input.c b/sound/usb/caiaq/input.c
index 84f26dce7f5d..a9130891bb69 100644
--- a/sound/usb/caiaq/input.c
+++ b/sound/usb/caiaq/input.c
@@ -829,15 +829,21 @@ exit_free_idev:
return ret;
}
-void snd_usb_caiaq_input_free(struct snd_usb_caiaqdev *cdev)
+void snd_usb_caiaq_input_disconnect(struct snd_usb_caiaqdev *cdev)
{
if (!cdev || !cdev->input_dev)
return;
usb_kill_urb(cdev->ep4_in_urb);
+ input_unregister_device(cdev->input_dev);
+}
+
+void snd_usb_caiaq_input_free(struct snd_usb_caiaqdev *cdev)
+{
+ if (!cdev || !cdev->input_dev)
+ return;
+
usb_free_urb(cdev->ep4_in_urb);
cdev->ep4_in_urb = NULL;
-
- input_unregister_device(cdev->input_dev);
cdev->input_dev = NULL;
}
diff --git a/sound/usb/caiaq/input.h b/sound/usb/caiaq/input.h
index c42891e7be88..fbe267f85d02 100644
--- a/sound/usb/caiaq/input.h
+++ b/sound/usb/caiaq/input.h
@@ -4,6 +4,7 @@
void snd_usb_caiaq_input_dispatch(struct snd_usb_caiaqdev *cdev, char *buf, unsigned int len);
int snd_usb_caiaq_input_init(struct snd_usb_caiaqdev *cdev);
+void snd_usb_caiaq_input_disconnect(struct snd_usb_caiaqdev *cdev);
void snd_usb_caiaq_input_free(struct snd_usb_caiaqdev *cdev);
#endif
diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c
index bd67027c7677..66976be06bc0 100644
--- a/sound/usb/mixer.c
+++ b/sound/usb/mixer.c
@@ -1084,6 +1084,21 @@ static void volume_control_quirks(struct usb_mixer_elem_info *cval,
struct snd_kcontrol *kctl)
{
struct snd_usb_audio *chip = cval->head.mixer->chip;
+
+ if (chip->quirk_flags & QUIRK_FLAG_MIC_RES_384) {
+ if (!strcmp(kctl->id.name, "Mic Capture Volume")) {
+ usb_audio_info(chip,
+ "set resolution quirk: cval->res = 384\n");
+ cval->res = 384;
+ }
+ } else if (chip->quirk_flags & QUIRK_FLAG_MIC_RES_16) {
+ if (!strcmp(kctl->id.name, "Mic Capture Volume")) {
+ usb_audio_info(chip,
+ "set resolution quirk: cval->res = 16\n");
+ cval->res = 16;
+ }
+ }
+
switch (chip->usb_id) {
case USB_ID(0x0763, 0x2030): /* M-Audio Fast Track C400 */
case USB_ID(0x0763, 0x2031): /* M-Audio Fast Track C600 */
@@ -1168,27 +1183,6 @@ static void volume_control_quirks(struct usb_mixer_elem_info *cval,
}
break;
- case USB_ID(0x046d, 0x0807): /* Logitech Webcam C500 */
- case USB_ID(0x046d, 0x0808):
- case USB_ID(0x046d, 0x0809):
- case USB_ID(0x046d, 0x0819): /* Logitech Webcam C210 */
- case USB_ID(0x046d, 0x081b): /* HD Webcam c310 */
- case USB_ID(0x046d, 0x081d): /* HD Webcam c510 */
- case USB_ID(0x046d, 0x0825): /* HD Webcam c270 */
- case USB_ID(0x046d, 0x0826): /* HD Webcam c525 */
- case USB_ID(0x046d, 0x08ca): /* Logitech Quickcam Fusion */
- case USB_ID(0x046d, 0x0991):
- case USB_ID(0x046d, 0x09a2): /* QuickCam Communicate Deluxe/S7500 */
- /* Most audio usb devices lie about volume resolution.
- * Most Logitech webcams have res = 384.
- * Probably there is some logitech magic behind this number --fishor
- */
- if (!strcmp(kctl->id.name, "Mic Capture Volume")) {
- usb_audio_info(chip,
- "set resolution quirk: cval->res = 384\n");
- cval->res = 384;
- }
- break;
case USB_ID(0x0495, 0x3042): /* ESS Technology Asus USB DAC */
if ((strstr(kctl->id.name, "Playback Volume") != NULL) ||
strstr(kctl->id.name, "Capture Volume") != NULL) {
@@ -1197,28 +1191,6 @@ static void volume_control_quirks(struct usb_mixer_elem_info *cval,
cval->res = 1;
}
break;
- case USB_ID(0x1224, 0x2a25): /* Jieli Technology USB PHY 2.0 */
- if (!strcmp(kctl->id.name, "Mic Capture Volume")) {
- usb_audio_info(chip,
- "set resolution quirk: cval->res = 16\n");
- cval->res = 16;
- }
- break;
- case USB_ID(0x1bcf, 0x2283): /* NexiGo N930AF FHD Webcam */
- case USB_ID(0x03f0, 0x654a): /* HP 320 FHD Webcam */
- if (!strcmp(kctl->id.name, "Mic Capture Volume")) {
- usb_audio_info(chip,
- "set resolution quirk: cval->res = 16\n");
- cval->res = 16;
- }
- break;
- case USB_ID(0x1bcf, 0x2281): /* HD Webcam */
- if (!strcmp(kctl->id.name, "Mic Capture Volume")) {
- usb_audio_info(chip,
- "set resolution quirk: cval->res = 16\n");
- cval->res = 16;
- }
- break;
}
}
@@ -2225,7 +2197,8 @@ static void build_mixer_unit_ctl(struct mixer_build *state,
len = get_term_name(state->chip, iterm, kctl->id.name,
sizeof(kctl->id.name), 0);
if (!len)
- len = sprintf(kctl->id.name, "Mixer Source %d", in_ch + 1);
+ snprintf(kctl->id.name, sizeof(kctl->id.name), "Mixer Source %d", in_ch + 1);
+
append_ctl_name(kctl, " Volume");
usb_audio_dbg(state->chip, "[%d] MU [%s] ch = %d, val = %d/%d\n",
diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c
index 6456e87e2f39..8bbf070b3676 100644
--- a/sound/usb/mixer_quirks.c
+++ b/sound/usb/mixer_quirks.c
@@ -3498,7 +3498,7 @@ static int snd_rme_digiface_controls_create(struct usb_mixer_interface *mixer)
}
/*
- * Pioneer DJ DJM Mixers
+ * Pioneer DJ / AlphaTheta DJM Mixers
*
* These devices generally have options for soft-switching the playback and
* capture sources in addition to the recording level. Although different
@@ -3515,17 +3515,23 @@ static int snd_rme_digiface_controls_create(struct usb_mixer_interface *mixer)
#define SND_DJM_CAP_CDLINE 0x01
#define SND_DJM_CAP_DIGITAL 0x02
#define SND_DJM_CAP_PHONO 0x03
+#define SND_DJM_CAP_PREFADER 0x05
#define SND_DJM_CAP_PFADER 0x06
#define SND_DJM_CAP_XFADERA 0x07
#define SND_DJM_CAP_XFADERB 0x08
#define SND_DJM_CAP_MIC 0x09
#define SND_DJM_CAP_AUX 0x0d
#define SND_DJM_CAP_RECOUT 0x0a
+#define SND_DJM_CAP_RECOUT_NOMIC 0x0e
#define SND_DJM_CAP_NONE 0x0f
#define SND_DJM_CAP_CH1PFADER 0x11
#define SND_DJM_CAP_CH2PFADER 0x12
#define SND_DJM_CAP_CH3PFADER 0x13
#define SND_DJM_CAP_CH4PFADER 0x14
+#define SND_DJM_CAP_CH1PREFADER 0x31
+#define SND_DJM_CAP_CH2PREFADER 0x32
+#define SND_DJM_CAP_CH3PREFADER 0x33
+#define SND_DJM_CAP_CH4PREFADER 0x34
// Playback types
#define SND_DJM_PB_CH1 0x00
@@ -3551,6 +3557,7 @@ static int snd_rme_digiface_controls_create(struct usb_mixer_interface *mixer)
#define SND_DJM_900NXS2_IDX 0x3
#define SND_DJM_750MK2_IDX 0x4
#define SND_DJM_450_IDX 0x5
+#define SND_DJM_A9_IDX 0x6
#define SND_DJM_CTL(_name, suffix, _default_value, _windex) { \
@@ -3579,7 +3586,7 @@ struct snd_djm_ctl {
u16 wIndex;
};
-static const char *snd_djm_get_label_caplevel(u16 wvalue)
+static const char *snd_djm_get_label_caplevel_common(u16 wvalue)
{
switch (wvalue) {
case 0x0000: return "-19dB";
@@ -3590,6 +3597,20 @@ static const char *snd_djm_get_label_caplevel(u16 wvalue)
}
};
+// The DJM-A9 has different capture levels than other, older models
+static const char *snd_djm_get_label_caplevel_a9(u16 wvalue)
+{
+ switch (wvalue) {
+ case 0x0000: return "+15dB";
+ case 0x0100: return "+12dB";
+ case 0x0200: return "+9dB";
+ case 0x0300: return "+6dB";
+ case 0x0400: return "+3dB";
+ case 0x0500: return "0dB";
+ default: return NULL;
+ }
+};
+
static const char *snd_djm_get_label_cap_common(u16 wvalue)
{
switch (wvalue & 0x00ff) {
@@ -3602,8 +3623,13 @@ static const char *snd_djm_get_label_cap_common(u16 wvalue)
case SND_DJM_CAP_XFADERB: return "Cross Fader B";
case SND_DJM_CAP_MIC: return "Mic";
case SND_DJM_CAP_RECOUT: return "Rec Out";
+ case SND_DJM_CAP_RECOUT_NOMIC: return "Rec Out without Mic";
case SND_DJM_CAP_AUX: return "Aux";
case SND_DJM_CAP_NONE: return "None";
+ case SND_DJM_CAP_CH1PREFADER: return "Pre Fader Ch1";
+ case SND_DJM_CAP_CH2PREFADER: return "Pre Fader Ch2";
+ case SND_DJM_CAP_CH3PREFADER: return "Pre Fader Ch3";
+ case SND_DJM_CAP_CH4PREFADER: return "Pre Fader Ch4";
case SND_DJM_CAP_CH1PFADER: return "Post Fader Ch1";
case SND_DJM_CAP_CH2PFADER: return "Post Fader Ch2";
case SND_DJM_CAP_CH3PFADER: return "Post Fader Ch3";
@@ -3623,6 +3649,14 @@ static const char *snd_djm_get_label_cap_850(u16 wvalue)
}
};
+static const char *snd_djm_get_label_caplevel(u8 device_idx, u16 wvalue)
+{
+ switch (device_idx) {
+ case SND_DJM_A9_IDX: return snd_djm_get_label_caplevel_a9(wvalue);
+ default: return snd_djm_get_label_caplevel_common(wvalue);
+ }
+};
+
static const char *snd_djm_get_label_cap(u8 device_idx, u16 wvalue)
{
switch (device_idx) {
@@ -3644,7 +3678,7 @@ static const char *snd_djm_get_label_pb(u16 wvalue)
static const char *snd_djm_get_label(u8 device_idx, u16 wvalue, u16 windex)
{
switch (windex) {
- case SND_DJM_WINDEX_CAPLVL: return snd_djm_get_label_caplevel(wvalue);
+ case SND_DJM_WINDEX_CAPLVL: return snd_djm_get_label_caplevel(device_idx, wvalue);
case SND_DJM_WINDEX_CAP: return snd_djm_get_label_cap(device_idx, wvalue);
case SND_DJM_WINDEX_PB: return snd_djm_get_label_pb(wvalue);
default: return NULL;
@@ -3653,7 +3687,7 @@ static const char *snd_djm_get_label(u8 device_idx, u16 wvalue, u16 windex)
// common DJM capture level option values
static const u16 snd_djm_opts_cap_level[] = {
- 0x0000, 0x0100, 0x0200, 0x0300 };
+ 0x0000, 0x0100, 0x0200, 0x0300, 0x400, 0x500 };
// DJM-250MK2
@@ -3795,6 +3829,28 @@ static const struct snd_djm_ctl snd_djm_ctls_750mk2[] = {
};
+// DJM-A9
+static const u16 snd_djm_opts_a9_cap1[] = {
+ 0x0107, 0x0108, 0x0109, 0x010a, 0x010e,
+ 0x111, 0x112, 0x113, 0x114, 0x0131, 0x132, 0x133, 0x134 };
+static const u16 snd_djm_opts_a9_cap2[] = {
+ 0x0201, 0x0202, 0x0203, 0x0205, 0x0206, 0x0207, 0x0208, 0x0209, 0x020a, 0x020e };
+static const u16 snd_djm_opts_a9_cap3[] = {
+ 0x0301, 0x0302, 0x0303, 0x0305, 0x0306, 0x0307, 0x0308, 0x0309, 0x030a, 0x030e };
+static const u16 snd_djm_opts_a9_cap4[] = {
+ 0x0401, 0x0402, 0x0403, 0x0405, 0x0406, 0x0407, 0x0408, 0x0409, 0x040a, 0x040e };
+static const u16 snd_djm_opts_a9_cap5[] = {
+ 0x0501, 0x0502, 0x0503, 0x0505, 0x0506, 0x0507, 0x0508, 0x0509, 0x050a, 0x050e };
+
+static const struct snd_djm_ctl snd_djm_ctls_a9[] = {
+ SND_DJM_CTL("Capture Level", cap_level, 0, SND_DJM_WINDEX_CAPLVL),
+ SND_DJM_CTL("Master Input", a9_cap1, 3, SND_DJM_WINDEX_CAP),
+ SND_DJM_CTL("Ch1 Input", a9_cap2, 2, SND_DJM_WINDEX_CAP),
+ SND_DJM_CTL("Ch2 Input", a9_cap3, 2, SND_DJM_WINDEX_CAP),
+ SND_DJM_CTL("Ch3 Input", a9_cap4, 2, SND_DJM_WINDEX_CAP),
+ SND_DJM_CTL("Ch4 Input", a9_cap5, 2, SND_DJM_WINDEX_CAP)
+};
+
static const struct snd_djm_device snd_djm_devices[] = {
[SND_DJM_250MK2_IDX] = SND_DJM_DEVICE(250mk2),
[SND_DJM_750_IDX] = SND_DJM_DEVICE(750),
@@ -3802,6 +3858,7 @@ static const struct snd_djm_device snd_djm_devices[] = {
[SND_DJM_900NXS2_IDX] = SND_DJM_DEVICE(900nxs2),
[SND_DJM_750MK2_IDX] = SND_DJM_DEVICE(750mk2),
[SND_DJM_450_IDX] = SND_DJM_DEVICE(450),
+ [SND_DJM_A9_IDX] = SND_DJM_DEVICE(a9),
};
@@ -4079,6 +4136,9 @@ int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer)
case USB_ID(0x2b73, 0x000a): /* Pioneer DJ DJM-900NXS2 */
err = snd_djm_controls_create(mixer, SND_DJM_900NXS2_IDX);
break;
+ case USB_ID(0x2b73, 0x003c): /* Pioneer DJ / AlphaTheta DJM-A9 */
+ err = snd_djm_controls_create(mixer, SND_DJM_A9_IDX);
+ break;
}
return err;
diff --git a/sound/usb/mixer_scarlett2.c b/sound/usb/mixer_scarlett2.c
index 4cddf84db631..7f595c1752a5 100644
--- a/sound/usb/mixer_scarlett2.c
+++ b/sound/usb/mixer_scarlett2.c
@@ -11,7 +11,7 @@
* - Clarett 2Pre/4Pre/8Pre USB
* - Clarett+ 2Pre/4Pre/8Pre
*
- * Copyright (c) 2018-2023 by Geoffrey D. Bennett <g at b4.vu>
+ * Copyright (c) 2018-2024 by Geoffrey D. Bennett <g at b4.vu>
* Copyright (c) 2020-2021 by Vladimir Sadovnikov <[email protected]>
* Copyright (c) 2022 by Christian Colglazier <[email protected]>
*
@@ -1079,6 +1079,9 @@ struct scarlett2_device_info {
/* minimum firmware version required */
u16 min_firmware_version;
+ /* has a downloadable device map */
+ u8 has_devmap;
+
/* support for main/alt speaker switching */
u8 has_speaker_switching;
@@ -1253,7 +1256,7 @@ struct scarlett2_data {
u8 phantom_switch[SCARLETT2_PHANTOM_SWITCH_MAX];
u8 phantom_persistence;
u8 input_select_switch;
- u8 input_link_switch[SCARLETT2_INPUT_GAIN_MAX / 2];
+ u8 input_link_switch[SCARLETT2_INPUT_GAIN_MAX];
u8 gain[SCARLETT2_INPUT_GAIN_MAX];
u8 autogain_switch[SCARLETT2_INPUT_GAIN_MAX];
u8 autogain_status[SCARLETT2_INPUT_GAIN_MAX];
@@ -1284,7 +1287,7 @@ struct scarlett2_data {
struct snd_kcontrol *input_mute_ctls[SCARLETT2_INPUT_MUTE_SWITCH_MAX];
struct snd_kcontrol *phantom_ctls[SCARLETT2_PHANTOM_SWITCH_MAX];
struct snd_kcontrol *input_select_ctl;
- struct snd_kcontrol *input_link_ctls[SCARLETT2_INPUT_GAIN_MAX / 2];
+ struct snd_kcontrol *input_link_ctls[SCARLETT2_INPUT_GAIN_MAX];
struct snd_kcontrol *input_gain_ctls[SCARLETT2_INPUT_GAIN_MAX];
struct snd_kcontrol *autogain_ctls[SCARLETT2_INPUT_GAIN_MAX];
struct snd_kcontrol *autogain_status_ctls[SCARLETT2_INPUT_GAIN_MAX];
@@ -1773,6 +1776,7 @@ static const struct scarlett2_device_info s18i20_gen3_info = {
static const struct scarlett2_device_info vocaster_one_info = {
.config_set = &scarlett2_config_set_vocaster,
.min_firmware_version = 1769,
+ .has_devmap = 1,
.phantom_count = 1,
.inputs_per_phantom = 1,
@@ -1815,6 +1819,7 @@ static const struct scarlett2_device_info vocaster_one_info = {
static const struct scarlett2_device_info vocaster_two_info = {
.config_set = &scarlett2_config_set_vocaster,
.min_firmware_version = 1769,
+ .has_devmap = 1,
.phantom_count = 2,
.inputs_per_phantom = 1,
@@ -1858,6 +1863,7 @@ static const struct scarlett2_device_info vocaster_two_info = {
static const struct scarlett2_device_info solo_gen4_info = {
.config_set = &scarlett2_config_set_gen4_solo,
.min_firmware_version = 2115,
+ .has_devmap = 1,
.level_input_count = 1,
.air_input_count = 1,
@@ -1912,6 +1918,7 @@ static const struct scarlett2_device_info solo_gen4_info = {
static const struct scarlett2_device_info s2i2_gen4_info = {
.config_set = &scarlett2_config_set_gen4_2i2,
.min_firmware_version = 2115,
+ .has_devmap = 1,
.level_input_count = 2,
.air_input_count = 2,
@@ -1966,6 +1973,7 @@ static const struct scarlett2_device_info s2i2_gen4_info = {
static const struct scarlett2_device_info s4i4_gen4_info = {
.config_set = &scarlett2_config_set_gen4_4i4,
.min_firmware_version = 2089,
+ .has_devmap = 1,
.level_input_count = 2,
.air_input_count = 2,
@@ -2264,6 +2272,8 @@ static int scarlett2_get_port_start_num(
#define SCARLETT2_USB_GET_DATA 0x00800000
#define SCARLETT2_USB_SET_DATA 0x00800001
#define SCARLETT2_USB_DATA_CMD 0x00800002
+#define SCARLETT2_USB_INFO_DEVMAP 0x0080000c
+#define SCARLETT2_USB_GET_DEVMAP 0x0080000d
#define SCARLETT2_USB_CONFIG_SAVE 6
@@ -2277,6 +2287,14 @@ static int scarlett2_get_port_start_num(
#define SCARLETT2_SEGMENT_SETTINGS_NAME "App_Settings"
#define SCARLETT2_SEGMENT_FIRMWARE_NAME "App_Upgrade"
+/* Gen 4 device firmware provides access to a base64-encoded
+ * zlib-compressed JSON description of the device's capabilities and
+ * configuration. This device map is made available in
+ * /proc/asound/cardX/device-map.json.zz.b64
+ */
+#define SCARLETT2_DEVMAP_BLOCK_SIZE 1024
+#define SCARLETT2_DEVMAP_FILENAME "device-map.json.zz.b64"
+
/* proprietary request/response format */
struct scarlett2_usb_packet {
__le32 cmd;
@@ -3409,7 +3427,7 @@ static int scarlett2_update_autogain(struct usb_mixer_interface *mixer)
private->num_autogain_status_texts - 1;
- for (int i = 0; i < SCARLETT2_AG_TARGET_COUNT; i++)
+ for (i = 0; i < SCARLETT2_AG_TARGET_COUNT; i++)
if (scarlett2_has_config_item(private,
scarlett2_ag_target_configs[i])) {
err = scarlett2_usb_get_config(
@@ -3420,7 +3438,7 @@ static int scarlett2_update_autogain(struct usb_mixer_interface *mixer)
}
/* convert from negative dBFS as used by the device */
- for (int i = 0; i < SCARLETT2_AG_TARGET_COUNT; i++)
+ for (i = 0; i < SCARLETT2_AG_TARGET_COUNT; i++)
private->ag_targets[i] = -ag_target_values[i];
return 0;
@@ -3439,7 +3457,7 @@ static void scarlett2_autogain_update_access(struct usb_mixer_interface *mixer)
scarlett2_set_ctl_access(private->input_select_ctl, val);
if (scarlett2_has_config_item(private,
SCARLETT2_CONFIG_INPUT_LINK_SWITCH))
- for (i = 0; i < info->gain_input_count / 2; i++)
+ for (i = 0; i < info->gain_input_count; i++)
scarlett2_set_ctl_access(private->input_link_ctls[i],
val);
for (i = 0; i < info->gain_input_count; i++)
@@ -3480,7 +3498,7 @@ static void scarlett2_autogain_notify_access(struct usb_mixer_interface *mixer)
&private->input_select_ctl->id);
if (scarlett2_has_config_item(private,
SCARLETT2_CONFIG_INPUT_LINK_SWITCH))
- for (i = 0; i < info->gain_input_count / 2; i++)
+ for (i = 0; i < info->gain_input_count; i++)
snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_INFO,
&private->input_link_ctls[i]->id);
for (i = 0; i < info->gain_input_count; i++)
@@ -3825,7 +3843,7 @@ static int scarlett2_update_input_select(struct usb_mixer_interface *mixer)
{
struct scarlett2_data *private = mixer->private_data;
const struct scarlett2_device_info *info = private->info;
- int link_count = info->gain_input_count / 2;
+ int link_count = info->gain_input_count;
int err;
private->input_select_updated = 0;
@@ -3847,10 +3865,6 @@ static int scarlett2_update_input_select(struct usb_mixer_interface *mixer)
if (err < 0)
return err;
- /* simplified because no model yet has link_count > 1 */
- if (private->input_link_switch[0])
- private->input_select_switch = 0;
-
return 0;
}
@@ -3887,9 +3901,9 @@ static int scarlett2_input_select_ctl_put(
struct usb_mixer_elem_info *elem = kctl->private_data;
struct usb_mixer_interface *mixer = elem->head.mixer;
struct scarlett2_data *private = mixer->private_data;
+ const struct scarlett2_device_info *info = private->info;
int oval, val, err;
- int max_val = private->input_link_switch[0] ? 0 : 1;
mutex_lock(&private->data_mutex);
@@ -3907,19 +3921,18 @@ static int scarlett2_input_select_ctl_put(
if (val < 0)
val = 0;
- else if (val > max_val)
- val = max_val;
+ else if (val >= info->gain_input_count)
+ val = info->gain_input_count - 1;
if (oval == val)
goto unlock;
private->input_select_switch = val;
- /* Send switch change to the device if inputs not linked */
- if (!private->input_link_switch[0])
- err = scarlett2_usb_set_config(
- mixer, SCARLETT2_CONFIG_INPUT_SELECT_SWITCH,
- 1, val);
+ /* Send new value to the device */
+ err = scarlett2_usb_set_config(
+ mixer, SCARLETT2_CONFIG_INPUT_SELECT_SWITCH,
+ 0, val);
if (err == 0)
err = 1;
@@ -3936,8 +3949,7 @@ static int scarlett2_input_select_ctl_info(
struct scarlett2_data *private = mixer->private_data;
int inputs = private->info->gain_input_count;
- int i, j;
- int err;
+ int i, err;
char **values = kcalloc(inputs, sizeof(char *), GFP_KERNEL);
if (!values)
@@ -3954,21 +3966,11 @@ static int scarlett2_input_select_ctl_info(
if (err < 0)
goto unlock;
- /* Loop through each input
- * Linked inputs have one value for the pair
- */
- for (i = 0, j = 0; i < inputs; i++) {
- if (private->input_link_switch[i / 2]) {
- values[j++] = kasprintf(
- GFP_KERNEL, "Input %d-%d", i + 1, i + 2);
- i++;
- } else {
- values[j++] = kasprintf(
- GFP_KERNEL, "Input %d", i + 1);
- }
- }
+ /* Loop through each input */
+ for (i = 0; i < inputs; i++)
+ values[i] = kasprintf(GFP_KERNEL, "Input %d", i + 1);
- err = snd_ctl_enum_info(uinfo, 1, j,
+ err = snd_ctl_enum_info(uinfo, 1, i,
(const char * const *)values);
unlock:
@@ -4077,18 +4079,8 @@ static int scarlett2_input_link_ctl_put(
private->input_link_switch[index] = val;
- /* Notify of change in input select options available */
- snd_ctl_notify(mixer->chip->card,
- SNDRV_CTL_EVENT_MASK_VALUE | SNDRV_CTL_EVENT_MASK_INFO,
- &private->input_select_ctl->id);
- private->input_select_updated = 1;
-
- /* Send switch change to the device
- * Link for channels 1-2 is at index 1
- * No device yet has more than 2 channels linked
- */
err = scarlett2_usb_set_config(
- mixer, SCARLETT2_CONFIG_INPUT_LINK_SWITCH, index + 1, val);
+ mixer, SCARLETT2_CONFIG_INPUT_LINK_SWITCH, index, val);
if (err == 0)
err = 1;
@@ -5385,6 +5377,8 @@ static int scarlett2_compressor_ctl_put(
int index = elem->control;
int channel = index / SCARLETT2_COMPRESSOR_PARAM_COUNT;
int param_index = index % SCARLETT2_COMPRESSOR_PARAM_COUNT;
+ const struct compressor_param *param = &compressor_params[param_index];
+
int oval, val, err;
s32 scaled_val;
@@ -5406,8 +5400,6 @@ static int scarlett2_compressor_ctl_put(
private->compressor_values[index] = val;
- const struct compressor_param *param = &compressor_params[param_index];
-
scaled_val = val << param->scale_bits;
/* Send change to the device */
@@ -6916,10 +6908,9 @@ static int scarlett2_add_line_in_ctls(struct usb_mixer_interface *mixer)
if (scarlett2_has_config_item(private,
SCARLETT2_CONFIG_INPUT_LINK_SWITCH)) {
- for (i = 0; i < info->gain_input_count / 2; i++) {
+ for (i = 0; i < info->gain_input_count; i++) {
scnprintf(s, sizeof(s),
- "Line In %d-%d Link Capture Switch",
- (i * 2) + 1, (i * 2) + 2);
+ "Line In %d Link Capture Switch", i + 1);
err = scarlett2_add_new_ctl(
mixer, &scarlett2_input_link_ctl,
i, 1, s, &private->input_link_ctls[i]);
@@ -8246,7 +8237,7 @@ static void scarlett2_notify_input_select(struct usb_mixer_interface *mixer)
SNDRV_CTL_EVENT_MASK_VALUE | SNDRV_CTL_EVENT_MASK_INFO,
&private->input_select_ctl->id);
- for (i = 0; i < info->gain_input_count / 2; i++)
+ for (i = 0; i < info->gain_input_count; i++)
snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE,
&private->input_link_ctls[i]->id);
}
@@ -9518,7 +9509,7 @@ static long scarlett2_hwdep_write(struct snd_hwdep *hw,
SCARLETT2_FLASH_BLOCK_SIZE;
if (count < 0 || *offset < 0 || *offset + count >= flash_size)
- return -EINVAL;
+ return -ENOSPC;
if (!count)
return 0;
@@ -9591,6 +9582,116 @@ static int scarlett2_hwdep_init(struct usb_mixer_interface *mixer)
return 0;
}
+/*** device-map file ***/
+
+static ssize_t scarlett2_devmap_read(
+ struct snd_info_entry *entry,
+ void *file_private_data,
+ struct file *file,
+ char __user *buf,
+ size_t count,
+ loff_t pos)
+{
+ struct usb_mixer_interface *mixer = entry->private_data;
+ u8 *resp_buf;
+ const size_t block_size = SCARLETT2_DEVMAP_BLOCK_SIZE;
+ size_t copied = 0;
+
+ if (pos >= entry->size)
+ return 0;
+
+ if (pos + count > entry->size)
+ count = entry->size - pos;
+
+ resp_buf = kmalloc(block_size, GFP_KERNEL);
+ if (!resp_buf)
+ return -ENOMEM;
+
+ while (count > 0) {
+ /* SCARLETT2_USB_GET_DEVMAP reads only on block boundaries,
+ * so we need to read a whole block and copy the requested
+ * chunk to userspace.
+ */
+
+ __le32 req;
+ int err;
+
+ /* offset within the block that we're reading */
+ size_t offset = pos % block_size;
+
+ /* read_size is block_size except for the last block */
+ size_t block_start = pos - offset;
+ size_t read_size = min_t(size_t,
+ block_size,
+ entry->size - block_start);
+
+ /* size of the chunk to copy to userspace */
+ size_t copy_size = min_t(size_t, count, read_size - offset);
+
+ /* request the block */
+ req = cpu_to_le32(pos / block_size);
+ err = scarlett2_usb(mixer, SCARLETT2_USB_GET_DEVMAP,
+ &req, sizeof(req), resp_buf, read_size);
+ if (err < 0) {
+ kfree(resp_buf);
+ return copied ? copied : err;
+ }
+
+ if (copy_to_user(buf, resp_buf + offset, copy_size)) {
+ kfree(resp_buf);
+ return -EFAULT;
+ }
+
+ buf += copy_size;
+ pos += copy_size;
+ copied += copy_size;
+ count -= copy_size;
+ }
+
+ kfree(resp_buf);
+ return copied;
+}
+
+static const struct snd_info_entry_ops scarlett2_devmap_ops = {
+ .read = scarlett2_devmap_read,
+};
+
+static int scarlett2_devmap_init(struct usb_mixer_interface *mixer)
+{
+ struct snd_card *card = mixer->chip->card;
+ struct scarlett2_data *private = mixer->private_data;
+ const struct scarlett2_device_info *info = private->info;
+ __le16 config_len_buf[2];
+ int config_len;
+ struct snd_info_entry *entry;
+ int err;
+
+ /* If the device doesn't support the DEVMAP commands, don't
+ * create the /proc/asound/cardX/scarlett.json.zlib entry
+ */
+ if (!info->has_devmap)
+ return 0;
+
+ err = scarlett2_usb(mixer, SCARLETT2_USB_INFO_DEVMAP,
+ NULL, 0, &config_len_buf, sizeof(config_len_buf));
+ if (err < 0)
+ return err;
+
+ config_len = le16_to_cpu(config_len_buf[1]);
+
+ err = snd_card_proc_new(card, SCARLETT2_DEVMAP_FILENAME, &entry);
+ if (err < 0)
+ return err;
+
+ entry->content = SNDRV_INFO_CONTENT_DATA;
+ entry->private_data = mixer;
+ entry->c.ops = &scarlett2_devmap_ops;
+ entry->size = config_len;
+ entry->mode = S_IFREG | 0444;
+
+ return 0;
+}
+
int snd_scarlett2_init(struct usb_mixer_interface *mixer)
{
struct snd_usb_audio *chip = mixer->chip;
@@ -9641,11 +9742,20 @@ int snd_scarlett2_init(struct usb_mixer_interface *mixer)
}
err = scarlett2_hwdep_init(mixer);
- if (err < 0)
+ if (err < 0) {
usb_audio_err(mixer->chip,
"Error creating %s hwdep device: %d",
entry->series_name,
err);
+ return err;
+ }
+
+ err = scarlett2_devmap_init(mixer);
+ if (err < 0)
+ usb_audio_err(mixer->chip,
+ "Error creating %s devmap entry: %d",
+ entry->series_name,
+ err);
return err;
}
diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h
index 199d0603cf8e..c49383e64678 100644
--- a/sound/usb/quirks-table.h
+++ b/sound/usb/quirks-table.h
@@ -3131,6 +3131,63 @@ YAMAHA_DEVICE(0x7010, "UB99"),
}
},
+{
+ /*
+ * Pioneer DJ / AlphaTheta DJM-A9
+ * 10 channels playback & 12 channels capture @ 44.1/48/96kHz S24LE
+ */
+ USB_DEVICE_VENDOR_SPEC(0x2b73, 0x003c),
+ QUIRK_DRIVER_INFO {
+ QUIRK_DATA_COMPOSITE {
+ {
+ QUIRK_DATA_AUDIOFORMAT(0) {
+ .formats = SNDRV_PCM_FMTBIT_S24_3LE,
+ .channels = 10,
+ .iface = 0,
+ .altsetting = 1,
+ .altset_idx = 1,
+ .endpoint = 0x01,
+ .ep_attr = USB_ENDPOINT_XFER_ISOC|
+ USB_ENDPOINT_SYNC_ASYNC,
+ .rates = SNDRV_PCM_RATE_44100|
+ SNDRV_PCM_RATE_48000|
+ SNDRV_PCM_RATE_96000,
+ .rate_min = 44100,
+ .rate_max = 96000,
+ .nr_rates = 3,
+ .rate_table = (unsigned int[]) {
+ 44100, 48000, 96000
+ }
+ }
+ },
+ {
+ QUIRK_DATA_AUDIOFORMAT(0) {
+ .formats = SNDRV_PCM_FMTBIT_S24_3LE,
+ .channels = 12,
+ .iface = 0,
+ .altsetting = 1,
+ .altset_idx = 1,
+ .endpoint = 0x82,
+ .ep_idx = 1,
+ .ep_attr = USB_ENDPOINT_XFER_ISOC|
+ USB_ENDPOINT_SYNC_ASYNC|
+ USB_ENDPOINT_USAGE_IMPLICIT_FB,
+ .rates = SNDRV_PCM_RATE_44100|
+ SNDRV_PCM_RATE_48000|
+ SNDRV_PCM_RATE_96000,
+ .rate_min = 44100,
+ .rate_max = 96000,
+ .nr_rates = 3,
+ .rate_table = (unsigned int[]) {
+ 44100, 48000, 96000
+ }
+ }
+ },
+ QUIRK_COMPOSITE_END
+ }
+ }
+},
+
/*
* MacroSilicon MS2100/MS2106 based AV capture cards
*
diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c
index c5fd180357d1..cbfbb064a9c2 100644
--- a/sound/usb/quirks.c
+++ b/sound/usb/quirks.c
@@ -2115,7 +2115,7 @@ struct usb_audio_quirk_flags_table {
static const struct usb_audio_quirk_flags_table quirk_flags_table[] = {
/* Device matches */
DEVICE_FLG(0x03f0, 0x654a, /* HP 320 FHD Webcam */
- QUIRK_FLAG_GET_SAMPLE_RATE),
+ QUIRK_FLAG_GET_SAMPLE_RATE | QUIRK_FLAG_MIC_RES_16),
DEVICE_FLG(0x041e, 0x3000, /* Creative SB Extigy */
QUIRK_FLAG_IGNORE_CTL_ERROR),
DEVICE_FLG(0x041e, 0x4080, /* Creative Live Cam VF0610 */
@@ -2123,10 +2123,31 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = {
DEVICE_FLG(0x045e, 0x083c, /* MS USB Link headset */
QUIRK_FLAG_GET_SAMPLE_RATE | QUIRK_FLAG_CTL_MSG_DELAY |
QUIRK_FLAG_DISABLE_AUTOSUSPEND),
+ DEVICE_FLG(0x046d, 0x0807, /* Logitech Webcam C500 */
+ QUIRK_FLAG_CTL_MSG_DELAY_1M | QUIRK_FLAG_MIC_RES_384),
+ DEVICE_FLG(0x046d, 0x0808, /* Logitech Webcam C600 */
+ QUIRK_FLAG_CTL_MSG_DELAY_1M | QUIRK_FLAG_MIC_RES_384),
+ DEVICE_FLG(0x046d, 0x0809,
+ QUIRK_FLAG_CTL_MSG_DELAY_1M | QUIRK_FLAG_MIC_RES_384),
+ DEVICE_FLG(0x046d, 0x0819, /* Logitech Webcam C210 */
+ QUIRK_FLAG_CTL_MSG_DELAY_1M | QUIRK_FLAG_MIC_RES_384),
+ DEVICE_FLG(0x046d, 0x081b, /* HD Webcam c310 */
+ QUIRK_FLAG_CTL_MSG_DELAY_1M | QUIRK_FLAG_MIC_RES_384),
+ DEVICE_FLG(0x046d, 0x081d, /* HD Webcam c510 */
+ QUIRK_FLAG_CTL_MSG_DELAY_1M | QUIRK_FLAG_MIC_RES_384),
+ DEVICE_FLG(0x046d, 0x0825, /* HD Webcam c270 */
+ QUIRK_FLAG_CTL_MSG_DELAY_1M | QUIRK_FLAG_MIC_RES_384),
+ DEVICE_FLG(0x046d, 0x0826, /* HD Webcam c525 */
+ QUIRK_FLAG_CTL_MSG_DELAY_1M | QUIRK_FLAG_MIC_RES_384),
DEVICE_FLG(0x046d, 0x084c, /* Logitech ConferenceCam Connect */
QUIRK_FLAG_GET_SAMPLE_RATE | QUIRK_FLAG_CTL_MSG_DELAY_1M),
+ DEVICE_FLG(0x046d, 0x08ca, /* Logitech Quickcam Fusion */
+ QUIRK_FLAG_CTL_MSG_DELAY_1M | QUIRK_FLAG_MIC_RES_384),
DEVICE_FLG(0x046d, 0x0991, /* Logitech QuickCam Pro */
- QUIRK_FLAG_CTL_MSG_DELAY_1M | QUIRK_FLAG_IGNORE_CTL_ERROR),
+ QUIRK_FLAG_CTL_MSG_DELAY_1M | QUIRK_FLAG_IGNORE_CTL_ERROR |
+ QUIRK_FLAG_MIC_RES_384),
+ DEVICE_FLG(0x046d, 0x09a2, /* QuickCam Communicate Deluxe/S7500 */
+ QUIRK_FLAG_CTL_MSG_DELAY_1M | QUIRK_FLAG_MIC_RES_384),
DEVICE_FLG(0x046d, 0x09a4, /* Logitech QuickCam E 3500 */
QUIRK_FLAG_CTL_MSG_DELAY_1M | QUIRK_FLAG_IGNORE_CTL_ERROR),
DEVICE_FLG(0x0499, 0x1509, /* Steinberg UR22 */
@@ -2194,7 +2215,7 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = {
DEVICE_FLG(0x0fd9, 0x0008, /* Hauppauge HVR-950Q */
QUIRK_FLAG_SHARE_MEDIA_DEVICE | QUIRK_FLAG_ALIGN_TRANSFER),
DEVICE_FLG(0x1224, 0x2a25, /* Jieli Technology USB PHY 2.0 */
- QUIRK_FLAG_GET_SAMPLE_RATE),
+ QUIRK_FLAG_GET_SAMPLE_RATE | QUIRK_FLAG_MIC_RES_16),
DEVICE_FLG(0x1395, 0x740a, /* Sennheiser DECT */
QUIRK_FLAG_GET_SAMPLE_RATE),
DEVICE_FLG(0x1397, 0x0507, /* Behringer UMC202HD */
@@ -2232,9 +2253,9 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = {
DEVICE_FLG(0x19f7, 0x0035, /* RODE NT-USB+ */
QUIRK_FLAG_GET_SAMPLE_RATE),
DEVICE_FLG(0x1bcf, 0x2281, /* HD Webcam */
- QUIRK_FLAG_GET_SAMPLE_RATE),
+ QUIRK_FLAG_GET_SAMPLE_RATE | QUIRK_FLAG_MIC_RES_16),
DEVICE_FLG(0x1bcf, 0x2283, /* NexiGo N930AF FHD Webcam */
- QUIRK_FLAG_GET_SAMPLE_RATE),
+ QUIRK_FLAG_GET_SAMPLE_RATE | QUIRK_FLAG_MIC_RES_16),
DEVICE_FLG(0x2040, 0x7200, /* Hauppauge HVR-950Q */
QUIRK_FLAG_SHARE_MEDIA_DEVICE | QUIRK_FLAG_ALIGN_TRANSFER),
DEVICE_FLG(0x2040, 0x7201, /* Hauppauge HVR-950Q-MXL */
diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h
index b0f042c99608..158ec053dc44 100644
--- a/sound/usb/usbaudio.h
+++ b/sound/usb/usbaudio.h
@@ -194,6 +194,8 @@ extern bool snd_usb_skip_validation;
* QUIRK_FLAG_FIXED_RATE
* Do not set PCM rate (frequency) when only one rate is available
* for the given endpoint.
+ * QUIRK_FLAG_MIC_RES_16 and QUIRK_FLAG_MIC_RES_384
+ * Set the fixed resolution for Mic Capture Volume (mostly for webcams)
*/
#define QUIRK_FLAG_GET_SAMPLE_RATE (1U << 0)
@@ -218,5 +220,7 @@ extern bool snd_usb_skip_validation;
#define QUIRK_FLAG_IFACE_SKIP_CLOSE (1U << 19)
#define QUIRK_FLAG_FORCE_IFACE_RESET (1U << 20)
#define QUIRK_FLAG_FIXED_RATE (1U << 21)
+#define QUIRK_FLAG_MIC_RES_16 (1U << 22)
+#define QUIRK_FLAG_MIC_RES_384 (1U << 23)
#endif /* __USBAUDIO_H */
diff --git a/sound/usb/usx2y/us122l.c b/sound/usb/usx2y/us122l.c
index 1be0e980feb9..6bcf8b859ebb 100644
--- a/sound/usb/usx2y/us122l.c
+++ b/sound/usb/usx2y/us122l.c
@@ -89,13 +89,6 @@ static void pt_info_set(struct usb_device *dev, u8 v)
v, 0, NULL, 0, 1000, GFP_NOIO);
}
-static void usb_stream_hwdep_vm_open(struct vm_area_struct *area)
-{
- struct us122l *us122l = area->vm_private_data;
-
- atomic_inc(&us122l->mmap_count);
-}
-
static vm_fault_t usb_stream_hwdep_vm_fault(struct vm_fault *vmf)
{
unsigned long offset;
@@ -132,17 +125,9 @@ unlock:
return VM_FAULT_SIGBUS;
}
-static void usb_stream_hwdep_vm_close(struct vm_area_struct *area)
-{
- struct us122l *us122l = area->vm_private_data;
-
- atomic_dec(&us122l->mmap_count);
-}
static const struct vm_operations_struct usb_stream_hwdep_vm_ops = {
- .open = usb_stream_hwdep_vm_open,
.fault = usb_stream_hwdep_vm_fault,
- .close = usb_stream_hwdep_vm_close,
};
static int usb_stream_hwdep_open(struct snd_hwdep *hw, struct file *file)
@@ -218,7 +203,6 @@ static int usb_stream_hwdep_mmap(struct snd_hwdep *hw,
if (!read)
vm_flags_set(area, VM_DONTEXPAND);
area->vm_private_data = us122l;
- atomic_inc(&us122l->mmap_count);
out:
mutex_unlock(&us122l->mutex);
return err;
@@ -606,10 +590,7 @@ static void snd_us122l_disconnect(struct usb_interface *intf)
usb_put_intf(usb_ifnum_to_if(us122l->dev, 1));
usb_put_dev(us122l->dev);
- while (atomic_read(&us122l->mmap_count))
- msleep(500);
-
- snd_card_free(card);
+ snd_card_free_when_closed(card);
}
static int snd_us122l_suspend(struct usb_interface *intf, pm_message_t message)
diff --git a/sound/usb/usx2y/us122l.h b/sound/usb/usx2y/us122l.h
index c32ae5e981e9..8e59b78d3514 100644
--- a/sound/usb/usx2y/us122l.h
+++ b/sound/usb/usx2y/us122l.h
@@ -16,8 +16,6 @@ struct us122l {
struct file *slave;
struct list_head midi_list;
- atomic_t mmap_count;
-
bool is_us144;
};
diff --git a/sound/usb/usx2y/usbusx2y.c b/sound/usb/usx2y/usbusx2y.c
index 2f9cede242b3..5f81c68fd42b 100644
--- a/sound/usb/usx2y/usbusx2y.c
+++ b/sound/usb/usx2y/usbusx2y.c
@@ -422,7 +422,7 @@ static void snd_usx2y_disconnect(struct usb_interface *intf)
}
if (usx2y->us428ctls_sharedmem)
wake_up(&usx2y->us428ctls_wait_queue_head);
- snd_card_free(card);
+ snd_card_free_when_closed(card);
}
static int snd_usx2y_probe(struct usb_interface *intf,