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