summaryrefslogtreecommitdiff
path: root/sys/dev/pci
diff options
context:
space:
mode:
authorJacob Meuser <jakemsr@cvs.openbsd.org>2008-12-31 12:54:44 +0000
committerJacob Meuser <jakemsr@cvs.openbsd.org>2008-12-31 12:54:44 +0000
commitf586ebe20d0ffdaea0fa0828203b2dafdcf383cb (patch)
treef772ed27ec7ae2193123ed683c3f29806e74b55f /sys/dev/pci
parente9752d163533429190145e2f552a1a4dbddd1c8a (diff)
rewrite azalia_codec_connect_stream
- quit swapping channels 2:3 with 4:5 when processing 6 or more channels. hacks deep in drivers to "fix" wrongly encoded files is just wrong. - try to be sure headphones AND speakers get DAC output by default.
Diffstat (limited to 'sys/dev/pci')
-rw-r--r--sys/dev/pci/azalia.c96
1 files changed, 55 insertions, 41 deletions
diff --git a/sys/dev/pci/azalia.c b/sys/dev/pci/azalia.c
index 10418dfab01..cf295148f2e 100644
--- a/sys/dev/pci/azalia.c
+++ b/sys/dev/pci/azalia.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: azalia.c,v 1.102 2008/12/31 12:47:30 jakemsr Exp $ */
+/* $OpenBSD: azalia.c,v 1.103 2008/12/31 12:54:43 jakemsr Exp $ */
/* $NetBSD: azalia.c,v 1.20 2006/05/07 08:31:44 kent Exp $ */
/*-
@@ -1637,60 +1637,74 @@ int
azalia_codec_connect_stream(codec_t *this, int dir, uint16_t fmt, int number)
{
const convgroup_t *group;
- uint32_t v;
- int i, err, startchan, nchan;
- nid_t nid;
- boolean_t flag222;
+ widget_t *w;
+ uint32_t digital, stream_chan;
+ int i, err, curchan, nchan, widchan;
- DPRINTFN(1, ("%s: fmt=0x%4.4x number=%d\n", __func__, fmt, number));
err = 0;
+ nchan = (fmt & HDA_SD_FMT_CHAN) + 1;
+
if (dir == AUMODE_RECORD)
group = &this->adcs.groups[this->adcs.cur];
else
group = &this->dacs.groups[this->dacs.cur];
- flag222 = group->nconv >= 3 &&
- (WIDGET_CHANNELS(&this->w[group->conv[0]]) == 2) &&
- (WIDGET_CHANNELS(&this->w[group->conv[1]]) == 2) &&
- (WIDGET_CHANNELS(&this->w[group->conv[2]]) == 2);
- nchan = (fmt & HDA_SD_FMT_CHAN) + 1;
- startchan = 0;
+
+ curchan = 0;
for (i = 0; i < group->nconv; i++) {
- uint32_t stream_chan;
- nid = group->conv[i];
+ w = &this->w[group->conv[i]];
+ widchan = WIDGET_CHANNELS(w);
+
+ stream_chan = (number << 4);
+ if (curchan < nchan) {
+ stream_chan |= curchan;
+ } else if (w->nid == this->spkr_dac ||
+ w->nid == this->hp_dac) {
+ stream_chan |= 0; /* first channel(s) */
+ } else
+ stream_chan = 0; /* idle stream */
- /* surround and c/lfe handling */
- if (nchan >= 6 && flag222 && i == 1) {
- nid = group->conv[2];
- } else if (nchan >= 6 && flag222 && i == 2) {
- nid = group->conv[1];
+ if (stream_chan == 0) {
+ DPRINTFN(0, ("%s: %2.2x is idle\n", __func__, w->nid));
+ } else {
+ DPRINTFN(0, ("%s: %2.2x on stream chan %d\n", __func__,
+ w->nid, stream_chan & ~(number << 4)));
}
- if (startchan >= nchan)
- stream_chan = 0; /* stream#0 */
- else
- stream_chan = (number << 4) | startchan;
+ err = this->comresp(this, w->nid,
+ CORB_SET_CONVERTER_FORMAT, fmt, NULL);
+ if (err) {
+ DPRINTF(("%s: nid %2.2x fmt %2.2x: %d\n",
+ __func__, w->nid, fmt, err));
+ break;
+ }
+ err = this->comresp(this, w->nid,
+ CORB_SET_CONVERTER_STREAM_CHANNEL, stream_chan, NULL);
+ if (err) {
+ DPRINTF(("%s: nid %2.2x chan %d: %d\n",
+ __func__, w->nid, stream_chan, err));
+ break;
+ }
- err = this->comresp(this, nid, CORB_SET_CONVERTER_FORMAT,
- fmt, NULL);
- if (err)
- goto exit;
- err = this->comresp(this, nid, CORB_SET_CONVERTER_STREAM_CHANNEL,
- stream_chan, NULL);
- if (err)
- goto exit;
- if (this->w[nid].widgetcap & COP_AWCAP_DIGITAL) {
- /* enable S/PDIF */
- this->comresp(this, nid, CORB_GET_DIGITAL_CONTROL,
- 0, &v);
- v = (v & 0xff) | CORB_DCC_DIGEN;
- this->comresp(this, nid, CORB_SET_DIGITAL_CONTROL_L,
- v, NULL);
+ if (w->widgetcap & COP_AWCAP_DIGITAL) {
+ err = this->comresp(this, w->nid,
+ CORB_GET_DIGITAL_CONTROL, 0, &digital);
+ if (err) {
+ DPRINTF(("%s: nid %2.2x get digital: %d\n",
+ __func__, w->nid, err));
+ break;
+ }
+ digital = (digital & 0xff) | CORB_DCC_DIGEN;
+ err = this->comresp(this, w->nid,
+ CORB_SET_DIGITAL_CONTROL_L, digital, NULL);
+ if (err) {
+ DPRINTF(("%s: nid %2.2x set digital: %d\n",
+ __func__, w->nid, err));
+ break;
+ }
}
- startchan += WIDGET_CHANNELS(&this->w[nid]);
+ curchan += widchan;
}
-exit:
- DPRINTFN(1, ("%s: leave with %d\n", __func__, err));
return err;
}