Subject: Re: kern/34071: azalia device driver doesn't support pin sensing
To: None <gnats-bugs@netbsd.org>
From: Berndt Josef Wulf <wulf@ping.net.au>
List: netbsd-bugs
Date: 02/07/2007 12:57:45
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