Bug 91683

Summary: [sound] [patch] bug on sound driver & solution
Product: Base System Reporter: Marc Flambard <marc-pub>
Component: kernAssignee: Ariff Abdullah <ariff>
Status: Closed FIXED    
Severity: Affects Only Me    
Priority: Normal    
Version: Unspecified   
Hardware: Any   
OS: Any   

Description Marc Flambard 2006-01-11 21:00:19 UTC
I found "bug" on sound driver (channel.c,v 1.99.2.1 & feeder.c,v 1.33.2.1).
I use CS4630 based sound card (minimum 11025Hz at recording).

Changing format capacity for record channel on csa driver(csapcm.c),
reveals some interesting things.
I show you sndstat on 2 situations (I use application that require 8Khz mono)

WITH:
static u_int32_t csa_recfmt[] = {
	AFMT_S16_LE,
	AFMT_STEREO | AFMT_S16_LE,
	0
};
SNDSTAT:
{hardware} -> feeder_root(0x10000010) -> feeder_rate(11025 -> 8000) -> feeder_stereotomono16(0x10000010 -> 0x00000010) -> {userland}

here everything is ok.

WITH:
static u_int32_t csa_recfmt[] = {
	AFMT_STEREO | AFMT_S16_LE,
	AFMT_S16_LE,
	0
};
SNDSTAT:
{hardware} -> feeder_root(0x00000010) -> feeder_monotostereo16(0x00000010 -> 0x10000010) -> feeder_rate(11025 -> 8000) -> feeder_stereotomono16(0x10000010 -> 0x00000010) -> {userland}

why using mono capacity with feeder_monotostereo whereas the hardware is able to deliver stereo?

Fix: 

In function feeder_fmtchain(feeder.c):
if we test maxdepth before testing validity,
the function chn_fmtchain(feeder.c) will be able to
distinguish the difference between [feeder_root->feeder_monotostereo16->feeder_rate]
and [feeder_root->feeder_rate] without dependency on format arrangement and
without changes made between feeder.c-v1.33 and v1.33.2.1 (particularly reverse scanning!).
Moreover this change simplify chn_buildfeeder(channel.c).

I join diffs and tests with debug messages.

Marc Flambard

Tests with debug messages:

-----ACTUALLY-----

