- add initialization for ATI HDMI audio

- add custom mixer table for AD1986A by scw@
PR: kern/36140
This commit is contained in:
kent 2008-01-03 17:39:03 +00:00
parent 75fc209bcf
commit c89324c85e
1 changed files with 265 additions and 2 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: azalia_codec.c,v 1.50 2007/12/09 20:28:06 jmcneill Exp $ */
/* $NetBSD: azalia_codec.c,v 1.51 2008/01/03 17:39:03 kent Exp $ */
/*-
* Copyright (c) 2005 The NetBSD Foundation, Inc.
@ -37,7 +37,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: azalia_codec.c,v 1.50 2007/12/09 20:28:06 jmcneill Exp $");
__KERNEL_RCSID(0, "$NetBSD: azalia_codec.c,v 1.51 2008/01/03 17:39:03 kent Exp $");
#include <sys/param.h>
#include <sys/device.h>
@ -130,6 +130,8 @@ static int ad1983_mixer_init(codec_t *);
static int ad1983_unsol_event(codec_t *, int);
static int ad1984_init_widget(const codec_t *, widget_t *, nid_t);
static int ad1984_mixer_init(codec_t *);
static int ad1986a_init_dacgroup(codec_t *);
static int ad1986a_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 *);
@ -138,6 +140,7 @@ static int stac9221_mixer_init(codec_t *);
static int stac9221_gpio_unmute(codec_t *, int);
static int stac9200_mixer_init(codec_t *);
static int stac9200_unsol_event(codec_t *, int);
static int atihdmi_init_dacgroup(codec_t *);
int
@ -158,6 +161,19 @@ azalia_codec_init_vtbl(codec_t *this)
this->get_port = generic_get_port;
this->unsol_event = NULL;
switch (this->vid) {
case 0x10027919:
case 0x1002793c:
this->name = "ATI RS600 HDMI";
this->init_dacgroup = atihdmi_init_dacgroup;
break;
case 0x1002791a:
this->name = "ATI RS690/780 HDMI";
this->init_dacgroup = atihdmi_init_dacgroup;
break;
case 0x1002aa01:
this->name = "ATI R600 HDMI";
this->init_dacgroup = atihdmi_init_dacgroup;
break;
case 0x10ec0260:
this->name = "Realtek ALC260";
this->mixer_init = alc260_mixer_init;
@ -227,6 +243,12 @@ azalia_codec_init_vtbl(codec_t *this)
this->init_widget = ad1984_init_widget;
this->mixer_init = ad1984_mixer_init;
break;
case 0x11d41986:
/* http://www.analog.com/en/prod/0,2877,AD1986A,00.html */
this->name = "Analog Devices AD1986A";
this->init_dacgroup = ad1986a_init_dacgroup;
this->mixer_init = ad1986a_mixer_init;
break;
case 0x11d41988:
/* http://www.analog.com/en/prod/0,2877,AD1988A,00.html */
this->name = "Analog Devices AD1988A";
@ -3118,6 +3140,229 @@ ad1984_init_widget(const codec_t *this, widget_t *w, nid_t nid)
return 0;
}
/* ----------------------------------------------------------------
* Analog Devices AD1986A
* ---------------------------------------------------------------- */
static const mixer_item_t ad1986a_mixer_items[] = {
AZ_MIXER_CLASSES,
{{0, {AzaliaNdigital "." AudioNsource, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
0, 0, .un.e={2, {{{"hdaudio", 0}, 0}, {{"recordout", 0}, 1}}}}, 0x02, MI_TARGET_CONNLIST},
#if 0
/* fix to mixerout (default) */
{{0, {AudioNheadphone ".src", 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
0, 0, .un.e={3, {{{AudioNmixerout, 0}, 0}, {{"surrounddac", 0}, 1},
{{"clfedac", 0}, 2}}}}, 0x0a, MI_TARGET_CONNLIST},
#endif
{{0, {AudioNheadphone "." AudioNmute, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
0, 0, ENUM_OFFON}, 0x1a, MI_TARGET_OUTAMP},
{{0, {AudioNheadphone "." "boost", 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
0, 0, ENUM_OFFON}, 0x1a, MI_TARGET_PINBOOST},
{{0, {AudioNheadphone, 0}, AUDIO_MIXER_VALUE, AZ_CLASS_OUTPUT,
0, 0, .un.v={{"", 0}, 2, MIXER_DELTA(31)}}, 0x1a, MI_TARGET_OUTAMP},
#if 0
/* fix to mixerout (default) */
{{0, {AudioNline "." AudioNsource, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
0, 0, .un.e={2, {{{AudioNmixerout, 0}, 0}, {{"surrounddac", 0}, 1}}}},
0x0b, MI_TARGET_CONNLIST},
#endif
{{0, {AudioNline "." AudioNmute, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
0, 0, ENUM_OFFON}, 0x1b, MI_TARGET_OUTAMP},
{{0, {AudioNline "." "boost", 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
0, 0, ENUM_OFFON}, 0x1b, MI_TARGET_PINBOOST},
{{0, {AudioNline "." "eapd", 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
0, 0, ENUM_OFFON}, 0x1b, MI_TARGET_EAPD},
{{0, {AudioNline, 0}, AUDIO_MIXER_VALUE, AZ_CLASS_OUTPUT,
0, 0, .un.v={{"", 0}, 2, MIXER_DELTA(31)}}, 0x1b, MI_TARGET_OUTAMP},
#if 0
/* fix to the surround DAC (default) */
{{0, {AudioNsurround "." AudioNsource, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
0, 0, .un.e={2, {{{"surrounddac", 0}, 0}, {{AudioNmixerout, 0}, 1}}}},
0x0c, MI_TARGET_CONNLIST},
/* unmute */
{{0, {AudioNsurround "." AudioNmute, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
0, 0, ENUM_OFFON}, 0x1c, MI_TARGET_OUTAMP},
/* fix to output */
{{0, {AudioNsurround "." "dir", 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
0, 0, ENUM_IO}, 0x1c, MI_TARGET_PINDIR},
/* fix to maximum */
{{0, {AudioNsurround, 0}, AUDIO_MIXER_VALUE, AZ_CLASS_OUTPUT,
0, 0, .un.v={{"", 0}, 2, MIXER_DELTA(31)}}, 0x1c, MI_TARGET_OUTAMP},
#endif
{{0, {AudioNsurround "." AudioNmute, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
0, 0, ENUM_OFFON}, 0x04, MI_TARGET_OUTAMP},
{{0, {AudioNsurround, 0}, AUDIO_MIXER_VALUE, AZ_CLASS_OUTPUT,
0, 0, .un.v={{"", 0}, 2, MIXER_DELTA(31)}}, 0x04, MI_TARGET_OUTAMP},
#if 0
/* fix to the clfe DAC (default) */
{{0, {AzaliaNclfe "." AudioNsource, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
0, 0, .un.e={2, {{{"clfedac", 0}, 0}, {{"mixeroutmono", 0}, 1}}}},
0x0d, MI_TARGET_CONNLIST},
/* unmute */
{{0, {AzaliaNclfe "." AudioNmute, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
0, 0, ENUM_OFFON}, 0x1d, MI_TARGET_OUTAMP},
/* fix to output */
{{0, {AzaliaNclfe "." "dir", 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
0, 0, ENUM_IO}, 0x1d, MI_TARGET_PINDIR},
/* fix to maximum */
{{0, {AzaliaNclfe, 0}, AUDIO_MIXER_VALUE, AZ_CLASS_OUTPUT,
0, 0, .un.v={{"", 0}, 2, MIXER_DELTA(31)}}, 0x1d, MI_TARGET_OUTAMP},
#endif
{{0, {AzaliaNclfe "." AudioNmute, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
0, 0, ENUM_OFFON}, 0x05, MI_TARGET_OUTAMP},
{{0, {AzaliaNclfe, 0}, AUDIO_MIXER_VALUE, AZ_CLASS_OUTPUT,
0, 0, .un.v={{"", 0}, 2, MIXER_DELTA(31)}}, 0x05, MI_TARGET_OUTAMP},
{{0, {AzaliaNclfe "." "lrswap", 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
0, 0, ENUM_OFFON}, 0x1d, MI_TARGET_LRSWAP},
{{0, {AudioNmono "." AudioNsource, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
0, 0, .un.e={2, {{{AudioNmixerout, 0}, 0}, {{AudioNmicrophone, 0}, 1}}}},
0x0e, MI_TARGET_CONNLIST},
{{0, {AudioNmono "." AudioNmute, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
0, 0, ENUM_OFFON}, 0x1e, MI_TARGET_OUTAMP},
{{0, {AudioNmono, 0}, AUDIO_MIXER_VALUE, AZ_CLASS_OUTPUT,
0, 0, .un.v={{"", 0}, 2, MIXER_DELTA(31)}}, 0x1e, MI_TARGET_OUTAMP},
/* Front DAC */
{{0, {AudioNdac "." AudioNmute, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_INPUT,
0, 0, ENUM_OFFON}, 0x03, MI_TARGET_OUTAMP},
{{0, {AudioNdac, 0}, AUDIO_MIXER_VALUE, AZ_CLASS_INPUT,
0, 0, .un.v={{"", 0}, 2, MIXER_DELTA(31)}}, 0x03, MI_TARGET_OUTAMP},
#if 0
/* 0x09: 5.1 -> Stereo Downmix */
{{0, {"downmix" "." AudioNmute, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_INPUT,
0, 0, ENUM_OFFON}, 0x09, MI_TARGET_OUTAMP},
#endif
#if 0
/* mic source is mic jack (default) */
{{0, {AudioNmicrophone "." AudioNsource, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_INPUT,
0, 0, .un.e={8, {{{AudioNmicrophone, 0}, 0}, {{AudioNline, 0}, 1},
{{AzaliaNclfe, 0}, 2}, {{AzaliaNclfe "2", 0}, 3},
{{"micclfe", 0}, 4}, {{"micline", 0}, 5},
{{"clfeline", 0}, 6}, {{"miclineclfe", 0}, 7}}}},
0x0f, MI_TARGET_CONNLIST},
#endif
{{0, {AudioNmicrophone "." "gain", 0}, AUDIO_MIXER_VALUE, AZ_CLASS_RECORD,
0, 0, .un.v={{"", 0}, 2, MIXER_DELTA(3)}}, 0x0f, MI_TARGET_OUTAMP},
{{0, {AudioNmicrophone "." AudioNmute, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_RECORD,
0, 0, ENUM_OFFON}, 0x13, MI_TARGET_OUTAMP},
{{0, {AudioNmicrophone, 0}, AUDIO_MIXER_VALUE, AZ_CLASS_RECORD,
0, 0, .un.v={{"", 0}, 2, MIXER_DELTA(31)}}, 0x13, MI_TARGET_OUTAMP},
#if 0
/* line source is line jack (default) */
{{0, {AudioNline "." AudioNsource, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_INPUT,
0, 0, .un.e={3, {{{AudioNline, 0}, 0}, {{AudioNsurround, 0}, 1},
{{AudioNmicrophone, 0}, 2}}}}, 0x10, MI_TARGET_CONNLIST},
#endif
{{0, {AudioNline "." AudioNmute, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_INPUT,
0, 0, ENUM_OFFON}, 0x17, MI_TARGET_OUTAMP},
{{0, {AudioNline, 0}, AUDIO_MIXER_VALUE, AZ_CLASS_INPUT,
0, 0, .un.v={{"", 0}, 2, MIXER_DELTA(31)}}, 0x17, MI_TARGET_OUTAMP},
{{0, {"phone" "." AudioNmute, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_INPUT,
0, 0, ENUM_OFFON}, 0x14, MI_TARGET_OUTAMP},
{{0, {"phone", 0}, AUDIO_MIXER_VALUE, AZ_CLASS_INPUT,
0, 0, .un.v={{"", 0}, 2, MIXER_DELTA(31)}}, 0x14, MI_TARGET_OUTAMP},
{{0, {AudioNcd "." AudioNmute, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_INPUT,
0, 0, ENUM_OFFON}, 0x15, MI_TARGET_OUTAMP},
{{0, {AudioNcd, 0}, AUDIO_MIXER_VALUE, AZ_CLASS_INPUT,
0, 0, .un.v={{"", 0}, 2, MIXER_DELTA(31)}}, 0x15, MI_TARGET_OUTAMP},
{{0, {AudioNaux "." AudioNmute, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_INPUT,
0, 0, ENUM_OFFON}, 0x16, MI_TARGET_OUTAMP},
{{0, {AudioNaux, 0}, AUDIO_MIXER_VALUE, AZ_CLASS_INPUT,
0, 0, .un.v={{"", 0}, 2, MIXER_DELTA(31)}}, 0x16, MI_TARGET_OUTAMP},
{{0, {AudioNspeaker "." AudioNmute, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_INPUT,
0, 0, ENUM_OFFON}, 0x18, MI_TARGET_OUTAMP},
{{0, {AudioNspeaker, 0}, AUDIO_MIXER_VALUE, AZ_CLASS_INPUT,
0, 0, .un.v={{"", 0}, 2, MIXER_DELTA(15)}}, 0x18, MI_TARGET_OUTAMP},
/* 0x11: inputs.sel11.source=sel0f [ sel0f mix2b ] XXXX
inputs.sel11.lrswap=off [ off on ] XXXX */
{{0, {AudioNsource, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_RECORD,
0, 0, .un.e={7, {{{AudioNmicrophone, 0}, 0}, {{AudioNcd, 0}, 1},
{{AudioNaux, 0}, 2}, {{AudioNline, 0}, 3},
{{AudioNmixerout, 0}, 4}, {{"mixeroutmono", 0}, 5},
{{"phone", 0}, 6}}}},
0x12, MI_TARGET_CONNLIST},
{{0, {AudioNvolume "." AudioNmute, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_RECORD,
0, 0, ENUM_OFFON}, 0x12, MI_TARGET_OUTAMP},
{{0, {AudioNvolume, 0}, AUDIO_MIXER_VALUE, AZ_CLASS_RECORD,
0, 0, .un.v={{"", 0}, 2, MIXER_DELTA(15)}}, 0x12, 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
ad1986a_mixer_init(codec_t *this)
{
mixer_ctrl_t mc;
this->nmixers = sizeof(ad1986a_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, ad1986a_mixer_items,
sizeof(mixer_item_t) * this->nmixers);
generic_mixer_fix_indexes(this);
generic_mixer_default(this);
mc.dev = -1;
mc.type = AUDIO_MIXER_ENUM;
mc.un.ord = 0; /* unmute */
generic_mixer_set(this, 0x1c, MI_TARGET_OUTAMP, &mc);
mc.un.ord = 1; /* dir: output */
generic_mixer_set(this, 0x1c, MI_TARGET_PINDIR, &mc);
mc.type = AUDIO_MIXER_VALUE;
mc.un.value.num_channels = 2;
mc.un.value.level[0] = AUDIO_MAX_GAIN;
mc.un.value.level[1] = AUDIO_MAX_GAIN;
generic_mixer_set(this, 0x1c, MI_TARGET_VOLUME, &mc);
mc.type = AUDIO_MIXER_ENUM;
mc.un.ord = 0; /* unmute */
generic_mixer_set(this, 0x1d, MI_TARGET_OUTAMP, &mc);
mc.un.ord = 1; /* dir: output */
generic_mixer_set(this, 0x1d, MI_TARGET_PINDIR, &mc);
mc.type = AUDIO_MIXER_VALUE;
mc.un.value.num_channels = 2;
mc.un.value.level[0] = AUDIO_MAX_GAIN;
mc.un.value.level[1] = AUDIO_MAX_GAIN;
generic_mixer_set(this, 0x1d, MI_TARGET_VOLUME, &mc);
return 0;
}
static int
ad1986a_init_dacgroup(codec_t *this)
{
static const convgroupset_t dacs = {
-1, 2,
{{6, {0x03, 0x04, 0x05}}, /* analog 6ch */
{1, {0x02}}}}; /* digital */
static const convgroupset_t adcs = {
-1, 1,
{{1, {0x06}}}}; /* analog 2ch */
this->dacs = dacs;
this->adcs = adcs;
return 0;
}
/* ----------------------------------------------------------------
* Analog Devices AD1988A/AD1988B
* ---------------------------------------------------------------- */
@ -3436,3 +3681,21 @@ stac9200_unsol_event(codec_t *this, int tag)
}
return 0;
}
/* ----------------------------------------------------------------
* ATI HDMI
* ---------------------------------------------------------------- */
static int
atihdmi_init_dacgroup(codec_t *this)
{
static const convgroupset_t dacs = {
-1, 1,
{{1, {0x02}}}}; /* digital */
static const convgroupset_t adcs = {-1, 0, {}}; /* no recording */
this->dacs = dacs;
this->adcs = adcs;
return 0;
}