summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authorJacob Meuser <jakemsr@cvs.openbsd.org>2008-12-25 22:15:06 +0000
committerJacob Meuser <jakemsr@cvs.openbsd.org>2008-12-25 22:15:06 +0000
commitebe426e94d0d89c3e2cad9e759dacbb252b2fc2a (patch)
tree3a6535d37b682f6c080cdaef45ad769dbdec4a3b /sys/dev
parent16ca401b45ea601c777ce0386822772d93ed6135 (diff)
currently azalia only supports one codec. instead of using simply the
first codec with an audio function group, use the first codec with an audio function group that can do analog I/O, if there is one. codecs that just do digital I/O aren't quite as useful, yet.
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/pci/azalia.c59
1 files changed, 52 insertions, 7 deletions
diff --git a/sys/dev/pci/azalia.c b/sys/dev/pci/azalia.c
index acbf4ccd9ba..8d49e985864 100644
--- a/sys/dev/pci/azalia.c
+++ b/sys/dev/pci/azalia.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: azalia.c,v 1.95 2008/12/25 00:58:15 jakemsr Exp $ */
+/* $OpenBSD: azalia.c,v 1.96 2008/12/25 22:15:05 jakemsr Exp $ */
/* $NetBSD: azalia.c,v 1.20 2006/05/07 08:31:44 kent Exp $ */
/*-
@@ -665,7 +665,8 @@ void
azalia_attach_intr(struct device *self)
{
azalia_t *az;
- int err, i, c;
+ codec_t *codec;
+ int err, i, j, c;
az = (azalia_t*)self;
@@ -685,18 +686,43 @@ azalia_attach_intr(struct device *self)
AZ_WRITE_4(az, INTCTL,
AZ_READ_4(az, INTCTL) | HDA_INTCTL_CIE | HDA_INTCTL_GIE);
- c = -1;
+ c = 0;
for (i = 0; i < az->ncodecs; i++) {
err = azalia_codec_init(&az->codecs[i]);
- if (!err && c < 0)
- c = i;
+ if (!err)
+ c++;
}
- if (c < 0) {
+ if (c == 0) {
printf("%s: No codecs found\n", XNAME(az));
goto err_exit;
}
- /* Use the first audio codec */
+
+ /* Use the first codec capable of analog I/O. If there are none,
+ * use the first codec capable of digital I/O.
+ */
+ c = -1;
+ for (i = 0; i < az->ncodecs; i++) {
+ if (az->codecs[i].audiofunc < 0)
+ continue;
+ codec = &az->codecs[i];
+ FOR_EACH_WIDGET(codec, j) {
+ if (codec->w[j].type == COP_AWTYPE_AUDIO_OUTPUT ||
+ codec->w[j].type == COP_AWTYPE_AUDIO_INPUT) {
+ if (codec->w[j].widgetcap & COP_AWCAP_DIGITAL) {
+ if (c < 0)
+ c = i;
+ } else {
+ c = i;
+ break;
+ }
+ }
+ }
+ }
az->codecno = c;
+ if (az->codecno < 0) {
+ DPRINTF(("%s: chosen codec has no converters.\n", XNAME(az)));
+ goto err_exit;
+ }
printf("%s: codecs: ", XNAME(az));
for (i = 0; i < az->ncodecs; i++) {
@@ -710,6 +736,19 @@ azalia_attach_intr(struct device *self)
}
printf("\n");
+ /* All codecs with audio are enabled, but only one will be used. */
+ for (i = 0; i < az->ncodecs; i++) {
+ codec = &az->codecs[i];
+ if (i != az->codecno) {
+ if (codec->audiofunc < 0)
+ continue;
+ codec->comresp(codec, codec->audiofunc,
+ CORB_SET_POWER_STATE, CORB_PS_D3, NULL);
+ DELAY(100);
+ azalia_codec_delete(codec);
+ }
+ }
+
/* Use stream#1 and #2. Don't use stream#0. */
if (azalia_stream_init(&az->pstream, az, az->nistreams + 0,
1, AUMODE_PLAY))
@@ -1298,12 +1337,18 @@ azalia_codec_delete(codec_t *this)
this->formats = NULL;
}
this->nformats = 0;
+
if (this->encs != NULL) {
free(this->encs, M_DEVBUF);
this->encs = NULL;
}
this->nencs = 0;
+ if (this->w != NULL) {
+ free(this->w, M_DEVBUF);
+ this->w = NULL;
+ }
+
return 0;
}