[PATCH - Basic mixer support for Fast Track Ultra 3/6]Add mixer quirk for Fast Track Ultra devices

Felix Homann linuxaudio at showlabor.de
Wed May 18 10:05:34 CEST 2011


Signed-off-by: Felix Homann <linuxaudio at showlabor.de>

diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c
index ea95ce2..1c37792 100644
--- a/sound/usb/mixer.c
+++ b/sound/usb/mixer.c
@@ -542,6 +542,31 @@ static int add_control_to_empty(struct mixer_build *state, struct snd_kcontrol *
 	return 0;
 }
 
+/* 
+ * This is almost the same as 'add_control_to_empty' but using a mixer instead of a mixer_build
+ * it simplifies building a mixer for devices without proper descriptors,
+ * e.g. the Fast Track Ultra devices
+ */ 
+int add_unique_control_to_empty_mixer(struct usb_mixer_interface *mixer, struct snd_kcontrol *kctl)
+{
+	struct usb_mixer_elem_info *cval = kctl->private_data;
+	int err;
+	
+	/* No duplicates! */
+	if (snd_ctl_find_id(mixer->chip->card, &kctl->id))
+		return 0;
+
+	if ((err = snd_ctl_add(mixer->chip->card, kctl)) < 0) {
+		snd_printd(KERN_ERR "cannot add control (err = %d)\n", err);
+		return err;
+	}
+	
+	cval->elem_id = &kctl->id;
+	cval->next_id_elem = mixer->id_elems[cval->id];
+	mixer->id_elems[cval->id] = cval;
+	
+	return 0;
+}
 
 /*
  * get a terminal name string
@@ -1331,6 +1356,57 @@ static void build_mixer_unit_ctl(struct mixer_build *state,
 	add_control_to_empty(state, kctl);
 }
 
+/*
+ * build a mixer unit control and give it a name
+ *
+ * this is essentially identical to build_mixer_unit_ctl but doesn't
+ * rely on proper descriptors to get a name for a control.
+ * At least, useful for Fast Track Ultra devices.
+ */
+
+int build_named_mixer_unit_ctl(struct usb_mixer_interface *mixer,
+	int in_pin, int in_ch, int unitid, int val_type, unsigned int cmask, char* ctrl_name, int channels)
+{
+	struct usb_mixer_elem_info *cval;
+	struct snd_kcontrol *kctl;
+	int err;
+	
+	cval = kzalloc(sizeof(*cval), GFP_KERNEL);
+	if (! cval)
+		return -1;
+	
+	cval->mixer = mixer;
+	cval->id = unitid;
+	cval->control = in_ch + 1; /* based on 1 */
+	cval->val_type = val_type; /* like USB_MIXER_S16 etc. */
+	if (!((0 < channels) && (channels <= MAX_CHANNELS)))
+		return -1;
+	cval->channels = 1;
+	cval->cmask = cmask;
+	/* get min/max values */
+	get_min_max(cval, 0);
+	
+	kctl = snd_ctl_new1(&usb_feature_unit_ctl, cval);
+	if (! kctl) {
+		snd_printk(KERN_ERR "cannot malloc kcontrol\n");
+		kfree(cval);
+		return -1;
+	}
+	
+	kctl->tlv.c = mixer_vol_tlv;
+	kctl->vd[0].access |= 
+		SNDRV_CTL_ELEM_ACCESS_TLV_READ |
+		SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK;
+	kctl->private_free = usb_mixer_elem_free;
+	
+	sprintf(kctl->id.name, ctrl_name);
+	
+	if (err = add_unique_control_to_empty_mixer(mixer, kctl))
+		return err;
+	
+	return 0;
+}
+
 
 /*
  * parse a mixer unit
diff --git a/sound/usb/mixer.h b/sound/usb/mixer.h
index 86af922..6fe7bea 100644
--- a/sound/usb/mixer.h
+++ b/sound/usb/mixer.h
@@ -61,6 +61,9 @@ void snd_usb_mixer_notify_id(struct usb_mixer_interface *mixer, int unitid);
 
 int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval,
 				int request, int validx, int value_set);
+int build_named_mixer_unit_ctl(struct usb_mixer_interface *mixer,
+		int in_pin, int in_ch, int unitid, int val_type, 
+		unsigned int cmask, char* ctrl_name, int channels);
 void snd_usb_mixer_inactivate(struct usb_mixer_interface *mixer);
 int snd_usb_mixer_activate(struct usb_mixer_interface *mixer);
 
diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c
index 73dcc82..e87f359 100644
--- a/sound/usb/mixer_quirks.c
+++ b/sound/usb/mixer_quirks.c
@@ -500,6 +500,36 @@ void snd_emuusb_set_samplerate(struct snd_usb_audio *chip,
 	}
 }
 
+/*
+ * Create mixer controls for Fast Track Ultra (8R)
+ */
+int snd_ftu_controls_create(struct usb_mixer_interface *mixer)
+{
+	char name[44];
+	int out, in_ch, unitid, err;
+	unsigned int cmask;
+	int val_type =  USB_MIXER_S16;
+	int channels = 1; /* mono channels */
+	
+	unitid = 5; // FTU's unit id
+	for (out = 0; out < 8; ++out) {
+		for (in_ch = 0; in_ch < 16; ++in_ch) {
+				cmask = (1 << in_ch);
+			if (in_ch < 8)
+				sprintf(name, "AIn%d - Out%d Capture Volume", in_ch + 1, out + 1);
+			else if (in_ch >= 8)
+				sprintf(name, "DIn%d - Out%d Playback Volume", in_ch - 7, out + 1);     
+			if ((err = build_named_mixer_unit_ctl(mixer, in_ch, out, unitid, 
+				val_type, cmask, name, channels))) {
+				return err;
+			}
+		}
+	}
+	
+	return 0;
+}
+
+
 int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer)
 {
 	int err = 0;
@@ -537,6 +567,10 @@ int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer)
 				snd_nativeinstruments_ta10_mixers,
 				ARRAY_SIZE(snd_nativeinstruments_ta10_mixers));
 		break;
+	case USB_ID(0x0763, 0x2080):/* M-Audio Fast Track Ultra */
+	case USB_ID(0x0763, 0x2081): /* M-Audio Fast Track Ultra 8R */
+		err = snd_ftu_controls_create(mixer);
+		break;
 	}
 
 	return err;
-- 
1.7.4.1


--------------000101040900080309070209
Content-Type: text/x-patch;
 name="0004-Try-to-create-a-mixer-for-quirked-devices-too.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0004-Try-to-create-a-mixer-for-quirked-devices-too.patch"



More information about the Alsa-devel mailing list