WITH:
static u_int32_t csa_recfmt[] = {
	AFMT_S16_LE,
	AFMT_STEREO | AFMT_S16_LE,
	0
};
SNDSTAT:
{hardware} -> feeder_root(0x10000010) -> feeder_rate(11025 -> 8000) -> feeder_stereotomono16(0x10000010 -> 0x00000010) -> {userland}
DEBUG:
Jan 11 15:55:46 pc-marc1 kernel: setspeed, channel pcm0:record:0
Jan 11 15:55:46 pc-marc1 kernel: want speed 8000, try speed 11025, got speed 11025
Jan 11 15:55:46 pc-marc1 kernel: feederflags 10
Jan 11 15:55:46 pc-marc1 kernel: find feeder type 4, got 0xc76efce0
Jan 11 15:55:46 pc-marc1 kernel: chn_buildfeeder>>type:4
Jan 11 15:55:46 pc-marc1 kernel: chn_buildfeeder>>c->format:00000010
Jan 11 15:55:46 pc-marc1 kernel: chn_buildfeeder>>fc->desc->in:10000010
Jan 11 15:55:46 pc-marc1 kernel: chn_buildfeeder>>fc->desc->out:10000010
Jan 11 15:55:46 pc-marc1 kernel: chn_buildfeeder>>c->feeder->desc->out:00000010
Jan 11 15:55:46 pc-marc1 kernel: chn_buildfeeder>>fmtlist[0]:00000010
Jan 11 15:55:46 pc-marc1 kernel: chn_buildfeeder>>fmtlist[1]:10000010
Jan 11 15:55:46 pc-marc1 kernel: build fmtchain from 0x10 to 0x10000010:
Jan 11 15:55:46 pc-marc1 kernel: call feeder_fmtchain with maxdepth=0
Jan 11 15:55:46 pc-marc1 kernel: trying feeder_root (0 -> 10000010)...
Jan 11 15:55:46 pc-marc1 kernel: got it
Jan 11 15:55:46 pc-marc1 kernel: call feeder_fmtchain with maxdepth=0
Jan 11 15:55:46 pc-marc1 kernel: trying feeder_root (0 -> 10)...
Jan 11 15:55:46 pc-marc1 kernel: trying feeder_endian16 (10 -> 20)...
Jan 11 15:55:46 pc-marc1 kernel: trying feeder_sign16le (10 -> 80)...
Jan 11 15:55:46 pc-marc1 kernel: trying feeder_monotostereo16 (10 -> 10000010)...
Jan 11 15:55:46 pc-marc1 kernel: got it
Jan 11 15:55:46 pc-marc1 kernel: call feeder_fmtchain for best chain (maxdepth=0)
Jan 11 15:55:46 pc-marc1 kernel: trying feeder_root (0 -> 10000010)...
Jan 11 15:55:46 pc-marc1 kernel: got it
Jan 11 15:55:46 pc-marc1 kernel: ok
Jan 11 15:55:46 pc-marc1 kernel: added feeder 0xc76efce0, output 0x10000010
Jan 11 15:55:46 pc-marc1 kernel: call feeder_fmtchain with maxdepth=0
Jan 11 15:55:46 pc-marc1 kernel: trying feeder_rate (10000010 -> 10000010)...
Jan 11 15:55:46 pc-marc1 kernel: trying feeder_endian16 (10000010 -> 10000020)...
Jan 11 15:55:46 pc-marc1 kernel: trying feeder_sign16le (10000010 -> 10000080)...
Jan 11 15:55:46 pc-marc1 kernel: trying feeder_stereotomono16 (10000010 -> 10)...
Jan 11 15:55:46 pc-marc1 kernel: got it
Jan 11 15:55:46 pc-marc1 kernel: call feeder_fmtchain for best chain (maxdepth=0)
Jan 11 15:55:46 pc-marc1 kernel: trying feeder_rate (10000010 -> 10000010)...
Jan 11 15:55:46 pc-marc1 kernel: trying feeder_endian16 (10000010 -> 10000020)...
Jan 11 15:55:46 pc-marc1 kernel: trying feeder_sign16le (10000010 -> 10000080)...
Jan 11 15:55:46 pc-marc1 kernel: trying feeder_stereotomono16 (10000010 -> 10)...
Jan 11 15:55:46 pc-marc1 kernel: got it
Jan 11 15:55:46 pc-marc1 kernel: r = 0
Jan 11 15:55:46 pc-marc1 kernel: chn_setblocksize(0, 0)
Jan 11 15:55:46 pc-marc1 kernel: feedrate = 0xc5e26180
Jan 11 15:55:46 pc-marc1 kernel: feeder_set(FEEDRATE_SRC, 11025) = 0
Jan 11 15:55:46 pc-marc1 kernel: feeder_set(FEEDRATE_DST, 8000) = 0
Jan 11 15:55:46 pc-marc1 kernel: setspeed done, r = 0

