Merge from vendor branch LESS:
[dragonfly.git] / sys / dev / sound / pcm / ac97.c
1 /*-
2  * Copyright (c) 1999 Cameron Grant <cg@freebsd.org>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  *
26  * $FreeBSD: src/sys/dev/sound/pcm/ac97.c,v 1.53.2.5 2007/05/13 20:53:39 ariff Exp $
27  * $DragonFly: src/sys/dev/sound/pcm/ac97.c,v 1.25 2007/06/16 20:07:22 dillon Exp $
28  */
29
30 #include <dev/sound/pcm/sound.h>
31 #include <dev/sound/pcm/ac97.h>
32 #include <dev/sound/pcm/ac97_patch.h>
33
34 #include <bus/pci/pcivar.h>
35
36 #include "mixer_if.h"
37
38 SND_DECLARE_FILE("$DragonFly: src/sys/dev/sound/pcm/ac97.c,v 1.25 2007/06/16 20:07:22 dillon Exp $");
39
40 MALLOC_DEFINE(M_AC97, "ac97", "ac97 codec");
41
42 struct ac97mixtable_entry {
43         int      reg:8;         /* register index               */
44                                 /* reg < 0 if inverted polarity */
45         unsigned bits:4;        /* width of control field       */
46         unsigned ofs:4;         /* offset (only if stereo=0)    */
47         unsigned stereo:1;      /* set for stereo controls      */
48         unsigned mute:1;        /* bit15 is MUTE                */
49         unsigned recidx:4;      /* index in rec mux             */
50         unsigned mask:1;        /* use only masked bits         */
51         unsigned enable:1;      /* entry is enabled             */
52 };
53
54 #define AC97_NAMELEN    16
55 struct ac97_info {
56         kobj_t methods;
57         device_t dev;
58         void *devinfo;
59         u_int32_t id;
60         u_int32_t subvendor;
61         unsigned count, caps, se, extcaps, extid, extstat, noext:1;
62         u_int32_t flags;
63         struct ac97mixtable_entry mix[32];
64         char name[AC97_NAMELEN];
65         sndlock_t       lock;
66 };
67
68 struct ac97_vendorid {
69         u_int32_t   id;
70         const char *name;
71 };
72
73 struct ac97_codecid {
74         u_int32_t  id;
75         u_int8_t   stepmask;
76         u_int8_t   noext:1;
77         char      *name;
78         ac97_patch patch;
79 };
80
81 static const struct ac97mixtable_entry ac97mixtable_default[32] = {
82     /*  [offset]                        reg          bits of st mu re mk en */
83         [SOUND_MIXER_VOLUME]    = { AC97_MIX_MASTER,    5, 0, 1, 1, 6, 0, 1 },
84         [SOUND_MIXER_OGAIN]     = { AC97_MIX_AUXOUT,    5, 0, 1, 1, 0, 0, 0 },
85         [SOUND_MIXER_PHONEOUT]  = { AC97_MIX_MONO,      5, 0, 0, 1, 7, 0, 0 },
86         [SOUND_MIXER_BASS]      = { AC97_MIX_TONE,      4, 8, 0, 0, 0, 1, 0 },
87         [SOUND_MIXER_TREBLE]    = { AC97_MIX_TONE,      4, 0, 0, 0, 0, 1, 0 },
88         [SOUND_MIXER_PCM]       = { AC97_MIX_PCM,       5, 0, 1, 1, 0, 0, 1 },
89         [SOUND_MIXER_SPEAKER]   = { AC97_MIX_BEEP,      4, 1, 0, 1, 0, 0, 0 },
90         [SOUND_MIXER_LINE]      = { AC97_MIX_LINE,      5, 0, 1, 1, 5, 0, 1 },
91         [SOUND_MIXER_PHONEIN]   = { AC97_MIX_PHONE,     5, 0, 0, 1, 8, 0, 0 },
92         [SOUND_MIXER_MIC]       = { AC97_MIX_MIC,       5, 0, 0, 1, 1, 1, 1 },
93         /* use igain for the mic 20dB boost */
94         [SOUND_MIXER_IGAIN]     = { -AC97_MIX_MIC,      1, 6, 0, 0, 0, 1, 1 },
95         [SOUND_MIXER_CD]        = { AC97_MIX_CD,        5, 0, 1, 1, 2, 0, 1 },
96         [SOUND_MIXER_LINE1]     = { AC97_MIX_AUX,       5, 0, 1, 1, 4, 0, 0 },
97         [SOUND_MIXER_VIDEO]     = { AC97_MIX_VIDEO,     5, 0, 1, 1, 3, 0, 0 },
98         [SOUND_MIXER_RECLEV]    = { -AC97_MIX_RGAIN,    4, 0, 1, 1, 0, 0, 1 }
99 };
100
101 static const struct ac97_vendorid ac97vendorid[] = {
102         { 0x41445300, "Analog Devices" },
103         { 0x414b4d00, "Asahi Kasei" },
104         { 0x414c4300, "Realtek" },
105         { 0x414c4700, "Avance Logic" },
106         { 0x43525900, "Cirrus Logic" },
107         { 0x434d4900, "C-Media Electronics" },
108         { 0x43585400, "Conexant" },
109         { 0x44543000, "Diamond Technology" },
110         { 0x454d4300, "eMicro" },
111         { 0x45838300, "ESS Technology" },
112         { 0x48525300, "Intersil" },
113         { 0x49434500, "ICEnsemble" },
114         { 0x49544500, "ITE, Inc." },
115         { 0x4e534300, "National Semiconductor" },
116         { 0x50534300, "Philips Semiconductor" },
117         { 0x83847600, "SigmaTel" },
118         { 0x53494c00, "Silicon Laboratories" },
119         { 0x54524100, "TriTech" },
120         { 0x54584e00, "Texas Instruments" },
121         { 0x56494100, "VIA Technologies" },
122         { 0x57454300, "Winbond" },
123         { 0x574d4c00, "Wolfson" },
124         { 0x594d4800, "Yamaha" },
125         /* 
126          * XXX This is a fluke, really! The real vendor
127          * should be SigmaTel, not this! This should be
128          * removed someday!
129          */
130         { 0x01408300, "Creative" },
131         { 0x00000000, NULL }
132 };
133
134 static struct ac97_codecid ac97codecid[] = {
135         { 0x41445303, 0x00, 0, "AD1819",        0 },
136         { 0x41445340, 0x00, 0, "AD1881",        0 },
137         { 0x41445348, 0x00, 0, "AD1881A",       0 },
138         { 0x41445360, 0x00, 0, "AD1885",        0 },
139         { 0x41445361, 0x00, 0, "AD1886",        ad1886_patch },
140         { 0x41445362, 0x00, 0, "AD1887",        0 },
141         { 0x41445363, 0x00, 0, "AD1886A",       0 },
142         { 0x41445368, 0x00, 0, "AD1888",        ad198x_patch },
143         { 0x41445370, 0x00, 0, "AD1980",        ad198x_patch },
144         { 0x41445372, 0x00, 0, "AD1981A",       0 },
145         { 0x41445374, 0x00, 0, "AD1981B",       ad1981b_patch },
146         { 0x41445375, 0x00, 0, "AD1985",        ad198x_patch },
147         { 0x41445378, 0x00, 0, "AD1986",        ad198x_patch },
148         { 0x414b4d00, 0x00, 1, "AK4540",        0 },
149         { 0x414b4d01, 0x00, 1, "AK4542",        0 },
150         { 0x414b4d02, 0x00, 1, "AK4543",        0 },
151         { 0x414b4d06, 0x00, 0, "AK4544A",       0 },
152         { 0x454b4d07, 0x00, 0, "AK4545",        0 },
153         { 0x414c4320, 0x0f, 0, "ALC100",        0 },
154         { 0x414c4730, 0x0f, 0, "ALC101",        0 },
155         { 0x414c4710, 0x0f, 0, "ALC200",        0 },
156         { 0x414c4740, 0x0f, 0, "ALC202",        0 },
157         { 0x414c4720, 0x0f, 0, "ALC650",        0 },
158         { 0x414c4752, 0x0f, 0, "ALC250",        0 },
159         { 0x414c4760, 0x0f, 0, "ALC655",        alc655_patch },
160         { 0x414c4770, 0x0f, 0, "ALC203",        0 },
161         { 0x414c4780, 0x0f, 0, "ALC658",        0 },
162         { 0x414c4790, 0x0f, 0, "ALC850",        0 },
163         { 0x43525900, 0x07, 0, "CS4297",        0 },
164         { 0x43525910, 0x07, 0, "CS4297A",       0 },
165         { 0x43525920, 0x07, 0, "CS4294/98",     0 },
166         { 0x4352592d, 0x07, 0, "CS4294",        0 },
167         { 0x43525930, 0x07, 0, "CS4299",        0 },
168         { 0x43525940, 0x07, 0, "CS4201",        0 },
169         { 0x43525958, 0x07, 0, "CS4205",        0 },
170         { 0x43525960, 0x07, 0, "CS4291A",       0 },
171         { 0x434d4961, 0x00, 0, "CMI9739",       cmi9739_patch },
172         { 0x434d4941, 0x00, 0, "CMI9738",       0 },
173         { 0x434d4978, 0x00, 0, "CMI9761",       0 },
174         { 0x434d4982, 0x00, 0, "CMI9761",       0 },
175         { 0x434d4983, 0x00, 0, "CMI9761",       0 },
176         { 0x43585421, 0x00, 0, "HSD11246",      0 },
177         { 0x43585428, 0x07, 0, "CX20468",       0 },
178         { 0x43585430, 0x00, 0, "CX20468-21",    0 },
179         { 0x44543000, 0x00, 0, "DT0398",        0 },
180         { 0x454d4323, 0x00, 0, "EM28023",       0 },
181         { 0x454d4328, 0x00, 0, "EM28028",       0 },
182         { 0x45838308, 0x00, 0, "ES1988",        0 }, /* Formerly ES1921(?) */
183         { 0x48525300, 0x00, 0, "HMP9701",       0 },
184         { 0x49434501, 0x00, 0, "ICE1230",       0 },
185         { 0x49434511, 0x00, 0, "ICE1232",       0 },
186         { 0x49434514, 0x00, 0, "ICE1232A",      0 },
187         { 0x49434551, 0x03, 0, "VT1616",        0 }, /* Via badged ICE */
188         { 0x49544520, 0x00, 0, "ITE2226E",      0 },
189         { 0x49544560, 0x07, 0, "ITE2646E",      0 }, /* XXX: patch needed */
190         { 0x4e534340, 0x00, 0, "LM4540",        0 }, /* Spec blank on revid */
191         { 0x4e534343, 0x00, 0, "LM4543",        0 }, /* Ditto */
192         { 0x4e534346, 0x00, 0, "LM4546A",       0 },
193         { 0x4e534348, 0x00, 0, "LM4548A",       0 },
194         { 0x4e534331, 0x00, 0, "LM4549",        0 },
195         { 0x4e534349, 0x00, 0, "LM4549A",       0 },
196         { 0x4e534350, 0x00, 0, "LM4550",        0 },
197         { 0x50534301, 0x00, 0, "UCB1510",       0 },
198         { 0x50534304, 0x00, 0, "UCB1400",       0 },
199         { 0x83847600, 0x00, 0, "STAC9700/83/84",        0 },
200         { 0x83847604, 0x00, 0, "STAC9701/03/04/05", 0 },
201         { 0x83847605, 0x00, 0, "STAC9704",      0 },
202         { 0x83847608, 0x00, 0, "STAC9708/11",   0 },
203         { 0x83847609, 0x00, 0, "STAC9721/23",   0 },
204         { 0x83847644, 0x00, 0, "STAC9744/45",   0 },
205         { 0x83847650, 0x00, 0, "STAC9750/51",   0 },
206         { 0x83847652, 0x00, 0, "STAC9752/53",   0 },
207         { 0x83847656, 0x00, 0, "STAC9756/57",   0 },
208         { 0x83847658, 0x00, 0, "STAC9758/59",   0 },
209         { 0x83847660, 0x00, 0, "STAC9760/61",   0 }, /* Extrapolated */
210         { 0x83847662, 0x00, 0, "STAC9762/63",   0 }, /* Extrapolated */
211         { 0x83847666, 0x00, 0, "STAC9766/67",   0 },
212         { 0x53494c22, 0x00, 0, "Si3036",        0 },
213         { 0x53494c23, 0x00, 0, "Si3038",        0 },
214         { 0x54524103, 0x00, 0, "TR28023",       0 }, /* Extrapolated */
215         { 0x54524106, 0x00, 0, "TR28026",       0 },
216         { 0x54524108, 0x00, 0, "TR28028",       0 },
217         { 0x54524123, 0x00, 0, "TR28602",       0 },
218         { 0x54524e03, 0x07, 0, "TLV320AIC27",   0 },
219         { 0x54584e20, 0x00, 0, "TLC320AD90",    0 },
220         { 0x56494161, 0x00, 0, "VIA1612A",      0 },
221         { 0x56494170, 0x00, 0, "VIA1617A",      0 },
222         { 0x574d4c00, 0x00, 0, "WM9701A",       0 },
223         { 0x574d4c03, 0x00, 0, "WM9703/4/7/8",  0 },
224         { 0x574d4c04, 0x00, 0, "WM9704Q",       0 },
225         { 0x574d4c05, 0x00, 0, "WM9705/10",     0 },
226         { 0x574d4d09, 0x00, 0, "WM9709",        0 },
227         { 0x574d4c12, 0x00, 0, "WM9711/12",     0 }, /* XXX: patch needed */
228         { 0x57454301, 0x00, 0, "W83971D",       0 },
229         { 0x594d4800, 0x00, 0, "YMF743",        0 },
230         { 0x594d4802, 0x00, 0, "YMF752",        0 },
231         { 0x594d4803, 0x00, 0, "YMF753",        0 },
232         /* 
233          * XXX This is a fluke, really! The real codec
234          * should be STAC9704, not this! This should be
235          * removed someday!
236          */
237         { 0x01408384, 0x00, 0, "EV1938",        0 },
238         { 0, 0, 0, NULL, 0 }
239 };
240
241 static char *ac97enhancement[] = {
242         "no 3D Stereo Enhancement",
243         "Analog Devices Phat Stereo",
244         "Creative Stereo Enhancement",
245         "National Semi 3D Stereo Enhancement",
246         "Yamaha Ymersion",
247         "BBE 3D Stereo Enhancement",
248         "Crystal Semi 3D Stereo Enhancement",
249         "Qsound QXpander",
250         "Spatializer 3D Stereo Enhancement",
251         "SRS 3D Stereo Enhancement",
252         "Platform Tech 3D Stereo Enhancement",
253         "AKM 3D Audio",
254         "Aureal Stereo Enhancement",
255         "Aztech 3D Enhancement",
256         "Binaura 3D Audio Enhancement",
257         "ESS Technology Stereo Enhancement",
258         "Harman International VMAx",
259         "Nvidea 3D Stereo Enhancement",
260         "Philips Incredible Sound",
261         "Texas Instruments 3D Stereo Enhancement",
262         "VLSI Technology 3D Stereo Enhancement",
263         "TriTech 3D Stereo Enhancement",
264         "Realtek 3D Stereo Enhancement",
265         "Samsung 3D Stereo Enhancement",
266         "Wolfson Microelectronics 3D Enhancement",
267         "Delta Integration 3D Enhancement",
268         "SigmaTel 3D Enhancement",
269         "Reserved 27",
270         "Rockwell 3D Stereo Enhancement",
271         "Reserved 29",
272         "Reserved 30",
273         "Reserved 31"
274 };
275
276 static char *ac97feature[] = {
277         "mic channel",
278         "reserved",
279         "tone",
280         "simulated stereo",
281         "headphone",
282         "bass boost",
283         "18 bit DAC",
284         "20 bit DAC",
285         "18 bit ADC",
286         "20 bit ADC"
287 };
288
289 static char *ac97extfeature[] = {
290         "variable rate PCM",
291         "double rate PCM",
292         "reserved 1",
293         "variable rate mic",
294         "reserved 2",
295         "reserved 3",
296         "center DAC",
297         "surround DAC",
298         "LFE DAC",
299         "AMAP",
300         "reserved 4",
301         "reserved 5",
302         "reserved 6",
303         "reserved 7",
304 };
305
306 u_int16_t
307 ac97_rdcd(struct ac97_info *codec, int reg)
308 {
309         if (codec->flags & AC97_F_RDCD_BUG) {
310                 u_int16_t i[2], j = 100;
311
312                 i[0] = AC97_READ(codec->methods, codec->devinfo, reg);
313                 i[1] = AC97_READ(codec->methods, codec->devinfo, reg);
314                 while (i[0] != i[1] && j)
315                         i[j-- & 1] = AC97_READ(codec->methods, codec->devinfo, reg);
316 #if 0
317                 if (j < 100) {
318                         device_printf(codec->dev, "%s(): Inconsistent register value at"
319                                         " 0x%08x (retry: %d)\n", __func__, reg, 100 - j);
320                 }
321 #endif
322                 return i[!(j & 1)];
323         }
324         return AC97_READ(codec->methods, codec->devinfo, reg);
325 }
326
327 void
328 ac97_wrcd(struct ac97_info *codec, int reg, u_int16_t val)
329 {
330         AC97_WRITE(codec->methods, codec->devinfo, reg, val);
331 }
332
333 static void
334 ac97_reset(struct ac97_info *codec)
335 {
336         u_int32_t i, ps;
337         ac97_wrcd(codec, AC97_REG_RESET, 0);
338         for (i = 0; i < 500; i++) {
339                 ps = ac97_rdcd(codec, AC97_REG_POWER) & AC97_POWER_STATUS;
340                 if (ps == AC97_POWER_STATUS)
341                         return;
342                 DELAY(1000);
343         }
344         device_printf(codec->dev, "AC97 reset timed out.\n");
345 }
346
347 int
348 ac97_setrate(struct ac97_info *codec, int which, int rate)
349 {
350         u_int16_t v;
351
352         switch(which) {
353         case AC97_REGEXT_FDACRATE:
354         case AC97_REGEXT_SDACRATE:
355         case AC97_REGEXT_LDACRATE:
356         case AC97_REGEXT_LADCRATE:
357         case AC97_REGEXT_MADCRATE:
358                 break;
359
360         default:
361                 return -1;
362         }
363
364         snd_mtxlock(codec->lock);
365         if (rate != 0) {
366                 v = rate;
367                 if (codec->extstat & AC97_EXTCAP_DRA)
368                         v >>= 1;
369                 ac97_wrcd(codec, which, v);
370         }
371         v = ac97_rdcd(codec, which);
372         if (codec->extstat & AC97_EXTCAP_DRA)
373                 v <<= 1;
374         snd_mtxunlock(codec->lock);
375         return v;
376 }
377
378 int
379 ac97_setextmode(struct ac97_info *codec, u_int16_t mode)
380 {
381         mode &= AC97_EXTCAPS;
382         if ((mode & ~codec->extcaps) != 0) {
383                 device_printf(codec->dev, "ac97 invalid mode set 0x%04x\n",
384                               mode);
385                 return -1;
386         }
387         snd_mtxlock(codec->lock);
388         ac97_wrcd(codec, AC97_REGEXT_STAT, mode);
389         codec->extstat = ac97_rdcd(codec, AC97_REGEXT_STAT) & AC97_EXTCAPS;
390         snd_mtxunlock(codec->lock);
391         return (mode == codec->extstat)? 0 : -1;
392 }
393
394 u_int16_t
395 ac97_getextmode(struct ac97_info *codec)
396 {
397         return codec->extstat;
398 }
399
400 u_int16_t
401 ac97_getextcaps(struct ac97_info *codec)
402 {
403         return codec->extcaps;
404 }
405
406 u_int16_t
407 ac97_getcaps(struct ac97_info *codec)
408 {
409         return codec->caps;
410 }
411
412 u_int32_t
413 ac97_getsubvendor(struct ac97_info *codec)
414 {
415         return codec->subvendor;
416 }
417
418 static int
419 ac97_setrecsrc(struct ac97_info *codec, int channel)
420 {
421         struct ac97mixtable_entry *e = &codec->mix[channel];
422
423         if (e->recidx > 0) {
424                 int val = e->recidx - 1;
425                 val |= val << 8;
426                 snd_mtxlock(codec->lock);
427                 ac97_wrcd(codec, AC97_REG_RECSEL, val);
428                 snd_mtxunlock(codec->lock);
429                 return 0;
430         } else
431                 return -1;
432 }
433
434 static int
435 ac97_setmixer(struct ac97_info *codec, unsigned channel, unsigned left, unsigned right)
436 {
437         struct ac97mixtable_entry *e = &codec->mix[channel];
438
439         if (e->reg && e->enable && e->bits) {
440                 int mask, max, val, reg;
441
442                 reg = (e->reg >= 0) ? e->reg : -e->reg; /* AC97 register    */
443                 max = (1 << e->bits) - 1;               /* actual range     */
444                 mask = (max << 8) | max;                /* bits of interest */
445
446                 if (!e->stereo)
447                         right = left;
448
449                 /*
450                  * Invert the range if the polarity requires so,
451                  * then scale to 0..max-1 to compute the value to
452                  * write into the codec, and scale back to 0..100
453                  * for the return value.
454                  */
455                 if (e->reg > 0) {
456                         left = 100 - left;
457                         right = 100 - right;
458                 }
459
460                 left = (left * max) / 100;
461                 right = (right * max) / 100;
462
463                 val = (left << 8) | right;
464
465                 left = (left * 100) / max;
466                 right = (right * 100) / max;
467
468                 if (e->reg > 0) {
469                         left = 100 - left;
470                         right = 100 - right;
471                 }
472
473                 /*
474                  * For mono controls, trim val and mask, also taking
475                  * care of e->ofs (offset of control field).
476                  */
477                 if (e->ofs) {
478                         val &= max;
479                         val <<= e->ofs;
480                         mask = (max << e->ofs);
481                 }
482
483                 /*
484                  * If we have a mute bit, add it to the mask and
485                  * update val and set mute if both channels require a
486                  * zero volume.
487                  */
488                 if (e->mute == 1) {
489                         mask |= AC97_MUTE;
490                         if (left == 0 && right == 0)
491                                 val = AC97_MUTE;
492                 }
493
494                 /*
495                  * If the mask bit is set, do not alter the other bits.
496                  */
497                 snd_mtxlock(codec->lock);
498                 if (e->mask) {
499                         int cur = ac97_rdcd(codec, reg);
500                         val |= cur & ~(mask);
501                 }
502                 ac97_wrcd(codec, reg, val);
503                 snd_mtxunlock(codec->lock);
504                 return left | (right << 8);
505         } else {
506 #if 0
507                 kprintf("ac97_setmixer: reg=%d, bits=%d, enable=%d\n", e->reg, e->bits, e->enable);
508 #endif
509                 return -1;
510         }
511 }
512
513 static void
514 ac97_fix_auxout(struct ac97_info *codec)
515 {
516         int keep_ogain;
517
518         /*
519          * By default, The ac97 aux_out register (0x04) corresponds to OSS's
520          * OGAIN setting.
521          *
522          * We first check whether aux_out is a valid register.  If not
523          * we may not want to keep ogain.
524          */
525         keep_ogain = ac97_rdcd(codec, AC97_MIX_AUXOUT) & 0x8000;
526
527         /*
528          * Determine what AUX_OUT really means, it can be:
529          *
530          * 1. Headphone out.
531          * 2. 4-Channel Out
532          * 3. True line level out (effectively master volume).
533          *
534          * See Sections 5.2.1 and 5.27 for AUX_OUT Options in AC97r2.{2,3}.
535          */
536         if (codec->extcaps & AC97_EXTCAP_SDAC &&
537             ac97_rdcd(codec, AC97_MIXEXT_SURROUND) == 0x8080) {
538                 codec->mix[SOUND_MIXER_OGAIN].reg = AC97_MIXEXT_SURROUND;
539                 keep_ogain = 1;
540         }
541
542         if (keep_ogain == 0) {
543                 bzero(&codec->mix[SOUND_MIXER_OGAIN],
544                       sizeof(codec->mix[SOUND_MIXER_OGAIN]));
545         }
546 }
547
548 static void
549 ac97_fix_tone(struct ac97_info *codec)
550 {
551         /*
552          * YMF chips does not indicate tone and 3D enhancement capability
553          * in the AC97_REG_RESET register.
554          */
555         switch (codec->id) {
556         case 0x594d4800:        /* YMF743 */
557         case 0x594d4803:        /* YMF753 */
558                 codec->caps |= AC97_CAP_TONE;
559                 codec->se |= 0x04;
560                 break;
561         case 0x594d4802:        /* YMF752 */
562                 codec->se |= 0x04;
563                 break;
564         default:
565                 break;
566         }
567
568         /* Hide treble and bass if they don't exist */
569         if ((codec->caps & AC97_CAP_TONE) == 0) {
570                 bzero(&codec->mix[SOUND_MIXER_BASS],
571                       sizeof(codec->mix[SOUND_MIXER_BASS]));
572                 bzero(&codec->mix[SOUND_MIXER_TREBLE],
573                       sizeof(codec->mix[SOUND_MIXER_TREBLE]));
574         }
575 }
576
577 static void
578 ac97_fix_volume(struct ac97_info *codec)
579 {
580         struct snddev_info *d = device_get_softc(codec->dev);
581
582 #if 0
583         /* XXX For the sake of debugging purposes */
584         ac97_wrcd(codec, AC97_MIX_PCM, 0);
585         bzero(&codec->mix[SOUND_MIXER_PCM],
586                 sizeof(codec->mix[SOUND_MIXER_PCM]));
587         if (d)
588                 d->flags |= SD_F_SOFTPCMVOL;
589         return;
590 #endif
591         switch (codec->id) {
592                 case 0x434d4941:        /* CMI9738 */
593                 case 0x434d4961:        /* CMI9739 */
594                 case 0x434d4978:        /* CMI9761 */
595                 case 0x434d4982:        /* CMI9761 */
596                 case 0x434d4983:        /* CMI9761 */
597                         ac97_wrcd(codec, AC97_MIX_PCM, 0);
598                         break;
599                 default:
600                         return;
601                         break;
602         }
603         bzero(&codec->mix[SOUND_MIXER_PCM],
604                         sizeof(codec->mix[SOUND_MIXER_PCM]));
605         if (d)
606                 d->flags |= SD_F_SOFTPCMVOL;
607 }
608
609 static const char*
610 ac97_hw_desc(u_int32_t id, const char* vname, const char* cname, char* buf)
611 {
612         if (cname == NULL) {
613                 ksprintf(buf, "Unknown AC97 Codec (id = 0x%08x)", id);
614                 return buf;
615         }
616
617         if (vname == NULL) vname = "Unknown";
618
619         if (bootverbose) {
620                 ksprintf(buf, "%s %s AC97 Codec (id = 0x%08x)", vname, cname, id);
621         } else {
622                 ksprintf(buf, "%s %s AC97 Codec", vname, cname);
623         }
624         return buf;
625 }
626
627 static unsigned
628 ac97_initmixer(struct ac97_info *codec)
629 {
630         ac97_patch codec_patch;
631         const char *cname, *vname;
632         char desc[80];
633         u_int8_t model, step;
634         unsigned i, j, k, bit, old;
635         u_int32_t id;
636         int reg;
637
638         snd_mtxlock(codec->lock);
639         codec->count = AC97_INIT(codec->methods, codec->devinfo);
640         if (codec->count == 0) {
641                 device_printf(codec->dev, "ac97 codec init failed\n");
642                 snd_mtxunlock(codec->lock);
643                 return ENODEV;
644         }
645
646         ac97_wrcd(codec, AC97_REG_POWER, (codec->flags & AC97_F_EAPD_INV)? 0x8000 : 0x0000);
647         ac97_reset(codec);
648         ac97_wrcd(codec, AC97_REG_POWER, (codec->flags & AC97_F_EAPD_INV)? 0x8000 : 0x0000);
649
650         i = ac97_rdcd(codec, AC97_REG_RESET);
651         j = ac97_rdcd(codec, AC97_REG_RESET);
652         /*
653          * Let see if this codec can return consistent value.
654          * If not, turn on aggressive read workaround
655          * (STAC9704 comes in mind).
656          */
657         if (i != j) {
658                 codec->flags |= AC97_F_RDCD_BUG;
659                 i = ac97_rdcd(codec, AC97_REG_RESET);
660         }
661         codec->caps = i & 0x03ff;
662         codec->se =  (i & 0x7c00) >> 10;
663
664         id = (ac97_rdcd(codec, AC97_REG_ID1) << 16) | ac97_rdcd(codec, AC97_REG_ID2);
665         if (id == 0 || id == 0xffffffff) {
666                 device_printf(codec->dev, "ac97 codec invalid or not present (id == %x)\n", id);
667                 snd_mtxunlock(codec->lock);
668                 return ENODEV;
669         }
670
671         codec->id = id;
672         codec->subvendor = (u_int32_t)pci_get_subdevice(codec->dev) << 16;
673         codec->subvendor |= (u_int32_t)pci_get_subvendor(codec->dev) &
674             0x0000ffff;
675         codec->noext = 0;
676         codec_patch = NULL;
677
678         cname = NULL;
679         model = step = 0;
680         for (i = 0; ac97codecid[i].id; i++) {
681                 u_int32_t modelmask = 0xffffffff ^ ac97codecid[i].stepmask;
682                 if ((ac97codecid[i].id & modelmask) == (id & modelmask)) {
683                         codec->noext = ac97codecid[i].noext;
684                         codec_patch = ac97codecid[i].patch;
685                         cname = ac97codecid[i].name;
686                         model = (id & modelmask) & 0xff;
687                         step = (id & ~modelmask) & 0xff;
688                         break;
689                 }
690         }
691
692         vname = NULL;
693         for (i = 0; ac97vendorid[i].id; i++) {
694                 if (ac97vendorid[i].id == (id & 0xffffff00)) {
695                         vname = ac97vendorid[i].name;
696                         break;
697                 }
698         }
699
700         codec->extcaps = 0;
701         codec->extid = 0;
702         codec->extstat = 0;
703         if (!codec->noext) {
704                 i = ac97_rdcd(codec, AC97_REGEXT_ID);
705                 if (i != 0xffff) {
706                         codec->extcaps = i & 0x3fff;
707                         codec->extid =  (i & 0xc000) >> 14;
708                         codec->extstat = ac97_rdcd(codec, AC97_REGEXT_STAT) & AC97_EXTCAPS;
709                 }
710         }
711
712         for (i = 0; i < 32; i++) {
713                 codec->mix[i] = ac97mixtable_default[i];
714         }
715         ac97_fix_auxout(codec);
716         ac97_fix_tone(codec);
717         ac97_fix_volume(codec);
718         if (codec_patch)
719                 codec_patch(codec);
720
721         for (i = 0; i < 32; i++) {
722                 k = codec->noext? codec->mix[i].enable : 1;
723                 reg = codec->mix[i].reg;
724                 if (reg < 0)
725                         reg = -reg;
726                 if (k && reg) {
727                         j = old = ac97_rdcd(codec, reg);
728                         /*
729                          * Test for mute bit (except for AC97_MIX_TONE,
730                          * where we simply assume it as available).
731                          */
732                         if (codec->mix[i].mute) {
733                                 ac97_wrcd(codec, reg, j | 0x8000);
734                                 j = ac97_rdcd(codec, reg);
735                         } else
736                                 j |= 0x8000;
737                         if ((j & 0x8000)) {
738                                 /*
739                                  * Test whether the control width should be
740                                  * 4, 5 or 6 bit. For 5bit register, we should
741                                  * test it whether it's really 5 or 6bit. Leave
742                                  * 4bit register alone, because sometimes an
743                                  * attempt to write past 4th bit may cause
744                                  * incorrect result especially for AC97_MIX_BEEP
745                                  * (ac97 2.3).
746                                  */
747                                 bit = codec->mix[i].bits;
748                                 if (bit == 5)
749                                         bit++;
750                                 j = ((1 << bit) - 1) << codec->mix[i].ofs;
751                                 ac97_wrcd(codec, reg,
752                                         j | (codec->mix[i].mute ? 0x8000 : 0));
753                                 k = ac97_rdcd(codec, reg) & j;
754                                 k >>= codec->mix[i].ofs;
755                                 if (reg == AC97_MIX_TONE &&
756                                                         ((k & 0x0001) == 0x0000))
757                                         k >>= 1;
758                                 for (j = 0; k >> j; j++)
759                                         ;
760                                 if (j != 0) {
761 #if 0
762                                         device_printf(codec->dev, "%2d: [ac97_rdcd() = %d] [Testbit = %d] %d -> %d\n",
763                                                 i, k, bit, codec->mix[i].bits, j);
764 #endif
765                                         codec->mix[i].enable = 1;
766                                         codec->mix[i].bits = j;
767                                 } else if (reg == AC97_MIX_BEEP) {
768                                         /*
769                                          * Few codec such as CX20468-21 does
770                                          * have this control register, although
771                                          * the only usable part is the mute bit.
772                                          */
773                                         codec->mix[i].enable = 1;
774                                 } else
775                                         codec->mix[i].enable = 0;
776                         } else
777                                 codec->mix[i].enable = 0;
778                         ac97_wrcd(codec, reg, old);
779                 }
780 #if 0
781                 kprintf("mixch %d, en=%d, b=%d\n", i, codec->mix[i].enable, codec->mix[i].bits);
782 #endif
783         }
784
785         device_printf(codec->dev, "<%s>\n",
786                       ac97_hw_desc(codec->id, vname, cname, desc));
787
788         if (bootverbose) {
789                 if (codec->flags & AC97_F_RDCD_BUG)
790                         device_printf(codec->dev, "Buggy AC97 Codec: aggressive ac97_rdcd() workaround enabled\n");
791                 device_printf(codec->dev, "Codec features ");
792                 for (i = j = 0; i < 10; i++)
793                         if (codec->caps & (1 << i))
794                                 kprintf("%s%s", j++? ", " : "", ac97feature[i]);
795                 kprintf("%s%d bit master volume", j++? ", " : "", codec->mix[SOUND_MIXER_VOLUME].bits);
796                 kprintf("%s%s\n", j? ", " : "", ac97enhancement[codec->se]);
797
798                 if (codec->extcaps != 0 || codec->extid) {
799                         device_printf(codec->dev, "%s codec",
800                                       codec->extid? "Secondary" : "Primary");
801                         if (codec->extcaps)
802                                 kprintf(" extended features ");
803                         for (i = j = 0; i < 14; i++)
804                                 if (codec->extcaps & (1 << i))
805                                         kprintf("%s%s", j++? ", " : "", ac97extfeature[i]);
806                         kprintf("\n");
807                 }
808         }
809
810         i = 0;
811         while ((ac97_rdcd(codec, AC97_REG_POWER) & 2) == 0) {
812                 if (++i == 100) {
813                         device_printf(codec->dev, "ac97 codec reports dac not ready\n");
814                         break;
815                 }
816                 DELAY(1000);
817         }
818         if (bootverbose)
819                 device_printf(codec->dev, "ac97 codec dac ready count: %d\n", i);
820         snd_mtxunlock(codec->lock);
821         return 0;
822 }
823
824 static unsigned
825 ac97_reinitmixer(struct ac97_info *codec)
826 {
827         snd_mtxlock(codec->lock);
828         codec->count = AC97_INIT(codec->methods, codec->devinfo);
829         if (codec->count == 0) {
830                 device_printf(codec->dev, "ac97 codec init failed\n");
831                 snd_mtxunlock(codec->lock);
832                 return ENODEV;
833         }
834
835         ac97_wrcd(codec, AC97_REG_POWER, (codec->flags & AC97_F_EAPD_INV)? 0x8000 : 0x0000);
836         ac97_reset(codec);
837         ac97_wrcd(codec, AC97_REG_POWER, (codec->flags & AC97_F_EAPD_INV)? 0x8000 : 0x0000);
838
839         if (!codec->noext) {
840                 ac97_wrcd(codec, AC97_REGEXT_STAT, codec->extstat);
841                 if ((ac97_rdcd(codec, AC97_REGEXT_STAT) & AC97_EXTCAPS)
842                     != codec->extstat)
843                         device_printf(codec->dev, "ac97 codec failed to reset extended mode (%x, got %x)\n",
844                                       codec->extstat,
845                                       ac97_rdcd(codec, AC97_REGEXT_STAT) &
846                                       AC97_EXTCAPS);
847         }
848
849         if ((ac97_rdcd(codec, AC97_REG_POWER) & 2) == 0)
850                 device_printf(codec->dev, "ac97 codec reports dac not ready\n");
851         snd_mtxunlock(codec->lock);
852         return 0;
853 }
854
855 struct ac97_info *
856 ac97_create(device_t dev, void *devinfo, kobj_class_t cls)
857 {
858         struct ac97_info *codec;
859
860         codec = (struct ac97_info *)kmalloc(sizeof *codec, M_AC97, M_NOWAIT);
861         if (codec == NULL)
862                 return NULL;
863
864         ksnprintf(codec->name, AC97_NAMELEN, "%s:ac97", device_get_nameunit(dev));
865         codec->lock = snd_mtxcreate(codec->name, "ac97 codec");
866         codec->methods = kobj_create(cls, M_AC97, M_WAITOK);
867         if (codec->methods == NULL) {
868                 snd_mtxfree(codec->lock);
869                 kfree(codec, M_AC97);
870                 return NULL;
871         }
872
873         codec->dev = dev;
874         codec->devinfo = devinfo;
875         codec->flags = 0;
876         return codec;
877 }
878
879 void
880 ac97_destroy(struct ac97_info *codec)
881 {
882         if (codec->methods != NULL)
883                 kobj_delete(codec->methods, M_AC97);
884         snd_mtxfree(codec->lock);
885         kfree(codec, M_AC97);
886 }
887
888 void
889 ac97_setflags(struct ac97_info *codec, u_int32_t val)
890 {
891         codec->flags = val;
892 }
893
894 u_int32_t
895 ac97_getflags(struct ac97_info *codec)
896 {
897         return codec->flags;
898 }
899
900 /* -------------------------------------------------------------------- */
901
902 static int
903 ac97mix_init(struct snd_mixer *m)
904 {
905         struct ac97_info *codec = mix_getdevinfo(m);
906         u_int32_t i, mask;
907
908         if (codec == NULL)
909                 return -1;
910
911         if (ac97_initmixer(codec))
912                 return -1;
913
914         mask = 0;
915         for (i = 0; i < 32; i++)
916                 mask |= codec->mix[i].enable? 1 << i : 0;
917         mix_setdevs(m, mask);
918
919         mask = 0;
920         for (i = 0; i < 32; i++)
921                 mask |= codec->mix[i].recidx? 1 << i : 0;
922         mix_setrecdevs(m, mask);
923         return 0;
924 }
925
926 static int
927 ac97mix_uninit(struct snd_mixer *m)
928 {
929         struct ac97_info *codec = mix_getdevinfo(m);
930
931         if (codec == NULL)
932                 return -1;
933         /*
934         if (ac97_uninitmixer(codec))
935                 return -1;
936         */
937         ac97_destroy(codec);
938         return 0;
939 }
940
941 static int
942 ac97mix_reinit(struct snd_mixer *m)
943 {
944         struct ac97_info *codec = mix_getdevinfo(m);
945
946         if (codec == NULL)
947                 return -1;
948         return ac97_reinitmixer(codec);
949 }
950
951 static int
952 ac97mix_set(struct snd_mixer *m, unsigned dev, unsigned left, unsigned right)
953 {
954         struct ac97_info *codec = mix_getdevinfo(m);
955
956         if (codec == NULL)
957                 return -1;
958         return ac97_setmixer(codec, dev, left, right);
959 }
960
961 static int
962 ac97mix_setrecsrc(struct snd_mixer *m, u_int32_t src)
963 {
964         int i;
965         struct ac97_info *codec = mix_getdevinfo(m);
966
967         if (codec == NULL)
968                 return -1;
969         for (i = 0; i < SOUND_MIXER_NRDEVICES; i++)
970                 if ((src & (1 << i)) != 0)
971                         break;
972         return (ac97_setrecsrc(codec, i) == 0)? 1 << i : -1;
973 }
974
975 static kobj_method_t ac97mixer_methods[] = {
976         KOBJMETHOD(mixer_init,          ac97mix_init),
977         KOBJMETHOD(mixer_uninit,        ac97mix_uninit),
978         KOBJMETHOD(mixer_reinit,        ac97mix_reinit),
979         KOBJMETHOD(mixer_set,           ac97mix_set),
980         KOBJMETHOD(mixer_setrecsrc,     ac97mix_setrecsrc),
981         { 0, 0 }
982 };
983 MIXER_DECLARE(ac97mixer);
984
985 /* -------------------------------------------------------------------- */
986
987 kobj_class_t
988 ac97_getmixerclass(void)
989 {
990         return &ac97mixer_class;
991 }