All of lore.kernel.org
 help / color / mirror / Atom feed
* Re: [Alsa-user] No sound on Extigy
       [not found]   ` <s5hbs28yx2p.wl@alsa2.suse.de>
@ 2003-01-23 13:23     ` Takashi Iwai
       [not found]       ` <1043385385.1964.3.camel@idefix.homelinux.org>
  0 siblings, 1 reply; 3+ messages in thread
From: Takashi Iwai @ 2003-01-23 13:23 UTC (permalink / raw)
  To: Clemens Ladisch; +Cc: Jean-Marc Valin, alsa-devel

[-- Attachment #1: Type: text/plain, Size: 663 bytes --]

(moved to alsa-devel up to now...)

At Thu, 23 Jan 2003 11:33:50 +0100,
I wrote:
> 
> At Thu, 23 Jan 2003 11:26:02 +0100 (MET),
> Clemens Ladisch wrote:
> > 
> > The default output device used by aplay is "hw:0", which doesn't
> > automatically convert sample rates. Try "aplay -D plughw:0 something.wav".
> 
> i'm afraid that it doesn't work, too, because this configuration is
> not handled well.  anyway please try once.
> 
> it's tough to solve...

if the original usb-audio driver doesn't work with plughw like above,
please try the attached patch.

it will show many debug messages.  you can suppress it by undefining
HW_CONST_DEBUG at line 1167.


Takashi

[-- Attachment #2: usb-const.dif --]
[-- Type: application/octet-stream, Size: 8361 bytes --]

Index: alsa-kernel/usb/usbaudio.c
===================================================================
RCS file: /suse/tiwai/cvs/alsa/alsa-kernel/usb/usbaudio.c,v
retrieving revision 1.38
diff -u -r1.38 usbaudio.c
--- alsa-kernel/usb/usbaudio.c	22 Jan 2003 15:46:51 -0000	1.38
+++ alsa-kernel/usb/usbaudio.c	23 Jan 2003 13:19:44 -0000
@@ -36,7 +36,7 @@
 #include <sound/core.h>
 #include <sound/info.h>
 #include <sound/pcm.h>
-#include <sound/seq_device.h>
+#include <sound/pcm_params.h>
 #define SNDRV_GET_ID
 #include <sound/initval.h>
 
@@ -1161,12 +1161,243 @@
 };
 
 /*
+ * h/w constraints
+ */
+
+#define HW_CONST_DEBUG
+
+static int hw_check_valid_format(snd_pcm_hw_params_t *params, struct audioformat *fp)
+{
+	snd_interval_t *it = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
+	snd_interval_t *ct = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
+	snd_mask_t *fmts = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
+
+	/* check the format */
+	if (! snd_mask_test(fmts, fp->format))
+		return 0;
+	/* check the channels */
+	if (fp->channels < ct->min || fp->channels > ct->max)
+		return 0;
+	/* check the rate is within the range */
+	if (fp->rate_min > it->max || (fp->rate_min == it->max && !it->openmax))
+		return 0;
+	if (fp->rate_max < it->min || (fp->rate_max == it->min && !it->openmin))
+		return 0;
+	return 1;
+}
+
+static int hw_rule_rate(snd_pcm_hw_params_t *params,
+			snd_pcm_hw_rule_t *rule)
+{
+	snd_usb_substream_t *subs = rule->private;
+	struct list_head *p;
+	snd_interval_t *it = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
+	int rmin, rmax, changed;
+	
+#ifdef HW_CONST_DEBUG
+	printk(KERN_DEBUG "hw_rule_rate: (%d,%d)\n", it->min, it->max);
+#endif
+	changed = 0;
+	rmin = rmax = 0;
+	list_for_each(p, &subs->fmt_list) {
+		struct audioformat *fp;
+		fp = list_entry(p, struct audioformat, list);
+		if (! hw_check_valid_format(params, fp))
+			continue;
+		if (changed++) {
+			if (rmin > fp->rate_min)
+				rmin = fp->rate_min;
+			if (rmax < fp->rate_max)
+				rmax = fp->rate_max;
+		} else {
+			rmin = fp->rate_min;
+			rmax = fp->rate_max;
+		}
+	}
+
+	if (! changed) {
+#ifdef HW_CONST_DEBUG
+		printk(KERN_DEBUG "  --> get empty\n");
+#endif
+		it->empty = 1;
+		return -EINVAL;
+	}
+
+	changed = 0;
+	if (it->min < rmin) {
+		it->min = rmin;
+		it->openmin = 0;
+		changed = 1;
+	}
+	if (it->max > rmax) {
+		it->max = rmax;
+		it->openmax = 0;
+		changed = 1;
+	}
+	if (snd_interval_checkempty(it)) {
+		it->empty = 1;
+		return -EINVAL;
+	}
+#ifdef HW_CONST_DEBUG
+	printk(KERN_DEBUG "  --> (%d, %d) (changed = %d)\n", it->min, it->max, changed);
+#endif
+	return changed;
+}
+
+
+static int hw_rule_channels(snd_pcm_hw_params_t *params,
+			    snd_pcm_hw_rule_t *rule)
+{
+	snd_usb_substream_t *subs = rule->private;
+	struct list_head *p;
+	snd_interval_t *it = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
+	int rmin, rmax, changed;
+	
+#ifdef HW_CONST_DEBUG
+	printk(KERN_DEBUG "hw_rule_channels: (%d,%d)\n", it->min, it->max);
+#endif
+	changed = 0;
+	rmin = rmax = 0;
+	list_for_each(p, &subs->fmt_list) {
+		struct audioformat *fp;
+		fp = list_entry(p, struct audioformat, list);
+		if (! hw_check_valid_format(params, fp))
+			continue;
+		if (changed++) {
+			if (rmin > fp->channels)
+				rmin = fp->channels;
+			if (rmax < fp->channels)
+				rmax = fp->channels;
+		} else {
+			rmin = fp->channels;
+			rmax = fp->channels;
+		}
+	}
+
+	if (! changed) {
+#ifdef HW_CONST_DEBUG
+		printk(KERN_DEBUG "  --> get empty\n");
+#endif
+		it->empty = 1;
+		return -EINVAL;
+	}
+
+	changed = 0;
+	if (it->min < rmin) {
+		it->min = rmin;
+		it->openmin = 0;
+		changed = 1;
+	}
+	if (it->max > rmax) {
+		it->max = rmax;
+		it->openmax = 0;
+		changed = 1;
+	}
+	if (snd_interval_checkempty(it)) {
+		it->empty = 1;
+		return -EINVAL;
+	}
+#ifdef HW_CONST_DEBUG
+	printk(KERN_DEBUG "  --> (%d, %d) (changed = %d)\n", it->min, it->max, changed);
+#endif
+	return changed;
+}
+
+static int hw_rule_format(snd_pcm_hw_params_t *params,
+			  snd_pcm_hw_rule_t *rule)
+{
+	snd_usb_substream_t *subs = rule->private;
+	struct list_head *p;
+	snd_mask_t *fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
+	u64 fbits;
+	u32 oldbits[2];
+	int changed;
+	
+#ifdef HW_CONST_DEBUG
+	printk(KERN_DEBUG "hw_rule_format: %x:%x\n", fmt->bits[0], fmt->bits[1]);
+#endif
+	fbits = 0;
+	list_for_each(p, &subs->fmt_list) {
+		struct audioformat *fp;
+		fp = list_entry(p, struct audioformat, list);
+		if (! hw_check_valid_format(params, fp))
+			continue;
+		fbits |= (1UL << fp->format);
+	}
+
+	oldbits[0] = fmt->bits[0];
+	oldbits[1] = fmt->bits[1];
+	fmt->bits[0] &= (u32)fbits;
+	fmt->bits[1] &= (u32)(fbits >> 32);
+	if (! fmt->bits[0] && ! fmt->bits[1]) {
+#ifdef HW_CONST_DEBUG
+		printk(KERN_DEBUG "  --> get empty\n");
+#endif
+		return -EINVAL;
+	}
+	changed = (oldbits[0] != fmt->bits[0] || oldbits[1] != fmt->bits[1]);
+#ifdef HW_CONST_DEBUG
+	printk(KERN_DEBUG "  --> %x:%x (changed = %d)\n", fmt->bits[0], fmt->bits[1], changed);
+#endif
+	return changed;
+}
+
+/*
+ * check whether the registered audio formats need special hw-constraints
+ */
+static int check_hw_params_convention(snd_usb_substream_t *subs)
+{
+	int i;
+	u32 channels[64];
+	u32 rates[64];
+	u32 cmaster, rmaster;
+	struct list_head *p;
+
+	memset(channels, 0, sizeof(channels));
+	memset(rates, 0, sizeof(rates));
+
+	list_for_each(p, &subs->fmt_list) {
+		struct audioformat *f;
+		f = list_entry(p, struct audioformat, list);
+		/* uncoventional rates? */
+		if (f->channels > 32 || (f->rates & SNDRV_PCM_RATE_KNOT))
+			return 1;
+		/* combination of continuous rates and fixed rates? */
+		if (rates[f->format] & SNDRV_PCM_RATE_CONTINUOUS) {
+			if (f->rates != rates[f->format])
+				return 1;
+		}
+		if (f->rates & SNDRV_PCM_RATE_CONTINUOUS) {
+			if (rates[f->format] && rates[f->format] != f->rates)
+				return 1;
+		}
+		channels[f->format] |= (1 << f->channels);
+		rates[f->format] |= f->rates;
+	}
+	/* check whether channels and rates match for all formats */
+	cmaster = rmaster = 0;
+	for (i = 0; i < 64; i++) {
+		if (cmaster != channels[i] && cmaster && channels[i])
+			return 1;
+		if (rmaster != rates[i] && rmaster && rates[i])
+			return 1;
+		if (channels[i])
+			cmaster = channels[i];
+		if (rates[i])
+			rmaster = rates[i];
+	}
+	return 0;
+}
+
+
+/*
  * set up the runtime hardware information.
  */
 
-static void setup_hw_info(snd_pcm_runtime_t *runtime, snd_usb_substream_t *subs)
+static int setup_hw_info(snd_pcm_runtime_t *runtime, snd_usb_substream_t *subs)
 {
 	struct list_head *p;
+	int err;
 
 	runtime->hw.formats = subs->formats;
 
@@ -1195,9 +1426,30 @@
 				     1000 * MIN_PACKS_URB,
 				     /*(NRPACKS * MAX_URBS) * 1000*/ UINT_MAX);
 
-	/* FIXME: we need more constraints to restrict the format type,
-	 * channels and rates according to the audioformat list!
-	 */
+	if (check_hw_params_convention(subs)) {
+#ifdef HW_CONST_DEBUG
+		printk(KERN_DEBUG "setting extra hw constraints...\n");
+#endif
+		if ((err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, 
+					       hw_rule_rate, subs,
+					       SNDRV_PCM_HW_PARAM_FORMAT,
+					       SNDRV_PCM_HW_PARAM_CHANNELS,
+					       -1)) < 0)
+			return err;
+		if ((err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, 
+					       hw_rule_channels, subs,
+					       SNDRV_PCM_HW_PARAM_FORMAT,
+					       SNDRV_PCM_HW_PARAM_RATE,
+					       -1)) < 0)
+			return err;
+		if ((err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_FORMAT,
+					       hw_rule_format, subs,
+					       SNDRV_PCM_HW_PARAM_RATE,
+					       SNDRV_PCM_HW_PARAM_CHANNELS,
+					       -1)) < 0)
+			return err;
+	}
+	return 0;
 }
 
 static int snd_usb_pcm_open(snd_pcm_substream_t *substream, int direction,
@@ -1212,8 +1464,7 @@
 	runtime->hw = *hw;
 	runtime->private_data = subs;
 	subs->pcm_substream = substream;
-	setup_hw_info(runtime, subs);
-	return 0;
+	return setup_hw_info(runtime, subs);
 }
 
 static int snd_usb_pcm_close(snd_pcm_substream_t *substream, int direction)
@@ -1821,10 +2072,8 @@
 						break;
 					}
 				}
-#if 0 // FIXME - we need to define constraint
-				if (c >= 13)
-					fp->rates |= SNDRV_PCM_KNOT; /* unconventional rate */
-#endif
+				if (c >= 13)  /* unconventional rate */
+					fp->rates |= SNDRV_PCM_RATE_KNOT;
 			}
 
 		} else {

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [Alsa-user] No sound on Extigy
       [not found]       ` <1043385385.1964.3.camel@idefix.homelinux.org>
