summaryrefslogtreecommitdiff
path: root/sys/dev/pci
diff options
context:
space:
mode:
authorDeanna Phillips <deanna@cvs.openbsd.org>2007-09-20 17:41:33 +0000
committerDeanna Phillips <deanna@cvs.openbsd.org>2007-09-20 17:41:33 +0000
commite4d960673450cc3ddbb8baee5620ed787fcc79bd (patch)
tree9a0468cda1c4cfa406e2bb625dde9b9b35f47ffb /sys/dev/pci
parent4818bcdb512a35e2610aaeefc5b16df2041945cd (diff)
Add mixer items, master volume and dacgroup init for Analog Devices
AD1984. Recording isn't supported yet. Lots of testing by reyk@, Pau Amaro-Seoane and Alexey Vatchenko; thanks!
Diffstat (limited to 'sys/dev/pci')
-rw-r--r--sys/dev/pci/azalia_codec.c151
1 files changed, 150 insertions, 1 deletions
diff --git a/sys/dev/pci/azalia_codec.c b/sys/dev/pci/azalia_codec.c
index 0667ec6a325..4c6a6ca094a 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.35 2007/09/11 05:17:47 deanna Exp $ */
+/* $OpenBSD: azalia_codec.c,v 1.36 2007/09/20 17:41:32 deanna Exp $ */
/* $NetBSD: azalia_codec.c,v 1.8 2006/05/10 11:17:27 kent Exp $ */
/*-
@@ -100,6 +100,10 @@ int azalia_alc883_init_dacgroup(codec_t *);
int azalia_alc883_mixer_init(codec_t *);
int azalia_ad1981hd_init_widget(const codec_t *, widget_t *, nid_t);
int azalia_ad1981hd_mixer_init(codec_t *);
+int azalia_ad1984_init_dacgroup(codec_t *);
+int azalia_ad1984_mixer_init(codec_t *);
+int azalia_ad1984_set_port(codec_t *, mixer_ctrl_t *);
+int azalia_ad1984_get_port(codec_t *, mixer_ctrl_t *);
int azalia_cmi9880_init_dacgroup(codec_t *);
int azalia_cmi9880_mixer_init(codec_t *);
int azalia_stac9221_init_dacgroup(codec_t *);
@@ -165,6 +169,14 @@ azalia_codec_init_vtbl(codec_t *this)
/* http://www.analog.com/en/prod/0,2877,AD1983,00.html */
this->name = "Analog Devices AD1983";
break;
+ case 0x11d41984:
+ /* http://www.analog.com/en/prod/0,2877,AD1984,00.html */
+ this->name = "Analog Devices AD1984";
+ this->init_dacgroup = azalia_ad1984_init_dacgroup;
+ this->mixer_init = azalia_ad1984_mixer_init;
+ this->get_port = azalia_ad1984_get_port;
+ this->set_port = azalia_ad1984_set_port;
+ break;
case 0x434d4980:
this->name = "CMedia CMI9880";
this->init_dacgroup = azalia_cmi9880_init_dacgroup;
@@ -2232,6 +2244,143 @@ azalia_ad1981hd_mixer_init(codec_t *this)
}
/* ----------------------------------------------------------------
+ * Analog Devices AD1984
+ * ---------------------------------------------------------------- */
+
+int
+azalia_ad1984_init_dacgroup(codec_t *this)
+{
+ static const convgroupset_t dacs = {
+ -1, 1,
+ {{2, {0x03, 0x04}}}};
+
+ static const convgroupset_t adcs = {
+ -1, 2,
+ {{1, {0x05}},
+ {1, {0x06}}}};
+
+ this->dacs = dacs;
+ this->adcs = adcs;
+ return 0;
+}
+
+static const mixer_item_t ad1984_mixer_items[] = {
+ {{AZ_CLASS_INPUT, {AudioCinputs}, AUDIO_MIXER_CLASS, AZ_CLASS_INPUT, 0, 0}, 0},
+ {{AZ_CLASS_OUTPUT, {AudioCoutputs}, AUDIO_MIXER_CLASS, AZ_CLASS_OUTPUT, 0, 0}, 0},
+ {{AZ_CLASS_RECORD, {AudioCrecord}, AUDIO_MIXER_CLASS, AZ_CLASS_RECORD, 0, 0}, 0},
+#define AD1984_DAC_HP 0x03
+#define AD1984_DAC_SPEAKER 0x04
+#define AD1984_TARGET_MASTER -1
+#define AD1984_TARGET_MASTER_MUTE -2
+ {{0, {AudioNmaster}, AUDIO_MIXER_VALUE, AZ_CLASS_OUTPUT,
+ 4, 0, .un.v={{""}, 2, MIXER_DELTA(39)}}, 0x03, AD1984_TARGET_MASTER},
+ {{0, {AudioNmute}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
+ 0, 3, ENUM_OFFON}, 0x11, AD1984_TARGET_MASTER_MUTE},
+ {{0, {AudioNheadphone}, AUDIO_MIXER_VALUE, AZ_CLASS_OUTPUT,
+ 0, 0, .un.v={{""}, 2, MIXER_DELTA(39)}}, 0x03, MI_TARGET_OUTAMP},
+ {{0, {AudioNheadphone"."AudioNmute}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
+ 0, 0, ENUM_OFFON}, 0x11, MI_TARGET_OUTAMP},
+ {{0, {AudioNheadphone".boost"}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
+ 0, 0, ENUM_OFFON}, 0x11, MI_TARGET_PINBOOST},
+ {{0, {AudioNspeaker}, AUDIO_MIXER_VALUE, AZ_CLASS_OUTPUT,
+ 0, 0, .un.v={{""}, 2, MIXER_DELTA(39)}}, 0x04, MI_TARGET_OUTAMP},
+ {{0, {AudioNspeaker"."AudioNmute}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
+ 0, 0, ENUM_OFFON}, 0x12, MI_TARGET_OUTAMP},
+ {{0, {AudioNspeaker".boost"}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
+ 0, 0, ENUM_OFFON}, 0x12, MI_TARGET_PINBOOST},
+ {{0, {AudioNmono}, AUDIO_MIXER_VALUE, AZ_CLASS_OUTPUT,
+ 0, 0, .un.v={{""}, 1, MIXER_DELTA(31)}}, 0x13, MI_TARGET_OUTAMP},
+ {{0, {AudioNmono"."AudioNmute}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
+ 0, 0, ENUM_OFFON}, 0x13, MI_TARGET_OUTAMP}
+};
+
+int
+azalia_ad1984_mixer_init(codec_t *this)
+{
+ mixer_ctrl_t mc;
+
+ this->nmixers = sizeof(ad1984_mixer_items) / sizeof(mixer_item_t);
+ this->mixers = malloc(sizeof(mixer_item_t) * this->nmixers,
+ M_DEVBUF, M_NOWAIT | M_ZERO);
+ if (this->mixers == NULL) {
+ printf("%s: out of memory in %s\n", XNAME(this), __func__);
+ return ENOMEM;
+ }
+ memcpy(this->mixers, ad1984_mixer_items,
+ sizeof(mixer_item_t) * this->nmixers);
+ azalia_generic_mixer_fix_indexes(this);
+ azalia_generic_mixer_default(this);
+ mc.dev = -1;
+ mc.type = AUDIO_MIXER_ENUM;
+ mc.un.ord = 0; /* pindir: input */
+ azalia_generic_mixer_set(this, 0x1c, MI_TARGET_PINDIR, &mc); /* mic */
+ mc.un.ord = 1; /* enable */
+ azalia_generic_mixer_set(this, 0x12, MI_TARGET_EAPD, &mc);
+ azalia_generic_mixer_set(this, 0x13, MI_TARGET_EAPD, &mc);
+
+ mc.un.ord = 0; /* unmute */
+ azalia_generic_mixer_set(this, 0x07, MI_TARGET_INAMP(0), &mc);
+ azalia_generic_mixer_set(this, 0x07, MI_TARGET_INAMP(1), &mc);
+ azalia_generic_mixer_set(this, 0x0a, MI_TARGET_INAMP(0), &mc);
+ azalia_generic_mixer_set(this, 0x0a, MI_TARGET_INAMP(1), &mc);
+ azalia_generic_mixer_set(this, 0x0b, MI_TARGET_INAMP(0), &mc);
+ azalia_generic_mixer_set(this, 0x0b, MI_TARGET_INAMP(1), &mc);
+ azalia_generic_mixer_set(this, 0x1e, MI_TARGET_INAMP(0), &mc);
+ azalia_generic_mixer_set(this, 0x1e, MI_TARGET_INAMP(1), &mc);
+ azalia_generic_mixer_set(this, 0x24, MI_TARGET_INAMP(0), &mc);
+ azalia_generic_mixer_set(this, 0x24, MI_TARGET_INAMP(1), &mc);
+
+ return 0;
+}
+
+int
+azalia_ad1984_set_port(codec_t *this, mixer_ctrl_t *mc)
+{
+ const mixer_item_t *m;
+ 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 (m->target == AD1984_TARGET_MASTER) {
+ err = azalia_generic_mixer_set(this, AD1984_DAC_HP,
+ MI_TARGET_OUTAMP, mc);
+ err = azalia_generic_mixer_set(this, AD1984_DAC_SPEAKER,
+ MI_TARGET_OUTAMP, mc);
+ return err;
+ }
+ if (m->target == AD1984_TARGET_MASTER_MUTE) {
+ err = azalia_generic_mixer_set(this, 0x11, MI_TARGET_OUTAMP, mc);
+ err = azalia_generic_mixer_set(this, 0x12, MI_TARGET_OUTAMP, mc);
+ err = azalia_generic_mixer_set(this, 0x13, MI_TARGET_OUTAMP, mc);
+ return err;
+ }
+ return azalia_generic_mixer_set(this, m->nid, m->target, mc);
+}
+
+int
+azalia_ad1984_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 (m->target == AD1984_TARGET_MASTER ||
+ m->target == AD1984_TARGET_MASTER_MUTE)
+ return azalia_generic_mixer_get(this, m->nid,
+ MI_TARGET_OUTAMP, mc);
+ return azalia_generic_mixer_get(this, m->nid, m->target, mc);
+}
+
+/* ----------------------------------------------------------------
* CMedia CMI9880
* ---------------------------------------------------------------- */