29#ifdef HAVE_KERNEL_OPTION_HEADERS
57#define AC97_MIXER_SIZE SOUND_MIXER_NRDEVICES
89 [SOUND_MIXER_PHONEOUT] = {
AC97_MIX_MONO, 5, 0, 0, 1, 7, 0, 0 },
91 [SOUND_MIXER_TREBLE] = {
AC97_MIX_TONE, 4, 0, 0, 0, 0, 1, 0 },
92 [SOUND_MIXER_PCM] = {
AC97_MIX_PCM, 5, 0, 1, 1, 0, 0, 1 },
93 [SOUND_MIXER_SPEAKER] = {
AC97_MIX_BEEP, 4, 1, 0, 1, 0, 0, 0 },
96 [SOUND_MIXER_MIC] = {
AC97_MIX_MIC, 5, 0, 0, 1, 1, 1, 1 },
98 [SOUND_MIXER_IGAIN] = { -
AC97_MIX_MIC, 1, 6, 0, 0, 0, 1, 1 },
99 [SOUND_MIXER_CD] = {
AC97_MIX_CD, 5, 0, 1, 1, 2, 0, 1 },
100 [SOUND_MIXER_LINE1] = {
AC97_MIX_AUX, 5, 0, 1, 1, 4, 0, 0 },
106 { 0x41445300,
"Analog Devices" },
107 { 0x414b4d00,
"Asahi Kasei" },
108 { 0x414c4300,
"Realtek" },
109 { 0x414c4700,
"Avance Logic" },
110 { 0x43525900,
"Cirrus Logic" },
111 { 0x434d4900,
"C-Media Electronics" },
112 { 0x43585400,
"Conexant" },
113 { 0x44543000,
"Diamond Technology" },
114 { 0x454d4300,
"eMicro" },
115 { 0x45838300,
"ESS Technology" },
116 { 0x48525300,
"Intersil" },
117 { 0x49434500,
"ICEnsemble" },
118 { 0x49544500,
"ITE, Inc." },
119 { 0x4e534300,
"National Semiconductor" },
120 { 0x50534300,
"Philips Semiconductor" },
121 { 0x83847600,
"SigmaTel" },
122 { 0x53494c00,
"Silicon Laboratories" },
123 { 0x54524100,
"TriTech" },
124 { 0x54584e00,
"Texas Instruments" },
125 { 0x56494100,
"VIA Technologies" },
126 { 0x57454300,
"Winbond" },
127 { 0x574d4c00,
"Wolfson" },
128 { 0x594d4800,
"Yamaha" },
134 { 0x01408300,
"Creative" },
139 { 0x41445303, 0x00, 0,
"AD1819", 0 },
140 { 0x41445340, 0x00, 0,
"AD1881", 0 },
141 { 0x41445348, 0x00, 0,
"AD1881A", 0 },
142 { 0x41445360, 0x00, 0,
"AD1885", 0 },
144 { 0x41445362, 0x00, 0,
"AD1887", 0 },
145 { 0x41445363, 0x00, 0,
"AD1886A", 0 },
148 { 0x41445372, 0x00, 0,
"AD1981A", 0 },
152 { 0x414b4d00, 0x00, 1,
"AK4540", 0 },
153 { 0x414b4d01, 0x00, 1,
"AK4542", 0 },
154 { 0x414b4d02, 0x00, 1,
"AK4543", 0 },
155 { 0x414b4d06, 0x00, 0,
"AK4544A", 0 },
156 { 0x454b4d07, 0x00, 0,
"AK4545", 0 },
157 { 0x414c4320, 0x0f, 0,
"ALC100", 0 },
158 { 0x414c4730, 0x0f, 0,
"ALC101", 0 },
159 { 0x414c4710, 0x0f, 0,
"ALC200", 0 },
160 { 0x414c4740, 0x0f, 0,
"ALC202", 0 },
161 { 0x414c4720, 0x0f, 0,
"ALC650", 0 },
162 { 0x414c4752, 0x0f, 0,
"ALC250", 0 },
164 { 0x414c4770, 0x0f, 0,
"ALC203", 0 },
165 { 0x414c4780, 0x0f, 0,
"ALC658", 0 },
166 { 0x414c4790, 0x0f, 0,
"ALC850", 0 },
167 { 0x43525900, 0x07, 0,
"CS4297", 0 },
168 { 0x43525910, 0x07, 0,
"CS4297A", 0 },
169 { 0x43525920, 0x07, 0,
"CS4294/98", 0 },
170 { 0x4352592d, 0x07, 0,
"CS4294", 0 },
171 { 0x43525930, 0x07, 0,
"CS4299", 0 },
172 { 0x43525940, 0x07, 0,
"CS4201", 0 },
173 { 0x43525958, 0x07, 0,
"CS4205", 0 },
174 { 0x43525960, 0x07, 0,
"CS4291A", 0 },
176 { 0x434d4941, 0x00, 0,
"CMI9738", 0 },
177 { 0x434d4978, 0x00, 0,
"CMI9761", 0 },
178 { 0x434d4982, 0x00, 0,
"CMI9761", 0 },
179 { 0x434d4983, 0x00, 0,
"CMI9761", 0 },
180 { 0x43585421, 0x00, 0,
"HSD11246", 0 },
181 { 0x43585428, 0x07, 0,
"CX20468", 0 },
182 { 0x43585430, 0x00, 0,
"CX20468-21", 0 },
183 { 0x44543000, 0x00, 0,
"DT0398", 0 },
184 { 0x454d4323, 0x00, 0,
"EM28023", 0 },
185 { 0x454d4328, 0x00, 0,
"EM28028", 0 },
186 { 0x45838308, 0x00, 0,
"ES1988", 0 },
187 { 0x48525300, 0x00, 0,
"HMP9701", 0 },
188 { 0x49434501, 0x00, 0,
"ICE1230", 0 },
189 { 0x49434511, 0x00, 0,
"ICE1232", 0 },
190 { 0x49434514, 0x00, 0,
"ICE1232A", 0 },
191 { 0x49434551, 0x03, 0,
"VT1616", 0 },
192 { 0x49544520, 0x00, 0,
"ITE2226E", 0 },
193 { 0x49544560, 0x07, 0,
"ITE2646E", 0 },
194 { 0x4e534340, 0x00, 0,
"LM4540", 0 },
195 { 0x4e534343, 0x00, 0,
"LM4543", 0 },
196 { 0x4e534346, 0x00, 0,
"LM4546A", 0 },
197 { 0x4e534348, 0x00, 0,
"LM4548A", 0 },
198 { 0x4e534331, 0x00, 0,
"LM4549", 0 },
199 { 0x4e534349, 0x00, 0,
"LM4549A", 0 },
200 { 0x4e534350, 0x00, 0,
"LM4550", 0 },
201 { 0x50534301, 0x00, 0,
"UCB1510", 0 },
202 { 0x50534304, 0x00, 0,
"UCB1400", 0 },
203 { 0x83847600, 0x00, 0,
"STAC9700/83/84", 0 },
204 { 0x83847604, 0x00, 0,
"STAC9701/03/04/05", 0 },
205 { 0x83847605, 0x00, 0,
"STAC9704", 0 },
206 { 0x83847608, 0x00, 0,
"STAC9708/11", 0 },
207 { 0x83847609, 0x00, 0,
"STAC9721/23", 0 },
208 { 0x83847644, 0x00, 0,
"STAC9744/45", 0 },
209 { 0x83847650, 0x00, 0,
"STAC9750/51", 0 },
210 { 0x83847652, 0x00, 0,
"STAC9752/53", 0 },
211 { 0x83847656, 0x00, 0,
"STAC9756/57", 0 },
212 { 0x83847658, 0x00, 0,
"STAC9758/59", 0 },
213 { 0x83847660, 0x00, 0,
"STAC9760/61", 0 },
214 { 0x83847662, 0x00, 0,
"STAC9762/63", 0 },
215 { 0x83847666, 0x00, 0,
"STAC9766/67", 0 },
216 { 0x53494c22, 0x00, 0,
"Si3036", 0 },
217 { 0x53494c23, 0x00, 0,
"Si3038", 0 },
218 { 0x54524103, 0x00, 0,
"TR28023", 0 },
219 { 0x54524106, 0x00, 0,
"TR28026", 0 },
220 { 0x54524108, 0x00, 0,
"TR28028", 0 },
221 { 0x54524123, 0x00, 0,
"TR28602", 0 },
222 { 0x54524e03, 0x07, 0,
"TLV320AIC27", 0 },
223 { 0x54584e20, 0x00, 0,
"TLC320AD90", 0 },
224 { 0x56494161, 0x00, 0,
"VIA1612A", 0 },
225 { 0x56494170, 0x00, 0,
"VIA1617A", 0 },
226 { 0x574d4c00, 0x00, 0,
"WM9701A", 0 },
227 { 0x574d4c03, 0x00, 0,
"WM9703/4/7/8", 0 },
228 { 0x574d4c04, 0x00, 0,
"WM9704Q", 0 },
229 { 0x574d4c05, 0x00, 0,
"WM9705/10", 0 },
230 { 0x574d4d09, 0x00, 0,
"WM9709", 0 },
231 { 0x574d4c12, 0x00, 0,
"WM9711/12", 0 },
232 { 0x57454301, 0x00, 0,
"W83971D", 0 },
233 { 0x594d4800, 0x00, 0,
"YMF743", 0 },
234 { 0x594d4802, 0x00, 0,
"YMF752", 0 },
235 { 0x594d4803, 0x00, 0,
"YMF753", 0 },
241 { 0x01408384, 0x00, 0,
"EV1938", 0 },
246 "no 3D Stereo Enhancement",
247 "Analog Devices Phat Stereo",
248 "Creative Stereo Enhancement",
249 "National Semi 3D Stereo Enhancement",
251 "BBE 3D Stereo Enhancement",
252 "Crystal Semi 3D Stereo Enhancement",
254 "Spatializer 3D Stereo Enhancement",
255 "SRS 3D Stereo Enhancement",
256 "Platform Tech 3D Stereo Enhancement",
258 "Aureal Stereo Enhancement",
259 "Aztech 3D Enhancement",
260 "Binaura 3D Audio Enhancement",
261 "ESS Technology Stereo Enhancement",
262 "Harman International VMAx",
263 "Nvidea 3D Stereo Enhancement",
264 "Philips Incredible Sound",
265 "Texas Instruments 3D Stereo Enhancement",
266 "VLSI Technology 3D Stereo Enhancement",
267 "TriTech 3D Stereo Enhancement",
268 "Realtek 3D Stereo Enhancement",
269 "Samsung 3D Stereo Enhancement",
270 "Wolfson Microelectronics 3D Enhancement",
271 "Delta Integration 3D Enhancement",
272 "SigmaTel 3D Enhancement",
274 "Rockwell 3D Stereo Enhancement",
314 u_int16_t i[2], j = 100;
318 while (i[0] != i[1] && j)
322 device_printf(codec->
dev,
"%s(): Inconsistent register value at"
323 " 0x%08x (retry: %d)\n", __func__,
reg, 100 - j);
342 for (i = 0; i < 500; i++) {
348 device_printf(codec->
dev,
"AC97 reset timed out.\n");
386 if ((mode & ~codec->
extcaps) != 0) {
387 device_printf(codec->
dev,
"ac97 invalid mode set 0x%04x\n",
395 return (mode == codec->
extstat)? 0 : -1;
511 printf(
"ac97_setmixer: reg=%d, bits=%d, enable=%d\n", e->
reg, e->
bits, e->
enable);
546 if (keep_ogain == 0) {
547 bzero(&codec->
mix[SOUND_MIXER_OGAIN],
548 sizeof(codec->
mix[SOUND_MIXER_OGAIN]));
574 bzero(&codec->
mix[SOUND_MIXER_BASS],
575 sizeof(codec->
mix[SOUND_MIXER_BASS]));
576 bzero(&codec->
mix[SOUND_MIXER_TREBLE],
577 sizeof(codec->
mix[SOUND_MIXER_TREBLE]));
585 sprintf(
buf,
"Unknown AC97 Codec (id = 0x%08x)",
id);
589 if (vname == NULL) vname =
"Unknown";
592 sprintf(
buf,
"%s %s AC97 Codec (id = 0x%08x)", vname, cname,
id);
594 sprintf(
buf,
"%s %s AC97 Codec", vname, cname);
603 const char *cname, *vname;
606 u_int8_t
model, step;
607 unsigned i, j,
k, bit, old;
613 if (codec->
count == 0) {
614 device_printf(codec->
dev,
"ac97 codec init failed\n");
631 if (i != j || j !=
k) {
635 codec->
caps = i & 0x03ff;
636 codec->
se = (i & 0x7c00) >> 10;
639 if (
id == 0 ||
id == 0xffffffff) {
640 device_printf(codec->
dev,
"ac97 codec invalid or not present (id == %x)\n",
id);
646 while (strcmp(device_get_name(device_get_parent(pdev)),
"pci") != 0) {
648 pdev = device_get_parent(pdev);
651 codec->
subvendor = (u_int32_t)pci_get_subdevice(pdev) << 16;
652 codec->
subvendor |= (u_int32_t)pci_get_subvendor(pdev) &
661 if ((
ac97codecid[i].
id & modelmask) == (
id & modelmask)) {
665 model = (
id & modelmask) & 0xff;
666 step = (
id & ~modelmask) & 0xff;
686 codec->
extid = (i & 0xc000) >> 14;
728 j = ((1 << bit) - 1) << codec->
mix[i].
ofs;
730 j | (codec->
mix[i].
mute ? 0x8000 : 0));
734 ((
k & 0x0001) == 0x0000))
736 for (j = 0;
k >> j; j++)
740 device_printf(codec->
dev,
"%2d: [ac97_rdcd() = %d] [Testbit = %d] %d -> %d\n",
759 printf(
"mixch %d, en=%d, b=%d\n", i, codec->
mix[i].
enable, codec->
mix[i].
bits);
763 device_printf(codec->
dev,
"<%s>\n",
768 device_printf(codec->
dev,
"Buggy AC97 Codec: aggressive ac97_rdcd() workaround enabled\n");
769 device_printf(codec->
dev,
"Codec features ");
770 for (i = j = 0; i < 10; i++)
771 if (codec->
caps & (1 << i))
773 printf(
"%s%d bit master volume", j++?
", " :
"", codec->
mix[SOUND_MIXER_VOLUME].
bits);
777 device_printf(codec->
dev,
"%s codec",
778 codec->
extid?
"Secondary" :
"Primary");
780 printf(
" extended features ");
781 for (i = j = 0; i < 14; i++)
791 device_printf(codec->
dev,
"ac97 codec reports dac not ready\n");
797 device_printf(codec->
dev,
"ac97 codec dac ready count: %d\n", i);
807 if (codec->
count == 0) {
808 device_printf(codec->
dev,
"ac97 codec init failed\n");
821 device_printf(codec->
dev,
"ac97 codec failed to reset extended mode (%x, got %x)\n",
828 device_printf(codec->
dev,
"ac97 codec reports dac not ready\n");
839 codec = malloc(
sizeof(*codec), M_AC97, M_WAITOK | M_ZERO);
840 snprintf(codec->
name,
sizeof(codec->
name),
"%s:ac97",
841 device_get_nameunit(
dev));
843 codec->
methods = kobj_create(cls, M_AC97, M_WAITOK | M_ZERO);
848 if (resource_int_value(device_get_name(
dev), device_get_unit(
dev),
849 "eapdinv", &i) == 0 && i != 0)
852 if (resource_int_value(device_get_name(
dev), device_get_unit(
dev),
853 "softpcmvol", &i) == 0 && i != 0)
864 kobj_delete(codec->
methods, M_AC97);
887 int ea, inv, err = 0;
890 codec = oidp->oid_arg1;
891 if (codec == NULL || codec->
id == 0 || codec->
lock == NULL)
896 ea = (
val >> 15) ^ inv;
898 err = sysctl_handle_int(oidp, &ea, 0,
req);
899 if (err == 0 &&
req->newptr != NULL) {
900 if (ea != 0 && ea != 1)
902 if (ea != ((
val >> 15) ^ inv)) {
916 if (codec == NULL || codec->
dev == NULL)
924 if ((
val & 0x8000) == (orig & 0x8000))
926 SYSCTL_ADD_PROC(device_get_sysctl_ctx(codec->
dev),
927 SYSCTL_CHILDREN(device_get_sysctl_tree(codec->
dev)),
929 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE,
931 "I",
"AC97 External Amplifier");
958 if (codec->
mix[SOUND_MIXER_OGAIN].
enable)
959 mask |= SOUND_MASK_OGAIN;
960 if (codec->
mix[SOUND_MIXER_PHONEOUT].
enable)
961 mask |= SOUND_MASK_PHONEOUT;
962 if (codec->
mix[SOUND_MIXER_VOLUME].
enable)
982 codec->
mix[SOUND_MIXER_OGAIN].
enable = 1;
983 codec->
mix[SOUND_MIXER_PHONEOUT].
enable = 1;
989 SOUND_MASK_OGAIN | SOUND_MASK_PHONEOUT);
1000 bzero(&codec->
mix[SOUND_MIXER_PCM],
1001 sizeof(codec->
mix[SOUND_MIXER_PCM]));
1015 SOUND_MASK_PCM | SOUND_MASK_CD);
1079 if ((
src & (1 << i)) != 0)
1099 return &ac97mixer_class;
static void ac97_init_sysctl(struct ac97_info *codec)
u_int16_t ac97_getextmode(struct ac97_info *codec)
static int ac97mix_init(struct snd_mixer *m)
void ac97_wrcd(struct ac97_info *codec, int reg, u_int16_t val)
int ac97_setextmode(struct ac97_info *codec, u_int16_t mode)
u_int16_t ac97_getcaps(struct ac97_info *codec)
u_int32_t ac97_getflags(struct ac97_info *codec)
static char * ac97feature[]
u_int16_t ac97_getextcaps(struct ac97_info *codec)
kobj_class_t ac97_getmixerclass(void)
void ac97_destroy(struct ac97_info *codec)
static int sysctl_hw_snd_ac97_eapd(SYSCTL_HANDLER_ARGS)
u_int32_t ac97_getsubvendor(struct ac97_info *codec)
SND_DECLARE_FILE("$FreeBSD$")
static MALLOC_DEFINE(M_AC97, "ac97", "ac97 codec")
static const char * ac97_hw_desc(u_int32_t id, const char *vname, const char *cname, char *buf)
static int ac97mix_uninit(struct snd_mixer *m)
static unsigned ac97_reinitmixer(struct ac97_info *codec)
static int ac97mix_set(struct snd_mixer *m, unsigned dev, unsigned left, unsigned right)
static unsigned ac97_initmixer(struct ac97_info *codec)
static u_int32_t ac97mix_setrecsrc(struct snd_mixer *m, u_int32_t src)
static const struct ac97mixtable_entry ac97mixtable_default[AC97_MIXER_SIZE]
void ac97_setflags(struct ac97_info *codec, u_int32_t val)
static kobj_method_t ac97mixer_methods[]
static int ac97mix_reinit(struct snd_mixer *m)
static struct ac97_codecid ac97codecid[]
static char * ac97enhancement[]
static void ac97_fix_tone(struct ac97_info *codec)
u_int16_t ac97_rdcd(struct ac97_info *codec, int reg)
struct ac97_info * ac97_create(device_t dev, void *devinfo, kobj_class_t cls)
static void ac97_fix_auxout(struct ac97_info *codec)
static int ac97_setrecsrc(struct ac97_info *codec, int channel)
static int ac97_setmixer(struct ac97_info *codec, unsigned channel, unsigned left, unsigned right)
int ac97_setrate(struct ac97_info *codec, int which, int rate)
static void ac97_reset(struct ac97_info *codec)
static char * ac97extfeature[]
static const struct ac97_vendorid ac97vendorid[]
#define AC97_POWER_STATUS
#define AC97_REGEXT_FDACRATE
#define AC97_MIXEXT_SURROUND
#define AC97_REGEXT_MADCRATE
#define AC97_REGEXT_LDACRATE
#define AC97_REGEXT_LADCRATE
#define AC97_REGEXT_SDACRATE
void ad1981b_patch(struct ac97_info *codec)
void ad198x_patch(struct ac97_info *codec)
void alc655_patch(struct ac97_info *codec)
void ad1886_patch(struct ac97_info *codec)
void cmi9739_patch(struct ac97_info *codec)
void(* ac97_patch)(struct ac97_info *)
struct pcmchan_matrix * m
static int mixer_setrecsrc(struct snd_mixer *mixer, u_int32_t src)
void mix_setparentchild(struct snd_mixer *m, u_int32_t parent, u_int32_t childs)
void mix_setrealdev(struct snd_mixer *m, u_int32_t dev, u_int32_t realdev)
int mixer_init(device_t dev, kobj_class_t cls, void *devinfo)
static int mixer_set(struct snd_mixer *m, u_int dev, u_int32_t muted, u_int lev)
int mixer_uninit(device_t dev)
void mix_setdevs(struct snd_mixer *m, u_int32_t v)
int mixer_reinit(device_t dev)
void * mix_getdevinfo(struct snd_mixer *m)
void mix_setrecdevs(struct snd_mixer *m, u_int32_t v)
Record mask of available recording devices.
void * snd_mtxcreate(const char *desc, const char *type)
void pcm_setflags(device_t dev, uint32_t val)
uint32_t pcm_getflags(device_t dev)
void snd_mtxfree(void *m)
struct ac97mixtable_entry mix[AC97_MIXER_SIZE]