summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/pci/azalia.c115
-rw-r--r--sys/dev/pci/azalia.h7
-rw-r--r--sys/dev/pci/azalia_codec.c44
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);