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: Berndt Josef Wulf <wulf@ping.net.au>
List: netbsd-bugs
Date: 02/07/2007 01:30:02
The following reply was made to PR kern/34071; it has been noted by GNATS.

From: Berndt Josef Wulf <wulf@ping.net.au>
To: gnats-bugs@netbsd.org
Cc: kent@netbsd.org, gnats-admin@netbsd.org, netbsd-bugs@netbsd.org,
	wulf@netbsd.org
Subject: Re: kern/34071: azalia device driver doesn't support pin sensing
Date: Wed, 7 Feb 2007 12:57:45 +1030

 On Tuesday 06 February 2007 01:10, TAMURA Kent wrote:
 > 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>
  G'day,
 
 Thanks for this patch. I've applied it and installed new kernel. 
 Unfortunately, it appears that no event is registered when plugging in the 
 headphone set into line socket.
 
 System information:
 
 Hardware - Dell Inspiron 9400
 
 Kernel -
 NetBSD barossa 4.99.9 NetBSD 4.99.9 (BAROSSA) #2: Tue Feb  6 08:19:47 CST 2007  
 wulf@barossa:/sys/arch/i386/compile/BAROSSA i386
 
 The azalia device is detected as:
 
 azalia0 at pci0 dev 27 function 0: Generic High Definition Audio Controller
 azalia0: interrupting at ioapic0 pin 21 (irq 11)
 azalia0: host: Intel 82801GB/GR High Definition Audio Controller (rev. 1)
 azalia0: host: High Definition Audio rev. 1.0
 [...]
 azalia0: codec[0]: Sigmatel STAC9220 (rev. 34.1)
 azalia0: codec[0]: High Definition Audio rev. 1.0
 azalia0: playback: max channels=2, encodings=1<PCM>
 azalia0: playback: PCM 
 formats=e07e0<24bit,20bit,16bit,192kHz,176.4kHz,96kHz,88.
 2kHz,48kHz,44.1kHz>
 azalia0: recording: max channels=2, encodings=1<PCM>
 azalia0: recording: PCM 
 formats=e07e0<24bit,20bit,16bit,192kHz,176.4kHz,96kHz,88
 .2kHz,48kHz,44.1kHz>
 azalia0: codec[1]: 0x14f1/0x2bfa (rev. 0.0)
 azalia0: codec[1]: High Definition Audio rev. 0.9
 azalia0: codec[1]: No support for modem function groups
 azalia0: codec[1] has no audio function groups
 audio0 at azalia0: full duplex, independent
 
 cheerio Berndt