Lines Matching +full:codec +full:- +full:0

1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause
40 static MALLOC_DEFINE(M_AC97, "ac97", "ac97 codec");
46 /* reg < 0 if inverted polarity */
48 unsigned ofs:4; /* offset (only if stereo=0) */
86 [SOUND_MIXER_VOLUME] = { AC97_MIX_MASTER, 5, 0, 1, 1, 6, 0, 1 },
87 [SOUND_MIXER_OGAIN] = { AC97_MIX_AUXOUT, 5, 0, 1, 1, 0, 0, 0 },
88 [SOUND_MIXER_PHONEOUT] = { AC97_MIX_MONO, 5, 0, 0, 1, 7, 0, 0 },
89 [SOUND_MIXER_BASS] = { AC97_MIX_TONE, 4, 8, 0, 0, 0, 1, 0 },
90 [SOUND_MIXER_TREBLE] = { AC97_MIX_TONE, 4, 0, 0, 0, 0, 1, 0 },
91 [SOUND_MIXER_PCM] = { AC97_MIX_PCM, 5, 0, 1, 1, 0, 0, 1 },
92 [SOUND_MIXER_SPEAKER] = { AC97_MIX_BEEP, 4, 1, 0, 1, 0, 0, 0 },
93 [SOUND_MIXER_LINE] = { AC97_MIX_LINE, 5, 0, 1, 1, 5, 0, 1 },
94 [SOUND_MIXER_PHONEIN] = { AC97_MIX_PHONE, 5, 0, 0, 1, 8, 0, 0 },
95 [SOUND_MIXER_MIC] = { AC97_MIX_MIC, 5, 0, 0, 1, 1, 1, 1 },
97 [SOUND_MIXER_IGAIN] = { -AC97_MIX_MIC, 1, 6, 0, 0, 0, 1, 1 },
98 [SOUND_MIXER_CD] = { AC97_MIX_CD, 5, 0, 1, 1, 2, 0, 1 },
99 [SOUND_MIXER_LINE1] = { AC97_MIX_AUX, 5, 0, 1, 1, 4, 0, 0 },
100 [SOUND_MIXER_VIDEO] = { AC97_MIX_VIDEO, 5, 0, 1, 1, 3, 0, 0 },
101 [SOUND_MIXER_RECLEV] = { -AC97_MIX_RGAIN, 4, 0, 1, 1, 0, 0, 1 }
105 { 0x41445300, "Analog Devices" },
106 { 0x414b4d00, "Asahi Kasei" },
107 { 0x414c4300, "Realtek" },
108 { 0x414c4700, "Avance Logic" },
109 { 0x43525900, "Cirrus Logic" },
110 { 0x434d4900, "C-Media Electronics" },
111 { 0x43585400, "Conexant" },
112 { 0x44543000, "Diamond Technology" },
113 { 0x454d4300, "eMicro" },
114 { 0x45838300, "ESS Technology" },
115 { 0x48525300, "Intersil" },
116 { 0x49434500, "ICEnsemble" },
117 { 0x49544500, "ITE, Inc." },
118 { 0x4e534300, "National Semiconductor" },
119 { 0x50534300, "Philips Semiconductor" },
120 { 0x83847600, "SigmaTel" },
121 { 0x53494c00, "Silicon Laboratories" },
122 { 0x54524100, "TriTech" },
123 { 0x54584e00, "Texas Instruments" },
124 { 0x56494100, "VIA Technologies" },
125 { 0x57454300, "Winbond" },
126 { 0x574d4c00, "Wolfson" },
127 { 0x594d4800, "Yamaha" },
133 { 0x01408300, "Creative" },
134 { 0x00000000, NULL }
144 { 0x41445303, 0x00, 0, "AD1819", 0 },
145 { 0x41445340, 0x00, 0, "AD1881", 0 },
146 { 0x41445348, 0x00, 0, "AD1881A", 0 },
147 { 0x41445360, 0x00, 0, "AD1885", 0 },
148 { 0x41445361, 0x00, 0, "AD1886", ad1886_patch },
149 { 0x41445362, 0x00, 0, "AD1887", 0 },
150 { 0x41445363, 0x00, 0, "AD1886A", 0 },
151 { 0x41445368, 0x00, 0, "AD1888", ad198x_patch },
152 { 0x41445370, 0x00, 0, "AD1980", ad198x_patch },
153 { 0x41445372, 0x00, 0, "AD1981A", 0 },
154 { 0x41445374, 0x00, 0, "AD1981B", ad1981b_patch },
155 { 0x41445375, 0x00, 0, "AD1985", ad198x_patch },
156 { 0x41445378, 0x00, 0, "AD1986", ad198x_patch },
157 { 0x414b4d00, 0x00, 1, "AK4540", 0 },
158 { 0x414b4d01, 0x00, 1, "AK4542", 0 },
159 { 0x414b4d02, 0x00, 1, "AK4543", 0 },
160 { 0x414b4d06, 0x00, 0, "AK4544A", 0 },
161 { 0x454b4d07, 0x00, 0, "AK4545", 0 },
162 { 0x414c4320, 0x0f, 0, "ALC100", 0 },
163 { 0x414c4730, 0x0f, 0, "ALC101", 0 },
164 { 0x414c4710, 0x0f, 0, "ALC200", 0 },
165 { 0x414c4740, 0x0f, 0, "ALC202", 0 },
166 { 0x414c4720, 0x0f, 0, "ALC650", 0 },
167 { 0x414c4752, 0x0f, 0, "ALC250", 0 },
168 { 0x414c4760, 0x0f, 0, "ALC655", alc655_patch },
169 { 0x414c4770, 0x0f, 0, "ALC203", 0 },
170 { 0x414c4780, 0x0f, 0, "ALC658", 0 },
171 { 0x414c4790, 0x0f, 0, "ALC850", 0 },
172 { 0x43525900, 0x07, 0, "CS4297", 0 },
173 { 0x43525910, 0x07, 0, "CS4297A", 0 },
174 { 0x43525920, 0x07, 0, "CS4294/98", 0 },
175 { 0x4352592d, 0x07, 0, "CS4294", 0 },
176 { 0x43525930, 0x07, 0, "CS4299", 0 },
177 { 0x43525940, 0x07, 0, "CS4201", 0 },
178 { 0x43525958, 0x07, 0, "CS4205", 0 },
179 { 0x43525960, 0x07, 0, "CS4291A", 0 },
180 { 0x434d4961, 0x00, 0, "CMI9739", cmi9739_patch },
181 { 0x434d4941, 0x00, 0, "CMI9738", 0 },
182 { 0x434d4978, 0x00, 0, "CMI9761", 0 },
183 { 0x434d4982, 0x00, 0, "CMI9761", 0 },
184 { 0x434d4983, 0x00, 0, "CMI9761", 0 },
185 { 0x43585421, 0x00, 0, "HSD11246", 0 },
186 { 0x43585428, 0x07, 0, "CX20468", 0 },
187 { 0x43585430, 0x00, 0, "CX20468-21", 0 },
188 { 0x44543000, 0x00, 0, "DT0398", 0 },
189 { 0x454d4323, 0x00, 0, "EM28023", 0 },
190 { 0x454d4328, 0x00, 0, "EM28028", 0 },
191 { 0x45838308, 0x00, 0, "ES1988", 0 }, /* Formerly ES1921(?) */
192 { 0x48525300, 0x00, 0, "HMP9701", 0 },
193 { 0x49434501, 0x00, 0, "ICE1230", 0 },
194 { 0x49434511, 0x00, 0, "ICE1232", 0 },
195 { 0x49434514, 0x00, 0, "ICE1232A", 0 },
196 { 0x49434551, 0x03, 0, "VT1616", 0 }, /* Via badged ICE */
197 { 0x49544520, 0x00, 0, "ITE2226E", 0 },
198 { 0x49544560, 0x07, 0, "ITE2646E", 0 }, /* XXX: patch needed */
199 { 0x4e534340, 0x00, 0, "LM4540", 0 }, /* Spec blank on revid */
200 { 0x4e534343, 0x00, 0, "LM4543", 0 }, /* Ditto */
201 { 0x4e534346, 0x00, 0, "LM4546A", 0 },
202 { 0x4e534348, 0x00, 0, "LM4548A", 0 },
203 { 0x4e534331, 0x00, 0, "LM4549", 0 },
204 { 0x4e534349, 0x00, 0, "LM4549A", 0 },
205 { 0x4e534350, 0x00, 0, "LM4550", 0 },
206 { 0x50534301, 0x00, 0, "UCB1510", 0 },
207 { 0x50534304, 0x00, 0, "UCB1400", 0 },
208 { 0x83847600, 0x00, 0, "STAC9700/83/84", 0 },
209 { 0x83847604, 0x00, 0, "STAC9701/03/04/05", 0 },
210 { 0x83847605, 0x00, 0, "STAC9704", 0 },
211 { 0x83847608, 0x00, 0, "STAC9708/11", 0 },
212 { 0x83847609, 0x00, 0, "STAC9721/23", 0 },
213 { 0x83847644, 0x00, 0, "STAC9744/45", 0 },
214 { 0x83847650, 0x00, 0, "STAC9750/51", 0 },
215 { 0x83847652, 0x00, 0, "STAC9752/53", 0 },
216 { 0x83847656, 0x00, 0, "STAC9756/57", 0 },
217 { 0x83847658, 0x00, 0, "STAC9758/59", 0 },
218 { 0x83847660, 0x00, 0, "STAC9760/61", 0 }, /* Extrapolated */
219 { 0x83847662, 0x00, 0, "STAC9762/63", 0 }, /* Extrapolated */
220 { 0x83847666, 0x00, 0, "STAC9766/67", 0 },
221 { 0x53494c22, 0x00, 0, "Si3036", 0 },
222 { 0x53494c23, 0x00, 0, "Si3038", 0 },
223 { 0x54524103, 0x00, 0, "TR28023", 0 }, /* Extrapolated */
224 { 0x54524106, 0x00, 0, "TR28026", 0 },
225 { 0x54524108, 0x00, 0, "TR28028", 0 },
226 { 0x54524123, 0x00, 0, "TR28602", 0 },
227 { 0x54524e03, 0x07, 0, "TLV320AIC27", 0 },
228 { 0x54584e20, 0x00, 0, "TLC320AD90", 0 },
229 { 0x56494161, 0x00, 0, "VIA1612A", 0 },
230 { 0x56494170, 0x00, 0, "VIA1617A", 0 },
231 { 0x574d4c00, 0x00, 0, "WM9701A", 0 },
232 { 0x574d4c03, 0x00, 0, "WM9703/4/7/8", 0 },
233 { 0x574d4c04, 0x00, 0, "WM9704Q", 0 },
234 { 0x574d4c05, 0x00, 0, "WM9705/10", 0 },
235 { 0x574d4d09, 0x00, 0, "WM9709", 0 },
236 { 0x574d4c12, 0x00, 0, "WM9711/12", 0 }, /* XXX: patch needed */
237 { 0x57454301, 0x00, 0, "W83971D", 0 },
238 { 0x594d4800, 0x00, 0, "YMF743", 0 },
239 { 0x594d4802, 0x00, 0, "YMF752", 0 },
240 { 0x594d4803, 0x00, 0, "YMF753", 0 },
242 * XXX This is a fluke, really! The real codec
246 { 0x01408384, 0x00, 0, "EV1938", 0 },
247 { 0, 0, 0, NULL, 0 }
316 ac97_rdcd(struct ac97_info *codec, int reg) in ac97_rdcd() argument
318 if (codec->flags & AC97_F_RDCD_BUG) { in ac97_rdcd()
321 i[0] = AC97_READ(codec->methods, codec->devinfo, reg); in ac97_rdcd()
322 i[1] = AC97_READ(codec->methods, codec->devinfo, reg); in ac97_rdcd()
323 while (i[0] != i[1] && j) in ac97_rdcd()
324 i[j-- & 1] = AC97_READ(codec->methods, codec->devinfo, reg); in ac97_rdcd()
327 return AC97_READ(codec->methods, codec->devinfo, reg); in ac97_rdcd()
331 ac97_wrcd(struct ac97_info *codec, int reg, u_int16_t val) in ac97_wrcd() argument
333 AC97_WRITE(codec->methods, codec->devinfo, reg, val); in ac97_wrcd()
337 ac97_reset(struct ac97_info *codec) in ac97_reset() argument
340 ac97_wrcd(codec, AC97_REG_RESET, 0); in ac97_reset()
341 for (i = 0; i < 500; i++) { in ac97_reset()
342 ps = ac97_rdcd(codec, AC97_REG_POWER) & AC97_POWER_STATUS; in ac97_reset()
347 device_printf(codec->dev, "AC97 reset timed out.\n"); in ac97_reset()
351 ac97_setrate(struct ac97_info *codec, int which, int rate) in ac97_setrate() argument
364 return -1; in ac97_setrate()
367 snd_mtxlock(codec->lock); in ac97_setrate()
368 if (rate != 0) { in ac97_setrate()
370 if (codec->extstat & AC97_EXTCAP_DRA) in ac97_setrate()
372 ac97_wrcd(codec, which, v); in ac97_setrate()
374 v = ac97_rdcd(codec, which); in ac97_setrate()
375 if (codec->extstat & AC97_EXTCAP_DRA) in ac97_setrate()
377 snd_mtxunlock(codec->lock); in ac97_setrate()
382 ac97_setextmode(struct ac97_info *codec, u_int16_t mode) in ac97_setextmode() argument
385 if ((mode & ~codec->extcaps) != 0) { in ac97_setextmode()
386 device_printf(codec->dev, "ac97 invalid mode set 0x%04x\n", in ac97_setextmode()
388 return -1; in ac97_setextmode()
390 snd_mtxlock(codec->lock); in ac97_setextmode()
391 ac97_wrcd(codec, AC97_REGEXT_STAT, mode); in ac97_setextmode()
392 codec->extstat = ac97_rdcd(codec, AC97_REGEXT_STAT) & AC97_EXTCAPS; in ac97_setextmode()
393 snd_mtxunlock(codec->lock); in ac97_setextmode()
394 return (mode == codec->extstat)? 0 : -1; in ac97_setextmode()
398 ac97_getextmode(struct ac97_info *codec) in ac97_getextmode() argument
400 return codec->extstat; in ac97_getextmode()
404 ac97_getextcaps(struct ac97_info *codec) in ac97_getextcaps() argument
406 return codec->extcaps; in ac97_getextcaps()
410 ac97_getcaps(struct ac97_info *codec) in ac97_getcaps() argument
412 return codec->caps; in ac97_getcaps()
416 ac97_getsubvendor(struct ac97_info *codec) in ac97_getsubvendor() argument
418 return codec->subvendor; in ac97_getsubvendor()
422 ac97_setrecsrc(struct ac97_info *codec, int channel) in ac97_setrecsrc() argument
424 struct ac97mixtable_entry *e = &codec->mix[channel]; in ac97_setrecsrc()
426 if (e->recidx > 0) { in ac97_setrecsrc()
427 int val = e->recidx - 1; in ac97_setrecsrc()
429 snd_mtxlock(codec->lock); in ac97_setrecsrc()
430 ac97_wrcd(codec, AC97_REG_RECSEL, val); in ac97_setrecsrc()
431 snd_mtxunlock(codec->lock); in ac97_setrecsrc()
432 return 0; in ac97_setrecsrc()
434 return -1; in ac97_setrecsrc()
438 ac97_setmixer(struct ac97_info *codec, unsigned channel, unsigned left, unsigned right) in ac97_setmixer() argument
440 struct ac97mixtable_entry *e = &codec->mix[channel]; in ac97_setmixer()
442 if (e->reg && e->enable && e->bits) { in ac97_setmixer()
445 reg = (e->reg >= 0) ? e->reg : -e->reg; /* AC97 register */ in ac97_setmixer()
446 max = (1 << e->bits) - 1; /* actual range */ in ac97_setmixer()
449 if (!e->stereo) in ac97_setmixer()
454 * then scale to 0..max-1 to compute the value to in ac97_setmixer()
455 * write into the codec, and scale back to 0..100 in ac97_setmixer()
458 if (e->reg > 0) { in ac97_setmixer()
459 left = 100 - left; in ac97_setmixer()
460 right = 100 - right; in ac97_setmixer()
471 if (e->reg > 0) { in ac97_setmixer()
472 left = 100 - left; in ac97_setmixer()
473 right = 100 - right; in ac97_setmixer()
478 * care of e->ofs (offset of control field). in ac97_setmixer()
480 if (e->ofs) { in ac97_setmixer()
482 val <<= e->ofs; in ac97_setmixer()
483 mask = (max << e->ofs); in ac97_setmixer()
491 if (e->mute == 1) { in ac97_setmixer()
493 if (left == 0 && right == 0) in ac97_setmixer()
500 snd_mtxlock(codec->lock); in ac97_setmixer()
501 if (e->mask) { in ac97_setmixer()
502 int cur = ac97_rdcd(codec, reg); in ac97_setmixer()
505 ac97_wrcd(codec, reg, val); in ac97_setmixer()
506 snd_mtxunlock(codec->lock); in ac97_setmixer()
509 return -1; in ac97_setmixer()
514 ac97_fix_auxout(struct ac97_info *codec) in ac97_fix_auxout() argument
519 * By default, The ac97 aux_out register (0x04) corresponds to OSS's in ac97_fix_auxout()
525 keep_ogain = ac97_rdcd(codec, AC97_MIX_AUXOUT) & 0x8000; in ac97_fix_auxout()
531 * 2. 4-Channel Out in ac97_fix_auxout()
536 if (codec->extcaps & AC97_EXTCAP_SDAC && in ac97_fix_auxout()
537 ac97_rdcd(codec, AC97_MIXEXT_SURROUND) == 0x8080) { in ac97_fix_auxout()
538 codec->mix[SOUND_MIXER_OGAIN].reg = AC97_MIXEXT_SURROUND; in ac97_fix_auxout()
542 if (keep_ogain == 0) { in ac97_fix_auxout()
543 bzero(&codec->mix[SOUND_MIXER_OGAIN], in ac97_fix_auxout()
544 sizeof(codec->mix[SOUND_MIXER_OGAIN])); in ac97_fix_auxout()
549 ac97_fix_tone(struct ac97_info *codec) in ac97_fix_tone() argument
555 switch (codec->id) { in ac97_fix_tone()
556 case 0x594d4800: /* YMF743 */ in ac97_fix_tone()
557 case 0x594d4803: /* YMF753 */ in ac97_fix_tone()
558 codec->caps |= AC97_CAP_TONE; in ac97_fix_tone()
559 codec->se |= 0x04; in ac97_fix_tone()
561 case 0x594d4802: /* YMF752 */ in ac97_fix_tone()
562 codec->se |= 0x04; in ac97_fix_tone()
569 if ((codec->caps & AC97_CAP_TONE) == 0) { in ac97_fix_tone()
570 bzero(&codec->mix[SOUND_MIXER_BASS], in ac97_fix_tone()
571 sizeof(codec->mix[SOUND_MIXER_BASS])); in ac97_fix_tone()
572 bzero(&codec->mix[SOUND_MIXER_TREBLE], in ac97_fix_tone()
573 sizeof(codec->mix[SOUND_MIXER_TREBLE])); in ac97_fix_tone()
581 sprintf(buf, "Unknown AC97 Codec (id = 0x%08x)", id); in ac97_hw_desc()
588 sprintf(buf, "%s %s AC97 Codec (id = 0x%08x)", vname, cname, id); in ac97_hw_desc()
590 sprintf(buf, "%s %s AC97 Codec", vname, cname); in ac97_hw_desc()
596 ac97_initmixer(struct ac97_info *codec) in ac97_initmixer() argument
606 snd_mtxlock(codec->lock); in ac97_initmixer()
607 codec->count = AC97_INIT(codec->methods, codec->devinfo); in ac97_initmixer()
608 if (codec->count == 0) { in ac97_initmixer()
609 device_printf(codec->dev, "ac97 codec init failed\n"); in ac97_initmixer()
610 snd_mtxunlock(codec->lock); in ac97_initmixer()
614 ac97_wrcd(codec, AC97_REG_POWER, (codec->flags & AC97_F_EAPD_INV)? 0x8000 : 0x0000); in ac97_initmixer()
615 ac97_reset(codec); in ac97_initmixer()
616 ac97_wrcd(codec, AC97_REG_POWER, (codec->flags & AC97_F_EAPD_INV)? 0x8000 : 0x0000); in ac97_initmixer()
618 i = ac97_rdcd(codec, AC97_REG_RESET); in ac97_initmixer()
619 j = ac97_rdcd(codec, AC97_REG_RESET); in ac97_initmixer()
620 k = ac97_rdcd(codec, AC97_REG_RESET); in ac97_initmixer()
622 * Let see if this codec can return consistent value. in ac97_initmixer()
627 codec->flags |= AC97_F_RDCD_BUG; in ac97_initmixer()
628 i = ac97_rdcd(codec, AC97_REG_RESET); in ac97_initmixer()
630 codec->caps = i & 0x03ff; in ac97_initmixer()
631 codec->se = (i & 0x7c00) >> 10; in ac97_initmixer()
633 id = (ac97_rdcd(codec, AC97_REG_ID1) << 16) | ac97_rdcd(codec, AC97_REG_ID2); in ac97_initmixer()
634 if (id == 0 || id == 0xffffffff) { in ac97_initmixer()
635 device_printf(codec->dev, "ac97 codec invalid or not present (id == %x)\n", id); in ac97_initmixer()
636 snd_mtxunlock(codec->lock); in ac97_initmixer()
640 pdev = codec->dev; in ac97_initmixer()
641 while (strcmp(device_get_name(device_get_parent(pdev)), "pci") != 0) { in ac97_initmixer()
642 /* find the top-level PCI device handler */ in ac97_initmixer()
645 codec->id = id; in ac97_initmixer()
646 codec->subvendor = (u_int32_t)pci_get_subdevice(pdev) << 16; in ac97_initmixer()
647 codec->subvendor |= (u_int32_t)pci_get_subvendor(pdev) & in ac97_initmixer()
648 0x0000ffff; in ac97_initmixer()
649 codec->noext = 0; in ac97_initmixer()
653 for (i = 0; ac97codecid[i].id; i++) { in ac97_initmixer()
654 u_int32_t modelmask = 0xffffffff ^ ac97codecid[i].stepmask; in ac97_initmixer()
656 codec->noext = ac97codecid[i].noext; in ac97_initmixer()
664 for (i = 0; ac97vendorid[i].id; i++) { in ac97_initmixer()
665 if (ac97vendorid[i].id == (id & 0xffffff00)) { in ac97_initmixer()
671 codec->extcaps = 0; in ac97_initmixer()
672 codec->extid = 0; in ac97_initmixer()
673 codec->extstat = 0; in ac97_initmixer()
674 if (!codec->noext) { in ac97_initmixer()
675 i = ac97_rdcd(codec, AC97_REGEXT_ID); in ac97_initmixer()
676 if (i != 0xffff) { in ac97_initmixer()
677 codec->extcaps = i & 0x3fff; in ac97_initmixer()
678 codec->extid = (i & 0xc000) >> 14; in ac97_initmixer()
679 codec->extstat = ac97_rdcd(codec, AC97_REGEXT_STAT) & AC97_EXTCAPS; in ac97_initmixer()
683 for (i = 0; i < AC97_MIXER_SIZE; i++) { in ac97_initmixer()
684 codec->mix[i] = ac97mixtable_default[i]; in ac97_initmixer()
686 ac97_fix_auxout(codec); in ac97_initmixer()
687 ac97_fix_tone(codec); in ac97_initmixer()
689 codec_patch(codec); in ac97_initmixer()
691 for (i = 0; i < AC97_MIXER_SIZE; i++) { in ac97_initmixer()
692 k = codec->noext? codec->mix[i].enable : 1; in ac97_initmixer()
693 reg = codec->mix[i].reg; in ac97_initmixer()
694 if (reg < 0) in ac97_initmixer()
695 reg = -reg; in ac97_initmixer()
697 j = old = ac97_rdcd(codec, reg); in ac97_initmixer()
702 if (codec->mix[i].mute) { in ac97_initmixer()
703 ac97_wrcd(codec, reg, j | 0x8000); in ac97_initmixer()
704 j = ac97_rdcd(codec, reg); in ac97_initmixer()
706 j |= 0x8000; in ac97_initmixer()
707 if ((j & 0x8000)) { in ac97_initmixer()
717 bit = codec->mix[i].bits; in ac97_initmixer()
720 j = ((1 << bit) - 1) << codec->mix[i].ofs; in ac97_initmixer()
721 ac97_wrcd(codec, reg, in ac97_initmixer()
722 j | (codec->mix[i].mute ? 0x8000 : 0)); in ac97_initmixer()
723 k = ac97_rdcd(codec, reg) & j; in ac97_initmixer()
724 k >>= codec->mix[i].ofs; in ac97_initmixer()
726 ((k & 0x0001) == 0x0000)) in ac97_initmixer()
728 for (j = 0; k >> j; j++) in ac97_initmixer()
730 if (j != 0) { in ac97_initmixer()
731 codec->mix[i].enable = 1; in ac97_initmixer()
732 codec->mix[i].bits = j; in ac97_initmixer()
735 * Few codec such as CX20468-21 does in ac97_initmixer()
739 codec->mix[i].enable = 1; in ac97_initmixer()
741 codec->mix[i].enable = 0; in ac97_initmixer()
743 codec->mix[i].enable = 0; in ac97_initmixer()
744 ac97_wrcd(codec, reg, old); in ac97_initmixer()
748 device_printf(codec->dev, "<%s>\n", in ac97_initmixer()
749 ac97_hw_desc(codec->id, vname, cname, desc)); in ac97_initmixer()
752 if (codec->flags & AC97_F_RDCD_BUG) in ac97_initmixer()
753 device_printf(codec->dev, "Buggy AC97 Codec: aggressive ac97_rdcd() workaround enabled\n"); in ac97_initmixer()
754 device_printf(codec->dev, "Codec features "); in ac97_initmixer()
755 for (i = j = 0; i < 10; i++) in ac97_initmixer()
756 if (codec->caps & (1 << i)) in ac97_initmixer()
758 printf("%s%d bit master volume", j++? ", " : "", codec->mix[SOUND_MIXER_VOLUME].bits); in ac97_initmixer()
759 printf("%s%s\n", j? ", " : "", ac97enhancement[codec->se]); in ac97_initmixer()
761 if (codec->extcaps != 0 || codec->extid) { in ac97_initmixer()
762 device_printf(codec->dev, "%s codec", in ac97_initmixer()
763 codec->extid? "Secondary" : "Primary"); in ac97_initmixer()
764 if (codec->extcaps) in ac97_initmixer()
766 for (i = j = 0; i < 14; i++) in ac97_initmixer()
767 if (codec->extcaps & (1 << i)) in ac97_initmixer()
773 i = 0; in ac97_initmixer()
774 while ((ac97_rdcd(codec, AC97_REG_POWER) & 2) == 0) { in ac97_initmixer()
776 device_printf(codec->dev, "ac97 codec reports dac not ready\n"); in ac97_initmixer()
782 device_printf(codec->dev, "ac97 codec dac ready count: %d\n", i); in ac97_initmixer()
783 snd_mtxunlock(codec->lock); in ac97_initmixer()
784 return 0; in ac97_initmixer()
788 ac97_reinitmixer(struct ac97_info *codec) in ac97_reinitmixer() argument
790 snd_mtxlock(codec->lock); in ac97_reinitmixer()
791 codec->count = AC97_INIT(codec->methods, codec->devinfo); in ac97_reinitmixer()
792 if (codec->count == 0) { in ac97_reinitmixer()
793 device_printf(codec->dev, "ac97 codec init failed\n"); in ac97_reinitmixer()
794 snd_mtxunlock(codec->lock); in ac97_reinitmixer()
798 ac97_wrcd(codec, AC97_REG_POWER, (codec->flags & AC97_F_EAPD_INV)? 0x8000 : 0x0000); in ac97_reinitmixer()
799 ac97_reset(codec); in ac97_reinitmixer()
800 ac97_wrcd(codec, AC97_REG_POWER, (codec->flags & AC97_F_EAPD_INV)? 0x8000 : 0x0000); in ac97_reinitmixer()
802 if (!codec->noext) { in ac97_reinitmixer()
803 ac97_wrcd(codec, AC97_REGEXT_STAT, codec->extstat); in ac97_reinitmixer()
804 if ((ac97_rdcd(codec, AC97_REGEXT_STAT) & AC97_EXTCAPS) in ac97_reinitmixer()
805 != codec->extstat) in ac97_reinitmixer()
806 device_printf(codec->dev, "ac97 codec failed to reset extended mode (%x, got %x)\n", in ac97_reinitmixer()
807 codec->extstat, in ac97_reinitmixer()
808 ac97_rdcd(codec, AC97_REGEXT_STAT) & in ac97_reinitmixer()
812 if ((ac97_rdcd(codec, AC97_REG_POWER) & 2) == 0) in ac97_reinitmixer()
813 device_printf(codec->dev, "ac97 codec reports dac not ready\n"); in ac97_reinitmixer()
814 snd_mtxunlock(codec->lock); in ac97_reinitmixer()
815 return 0; in ac97_reinitmixer()
821 struct ac97_info *codec; in ac97_create() local
824 codec = malloc(sizeof(*codec), M_AC97, M_WAITOK | M_ZERO); in ac97_create()
825 snprintf(codec->name, sizeof(codec->name), "%s:ac97", in ac97_create()
827 codec->lock = snd_mtxcreate(codec->name, "ac97 codec"); in ac97_create()
828 codec->methods = kobj_create(cls, M_AC97, M_WAITOK | M_ZERO); in ac97_create()
829 codec->dev = dev; in ac97_create()
830 codec->devinfo = devinfo; in ac97_create()
831 codec->flags = 0; in ac97_create()
834 "eapdinv", &i) == 0 && i != 0) in ac97_create()
835 codec->flags |= AC97_F_EAPD_INV; in ac97_create()
838 "softpcmvol", &i) == 0 && i != 0) in ac97_create()
841 return codec; in ac97_create()
845 ac97_destroy(struct ac97_info *codec) in ac97_destroy() argument
847 snd_mtxlock(codec->lock); in ac97_destroy()
848 if (codec->methods != NULL) in ac97_destroy()
849 kobj_delete(codec->methods, M_AC97); in ac97_destroy()
850 snd_mtxfree(codec->lock); in ac97_destroy()
851 free(codec, M_AC97); in ac97_destroy()
855 ac97_setflags(struct ac97_info *codec, u_int32_t val) in ac97_setflags() argument
857 codec->flags = val; in ac97_setflags()
861 ac97_getflags(struct ac97_info *codec) in ac97_getflags() argument
863 return codec->flags; in ac97_getflags()
867 ad1886_patch(struct ac97_info *codec) in ad1886_patch() argument
869 #define AC97_AD_JACK_SPDIF 0x72 in ad1886_patch()
876 ac97_wrcd(codec, AC97_AD_JACK_SPDIF, 0x0010); in ad1886_patch()
880 ad198x_patch(struct ac97_info *codec) in ad198x_patch() argument
882 switch (ac97_getsubvendor(codec)) { in ad198x_patch()
883 case 0x11931043: /* Not for ASUS A9T (probably else too). */ in ad198x_patch()
886 ac97_wrcd(codec, 0x76, ac97_rdcd(codec, 0x76) | 0x0420); in ad198x_patch()
892 ad1981b_patch(struct ac97_info *codec) in ad1981b_patch() argument
897 switch (ac97_getsubvendor(codec)) { in ad1981b_patch()
898 case 0x02d91014: /* IBM Thinkcentre */ in ad1981b_patch()
899 case 0x099c103c: /* HP nx6110 */ in ad1981b_patch()
900 ac97_wrcd(codec, AC97_AD_JACK_SPDIF, in ad1981b_patch()
901 ac97_rdcd(codec, AC97_AD_JACK_SPDIF) | 0x0800); in ad1981b_patch()
909 cmi9739_patch(struct ac97_info *codec) in cmi9739_patch() argument
915 switch (ac97_getsubvendor(codec)) { in cmi9739_patch()
916 case 0x18431043: /* ASUS W1000N */ in cmi9739_patch()
917 ac97_wrcd(codec, AC97_REG_POWER, 0x000f); in cmi9739_patch()
918 ac97_wrcd(codec, AC97_MIXEXT_CLFE, 0x0000); in cmi9739_patch()
919 ac97_wrcd(codec, 0x64, 0x7110); in cmi9739_patch()
927 alc655_patch(struct ac97_info *codec) in alc655_patch() argument
930 * MSI (Micro-Star International) specific EAPD quirk. in alc655_patch()
932 switch (ac97_getsubvendor(codec)) { in alc655_patch()
933 case 0x00611462: /* MSI S250 */ in alc655_patch()
934 case 0x01311462: /* MSI S270 */ in alc655_patch()
935 case 0x01611462: /* LG K1 Express */ in alc655_patch()
936 case 0x03511462: /* MSI L725 */ in alc655_patch()
937 ac97_wrcd(codec, 0x7a, ac97_rdcd(codec, 0x7a) & 0xfffd); in alc655_patch()
939 case 0x10ca1734: in alc655_patch()
946 ac97_wrcd(codec, 0x6a, ac97_rdcd(codec, 0x6a) | 0x0001); in alc655_patch()
953 /* -------------------------------------------------------------------- */
958 struct ac97_info *codec; in sysctl_hw_snd_ac97_eapd() local
959 int ea, inv, err = 0; in sysctl_hw_snd_ac97_eapd()
962 codec = oidp->oid_arg1; in sysctl_hw_snd_ac97_eapd()
963 if (codec == NULL || codec->id == 0 || codec->lock == NULL) in sysctl_hw_snd_ac97_eapd()
965 snd_mtxlock(codec->lock); in sysctl_hw_snd_ac97_eapd()
966 val = ac97_rdcd(codec, AC97_REG_POWER); in sysctl_hw_snd_ac97_eapd()
967 inv = (codec->flags & AC97_F_EAPD_INV) ? 0 : 1; in sysctl_hw_snd_ac97_eapd()
969 snd_mtxunlock(codec->lock); in sysctl_hw_snd_ac97_eapd()
970 err = sysctl_handle_int(oidp, &ea, 0, req); in sysctl_hw_snd_ac97_eapd()
971 if (err == 0 && req->newptr != NULL) { in sysctl_hw_snd_ac97_eapd()
972 if (ea != 0 && ea != 1) in sysctl_hw_snd_ac97_eapd()
975 snd_mtxlock(codec->lock); in sysctl_hw_snd_ac97_eapd()
976 ac97_wrcd(codec, AC97_REG_POWER, val ^ 0x8000); in sysctl_hw_snd_ac97_eapd()
977 snd_mtxunlock(codec->lock); in sysctl_hw_snd_ac97_eapd()
984 ac97_init_sysctl(struct ac97_info *codec) in ac97_init_sysctl() argument
988 if (codec == NULL || codec->dev == NULL) in ac97_init_sysctl()
990 snd_mtxlock(codec->lock); in ac97_init_sysctl()
991 orig = ac97_rdcd(codec, AC97_REG_POWER); in ac97_init_sysctl()
992 ac97_wrcd(codec, AC97_REG_POWER, orig ^ 0x8000); in ac97_init_sysctl()
993 val = ac97_rdcd(codec, AC97_REG_POWER); in ac97_init_sysctl()
994 ac97_wrcd(codec, AC97_REG_POWER, orig); in ac97_init_sysctl()
995 snd_mtxunlock(codec->lock); in ac97_init_sysctl()
996 if ((val & 0x8000) == (orig & 0x8000)) in ac97_init_sysctl()
998 SYSCTL_ADD_PROC(device_get_sysctl_ctx(codec->dev), in ac97_init_sysctl()
999 SYSCTL_CHILDREN(device_get_sysctl_tree(codec->dev)), in ac97_init_sysctl()
1002 codec, sizeof(codec), sysctl_hw_snd_ac97_eapd, in ac97_init_sysctl()
1009 struct ac97_info *codec = mix_getdevinfo(m); in ac97mix_init() local
1012 if (codec == NULL) in ac97mix_init()
1013 return -1; in ac97mix_init()
1015 if (ac97_initmixer(codec)) in ac97mix_init()
1016 return -1; in ac97mix_init()
1018 switch (codec->id) { in ac97mix_init()
1019 case 0x41445374: /* AD1981B */ in ac97mix_init()
1020 switch (codec->subvendor) { in ac97mix_init()
1021 case 0x02d91014: in ac97mix_init()
1029 mask = 0; in ac97mix_init()
1030 if (codec->mix[SOUND_MIXER_OGAIN].enable) in ac97mix_init()
1032 if (codec->mix[SOUND_MIXER_PHONEOUT].enable) in ac97mix_init()
1034 if (codec->mix[SOUND_MIXER_VOLUME].enable) in ac97mix_init()
1044 case 0x099c103c: in ac97mix_init()
1054 codec->mix[SOUND_MIXER_OGAIN].enable = 1; in ac97mix_init()
1055 codec->mix[SOUND_MIXER_PHONEOUT].enable = 1; in ac97mix_init()
1067 case 0x434d4941: /* CMI9738 */ in ac97mix_init()
1068 case 0x434d4961: /* CMI9739 */ in ac97mix_init()
1069 case 0x434d4978: /* CMI9761 */ in ac97mix_init()
1070 case 0x434d4982: /* CMI9761 */ in ac97mix_init()
1071 case 0x434d4983: /* CMI9761 */ in ac97mix_init()
1072 bzero(&codec->mix[SOUND_MIXER_PCM], in ac97mix_init()
1073 sizeof(codec->mix[SOUND_MIXER_PCM])); in ac97mix_init()
1074 pcm_setflags(codec->dev, pcm_getflags(codec->dev) | in ac97mix_init()
1082 if (pcm_getflags(codec->dev) & SD_F_SOFTPCMVOL) in ac97mix_init()
1083 ac97_wrcd(codec, AC97_MIX_PCM, 0); in ac97mix_init()
1085 mask = 0; in ac97mix_init()
1086 for (i = 0; i < AC97_MIXER_SIZE; i++) in ac97mix_init()
1087 mask |= codec->mix[i].enable? 1 << i : 0; in ac97mix_init()
1090 mask = 0; in ac97mix_init()
1091 for (i = 0; i < AC97_MIXER_SIZE; i++) in ac97mix_init()
1092 mask |= codec->mix[i].recidx? 1 << i : 0; in ac97mix_init()
1095 ac97_init_sysctl(codec); in ac97mix_init()
1097 return 0; in ac97mix_init()
1103 struct ac97_info *codec = mix_getdevinfo(m); in ac97mix_uninit() local
1105 if (codec == NULL) in ac97mix_uninit()
1106 return -1; in ac97mix_uninit()
1108 if (ac97_uninitmixer(codec)) in ac97mix_uninit()
1109 return -1; in ac97mix_uninit()
1111 ac97_destroy(codec); in ac97mix_uninit()
1112 return 0; in ac97mix_uninit()
1118 struct ac97_info *codec = mix_getdevinfo(m); in ac97mix_reinit() local
1120 if (codec == NULL) in ac97mix_reinit()
1121 return -1; in ac97mix_reinit()
1122 return ac97_reinitmixer(codec); in ac97mix_reinit()
1128 struct ac97_info *codec = mix_getdevinfo(m); in ac97mix_set() local
1130 if (codec == NULL || dev >= AC97_MIXER_SIZE) in ac97mix_set()
1131 return -1; in ac97mix_set()
1132 return ac97_setmixer(codec, dev, left, right); in ac97mix_set()
1139 struct ac97_info *codec = mix_getdevinfo(m); in ac97mix_setrecsrc() local
1141 if (codec == NULL) in ac97mix_setrecsrc()
1142 return -1; in ac97mix_setrecsrc()
1143 for (i = 0; i < AC97_MIXER_SIZE; i++) in ac97mix_setrecsrc()
1144 if ((src & (1 << i)) != 0) in ac97mix_setrecsrc()
1146 return (ac97_setrecsrc(codec, i) == 0)? 1U << i : 0xffffffffU; in ac97mix_setrecsrc()
1159 /* -------------------------------------------------------------------- */