From 3195954da9cdb1cadb2059921c62e69d376c624f Mon Sep 17 00:00:00 2001
From: Andrea Borgia <andrea@borgia.bo.it>
Date: Wed, 7 Jan 2009 22:58:50 +0100
Subject: ALSA: preliminary support for Toshiba SB-0500

The Toshiba Multimedia Center SB-0500 is a rebranded version of the
Creative Technology SB Live! 24-bit External: it shares the same chipset
and only has minor cosmetic differences. Remote controller works with
alsa_usb module, basic audio is there and mixer controls are mostly
untested.

Signed-off-by: Andrea Borgia <andrea@borgia.bo.it>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/usb/usbmixer.c      | 15 ++++++++++-----
 sound/usb/usbmixer_maps.c |  5 +++++
 2 files changed, 15 insertions(+), 5 deletions(-)

(limited to 'sound')

diff --git a/sound/usb/usbmixer.c b/sound/usb/usbmixer.c
index 00397c8a765b..bc8bd00047ad 100644
--- a/sound/usb/usbmixer.c
+++ b/sound/usb/usbmixer.c
@@ -66,6 +66,7 @@ static const struct rc_config {
 	{ USB_ID(0x041e, 0x3000), 0, 1, 2, 1,  18, 0x0013 }, /* Extigy       */
 	{ USB_ID(0x041e, 0x3020), 2, 1, 6, 6,  18, 0x0013 }, /* Audigy 2 NX  */
 	{ USB_ID(0x041e, 0x3040), 2, 2, 6, 6,  2,  0x6e91 }, /* Live! 24-bit */
+	{ USB_ID(0x041e, 0x3048), 2, 2, 6, 6,  2,  0x6e91 }, /* Toshiba SB0500 */
 };
 
 struct usb_mixer_interface {
@@ -1706,7 +1707,8 @@ static void snd_usb_mixer_memory_change(struct usb_mixer_interface *mixer,
 		break;
 	/* live24ext: 4 = line-in jack */
 	case 3:	/* hp-out jack (may actuate Mute) */
-		if (mixer->chip->usb_id == USB_ID(0x041e, 0x3040))
+		if (mixer->chip->usb_id == USB_ID(0x041e, 0x3040) ||
+		    mixer->chip->usb_id == USB_ID(0x041e, 0x3048))
 			snd_usb_mixer_notify_id(mixer, mixer->rc_cfg->mute_mixer_id);
 		break;
 	default:
@@ -1956,8 +1958,9 @@ static int snd_audigy2nx_controls_create(struct usb_mixer_interface *mixer)
 	int i, err;
 
 	for (i = 0; i < ARRAY_SIZE(snd_audigy2nx_controls); ++i) {
-		if (i > 1 &&  /* Live24ext has 2 LEDs only */
-			mixer->chip->usb_id == USB_ID(0x041e, 0x3040))
+		if (i > 1 && /* Live24ext has 2 LEDs only */
+			(mixer->chip->usb_id == USB_ID(0x041e, 0x3040) ||
+			 mixer->chip->usb_id == USB_ID(0x041e, 0x3048)))
 			break; 
 		err = snd_ctl_add(mixer->chip->card,
 				  snd_ctl_new1(&snd_audigy2nx_controls[i], mixer));
@@ -1994,7 +1997,8 @@ static void snd_audigy2nx_proc_read(struct snd_info_entry *entry,
 	snd_iprintf(buffer, "%s jacks\n\n", mixer->chip->card->shortname);
 	if (mixer->chip->usb_id == USB_ID(0x041e, 0x3020))
 		jacks = jacks_audigy2nx;
-	else if (mixer->chip->usb_id == USB_ID(0x041e, 0x3040))
+	else if (mixer->chip->usb_id == USB_ID(0x041e, 0x3040) ||
+		 mixer->chip->usb_id == USB_ID(0x041e, 0x3048))
 		jacks = jacks_live24ext;
 	else
 		return;
@@ -2044,7 +2048,8 @@ int snd_usb_create_mixer(struct snd_usb_audio *chip, int ctrlif,
 		goto _error;
 
 	if (mixer->chip->usb_id == USB_ID(0x041e, 0x3020) ||
-	    mixer->chip->usb_id == USB_ID(0x041e, 0x3040)) {
+	    mixer->chip->usb_id == USB_ID(0x041e, 0x3040) ||
+	    mixer->chip->usb_id == USB_ID(0x041e, 0x3048)) {
 		struct snd_info_entry *entry;
 
 		if ((err = snd_audigy2nx_controls_create(mixer)) < 0)
diff --git a/sound/usb/usbmixer_maps.c b/sound/usb/usbmixer_maps.c
index d755be0ad811..f41214f3ad6b 100644
--- a/sound/usb/usbmixer_maps.c
+++ b/sound/usb/usbmixer_maps.c
@@ -284,6 +284,11 @@ static struct usbmix_ctl_map usbmix_ctl_maps[] = {
 		.id = USB_ID(0x041e, 0x3040),
 		.map = live24ext_map,
 	},
+	{
+		.id = USB_ID(0x041e, 0x3048),
+		.map = audigy2nx_map,
+		.selector_map = audigy2nx_selectors,
+	},
 	{
 		/* Hercules DJ Console (Windows Edition) */
 		.id = USB_ID(0x06f8, 0xb000),
-- 
cgit v1.2.3-58-ga151


From dc61b66fc724f89d357c43e2319d2cb7bec1e517 Mon Sep 17 00:00:00 2001
From: Andrea Borgia <andrea@borgia.bo.it>
Date: Mon, 12 Jan 2009 23:17:47 +0100
Subject: ALSA: rename "Device" to "Toshiba SB-0500" via quirks

Signed-off-by: Andrea Borgia <andrea@borgia.bo.it>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/usb/usbquirks.h | 10 ++++++++++
 1 file changed, 10 insertions(+)

(limited to 'sound')

diff --git a/sound/usb/usbquirks.h b/sound/usb/usbquirks.h
index 92115755d98e..d59323ecd571 100644
--- a/sound/usb/usbquirks.h
+++ b/sound/usb/usbquirks.h
@@ -39,6 +39,16 @@
 	.idProduct = prod, \
 	.bInterfaceClass = USB_CLASS_VENDOR_SPEC
 
+/* Creative/Toshiba Multimedia Center SB-0500 */
+{
+	USB_DEVICE(0x041e, 0x3048),
+	.driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
+		.vendor_name = "Toshiba",
+		.product_name = "SB-0500",
+		.ifnum = QUIRK_NO_INTERFACE
+	}
+},
+
 /* Creative/E-Mu devices */
 {
 	USB_DEVICE(0x041e, 0x3010),
-- 
cgit v1.2.3-58-ga151


From 641b4879444c0edb276fedca5c2fcbd2e5c70044 Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Thu, 15 Jan 2009 17:05:24 +0100
Subject: ALSA: usb-audio - Cache mixer values

Cache mixer values in usb-audio driver to reduce too excessive
accesses to the hardware.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/usb/usbmixer.c | 122 +++++++++++++++++++++++++++++----------------------
 1 file changed, 70 insertions(+), 52 deletions(-)

(limited to 'sound')

diff --git a/sound/usb/usbmixer.c b/sound/usb/usbmixer.c
index 00397c8a765b..c07b3f8485e3 100644
--- a/sound/usb/usbmixer.c
+++ b/sound/usb/usbmixer.c
@@ -110,6 +110,8 @@ struct mixer_build {
 	const struct usbmix_selector_map *selector_map;
 };
 
+#define MAX_CHANNELS	10	/* max logical channels */
+
 struct usb_mixer_elem_info {
 	struct usb_mixer_interface *mixer;
 	struct usb_mixer_elem_info *next_id_elem; /* list of controls with same id */
@@ -120,6 +122,8 @@ struct usb_mixer_elem_info {
 	int channels;
 	int val_type;
 	int min, max, res;
+	int cached;
+	int cache_val[MAX_CHANNELS];
 	u8 initialized;
 };
 
@@ -181,8 +185,6 @@ enum {
 	USB_PROC_DCR_RELEASE = 6,
 };
 
-#define MAX_CHANNELS	10	/* max logical channels */
-
 
 /*
  * manual mapping of mixer names
@@ -376,11 +378,35 @@ static int get_cur_ctl_value(struct usb_mixer_elem_info *cval, int validx, int *
 }
 
 /* channel = 0: master, 1 = first channel */
-static inline int get_cur_mix_value(struct usb_mixer_elem_info *cval, int channel, int *value)
+static inline int get_cur_mix_raw(struct usb_mixer_elem_info *cval,
+				  int channel, int *value)
 {
 	return get_ctl_value(cval, GET_CUR, (cval->control << 8) | channel, value);
 }
 
+static int get_cur_mix_value(struct usb_mixer_elem_info *cval,
+			     int channel, int index, int *value)
+{
+	int err;
+
+	if (cval->cached & (1 << channel)) {
+		*value = cval->cache_val[index];
+		return 0;
+	}
+	err = get_cur_mix_raw(cval, channel, value);
+	if (err < 0) {
+		if (!cval->mixer->ignore_ctl_error)
+			snd_printd(KERN_ERR "cannot get current value for "
+				   "control %d ch %d: err = %d\n",
+				   cval->control, channel, err);
+		return err;
+	}
+	cval->cached |= 1 << channel;
+	cval->cache_val[index] = *value;
+	return 0;
+}
+
+
 /*
  * set a mixer value
  */
@@ -412,9 +438,17 @@ static int set_cur_ctl_value(struct usb_mixer_elem_info *cval, int validx, int v
 	return set_ctl_value(cval, SET_CUR, validx, value);
 }
 
-static inline int set_cur_mix_value(struct usb_mixer_elem_info *cval, int channel, int value)
+static int set_cur_mix_value(struct usb_mixer_elem_info *cval, int channel,
+			     int index, int value)
 {
-	return set_ctl_value(cval, SET_CUR, (cval->control << 8) | channel, value);
+	int err;
+	err = set_ctl_value(cval, SET_CUR, (cval->control << 8) | channel,
+			    value);
+	if (err < 0)
+		return err;
+	cval->cached |= 1 << channel;
+	cval->cache_val[index] = value;
+	return 0;
 }
 
 /*
@@ -718,7 +752,7 @@ static int get_min_max(struct usb_mixer_elem_info *cval, int default_min)
 		if (cval->min + cval->res < cval->max) {
 			int last_valid_res = cval->res;
 			int saved, test, check;
-			get_cur_mix_value(cval, minchn, &saved);
+			get_cur_mix_raw(cval, minchn, &saved);
 			for (;;) {
 				test = saved;
 				if (test < cval->max)
@@ -726,8 +760,8 @@ static int get_min_max(struct usb_mixer_elem_info *cval, int default_min)
 				else
 					test -= cval->res;
 				if (test < cval->min || test > cval->max ||
-				    set_cur_mix_value(cval, minchn, test) ||
-				    get_cur_mix_value(cval, minchn, &check)) {
+				    set_cur_mix_value(cval, minchn, 0, test) ||
+				    get_cur_mix_raw(cval, minchn, &check)) {
 					cval->res = last_valid_res;
 					break;
 				}
@@ -735,7 +769,7 @@ static int get_min_max(struct usb_mixer_elem_info *cval, int default_min)
 					break;
 				cval->res *= 2;
 			}
-			set_cur_mix_value(cval, minchn, saved);
+			set_cur_mix_value(cval, minchn, 0, saved);
 		}
 
 		cval->initialized = 1;
@@ -775,35 +809,25 @@ static int mixer_ctl_feature_get(struct snd_kcontrol *kcontrol, struct snd_ctl_e
 	struct usb_mixer_elem_info *cval = kcontrol->private_data;
 	int c, cnt, val, err;
 
+	ucontrol->value.integer.value[0] = cval->min;
 	if (cval->cmask) {
 		cnt = 0;
 		for (c = 0; c < MAX_CHANNELS; c++) {
-			if (cval->cmask & (1 << c)) {
-				err = get_cur_mix_value(cval, c + 1, &val);
-				if (err < 0) {
-					if (cval->mixer->ignore_ctl_error) {
-						ucontrol->value.integer.value[0] = cval->min;
-						return 0;
-					}
-					snd_printd(KERN_ERR "cannot get current value for control %d ch %d: err = %d\n", cval->control, c + 1, err);
-					return err;
-				}
-				val = get_relative_value(cval, val);
-				ucontrol->value.integer.value[cnt] = val;
-				cnt++;
-			}
+			if (!(cval->cmask & (1 << c)))
+				continue;
+			err = get_cur_mix_value(cval, c + 1, cnt, &val);
+			if (err < 0)
+				return cval->mixer->ignore_ctl_error ? 0 : err;
+			val = get_relative_value(cval, val);
+			ucontrol->value.integer.value[cnt] = val;
+			cnt++;
 		}
+		return 0;
 	} else {
 		/* master channel */
-		err = get_cur_mix_value(cval, 0, &val);
-		if (err < 0) {
-			if (cval->mixer->ignore_ctl_error) {
-				ucontrol->value.integer.value[0] = cval->min;
-				return 0;
-			}
-			snd_printd(KERN_ERR "cannot get current value for control %d master ch: err = %d\n", cval->control, err);
-			return err;
-		}
+		err = get_cur_mix_value(cval, 0, 0, &val);
+		if (err < 0)
+			return cval->mixer->ignore_ctl_error ? 0 : err;
 		val = get_relative_value(cval, val);
 		ucontrol->value.integer.value[0] = val;
 	}
@@ -820,34 +844,28 @@ static int mixer_ctl_feature_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e
 	if (cval->cmask) {
 		cnt = 0;
 		for (c = 0; c < MAX_CHANNELS; c++) {
-			if (cval->cmask & (1 << c)) {
-				err = get_cur_mix_value(cval, c + 1, &oval);
-				if (err < 0) {
-					if (cval->mixer->ignore_ctl_error)
-						return 0;
-					return err;
-				}
-				val = ucontrol->value.integer.value[cnt];
-				val = get_abs_value(cval, val);
-				if (oval != val) {
-					set_cur_mix_value(cval, c + 1, val);
-					changed = 1;
-				}
-				get_cur_mix_value(cval, c + 1, &val);
-				cnt++;
+			if (!(cval->cmask & (1 << c)))
+				continue;
+			err = get_cur_mix_value(cval, c + 1, cnt, &oval);
+			if (err < 0)
+				return cval->mixer->ignore_ctl_error ? 0 : err;
+			val = ucontrol->value.integer.value[cnt];
+			val = get_abs_value(cval, val);
+			if (oval != val) {
+				set_cur_mix_value(cval, c + 1, cnt, val);
+				changed = 1;
 			}
+			cnt++;
 		}
 	} else {
 		/* master channel */
-		err = get_cur_mix_value(cval, 0, &oval);
-		if (err < 0 && cval->mixer->ignore_ctl_error)
-			return 0;
+		err = get_cur_mix_value(cval, 0, 0, &oval);
 		if (err < 0)
-			return err;
+			return cval->mixer->ignore_ctl_error ? 0 : err;
 		val = ucontrol->value.integer.value[0];
 		val = get_abs_value(cval, val);
 		if (val != oval) {
-			set_cur_mix_value(cval, 0, val);
+			set_cur_mix_value(cval, 0, 0, val);
 			changed = 1;
 		}
 	}
-- 
cgit v1.2.3-58-ga151


From 8693290b9038f32b6b9bafd97b7e18465d62655b Mon Sep 17 00:00:00 2001
From: Andreas Bergmeier <lcid-fire@gmx.net>
Date: Sun, 18 Jan 2009 18:48:03 +0100
Subject: ALSA: usb-audio - Quirk for Serato phono

Ignore errors (wrong usb interface data) found when using the serato
scratch live box with alsa

Thus the alsa controls can be accessed (beware: they don't work though -
but at least it's one ugly error message less)

Signed-off-by: Andreas Bergmeier <lcid-fire@gmx.net>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/usb/usbmixer_maps.c | 21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)

(limited to 'sound')

diff --git a/sound/usb/usbmixer_maps.c b/sound/usb/usbmixer_maps.c
index f41214f3ad6b..3e5d66cf1f5a 100644
--- a/sound/usb/usbmixer_maps.c
+++ b/sound/usb/usbmixer_maps.c
@@ -261,6 +261,22 @@ static struct usbmix_name_map aureon_51_2_map[] = {
 	{} /* terminator */
 };
 
+static struct usbmix_name_map scratch_live_map[] = {
+	/* 1: IT Line 1 (USB streaming) */
+	/* 2: OT Line 1 (Speaker) */
+	/* 3: IT Line 1 (Line connector) */
+	{ 4, "Line 1 In" }, /* FU */
+	/* 5: OT Line 1 (USB streaming) */
+	/* 6: IT Line 2 (USB streaming) */
+	/* 7: OT Line 2 (Speaker) */
+	/* 8: IT Line 2 (Line connector) */
+	{ 9, "Line 2 In" }, /* FU */
+	/* 10: OT Line 2 (USB streaming) */
+	/* 11: IT Mic (Line connector) */
+	/* 12: OT Mic (USB streaming) */
+	{ 0 } /* terminator */
+};
+
 /*
  * Control map entries
  */
@@ -316,6 +332,11 @@ static struct usbmix_ctl_map usbmix_ctl_maps[] = {
 		.id = USB_ID(0x0ccd, 0x0028),
 		.map = aureon_51_2_map,
 	},
+	{
+		.id = USB_ID(0x13e5, 0x0001),
+		.map = scratch_live_map,
+		.ignore_ctl_error = 1,
+	},
 	{ 0 } /* terminator */
 };
 
-- 
cgit v1.2.3-58-ga151


From b7eb4a06e9980973755b7e95a6d97fb8decbf8fd Mon Sep 17 00:00:00 2001
From: Clemens Ladisch <clemens@ladisch.de>
Date: Mon, 26 Jan 2009 08:08:34 +0100
Subject: sound: usb-audio: use normal number of frames for no-data URBs

When sending a silence URB (before playback has started, or when it is
paused), use the number of frames that would be normally sent instead of
a single frame so that the rate at which completion interrupts arrive is
consistent.

Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/usb/usbaudio.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

(limited to 'sound')

diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c
index c709b9563226..417d557ed641 100644
--- a/sound/usb/usbaudio.c
+++ b/sound/usb/usbaudio.c
@@ -525,7 +525,7 @@ static int snd_usb_audio_next_packet_size(struct snd_usb_substream *subs)
 /*
  * Prepare urb for streaming before playback starts or when paused.
  *
- * We don't have any data, so we send a frame of silence.
+ * We don't have any data, so we send silence.
  */
 static int prepare_nodata_playback_urb(struct snd_usb_substream *subs,
 				       struct snd_pcm_runtime *runtime,
@@ -537,13 +537,13 @@ static int prepare_nodata_playback_urb(struct snd_usb_substream *subs,
 
 	offs = 0;
 	urb->dev = ctx->subs->dev;
-	urb->number_of_packets = subs->packs_per_ms;
-	for (i = 0; i < subs->packs_per_ms; ++i) {
+	for (i = 0; i < ctx->packets; ++i) {
 		counts = snd_usb_audio_next_packet_size(subs);
 		urb->iso_frame_desc[i].offset = offs * stride;
 		urb->iso_frame_desc[i].length = counts * stride;
 		offs += counts;
 	}
+	urb->number_of_packets = ctx->packets;
 	urb->transfer_buffer_length = offs * stride;
 	memset(urb->transfer_buffer,
 	       subs->cur_audiofmt->format == SNDRV_PCM_FORMAT_U8 ? 0x80 : 0,
-- 
cgit v1.2.3-58-ga151


From 4d788e040b72d2a46ea3ba726b7fa0b65de06c88 Mon Sep 17 00:00:00 2001
From: Clemens Ladisch <clemens@ladisch.de>
Date: Mon, 26 Jan 2009 08:09:28 +0100
Subject: sound: usb-audio: limit playback queue length

Once our URBs contain enough packets, queueing more URBs does not give
us any additional underrun protection (as we use double-buffering) but
just increases latency unnecessarily.  Therefore, we try to limit the
queue length to some reasonable value.

Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/usb/usbaudio.c | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

(limited to 'sound')

diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c
index 417d557ed641..f3d4de23fedf 100644
--- a/sound/usb/usbaudio.c
+++ b/sound/usb/usbaudio.c
@@ -108,6 +108,7 @@ MODULE_PARM_DESC(ignore_ctl_error,
 #define MAX_URBS	8
 #define SYNC_URBS	4	/* always four urbs for sync */
 #define MIN_PACKS_URB	1	/* minimum 1 packet per urb */
+#define MAX_QUEUE	24	/* try not to exceed this queue length, in ms */
 
 struct audioformat {
 	struct list_head list;
@@ -1079,7 +1080,7 @@ static int init_substream_urbs(struct snd_usb_substream *subs, unsigned int peri
 
 	/* decide how many packets to be used */
 	if (is_playback) {
-		unsigned int minsize;
+		unsigned int minsize, maxpacks;
 		/* determine how small a packet can be */
 		minsize = (subs->freqn >> (16 - subs->datainterval))
 			  * (frame_bits >> 3);
@@ -1094,6 +1095,12 @@ static int init_substream_urbs(struct snd_usb_substream *subs, unsigned int peri
 		/* we need at least two URBs for queueing */
 		if (total_packs < 2 * MIN_PACKS_URB * packs_per_ms)
 			total_packs = 2 * MIN_PACKS_URB * packs_per_ms;
+		else {
+			/* and we don't want too long a queue either */
+			maxpacks = max((unsigned int)MAX_QUEUE, urb_packs * 2);
+			if (total_packs > maxpacks * packs_per_ms)
+				total_packs = maxpacks * packs_per_ms;
+		}
 	} else {
 		total_packs = MAX_URBS * urb_packs;
 	}
-- 
cgit v1.2.3-58-ga151


From 160389c8d21c8139a93191c2e5ca2273f311ed4e Mon Sep 17 00:00:00 2001
From: Clemens Ladisch <clemens@ladisch.de>
Date: Mon, 26 Jan 2009 08:10:19 +0100
Subject: sound: usb-audio: make URB sizes more equal

Distribute the packets evenly among the URBs, instead of making all URBs
except the last one to have the maximum size.  This makes the timing of
pointer updates more regular and removes some special cases from the
code.

Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/usb/usbaudio.c | 29 +++++------------------------
 1 file changed, 5 insertions(+), 24 deletions(-)

(limited to 'sound')

diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c
index f3d4de23fedf..44485b29f675 100644
--- a/sound/usb/usbaudio.c
+++ b/sound/usb/usbaudio.c
@@ -1035,9 +1035,9 @@ static void release_substream_urbs(struct snd_usb_substream *subs, int force)
 static int init_substream_urbs(struct snd_usb_substream *subs, unsigned int period_bytes,
 			       unsigned int rate, unsigned int frame_bits)
 {
-	unsigned int maxsize, n, i;
+	unsigned int maxsize, i;
 	int is_playback = subs->direction == SNDRV_PCM_STREAM_PLAYBACK;
-	unsigned int npacks[MAX_URBS], urb_packs, total_packs, packs_per_ms;
+	unsigned int urb_packs, total_packs, packs_per_ms;
 
 	/* calculate the frequency in 16.16 format */
 	if (snd_usb_get_speed(subs->dev) == USB_SPEED_FULL)
@@ -1109,31 +1109,11 @@ static int init_substream_urbs(struct snd_usb_substream *subs, unsigned int peri
 		/* too much... */
 		subs->nurbs = MAX_URBS;
 		total_packs = MAX_URBS * urb_packs;
-	}
-	n = total_packs;
-	for (i = 0; i < subs->nurbs; i++) {
-		npacks[i] = n > urb_packs ? urb_packs : n;
-		n -= urb_packs;
-	}
-	if (subs->nurbs <= 1) {
+	} else if (subs->nurbs < 2) {
 		/* too little - we need at least two packets
 		 * to ensure contiguous playback/capture
 		 */
 		subs->nurbs = 2;
-		npacks[0] = (total_packs + 1) / 2;
-		npacks[1] = total_packs - npacks[0];
-	} else if (npacks[subs->nurbs-1] < MIN_PACKS_URB * packs_per_ms) {
-		/* the last packet is too small.. */
-		if (subs->nurbs > 2) {
-			/* merge to the first one */
-			npacks[0] += npacks[subs->nurbs - 1];
-			subs->nurbs--;
-		} else {
-			/* divide to two */
-			subs->nurbs = 2;
-			npacks[0] = (total_packs + 1) / 2;
-			npacks[1] = total_packs - npacks[0];
-		}
 	}
 
 	/* allocate and initialize data urbs */
@@ -1141,7 +1121,8 @@ static int init_substream_urbs(struct snd_usb_substream *subs, unsigned int peri
 		struct snd_urb_ctx *u = &subs->dataurb[i];
 		u->index = i;
 		u->subs = subs;
-		u->packets = npacks[i];
+		u->packets = (i + 1) * total_packs / subs->nurbs
+			- i * total_packs / subs->nurbs;
 		u->buffer_size = maxsize * u->packets;
 		if (subs->fmt_type == USB_FORMAT_TYPE_II)
 			u->packets++; /* for transfer delimiter */
-- 
cgit v1.2.3-58-ga151


From b9d710b3c530ed91e8683933fe94c7605d175bf5 Mon Sep 17 00:00:00 2001
From: Andreas Bergmeier <lcid-fire@gmx.net>
Date: Sat, 24 Jan 2009 12:15:14 +0100
Subject: ALSA: usbaudio - use printf format instead of hardcoding it

Rather use printf format instead of hardcoding prefix like 0x.
A next step would be to predefine certain formats.

Signed-off-by: Andreas Bergmeier <lcid-fire@gmx.net>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/usb/usbaudio.c | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

(limited to 'sound')

diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c
index 44485b29f675..4636926d12d7 100644
--- a/sound/usb/usbaudio.c
+++ b/sound/usb/usbaudio.c
@@ -1280,14 +1280,14 @@ static int init_usb_sample_rate(struct usb_device *dev, int iface,
 		if ((err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), SET_CUR,
 					   USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_OUT,
 					   SAMPLING_FREQ_CONTROL << 8, ep, data, 3, 1000)) < 0) {
-			snd_printk(KERN_ERR "%d:%d:%d: cannot set freq %d to ep 0x%x\n",
+			snd_printk(KERN_ERR "%d:%d:%d: cannot set freq %d to ep %#x\n",
 				   dev->devnum, iface, fmt->altsetting, rate, ep);
 			return err;
 		}
 		if ((err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), GET_CUR,
 					   USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_IN,
 					   SAMPLING_FREQ_CONTROL << 8, ep, data, 3, 1000)) < 0) {
-			snd_printk(KERN_WARNING "%d:%d:%d: cannot get freq at ep 0x%x\n",
+			snd_printk(KERN_WARNING "%d:%d:%d: cannot get freq at ep %#x\n",
 				   dev->devnum, iface, fmt->altsetting, ep);
 			return 0; /* some devices don't support reading */
 		}
@@ -1456,7 +1456,7 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream,
 	channels = params_channels(hw_params);
 	fmt = find_format(subs, format, rate, channels);
 	if (!fmt) {
-		snd_printd(KERN_DEBUG "cannot set format: format = 0x%x, rate = %d, channels = %d\n",
+		snd_printd(KERN_DEBUG "cannot set format: format = %#x, rate = %d, channels = %d\n",
 			   format, rate, channels);
 		return -EINVAL;
 	}
@@ -2148,7 +2148,7 @@ static void proc_dump_substream_formats(struct snd_usb_substream *subs, struct s
 		fp = list_entry(p, struct audioformat, list);
 		snd_iprintf(buffer, "  Interface %d\n", fp->iface);
 		snd_iprintf(buffer, "    Altset %d\n", fp->altsetting);
-		snd_iprintf(buffer, "    Format: 0x%x\n", fp->format);
+		snd_iprintf(buffer, "    Format: %#x\n", fp->format);
 		snd_iprintf(buffer, "    Channels: %d\n", fp->channels);
 		snd_iprintf(buffer, "    Endpoint: %d %s (%s)\n",
 			    fp->endpoint & USB_ENDPOINT_NUMBER_MASK,
@@ -2168,7 +2168,7 @@ static void proc_dump_substream_formats(struct snd_usb_substream *subs, struct s
 			snd_iprintf(buffer, "\n");
 		}
 		// snd_iprintf(buffer, "    Max Packet Size = %d\n", fp->maxpacksize);
-		// snd_iprintf(buffer, "    EP Attribute = 0x%x\n", fp->attributes);
+		// snd_iprintf(buffer, "    EP Attribute = %#x\n", fp->attributes);
 	}
 }
 
@@ -2607,7 +2607,7 @@ static int parse_audio_format_ii(struct snd_usb_audio *chip, struct audioformat
 		fp->format = SNDRV_PCM_FORMAT_MPEG;
 		break;
 	default:
-		snd_printd(KERN_INFO "%d:%u:%d : unknown format tag 0x%x is detected.  processed as MPEG.\n",
+		snd_printd(KERN_INFO "%d:%u:%d : unknown format tag %#x is detected.  processed as MPEG.\n",
 			   chip->dev->devnum, fp->iface, fp->altsetting, format);
 		fp->format = SNDRV_PCM_FORMAT_MPEG;
 		break;
@@ -2805,7 +2805,7 @@ static int parse_audio_endpoints(struct snd_usb_audio *chip, int iface_no)
 			continue;
 		}
 
-		snd_printdd(KERN_INFO "%d:%u:%d: add audio endpoint 0x%x\n", dev->devnum, iface_no, altno, fp->endpoint);
+		snd_printdd(KERN_INFO "%d:%u:%d: add audio endpoint %#x\n", dev->devnum, iface_no, altno, fp->endpoint);
 		err = add_audio_endpoint(chip, stream, fp);
 		if (err < 0) {
 			kfree(fp->rate_table);
-- 
cgit v1.2.3-58-ga151


From 54530bded6ecf22d683423b66fc3cd6dddb249aa Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Thu, 5 Feb 2009 15:55:18 +0100
Subject: ALSA: usb - Add missing KERN_* prefix to printk

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/usb/usbaudio.c         | 6 ++++--
 sound/usb/usbmixer.c         | 5 ++++-
 sound/usb/usx2y/usb_stream.c | 2 +-
 3 files changed, 9 insertions(+), 4 deletions(-)

(limited to 'sound')

diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c
index 4636926d12d7..c69cc6e4f549 100644
--- a/sound/usb/usbaudio.c
+++ b/sound/usb/usbaudio.c
@@ -1419,9 +1419,11 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt)
 	subs->cur_audiofmt = fmt;
 
 #if 0
-	printk("setting done: format = %d, rate = %d..%d, channels = %d\n",
+	printk(KERN_DEBUG
+	       "setting done: format = %d, rate = %d..%d, channels = %d\n",
 	       fmt->format, fmt->rate_min, fmt->rate_max, fmt->channels);
-	printk("  datapipe = 0x%0x, syncpipe = 0x%0x\n",
+	printk(KERN_DEBUG
+	       "  datapipe = 0x%0x, syncpipe = 0x%0x\n",
 	       subs->datapipe, subs->syncpipe);
 #endif
 
diff --git a/sound/usb/usbmixer.c b/sound/usb/usbmixer.c
index 330f2fbff2d1..6615cd3b4079 100644
--- a/sound/usb/usbmixer.c
+++ b/sound/usb/usbmixer.c
@@ -222,7 +222,10 @@ static int check_ignored_ctl(struct mixer_build *state, int unitid, int control)
 	for (p = state->map; p->id; p++) {
 		if (p->id == unitid && ! p->name &&
 		    (! control || ! p->control || control == p->control)) {
-			// printk("ignored control %d:%d\n", unitid, control);
+			/*
+			printk(KERN_DEBUG "ignored control %d:%d\n",
+			       unitid, control);
+			*/
 			return 1;
 		}
 	}
diff --git a/sound/usb/usx2y/usb_stream.c b/sound/usb/usx2y/usb_stream.c
index 70b96355ca4c..24393dafcb6e 100644
--- a/sound/usb/usx2y/usb_stream.c
+++ b/sound/usb/usx2y/usb_stream.c
@@ -557,7 +557,7 @@ static void stream_start(struct usb_stream_kernel *sk,
 		s->idle_insize -= max_diff - max_diff_0;
 		s->idle_insize += urb_size - s->period_size;
 		if (s->idle_insize < 0) {
-			snd_printk("%i %i %i\n",
+			snd_printk(KERN_WARNING "%i %i %i\n",
 				   s->idle_insize, urb_size, s->period_size);
 			return;
 		} else if (s->idle_insize == 0) {
-- 
cgit v1.2.3-58-ga151


From f3990e610a157e9c36af85a75bc66260dff31f40 Mon Sep 17 00:00:00 2001
From: Clemens Ladisch <clemens@ladisch.de>
Date: Fri, 20 Feb 2009 09:32:40 +0100
Subject: sound: usb-audio: remove MIN_PACKS_URB

Remove the MIN_PACKS_URB symbol because other limits can force the
number of packets down to one, regardless of the value of this symbol,
and nobody has ever changed it anyway.

Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/usb/usbaudio.c | 14 ++++++--------
 1 file changed, 6 insertions(+), 8 deletions(-)

(limited to 'sound')

diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c
index c69cc6e4f549..2b24496ddec7 100644
--- a/sound/usb/usbaudio.c
+++ b/sound/usb/usbaudio.c
@@ -107,7 +107,6 @@ MODULE_PARM_DESC(ignore_ctl_error,
 #define MAX_PACKS_HS	(MAX_PACKS * 8)	/* in high speed mode */
 #define MAX_URBS	8
 #define SYNC_URBS	4	/* always four urbs for sync */
-#define MIN_PACKS_URB	1	/* minimum 1 packet per urb */
 #define MAX_QUEUE	24	/* try not to exceed this queue length, in ms */
 
 struct audioformat {
@@ -1071,8 +1070,7 @@ static int init_substream_urbs(struct snd_usb_substream *subs, unsigned int peri
 	subs->packs_per_ms = packs_per_ms;
 
 	if (is_playback) {
-		urb_packs = nrpacks;
-		urb_packs = max(urb_packs, (unsigned int)MIN_PACKS_URB);
+		urb_packs = max(nrpacks, 1);
 		urb_packs = min(urb_packs, (unsigned int)MAX_PACKS);
 	} else
 		urb_packs = 1;
@@ -1093,9 +1091,9 @@ static int init_substream_urbs(struct snd_usb_substream *subs, unsigned int peri
 		total_packs = (total_packs + packs_per_ms - 1)
 				& ~(packs_per_ms - 1);
 		/* we need at least two URBs for queueing */
-		if (total_packs < 2 * MIN_PACKS_URB * packs_per_ms)
-			total_packs = 2 * MIN_PACKS_URB * packs_per_ms;
-		else {
+		if (total_packs < 2 * packs_per_ms) {
+			total_packs = 2 * packs_per_ms;
+		} else {
 			/* and we don't want too long a queue either */
 			maxpacks = max((unsigned int)MAX_QUEUE, urb_packs * 2);
 			if (total_packs > maxpacks * packs_per_ms)
@@ -1909,7 +1907,7 @@ static int setup_hw_info(struct snd_pcm_runtime *runtime, struct snd_usb_substre
 	 * in the current code assume the 1ms period.
 	 */
 	snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIOD_TIME,
-				     1000 * MIN_PACKS_URB,
+				     1000,
 				     /*(nrpacks * MAX_URBS) * 1000*/ UINT_MAX);
 
 	err = check_hw_params_convention(subs);
@@ -3753,7 +3751,7 @@ static int usb_audio_resume(struct usb_interface *intf)
 
 static int __init snd_usb_audio_init(void)
 {
-	if (nrpacks < MIN_PACKS_URB || nrpacks > MAX_PACKS) {
+	if (nrpacks < 1 || nrpacks > MAX_PACKS) {
 		printk(KERN_WARNING "invalid nrpacks value.\n");
 		return -EINVAL;
 	}
-- 
cgit v1.2.3-58-ga151


From eab2b553c3d3ed20698c4a9c7e049a60b804e2f5 Mon Sep 17 00:00:00 2001
From: Clemens Ladisch <clemens@ladisch.de>
Date: Mon, 2 Mar 2009 11:45:50 +0100
Subject: sound: usb-audio: fix rules check for 32-channel devices

When storing the channel numbers used by a format, and if the device
happens to support 32 channels, the code would try to store 1<<32 in
a 32-bit value.

Since no valid format can have zero channels, we can use 1<<(channels-1)
instead of 1<<channels so that all the channel numbers that we test for
fit into 32 bits.

Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/usb/usbaudio.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

(limited to 'sound')

diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c
index 2b24496ddec7..f853b627cf43 100644
--- a/sound/usb/usbaudio.c
+++ b/sound/usb/usbaudio.c
@@ -1783,7 +1783,7 @@ static int check_hw_params_convention(struct snd_usb_substream *subs)
 			if (rates[f->format] && rates[f->format] != f->rates)
 				goto __out;
 		}
-		channels[f->format] |= (1 << f->channels);
+		channels[f->format] |= 1 << (f->channels - 1);
 		rates[f->format] |= f->rates;
 		/* needs knot? */
 		if (f->rates & SNDRV_PCM_RATE_KNOT)
@@ -1810,7 +1810,7 @@ static int check_hw_params_convention(struct snd_usb_substream *subs)
 			continue;
 		for (i = 0; i < 32; i++) {
 			if (f->rates & (1 << i))
-				channels[i] |= (1 << f->channels);
+				channels[i] |= 1 << (f->channels - 1);
 		}
 	}
 	cmaster = 0;
-- 
cgit v1.2.3-58-ga151


From b1c86bb807448701400abc6eb8e958475ab5424b Mon Sep 17 00:00:00 2001
From: Clemens Ladisch <clemens@ladisch.de>
Date: Mon, 2 Mar 2009 12:06:28 +0100
Subject: sound: usb-audio: fix queue length check for high speed devices

When checking for the maximum queue length, we have to take into account
that MAX_QUEUE is measured in milliseconds (i.e., frames) while the unit
of urb_packs is whatever data packet interval the device uses (possibly
less than one frame when using high speed devices).

Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/usb/usbaudio.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

(limited to 'sound')

diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c
index f853b627cf43..defe9913cbb2 100644
--- a/sound/usb/usbaudio.c
+++ b/sound/usb/usbaudio.c
@@ -1095,9 +1095,8 @@ static int init_substream_urbs(struct snd_usb_substream *subs, unsigned int peri
 			total_packs = 2 * packs_per_ms;
 		} else {
 			/* and we don't want too long a queue either */
-			maxpacks = max((unsigned int)MAX_QUEUE, urb_packs * 2);
-			if (total_packs > maxpacks * packs_per_ms)
-				total_packs = maxpacks * packs_per_ms;
+			maxpacks = max(MAX_QUEUE * packs_per_ms, urb_packs * 2);
+			total_packs = min(total_packs, maxpacks);
 		}
 	} else {
 		total_packs = MAX_URBS * urb_packs;
-- 
cgit v1.2.3-58-ga151