@ 2003-01-24 14:37         ` Takashi Iwai
  2003-01-27 15:25         ` Takashi Iwai
  1 sibling, 0 replies; 3+ messages in thread
From: Takashi Iwai @ 2003-01-24 14:37 UTC (permalink / raw)
  To: Jean-Marc Valin; +Cc: alsa-devel

At Fri, 24 Jan 2003 00:16:25 -0500,
Jean-Marc Valin wrote:
> 
> [1  <text/plain; ISO-8859-1 (quoted-printable)>]
> > if the original usb-audio driver doesn't work with plughw like above,
> > please try the attached patch.
> 
> I tried the patch, but I still can't play anything other than 48000, 2
> channels and 48000, 4 channels (tried the other ones listed in
> /proc/asound/card0/stream0 but they didn't work). Any way I can at least
> get 44.1 kHz/stereo and 8000/mono working?

please show me the kernel debug messages when you tried 44100 2ch
samples!


Takashi


-------------------------------------------------------
This SF.NET email is sponsored by:
SourceForge Enterprise Edition + IBM + LinuxWorld = Something 2 See!
http://www.vasoftware.com

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [Alsa-user] No sound on Extigy
       [not found]       ` <1043385385.1964.3.camel@idefix.homelinux.org>
  2003-01-24 14:37         ` Takashi Iwai
@ 2003-01-27 15:25         ` Takashi Iwai
  1 sibling, 0 replies; 3+ messages in thread
From: Takashi Iwai @ 2003-01-27 15:25 UTC (permalink / raw)
  To: Jean-Marc Valin; +Cc: alsa-devel

At Fri, 24 Jan 2003 00:16:25 -0500,
Jean-Marc Valin wrote:
> 
> [1  <text/plain; ISO-8859-1 (quoted-printable)>]
> > if the original usb-audio driver doesn't work with plughw like above,
> > please try the attached patch.
> 
> I tried the patch, but I still can't play anything other than 48000, 2
> channels and 48000, 4 channels (tried the other ones listed in
> /proc/asound/card0/stream0 but they didn't work). Any way I can at least
> get 44.1 kHz/stereo and 8000/mono working?

there was a bug in the patch.  i already committed the fixed version
to cvs.  please update the cvs version and give a try again (you'll
need to plug layer anyway, because extigy doesn't support two-channels
44100 hz).


Takashi


-------------------------------------------------------
This SF.NET email is sponsored by:
SourceForge Enterprise Edition + IBM + LinuxWorld = Something 2 See!
http://www.vasoftware.com

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2003-01-27 15:25 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <s5hel74yya8.wl@alsa2.suse.de>
     [not found] ` <Pine.HPX.4.33n.0301231122530.18209-100000@studcom.urz.uni-halle.de>
     [not found]   ` <s5hbs28yx2p.wl@alsa2.suse.de>
2003-01-23 13:23     ` [Alsa-user] No sound on Extigy Takashi Iwai
     [not found]       ` <1043385385.1964.3.camel@idefix.homelinux.org>
2003-01-24 14:37         ` Takashi Iwai
2003-01-27 15:25         ` Takashi Iwai

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.