Subject: Re: kern/34071: azalia device driver doesn't support pin sensing
To: None <kent@NetBSD.org, gnats-admin@netbsd.org, netbsd-bugs@netbsd.org,>
From: TAMURA Kent <kent@NetBSD.org>
List: netbsd-bugs
Date: 02/05/2007 14:40:02
The following reply was made to PR kern/34071; it has been noted by GNATS.
From: "TAMURA Kent" <kent@NetBSD.org>
To: "Berndt Josef Wulf" <wulf@ping.net.au>
Cc: gnats-bugs@netbsd.org
Subject: Re: kern/34071: azalia device driver doesn't support pin sensing
Date: Mon, 5 Feb 2007 23:35:51 +0900
Could you test the following patch and tell me the name of
the machine or mainboard?
----------------------------------------------------------------
Index: azalia_codec.c
===================================================================
RCS file: /cvsroot/src/sys/dev/pci/azalia_codec.c,v
retrieving revision 1.28
diff -u -r1.28 azalia_codec.c
--- azalia_codec.c 6 Jan 2007 18:35:35 -0000 1.28
+++ azalia_codec.c 5 Feb 2007 14:32:42 -0000
@@ -123,6 +123,9 @@
static int stac9221_init_dacgroup(codec_t *);
static int stac9221_mixer_init(codec_t *);
static int stac9220_mixer_init(codec_t *);
+static int stac9220_set_port(codec_t *, mixer_ctrl_t *);
+static int stac9220_get_port(codec_t *, mixer_ctrl_t *);
+static int stac9220_unsol_event(codec_t *, int);
int
@@ -190,6 +193,9 @@
case 0x83847690:
this->name = "Sigmatel STAC9220";
this->mixer_init = stac9220_mixer_init;
+ this->set_port = stac9220_set_port;
+ this->unsol_event = stac9220_unsol_event;
+ extra_size = 1;
break;
}
if (extra_size > 0) {
@@ -2606,6 +2612,7 @@
stac9220_mixer_init(codec_t *this)
{
mixer_ctrl_t mc;
+ uint32_t value;
this->nmixers = sizeof(stac9220_mixer_items) / sizeof(mixer_item_t);
this->mixers = malloc(sizeof(mixer_item_t) * this->nmixers,
@@ -2633,7 +2640,104 @@
mc.un.value.level[1] = mc.un.value.level[0];
generic_mixer_set(this, 0x0c, MI_TARGET_OUTAMP, &mc);
+#define STAC9220_XXX_ID 0x01cd1028
+#define STAC9220_EVENT_HP 0
+#define STAC9220_EXTRA_MASTER 0
+#define STAC9220_NID_MASTER 0x0b
+#define STAC9220_NID_HP 0x0d
+ if (this->subid == STAC9220_XXX_ID) {
+ /* setup a unsolicited event for the headphones */
+ this->comresp(this, STAC9220_NID_HP, CORB_SET_UNSOLICITED_RESPONSE,
+ CORB_UNSOL_ENABLE | STAC9220_EVENT_HP, NULL);
+ this->extra[STAC9220_EXTRA_MASTER] = 0; /* unmute */
+ /* If the headphone presents, mute the internal speaker */
+ this->comresp(this, STAC9220_NID_HP, CORB_GET_PIN_SENSE, 0, &value);
+ mc.un.ord = value & CORB_PS_PRESENSE ? 1 : 0;
+ generic_mixer_set(this, STAC9220_NID_MASTER, MI_TARGET_OUTAMP, &mc);
+ this->get_port = stac9220_get_port;
+ }
+ return 0;
+}
+
+static int
+stac9220_set_port(codec_t *this, mixer_ctrl_t *mc)
+{
+ const mixer_item_t *m;
+ uint32_t value;
+ int err;
+
+ if (mc->dev >= this->nmixers)
+ return ENXIO;
+ m = &this->mixers[mc->dev];
+ if (mc->type != m->devinfo.type)
+ return EINVAL;
+ if (mc->type == AUDIO_MIXER_CLASS)
+ return 0;
+ if (this->subid == STAC9220_XXX_ID && m->nid == STAC9220_NID_MASTER &&
+ m->target == MI_TARGET_OUTAMP && mc->type == AUDIO_MIXER_ENUM) {
+ if (mc->un.ord != 0 && mc->un.ord != 1)
+ return EINVAL;
+ this->extra[STAC9220_EXTRA_MASTER] = mc->un.ord;
+ err = this->comresp(this, STAC9220_NID_HP,
+ CORB_GET_PIN_SENSE, 0, &value);
+ if (err)
+ return err;
+ if (!(value & CORB_PS_PRESENSE)) {
+ return generic_mixer_set(this, m->nid, m->target, mc);
+ }
+ return 0;
+ }
+ return generic_mixer_set(this, m->nid, m->target, mc);
+}
+
+static int
+stac9220_get_port(codec_t *this, mixer_ctrl_t *mc)
+{
+ const mixer_item_t *m;
+
+ if (mc->dev >= this->nmixers)
+ return ENXIO;
+ m = &this->mixers[mc->dev];
+ mc->type = m->devinfo.type;
+ if (mc->type == AUDIO_MIXER_CLASS)
+ return 0;
+ if (this->subid == STAC9220_XXX_ID && m->nid == STAC9220_NID_MASTER &&
+ m->target == MI_TARGET_OUTAMP && mc->type == AUDIO_MIXER_ENUM) {
+ mc->un.ord = this->extra[STAC9220_EXTRA_MASTER];
+ return 0;
+ }
+ return generic_mixer_get(this, m->nid, m->target, mc);
+}
+
+static int
+stac9220_unsol_event(codec_t *this, int tag)
+{
+ int err;
+ uint32_t value;
+ mixer_ctrl_t mc;
+
+ switch (tag) {
+ case STAC9220_EVENT_HP:
+ err = this->comresp(this, STAC9220_NID_HP,
+ CORB_GET_PIN_SENSE, 0, &value);
+ if (err)
+ break;
+ mc.dev = -1;
+ mc.type = AUDIO_MIXER_ENUM;
+ if (value & CORB_PS_PRESENSE) {
+ DPRINTF(("%s: headphone has been inserted.\n", __func__));
+ mc.un.ord = 1; /* mute */
+ generic_mixer_set(this, STAC9220_NID_MASTER,
+ MI_TARGET_OUTAMP, &mc);
+ } else {
+ DPRINTF(("%s: headphone has been pulled out.\n", __func__));
+ mc.un.ord = this->extra[ALC260_EXTRA_MASTER];
+ generic_mixer_set(this, STAC9220_NID_MASTER,
+ MI_TARGET_OUTAMP, &mc);
+ }
+ break;
+ default:
+ printf("%s: unknown tag: %d\n", __func__, tag);
+ }
return 0;
}
----------------------------------------------------------------
--
TAMURA Kent <kent_2007 at hauN.org> <kent at NetBSD.org>