aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sound/drivers/vx/vx_core.c2
-rw-r--r--sound/pci/hda/hda_jack.c73
-rw-r--r--sound/pci/hda/hda_jack.h8
-rw-r--r--sound/pci/hda/patch_realtek.c15
-rw-r--r--sound/pci/mixart/mixart_hwdep.c3
-rw-r--r--sound/pci/vx222/vx222_ops.c10
-rw-r--r--sound/ppc/snd_ps3_reg.h2
-rw-r--r--sound/usb/midi.c123
-rw-r--r--sound/usb/midi.h2
-rw-r--r--sound/usb/mixer_quirks.c60
-rw-r--r--sound/usb/quirks-table.h63
-rw-r--r--sound/usb/quirks.c3
12 files changed, 321 insertions, 43 deletions
diff --git a/sound/drivers/vx/vx_core.c b/sound/drivers/vx/vx_core.c
index d5c65cab195b..a22e5b1a5458 100644
--- a/sound/drivers/vx/vx_core.c
+++ b/sound/drivers/vx/vx_core.c
@@ -402,7 +402,7 @@ int vx_send_rih(struct vx_core *chip, int cmd)
#define END_OF_RESET_WAIT_TIME 500 /* us */
/**
- * snd_vx_boot_xilinx - boot up the xilinx interface
+ * snd_vx_load_boot_image - boot up the xilinx interface
* @chip: VX core instance
* @boot: the boot record to load
*/
diff --git a/sound/pci/hda/hda_jack.c b/sound/pci/hda/hda_jack.c
index ac00866d8032..f29975e3e98d 100644
--- a/sound/pci/hda/hda_jack.c
+++ b/sound/pci/hda/hda_jack.c
@@ -389,6 +389,69 @@ int snd_hda_jack_set_gating_jack(struct hda_codec *codec, hda_nid_t gated_nid,
EXPORT_SYMBOL_GPL(snd_hda_jack_set_gating_jack);
/**
+ * snd_hda_jack_bind_keymap - bind keys generated from one NID to another jack.
+ * @codec: the HDA codec
+ * @key_nid: key event is generated by this pin NID
+ * @keymap: map of key type and key code
+ * @jack_nid: key reports to the jack of this pin NID
+ *
+ * This function is used in the case of key is generated from one NID while is
+ * reported to the jack of another NID.
+ */
+int snd_hda_jack_bind_keymap(struct hda_codec *codec, hda_nid_t key_nid,
+ const struct hda_jack_keymap *keymap,
+ hda_nid_t jack_nid)
+{
+ const struct hda_jack_keymap *map;
+ struct hda_jack_tbl *key_gen = snd_hda_jack_tbl_get(codec, key_nid);
+ struct hda_jack_tbl *report_to = snd_hda_jack_tbl_get(codec, jack_nid);
+
+ WARN_ON(codec->dp_mst);
+
+ if (!key_gen || !report_to || !report_to->jack)
+ return -EINVAL;
+
+ key_gen->key_report_jack = jack_nid;
+
+ if (keymap)
+ for (map = keymap; map->type; map++)
+ snd_jack_set_key(report_to->jack, map->type, map->key);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(snd_hda_jack_bind_keymap);
+
+/**
+ * snd_hda_jack_set_button_state - report button event to the hda_jack_tbl button_state.
+ * @codec: the HDA codec
+ * @jack_nid: the button event reports to the jack_tbl of this NID
+ * @button_state: the button event captured by codec
+ *
+ * Codec driver calls this function to report the button event.
+ */
+void snd_hda_jack_set_button_state(struct hda_codec *codec, hda_nid_t jack_nid,
+ int button_state)
+{
+ struct hda_jack_tbl *jack = snd_hda_jack_tbl_get(codec, jack_nid);
+
+ if (!jack)
+ return;
+
+ if (jack->key_report_jack) {
+ struct hda_jack_tbl *report_to =
+ snd_hda_jack_tbl_get(codec, jack->key_report_jack);
+
+ if (report_to) {
+ report_to->button_state = button_state;
+ return;
+ }
+ }
+
+ jack->button_state = button_state;
+}
+EXPORT_SYMBOL_GPL(snd_hda_jack_set_button_state);
+
+/**
* snd_hda_jack_report_sync - sync the states of all jacks and report if changed
* @codec: the HDA codec
*/
@@ -651,7 +714,15 @@ void snd_hda_jack_unsol_event(struct hda_codec *codec, unsigned int res)
}
if (!event)
return;
- event->jack_dirty = 1;
+
+ if (event->key_report_jack) {
+ struct hda_jack_tbl *report_to =
+ snd_hda_jack_tbl_get_mst(codec, event->key_report_jack,
+ event->dev_id);
+ if (report_to)
+ report_to->jack_dirty = 1;
+ } else
+ event->jack_dirty = 1;
call_jack_callback(codec, res, event);
snd_hda_jack_report_sync(codec);
diff --git a/sound/pci/hda/hda_jack.h b/sound/pci/hda/hda_jack.h
index 8ceaf0ef5df1..2abf7aac243a 100644
--- a/sound/pci/hda/hda_jack.h
+++ b/sound/pci/hda/hda_jack.h
@@ -40,6 +40,7 @@ struct hda_jack_tbl {
unsigned int block_report:1; /* in a transitional state - do not report to userspace */
hda_nid_t gating_jack; /* valid when gating jack plugged */
hda_nid_t gated_jack; /* gated is dependent on this jack */
+ hda_nid_t key_report_jack; /* key reports to this jack */
int type;
int button_state;
struct snd_jack *jack;
@@ -99,6 +100,13 @@ snd_hda_jack_detect_enable_callback(struct hda_codec *codec, hda_nid_t nid,
int snd_hda_jack_set_gating_jack(struct hda_codec *codec, hda_nid_t gated_nid,
hda_nid_t gating_nid);
+int snd_hda_jack_bind_keymap(struct hda_codec *codec, hda_nid_t key_nid,
+ const struct hda_jack_keymap *keymap,
+ hda_nid_t jack_nid);
+
+void snd_hda_jack_set_button_state(struct hda_codec *codec, hda_nid_t jack_nid,
+ int button_state);
+
u32 snd_hda_jack_pin_sense(struct hda_codec *codec, hda_nid_t nid, int dev_id);
/* the jack state returned from snd_hda_jack_detect_state() */
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index b47504fa8dfd..c2ae077bd010 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -3103,7 +3103,7 @@ static void alc_headset_btn_callback(struct hda_codec *codec,
if (jack->unsol_res & (7 << 10))
report |= SND_JACK_BTN_3;
- jack->jack->button_state = report;
+ snd_hda_jack_set_button_state(codec, jack->nid, report);
}
static void alc_disable_headset_jack_key(struct hda_codec *codec)
@@ -3164,16 +3164,23 @@ static void alc_fixup_headset_jack(struct hda_codec *codec,
const struct hda_fixup *fix, int action)
{
struct alc_spec *spec = codec->spec;
+ hda_nid_t hp_pin;
switch (action) {
case HDA_FIXUP_ACT_PRE_PROBE:
spec->has_hs_key = 1;
snd_hda_jack_detect_enable_callback(codec, 0x55,
alc_headset_btn_callback);
- snd_hda_jack_add_kctl(codec, 0x55, "Headset Jack", false,
- SND_JACK_HEADSET, alc_headset_btn_keymap);
break;
- case HDA_FIXUP_ACT_INIT:
+ case HDA_FIXUP_ACT_BUILD:
+ hp_pin = alc_get_hp_pin(spec);
+ if (!hp_pin || snd_hda_jack_bind_keymap(codec, 0x55,
+ alc_headset_btn_keymap,
+ hp_pin))
+ snd_hda_jack_add_kctl(codec, 0x55, "Headset Jack",
+ false, SND_JACK_HEADSET,
+ alc_headset_btn_keymap);
+
alc_enable_headset_jack_key(codec);
break;
}
diff --git a/sound/pci/mixart/mixart_hwdep.c b/sound/pci/mixart/mixart_hwdep.c
index 13dcb2fd0a85..f579f7698bba 100644
--- a/sound/pci/mixart/mixart_hwdep.c
+++ b/sound/pci/mixart/mixart_hwdep.c
@@ -22,7 +22,8 @@
/**
- * wait for a value on a peudo register, exit with a timeout
+ * mixart_wait_nice_for_register_value - wait for a value on a peudo register,
+ * exit with a timeout
*
* @mgr: pointer to miXart manager structure
* @offset: unsigned pseudo_register base + offset of value
diff --git a/sound/pci/vx222/vx222_ops.c b/sound/pci/vx222/vx222_ops.c
index 23d4338dc553..a05537202738 100644
--- a/sound/pci/vx222/vx222_ops.c
+++ b/sound/pci/vx222/vx222_ops.c
@@ -78,7 +78,7 @@ static inline unsigned long vx2_reg_addr(struct vx_core *_chip, int reg)
}
/**
- * snd_vx_inb - read a byte from the register
+ * vx2_inb - read a byte from the register
* @chip: VX core instance
* @offset: register enum
*/
@@ -88,7 +88,7 @@ static unsigned char vx2_inb(struct vx_core *chip, int offset)
}
/**
- * snd_vx_outb - write a byte on the register
+ * vx2_outb - write a byte on the register
* @chip: VX core instance
* @offset: the register offset
* @val: the value to write
@@ -102,7 +102,7 @@ static void vx2_outb(struct vx_core *chip, int offset, unsigned char val)
}
/**
- * snd_vx_inl - read a 32bit word from the register
+ * vx2_inl - read a 32bit word from the register
* @chip: VX core instance
* @offset: register enum
*/
@@ -112,7 +112,7 @@ static unsigned int vx2_inl(struct vx_core *chip, int offset)
}
/**
- * snd_vx_outl - write a 32bit word on the register
+ * vx2_outl - write a 32bit word on the register
* @chip: VX core instance
* @offset: the register enum
* @val: the value to write
@@ -213,7 +213,7 @@ static int vx2_test_xilinx(struct vx_core *_chip)
/**
- * vx_setup_pseudo_dma - set up the pseudo dma read/write mode.
+ * vx2_setup_pseudo_dma - set up the pseudo dma read/write mode.
* @chip: VX core instance
* @do_write: 0 = read, 1 = set up for DMA write
*/
diff --git a/sound/ppc/snd_ps3_reg.h b/sound/ppc/snd_ps3_reg.h
index 566a3189766d..e2212b79335c 100644
--- a/sound/ppc/snd_ps3_reg.h
+++ b/sound/ppc/snd_ps3_reg.h
@@ -308,7 +308,7 @@ Indicates Interrupt status, which interrupt has occurred, and can clear
each interrupt in this register.
Writing 1b to a field containing 1b clears field and de-asserts interrupt.
Writing 0b to a field has no effect.
-Field vaules are the following:
+Field values are the following:
0 - Interrupt hasn't occurred.
1 - Interrupt has occurred.
diff --git a/sound/usb/midi.c b/sound/usb/midi.c
index 0c23fa6d8525..9efda4b06acb 100644
--- a/sound/usb/midi.c
+++ b/sound/usb/midi.c
@@ -47,6 +47,7 @@
#include <linux/usb.h>
#include <linux/wait.h>
#include <linux/usb/audio.h>
+#include <linux/usb/midi.h>
#include <linux/module.h>
#include <sound/core.h>
@@ -77,23 +78,6 @@ MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>");
MODULE_DESCRIPTION("USB Audio/MIDI helper module");
MODULE_LICENSE("Dual BSD/GPL");
-
-struct usb_ms_header_descriptor {
- __u8 bLength;
- __u8 bDescriptorType;
- __u8 bDescriptorSubtype;
- __u8 bcdMSC[2];
- __le16 wTotalLength;
-} __attribute__ ((packed));
-
-struct usb_ms_endpoint_descriptor {
- __u8 bLength;
- __u8 bDescriptorType;
- __u8 bDescriptorSubtype;
- __u8 bNumEmbMIDIJack;
- __u8 baAssocJackID[];
-} __attribute__ ((packed));
-
struct snd_usb_midi_in_endpoint;
struct snd_usb_midi_out_endpoint;
struct snd_usb_midi_endpoint;
@@ -1756,12 +1740,68 @@ static void snd_usbmidi_get_port_info(struct snd_rawmidi *rmidi, int number,
}
}
+static struct usb_midi_in_jack_descriptor *find_usb_in_jack_descriptor(
+ struct usb_host_interface *hostif, uint8_t jack_id)
+{
+ unsigned char *extra = hostif->extra;
+ int extralen = hostif->extralen;
+
+ while (extralen > 4) {
+ struct usb_midi_in_jack_descriptor *injd =
+ (struct usb_midi_in_jack_descriptor *)extra;
+
+ if (injd->bLength > 4 &&
+ injd->bDescriptorType == USB_DT_CS_INTERFACE &&
+ injd->bDescriptorSubtype == UAC_MIDI_IN_JACK &&
+ injd->bJackID == jack_id)
+ return injd;
+ if (!extra[0])
+ break;
+ extralen -= extra[0];
+ extra += extra[0];
+ }
+ return NULL;
+}
+
+static struct usb_midi_out_jack_descriptor *find_usb_out_jack_descriptor(
+ struct usb_host_interface *hostif, uint8_t jack_id)
+{
+ unsigned char *extra = hostif->extra;
+ int extralen = hostif->extralen;
+
+ while (extralen > 4) {
+ struct usb_midi_out_jack_descriptor *outjd =
+ (struct usb_midi_out_jack_descriptor *)extra;
+
+ if (outjd->bLength > 4 &&
+ outjd->bDescriptorType == USB_DT_CS_INTERFACE &&
+ outjd->bDescriptorSubtype == UAC_MIDI_OUT_JACK &&
+ outjd->bJackID == jack_id)
+ return outjd;
+ if (!extra[0])
+ break;
+ extralen -= extra[0];
+ extra += extra[0];
+ }
+ return NULL;
+}
+
static void snd_usbmidi_init_substream(struct snd_usb_midi *umidi,
- int stream, int number,
+ int stream, int number, int jack_id,
struct snd_rawmidi_substream **rsubstream)
{
struct port_info *port_info;
const char *name_format;
+ struct usb_interface *intf;
+ struct usb_host_interface *hostif;
+ struct usb_midi_in_jack_descriptor *injd;
+ struct usb_midi_out_jack_descriptor *outjd;
+ uint8_t jack_name_buf[32];
+ uint8_t *default_jack_name = "MIDI";
+ uint8_t *jack_name = default_jack_name;
+ uint8_t iJack;
+ size_t sz;
+ int res;
struct snd_rawmidi_substream *substream =
snd_usbmidi_find_substream(umidi, stream, number);
@@ -1771,11 +1811,36 @@ static void snd_usbmidi_init_substream(struct snd_usb_midi *umidi,
return;
}
- /* TODO: read port name from jack descriptor */
+ intf = umidi->iface;
+ if (intf && jack_id >= 0) {
+ hostif = intf->cur_altsetting;
+ iJack = 0;
+ if (stream != SNDRV_RAWMIDI_STREAM_OUTPUT) {
+ /* in jacks connect to outs */
+ outjd = find_usb_out_jack_descriptor(hostif, jack_id);
+ if (outjd) {
+ sz = USB_DT_MIDI_OUT_SIZE(outjd->bNrInputPins);
+ iJack = *(((uint8_t *) outjd) + sz - sizeof(uint8_t));
+ }
+ } else {
+ /* and out jacks connect to ins */
+ injd = find_usb_in_jack_descriptor(hostif, jack_id);
+ if (injd)
+ iJack = injd->iJack;
+ }
+ if (iJack != 0) {
+ res = usb_string(umidi->dev, iJack, jack_name_buf,
+ ARRAY_SIZE(jack_name_buf));
+ if (res)
+ jack_name = jack_name_buf;
+ }
+ }
+
port_info = find_port_info(umidi, number);
- name_format = port_info ? port_info->name : "%s MIDI %d";
+ name_format = port_info ? port_info->name :
+ (jack_name != default_jack_name ? "%s %s" : "%s %s %d");
snprintf(substream->name, sizeof(substream->name),
- name_format, umidi->card->shortname, number + 1);
+ name_format, umidi->card->shortname, jack_name, number + 1);
*rsubstream = substream;
}
@@ -1810,6 +1875,7 @@ static int snd_usbmidi_create_endpoints(struct snd_usb_midi *umidi,
snd_usbmidi_init_substream(umidi,
SNDRV_RAWMIDI_STREAM_OUTPUT,
out_ports,
+ endpoints[i].assoc_out_jacks[j],
&umidi->endpoints[i].out->ports[j].substream);
++out_ports;
}
@@ -1817,6 +1883,7 @@ static int snd_usbmidi_create_endpoints(struct snd_usb_midi *umidi,
snd_usbmidi_init_substream(umidi,
SNDRV_RAWMIDI_STREAM_INPUT,
in_ports,
+ endpoints[i].assoc_in_jacks[j],
&umidi->endpoints[i].in->ports[j].substream);
++in_ports;
}
@@ -1862,7 +1929,7 @@ static int snd_usbmidi_get_ms_info(struct snd_usb_midi *umidi,
struct usb_host_endpoint *hostep;
struct usb_endpoint_descriptor *ep;
struct usb_ms_endpoint_descriptor *ms_ep;
- int i, epidx;
+ int i, j, epidx;
intf = umidi->iface;
if (!intf)
@@ -1875,7 +1942,7 @@ static int snd_usbmidi_get_ms_info(struct snd_usb_midi *umidi,
ms_header->bDescriptorType == USB_DT_CS_INTERFACE &&
ms_header->bDescriptorSubtype == UAC_HEADER)
dev_dbg(&umidi->dev->dev, "MIDIStreaming version %02x.%02x\n",
- ms_header->bcdMSC[1], ms_header->bcdMSC[0]);
+ ((uint8_t *)&ms_header->bcdMSC)[1], ((uint8_t *)&ms_header->bcdMSC)[0]);
else
dev_warn(&umidi->dev->dev,
"MIDIStreaming interface descriptor not found\n");
@@ -1911,6 +1978,10 @@ static int snd_usbmidi_get_ms_info(struct snd_usb_midi *umidi,
endpoints[epidx].out_interval = 1;
endpoints[epidx].out_cables =
(1 << ms_ep->bNumEmbMIDIJack) - 1;
+ for (j = 0; j < ms_ep->bNumEmbMIDIJack; ++j)
+ endpoints[epidx].assoc_out_jacks[j] = ms_ep->baAssocJackID[j];
+ for (; j < ARRAY_SIZE(endpoints[epidx].assoc_out_jacks); ++j)
+ endpoints[epidx].assoc_out_jacks[j] = -1;
dev_dbg(&umidi->dev->dev, "EP %02X: %d jack(s)\n",
ep->bEndpointAddress, ms_ep->bNumEmbMIDIJack);
} else {
@@ -1928,6 +1999,10 @@ static int snd_usbmidi_get_ms_info(struct snd_usb_midi *umidi,
endpoints[epidx].in_interval = 1;
endpoints[epidx].in_cables =
(1 << ms_ep->bNumEmbMIDIJack) - 1;
+ for (j = 0; j < ms_ep->bNumEmbMIDIJack; ++j)
+ endpoints[epidx].assoc_in_jacks[j] = ms_ep->baAssocJackID[j];
+ for (; j < ARRAY_SIZE(endpoints[epidx].assoc_in_jacks); ++j)
+ endpoints[epidx].assoc_in_jacks[j] = -1;
dev_dbg(&umidi->dev->dev, "EP %02X: %d jack(s)\n",
ep->bEndpointAddress, ms_ep->bNumEmbMIDIJack);
}
@@ -2244,11 +2319,13 @@ static int snd_usbmidi_create_endpoints_midiman(struct snd_usb_midi *umidi,
snd_usbmidi_init_substream(umidi,
SNDRV_RAWMIDI_STREAM_OUTPUT,
cable,
+ -1 /* prevent trying to find jack */,
&umidi->endpoints[cable & 1].out->ports[cable].substream);
if (endpoint->in_cables & (1 << cable))
snd_usbmidi_init_substream(umidi,
SNDRV_RAWMIDI_STREAM_INPUT,
cable,
+ -1 /* prevent trying to find jack */,
&umidi->endpoints[0].in->ports[cable].substream);
}
return 0;
diff --git a/sound/usb/midi.h b/sound/usb/midi.h
index 8c38aec22999..3f153195c841 100644
--- a/sound/usb/midi.h
+++ b/sound/usb/midi.h
@@ -13,6 +13,8 @@ struct snd_usb_midi_endpoint_info {
uint8_t in_interval;
uint16_t out_cables; /* bitmask */
uint16_t in_cables; /* bitmask */
+ int16_t assoc_in_jacks[16];
+ int16_t assoc_out_jacks[16];
};
/* for QUIRK_MIDI_YAMAHA, data is NULL */
diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c
index 08873d2afe4d..5b77e8140ba6 100644
--- a/sound/usb/mixer_quirks.c
+++ b/sound/usb/mixer_quirks.c
@@ -2649,9 +2649,11 @@ static int snd_bbfpro_controls_create(struct usb_mixer_interface *mixer)
#define SND_DJM_DEVICE_SHIFT 24
// device table index
+// used for the snd_djm_devices table, so please update accordingly
#define SND_DJM_250MK2_IDX 0x0
#define SND_DJM_750_IDX 0x1
-#define SND_DJM_900NXS2_IDX 0x2
+#define SND_DJM_850_IDX 0x2
+#define SND_DJM_900NXS2_IDX 0x3
#define SND_DJM_CTL(_name, suffix, _default_value, _windex) { \
@@ -2691,7 +2693,7 @@ static const char *snd_djm_get_label_caplevel(u16 wvalue)
}
};
-static const char *snd_djm_get_label_cap(u16 wvalue)
+static const char *snd_djm_get_label_cap_common(u16 wvalue)
{
switch (wvalue & 0x00ff) {
case SND_DJM_CAP_LINE: return "Control Tone LINE";
@@ -2713,6 +2715,25 @@ static const char *snd_djm_get_label_cap(u16 wvalue)
}
};
+// The DJM-850 has different values for CD/LINE and LINE capture
+// control options than the other DJM declared in this file.
+static const char *snd_djm_get_label_cap_850(u16 wvalue)
+{
+ switch (wvalue & 0x00ff) {
+ case 0x00: return "Control Tone CD/LINE";
+ case 0x01: return "Control Tone LINE";
+ default: return snd_djm_get_label_cap_common(wvalue);
+ }
+};
+
+static const char *snd_djm_get_label_cap(u8 device_idx, u16 wvalue)
+{
+ switch (device_idx) {
+ case SND_DJM_850_IDX: return snd_djm_get_label_cap_850(wvalue);
+ default: return snd_djm_get_label_cap_common(wvalue);
+ }
+};
+
static const char *snd_djm_get_label_pb(u16 wvalue)
{
switch (wvalue & 0x00ff) {
@@ -2723,21 +2744,22 @@ static const char *snd_djm_get_label_pb(u16 wvalue)
}
};
-static const char *snd_djm_get_label(u16 wvalue, u16 windex)
+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_CAP: return snd_djm_get_label_cap(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;
}
};
-
-// DJM-250MK2
+// common DJM capture level option values
static const u16 snd_djm_opts_cap_level[] = {
0x0000, 0x0100, 0x0200, 0x0300 };
+
+// DJM-250MK2
static const u16 snd_djm_opts_250mk2_cap1[] = {
0x0103, 0x0100, 0x0106, 0x0107, 0x0108, 0x0109, 0x010d, 0x010a };
@@ -2781,6 +2803,25 @@ static const struct snd_djm_ctl snd_djm_ctls_750[] = {
};
+// DJM-850
+static const u16 snd_djm_opts_850_cap1[] = {
+ 0x0100, 0x0103, 0x0106, 0x0107, 0x0108, 0x0109, 0x010a, 0x010f };
+static const u16 snd_djm_opts_850_cap2[] = {
+ 0x0200, 0x0201, 0x0206, 0x0207, 0x0208, 0x0209, 0x020a, 0x020f };
+static const u16 snd_djm_opts_850_cap3[] = {
+ 0x0300, 0x0301, 0x0306, 0x0307, 0x0308, 0x0309, 0x030a, 0x030f };
+static const u16 snd_djm_opts_850_cap4[] = {
+ 0x0400, 0x0403, 0x0406, 0x0407, 0x0408, 0x0409, 0x040a, 0x040f };
+
+static const struct snd_djm_ctl snd_djm_ctls_850[] = {
+ SND_DJM_CTL("Capture Level", cap_level, 0, SND_DJM_WINDEX_CAPLVL),
+ SND_DJM_CTL("Ch1 Input", 850_cap1, 1, SND_DJM_WINDEX_CAP),
+ SND_DJM_CTL("Ch2 Input", 850_cap2, 0, SND_DJM_WINDEX_CAP),
+ SND_DJM_CTL("Ch3 Input", 850_cap3, 0, SND_DJM_WINDEX_CAP),
+ SND_DJM_CTL("Ch4 Input", 850_cap4, 1, SND_DJM_WINDEX_CAP)
+};
+
+
// DJM-900NXS2
static const u16 snd_djm_opts_900nxs2_cap1[] = {
0x0100, 0x0102, 0x0103, 0x0106, 0x0107, 0x0108, 0x0109, 0x010a };
@@ -2806,6 +2847,7 @@ static const struct snd_djm_ctl snd_djm_ctls_900nxs2[] = {
static const struct snd_djm_device snd_djm_devices[] = {
SND_DJM_DEVICE(250mk2),
SND_DJM_DEVICE(750),
+ SND_DJM_DEVICE(850),
SND_DJM_DEVICE(900nxs2)
};
@@ -2829,7 +2871,8 @@ static int snd_djm_controls_info(struct snd_kcontrol *kctl,
if (info->value.enumerated.item >= noptions)
info->value.enumerated.item = noptions - 1;
- name = snd_djm_get_label(ctl->options[info->value.enumerated.item],
+ name = snd_djm_get_label(device_idx,
+ ctl->options[info->value.enumerated.item],
ctl->wIndex);
if (!name)
return -EINVAL;
@@ -3045,6 +3088,9 @@ int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer)
case USB_ID(0x08e4, 0x017f): /* Pioneer DJ DJM-750 */
err = snd_djm_controls_create(mixer, SND_DJM_750_IDX);
break;
+ case USB_ID(0x08e4, 0x0163): /* Pioneer DJ DJM-850 */
+ err = snd_djm_controls_create(mixer, SND_DJM_850_IDX);
+ break;
case USB_ID(0x2b73, 0x000a): /* Pioneer DJ DJM-900NXS2 */
err = snd_djm_controls_create(mixer, SND_DJM_900NXS2_IDX);
break;
diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h
index 1165a5ac60f2..9716a9f7c095 100644
--- a/sound/usb/quirks-table.h
+++ b/sound/usb/quirks-table.h
@@ -3819,6 +3819,69 @@ AU0828_DEVICE(0x2040, 0x7270, "Hauppauge", "HVR-950Q"),
},
{
/*
+ * Pioneer DJ DJM-850
+ * 8 channels playback and 8 channels capture @ 44.1/48/96kHz S24LE
+ * Playback on EP 0x05
+ * Capture on EP 0x86
+ */
+ USB_DEVICE_VENDOR_SPEC(0x08e4, 0x0163),
+ .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) {
+ .ifnum = QUIRK_ANY_INTERFACE,
+ .type = QUIRK_COMPOSITE,
+ .data = (const struct snd_usb_audio_quirk[]) {
+ {
+ .ifnum = 0,
+ .type = QUIRK_AUDIO_FIXED_ENDPOINT,
+ .data = &(const struct audioformat) {
+ .formats = SNDRV_PCM_FMTBIT_S24_3LE,
+ .channels = 8,
+ .iface = 0,
+ .altsetting = 1,
+ .altset_idx = 1,
+ .endpoint = 0x05,
+ .ep_attr = USB_ENDPOINT_XFER_ISOC|
+ USB_ENDPOINT_SYNC_ASYNC|
+ USB_ENDPOINT_USAGE_DATA,
+ .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 }
+ }
+ },
+ {
+ .ifnum = 0,
+ .type = QUIRK_AUDIO_FIXED_ENDPOINT,
+ .data = &(const struct audioformat) {
+ .formats = SNDRV_PCM_FMTBIT_S24_3LE,
+ .channels = 8,
+ .iface = 0,
+ .altsetting = 1,
+ .altset_idx = 1,
+ .endpoint = 0x86,
+ .ep_idx = 1,
+ .ep_attr = USB_ENDPOINT_XFER_ISOC|
+ USB_ENDPOINT_SYNC_ASYNC|
+ USB_ENDPOINT_USAGE_DATA,
+ .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 }
+ }
+ },
+ {
+ .ifnum = -1
+ }
+ }
+ }
+},
+{
+ /*
* Pioneer DJ DJM-450
* PCM is 8 channels out @ 48 fixed (endpoint 0x01)
* and 8 channels in @ 48 fixed (endpoint 0x82).
diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c
index 737b2729c0d3..d02dac5fcd40 100644
--- a/sound/usb/quirks.c
+++ b/sound/usb/quirks.c
@@ -1503,6 +1503,9 @@ void snd_usb_set_format_quirk(struct snd_usb_substream *subs,
case USB_ID(0x2b73, 0x0013): /* Pioneer DJM-450 */
pioneer_djm_set_format_quirk(subs, 0x0082);
break;
+ case USB_ID(0x08e4, 0x0163): /* Pioneer DJM-850 */
+ pioneer_djm_set_format_quirk(subs, 0x0086);
+ break;
}
}