diff options
Diffstat (limited to 'sys')
-rw-r--r-- | sys/dev/pci/azalia.c | 115 | ||||
-rw-r--r-- | sys/dev/pci/azalia.h | 7 | ||||
-rw-r--r-- | sys/dev/pci/azalia_codec.c | 44 |
3 files changed, 59 insertions, 107 deletions
diff --git a/sys/dev/pci/azalia.c b/sys/dev/pci/azalia.c index 4d6921ed9ba..843f6940406 100644 --- a/sys/dev/pci/azalia.c +++ b/sys/dev/pci/azalia.c @@ -1,4 +1,4 @@ -/* $OpenBSD: azalia.c,v 1.72 2008/11/14 21:58:11 jakemsr Exp $ */ +/* $OpenBSD: azalia.c,v 1.73 2008/11/19 03:44:14 jakemsr Exp $ */ /* $NetBSD: azalia.c,v 1.20 2006/05/07 08:31:44 kent Exp $ */ /*- @@ -43,7 +43,6 @@ #include <sys/param.h> #include <sys/device.h> -#include <sys/timeout.h> #include <sys/malloc.h> #include <sys/systm.h> #include <uvm/uvm_param.h> @@ -171,7 +170,6 @@ typedef struct azalia_t { codec_t codecs[15]; int ncodecs; /* number of codecs */ int codecno; /* index of the using codec */ - struct timeout timeo; azalia_dma_t corb_dma; int corb_size; @@ -223,8 +221,6 @@ int azalia_free_dmamem(const azalia_t *, azalia_dma_t*); int azalia_codec_init(codec_t *); int azalia_codec_delete(codec_t *); -void azalia_codec_jack_intr(void *); -void azalia_codec_jack_handler(codec_t *); void azalia_codec_add_bits(codec_t *, int, uint32_t, int); void azalia_codec_add_format(codec_t *, int, int, int, uint32_t, int32_t); @@ -731,112 +727,12 @@ azalia_attach_intr(struct device *self) az->audiodev = audio_attach_mi(&azalia_hw_if, az, &az->dev); - /* Setup jack_intr if only there is no unsol_event handler. */ - if (az->codecs[az->codecno].unsol_event == NULL) { - timeout_set(&az->timeo, azalia_codec_jack_intr, az); - timeout_add_sec(&az->timeo, 2); - } - return; err_exit: azalia_pci_detach(self, 0); return; } -void -azalia_codec_jack_intr(void *addr) -{ - struct azalia_t *az = (struct azalia_t *)addr; - int s; - - s = splaudio(); - azalia_codec_jack_handler(&az->codecs[az->codecno]); - timeout_add_sec(&az->timeo, 2); - splx(s); -} - -void -azalia_codec_jack_handler(codec_t *this) -{ - int i, j, err, dev; - uint32_t sense, ctl, val, dir; - - FOR_EACH_WIDGET(this, i) { - const widget_t *w; - - dev = 0; - w = &this->w[i]; - - /* Find pin with conn=jack and presence capability. */ - if (w == NULL || w->type != COP_AWTYPE_PIN_COMPLEX || - (CORB_CD_PORT(w->d.pin.config)) != CORB_CD_JACK || - (!(w->d.pin.cap & COP_PINCAP_PRESENCE))) - continue; - - /* Headphones. */ - if (w->d.pin.device == CORB_CD_HEADPHONE && - (w->d.pin.cap & COP_PINCAP_HEADPHONE)) { - dev = CORB_CD_SPEAKER; /* (un)mute speakers */ - dir = CORB_PWC_OUTPUT; - } - - if (!dev) - continue; - - err = this->comresp(this, w->nid, CORB_GET_PIN_SENSE, - 0, &sense); - if (err) - break; - - err = this->comresp(this, w->nid, CORB_GET_PIN_WIDGET_CONTROL, - 0, &ctl); - if (err) - break; - - if (sense & CORB_PS_PRESENCE) - val = ctl | dir; - else - val = ctl & ~dir; - - if (val != ctl) { - ctl = val; - err = this->comresp(this, w->nid, - CORB_SET_PIN_WIDGET_CONTROL, ctl, NULL); - if (err) - break; - } - - FOR_EACH_WIDGET(this, j) { - const widget_t *w; - - w = &this->w[j]; - - /* Find suitable and connected pin for (un)mute. */ - if (w == NULL || w->type != COP_AWTYPE_PIN_COMPLEX || - (CORB_CD_PORT(w->d.pin.config)) == CORB_CD_NONE || - j == i || w->d.pin.device != dev) - continue; - - err = this->comresp(this, w->nid, - CORB_GET_PIN_WIDGET_CONTROL, 0, &ctl); - if (err) - break; - - if (sense & CORB_PS_PRESENCE) - val = ctl & ~dir; - else - val = ctl | dir; - - if (val != ctl) { - ctl = val; - err = this->comresp(this, w->nid, - CORB_SET_PIN_WIDGET_CONTROL, ctl, NULL); - if (err) - break; - } - } - } -} int azalia_init_corb(azalia_t *az) @@ -1897,6 +1793,7 @@ azalia_widget_print_audio(const widget_t *this, const char *lead) int azalia_widget_init_pin(widget_t *this, const codec_t *codec) { + codec_t *wcodec; uint32_t result; int err; @@ -1939,6 +1836,14 @@ azalia_widget_init_pin(widget_t *this, const codec_t *codec) CORB_SET_PIN_WIDGET_CONTROL, result, NULL); } } + /* sense pin */ + if (codec->nsense_pins < AZ_MAX_SENSE_PINS && + this->d.pin.cap & COP_PINCAP_PRESENCE && + CORB_CD_PORT(this->d.pin.config) == CORB_CD_JACK) { + wcodec = &codec->az->codecs[codec->az->codecno]; + wcodec->sense_pins[codec->nsense_pins] = this->nid; + wcodec->nsense_pins++; + } return 0; } diff --git a/sys/dev/pci/azalia.h b/sys/dev/pci/azalia.h index 4633b7d2f82..1d00df8e5fc 100644 --- a/sys/dev/pci/azalia.h +++ b/sys/dev/pci/azalia.h @@ -1,4 +1,4 @@ -/* $OpenBSD: azalia.h,v 1.20 2008/11/05 03:20:35 jakemsr Exp $ */ +/* $OpenBSD: azalia.h,v 1.21 2008/11/19 03:44:14 jakemsr Exp $ */ /* $NetBSD: azalia.h,v 1.6 2006/01/16 14:15:26 kent Exp $ */ /*- @@ -474,6 +474,7 @@ #define CORB_NID_ROOT 0 #define HDA_MAX_CHANNELS 16 +#define AZ_MAX_SENSE_PINS 8 /* memory-mapped types */ typedef struct { @@ -556,6 +557,7 @@ typedef struct { #define MI_TARGET_SPDIF 0x107 #define MI_TARGET_SPDIF_CC 0x108 #define MI_TARGET_EAPD 0x109 +#define AZ_TARGET_PINSENSE 0xf00 } mixer_item_t; #define VALID_WIDGET_NID(nid, codec) (nid == (codec)->audiofunc || \ @@ -616,6 +618,9 @@ typedef struct codec_t { struct audio_encoding* encs; int nencs; + nid_t sense_pins[AZ_MAX_SENSE_PINS]; + int nsense_pins; + uint32_t *extra; u_int rate; } codec_t; diff --git a/sys/dev/pci/azalia_codec.c b/sys/dev/pci/azalia_codec.c index 860c54427e2..f1000e32314 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.65 2008/11/17 00:42:53 jakemsr Exp $ */ +/* $OpenBSD: azalia_codec.c,v 1.66 2008/11/19 03:44:14 jakemsr Exp $ */ /* $NetBSD: azalia_codec.c,v 1.8 2006/05/10 11:17:27 kent Exp $ */ /*- @@ -881,6 +881,35 @@ azalia_generic_mixer_init(codec_t *this) } } + /* sense pins */ + for (i = 0; i < this->nsense_pins; i++) { + FOR_EACH_WIDGET(this, j) { + if (this->w[j].nid == this->sense_pins[i]) + break; + } + if (j == this->wend) { + DPRINTF(("%s: sense pin %2.2x not found\n", + __func__, this->sense_pins[i])); + continue; + } + + MIXER_REG_PROLOG; + m->nid = this->w[j].nid; + snprintf(d->label.name, sizeof(d->label.name), "%s_sense", + this->w[j].name); + d->type = AUDIO_MIXER_ENUM; + d->mixer_class = AZ_CLASS_OUTPUT; + m->target = AZ_TARGET_PINSENSE; + d->un.e.num_mem = 2; + d->un.e.member[0].ord = 0; + strlcpy(d->un.e.member[0].label.name, "unplugged", + MAX_AUDIO_DEV_LEN); + d->un.e.member[1].ord = 1; + strlcpy(d->un.e.member[1].label.name, "plugged", + MAX_AUDIO_DEV_LEN); + this->nmixers++; + } + /* if the codec has multiple DAC groups, create "inputs.usingdac" */ if (this->dacs.ngroups > 1) { MIXER_REG_PROLOG; @@ -1367,6 +1396,15 @@ azalia_generic_mixer_get(const codec_t *this, nid_t nid, int target, mixer_ctrl_ mc->un.ord = result & CORB_EAPD_EAPD ? 1 : 0; } + /* sense pin */ + else if (target == AZ_TARGET_PINSENSE) { + err = this->comresp(this, nid, CORB_GET_PIN_SENSE, + 0, &result); + if (err) + return err; + mc->un.ord = result & CORB_PS_PRESENCE ? 1 : 0; + } + else { printf("%s: internal error in %s: target=%x\n", XNAME(this), __func__, target); @@ -1648,6 +1686,10 @@ azalia_generic_mixer_set(codec_t *this, nid_t nid, int target, const mixer_ctrl_ return err; } + else if (target == AZ_TARGET_PINSENSE) { + /* do nothing, control is read only */ + } + else { printf("%s: internal error in %s: target=%x\n", XNAME(this), __func__, target); |