WITH:
static u_int32_t csa_recfmt[] = {
	AFMT_STEREO | AFMT_S16_LE,
	AFMT_S16_LE,
	0
};
SNDSTAT:
{hardware} -> feeder_root(0x00000010) -> feeder_monotostereo16(0x00000010 -> 0x10000010) -> feeder_rate(11025 -> 8000) -> feeder_stereotomono16(0x10000010 -> 0x00000010) -> {userland}
DEBUG:
Jan 11 15:59:21 pc-marc1 kernel: setspeed, channel pcm0:record:0
Jan 11 15:59:21 pc-marc1 kernel: want speed 8000, try speed 11025, got speed 11025
Jan 11 15:59:21 pc-marc1 kernel: feederflags 10
Jan 11 15:59:21 pc-marc1 kernel: find feeder type 4, got 0xc76efce0
Jan 11 15:59:21 pc-marc1 kernel: chn_buildfeeder>>type:4
Jan 11 15:59:21 pc-marc1 kernel: chn_buildfeeder>>c->format:00000010
Jan 11 15:59:21 pc-marc1 kernel: chn_buildfeeder>>fc->desc->in:10000010
Jan 11 15:59:21 pc-marc1 kernel: chn_buildfeeder>>fc->desc->out:10000010
Jan 11 15:59:21 pc-marc1 kernel: chn_buildfeeder>>c->feeder->desc->out:00000010
Jan 11 15:59:21 pc-marc1 kernel: chn_buildfeeder>>fmtlist[0]:10000010
Jan 11 15:59:21 pc-marc1 kernel: chn_buildfeeder>>fmtlist[1]:00000010
Jan 11 15:59:21 pc-marc1 kernel: build fmtchain from 0x10 to 0x10000010:
Jan 11 15:59:21 pc-marc1 kernel: call feeder_fmtchain with maxdepth=0
Jan 11 15:59:21 pc-marc1 kernel: trying feeder_root (0 -> 10)...
Jan 11 15:59:21 pc-marc1 kernel: trying feeder_endian16 (10 -> 20)...
Jan 11 15:59:21 pc-marc1 kernel: trying feeder_sign16le (10 -> 80)...
Jan 11 15:59:21 pc-marc1 kernel: trying feeder_monotostereo16 (10 -> 10000010)...
Jan 11 15:59:21 pc-marc1 kernel: got it
Jan 11 15:59:21 pc-marc1 kernel: call feeder_fmtchain with maxdepth=0
Jan 11 15:59:21 pc-marc1 kernel: trying feeder_root (0 -> 10000010)...
Jan 11 15:59:21 pc-marc1 kernel: got it
Jan 11 15:59:21 pc-marc1 kernel: call feeder_fmtchain for best chain (maxdepth=0)
Jan 11 15:59:21 pc-marc1 kernel: trying feeder_root (0 -> 10)...
Jan 11 15:59:21 pc-marc1 kernel: trying feeder_endian16 (10 -> 20)...
Jan 11 15:59:21 pc-marc1 kernel: trying feeder_sign16le (10 -> 80)...
Jan 11 15:59:21 pc-marc1 kernel: trying feeder_monotostereo16 (10 -> 10000010)...
Jan 11 15:59:21 pc-marc1 kernel: got it
Jan 11 15:59:21 pc-marc1 kernel: ok
Jan 11 15:59:21 pc-marc1 kernel: added feeder 0xc76efce0, output 0x10000010
Jan 11 15:59:21 pc-marc1 kernel: call feeder_fmtchain with maxdepth=0
Jan 11 15:59:21 pc-marc1 kernel: trying feeder_rate (10000010 -> 10000010)...
Jan 11 15:59:21 pc-marc1 kernel: trying feeder_endian16 (10000010 -> 10000020)...
Jan 11 15:59:21 pc-marc1 kernel: trying feeder_sign16le (10000010 -> 10000080)...
Jan 11 15:59:21 pc-marc1 kernel: trying feeder_stereotomono16 (10000010 -> 10)...
Jan 11 15:59:21 pc-marc1 kernel: got it
Jan 11 15:59:21 pc-marc1 kernel: call feeder_fmtchain for best chain (maxdepth=0)
Jan 11 15:59:21 pc-marc1 kernel: trying feeder_rate (10000010 -> 10000010)...
Jan 11 15:59:21 pc-marc1 kernel: trying feeder_endian16 (10000010 -> 10000020)...
Jan 11 15:59:21 pc-marc1 kernel: trying feeder_sign16le (10000010 -> 10000080)...
Jan 11 15:59:21 pc-marc1 kernel: trying feeder_stereotomono16 (10000010 -> 10)...
Jan 11 15:59:21 pc-marc1 kernel: got it
Jan 11 15:59:21 pc-marc1 kernel: r = 0
Jan 11 15:59:21 pc-marc1 kernel: chn_setblocksize(0, 0)
Jan 11 15:59:21 pc-marc1 kernel: feedrate = 0xc5e1eac0
Jan 11 15:59:21 pc-marc1 kernel: feeder_set(FEEDRATE_SRC, 11025) = 0
Jan 11 15:59:21 pc-marc1 kernel: feeder_set(FEEDRATE_DST, 8000) = 0
Jan 11 15:59:21 pc-marc1 kernel: setspeed done, r = 0

-----WITH MY MODIFICATIONS-----

