Subject: kern/35658: azalia can't recording properly under the multi-channel supported codecs
To: None <kern-bug-people@netbsd.org, gnats-admin@netbsd.org,>
From: None <kiku.nori@gmail.com>
List: netbsd-bugs
Date: 02/17/2007 11:30:00
>Number:         35658
>Category:       kern
>Synopsis:       azalia can't recording properly under the multi-channel supported codecs
>Confidential:   no
>Severity:       serious
>Priority:       high
>Responsible:    kern-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Sat Feb 17 11:30:00 +0000 2007
>Originator:     kikuma norimitsu
>Release:        netbsd-3-1-RELEASE
>Organization:
>Environment:
NetBSD shellfish 3.1 NetBSD 3.1 (shellfish.mp.azalia) #0: Sat Feb 17 18:36:10 JST 2007  nori@shellfish:/home/nori/src/usr/src/sys/arch/i386/compile/shellfish.mp.azalia i386
>Description:
according to HDA specification 7.2.3.1, 7.2.3.2 and 7.3.3.8, converter widget is able to set 1- or 2-channel.
according to HDA specification 7.3.3.11, assign steram 0 to unused converter widget.

by ignoring both rules in azalia_codec_connect_stream(), resulting in a bogus outputs.

>How-To-Repeat:
run audiorecord(1) under multi-channel supported codec, then check that size of outputs.

>Fix:
I made a patch.

--- azalia.c.org	2006-07-31 02:09:50.000000000 +0900
+++ azalia.c	2007-02-17 18:12:50.000000000 +0900
@@ -1370,11 +1370,14 @@
 			nid = group->conv[1];
 		}
 
-		err = this->comresp(this, nid, CORB_SET_CONVERTER_FORMAT, fmt, NULL);
+		DPRINTF(("%s: nid=%d fmt=0x%4.4x\n", __func__, nid, (fmt & ~HDA_SD_FMT_CHAN) | (WIDGET_CHANNELS(&this->w[nid]) - 1)));
+		err = this->comresp(this, nid, CORB_SET_CONVERTER_FORMAT,
+			(fmt & ~HDA_SD_FMT_CHAN) | (WIDGET_CHANNELS(&this->w[nid]) - 1), NULL);
 		if (err)
 			goto exit;
+		DPRINTF(("%s: nid=%d stream channel=0x%4.4x\n", __func__, nid, (startchan >= nchan ? 0: (number << 4)) | startchan));
 		err = this->comresp(this, nid, CORB_SET_CONVERTER_STREAM_CHANNEL,
-				    (number << 4) | startchan, NULL);
+			(startchan >= nchan ? 0: (number << 4)) | startchan, NULL);
 		if (err)
 			goto exit;
 		if (this->w[nid].widgetcap & COP_AWCAP_DIGITAL) {