* [PATCH 1/1] Added functionality for E-mu 0404USB/0202USB/TrackerPre
@ 2009-12-21 20:39 Zerg Cannibal
2009-12-25 13:29 ` Takashi Iwai
2009-12-27 12:04 ` James Courtier-Dutton
0 siblings, 2 replies; 8+ messages in thread
From: Zerg Cannibal @ 2009-12-21 20:39 UTC (permalink / raw)
To: alsa-devel
Added functionality:
1) Extension Units support (all XU settings now available at alsamixer, kmix, etc):
- "AnalogueIn soft limiter" switch;
- "Sample rate" selector (values 0,1,2,3,4,5 corresponds to 44.1 48 ... 192 kHz);
- "DigitalIn CLK source" selector (internal/external) (**);
- "DigitalOut format SPDIF/AC3" switch (**);
(**)E-mu-0404usb only.
2) Automatic device sample rate adjustment depending on substream samplerate for both capture and playback substream.
Patch is based on Mac OS-X driver (http://sourceforge.net/projects/zaudiodrivermac/) and successfully tested by Ubuntu community users for 0404usb and 0202usb.
Signed-off-by: CannibalZerg <cnb_zerg@yahoo.com>
---
sound/usb/usbaudio.c | 44 ++++++++++++++++++++++++++++++
sound/usb/usbaudio.h | 2 +
sound/usb/usbmixer.c | 73 +++++++++++++++++++++++++++++++++++++++++++++++---
3 files changed, 115 insertions(+), 4 deletions(-)
diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c
index 31b63ea..d8eb029 100644
--- a/sound/usb/usbaudio.c
+++ b/sound/usb/usbaudio.c
@@ -1271,6 +1271,42 @@ static int init_usb_sample_rate(struct usb_device *dev, int iface,
}
/*
+ * For E-Mu 0404USB/0202USB/TrackerPre sample rate should be set for device,
+ * not for interface.
+*/
+static void set_format_emu_quirk(struct snd_usb_substream *subs, struct audioformat *fmt)
+{
+ unsigned char emu_samplerate_id = 0;
+
+ /* When capture is active sample rate shouldn't be changed by playback substream*/
+ if (subs->direction == SNDRV_PCM_STREAM_PLAYBACK) {
+ if (subs->stream->substream[SNDRV_PCM_STREAM_CAPTURE].interface != -1)
+ return;
+ }
+
+ switch (fmt->rate_min) {
+ case 48000:
+ emu_samplerate_id = 1;
+ break;
+ case 88200:
+ emu_samplerate_id = 2;
+ break;
+ case 96000:
+ emu_samplerate_id = 3;
+ break;
+ case 176400:
+ emu_samplerate_id = 4;
+ break;
+ case 192000:
+ emu_samplerate_id = 5;
+ break;
+ default:
+ emu_samplerate_id = 0;
+ }
+ snd_emuusb_set_samplerate(subs->stream->chip, emu_samplerate_id);
+}
+
+/*
* find a matching format and set up the interface
*/
static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt)
@@ -1383,6 +1419,14 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt)
subs->cur_audiofmt = fmt;
+ switch (subs->stream->chip->usb_id) {
+ case USB_ID(0x041e, 0x3f02): /* E-Mu 0202 USB */
+ case USB_ID(0x041e, 0x3f04): /* E-Mu 0404 USB */
+ case USB_ID(0x041e, 0x3f0a): /* E-Mu Tracker Pre */
+ set_format_emu_quirk(subs, fmt);
+ break;
+ }
+
#if 0
printk(KERN_DEBUG
"setting done: format = %d, rate = %d..%d, channels = %d\n",
diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h
index 9826337..8558773 100644
--- a/sound/usb/usbaudio.h
+++ b/sound/usb/usbaudio.h
@@ -233,6 +233,8 @@ void snd_usbmidi_input_stop(struct list_head* p);
void snd_usbmidi_input_start(struct list_head* p);
void snd_usbmidi_disconnect(struct list_head *p);
+void snd_emuusb_set_samplerate(struct snd_usb_audio *chip, unsigned char samplerate_id);
+
/*
* retrieve usb_interface descriptor from the host interface
* (conditional for compatibility with the older API)
diff --git a/sound/usb/usbmixer.c b/sound/usb/usbmixer.c
index c998220..400208c 100644
--- a/sound/usb/usbmixer.c
+++ b/sound/usb/usbmixer.c
@@ -186,6 +186,21 @@ enum {
USB_PROC_DCR_RELEASE = 6,
};
+/*E-mu 0202(0404) eXtension Unit(XU) control*/
+enum {
+ USB_XU_CLOCK_RATE = 0xe301,
+ USB_XU_CLOCK_SOURCE = 0xe302,
+ USB_XU_DIGITAL_IO_STATUS = 0xe303,
+ USB_XU_DEVICE_OPTIONS = 0xe304,
+ USB_XU_DIRECT_MONITORING = 0xe305,
+ USB_XU_METERING = 0xe306
+};
+enum {
+ USB_XU_CLOCK_SOURCE_SELECTOR = 0x02, /* clock source*/
+ USB_XU_CLOCK_RATE_SELECTOR = 0x03, /* clock rate */
+ USB_XU_DIGITAL_FORMAT_SELECTOR = 0x01, /* the spdif format */
+ USB_XU_SOFT_LIMIT_SELECTOR = 0x03 /* soft limiter */
+};
/*
* manual mapping of mixer names
@@ -1330,7 +1345,32 @@ static struct procunit_info procunits[] = {
{ USB_PROC_DCR, "DCR", dcr_proc_info },
{ 0 },
};
-
+/*
+ * predefined data for extension units
+ */
+static struct procunit_value_info clock_rate_xu_info[] = {
+ { USB_XU_CLOCK_RATE_SELECTOR, "Selector", USB_MIXER_U8, 0},
+ { 0 }
+};
+static struct procunit_value_info clock_source_xu_info[] = {
+ { USB_XU_CLOCK_SOURCE_SELECTOR, "External", USB_MIXER_BOOLEAN},
+ { 0 }
+};
+static struct procunit_value_info spdif_format_xu_info[] = {
+ { USB_XU_DIGITAL_FORMAT_SELECTOR, "SPDIF/AC3", USB_MIXER_BOOLEAN},
+ { 0 }
+};
+static struct procunit_value_info soft_limit_xu_info[] = {
+ { USB_XU_SOFT_LIMIT_SELECTOR, " ", USB_MIXER_BOOLEAN},
+ { 0 }
+};
+static struct procunit_info extunits[] = {
+ { USB_XU_CLOCK_RATE, "Clock rate", clock_rate_xu_info },
+ { USB_XU_CLOCK_SOURCE, "DigitalIn CLK source", clock_source_xu_info },
+ { USB_XU_DIGITAL_IO_STATUS, "DigitalOut format:", spdif_format_xu_info },
+ { USB_XU_DEVICE_OPTIONS, "AnalogueIn Soft Limit", soft_limit_xu_info },
+ { 0 }
+};
/*
* build a processing/extension unit
*/
@@ -1391,8 +1431,16 @@ static int build_audio_procunit(struct mixer_build *state, int unitid, unsigned
cval->max = dsc[15];
cval->res = 1;
cval->initialized = 1;
- } else
- get_min_max(cval, valinfo->min_value);
+ } else {
+ if (type == USB_XU_CLOCK_RATE) {
+ /*E-Mu USB 0404/0202/TrackerPre samplerate control quirk*/
+ cval->min = 0;
+ cval->max = 5;
+ cval->res = 1;
+ cval->initialized = 1;
+ } else
+ get_min_max(cval, valinfo->min_value);
+ }
kctl = snd_ctl_new1(&mixer_procunit_ctl, cval);
if (! kctl) {
@@ -1433,7 +1481,7 @@ static int parse_audio_processing_unit(struct mixer_build *state, int unitid, un
static int parse_audio_extension_unit(struct mixer_build *state, int unitid, unsigned char *desc)
{
- return build_audio_procunit(state, unitid, desc, NULL, "Extension Unit");
+ return build_audio_procunit(state, unitid, desc, extunits, "Extension Unit");
}
@@ -2109,6 +2157,23 @@ static int snd_xonar_u1_controls_create(struct usb_mixer_interface *mixer)
return 0;
}
+void snd_emuusb_set_samplerate(struct snd_usb_audio *chip, unsigned char samplerate_id)
+{
+ struct usb_mixer_interface *mixer;
+ struct list_head *p;
+ struct usb_mixer_elem_info *cval;
+ int unitid = 12; /*SampleRate ExtensionUnit ID*/
+ list_for_each(p, &chip->mixer_list) {
+ mixer = list_entry(p, struct usb_mixer_interface, list);
+ cval = mixer->id_elems[unitid];
+ if (cval) {
+ set_cur_ctl_value(cval, cval->control << 8, samplerate_id);
+ snd_usb_mixer_notify_id(mixer, unitid);
+ }
+ break;
+ }
+}
+
int snd_usb_create_mixer(struct snd_usb_audio *chip, int ctrlif,
int ignore_error)
{
--
1.6.5.6
^ permalink raw reply related [flat|nested] 8+ messages in thread* Re: [PATCH 1/1] Added functionality for E-mu 0404USB/0202USB/TrackerPre
2009-12-21 20:39 [PATCH 1/1] Added functionality for E-mu 0404USB/0202USB/TrackerPre Zerg Cannibal
@ 2009-12-25 13:29 ` Takashi Iwai
2009-12-27 16:50 ` Sergiy Kovalchuk
2009-12-27 17:13 ` Sergiy Kovalchuk
2009-12-27 12:04 ` James Courtier-Dutton
1 sibling, 2 replies; 8+ messages in thread
From: Takashi Iwai @ 2009-12-25 13:29 UTC (permalink / raw)
To: Zerg Cannibal; +Cc: alsa-devel
At Mon, 21 Dec 2009 12:39:27 -0800 (PST),
Zerg Cannibal wrote:
>
> Added functionality:
> 1) Extension Units support (all XU settings now available at alsamixer, kmix, etc):
> - "AnalogueIn soft limiter" switch;
> - "Sample rate" selector (values 0,1,2,3,4,5 corresponds to 44.1 48 ... 192 kHz);
> - "DigitalIn CLK source" selector (internal/external) (**);
> - "DigitalOut format SPDIF/AC3" switch (**);
> (**)E-mu-0404usb only.
>
> 2) Automatic device sample rate adjustment depending on substream samplerate for both capture and playback substream.
>
> Patch is based on Mac OS-X driver (http://sourceforge.net/projects/zaudiodrivermac/) and successfully tested by Ubuntu community users for 0404usb and 0202usb.
>
> Signed-off-by: CannibalZerg <cnb_zerg@yahoo.com>
Thanks for the patch. Through a quick look, it's fine.
But, could you fix the following and repost?
- Fix warnings suggested by scripts/checkpatch.pl.
Some 80-chars warnings can be ignored if it makes worse, though.
- Please give the right name and address matching with your from
address.
Also, the sample rate control could be an enum at best. But, this
needs more another changes, so let's merge this patch first.
thanks,
Takashi
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 1/1] Added functionality for E-mu 0404USB/0202USB/TrackerPre
2009-12-25 13:29 ` Takashi Iwai
@ 2009-12-27 16:50 ` Sergiy Kovalchuk
2009-12-27 17:13 ` Sergiy Kovalchuk
1 sibling, 0 replies; 8+ messages in thread
From: Sergiy Kovalchuk @ 2009-12-27 16:50 UTC (permalink / raw)
To: Takashi Iwai; +Cc: alsa-devel
> Thanks for the patch. Through a quick look, it's
> fine.
> But, could you fix the following and repost?
Summary:
Added functionality for E-mu 0404USB/0202USB/TrackerPre
Added functionality:
1) Extension Units support (all XU settings now available at alsamixer, kmix, etc):
- "AnalogueIn soft limiter" switch;
- "Sample rate" selector (values 0,1,2,3,4,5 corresponds to 44.1 48 ... 192 kHz);
- "DigitalIn CLK source" selector (internal/external) (**);
- "DigitalOut format SPDIF/AC3" switch (**);
(**)E-mu-0404usb only.
2) Automatic device sample rate adjustment depending on substream samplerate for both capture and playback substream.
Signed-off-by: Sergiy Kovalchuk <cnb_zerg@yahoo.com>
---
sound/usb/usbaudio.c | 47 +++++++++++++++++++++++++++++++
sound/usb/usbaudio.h | 13 ++++++++
sound/usb/usbmixer.c | 75 +++++++++++++++++++++++++++++++++++++++++++++++--
3 files changed, 131 insertions(+), 4 deletions(-)
diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c
index 31b63ea..b60222b 100644
--- a/sound/usb/usbaudio.c
+++ b/sound/usb/usbaudio.c
@@ -1271,6 +1271,45 @@ static int init_usb_sample_rate(struct usb_device *dev, int iface,
}
/*
+ * For E-Mu 0404USB/0202USB/TrackerPre sample rate should be set for device,
+ * not for interface.
+*/
+static void set_format_emu_quirk(struct snd_usb_substream *subs,
+ struct audioformat *fmt)
+{
+ unsigned char emu_samplerate_id = 0;
+
+ /* When capture is active
+ * sample rate shouldn't be changed
+ * by playback substream*/
+ if (subs->direction == SNDRV_PCM_STREAM_PLAYBACK) {
+ if (subs->stream->substream[SNDRV_PCM_STREAM_CAPTURE].interface != -1)
+ return;
+ }
+
+ switch (fmt->rate_min) {
+ case 48000:
+ emu_samplerate_id = EMU_QUIRK_SR_48000HZ;
+ break;
+ case 88200:
+ emu_samplerate_id = EMU_QUIRK_SR_88200HZ;
+ break;
+ case 96000:
+ emu_samplerate_id = EMU_QUIRK_SR_96000HZ;
+ break;
+ case 176400:
+ emu_samplerate_id = EMU_QUIRK_SR_176400HZ;
+ break;
+ case 192000:
+ emu_samplerate_id = EMU_QUIRK_SR_96000HZ;
+ break;
+ default:
+ emu_samplerate_id = EMU_QUIRK_SR_192000HZ;
+ }
+ snd_emuusb_set_samplerate(subs->stream->chip, emu_samplerate_id);
+}
+
+/*
* find a matching format and set up the interface
*/
static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt)
@@ -1383,6 +1422,14 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt)
subs->cur_audiofmt = fmt;
+ switch (subs->stream->chip->usb_id) {
+ case USB_ID(0x041e, 0x3f02): /* E-Mu 0202 USB */
+ case USB_ID(0x041e, 0x3f04): /* E-Mu 0404 USB */
+ case USB_ID(0x041e, 0x3f0a): /* E-Mu Tracker Pre */
+ set_format_emu_quirk(subs, fmt);
+ break;
+ }
+
#if 0
printk(KERN_DEBUG
"setting done: format = %d, rate = %d..%d, channels = %d\n",
diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h
index 9826337..1522167 100644
--- a/sound/usb/usbaudio.h
+++ b/sound/usb/usbaudio.h
@@ -208,6 +208,16 @@ struct snd_usb_midi_endpoint_info {
/*
*/
+/*E-mu USB samplerate control quirk*/
+enum {
+ EMU_QUIRK_SR_44100HZ = 0,
+ EMU_QUIRK_SR_48000HZ,
+ EMU_QUIRK_SR_88200HZ,
+ EMU_QUIRK_SR_96000HZ,
+ EMU_QUIRK_SR_176400HZ,
+ EMU_QUIRK_SR_192000HZ
+};
+
#define combine_word(s) ((*(s)) | ((unsigned int)(s)[1] << 8))
#define combine_triple(s) (combine_word(s) | ((unsigned int)(s)[2] << 16))
#define combine_quad(s) (combine_triple(s) | ((unsigned int)(s)[3] << 24))
@@ -233,6 +243,9 @@ void snd_usbmidi_input_stop(struct list_head* p);
void snd_usbmidi_input_start(struct list_head* p);
void snd_usbmidi_disconnect(struct list_head *p);
+void snd_emuusb_set_samplerate(struct snd_usb_audio *chip,
+ unsigned char samplerate_id);
+
/*
* retrieve usb_interface descriptor from the host interface
* (conditional for compatibility with the older API)
diff --git a/sound/usb/usbmixer.c b/sound/usb/usbmixer.c
index c998220..9433112 100644
--- a/sound/usb/usbmixer.c
+++ b/sound/usb/usbmixer.c
@@ -186,6 +186,21 @@ enum {
USB_PROC_DCR_RELEASE = 6,
};
+/*E-mu 0202(0404) eXtension Unit(XU) control*/
+enum {
+ USB_XU_CLOCK_RATE = 0xe301,
+ USB_XU_CLOCK_SOURCE = 0xe302,
+ USB_XU_DIGITAL_IO_STATUS = 0xe303,
+ USB_XU_DEVICE_OPTIONS = 0xe304,
+ USB_XU_DIRECT_MONITORING = 0xe305,
+ USB_XU_METERING = 0xe306
+};
+enum {
+ USB_XU_CLOCK_SOURCE_SELECTOR = 0x02, /* clock source*/
+ USB_XU_CLOCK_RATE_SELECTOR = 0x03, /* clock rate */
+ USB_XU_DIGITAL_FORMAT_SELECTOR = 0x01, /* the spdif format */
+ USB_XU_SOFT_LIMIT_SELECTOR = 0x03 /* soft limiter */
+};
/*
* manual mapping of mixer names
@@ -1330,7 +1345,32 @@ static struct procunit_info procunits[] = {
{ USB_PROC_DCR, "DCR", dcr_proc_info },
{ 0 },
};
-
+/*
+ * predefined data for extension units
+ */
+static struct procunit_value_info clock_rate_xu_info[] = {
+ { USB_XU_CLOCK_RATE_SELECTOR, "Selector", USB_MIXER_U8, 0},
+ { 0 }
+};
+static struct procunit_value_info clock_source_xu_info[] = {
+ { USB_XU_CLOCK_SOURCE_SELECTOR, "External", USB_MIXER_BOOLEAN},
+ { 0 }
+};
+static struct procunit_value_info spdif_format_xu_info[] = {
+ { USB_XU_DIGITAL_FORMAT_SELECTOR, "SPDIF/AC3", USB_MIXER_BOOLEAN},
+ { 0 }
+};
+static struct procunit_value_info soft_limit_xu_info[] = {
+ { USB_XU_SOFT_LIMIT_SELECTOR, " ", USB_MIXER_BOOLEAN},
+ { 0 }
+};
+static struct procunit_info extunits[] = {
+ { USB_XU_CLOCK_RATE, "Clock rate", clock_rate_xu_info },
+ { USB_XU_CLOCK_SOURCE, "DigitalIn CLK source", clock_source_xu_info },
+ { USB_XU_DIGITAL_IO_STATUS, "DigitalOut format:", spdif_format_xu_info },
+ { USB_XU_DEVICE_OPTIONS, "AnalogueIn Soft Limit", soft_limit_xu_info },
+ { 0 }
+};
/*
* build a processing/extension unit
*/
@@ -1391,8 +1431,17 @@ static int build_audio_procunit(struct mixer_build *state, int unitid, unsigned
cval->max = dsc[15];
cval->res = 1;
cval->initialized = 1;
- } else
- get_min_max(cval, valinfo->min_value);
+ } else {
+ if (type == USB_XU_CLOCK_RATE) {
+ /*E-Mu USB 0404/0202/TrackerPre
+ * samplerate control quirk*/
+ cval->min = 0;
+ cval->max = 5;
+ cval->res = 1;
+ cval->initialized = 1;
+ } else
+ get_min_max(cval, valinfo->min_value);
+ }
kctl = snd_ctl_new1(&mixer_procunit_ctl, cval);
if (! kctl) {
@@ -1433,7 +1482,7 @@ static int parse_audio_processing_unit(struct mixer_build *state, int unitid, un
static int parse_audio_extension_unit(struct mixer_build *state, int unitid, unsigned char *desc)
{
- return build_audio_procunit(state, unitid, desc, NULL, "Extension Unit");
+ return build_audio_procunit(state, unitid, desc, extunits, "Extension Unit");
}
@@ -2109,6 +2158,24 @@ static int snd_xonar_u1_controls_create(struct usb_mixer_interface *mixer)
return 0;
}
+void snd_emuusb_set_samplerate(struct snd_usb_audio *chip,
+ unsigned char samplerate_id)
+{
+ struct usb_mixer_interface *mixer;
+ struct list_head *p;
+ struct usb_mixer_elem_info *cval;
+ int unitid = 12; /*SamleRate ExtensionUnit ID8*/
+ list_for_each(p, &chip->mixer_list) {
+ mixer = list_entry(p, struct usb_mixer_interface, list);
+ cval = mixer->id_elems[unitid];
+ if (cval) {
+ set_cur_ctl_value(cval, cval->control << 8, samplerate_id);
+ snd_usb_mixer_notify_id(mixer, unitid);
+ }
+ break;
+ }
+}
+
int snd_usb_create_mixer(struct snd_usb_audio *chip, int ctrlif,
int ignore_error)
{
--
1.6.6
^ permalink raw reply related [flat|nested] 8+ messages in thread* Re: [PATCH 1/1] Added functionality for E-mu 0404USB/0202USB/TrackerPre
2009-12-25 13:29 ` Takashi Iwai
2009-12-27 16:50 ` Sergiy Kovalchuk
@ 2009-12-27 17:13 ` Sergiy Kovalchuk
2009-12-28 11:33 ` Takashi Iwai
1 sibling, 1 reply; 8+ messages in thread
From: Sergiy Kovalchuk @ 2009-12-27 17:13 UTC (permalink / raw)
To: Takashi Iwai; +Cc: alsa-devel
!!! Sorry, previous patch is incorrect !!!
> Thanks for the patch. Through a quick look, it's
> fine.
> But, could you fix the following and repost?
Summary:
Added functionality for E-mu 0404USB/0202USB/TrackerPre
Added functionality:
1) Extension Units support (all XU settings now available at alsamixer, kmix, etc):
- "AnalogueIn soft limiter" switch;
- "Sample rate" selector (values 0,1,2,3,4,5 corresponds to 44.1 48 ... 192 kHz);
- "DigitalIn CLK source" selector (internal/external) (**);
- "DigitalOut format SPDIF/AC3" switch (**);
(**)E-mu-0404usb only.
2) Automatic device sample rate adjustment depending on substream samplerate for both capture and playback substream.
Signed-off-by: Sergiy Kovalchuk <cnb_zerg@yahoo.com>
---
sound/usb/usbaudio.c | 47 +++++++++++++++++++++++++++++++
sound/usb/usbaudio.h | 13 ++++++++
sound/usb/usbmixer.c | 75 +++++++++++++++++++++++++++++++++++++++++++++++--
3 files changed, 131 insertions(+), 4 deletions(-)
diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c
index 31b63ea..a356dac 100644
--- a/sound/usb/usbaudio.c
+++ b/sound/usb/usbaudio.c
@@ -1271,6 +1271,45 @@ static int init_usb_sample_rate(struct usb_device *dev, int iface,
}
/*
+ * For E-Mu 0404USB/0202USB/TrackerPre sample rate should be set for device,
+ * not for interface.
+*/
+static void set_format_emu_quirk(struct snd_usb_substream *subs,
+ struct audioformat *fmt)
+{
+ unsigned char emu_samplerate_id = 0;
+
+ /* When capture is active
+ * sample rate shouldn't be changed
+ * by playback substream*/
+ if (subs->direction == SNDRV_PCM_STREAM_PLAYBACK) {
+ if (subs->stream->substream[SNDRV_PCM_STREAM_CAPTURE].interface != -1)
+ return;
+ }
+
+ switch (fmt->rate_min) {
+ case 48000:
+ emu_samplerate_id = EMU_QUIRK_SR_48000HZ;
+ break;
+ case 88200:
+ emu_samplerate_id = EMU_QUIRK_SR_88200HZ;
+ break;
+ case 96000:
+ emu_samplerate_id = EMU_QUIRK_SR_96000HZ;
+ break;
+ case 176400:
+ emu_samplerate_id = EMU_QUIRK_SR_176400HZ;
+ break;
+ case 192000:
+ emu_samplerate_id = EMU_QUIRK_SR_192000HZ;
+ break;
+ default:
+ emu_samplerate_id = EMU_QUIRK_SR_44100HZ;
+ }
+ snd_emuusb_set_samplerate(subs->stream->chip, emu_samplerate_id);
+}
+
+/*
* find a matching format and set up the interface
*/
static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt)
@@ -1383,6 +1422,14 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt)
subs->cur_audiofmt = fmt;
+ switch (subs->stream->chip->usb_id) {
+ case USB_ID(0x041e, 0x3f02): /* E-Mu 0202 USB */
+ case USB_ID(0x041e, 0x3f04): /* E-Mu 0404 USB */
+ case USB_ID(0x041e, 0x3f0a): /* E-Mu Tracker Pre */
+ set_format_emu_quirk(subs, fmt);
+ break;
+ }
+
#if 0
printk(KERN_DEBUG
"setting done: format = %d, rate = %d..%d, channels = %d\n",
diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h
index 9826337..1522167 100644
--- a/sound/usb/usbaudio.h
+++ b/sound/usb/usbaudio.h
@@ -208,6 +208,16 @@ struct snd_usb_midi_endpoint_info {
/*
*/
+/*E-mu USB samplerate control quirk*/
+enum {
+ EMU_QUIRK_SR_44100HZ = 0,
+ EMU_QUIRK_SR_48000HZ,
+ EMU_QUIRK_SR_88200HZ,
+ EMU_QUIRK_SR_96000HZ,
+ EMU_QUIRK_SR_176400HZ,
+ EMU_QUIRK_SR_192000HZ
+};
+
#define combine_word(s) ((*(s)) | ((unsigned int)(s)[1] << 8))
#define combine_triple(s) (combine_word(s) | ((unsigned int)(s)[2] << 16))
#define combine_quad(s) (combine_triple(s) | ((unsigned int)(s)[3] << 24))
@@ -233,6 +243,9 @@ void snd_usbmidi_input_stop(struct list_head* p);
void snd_usbmidi_input_start(struct list_head* p);
void snd_usbmidi_disconnect(struct list_head *p);
+void snd_emuusb_set_samplerate(struct snd_usb_audio *chip,
+ unsigned char samplerate_id);
+
/*
* retrieve usb_interface descriptor from the host interface
* (conditional for compatibility with the older API)
diff --git a/sound/usb/usbmixer.c b/sound/usb/usbmixer.c
index c998220..adcb23b 100644
--- a/sound/usb/usbmixer.c
+++ b/sound/usb/usbmixer.c
@@ -186,6 +186,21 @@ enum {
USB_PROC_DCR_RELEASE = 6,
};
+/*E-mu 0202(0404) eXtension Unit(XU) control*/
+enum {
+ USB_XU_CLOCK_RATE = 0xe301,
+ USB_XU_CLOCK_SOURCE = 0xe302,
+ USB_XU_DIGITAL_IO_STATUS = 0xe303,
+ USB_XU_DEVICE_OPTIONS = 0xe304,
+ USB_XU_DIRECT_MONITORING = 0xe305,
+ USB_XU_METERING = 0xe306
+};
+enum {
+ USB_XU_CLOCK_SOURCE_SELECTOR = 0x02, /* clock source*/
+ USB_XU_CLOCK_RATE_SELECTOR = 0x03, /* clock rate */
+ USB_XU_DIGITAL_FORMAT_SELECTOR = 0x01, /* the spdif format */
+ USB_XU_SOFT_LIMIT_SELECTOR = 0x03 /* soft limiter */
+};
/*
* manual mapping of mixer names
@@ -1330,7 +1345,32 @@ static struct procunit_info procunits[] = {
{ USB_PROC_DCR, "DCR", dcr_proc_info },
{ 0 },
};
-
+/*
+ * predefined data for extension units
+ */
+static struct procunit_value_info clock_rate_xu_info[] = {
+ { USB_XU_CLOCK_RATE_SELECTOR, "Selector", USB_MIXER_U8, 0},
+ { 0 }
+};
+static struct procunit_value_info clock_source_xu_info[] = {
+ { USB_XU_CLOCK_SOURCE_SELECTOR, "External", USB_MIXER_BOOLEAN},
+ { 0 }
+};
+static struct procunit_value_info spdif_format_xu_info[] = {
+ { USB_XU_DIGITAL_FORMAT_SELECTOR, "SPDIF/AC3", USB_MIXER_BOOLEAN},
+ { 0 }
+};
+static struct procunit_value_info soft_limit_xu_info[] = {
+ { USB_XU_SOFT_LIMIT_SELECTOR, " ", USB_MIXER_BOOLEAN},
+ { 0 }
+};
+static struct procunit_info extunits[] = {
+ { USB_XU_CLOCK_RATE, "Clock rate", clock_rate_xu_info },
+ { USB_XU_CLOCK_SOURCE, "DigitalIn CLK source", clock_source_xu_info },
+ { USB_XU_DIGITAL_IO_STATUS, "DigitalOut format:", spdif_format_xu_info },
+ { USB_XU_DEVICE_OPTIONS, "AnalogueIn Soft Limit", soft_limit_xu_info },
+ { 0 }
+};
/*
* build a processing/extension unit
*/
@@ -1391,8 +1431,17 @@ static int build_audio_procunit(struct mixer_build *state, int unitid, unsigned
cval->max = dsc[15];
cval->res = 1;
cval->initialized = 1;
- } else
- get_min_max(cval, valinfo->min_value);
+ } else {
+ if (type == USB_XU_CLOCK_RATE) {
+ /*E-Mu USB 0404/0202/TrackerPre
+ * samplerate control quirk*/
+ cval->min = 0;
+ cval->max = 5;
+ cval->res = 1;
+ cval->initialized = 1;
+ } else
+ get_min_max(cval, valinfo->min_value);
+ }
kctl = snd_ctl_new1(&mixer_procunit_ctl, cval);
if (! kctl) {
@@ -1433,7 +1482,7 @@ static int parse_audio_processing_unit(struct mixer_build *state, int unitid, un
static int parse_audio_extension_unit(struct mixer_build *state, int unitid, unsigned char *desc)
{
- return build_audio_procunit(state, unitid, desc, NULL, "Extension Unit");
+ return build_audio_procunit(state, unitid, desc, extunits, "Extension Unit");
}
@@ -2109,6 +2158,24 @@ static int snd_xonar_u1_controls_create(struct usb_mixer_interface *mixer)
return 0;
}
+void snd_emuusb_set_samplerate(struct snd_usb_audio *chip,
+ unsigned char samplerate_id)
+{
+ struct usb_mixer_interface *mixer;
+ struct list_head *p;
+ struct usb_mixer_elem_info *cval;
+ int unitid = 12; /*SamleRate ExtensionUnit ID*/
+ list_for_each(p, &chip->mixer_list) {
+ mixer = list_entry(p, struct usb_mixer_interface, list);
+ cval = mixer->id_elems[unitid];
+ if (cval) {
+ set_cur_ctl_value(cval, cval->control << 8, samplerate_id);
+ snd_usb_mixer_notify_id(mixer, unitid);
+ }
+ break;
+ }
+}
+
int snd_usb_create_mixer(struct snd_usb_audio *chip, int ctrlif,
int ignore_error)
{
--
1.6.6
^ permalink raw reply related [flat|nested] 8+ messages in thread* Re: [PATCH 1/1] Added functionality for E-mu 0404USB/0202USB/TrackerPre
2009-12-27 17:13 ` Sergiy Kovalchuk
@ 2009-12-28 11:33 ` Takashi Iwai
0 siblings, 0 replies; 8+ messages in thread
From: Takashi Iwai @ 2009-12-28 11:33 UTC (permalink / raw)
To: Sergiy Kovalchuk; +Cc: alsa-devel
At Sun, 27 Dec 2009 09:13:41 -0800 (PST),
Sergiy Kovalchuk wrote:
>
> !!! Sorry, previous patch is incorrect !!!
>
> > Thanks for the patch. Through a quick look, it's
> > fine.
> > But, could you fix the following and repost?
>
> Summary:
> Added functionality for E-mu 0404USB/0202USB/TrackerPre
>
> Added functionality:
> 1) Extension Units support (all XU settings now available at alsamixer, kmix, etc):
> - "AnalogueIn soft limiter" switch;
> - "Sample rate" selector (values 0,1,2,3,4,5 corresponds to 44.1 48 ... 192 kHz);
> - "DigitalIn CLK source" selector (internal/external) (**);
> - "DigitalOut format SPDIF/AC3" switch (**);
> (**)E-mu-0404usb only.
>
> 2) Automatic device sample rate adjustment depending on substream samplerate for both capture and playback substream.
>
>
> Signed-off-by: Sergiy Kovalchuk <cnb_zerg@yahoo.com>
Thanks, applied now with minor coding-style fixes.
Takashi
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 1/1] Added functionality for E-mu 0404USB/0202USB/TrackerPre
2009-12-21 20:39 [PATCH 1/1] Added functionality for E-mu 0404USB/0202USB/TrackerPre Zerg Cannibal
2009-12-25 13:29 ` Takashi Iwai
@ 2009-12-27 12:04 ` James Courtier-Dutton
2009-12-27 15:05 ` Sergiy Kovalchuk
1 sibling, 1 reply; 8+ messages in thread
From: James Courtier-Dutton @ 2009-12-27 12:04 UTC (permalink / raw)
To: Zerg Cannibal; +Cc: alsa-devel
2009/12/22 Zerg Cannibal <cnb_zerg@yahoo.com>:
> Added functionality:
> 1) Extension Units support (all XU settings now available at alsamixer, kmix, etc):
> - "AnalogueIn soft limiter" switch;
> - "Sample rate" selector (values 0,1,2,3,4,5 corresponds to 44.1 48 ... 192 kHz);
> - "DigitalIn CLK source" selector (internal/external) (**);
> - "DigitalOut format SPDIF/AC3" switch (**);
> (**)E-mu-0404usb only.
>
> 2) Automatic device sample rate adjustment depending on substream samplerate for both capture and playback substream.
>
> Patch is based on Mac OS-X driver (http://sourceforge.net/projects/zaudiodrivermac/) and successfully tested by Ubuntu community users for 0404usb and 0202usb.
Further info for set_format_emu_quirk()
The values of XU_CR_SELECTOR_CONTROL can be:
0 = 44100
1 = 48000
2 = 88200
3 = 96000
4 = 176400
5 = 192000
USB_XU_CLOCK_RATE has a number of controls
00: Does nothing.
01: Does nothing
02: Query supported sample rates: Bitmap
03: XU_CR_SELECTOR_CONTROL: as above.
USB_XU_CLOCK_SOURCE has a number of controls:
00: Does nothing
01: Does nothing
02: USB_XU_CLOCK_SOURCE_SELECTOR_CONTROL: = 1 for External from
SPDIF-IN, 0 = Internal.
USB_XU_DIGITAL_IO has a number of controls:
00: Does nothing
01: Does nothing
02: XU_DIGITAL_IO_SAMPLE_RATE_CONTROL: spdif input sample rate. GET
only. 32bit value.
03: XU_DIGITAL_IO_SYNC_SOURCE_LOCK_STATUS: "Lock indicator". GET only
1=Locked. 0=no-lock.
04: Does nothing
05: XU_DIGITAL_IO_OUTPUT_FRAME_FORMAT: 0 = undefined, 1 = Consumer,
Copyright OFF, 2 = Consumer, Copyright ON, 3 = Professional.
USB_XU_DEVICE_OPTIONS has a number of controls:
00: Does nothing
01: Does nothing
02: Does nothing
03: XU_DO_SOFT_LIMIT_CONTROL: GET/SET: 1 = Soft limit ON, 0 = Soft limit OFF.
I have no info regarding 0xe305 or 0xe306.
I have firmware upgrade details and firmware version querying details
and usb speed query details, if one needs them.
The above info might only apply to an older version of the firmware,
so the driver might have to behave differently depending on the
installed firmware version.
Kind Regards
James
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 1/1] Added functionality for E-mu 0404USB/0202USB/TrackerPre
2009-12-27 12:04 ` James Courtier-Dutton
@ 2009-12-27 15:05 ` Sergiy Kovalchuk
2009-12-28 10:47 ` James Courtier-Dutton
0 siblings, 1 reply; 8+ messages in thread
From: Sergiy Kovalchuk @ 2009-12-27 15:05 UTC (permalink / raw)
To: James Courtier-Dutton; +Cc: alsa-devel
>
> Further info for set_format_emu_quirk()
>
Thank you for valuable information, especially for digital-in/out control/status values.
My first approach is to bring full functionality for analogue playback and capture, and current patch meets this demand, except capturing above 96kHz (I've got nothing, but white noise).
I'll appreciate any information that relates to 174.6kHz and 192kHz capture for E-mu products (MacOS-X driver officially doesn't support it).
Also there no way to obtain DigitalIO status without spawning separate thread, which periodically request the status from device and updates mixer info. My alsa-development skill is poor, so I prefer to avoid such dangerous improvements at the moment.
With Best Regards, Sergiy.
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 1/1] Added functionality for E-mu 0404USB/0202USB/TrackerPre
2009-12-27 15:05 ` Sergiy Kovalchuk
@ 2009-12-28 10:47 ` James Courtier-Dutton
0 siblings, 0 replies; 8+ messages in thread
From: James Courtier-Dutton @ 2009-12-28 10:47 UTC (permalink / raw)
To: Sergiy Kovalchuk; +Cc: alsa-devel
2009/12/28 Sergiy Kovalchuk <cnb_zerg@yahoo.com>:
>>
>> Further info for set_format_emu_quirk()
>>
>
> Thank you for valuable information, especially for digital-in/out control/status values.
> My first approach is to bring full functionality for analogue playback and capture, and current patch meets this demand, except capturing above 96kHz (I've got nothing, but white noise).
> I'll appreciate any information that relates to 174.6kHz and 192kHz capture for E-mu products (MacOS-X driver officially doesn't support it).
>
> Also there no way to obtain DigitalIO status without spawning separate thread, which periodically request the status from device and updates mixer info. My alsa-development skill is poor, so I prefer to avoid such dangerous improvements at the moment.
>
> With Best Regards, Sergiy.
>
I do not have the hardware with me at the moment, so I cannot test this.
The information I have does talk about the stream format changing
depending on whether one is in Full-Speed or High-Speed USB mode.
The reason given for not following the USB audio standard for HS mode
is that some USB controllers are buggy and this gets round the
problem.
Regarding the capture problems:
When the device is in HS mode and the 1/2 ms transfer alternative
setting is selected. The descriptor says that the samples are of
TYPE_I_PCM.
The actual format within the TYPE_I_PCM packet is:
offset 0: size=4, Length of this packet (dwLength)
offset 4: size=dwLength - 4, packet of interleaved audio data.
So, you will have to get the first 4 bytes of each packet dropped in
order for the stream to lock like real TYPE_I_PCM.
This is a work-around for an issue seen with some EHCI hosts which for
every other packet incorrectly report the received packet length as
zero bytes to the audio driver.
Also, the first two packets of any recording should be dropped as they
contain unwanted data.
When the clock rate it changed, the alsa driver will have to also
switch to the correct USB endpoint alternate setting to match it.
Use this vendor specific command to determine which mode the EMU is in.
Input values:
bmRequestType: 0xc0 (Get)
bRequest: 0x2a: (GET_CONNECTION_SPEED)
wValue: Not used.
wIndex: Not used.
wLength: 1
Returns:
at offset 0: Size 1, Type: Number, 0 = Full-Speed, 1 = High-Speed.
Another useful one could be:
Input values:
bmRequestType: 0xc0 (Get)
bRequest: 0x01: (GET_DEVICE_INFO)
wValue: Not used.
wIndex: Not used.
wLength: 32
Returns:
Offset 0: size=4, not used, set to 0
Offset 4: size=4, FirmwareVersion,
D31-24: Major version number
D23-16: Minor version number
D15-09: Build Year
D08-05: Build Month
D04-00: Build day
Offset 8: size=4, Hardware version
D31-09: Set to 0
D08-00: Hardware version
Offset 12: size=4, not used, set to 0.
Regarding the Digital IO status, the emu 0202/0404 has an interrupt
endpoint the function as per USB Audio 1.0 specification, section
3.7.1.2.
The problem being, only the 0404 uses it.
I hope this info helps.
Kind Regards
James
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2009-12-28 11:33 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-12-21 20:39 [PATCH 1/1] Added functionality for E-mu 0404USB/0202USB/TrackerPre Zerg Cannibal
2009-12-25 13:29 ` Takashi Iwai
2009-12-27 16:50 ` Sergiy Kovalchuk
2009-12-27 17:13 ` Sergiy Kovalchuk
2009-12-28 11:33 ` Takashi Iwai
2009-12-27 12:04 ` James Courtier-Dutton
2009-12-27 15:05 ` Sergiy Kovalchuk
2009-12-28 10:47 ` James Courtier-Dutton
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.