WITH:
static u_int32_t csa_recfmt[] = {
	AFMT_S16_LE,
	AFMT_STEREO | AFMT_S16_LE,
SNDSTAT:
{hardware} -> feeder_root(0x10000010) -> feeder_rate(11025 -> 8000) -> feeder_stereotomono16(0x10000010 -> 0x00000010) -> {userland}
DEBUG:
Jan 11 15:29:17 pc-marc1 kernel: setspeed, channel pcm0:record:0
Jan 11 15:29:17 pc-marc1 kernel: want speed 8000, try speed 11025, got speed 11025
Jan 11 15:29:17 pc-marc1 kernel: feederflags 10
Jan 11 15:29:17 pc-marc1 kernel: find feeder type 4, got 0xc752ac40
Jan 11 15:29:17 pc-marc1 kernel: chn_buildfeeder>>type:4
Jan 11 15:29:17 pc-marc1 kernel: chn_buildfeeder>>c->format:00000010
Jan 11 15:29:17 pc-marc1 kernel: chn_buildfeeder>>fc->desc->in:10000010
Jan 11 15:29:17 pc-marc1 kernel: chn_buildfeeder>>fc->desc->out:10000010
Jan 11 15:29:17 pc-marc1 kernel: chn_buildfeeder>>c->feeder->desc->out:00000010
Jan 11 15:29:17 pc-marc1 kernel: chn_buildfeeder>>fmtlist[0]:00000010
Jan 11 15:29:17 pc-marc1 kernel: chn_buildfeeder>>fmtlist[1]:10000010
Jan 11 15:29:17 pc-marc1 kernel: build fmtchain from 0x10 to 0x10000010:
Jan 11 15:29:17 pc-marc1 kernel: call feeder_fmtchain with maxdepth=0
Jan 11 15:29:17 pc-marc1 kernel: trying feeder_root (0 -> 10)...
Jan 11 15:29:17 pc-marc1 kernel: call feeder_fmtchain with maxdepth=1
Jan 11 15:29:17 pc-marc1 kernel: trying feeder_root (0 -> 10)...
Jan 11 15:29:17 pc-marc1 kernel: trying feeder_endian16 (10 -> 20)...
Jan 11 15:29:17 pc-marc1 kernel: trying feeder_sign16le (10 -> 80)...
Jan 11 15:29:17 pc-marc1 kernel: trying feeder_monotostereo16 (10 -> 10000010)...
Jan 11 15:29:17 pc-marc1 kernel: got it
Jan 11 15:29:17 pc-marc1 kernel: call feeder_fmtchain with maxdepth=0
Jan 11 15:29:17 pc-marc1 kernel: trying feeder_root (0 -> 10000010)...
Jan 11 15:29:17 pc-marc1 kernel: got it
Jan 11 15:29:17 pc-marc1 kernel: call feeder_fmtchain for best chain (maxdepth=0)
Jan 11 15:29:17 pc-marc1 kernel: trying feeder_root (0 -> 10000010)...
Jan 11 15:29:17 pc-marc1 kernel: got it
Jan 11 15:29:17 pc-marc1 kernel: ok
Jan 11 15:29:17 pc-marc1 kernel: added feeder 0xc752ac40, output 0x10000010
Jan 11 15:29:17 pc-marc1 kernel: call feeder_fmtchain with maxdepth=0
Jan 11 15:29:17 pc-marc1 kernel: trying feeder_rate (10000010 -> 10000010)...
Jan 11 15:29:17 pc-marc1 kernel: call feeder_fmtchain with maxdepth=1
Jan 11 15:29:17 pc-marc1 kernel: trying feeder_rate (10000010 -> 10000010)...
Jan 11 15:29:17 pc-marc1 kernel: trying feeder_endian16 (10000010 -> 10000020)...
Jan 11 15:29:17 pc-marc1 kernel: trying feeder_sign16le (10000010 -> 10000080)...
Jan 11 15:29:17 pc-marc1 kernel: trying feeder_stereotomono16 (10000010 -> 10)...
Jan 11 15:29:17 pc-marc1 kernel: got it
Jan 11 15:29:17 pc-marc1 kernel: call feeder_fmtchain for best chain (maxdepth=1)
Jan 11 15:29:17 pc-marc1 kernel: trying feeder_rate (10000010 -> 10000010)...
Jan 11 15:29:17 pc-marc1 kernel: trying feeder_endian16 (10000010 -> 10000020)...
Jan 11 15:29:17 pc-marc1 kernel: trying feeder_sign16le (10000010 -> 10000080)...
Jan 11 15:29:17 pc-marc1 kernel: trying feeder_stereotomono16 (10000010 -> 10)...
Jan 11 15:29:17 pc-marc1 kernel: got it
Jan 11 15:29:17 pc-marc1 kernel: r = 0
Jan 11 15:29:17 pc-marc1 kernel: chn_setblocksize(0, 0)
Jan 11 15:29:17 pc-marc1 kernel: feedrate = 0xc5669000
Jan 11 15:29:17 pc-marc1 kernel: feeder_set(FEEDRATE_SRC, 11025) = 0
Jan 11 15:29:17 pc-marc1 kernel: feeder_set(FEEDRATE_DST, 8000) = 0
Jan 11 15:29:17 pc-marc1 kernel: setspeed done, r = 0

WITH:
static u_int32_t csa_recfmt[] = {
	AFMT_STEREO | AFMT_S16_LE,
	AFMT_S16_LE,
	0
};
SNDSTAT:
{hardware} -> feeder_root(0x10000010) -> feeder_rate(11025 -> 8000) -> feeder_stereotomono16(0x10000010 -> 0x00000010) -> {userland}
DEBUG:
Jan 11 15:39:02 pc-marc1 kernel: setspeed, channel pcm0:record:0
Jan 11 15:39:02 pc-marc1 kernel: want speed 8000, try speed 11025, got speed 11025
Jan 11 15:39:02 pc-marc1 kernel: feederflags 10
Jan 11 15:39:02 pc-marc1 kernel: find feeder type 4, got 0xc76efc40
Jan 11 15:39:02 pc-marc1 kernel: chn_buildfeeder>>type:4
Jan 11 15:39:02 pc-marc1 kernel: chn_buildfeeder>>c->format:00000010
Jan 11 15:39:02 pc-marc1 kernel: chn_buildfeeder>>fc->desc->in:10000010
Jan 11 15:39:02 pc-marc1 kernel: chn_buildfeeder>>fc->desc->out:10000010
Jan 11 15:39:02 pc-marc1 kernel: chn_buildfeeder>>c->feeder->desc->out:00000010
Jan 11 15:39:02 pc-marc1 kernel: chn_buildfeeder>>fmtlist[0]:10000010
Jan 11 15:39:02 pc-marc1 kernel: chn_buildfeeder>>fmtlist[1]:00000010
Jan 11 15:39:02 pc-marc1 kernel: build fmtchain from 0x10 to 0x10000010:
Jan 11 15:39:02 pc-marc1 kernel: call feeder_fmtchain with maxdepth=0
Jan 11 15:39:02 pc-marc1 kernel: trying feeder_root (0 -> 10000010)...
Jan 11 15:39:02 pc-marc1 kernel: got it
Jan 11 15:39:02 pc-marc1 kernel: call feeder_fmtchain with maxdepth=0
Jan 11 15:39:02 pc-marc1 kernel: trying feeder_root (0 -> 10)...
Jan 11 15:39:02 pc-marc1 kernel: call feeder_fmtchain with maxdepth=1
Jan 11 15:39:02 pc-marc1 kernel: trying feeder_root (0 -> 10)...
Jan 11 15:39:02 pc-marc1 kernel: trying feeder_endian16 (10 -> 20)...
Jan 11 15:39:02 pc-marc1 kernel: trying feeder_sign16le (10 -> 80)...
Jan 11 15:39:02 pc-marc1 kernel: trying feeder_monotostereo16 (10 -> 10000010)...
Jan 11 15:39:02 pc-marc1 kernel: got it
Jan 11 15:39:02 pc-marc1 kernel: call feeder_fmtchain for best chain (maxdepth=0)
Jan 11 15:39:02 pc-marc1 kernel: trying feeder_root (0 -> 10000010)...
Jan 11 15:39:02 pc-marc1 kernel: got it
Jan 11 15:39:02 pc-marc1 kernel: ok
Jan 11 15:39:02 pc-marc1 kernel: added feeder 0xc76efc40, output 0x10000010
Jan 11 15:39:02 pc-marc1 kernel: call feeder_fmtchain with maxdepth=0
Jan 11 15:39:02 pc-marc1 kernel: trying feeder_rate (10000010 -> 10000010)...
Jan 11 15:39:02 pc-marc1 kernel: call feeder_fmtchain with maxdepth=1
Jan 11 15:39:02 pc-marc1 kernel: trying feeder_rate (10000010 -> 10000010)...
Jan 11 15:39:02 pc-marc1 kernel: trying feeder_endian16 (10000010 -> 10000020)...
Jan 11 15:39:02 pc-marc1 kernel: trying feeder_sign16le (10000010 -> 10000080)...
Jan 11 15:39:02 pc-marc1 kernel: trying feeder_stereotomono16 (10000010 -> 10)...
Jan 11 15:39:02 pc-marc1 kernel: got it
Jan 11 15:39:02 pc-marc1 kernel: call feeder_fmtchain for best chain (maxdepth=1)
Jan 11 15:39:02 pc-marc1 kernel: trying feeder_rate (10000010 -> 10000010)...
Jan 11 15:39:02 pc-marc1 kernel: trying feeder_endian16 (10000010 -> 10000020)...
Jan 11 15:39:02 pc-marc1 kernel: trying feeder_sign16le (10000010 -> 10000080)...
Jan 11 15:39:02 pc-marc1 kernel: trying feeder_stereotomono16 (10000010 -> 10)...
Jan 11 15:39:02 pc-marc1 kernel: got it
Jan 11 15:39:02 pc-marc1 kernel: r = 0
Jan 11 15:39:02 pc-marc1 kernel: chn_setblocksize(0, 0)
Jan 11 15:39:02 pc-marc1 kernel: feedrate = 0xc57ff8c0
Jan 11 15:39:02 pc-marc1 kernel: feeder_set(FEEDRATE_SRC, 11025) = 0
Jan 11 15:39:02 pc-marc1 kernel: feeder_set(FEEDRATE_DST, 8000) = 0
Jan 11 15:39:02 pc-marc1 kernel: setspeed done, r = 0


diffs:

-----channel.diff-----
1292c1292
< 	int err;
---
> 	int err,cnt;
1361,1372c1361,1375
< 			if ((type == FEEDER_RATE &&
< 					!fmtvalid(fc->desc->in, fmtlist))
< 					|| c->feeder->desc->out != fc->desc->in) {
<  				DEB(printf("build fmtchain from 0x%x to 0x%x: ", c->feeder->desc->out, fc->desc->in));
< 				tmp[0] = fc->desc->in;
< 				tmp[1] = 0;
< 				if (chn_fmtchain(c, tmp) == 0) {
< 					DEB(printf("failed\n"));
< 
< 					return ENODEV;
< 				}
<  				DEB(printf("ok\n"));
---
>  			DEB(printf("chn_buildfeeder>>c->format:%08x\n", c->format));
>  			DEB(printf("chn_buildfeeder>>fc->desc->in:%08x\n", fc->desc->in));
>  			DEB(printf("chn_buildfeeder>>fc->desc->out:%08x\n", fc->desc->out));
>  			DEB(printf("chn_buildfeeder>>c->feeder->desc->out:%08x\n", c->feeder->desc->out));
> 			cnt=-1;
> 			while(fmtlist[++cnt])
>  			   DEB(printf("chn_buildfeeder>>fmtlist[%i]:%08x\n", cnt, fmtlist[cnt]));
> 
>  			DEB(printf("build fmtchain to 0x%x:\n", fc->desc->in));
> 			tmp[0] = fc->desc->in;
> 			tmp[1] = 0;
> 			if (chn_fmtchain(c, tmp) == 0) {
> 				DEB(printf("failed\n"));
> 
> 				return ENODEV;
1373a1377
>  			DEB(printf("ok\n"));
1385,1396c1389,1394
< 	if (fmtvalid(c->feeder->desc->out, fmtlist)
< 			&& !(c->direction == PCMDIR_REC &&
< 				c->format != c->feeder->desc->out))
< 		hwfmt = c->feeder->desc->out;
< 	else {
< 		if (c->direction == PCMDIR_REC) {
< 			tmp[0] = c->format;
< 			tmp[1] = 0;
< 			hwfmt = chn_fmtchain(c, tmp);
< 		} else
< 			hwfmt = chn_fmtchain(c, fmtlist);
< 	}
---
> 	if (c->direction == PCMDIR_REC) {
> 		tmp[0] = c->format;
> 		tmp[1] = 0;
> 		hwfmt = chn_fmtchain(c, tmp);
> 	} else
> 		hwfmt = chn_fmtchain(c, fmtlist);

-----feeder.diff-----
268c268,271
< 	/* printf("trying %s (%x -> %x)...\n", source->class->name, source->desc->in, source->desc->out); */
---
> 	if (maxdepth < 0)
> 		return NULL;
> 
> 	DEB(printf("trying %s (%x -> %x)...\n", source->class->name, source->desc->in, source->desc->out)); 
270c273
< 		/* printf("got it\n"); */
---
> 		DEB(printf("got it\n")); 
274,276d276
< 	if (maxdepth < 0)
< 		return NULL;
< 
323,326c323
< 	while (from[i] != 0)
< 		i++;
< 	while (i > 0) {
< 		i--;
---
> 	while (from[i] != 0) {
330a328
> 			DEB(printf("call feeder_fmtchain with maxdepth=%i\n",max));
343a342
> 		i++;
348a348
> 	DEB(printf("call feeder_fmtchain for best chain (maxdepth=%i)\n",bestmax));
376,385c376
< 	if (c->direction == PCMDIR_REC) {
< 		try = c->feeder;
< 		while (try != NULL) {
< 			if (try->desc->type == FEEDER_ROOT)
< 				return try->desc->out;
< 			try = try->source;
< 		}
< 		return best;
< 	} else
< 		return c->feeder->desc->out;
---
> 	return (c->direction == PCMDIR_REC)? best : c->feeder->desc->out;


Marc Flambard
How-To-Repeat: change record format order of your sound card
example for csa:
static u_int32_t csa_recfmt[] = {
	AFMT_S16_LE,
	AFMT_STEREO | AFMT_S16_LE,
	0
};
change by:
static u_int32_t csa_recfmt[] = {
	AFMT_STEREO | AFMT_S16_LE,
	AFMT_S16_LE,
	0
};
Comment 1 Mark Linimon freebsd_committer freebsd_triage 2006-01-11 23:01:49 UTC
Responsible Changed
From-To: freebsd-bugs->freebsd-multimedia

Over to maintainer(s).
Comment 2 Ariff Abdullah freebsd_committer freebsd_triage 2006-01-21 07:25:33 UTC
Responsible Changed
From-To: freebsd-multimedia->ariff

I'll take this.
Comment 3 Ariff Abdullah freebsd_committer freebsd_triage 2006-01-21 07:46:52 UTC
Can you resubmit the patch using unified diff (diff -u) ?

--
Ariff Abdullah
FreeBSD
Comment 4 marc 2006-01-23 12:53:06 UTC
ok...

-----channel.diff-----

--- channel.c.old       Wed Jan 11 16:36:11 2006
+++ channel.c   Wed Jan 11 16:32:57 2006
@@ -1289,7 +1289,7 @@
        struct feeder_class *fc;
        struct pcm_feederdesc desc;
        u_int32_t tmp[2], type, flags, hwfmt, *fmtlist;
-       int err;
+       int err,cnt;

        CHN_LOCKASSERT(c);
        while (chn_removefeeder(c) == 0);
@@ -1358,19 +1358,23 @@
                                return EOPNOTSUPP;
                        }

-                       if ((type == FEEDER_RATE &&
-                                       !fmtvalid(fc->desc->in,
fmtlist))
-                                       || c->feeder->desc->out !=
fc->desc->in) {
-                               DEB(printf("build fmtchain from 0x%x to
0x%x: ", c->feeder->desc->out, fc->desc->in));
-                               tmp[0] = fc->desc->in;
-                               tmp[1] = 0;
-                               if (chn_fmtchain(c, tmp) == 0) {
-                                       DEB(printf("failed\n"));
-
-                                       return ENODEV;
-                               }
-                               DEB(printf("ok\n"));
+                       DEB(printf("chn_buildfeeder>>c->format:%08x\n",
c->format));
+                       DEB(printf("chn_buildfeeder>>fc->desc->in:%08x
\n", fc->desc->in));
+                       DEB(printf("chn_buildfeeder>>fc->desc->out:%08x
\n", fc->desc->out));
+
DEB(printf("chn_buildfeeder>>c->feeder->desc->out:%08x\n",
c->feeder->desc->out));
+                       cnt=-1;
+                       while(fmtlist[++cnt])
+                          DEB(printf("chn_buildfeeder>>fmtlist[%i]:%08x
\n", cnt, fmtlist[cnt]));
+
+                       DEB(printf("build fmtchain to 0x%x:\n",
fc->desc->in));
+                       tmp[0] = fc->desc->in;
+                       tmp[1] = 0;
+                       if (chn_fmtchain(c, tmp) == 0) {
+                               DEB(printf("failed\n"));
+
+                               return ENODEV;
                        }
+                       DEB(printf("ok\n"));

                        err = chn_addfeeder(c, fc, fc->desc);
                        if (err) {
@@ -1382,18 +1386,12 @@
                }
        }

-       if (fmtvalid(c->feeder->desc->out, fmtlist)
-                       && !(c->direction == PCMDIR_REC &&
-                               c->format != c->feeder->desc->out))
-               hwfmt = c->feeder->desc->out;
-       else {
-               if (c->direction == PCMDIR_REC) {
-                       tmp[0] = c->format;
-                       tmp[1] = 0;
-                       hwfmt = chn_fmtchain(c, tmp);
-               } else
-                       hwfmt = chn_fmtchain(c, fmtlist);
-       }
+       if (c->direction == PCMDIR_REC) {
+               tmp[0] = c->format;
+               tmp[1] = 0;
+               hwfmt = chn_fmtchain(c, tmp);
+       } else
+               hwfmt = chn_fmtchain(c, fmtlist);

        if (hwfmt == 0 || !fmtvalid(hwfmt, fmtlist)) {
                DEB(printf("Invalid hardware format: 0x%x\n", hwfmt));

-----feeder.diff-----

--- feeder.c.old        Wed Jan 11 16:35:38 2006
+++ feeder.c    Wed Jan 11 16:17:36 2006
@@ -265,15 +265,15 @@
        struct feedertab_entry *fte;
        struct pcm_feeder *try, *ret;

-       /* printf("trying %s (%x -> %x)...\n", source->class->name,
source->desc->in, source->desc->out); */
+       if (maxdepth < 0)
+               return NULL;
+
+       DEB(printf("trying %s (%x -> %x)...\n", source->class->name,
source->desc->in, source->desc->out));
        if (fmtvalid(source->desc->out, to)) {
-               /* printf("got it\n"); */
+               DEB(printf("got it\n"));
                return source;
        }

-       if (maxdepth < 0)
-               return NULL;
-
        SLIST_FOREACH(fte, &feedertab, link) {
                if (fte->desc == NULL)
                        continue;
@@ -320,14 +320,12 @@
        i = 0;
        best = 0;
        bestmax = 100;
-       while (from[i] != 0)
-               i++;
-       while (i > 0) {
-               i--;
+       while (from[i] != 0) {
                c->feeder->desc->out = from[i];
                try = NULL;
                max = 0;
                while (try == NULL && max < 8) {
+                       DEB(printf("call feeder_fmtchain with maxdepth=%
i\n",max));
                        try = feeder_fmtchain(to, c->feeder, stop, max);
                        if (try == NULL)
                                max++;
@@ -341,11 +339,13 @@
                        try = try->source;
                        feeder_destroy(del);
                }
+               i++;
        }
        if (best == 0)
                return 0;

        c->feeder->desc->out = best;
+       DEB(printf("call feeder_fmtchain for best chain (maxdepth=%
i)\n",bestmax));
        try = feeder_fmtchain(to, c->feeder, stop, bestmax);
        if (try == NULL)
                return 0;
@@ -373,16 +373,7 @@
        printf("%s [%d]\n", try->class->name, try->desc->idx);
 #endif

-       if (c->direction == PCMDIR_REC) {
-               try = c->feeder;
-               while (try != NULL) {
-                       if (try->desc->type == FEEDER_ROOT)
-                               return try->desc->out;
-                       try = try->source;
-               }
-               return best;
-       } else
-               return c->feeder->desc->out;
+       return (c->direction == PCMDIR_REC)? best :
c->feeder->desc->out;
 }

 void



Marc Flambard
Comment 5 Ariff Abdullah freebsd_committer freebsd_triage 2006-01-24 11:02:11 UTC
Thanks for the submission. 

Although this patch (which somehow revert everything to its original
form before the MegaMFC) works for you, it breaks heavily if it
involves weird combination of hardware formats (AFMT_S32_LE - under
extreme condition) or if you intend to do recording in other format
not supported by the hardware. Few utilities (pcmplay/pcmrec) can be
found at http://people.freebsd.org/~ariff/utils/ , which you can use
to do regression and torture test.

A better fix has been committed to -current, and will be MFCed later.

http://lists.freebsd.org/pipermail/cvs-src/2006-January/058517.html

I'm closing this PR.

Thanks.


--
Ariff Abdullah
FreeBSD
Comment 6 Ariff Abdullah freebsd_committer freebsd_triage 2006-01-29 04:01:58 UTC
State Changed
From-To: open->closed

Fix has been commited. Thanks.