summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjakemsr <jakemsr@openbsd.org>2008-11-27 23:30:58 +0000
committerjakemsr <jakemsr@openbsd.org>2008-11-27 23:30:58 +0000
commitde7cbcd6a2f3ae22f73f6910006a41360c354a7a (patch)
treef04890071203e08ac0672733f82627a6d3f443e0
parentfinally, generic converter grouping that fits our needs and works (diff)
downloadwireguard-openbsd-de7cbcd6a2f3ae22f73f6910006a41360c354a7a.tar.xz
wireguard-openbsd-de7cbcd6a2f3ae22f73f6910006a41360c354a7a.zip
widget initialization cleanup:
* configure widgets all in one place * add a flag on the widget_t to let us know if the widget is not connected; shaves a lot of connection checking code * be sure not to add power widgets as connectable sources/sinks * configure unconnected pins as output pins. should help some MacBooks and be benign to other devices. the last change has been tested by several as a separate diff. no real functional changes otherwise. from Alexey Suslikov. thanks!
-rw-r--r--sys/dev/pci/azalia.c123
-rw-r--r--sys/dev/pci/azalia.h12
-rw-r--r--sys/dev/pci/azalia_codec.c195
3 files changed, 134 insertions, 196 deletions
diff --git a/sys/dev/pci/azalia.c b/sys/dev/pci/azalia.c
index 27229edaa79..0bf2196ff29 100644
--- a/sys/dev/pci/azalia.c
+++ b/sys/dev/pci/azalia.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: azalia.c,v 1.74 2008/11/27 22:54:20 jakemsr Exp $ */
+/* $OpenBSD: azalia.c,v 1.75 2008/11/27 23:30:58 jakemsr Exp $ */
/* $NetBSD: azalia.c,v 1.20 2006/05/07 08:31:44 kent Exp $ */
/*-
@@ -1284,8 +1284,8 @@ azalia_codec_init(codec_t *this)
return err;
}
err = azalia_widget_label_widgets(this);
- if (err)
- return err;
+ if (err)
+ return err;
err = this->init_dacgroup(this);
if (err)
return err;
@@ -1632,23 +1632,33 @@ azalia_widget_init(widget_t *this, const codec_t *codec, nid_t nid)
this->widgetcap = result;
this->type = COP_AWCAP_TYPE(result);
if (this->widgetcap & COP_AWCAP_POWER) {
- codec->comresp(codec, nid, CORB_SET_POWER_STATE, CORB_PS_D0, &result);
+ codec->comresp(codec, nid, CORB_SET_POWER_STATE,
+ CORB_PS_D0, &result);
DELAY(100);
}
- if ((this->type == COP_AWTYPE_AUDIO_OUTPUT) ||
- (this->type == COP_AWTYPE_AUDIO_INPUT))
+
+ this->enable = 1;
+ switch (this->type) {
+ case COP_AWTYPE_AUDIO_OUTPUT:
+ /* FALLTHROUGH */
+ case COP_AWTYPE_AUDIO_INPUT:
azalia_widget_init_audio(this, codec);
- if (this->type == COP_AWTYPE_PIN_COMPLEX)
+ break;
+ case COP_AWTYPE_PIN_COMPLEX:
azalia_widget_init_pin(this, codec);
- if (this->type == COP_AWTYPE_VOLUME_KNOB) {
- err = codec->comresp(codec, this->nid,
- CORB_GET_PARAMETER,
+ break;
+ case COP_AWTYPE_VOLUME_KNOB:
+ err = codec->comresp(codec, this->nid, CORB_GET_PARAMETER,
COP_VOLUME_KNOB_CAPABILITIES, &result);
- if (!err)
- this->d.volume.cap = result;
+ if (err)
+ return err;
+ this->d.volume.cap = result;
+ break;
+ case COP_AWTYPE_POWER:
+ this->enable = 0;
+ break;
}
-
/* amplifier information */
if (this->widgetcap & COP_AWCAP_INAMP) {
if (this->widgetcap & COP_AWCAP_AMPOV)
@@ -1808,6 +1818,12 @@ azalia_widget_print_audio(const widget_t *this, const char *lead)
int
azalia_widget_init_pin(widget_t *this, const codec_t *codec)
{
+ typedef enum {
+ PIN_DIR_IN,
+ PIN_DIR_OUT,
+ PIN_DIR_MIC
+ } pintype_t;
+ pintype_t pintype = PIN_DIR_IN;
codec_t *wcodec;
uint32_t result;
int err;
@@ -1828,28 +1844,67 @@ azalia_widget_init_pin(widget_t *this, const codec_t *codec)
return err;
this->d.pin.cap = result;
- /* input pin */
- if ((this->d.pin.cap & COP_PINCAP_INPUT) &&
- (this->d.pin.cap & COP_PINCAP_OUTPUT) == 0) {
- err = codec->comresp(codec, this->nid,
- CORB_GET_PIN_WIDGET_CONTROL, 0, &result);
- if (err == 0) {
- result &= ~CORB_PWC_OUTPUT;
- result |= CORB_PWC_INPUT;
- codec->comresp(codec, this->nid,
- CORB_SET_PIN_WIDGET_CONTROL, result, NULL);
- }
+ if (!(this->d.pin.cap & COP_PINCAP_INPUT))
+ pintype = PIN_DIR_OUT;
+ if (!(this->d.pin.cap & COP_PINCAP_OUTPUT))
+ pintype = PIN_DIR_IN;
+
+ switch (this->d.pin.device) {
+ case CORB_CD_LINEOUT:
+ case CORB_CD_SPEAKER:
+ case CORB_CD_HEADPHONE:
+ case CORB_CD_SPDIFOUT:
+ case CORB_CD_DIGITALOUT:
+ pintype = PIN_DIR_OUT;
+ break;
+ case CORB_CD_CD:
+ case CORB_CD_LINEIN:
+ case CORB_CD_SPDIFIN:
+ case CORB_CD_DIGITALIN:
+ pintype = PIN_DIR_IN;
+ break;
+ case CORB_CD_MICIN:
+ pintype = PIN_DIR_MIC;
+ break;
}
- /* output pin, or bidirectional pin */
- if (this->d.pin.cap & COP_PINCAP_OUTPUT) {
- err = codec->comresp(codec, this->nid,
- CORB_GET_PIN_WIDGET_CONTROL, 0, &result);
- if (err == 0) {
- result &= ~CORB_PWC_INPUT;
- result |= CORB_PWC_OUTPUT;
- codec->comresp(codec, this->nid,
- CORB_SET_PIN_WIDGET_CONTROL, result, NULL);
- }
+
+ /* Disable unconnected pins */
+ if (CORB_CD_PORT(this->d.pin.config) == CORB_CD_NONE)
+ this->enable = 0;
+
+ /* Workaround broken machines which have their actual
+ output on ports marked conn=none (e.g. MacBookPro1,2).
+ Should not harm correct codec configurations. */
+ if (!this->enable)
+ pintype = PIN_DIR_OUT;
+
+ switch (pintype) {
+ case PIN_DIR_IN:
+ codec->comresp(codec, this->nid, CORB_SET_PIN_WIDGET_CONTROL,
+ CORB_PWC_INPUT, NULL);
+ break;
+ case PIN_DIR_OUT:
+ codec->comresp(codec, this->nid, CORB_SET_PIN_WIDGET_CONTROL,
+ CORB_PWC_OUTPUT, NULL);
+ break;
+ case PIN_DIR_MIC:
+ codec->comresp(codec, this->nid, CORB_SET_PIN_WIDGET_CONTROL,
+ CORB_PWC_INPUT|CORB_PWC_VREF_80, NULL);
+ break;
+ }
+
+ /* EAPD pin */
+ if (this->d.pin.cap & COP_PINCAP_EAPD) {
+ err = codec->comresp(codec, this->nid, CORB_GET_EAPD_BTL_ENABLE,
+ 0, &result);
+ if (err)
+ return err;
+ result &= 0xff;
+ result |= CORB_EAPD_EAPD;
+ err = codec->comresp(codec, this->nid, CORB_SET_EAPD_BTL_ENABLE,
+ result, &result);
+ if (err)
+ return err;
}
/* sense pin */
if (codec->nsense_pins < AZ_MAX_SENSE_PINS &&
diff --git a/sys/dev/pci/azalia.h b/sys/dev/pci/azalia.h
index 1d00df8e5fc..f31df1d65fa 100644
--- a/sys/dev/pci/azalia.h
+++ b/sys/dev/pci/azalia.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: azalia.h,v 1.21 2008/11/19 03:44:14 jakemsr Exp $ */
+/* $OpenBSD: azalia.h,v 1.22 2008/11/27 23:30:58 jakemsr Exp $ */
/* $NetBSD: azalia.h,v 1.6 2006/01/16 14:15:26 kent Exp $ */
/*-
@@ -513,6 +513,7 @@ typedef int nid_t;
typedef struct {
nid_t nid;
+ int enable;
uint32_t widgetcap;
int type; /* = bit20-24 of widgetcap */
int nconnections;
@@ -564,15 +565,6 @@ typedef struct {
(nid >= (codec)->wstart && \
nid < (codec)->wend))
-#define PIN_STATUS(wid, conn) \
- do { \
- if ((wid)->type != COP_AWTYPE_PIN_COMPLEX) \
- (conn) = 0; \
- else \
- (conn) = \
- ((wid)->d.pin.config & CORB_CD_PORT_MASK) >> 30; \
- } while (0)
-
typedef struct {
int nconv;
nid_t conv[HDA_MAX_CHANNELS]; /* front, surround, clfe, side, ... */
diff --git a/sys/dev/pci/azalia_codec.c b/sys/dev/pci/azalia_codec.c
index a24de856e2f..0fc75d25624 100644
--- a/sys/dev/pci/azalia_codec.c
+++ b/sys/dev/pci/azalia_codec.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: azalia_codec.c,v 1.68 2008/11/27 23:03:29 jakemsr Exp $ */
+/* $OpenBSD: azalia_codec.c,v 1.69 2008/11/27 23:30:58 jakemsr Exp $ */
/* $NetBSD: azalia_codec.c,v 1.8 2006/05/10 11:17:27 kent Exp $ */
/*-
@@ -49,7 +49,6 @@
#define AzaliaNclfe "clfe"
#define AzaliaNside "side"
-#define ALC260_FUJITSU_ID 0x132610cf
#define REALTEK_ALC660 0x10ec0660
#define ALC660_ASUS_G2K 0x13391043
#define REALTEK_ALC880 0x10ec0880
@@ -71,7 +70,6 @@
#define STAC9205_DELL_V1500 0x02281028
int azalia_generic_codec_init_dacgroup(codec_t *);
-int azalia_generic_codec_is_live_pin(const widget_t *, uint32_t, uint32_t);
int azalia_generic_codec_fnode(codec_t *, nid_t, int, int);
int azalia_generic_codec_add_convgroup(codec_t *, convgroupset_t *,
uint32_t, uint32_t);
@@ -328,17 +326,24 @@ azalia_generic_codec_add_convgroup(codec_t *this, convgroupset_t *group,
for (assoc = 0; assoc <= CORB_CD_ASSOCIATION_MAX; assoc++) {
for (seq = 0; seq <= CORB_CD_SEQUENCE_MAX; seq++) {
FOR_EACH_WIDGET(this, i) {
- const widget_t *w = &this->w[i];
+ const widget_t *w;
+
+ w = &this->w[i];
+ if (!w->enable)
+ continue;
+ if (w->type != COP_AWTYPE_PIN_COMPLEX)
+ continue;
+ if ((w->widgetcap &
+ COP_AWCAP_DIGITAL) != digital)
+ continue;
if (w->d.pin.sequence != seq ||
w->d.pin.association != assoc)
continue;
if (type == COP_AWTYPE_AUDIO_OUTPUT) {
- if (azalia_generic_codec_is_live_pin(w,
- COP_PINCAP_OUTPUT, digital) == 0)
+ if (!(w->d.pin.cap & COP_PINCAP_OUTPUT))
continue;
} else {
- if (azalia_generic_codec_is_live_pin(w,
- COP_PINCAP_INPUT, digital) == 0)
+ if (!(w->d.pin.cap & COP_PINCAP_INPUT))
continue;
}
DPRINTF(("\tpin=%2.2x, assoc=%d, seq=%d:",
@@ -392,37 +397,6 @@ done:
}
int
-azalia_generic_codec_is_live_pin(const widget_t *w, uint32_t iocap, uint32_t digital)
-{
- uint8_t conn, dev;
-
- if (w->type != COP_AWTYPE_PIN_COMPLEX)
- return 0;
- if ((w->d.pin.cap & iocap) == 0)
- return 0;
- if ((w->widgetcap & COP_AWCAP_DIGITAL) != digital)
- return 0;
- PIN_STATUS(w, conn);
- if (conn == CORB_CD_NONE)
- return 0;
- dev = CORB_CD_DEVICE(w->d.pin.config);
- if (iocap == COP_PINCAP_OUTPUT) {
- if (dev == CORB_CD_LINEOUT || dev == CORB_CD_SPEAKER ||
- dev == CORB_CD_HEADPHONE ||
- (digital == COP_AWCAP_DIGITAL &&
- (dev == CORB_CD_SPDIFOUT || dev == CORB_CD_DIGITALOUT)))
- return 1;
- } else {
- if (dev == CORB_CD_MICIN || dev == CORB_CD_LINEIN ||
- (digital == COP_AWCAP_DIGITAL &&
- (dev == CORB_CD_SPDIFIN || dev == CORB_CD_DIGITALIN)))
- return 1;
- }
-
- return 0;
-}
-
-int
azalia_generic_codec_fnode(codec_t *this, nid_t node, int index, int depth)
{
const widget_t *w;
@@ -449,9 +423,12 @@ azalia_generic_codec_fnode(codec_t *this, nid_t node, int index, int depth)
if (this->w[k].nid == j)
break;
if (k < this->wend) {
- ret = azalia_generic_codec_fnode(this, node, k, depth);
- if (ret >= 0)
- return ret;
+ if (this->w[k].enable) {
+ ret = azalia_generic_codec_fnode(this, node,
+ k, depth);
+ if (ret >= 0)
+ return ret;
+ }
}
}
return -1;
@@ -534,14 +511,8 @@ azalia_generic_mixer_init(codec_t *this)
const widget_t *w;
w = &this->w[i];
-
- /* skip unconnected pins */
- if (w->type == COP_AWTYPE_PIN_COMPLEX) {
- uint8_t conn =
- (w->d.pin.config & CORB_CD_PORT_MASK) >> 30;
- if (conn == 1) /* no physical connection */
- continue;
- }
+ if (!w->enable)
+ continue;
/* converters (DACc/ADCs)
* not mixer widgets, but keep track of connections to
@@ -551,15 +522,13 @@ azalia_generic_mixer_init(codec_t *this)
/* adcs */
if (w->type == COP_AWTYPE_AUDIO_INPUT) {
for (j = 0; j < w->nconnections; j++) {
- uint8_t conn;
+ const widget_t *ww;
if (!VALID_WIDGET_NID(w->connections[j],
this))
continue;
- /* skip unconnected pins */
- PIN_STATUS(&this->w[w->connections[j]],
- conn);
- if (conn == 1)
+ ww = &this->w[w->connections[j]];
+ if (!ww->enable)
continue;
for (k = 0; k < naconns; k++) {
if (aconns[k] ==
@@ -576,15 +545,13 @@ azalia_generic_mixer_init(codec_t *this)
/* dacs */
if (w->type == COP_AWTYPE_AUDIO_OUTPUT) {
for (j = 0; j < w->nconnections; j++) {
- uint8_t conn;
+ const widget_t *ww;
if (!VALID_WIDGET_NID(w->connections[j],
this))
continue;
- /* skip unconnected pins */
- PIN_STATUS(&this->w[w->connections[j]],
- conn);
- if (conn == 1)
+ ww = &this->w[w->connections[j]];
+ if (!ww->enable)
continue;
for (k = 0; k < ndconns; k++) {
if (dconns[k] ==
@@ -601,8 +568,7 @@ azalia_generic_mixer_init(codec_t *this)
}
/* selector */
- if (w->type != COP_AWTYPE_AUDIO_MIXER &&
- w->type != COP_AWTYPE_POWER && w->nconnections >= 2) {
+ if (w->type != COP_AWTYPE_AUDIO_MIXER && w->nconnections >= 2) {
MIXER_REG_PROLOG;
snprintf(d->label.name, sizeof(d->label.name),
"%s_source", w->name);
@@ -615,14 +581,12 @@ azalia_generic_mixer_init(codec_t *this)
d->mixer_class = AZ_CLASS_OUTPUT;
m->target = MI_TARGET_CONNLIST;
for (j = 0, k = 0; j < w->nconnections && k < 32; j++) {
- uint8_t conn;
+ const widget_t *ww;
if (!VALID_WIDGET_NID(w->connections[j], this))
continue;
- /* skip unconnected pins */
- PIN_STATUS(&this->w[w->connections[j]],
- conn);
- if (conn == 1)
+ ww = &this->w[w->connections[j]];
+ if (!ww->enable)
continue;
d->un.e.member[k].ord = j;
strlcpy(d->un.e.member[k].label.name,
@@ -702,16 +666,15 @@ azalia_generic_mixer_init(codec_t *this)
AudioNon, MAX_AUDIO_DEV_LEN);
this->nmixers++;
} else {
- uint8_t conn;
-
for (j = 0; j < w->nconnections; j++) {
+ const widget_t *ww;
+
MIXER_REG_PROLOG;
- if (!VALID_WIDGET_NID(w->connections[j], this))
+ if (!VALID_WIDGET_NID(w->connections[j],
+ this))
continue;
- /* skip unconnected pins */
- PIN_STATUS(&this->w[w->connections[j]],
- conn);
- if (conn == 1)
+ ww = &this->w[w->connections[j]];
+ if (!ww->enable)
continue;
snprintf(d->label.name, sizeof(d->label.name),
"%s_%s_mute", w->name,
@@ -761,16 +724,15 @@ azalia_generic_mixer_init(codec_t *this)
MIXER_DELTA(COP_AMPCAP_NUMSTEPS(w->inamp_cap));
this->nmixers++;
} else {
- uint8_t conn;
-
for (j = 0; j < w->nconnections; j++) {
+ const widget_t *ww;
+
MIXER_REG_PROLOG;
- if (!VALID_WIDGET_NID(w->connections[j], this))
+ if (!VALID_WIDGET_NID(w->connections[j],
+ this))
continue;
- /* skip unconnected pins */
- PIN_STATUS(&this->w[w->connections[j]],
- conn);
- if (conn == 1)
+ ww = &this->w[w->connections[j]];
+ if (!ww->enable)
continue;
snprintf(d->label.name, sizeof(d->label.name),
"%s_%s", w->name,
@@ -1041,77 +1003,6 @@ azalia_generic_mixer_default(codec_t *this)
int
azalia_generic_mixer_pin_sense(codec_t *this)
{
- typedef enum {
- PIN_DIR_IN,
- PIN_DIR_OUT,
- PIN_DIR_MIC
- } pintype_t;
- const widget_t *w;
- int i;
-
- FOR_EACH_WIDGET(this, i) {
- pintype_t pintype = PIN_DIR_IN;
-
- w = &this->w[i];
- if (w->type != COP_AWTYPE_PIN_COMPLEX)
- continue;
- if (!(w->d.pin.cap & COP_PINCAP_INPUT))
- pintype = PIN_DIR_OUT;
- if (!(w->d.pin.cap & COP_PINCAP_OUTPUT))
- pintype = PIN_DIR_IN;
-
- switch (w->d.pin.device) {
- case CORB_CD_LINEOUT:
- case CORB_CD_SPEAKER:
- case CORB_CD_HEADPHONE:
- case CORB_CD_SPDIFOUT:
- case CORB_CD_DIGITALOUT:
- pintype = PIN_DIR_OUT;
- break;
- case CORB_CD_CD:
- case CORB_CD_LINEIN:
- pintype = PIN_DIR_IN;
- break;
- case CORB_CD_MICIN:
- pintype = PIN_DIR_MIC;
- break;
- }
-
- switch (pintype) {
- case PIN_DIR_IN:
- this->comresp(this, w->nid,
- CORB_SET_PIN_WIDGET_CONTROL,
- CORB_PWC_INPUT, NULL);
- break;
- case PIN_DIR_OUT:
- this->comresp(this, w->nid,
- CORB_SET_PIN_WIDGET_CONTROL,
- CORB_PWC_OUTPUT, NULL);
- break;
- case PIN_DIR_MIC:
- this->comresp(this, w->nid,
- CORB_SET_PIN_WIDGET_CONTROL,
- CORB_PWC_INPUT|CORB_PWC_VREF_80, NULL);
- break;
- }
-
- if (w->d.pin.cap & COP_PINCAP_EAPD) {
- uint32_t result;
- int err;
-
- err = this->comresp(this, w->nid,
- CORB_GET_EAPD_BTL_ENABLE, 0, &result);
- if (err)
- continue;
- result &= 0xff;
- result |= CORB_EAPD_EAPD;
- err = this->comresp(this, w->nid,
- CORB_SET_EAPD_BTL_ENABLE, result, &result);
- if (err)
- continue;
- }
- }
-
/* GPIO quirks */
if (this->vid == SIGMATEL_STAC9221 && this->subid == STAC9221_APPLE_ID) {