summaryrefslogtreecommitdiff
path: root/sys/dev/pci/azalia.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/pci/azalia.c')
-rw-r--r--sys/dev/pci/azalia.c84
1 files changed, 80 insertions, 4 deletions
diff --git a/sys/dev/pci/azalia.c b/sys/dev/pci/azalia.c
index 194fd903e8e..9460f2de206 100644
--- a/sys/dev/pci/azalia.c
+++ b/sys/dev/pci/azalia.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: azalia.c,v 1.100 2008/12/31 11:25:36 jakemsr Exp $ */
+/* $OpenBSD: azalia.c,v 1.101 2008/12/31 11:54:55 jakemsr Exp $ */
/* $NetBSD: azalia.c,v 1.20 2006/05/07 08:31:44 kent Exp $ */
/*-
@@ -238,6 +238,8 @@ int azalia_codec_connect_stream(codec_t *, int, uint16_t, int);
int azalia_codec_disconnect_stream(codec_t *, int);
void azalia_codec_print_audiofunc(const codec_t *);
void azalia_codec_print_groups(const codec_t *);
+int azalia_codec_init_hp_spkr(codec_t *);
+int azalia_codec_find_defdac(codec_t *, int, int);
int azalia_widget_init(widget_t *, const codec_t *, int);
int azalia_widget_label_widgets(codec_t *);
@@ -1286,6 +1288,8 @@ azalia_codec_init(codec_t *this)
sizeof(this->w[CORB_NID_ROOT].name));
strlcpy(this->w[this->audiofunc].name, "hdaudio",
sizeof(this->w[this->audiofunc].name));
+
+ this->speaker = -1;
FOR_EACH_WIDGET(this, i) {
err = azalia_widget_init(&this->w[i], this, i);
if (err)
@@ -1313,17 +1317,89 @@ azalia_codec_init(codec_t *this)
err = this->init_dacgroup(this);
if (err)
return err;
+
+ azalia_codec_print_groups(this);
+
err = azalia_widget_label_widgets(this);
if (err)
return err;
- azalia_codec_print_groups(this);
-
err = azalia_codec_construct_format(this, 0, 0);
if (err)
return err;
- return this->mixer_init(this);
+ err = this->mixer_init(this);
+ if (err)
+ return err;
+
+ err = azalia_codec_init_hp_spkr(this);
+ if (err)
+ return err;
+
+ return 0;
+}
+
+int
+azalia_codec_init_hp_spkr(codec_t *this)
+{
+ int i;
+
+ this->hp_dac = -1;
+ this->spkr_dac = -1;
+
+ if (this->speaker != -1)
+ this->spkr_dac = azalia_codec_find_defdac(this,
+ this->speaker, 0);
+
+ if (this->headphones == -1) {
+ FOR_EACH_WIDGET(this, i) {
+ if (this->w[i].type != COP_AWTYPE_PIN_COMPLEX)
+ continue;
+ if (this->w[i].d.pin.device == CORB_CD_LINEOUT &&
+ (this->w[i].d.pin.cap & COP_PINCAP_HEADPHONE)) {
+ this->headphones = i;
+ break;
+ }
+ }
+ }
+
+ if (this->headphones != -1)
+ this->hp_dac = azalia_codec_find_defdac(this,
+ this->headphones, 0);
+
+ return 0;
+}
+
+int
+azalia_codec_find_defdac(codec_t *this, int index, int depth)
+{
+ const widget_t *w;
+ int ret;
+
+ w = &this->w[index];
+ if (w->enable == 0)
+ return -1;
+
+ if (w->type == COP_AWTYPE_AUDIO_OUTPUT)
+ return index;
+
+ if (depth > 0 &&
+ (w->type == COP_AWTYPE_PIN_COMPLEX ||
+ w->type == COP_AWTYPE_AUDIO_INPUT))
+ return -1;
+ if (++depth >= 10)
+ return -1;
+
+ if (w->nconnections > 0) {
+ index = w->connections[w->selected];
+ if (VALID_WIDGET_NID(index, this)) {
+ ret = azalia_codec_find_defdac(this, index, depth);
+ if (ret >= 0)
+ return ret;
+ }
+ }
+
+ return -1;
}
int