Subject: ad1983 azalia
To: None <tech-kern@netbsd.org>
From: Mark Davies <mark@mcs.vuw.ac.nz>
List: tech-kern
Date: 08/15/2007 19:46:52
--Boundary-00=_s9qwGAl1oG5BrPg
Content-Type: text/plain;
  charset="us-ascii"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline

Having now got the Dell Optiplex 745 running with azalia defined (but 
without ehci) I'd like to have it work so I've made a first stab at 
azalia_codec.c support for the AD1983.  Its based on the existing 
AD1981HD support and the differences as inferred from 
http://www.analog.com/en/prod/0,2877,AD{1981HD,1983},00.html.

It works in that I can get audio out from various KDE apps and can 
adjust the line-out, headphones and master volumes but not sure about 
the input side of things and inamp or the names/class for some of the 
items and there is no headphone jack detection (and probably other 
things I haven't thought about).

Attached is the dmesg output with AZALIA_DEBUG defined, mixerctl -av 
output and my current azalia_codec.c diff.

cheers
mark

--Boundary-00=_s9qwGAl1oG5BrPg
Content-Type: text/plain;
  charset="us-ascii";
  name="dmesg-azalia.out"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
	filename="dmesg-azalia.out"

azalia0 at pci0 dev 27 function 0: Generic High Definition Audio Controller
azalia0: interrupting at ioapic0 pin 16 (irq 11)
azalia0: host: Intel 82801H High Definition Audio Controller (rev. 2)
azalia0: host: High Definition Audio rev. 1.0
azalia0: host: 4 output, 4 input, and 0 bidi streams
azalia_attach: resetting
azalia_attach: reset counter = 5000
azalia_attach: reset counter = 4984
azalia0: found a codec at #0
azalia_init_corb: CORB allocation succeeded.
azalia_init_corb: CORBWP=0; size=256
azalia_init_rirb: RIRB allocation succeeded.
azalia_init_rirb: RIRBRP=0, size=256
azalia0: information of codec[0] follows:
azalia_codec_init_vtbl: vid=11d41983 subid=01da1028
azalia0: codec[0]: Analog Devices AD1983 (rev. 4.0)
azalia0: codec[0]: High Definition Audio rev. 1.0
azalia_codec_init: nidstart=1 #functions=1
azalia_codec_init: FTYPE result = 0x00000001
azalia_codec_init: There are 20 widgets in the audio function.
azalia0:    encodings=1<PCM>
azalia0:    PCM formats=e007f<24bit,20bit,16bit,48kHz,44.1kHz,32kHz,22.05kHz,16kHz,11.025kHz,8kHz>
azalia0:    inamp: mute=0 size=0 steps=0 offset=0
azalia0:    outamp: mute=1 size=5 steps=63 offset=61
azalia0: dac02 wcap=30311<DIGITAL,CONNLIST,FORMATOV,STEREO>
azalia0:    encodings=5<AC3,PCM>
azalia0:    PCM formats=20060<16bit,48kHz,44.1kHz>
azalia0:    connections=0x1,0x4; selected=0x1
azalia0: dac03 wcap=441<POWER,PROC,STEREO>
azalia0:    encodings=1<PCM>
azalia0:    PCM formats=e007f<24bit,20bit,16bit,48kHz,44.1kHz,32kHz,22.05kHz,16kHz,11.025kHz,8kHz>
azalia0: adc04 wcap=100501<POWER,CONNLIST,STEREO>
azalia0:    encodings=1<PCM>
azalia0:    PCM formats=e007f<24bit,20bit,16bit,48kHz,44.1kHz,32kHz,22.05kHz,16kHz,11.025kHz,8kHz>
azalia0:    connections=0x14; selected=0x14
azalia0: green05 wcap=400185<CONNLIST,UNSOL,OUTAMP,STEREO>
azalia0:    pin config; device=line-out color=green assoc=1 seq=0 cap=17<OUTPUT,PRESENCE,TRIGGER,IMPEDANCE>
azalia0:    connections=0x3,0xe; selected=0x3
azalia0:    outamp: mute=1 size=5 steps=63 offset=61
azalia0: black06 wcap=400185<CONNLIST,UNSOL,OUTAMP,STEREO>
azalia0:    pin config; device=headphones color=black assoc=1 seq=15 cap=1f<OUTPUT,HEADPHONE,PRESENCE,TRIGGER,IMPEDANCE>
azalia0:    connections=0x3,0xe; selected=0x3
azalia0:    outamp: mute=1 size=5 steps=63 offset=61
azalia0: unknown07 wcap=400104<CONNLIST,OUTAMP>
azalia0:    pin config; device=speaker color=unknown assoc=15 seq=0 cap=10<OUTPUT>
azalia0:    connections=0xf; selected=0xf
azalia0:    outamp: mute=1 size=5 steps=63 offset=61
azalia0: black08 wcap=400081<UNSOL,STEREO>
azalia0:    pin config; device=mic color=black assoc=2 seq=0 cap=1727<INPUT,PRESENCE,TRIGGER,IMPEDANCE>
azalia0: blue09 wcap=400081<UNSOL,STEREO>
azalia0:    pin config; device=line-in color=blue assoc=2 seq=14 cap=1727<INPUT,PRESENCE,TRIGGER,IMPEDANCE>
azalia0: black0a wcap=400301<DIGITAL,CONNLIST,STEREO>
azalia0:    pin config; device=SPDIF-out color=black assoc=15 seq=0 cap=10<OUTPUT>
azalia0:    connections=0x2; selected=0x2
azalia0: sel0b wcap=300101<CONNLIST,STEREO>
azalia0:    connections=0x3,0xc,0xd,0xe; selected=0x3
azalia0: sel0c wcap=30010d<CONNLIST,AMPOV,OUTAMP,STEREO>
azalia0:    connections=0x8,0x9; selected=0x8
azalia0:    outamp: mute=0 size=39 steps=3 offset=0
azalia0: sel0d wcap=300101<CONNLIST,STEREO>
azalia0:    connections=0x9,0x8; selected=0x9
azalia0: mix0e wcap=200101<CONNLIST,STEREO>
azalia0:    connections=0x11,0x12,0x13; selected=0x11
azalia0: mix0f wcap=200100<CONNLIST>
azalia0:    connections=0xb; selected=0xb
azalia0: beep10 wcap=70000c<AMPOV,OUTAMP>
azalia0:    outamp: mute=1 size=11 steps=15 offset=15
azalia0: sel11 wcap=30010d<CONNLIST,AMPOV,OUTAMP,STEREO>
azalia0:    connections=0x3; selected=0x3
azalia0:    outamp: mute=1 size=5 steps=31 offset=23
azalia0: sel12 wcap=30010d<CONNLIST,AMPOV,OUTAMP,STEREO>
azalia0:    connections=0xc; selected=0xc
azalia0:    outamp: mute=1 size=5 steps=31 offset=23
azalia0: sel13 wcap=30010d<CONNLIST,AMPOV,OUTAMP,STEREO>
azalia0:    connections=0xd; selected=0xd
azalia0:    outamp: mute=1 size=5 steps=31 offset=23
azalia0: sel14 wcap=30010d<CONNLIST,AMPOV,OUTAMP,STEREO>
azalia0:    connections=0xc,0xd,0xe,0xf; selected=0xc
azalia0:    outamp: mute=1 size=5 steps=15 offset=0
azalia0: pow15 wcap=500500<POWER,CONNLIST>
azalia0:    connections=0x5,0x89,0xb,0x94; selected=0x5
azalia_codec_init: dacgroup[0]: 03
azalia_codec_init: dacgroup[1]: 02
azalia0: playback: max channels=2, encodings=1<PCM>
azalia0: playback: PCM formats=e007f<24bit,20bit,16bit,48kHz,44.1kHz,32kHz,22.05kHz,16kHz,11.025kHz,8kHz>
azalia0: recording: max channels=2, encodings=1<PCM>
azalia0: recording: PCM formats=e007f<24bit,20bit,16bit,48kHz,44.1kHz,32kHz,22.05kHz,16kHz,11.025kHz,8kHz>
azalia0: using the #0 codec
audio0 at azalia0: full duplex, independent
azalia_round_blocksize: resultant block size = 1536
azalia_round_blocksize: resultant block size = 1536
azalia_open: flags=0x7
azalia_round_blocksize: resultant block size = 1536
azalia_round_blocksize: resultant block size = 1536
azalia_round_blocksize: resultant block size = 1536
azalia_round_blocksize: resultant block size = 1536
azalia_round_blocksize: resultant block size = 1536
azalia_round_blocksize: resultant block size = 1536
azalia_round_blocksize: resultant block size = 8704
azalia_round_blocksize: resultant block size = 8704
azalia_round_blocksize: resultant block size = 4096
azalia_round_blocksize: resultant block size = 4096
azalia_round_blocksize: resultant block size = 4096
azalia_round_blocksize: resultant block size = 4096
azalia_trigger_output: this=0xc3110000 start=0xcccd5000 end=0xccce5000 blk=4096 {enc=6 2ch 16/16bit 44100Hz}
azalia_codec_connect_stream: fmt=0x4011 number=1
azalia_codec_connect_stream: leave with 0
azalia_halt_output
azalia_close
azalia_open: flags=0x7
azalia_round_blocksize: resultant block size = 4096
azalia_round_blocksize: resultant block size = 4096
azalia_round_blocksize: resultant block size = 4096
azalia_round_blocksize: resultant block size = 4096
azalia_round_blocksize: resultant block size = 4096
azalia_round_blocksize: resultant block size = 4096
azalia_round_blocksize: resultant block size = 4096
azalia_round_blocksize: resultant block size = 4096
azalia_round_blocksize: resultant block size = 4096
azalia_round_blocksize: resultant block size = 4096
azalia_trigger_output: this=0xc3110000 start=0xcccd5000 end=0xccce5000 blk=4096 {enc=6 2ch 16/16bit 44100Hz}
azalia_codec_connect_stream: fmt=0x4011 number=1
azalia_codec_connect_stream: leave with 0
azalia_halt_output
azalia_close
azalia_open: flags=0x7
azalia_round_blocksize: resultant block size = 4096
azalia_round_blocksize: resultant block size = 4096
azalia_round_blocksize: resultant block size = 4096
azalia_round_blocksize: resultant block size = 4096
azalia_round_blocksize: resultant block size = 4096
azalia_round_blocksize: resultant block size = 4096
azalia_round_blocksize: resultant block size = 4096
azalia_round_blocksize: resultant block size = 4096
azalia_round_blocksize: resultant block size = 4096
azalia_round_blocksize: resultant block size = 4096
azalia_trigger_output: this=0xc3110000 start=0xcccd5000 end=0xccce5000 blk=4096 {enc=6 2ch 16/16bit 44100Hz}
azalia_codec_connect_stream: fmt=0x4011 number=1
azalia_codec_connect_stream: leave with 0

--Boundary-00=_s9qwGAl1oG5BrPg
Content-Type: text/plain;
  charset="us-ascii";
  name="mixerctl.out"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
	filename="mixerctl.out"

outputs.spdif.source=os  [ os adc ]
outputs.lineout.source=dac  [ dac mixerout ]
outputs.lineout.mute=off  [ off on ]
outputs.lineout=125,125  delta=17
outputs.lineout.dir=input  [ input output ]
outputs.lineout.boost=off  [ off on ]
outputs.headphones.src=dac  [ dac mixerout ]
outputs.headphones.mute=off  [ off on ]
outputs.headphones=255,255  delta=63
outputs.headphones.boost=on  [ off on ]
outputs.mono.mute=off  [ off on ]
outputs.mono=125  delta=63
outputs.mono.source=dac  [ dac mic linein mixerout ]
inputs.beep.mute=off  [ off on ]
inputs.beep=119  delta=15
inputs.dac.mute=off  [ off on ]
inputs.dac=255,255  delta=31
inputs.mic.mute=off  [ off on ]
inputs.mic=115,115  delta=31
inputs.linein.mute=off  [ off on ]
inputs.linein=123,123  delta=31
record.source=mic  [ mic linein mixerout mono ]
record.mute=off  [ off on ]
record.master=153,153  delta=15
playback.mode=analog  [ analog spdif ]

--Boundary-00=_s9qwGAl1oG5BrPg
Content-Type: text/x-diff;
  charset="us-ascii";
  name="azalia_codec.diff"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
	filename="azalia_codec.diff"

Index: azalia_codec.c
===================================================================
RCS file: /src/cvs/netbsd/src/sys/dev/pci/azalia_codec.c,v
retrieving revision 1.42
diff -u -r1.42 azalia_codec.c
--- azalia_codec.c	13 May 2007 03:28:19 -0000	1.42
+++ azalia_codec.c	14 Aug 2007 02:48:28 -0000
@@ -124,6 +124,7 @@
 static int	alc888_init_dacgroup(codec_t *);
 static int	ad1981hd_init_widget(const codec_t *, widget_t *, nid_t);
 static int	ad1981hd_mixer_init(codec_t *);
+static int	ad1983_mixer_init(codec_t *);
 static int	ad1988_init_dacgroup(codec_t *);
 static int	cmi9880_init_dacgroup(codec_t *);
 static int	cmi9880_mixer_init(codec_t *);
@@ -207,6 +208,7 @@
 	case 0x11d41983:
 		/* http://www.analog.com/en/prod/0,2877,AD1983,00.html */
 		this->name = "Analog Devices AD1983";
+		this->mixer_init = ad1983_mixer_init;
 		break;
 	case 0x11d41988:
 		/* http://www.analog.com/en/prod/0,2877,AD1988A,00.html */
@@ -2721,6 +2723,120 @@
 }
 
 /* ----------------------------------------------------------------
+ * Analog Devices AD1983
+ * ---------------------------------------------------------------- */
+
+static const mixer_item_t ad1983_mixer_items[] = {
+	AZ_MIXER_CLASSES,
+
+	{{0, {AzaliaNdigital "." AudioNsource, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
+	  0, 0, .un.e={2, {{{"os", 0}, 0}, {{"adc", 0}, 1}}}}, 0x02, MI_TARGET_CONNLIST},
+
+	{{0, {"lineout." AudioNsource, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
+	  0, 0, .un.e={2, {{{AudioNdac, 0}, 0}, {{AudioNmixerout, 0}, 1}}}},
+	 0x05, MI_TARGET_CONNLIST},
+	{{0, {"lineout." AudioNmute, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
+	  0, 0, ENUM_OFFON}, 0x05, MI_TARGET_OUTAMP},
+	{{0, {"lineout", 0}, AUDIO_MIXER_VALUE, AZ_CLASS_OUTPUT,
+	  0, 0, .un.v={{"", 0}, 2, MIXER_DELTA(15)}}, 0x05, MI_TARGET_OUTAMP},
+#if 0
+	{{0, {"lineout", 0}, AUDIO_MIXER_VALUE, AZ_CLASS_RECORD,
+	  0, 0, .un.v={{"", 0}, 2, MIXER_DELTA(3)}}, 0x05, MI_TARGET_INAMP(0)},
+#endif
+	{{0, {"lineout.dir", 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
+	  0, 0, ENUM_IO}, 0x05, MI_TARGET_PINDIR},
+	{{0, {"lineout.boost", 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
+	  0, 0, ENUM_OFFON}, 0x05, MI_TARGET_PINBOOST},
+
+
+	{{0, {AudioNheadphone ".src", 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
+	  0, 0, .un.e={2, {{{AudioNdac, 0}, 0}, {{AudioNmixerout, 0}, 1}}}},
+	 0x06, MI_TARGET_CONNLIST},
+	{{0, {AudioNheadphone "." AudioNmute, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
+	  0, 0, ENUM_OFFON}, 0x06, MI_TARGET_OUTAMP},
+	{{0, {AudioNheadphone, 0}, AUDIO_MIXER_VALUE, AZ_CLASS_OUTPUT,
+	  0, 0, .un.v={{"", 0}, 2, MIXER_DELTA(4)}}, 0x06, MI_TARGET_OUTAMP},
+	{{0, {AudioNheadphone ".boost", 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
+	  0, 0, ENUM_OFFON}, 0x06, MI_TARGET_PINBOOST},
+
+	{{0, {AudioNmono "." AudioNmute, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
+	  0, 0, ENUM_OFFON}, 0x07, MI_TARGET_OUTAMP},
+	{{0, {AudioNmono, 0}, AUDIO_MIXER_VALUE, AZ_CLASS_OUTPUT,
+	  0, 0, .un.v={{"", 0}, 1, MIXER_DELTA(4)}}, 0x07, MI_TARGET_OUTAMP},
+
+#if 0
+	{{0, {AudioNmicrophone, 0}, AUDIO_MIXER_VALUE, AZ_CLASS_RECORD,
+	  0, 0, .un.v={{"", 0}, 2, MIXER_DELTA(3)}}, 0x08, MI_TARGET_INAMP(0)},
+#endif
+
+#if 0
+	{{0, {"linein." AudioNmute, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
+	  0, 0, ENUM_OFFON}, 0x09, MI_TARGET_OUTAMP},
+	{{0, {"linein", 0}, AUDIO_MIXER_VALUE, AZ_CLASS_OUTPUT,
+	  0, 0, .un.v={{"", 0}, 2, MIXER_DELTA(63)}}, 0x09, MI_TARGET_OUTAMP},
+	{{0, {"linein", 0}, AUDIO_MIXER_VALUE, AZ_CLASS_RECORD,
+	  0, 0, .un.v={{"", 0}, 2, MIXER_DELTA(3)}}, 0x09, MI_TARGET_INAMP(0)},
+	{{0, {"linein.dir", 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
+	  0, 0, ENUM_IO}, 0x09, MI_TARGET_PINDIR},
+#endif
+
+	{{0, {AudioNmono "." AudioNsource, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
+	  0, 0, .un.e={4, {{{AudioNdac, 0}, 0}, {{AudioNmicrophone, 0}, 1},
+			   {{"linein", 0}, 2}, {{AudioNmixerout, 0}, 3}}}},
+	 0x0b, MI_TARGET_CONNLIST},
+
+	{{0, {"beep." AudioNmute, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_INPUT,
+	  0, 0, ENUM_OFFON}, 0x10, MI_TARGET_OUTAMP},
+	{{0, {"beep", 0}, AUDIO_MIXER_VALUE, AZ_CLASS_INPUT,
+	  0, 0, .un.v={{"", 0}, 1, MIXER_DELTA(17)}}, 0x10, MI_TARGET_OUTAMP},
+
+	{{0, {AudioNdac "." AudioNmute, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_INPUT,
+	  0, 0, ENUM_OFFON}, 0x11, MI_TARGET_OUTAMP},
+	{{0, {AudioNdac, 0}, AUDIO_MIXER_VALUE, AZ_CLASS_INPUT,
+	  0, 0, .un.v={{"", 0}, 2, MIXER_DELTA(8)}}, 0x11, MI_TARGET_OUTAMP},
+
+	{{0, {AudioNmicrophone "." AudioNmute, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_INPUT,
+	  0, 0, ENUM_OFFON}, 0x12, MI_TARGET_OUTAMP},
+	{{0, {AudioNmicrophone, 0}, AUDIO_MIXER_VALUE, AZ_CLASS_INPUT,
+	  0, 0, .un.v={{"", 0}, 2, MIXER_DELTA(8)}}, 0x12, MI_TARGET_OUTAMP},
+
+	{{0, {"linein." AudioNmute, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_INPUT,
+	  0, 0, ENUM_OFFON}, 0x13, MI_TARGET_OUTAMP},
+	{{0, {"linein", 0}, AUDIO_MIXER_VALUE, AZ_CLASS_INPUT,
+	  0, 0, .un.v={{"", 0}, 2, MIXER_DELTA(8)}}, 0x13, MI_TARGET_OUTAMP},
+
+	{{0, {AudioNsource, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_RECORD,
+	  0, 0, .un.e={4, {{{AudioNmicrophone, 0}, 0}, {{"linein", 0}, 1},
+			   {{AudioNmixerout, 0}, 2}, {{AudioNmono, 0}, 3}}}},
+	 0x14, MI_TARGET_CONNLIST},
+	{{0, {AudioNmute, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_RECORD,
+	  0, 0, ENUM_OFFON}, 0x14, MI_TARGET_OUTAMP},
+	{{0, {AudioNmaster, 0}, AUDIO_MIXER_VALUE, AZ_CLASS_RECORD,
+	  0, 0, .un.v={{"", 0}, 2, MIXER_DELTA(17)}}, 0x14, MI_TARGET_OUTAMP},
+
+	{{0, {AudioNmode, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_PLAYBACK, 0, 0,
+	  .un.e={2, {{{"analog", 0}, 0}, {{AzaliaNdigital, 0}, 1}}}}, 0, MI_TARGET_DAC},
+};
+
+static int
+ad1983_mixer_init(codec_t *this)
+{
+	this->nmixers = sizeof(ad1983_mixer_items) / sizeof(mixer_item_t);
+	this->mixers = malloc(sizeof(mixer_item_t) * this->nmixers,
+	    M_DEVBUF, M_ZERO | M_NOWAIT);
+	if (this->mixers == NULL) {
+		aprint_error("%s: out of memory in %s\n", XNAME(this), __func__);
+		return ENOMEM;
+	}
+	memcpy(this->mixers, ad1983_mixer_items,
+	    sizeof(mixer_item_t) * this->nmixers);
+	generic_mixer_fix_indexes(this);
+	generic_mixer_default(this);
+
+	return 0;
+}
+
+/* ----------------------------------------------------------------
  * Analog Devices AD1988A/AD1988B
  * ---------------------------------------------------------------- */
 

--Boundary-00=_s9qwGAl1oG5BrPg--