Branch data Line data Source code
1 : : /*
2 : : * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
3 : : * Universal interface for Audio Codec '97
4 : : *
5 : : * For more details look to AC '97 component specification revision 2.2
6 : : * by Intel Corporation (http://developer.intel.com).
7 : : *
8 : : *
9 : : * This program is free software; you can redistribute it and/or modify
10 : : * it under the terms of the GNU General Public License as published by
11 : : * the Free Software Foundation; either version 2 of the License, or
12 : : * (at your option) any later version.
13 : : *
14 : : * This program is distributed in the hope that it will be useful,
15 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 : : * GNU General Public License for more details.
18 : : *
19 : : * You should have received a copy of the GNU General Public License
20 : : * along with this program; if not, write to the Free Software
21 : : * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 : : *
23 : : */
24 : :
25 : : #include <linux/delay.h>
26 : : #include <linux/init.h>
27 : : #include <linux/slab.h>
28 : : #include <linux/pci.h>
29 : : #include <linux/module.h>
30 : : #include <linux/mutex.h>
31 : : #include <sound/core.h>
32 : : #include <sound/pcm.h>
33 : : #include <sound/tlv.h>
34 : : #include <sound/ac97_codec.h>
35 : : #include <sound/asoundef.h>
36 : : #include <sound/initval.h>
37 : : #include "ac97_id.h"
38 : :
39 : : #include "ac97_patch.c"
40 : :
41 : : MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
42 : : MODULE_DESCRIPTION("Universal interface for Audio Codec '97");
43 : : MODULE_LICENSE("GPL");
44 : :
45 : : static bool enable_loopback;
46 : :
47 : : module_param(enable_loopback, bool, 0444);
48 : : MODULE_PARM_DESC(enable_loopback, "Enable AC97 ADC/DAC Loopback Control");
49 : :
50 : : #ifdef CONFIG_SND_AC97_POWER_SAVE
51 : : static int power_save = CONFIG_SND_AC97_POWER_SAVE_DEFAULT;
52 : : module_param(power_save, int, 0644);
53 : : MODULE_PARM_DESC(power_save, "Automatic power-saving timeout "
54 : : "(in second, 0 = disable).");
55 : : #endif
56 : : /*
57 : :
58 : : */
59 : :
60 : : struct ac97_codec_id {
61 : : unsigned int id;
62 : : unsigned int mask;
63 : : const char *name;
64 : : int (*patch)(struct snd_ac97 *ac97);
65 : : int (*mpatch)(struct snd_ac97 *ac97);
66 : : unsigned int flags;
67 : : };
68 : :
69 : : static const struct ac97_codec_id snd_ac97_codec_id_vendors[] = {
70 : : { 0x41445300, 0xffffff00, "Analog Devices", NULL, NULL },
71 : : { 0x414b4d00, 0xffffff00, "Asahi Kasei", NULL, NULL },
72 : : { 0x414c4300, 0xffffff00, "Realtek", NULL, NULL },
73 : : { 0x414c4700, 0xffffff00, "Realtek", NULL, NULL },
74 : : /*
75 : : * This is an _inofficial_ Aztech Labs entry
76 : : * (value might differ from unknown official Aztech ID),
77 : : * currently used by the AC97 emulation of the almost-AC97 PCI168 card.
78 : : */
79 : : { 0x415a5400, 0xffffff00, "Aztech Labs (emulated)", NULL, NULL },
80 : : { 0x434d4900, 0xffffff00, "C-Media Electronics", NULL, NULL },
81 : : { 0x43525900, 0xffffff00, "Cirrus Logic", NULL, NULL },
82 : : { 0x43585400, 0xffffff00, "Conexant", NULL, NULL },
83 : : { 0x44543000, 0xffffff00, "Diamond Technology", NULL, NULL },
84 : : { 0x454d4300, 0xffffff00, "eMicro", NULL, NULL },
85 : : { 0x45838300, 0xffffff00, "ESS Technology", NULL, NULL },
86 : : { 0x48525300, 0xffffff00, "Intersil", NULL, NULL },
87 : : { 0x49434500, 0xffffff00, "ICEnsemble", NULL, NULL },
88 : : { 0x49544500, 0xffffff00, "ITE Tech.Inc", NULL, NULL },
89 : : { 0x4e534300, 0xffffff00, "National Semiconductor", NULL, NULL },
90 : : { 0x50534300, 0xffffff00, "Philips", NULL, NULL },
91 : : { 0x53494c00, 0xffffff00, "Silicon Laboratory", NULL, NULL },
92 : : { 0x53544d00, 0xffffff00, "STMicroelectronics", NULL, NULL },
93 : : { 0x54524100, 0xffffff00, "TriTech", NULL, NULL },
94 : : { 0x54584e00, 0xffffff00, "Texas Instruments", NULL, NULL },
95 : : { 0x56494100, 0xffffff00, "VIA Technologies", NULL, NULL },
96 : : { 0x57454300, 0xffffff00, "Winbond", NULL, NULL },
97 : : { 0x574d4c00, 0xffffff00, "Wolfson", NULL, NULL },
98 : : { 0x594d4800, 0xffffff00, "Yamaha", NULL, NULL },
99 : : { 0x83847600, 0xffffff00, "SigmaTel", NULL, NULL },
100 : : { 0, 0, NULL, NULL, NULL }
101 : : };
102 : :
103 : : static const struct ac97_codec_id snd_ac97_codec_ids[] = {
104 : : { 0x41445303, 0xffffffff, "AD1819", patch_ad1819, NULL },
105 : : { 0x41445340, 0xffffffff, "AD1881", patch_ad1881, NULL },
106 : : { 0x41445348, 0xffffffff, "AD1881A", patch_ad1881, NULL },
107 : : { 0x41445360, 0xffffffff, "AD1885", patch_ad1885, NULL },
108 : : { 0x41445361, 0xffffffff, "AD1886", patch_ad1886, NULL },
109 : : { 0x41445362, 0xffffffff, "AD1887", patch_ad1881, NULL },
110 : : { 0x41445363, 0xffffffff, "AD1886A", patch_ad1881, NULL },
111 : : { 0x41445368, 0xffffffff, "AD1888", patch_ad1888, NULL },
112 : : { 0x41445370, 0xffffffff, "AD1980", patch_ad1980, NULL },
113 : : { 0x41445372, 0xffffffff, "AD1981A", patch_ad1981a, NULL },
114 : : { 0x41445374, 0xffffffff, "AD1981B", patch_ad1981b, NULL },
115 : : { 0x41445375, 0xffffffff, "AD1985", patch_ad1985, NULL },
116 : : { 0x41445378, 0xffffffff, "AD1986", patch_ad1986, NULL },
117 : : { 0x414b4d00, 0xffffffff, "AK4540", NULL, NULL },
118 : : { 0x414b4d01, 0xffffffff, "AK4542", NULL, NULL },
119 : : { 0x414b4d02, 0xffffffff, "AK4543", NULL, NULL },
120 : : { 0x414b4d06, 0xffffffff, "AK4544A", NULL, NULL },
121 : : { 0x414b4d07, 0xffffffff, "AK4545", NULL, NULL },
122 : : { 0x414c4300, 0xffffff00, "ALC100,100P", NULL, NULL },
123 : : { 0x414c4710, 0xfffffff0, "ALC200,200P", NULL, NULL },
124 : : { 0x414c4721, 0xffffffff, "ALC650D", NULL, NULL }, /* already patched */
125 : : { 0x414c4722, 0xffffffff, "ALC650E", NULL, NULL }, /* already patched */
126 : : { 0x414c4723, 0xffffffff, "ALC650F", NULL, NULL }, /* already patched */
127 : : { 0x414c4720, 0xfffffff0, "ALC650", patch_alc650, NULL },
128 : : { 0x414c4730, 0xffffffff, "ALC101", NULL, NULL },
129 : : { 0x414c4740, 0xfffffff0, "ALC202", NULL, NULL },
130 : : { 0x414c4750, 0xfffffff0, "ALC250", NULL, NULL },
131 : : { 0x414c4760, 0xfffffff0, "ALC655", patch_alc655, NULL },
132 : : { 0x414c4770, 0xfffffff0, "ALC203", patch_alc203, NULL },
133 : : { 0x414c4781, 0xffffffff, "ALC658D", NULL, NULL }, /* already patched */
134 : : { 0x414c4780, 0xfffffff0, "ALC658", patch_alc655, NULL },
135 : : { 0x414c4790, 0xfffffff0, "ALC850", patch_alc850, NULL },
136 : : { 0x415a5401, 0xffffffff, "AZF3328", patch_aztech_azf3328, NULL },
137 : : { 0x434d4941, 0xffffffff, "CMI9738", patch_cm9738, NULL },
138 : : { 0x434d4961, 0xffffffff, "CMI9739", patch_cm9739, NULL },
139 : : { 0x434d4969, 0xffffffff, "CMI9780", patch_cm9780, NULL },
140 : : { 0x434d4978, 0xffffffff, "CMI9761A", patch_cm9761, NULL },
141 : : { 0x434d4982, 0xffffffff, "CMI9761B", patch_cm9761, NULL },
142 : : { 0x434d4983, 0xffffffff, "CMI9761A+", patch_cm9761, NULL },
143 : : { 0x43525900, 0xfffffff8, "CS4297", NULL, NULL },
144 : : { 0x43525910, 0xfffffff8, "CS4297A", patch_cirrus_spdif, NULL },
145 : : { 0x43525920, 0xfffffff8, "CS4298", patch_cirrus_spdif, NULL },
146 : : { 0x43525928, 0xfffffff8, "CS4294", NULL, NULL },
147 : : { 0x43525930, 0xfffffff8, "CS4299", patch_cirrus_cs4299, NULL },
148 : : { 0x43525948, 0xfffffff8, "CS4201", NULL, NULL },
149 : : { 0x43525958, 0xfffffff8, "CS4205", patch_cirrus_spdif, NULL },
150 : : { 0x43525960, 0xfffffff8, "CS4291", NULL, NULL },
151 : : { 0x43525970, 0xfffffff8, "CS4202", NULL, NULL },
152 : : { 0x43585421, 0xffffffff, "HSD11246", NULL, NULL }, // SmartMC II
153 : : { 0x43585428, 0xfffffff8, "Cx20468", patch_conexant, NULL }, // SmartAMC fixme: the mask might be different
154 : : { 0x43585430, 0xffffffff, "Cx20468-31", patch_conexant, NULL },
155 : : { 0x43585431, 0xffffffff, "Cx20551", patch_cx20551, NULL },
156 : : { 0x44543031, 0xfffffff0, "DT0398", NULL, NULL },
157 : : { 0x454d4328, 0xffffffff, "EM28028", NULL, NULL }, // same as TR28028?
158 : : { 0x45838308, 0xffffffff, "ESS1988", NULL, NULL },
159 : : { 0x48525300, 0xffffff00, "HMP9701", NULL, NULL },
160 : : { 0x49434501, 0xffffffff, "ICE1230", NULL, NULL },
161 : : { 0x49434511, 0xffffffff, "ICE1232", NULL, NULL }, // alias VIA VT1611A?
162 : : { 0x49434514, 0xffffffff, "ICE1232A", NULL, NULL },
163 : : { 0x49434551, 0xffffffff, "VT1616", patch_vt1616, NULL },
164 : : { 0x49434552, 0xffffffff, "VT1616i", patch_vt1616, NULL }, // VT1616 compatible (chipset integrated)
165 : : { 0x49544520, 0xffffffff, "IT2226E", NULL, NULL },
166 : : { 0x49544561, 0xffffffff, "IT2646E", patch_it2646, NULL },
167 : : { 0x4e534300, 0xffffffff, "LM4540,43,45,46,48", NULL, NULL }, // only guess --jk
168 : : { 0x4e534331, 0xffffffff, "LM4549", NULL, NULL },
169 : : { 0x4e534350, 0xffffffff, "LM4550", patch_lm4550, NULL }, // volume wrap fix
170 : : { 0x50534304, 0xffffffff, "UCB1400", patch_ucb1400, NULL },
171 : : { 0x53494c20, 0xffffffe0, "Si3036,8", mpatch_si3036, mpatch_si3036, AC97_MODEM_PATCH },
172 : : { 0x53544d02, 0xffffffff, "ST7597", NULL, NULL },
173 : : { 0x54524102, 0xffffffff, "TR28022", NULL, NULL },
174 : : { 0x54524103, 0xffffffff, "TR28023", NULL, NULL },
175 : : { 0x54524106, 0xffffffff, "TR28026", NULL, NULL },
176 : : { 0x54524108, 0xffffffff, "TR28028", patch_tritech_tr28028, NULL }, // added by xin jin [07/09/99]
177 : : { 0x54524123, 0xffffffff, "TR28602", NULL, NULL }, // only guess --jk [TR28023 = eMicro EM28023 (new CT1297)]
178 : : { 0x54584e03, 0xffffffff, "TLV320AIC27", NULL, NULL },
179 : : { 0x54584e20, 0xffffffff, "TLC320AD9xC", NULL, NULL },
180 : : { 0x56494161, 0xffffffff, "VIA1612A", NULL, NULL }, // modified ICE1232 with S/PDIF
181 : : { 0x56494170, 0xffffffff, "VIA1617A", patch_vt1617a, NULL }, // modified VT1616 with S/PDIF
182 : : { 0x56494182, 0xffffffff, "VIA1618", patch_vt1618, NULL },
183 : : { 0x57454301, 0xffffffff, "W83971D", NULL, NULL },
184 : : { 0x574d4c00, 0xffffffff, "WM9701,WM9701A", NULL, NULL },
185 : : { 0x574d4C03, 0xffffffff, "WM9703,WM9707,WM9708,WM9717", patch_wolfson03, NULL},
186 : : { 0x574d4C04, 0xffffffff, "WM9704M,WM9704Q", patch_wolfson04, NULL},
187 : : { 0x574d4C05, 0xffffffff, "WM9705,WM9710", patch_wolfson05, NULL},
188 : : { 0x574d4C09, 0xffffffff, "WM9709", NULL, NULL},
189 : : { 0x574d4C12, 0xffffffff, "WM9711,WM9712,WM9715", patch_wolfson11, NULL},
190 : : { 0x574d4c13, 0xffffffff, "WM9713,WM9714", patch_wolfson13, NULL, AC97_DEFAULT_POWER_OFF},
191 : : { 0x594d4800, 0xffffffff, "YMF743", patch_yamaha_ymf743, NULL },
192 : : { 0x594d4802, 0xffffffff, "YMF752", NULL, NULL },
193 : : { 0x594d4803, 0xffffffff, "YMF753", patch_yamaha_ymf753, NULL },
194 : : { 0x83847600, 0xffffffff, "STAC9700,83,84", patch_sigmatel_stac9700, NULL },
195 : : { 0x83847604, 0xffffffff, "STAC9701,3,4,5", NULL, NULL },
196 : : { 0x83847605, 0xffffffff, "STAC9704", NULL, NULL },
197 : : { 0x83847608, 0xffffffff, "STAC9708,11", patch_sigmatel_stac9708, NULL },
198 : : { 0x83847609, 0xffffffff, "STAC9721,23", patch_sigmatel_stac9721, NULL },
199 : : { 0x83847644, 0xffffffff, "STAC9744", patch_sigmatel_stac9744, NULL },
200 : : { 0x83847650, 0xffffffff, "STAC9750,51", NULL, NULL }, // patch?
201 : : { 0x83847652, 0xffffffff, "STAC9752,53", NULL, NULL }, // patch?
202 : : { 0x83847656, 0xffffffff, "STAC9756,57", patch_sigmatel_stac9756, NULL },
203 : : { 0x83847658, 0xffffffff, "STAC9758,59", patch_sigmatel_stac9758, NULL },
204 : : { 0x83847666, 0xffffffff, "STAC9766,67", NULL, NULL }, // patch?
205 : : { 0, 0, NULL, NULL, NULL }
206 : : };
207 : :
208 : :
209 : : static void update_power_regs(struct snd_ac97 *ac97);
210 : : #ifdef CONFIG_SND_AC97_POWER_SAVE
211 : : #define ac97_is_power_save_mode(ac97) \
212 : : ((ac97->scaps & AC97_SCAP_POWER_SAVE) && power_save)
213 : : #else
214 : : #define ac97_is_power_save_mode(ac97) 0
215 : : #endif
216 : :
217 : :
218 : : /*
219 : : * I/O routines
220 : : */
221 : :
222 : 71 : static int snd_ac97_valid_reg(struct snd_ac97 *ac97, unsigned short reg)
223 : : {
224 : : /* filter some registers for buggy codecs */
225 [ - - - - : 71 : switch (ac97->id) {
- - + ]
226 : : case AC97_ID_ST_AC97_ID4:
227 [ # # ]: 0 : if (reg == 0x08)
228 : : return 0;
229 : : /* fall through */
230 : : case AC97_ID_ST7597:
231 [ # # ]: 0 : if (reg == 0x22 || reg == 0x7a)
232 : : return 1;
233 : : /* fall through */
234 : : case AC97_ID_AK4540:
235 : : case AC97_ID_AK4542:
236 [ # # ][ # # ]: 0 : if (reg <= 0x1c || reg == 0x20 || reg == 0x26 || reg >= 0x7c)
237 : : return 1;
238 : : return 0;
239 : : case AC97_ID_AD1819: /* AD1819 */
240 : : case AC97_ID_AD1881: /* AD1881 */
241 : : case AC97_ID_AD1881A: /* AD1881A */
242 [ # # ]: 0 : if (reg >= 0x3a && reg <= 0x6e) /* 0x59 */
243 : : return 0;
244 : : return 1;
245 : : case AC97_ID_AD1885: /* AD1885 */
246 : : case AC97_ID_AD1886: /* AD1886 */
247 : : case AC97_ID_AD1886A: /* AD1886A - !!verify!! --jk */
248 : : case AC97_ID_AD1887: /* AD1887 - !!verify!! --jk */
249 [ # # ]: 0 : if (reg == 0x5a)
250 : : return 1;
251 [ # # ]: 0 : if (reg >= 0x3c && reg <= 0x6e) /* 0x59 */
252 : : return 0;
253 : : return 1;
254 : : case AC97_ID_STAC9700:
255 : : case AC97_ID_STAC9704:
256 : : case AC97_ID_STAC9705:
257 : : case AC97_ID_STAC9708:
258 : : case AC97_ID_STAC9721:
259 : : case AC97_ID_STAC9744:
260 : : case AC97_ID_STAC9756:
261 [ # # ]: 0 : if (reg <= 0x3a || reg >= 0x5a)
262 : : return 1;
263 : : return 0;
264 : : }
265 : : return 1;
266 : : }
267 : :
268 : : /**
269 : : * snd_ac97_write - write a value on the given register
270 : : * @ac97: the ac97 instance
271 : : * @reg: the register to change
272 : : * @value: the value to set
273 : : *
274 : : * Writes a value on the given register. This will invoke the write
275 : : * callback directly after the register check.
276 : : * This function doesn't change the register cache unlike
277 : : * #snd_ca97_write_cache(), so use this only when you don't want to
278 : : * reflect the change to the suspend/resume state.
279 : : */
280 : 0 : void snd_ac97_write(struct snd_ac97 *ac97, unsigned short reg, unsigned short value)
281 : : {
282 [ # # ]: 0 : if (!snd_ac97_valid_reg(ac97, reg))
283 : 0 : return;
284 [ # # ]: 0 : if ((ac97->id & 0xffffff00) == AC97_ID_ALC100) {
285 : : /* Fix H/W bug of ALC100/100P */
286 [ # # ]: 0 : if (reg == AC97_MASTER || reg == AC97_HEADPHONE)
287 : 0 : ac97->bus->ops->write(ac97, AC97_RESET, 0); /* reset audio codec */
288 : : }
289 : 0 : ac97->bus->ops->write(ac97, reg, value);
290 : : }
291 : :
292 : : EXPORT_SYMBOL(snd_ac97_write);
293 : :
294 : : /**
295 : : * snd_ac97_read - read a value from the given register
296 : : *
297 : : * @ac97: the ac97 instance
298 : : * @reg: the register to read
299 : : *
300 : : * Reads a value from the given register. This will invoke the read
301 : : * callback directly after the register check.
302 : : *
303 : : * Return: The read value.
304 : : */
305 : 0 : unsigned short snd_ac97_read(struct snd_ac97 *ac97, unsigned short reg)
306 : : {
307 [ + - ]: 71 : if (!snd_ac97_valid_reg(ac97, reg))
308 : : return 0;
309 : 71 : return ac97->bus->ops->read(ac97, reg);
310 : : }
311 : :
312 : : /* read a register - return the cached value if already read */
313 : : static inline unsigned short snd_ac97_read_cache(struct snd_ac97 *ac97, unsigned short reg)
314 : : {
315 [ # # ][ # # ]: 0 : if (! test_bit(reg, ac97->reg_accessed)) {
[ # # # # ]
[ # # ]
[ # # # # ]
[ # # ]
316 : 0 : ac97->regs[reg] = ac97->bus->ops->read(ac97, reg);
317 : : // set_bit(reg, ac97->reg_accessed);
318 : : }
319 : 0 : return ac97->regs[reg];
320 : : }
321 : :
322 : : EXPORT_SYMBOL(snd_ac97_read);
323 : :
324 : : /**
325 : : * snd_ac97_write_cache - write a value on the given register and update the cache
326 : : * @ac97: the ac97 instance
327 : : * @reg: the register to change
328 : : * @value: the value to set
329 : : *
330 : : * Writes a value on the given register and updates the register
331 : : * cache. The cached values are used for the cached-read and the
332 : : * suspend/resume.
333 : : */
334 : 0 : void snd_ac97_write_cache(struct snd_ac97 *ac97, unsigned short reg, unsigned short value)
335 : : {
336 [ # # ]: 0 : if (!snd_ac97_valid_reg(ac97, reg))
337 : 0 : return;
338 : 0 : mutex_lock(&ac97->reg_mutex);
339 : 0 : ac97->regs[reg] = value;
340 : 0 : ac97->bus->ops->write(ac97, reg, value);
341 : 0 : set_bit(reg, ac97->reg_accessed);
342 : 0 : mutex_unlock(&ac97->reg_mutex);
343 : : }
344 : :
345 : : EXPORT_SYMBOL(snd_ac97_write_cache);
346 : :
347 : : /**
348 : : * snd_ac97_update - update the value on the given register
349 : : * @ac97: the ac97 instance
350 : : * @reg: the register to change
351 : : * @value: the value to set
352 : : *
353 : : * Compares the value with the register cache and updates the value
354 : : * only when the value is changed.
355 : : *
356 : : * Return: 1 if the value is changed, 0 if no change, or a negative
357 : : * code on failure.
358 : : */
359 : 0 : int snd_ac97_update(struct snd_ac97 *ac97, unsigned short reg, unsigned short value)
360 : : {
361 : : int change;
362 : :
363 [ # # ]: 0 : if (!snd_ac97_valid_reg(ac97, reg))
364 : : return -EINVAL;
365 : 0 : mutex_lock(&ac97->reg_mutex);
366 : 0 : change = ac97->regs[reg] != value;
367 [ # # ]: 0 : if (change) {
368 : 0 : ac97->regs[reg] = value;
369 : 0 : ac97->bus->ops->write(ac97, reg, value);
370 : : }
371 : 0 : set_bit(reg, ac97->reg_accessed);
372 : 0 : mutex_unlock(&ac97->reg_mutex);
373 : 0 : return change;
374 : : }
375 : :
376 : : EXPORT_SYMBOL(snd_ac97_update);
377 : :
378 : : /**
379 : : * snd_ac97_update_bits - update the bits on the given register
380 : : * @ac97: the ac97 instance
381 : : * @reg: the register to change
382 : : * @mask: the bit-mask to change
383 : : * @value: the value to set
384 : : *
385 : : * Updates the masked-bits on the given register only when the value
386 : : * is changed.
387 : : *
388 : : * Return: 1 if the bits are changed, 0 if no change, or a negative
389 : : * code on failure.
390 : : */
391 : 0 : int snd_ac97_update_bits(struct snd_ac97 *ac97, unsigned short reg, unsigned short mask, unsigned short value)
392 : : {
393 : : int change;
394 : :
395 [ # # ]: 0 : if (!snd_ac97_valid_reg(ac97, reg))
396 : : return -EINVAL;
397 : 0 : mutex_lock(&ac97->reg_mutex);
398 : 0 : change = snd_ac97_update_bits_nolock(ac97, reg, mask, value);
399 : 0 : mutex_unlock(&ac97->reg_mutex);
400 : 0 : return change;
401 : : }
402 : :
403 : : EXPORT_SYMBOL(snd_ac97_update_bits);
404 : :
405 : : /* no lock version - see snd_ac97_update_bits() */
406 : 0 : int snd_ac97_update_bits_nolock(struct snd_ac97 *ac97, unsigned short reg,
407 : : unsigned short mask, unsigned short value)
408 : : {
409 : : int change;
410 : : unsigned short old, new;
411 : :
412 : : old = snd_ac97_read_cache(ac97, reg);
413 : 0 : new = (old & ~mask) | (value & mask);
414 : 0 : change = old != new;
415 [ # # ]: 0 : if (change) {
416 : 0 : ac97->regs[reg] = new;
417 : 0 : ac97->bus->ops->write(ac97, reg, new);
418 : : }
419 : 0 : set_bit(reg, ac97->reg_accessed);
420 : 0 : return change;
421 : : }
422 : :
423 : 0 : static int snd_ac97_ad18xx_update_pcm_bits(struct snd_ac97 *ac97, int codec, unsigned short mask, unsigned short value)
424 : : {
425 : : int change;
426 : : unsigned short old, new, cfg;
427 : :
428 : 0 : mutex_lock(&ac97->page_mutex);
429 : 0 : old = ac97->spec.ad18xx.pcmreg[codec];
430 : 0 : new = (old & ~mask) | (value & mask);
431 : 0 : change = old != new;
432 [ # # ]: 0 : if (change) {
433 : 0 : mutex_lock(&ac97->reg_mutex);
434 : : cfg = snd_ac97_read_cache(ac97, AC97_AD_SERIAL_CFG);
435 : 0 : ac97->spec.ad18xx.pcmreg[codec] = new;
436 : : /* select single codec */
437 : 0 : ac97->bus->ops->write(ac97, AC97_AD_SERIAL_CFG,
438 : : (cfg & ~0x7000) |
439 : 0 : ac97->spec.ad18xx.unchained[codec] | ac97->spec.ad18xx.chained[codec]);
440 : : /* update PCM bits */
441 : 0 : ac97->bus->ops->write(ac97, AC97_PCM, new);
442 : : /* select all codecs */
443 : 0 : ac97->bus->ops->write(ac97, AC97_AD_SERIAL_CFG,
444 : : cfg | 0x7000);
445 : 0 : mutex_unlock(&ac97->reg_mutex);
446 : : }
447 : 0 : mutex_unlock(&ac97->page_mutex);
448 : 0 : return change;
449 : : }
450 : :
451 : : /*
452 : : * Controls
453 : : */
454 : :
455 : 0 : static int snd_ac97_info_enum_double(struct snd_kcontrol *kcontrol,
456 : : struct snd_ctl_elem_info *uinfo)
457 : : {
458 : 0 : struct ac97_enum *e = (struct ac97_enum *)kcontrol->private_value;
459 : :
460 : 0 : uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
461 [ # # ]: 0 : uinfo->count = e->shift_l == e->shift_r ? 1 : 2;
462 : 0 : uinfo->value.enumerated.items = e->mask;
463 : :
464 [ # # ]: 0 : if (uinfo->value.enumerated.item > e->mask - 1)
465 : 0 : uinfo->value.enumerated.item = e->mask - 1;
466 : 0 : strcpy(uinfo->value.enumerated.name, e->texts[uinfo->value.enumerated.item]);
467 : 0 : return 0;
468 : : }
469 : :
470 : 0 : static int snd_ac97_get_enum_double(struct snd_kcontrol *kcontrol,
471 : : struct snd_ctl_elem_value *ucontrol)
472 : : {
473 : 0 : struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
474 : 0 : struct ac97_enum *e = (struct ac97_enum *)kcontrol->private_value;
475 : : unsigned short val, bitmask;
476 : :
477 [ # # ]: 0 : for (bitmask = 1; bitmask < e->mask; bitmask <<= 1)
478 : : ;
479 : 0 : val = snd_ac97_read_cache(ac97, e->reg);
480 : 0 : ucontrol->value.enumerated.item[0] = (val >> e->shift_l) & (bitmask - 1);
481 [ # # ]: 0 : if (e->shift_l != e->shift_r)
482 : 0 : ucontrol->value.enumerated.item[1] = (val >> e->shift_r) & (bitmask - 1);
483 : :
484 : 0 : return 0;
485 : : }
486 : :
487 : 0 : static int snd_ac97_put_enum_double(struct snd_kcontrol *kcontrol,
488 : : struct snd_ctl_elem_value *ucontrol)
489 : : {
490 : 0 : struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
491 : 0 : struct ac97_enum *e = (struct ac97_enum *)kcontrol->private_value;
492 : : unsigned short val;
493 : : unsigned short mask, bitmask;
494 : :
495 [ # # ]: 0 : for (bitmask = 1; bitmask < e->mask; bitmask <<= 1)
496 : : ;
497 [ # # ]: 0 : if (ucontrol->value.enumerated.item[0] > e->mask - 1)
498 : : return -EINVAL;
499 : 0 : val = ucontrol->value.enumerated.item[0] << e->shift_l;
500 : 0 : mask = (bitmask - 1) << e->shift_l;
501 [ # # ]: 0 : if (e->shift_l != e->shift_r) {
502 [ # # ]: 0 : if (ucontrol->value.enumerated.item[1] > e->mask - 1)
503 : : return -EINVAL;
504 : 0 : val |= ucontrol->value.enumerated.item[1] << e->shift_r;
505 : 0 : mask |= (bitmask - 1) << e->shift_r;
506 : : }
507 : 0 : return snd_ac97_update_bits(ac97, e->reg, mask, val);
508 : : }
509 : :
510 : : /* save/restore ac97 v2.3 paging */
511 : 0 : static int snd_ac97_page_save(struct snd_ac97 *ac97, int reg, struct snd_kcontrol *kcontrol)
512 : : {
513 : : int page_save = -1;
514 [ # # ][ # # ]: 0 : if ((kcontrol->private_value & (1<<25)) &&
515 [ # # ]: 0 : (ac97->ext_id & AC97_EI_REV_MASK) >= AC97_EI_REV_23 &&
516 : 0 : (reg >= 0x60 && reg < 0x70)) {
517 : 0 : unsigned short page = (kcontrol->private_value >> 26) & 0x0f;
518 : 0 : mutex_lock(&ac97->page_mutex); /* lock paging */
519 : 0 : page_save = snd_ac97_read(ac97, AC97_INT_PAGING) & AC97_PAGE_MASK;
520 : 0 : snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, page);
521 : : }
522 : 0 : return page_save;
523 : : }
524 : :
525 : 0 : static void snd_ac97_page_restore(struct snd_ac97 *ac97, int page_save)
526 : : {
527 [ # # ]: 0 : if (page_save >= 0) {
528 : 0 : snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, page_save);
529 : 0 : mutex_unlock(&ac97->page_mutex); /* unlock paging */
530 : : }
531 : 0 : }
532 : :
533 : : /* volume and switch controls */
534 : 0 : static int snd_ac97_info_volsw(struct snd_kcontrol *kcontrol,
535 : : struct snd_ctl_elem_info *uinfo)
536 : : {
537 : 0 : int mask = (kcontrol->private_value >> 16) & 0xff;
538 : 0 : int shift = (kcontrol->private_value >> 8) & 0x0f;
539 : 0 : int rshift = (kcontrol->private_value >> 12) & 0x0f;
540 : :
541 [ # # ]: 0 : uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;
542 [ # # ]: 0 : uinfo->count = shift == rshift ? 1 : 2;
543 : 0 : uinfo->value.integer.min = 0;
544 : 0 : uinfo->value.integer.max = mask;
545 : 0 : return 0;
546 : : }
547 : :
548 : 0 : static int snd_ac97_get_volsw(struct snd_kcontrol *kcontrol,
549 : : struct snd_ctl_elem_value *ucontrol)
550 : : {
551 : 0 : struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
552 : 0 : int reg = kcontrol->private_value & 0xff;
553 : 0 : int shift = (kcontrol->private_value >> 8) & 0x0f;
554 : 0 : int rshift = (kcontrol->private_value >> 12) & 0x0f;
555 : 0 : int mask = (kcontrol->private_value >> 16) & 0xff;
556 : 0 : int invert = (kcontrol->private_value >> 24) & 0x01;
557 : : int page_save;
558 : :
559 : 0 : page_save = snd_ac97_page_save(ac97, reg, kcontrol);
560 : 0 : ucontrol->value.integer.value[0] = (snd_ac97_read_cache(ac97, reg) >> shift) & mask;
561 [ # # ]: 0 : if (shift != rshift)
562 : 0 : ucontrol->value.integer.value[1] = (snd_ac97_read_cache(ac97, reg) >> rshift) & mask;
563 [ # # ]: 0 : if (invert) {
564 : 0 : ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0];
565 [ # # ]: 0 : if (shift != rshift)
566 : 0 : ucontrol->value.integer.value[1] = mask - ucontrol->value.integer.value[1];
567 : : }
568 : 0 : snd_ac97_page_restore(ac97, page_save);
569 : 0 : return 0;
570 : : }
571 : :
572 : 0 : static int snd_ac97_put_volsw(struct snd_kcontrol *kcontrol,
573 : : struct snd_ctl_elem_value *ucontrol)
574 : : {
575 : 0 : struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
576 : 0 : int reg = kcontrol->private_value & 0xff;
577 : 0 : int shift = (kcontrol->private_value >> 8) & 0x0f;
578 : 0 : int rshift = (kcontrol->private_value >> 12) & 0x0f;
579 : 0 : int mask = (kcontrol->private_value >> 16) & 0xff;
580 : 0 : int invert = (kcontrol->private_value >> 24) & 0x01;
581 : : int err, page_save;
582 : : unsigned short val, val2, val_mask;
583 : :
584 : 0 : page_save = snd_ac97_page_save(ac97, reg, kcontrol);
585 : 0 : val = (ucontrol->value.integer.value[0] & mask);
586 [ # # ]: 0 : if (invert)
587 : 0 : val = mask - val;
588 : 0 : val_mask = mask << shift;
589 : 0 : val = val << shift;
590 [ # # ]: 0 : if (shift != rshift) {
591 : 0 : val2 = (ucontrol->value.integer.value[1] & mask);
592 [ # # ]: 0 : if (invert)
593 : 0 : val2 = mask - val2;
594 : 0 : val_mask |= mask << rshift;
595 : 0 : val |= val2 << rshift;
596 : : }
597 : 0 : err = snd_ac97_update_bits(ac97, reg, val_mask, val);
598 : 0 : snd_ac97_page_restore(ac97, page_save);
599 : : #ifdef CONFIG_SND_AC97_POWER_SAVE
600 : : /* check analog mixer power-down */
601 : : if ((val_mask & AC97_PD_EAPD) &&
602 : : (kcontrol->private_value & (1<<30))) {
603 : : if (val & AC97_PD_EAPD)
604 : : ac97->power_up &= ~(1 << (reg>>1));
605 : : else
606 : : ac97->power_up |= 1 << (reg>>1);
607 : : update_power_regs(ac97);
608 : : }
609 : : #endif
610 : 0 : return err;
611 : : }
612 : :
613 : : static const struct snd_kcontrol_new snd_ac97_controls_master_mono[2] = {
614 : : AC97_SINGLE("Master Mono Playback Switch", AC97_MASTER_MONO, 15, 1, 1),
615 : : AC97_SINGLE("Master Mono Playback Volume", AC97_MASTER_MONO, 0, 31, 1)
616 : : };
617 : :
618 : : static const struct snd_kcontrol_new snd_ac97_controls_tone[2] = {
619 : : AC97_SINGLE("Tone Control - Bass", AC97_MASTER_TONE, 8, 15, 1),
620 : : AC97_SINGLE("Tone Control - Treble", AC97_MASTER_TONE, 0, 15, 1)
621 : : };
622 : :
623 : : static const struct snd_kcontrol_new snd_ac97_controls_pc_beep[2] = {
624 : : AC97_SINGLE("Beep Playback Switch", AC97_PC_BEEP, 15, 1, 1),
625 : : AC97_SINGLE("Beep Playback Volume", AC97_PC_BEEP, 1, 15, 1)
626 : : };
627 : :
628 : : static const struct snd_kcontrol_new snd_ac97_controls_mic_boost =
629 : : AC97_SINGLE("Mic Boost (+20dB)", AC97_MIC, 6, 1, 0);
630 : :
631 : :
632 : : static const char* std_rec_sel[] = {"Mic", "CD", "Video", "Aux", "Line", "Mix", "Mix Mono", "Phone"};
633 : : static const char* std_3d_path[] = {"pre 3D", "post 3D"};
634 : : static const char* std_mix[] = {"Mix", "Mic"};
635 : : static const char* std_mic[] = {"Mic1", "Mic2"};
636 : :
637 : : static const struct ac97_enum std_enum[] = {
638 : : AC97_ENUM_DOUBLE(AC97_REC_SEL, 8, 0, 8, std_rec_sel),
639 : : AC97_ENUM_SINGLE(AC97_GENERAL_PURPOSE, 15, 2, std_3d_path),
640 : : AC97_ENUM_SINGLE(AC97_GENERAL_PURPOSE, 9, 2, std_mix),
641 : : AC97_ENUM_SINGLE(AC97_GENERAL_PURPOSE, 8, 2, std_mic),
642 : : };
643 : :
644 : : static const struct snd_kcontrol_new snd_ac97_control_capture_src =
645 : : AC97_ENUM("Capture Source", std_enum[0]);
646 : :
647 : : static const struct snd_kcontrol_new snd_ac97_control_capture_vol =
648 : : AC97_DOUBLE("Capture Volume", AC97_REC_GAIN, 8, 0, 15, 0);
649 : :
650 : : static const struct snd_kcontrol_new snd_ac97_controls_mic_capture[2] = {
651 : : AC97_SINGLE("Mic Capture Switch", AC97_REC_GAIN_MIC, 15, 1, 1),
652 : : AC97_SINGLE("Mic Capture Volume", AC97_REC_GAIN_MIC, 0, 15, 0)
653 : : };
654 : :
655 : : enum {
656 : : AC97_GENERAL_PCM_OUT = 0,
657 : : AC97_GENERAL_STEREO_ENHANCEMENT,
658 : : AC97_GENERAL_3D,
659 : : AC97_GENERAL_LOUDNESS,
660 : : AC97_GENERAL_MONO,
661 : : AC97_GENERAL_MIC,
662 : : AC97_GENERAL_LOOPBACK
663 : : };
664 : :
665 : : static const struct snd_kcontrol_new snd_ac97_controls_general[7] = {
666 : : AC97_ENUM("PCM Out Path & Mute", std_enum[1]),
667 : : AC97_SINGLE("Simulated Stereo Enhancement", AC97_GENERAL_PURPOSE, 14, 1, 0),
668 : : AC97_SINGLE("3D Control - Switch", AC97_GENERAL_PURPOSE, 13, 1, 0),
669 : : AC97_SINGLE("Loudness (bass boost)", AC97_GENERAL_PURPOSE, 12, 1, 0),
670 : : AC97_ENUM("Mono Output Select", std_enum[2]),
671 : : AC97_ENUM("Mic Select", std_enum[3]),
672 : : AC97_SINGLE("ADC/DAC Loopback", AC97_GENERAL_PURPOSE, 7, 1, 0)
673 : : };
674 : :
675 : : static const struct snd_kcontrol_new snd_ac97_controls_3d[2] = {
676 : : AC97_SINGLE("3D Control - Center", AC97_3D_CONTROL, 8, 15, 0),
677 : : AC97_SINGLE("3D Control - Depth", AC97_3D_CONTROL, 0, 15, 0)
678 : : };
679 : :
680 : : static const struct snd_kcontrol_new snd_ac97_controls_center[2] = {
681 : : AC97_SINGLE("Center Playback Switch", AC97_CENTER_LFE_MASTER, 7, 1, 1),
682 : : AC97_SINGLE("Center Playback Volume", AC97_CENTER_LFE_MASTER, 0, 31, 1)
683 : : };
684 : :
685 : : static const struct snd_kcontrol_new snd_ac97_controls_lfe[2] = {
686 : : AC97_SINGLE("LFE Playback Switch", AC97_CENTER_LFE_MASTER, 15, 1, 1),
687 : : AC97_SINGLE("LFE Playback Volume", AC97_CENTER_LFE_MASTER, 8, 31, 1)
688 : : };
689 : :
690 : : static const struct snd_kcontrol_new snd_ac97_control_eapd =
691 : : AC97_SINGLE("External Amplifier", AC97_POWERDOWN, 15, 1, 1);
692 : :
693 : : static const struct snd_kcontrol_new snd_ac97_controls_modem_switches[2] = {
694 : : AC97_SINGLE("Off-hook Switch", AC97_GPIO_STATUS, 0, 1, 0),
695 : : AC97_SINGLE("Caller ID Switch", AC97_GPIO_STATUS, 2, 1, 0)
696 : : };
697 : :
698 : : /* change the existing EAPD control as inverted */
699 : : static void set_inv_eapd(struct snd_ac97 *ac97, struct snd_kcontrol *kctl)
700 : : {
701 : 0 : kctl->private_value = AC97_SINGLE_VALUE(AC97_POWERDOWN, 15, 1, 0);
702 : 0 : snd_ac97_update_bits(ac97, AC97_POWERDOWN, (1<<15), (1<<15)); /* EAPD up */
703 : 0 : ac97->scaps |= AC97_SCAP_INV_EAPD;
704 : : }
705 : :
706 : 0 : static int snd_ac97_spdif_mask_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
707 : : {
708 : 0 : uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
709 : 0 : uinfo->count = 1;
710 : 0 : return 0;
711 : : }
712 : :
713 : 0 : static int snd_ac97_spdif_cmask_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
714 : : {
715 : 0 : ucontrol->value.iec958.status[0] = IEC958_AES0_PROFESSIONAL |
716 : : IEC958_AES0_NONAUDIO |
717 : : IEC958_AES0_CON_EMPHASIS_5015 |
718 : : IEC958_AES0_CON_NOT_COPYRIGHT;
719 : 0 : ucontrol->value.iec958.status[1] = IEC958_AES1_CON_CATEGORY |
720 : : IEC958_AES1_CON_ORIGINAL;
721 : 0 : ucontrol->value.iec958.status[3] = IEC958_AES3_CON_FS;
722 : 0 : return 0;
723 : : }
724 : :
725 : 0 : static int snd_ac97_spdif_pmask_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
726 : : {
727 : : /* FIXME: AC'97 spec doesn't say which bits are used for what */
728 : 0 : ucontrol->value.iec958.status[0] = IEC958_AES0_PROFESSIONAL |
729 : : IEC958_AES0_NONAUDIO |
730 : : IEC958_AES0_PRO_FS |
731 : : IEC958_AES0_PRO_EMPHASIS_5015;
732 : 0 : return 0;
733 : : }
734 : :
735 : 0 : static int snd_ac97_spdif_default_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
736 : : {
737 : 0 : struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
738 : :
739 : 0 : mutex_lock(&ac97->reg_mutex);
740 : 0 : ucontrol->value.iec958.status[0] = ac97->spdif_status & 0xff;
741 : 0 : ucontrol->value.iec958.status[1] = (ac97->spdif_status >> 8) & 0xff;
742 : 0 : ucontrol->value.iec958.status[2] = (ac97->spdif_status >> 16) & 0xff;
743 : 0 : ucontrol->value.iec958.status[3] = (ac97->spdif_status >> 24) & 0xff;
744 : 0 : mutex_unlock(&ac97->reg_mutex);
745 : 0 : return 0;
746 : : }
747 : :
748 : 0 : static int snd_ac97_spdif_default_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
749 : : {
750 : 0 : struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
751 : : unsigned int new = 0;
752 : : unsigned short val = 0;
753 : : int change;
754 : :
755 : 0 : new = val = ucontrol->value.iec958.status[0] & (IEC958_AES0_PROFESSIONAL|IEC958_AES0_NONAUDIO);
756 [ # # ]: 0 : if (ucontrol->value.iec958.status[0] & IEC958_AES0_PROFESSIONAL) {
757 : 0 : new |= ucontrol->value.iec958.status[0] & (IEC958_AES0_PRO_FS|IEC958_AES0_PRO_EMPHASIS_5015);
758 [ # # # # ]: 0 : switch (new & IEC958_AES0_PRO_FS) {
759 : : case IEC958_AES0_PRO_FS_44100: val |= 0<<12; break;
760 : 0 : case IEC958_AES0_PRO_FS_48000: val |= 2<<12; break;
761 : 0 : case IEC958_AES0_PRO_FS_32000: val |= 3<<12; break;
762 : 0 : default: val |= 1<<12; break;
763 : : }
764 [ # # ]: 0 : if ((new & IEC958_AES0_PRO_EMPHASIS) == IEC958_AES0_PRO_EMPHASIS_5015)
765 : 0 : val |= 1<<3;
766 : : } else {
767 : 0 : new |= ucontrol->value.iec958.status[0] & (IEC958_AES0_CON_EMPHASIS_5015|IEC958_AES0_CON_NOT_COPYRIGHT);
768 : 0 : new |= ((ucontrol->value.iec958.status[1] & (IEC958_AES1_CON_CATEGORY|IEC958_AES1_CON_ORIGINAL)) << 8);
769 : 0 : new |= ((ucontrol->value.iec958.status[3] & IEC958_AES3_CON_FS) << 24);
770 [ # # ]: 0 : if ((new & IEC958_AES0_CON_EMPHASIS) == IEC958_AES0_CON_EMPHASIS_5015)
771 : 0 : val |= 1<<3;
772 [ # # ]: 0 : if (!(new & IEC958_AES0_CON_NOT_COPYRIGHT))
773 : 0 : val |= 1<<2;
774 : 0 : val |= ((new >> 8) & 0xff) << 4; // category + original
775 [ # # # # ]: 0 : switch ((new >> 24) & 0xff) {
776 : : case IEC958_AES3_CON_FS_44100: val |= 0<<12; break;
777 : 0 : case IEC958_AES3_CON_FS_48000: val |= 2<<12; break;
778 : 0 : case IEC958_AES3_CON_FS_32000: val |= 3<<12; break;
779 : 0 : default: val |= 1<<12; break;
780 : : }
781 : : }
782 : :
783 : 0 : mutex_lock(&ac97->reg_mutex);
784 : 0 : change = ac97->spdif_status != new;
785 : 0 : ac97->spdif_status = new;
786 : :
787 [ # # ]: 0 : if (ac97->flags & AC97_CS_SPDIF) {
788 : 0 : int x = (val >> 12) & 0x03;
789 [ # # # ]: 0 : switch (x) {
790 : : case 0: x = 1; break; // 44.1
791 : 0 : case 2: x = 0; break; // 48.0
792 : 0 : default: x = 0; break; // illegal.
793 : : }
794 : 0 : change |= snd_ac97_update_bits_nolock(ac97, AC97_CSR_SPDIF, 0x3fff, ((val & 0xcfff) | (x << 12)));
795 [ # # ]: 0 : } else if (ac97->flags & AC97_CX_SPDIF) {
796 : : int v;
797 [ # # ]: 0 : v = new & (IEC958_AES0_CON_EMPHASIS_5015|IEC958_AES0_CON_NOT_COPYRIGHT) ? 0 : AC97_CXR_COPYRGT;
798 : 0 : v |= new & IEC958_AES0_NONAUDIO ? AC97_CXR_SPDIF_AC3 : AC97_CXR_SPDIF_PCM;
799 : 0 : change |= snd_ac97_update_bits_nolock(ac97, AC97_CXR_AUDIO_MISC,
800 : : AC97_CXR_SPDIF_MASK | AC97_CXR_COPYRGT,
801 : : v);
802 [ # # ]: 0 : } else if (ac97->id == AC97_ID_YMF743) {
803 : 0 : change |= snd_ac97_update_bits_nolock(ac97,
804 : : AC97_YMF7X3_DIT_CTRL,
805 : : 0xff38,
806 : 0 : ((val << 4) & 0xff00) |
807 : 0 : ((val << 2) & 0x0038));
808 : : } else {
809 : : unsigned short extst = snd_ac97_read_cache(ac97, AC97_EXTENDED_STATUS);
810 : 0 : snd_ac97_update_bits_nolock(ac97, AC97_EXTENDED_STATUS, AC97_EA_SPDIF, 0); /* turn off */
811 : :
812 : 0 : change |= snd_ac97_update_bits_nolock(ac97, AC97_SPDIF, 0x3fff, val);
813 [ # # ]: 0 : if (extst & AC97_EA_SPDIF) {
814 : 0 : snd_ac97_update_bits_nolock(ac97, AC97_EXTENDED_STATUS, AC97_EA_SPDIF, AC97_EA_SPDIF); /* turn on again */
815 : : }
816 : : }
817 : 0 : mutex_unlock(&ac97->reg_mutex);
818 : :
819 : 0 : return change;
820 : : }
821 : :
822 : 0 : static int snd_ac97_put_spsa(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
823 : : {
824 : 0 : struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
825 : 0 : int reg = kcontrol->private_value & 0xff;
826 : 0 : int shift = (kcontrol->private_value >> 8) & 0xff;
827 : 0 : int mask = (kcontrol->private_value >> 16) & 0xff;
828 : : // int invert = (kcontrol->private_value >> 24) & 0xff;
829 : : unsigned short value, old, new;
830 : : int change;
831 : :
832 : 0 : value = (ucontrol->value.integer.value[0] & mask);
833 : :
834 : 0 : mutex_lock(&ac97->reg_mutex);
835 : 0 : mask <<= shift;
836 : 0 : value <<= shift;
837 : 0 : old = snd_ac97_read_cache(ac97, reg);
838 : 0 : new = (old & ~mask) | value;
839 : 0 : change = old != new;
840 : :
841 [ # # ]: 0 : if (change) {
842 : : unsigned short extst = snd_ac97_read_cache(ac97, AC97_EXTENDED_STATUS);
843 : 0 : snd_ac97_update_bits_nolock(ac97, AC97_EXTENDED_STATUS, AC97_EA_SPDIF, 0); /* turn off */
844 : 0 : change = snd_ac97_update_bits_nolock(ac97, reg, mask, value);
845 [ # # ]: 0 : if (extst & AC97_EA_SPDIF)
846 : 0 : snd_ac97_update_bits_nolock(ac97, AC97_EXTENDED_STATUS, AC97_EA_SPDIF, AC97_EA_SPDIF); /* turn on again */
847 : : }
848 : 0 : mutex_unlock(&ac97->reg_mutex);
849 : 0 : return change;
850 : : }
851 : :
852 : : static const struct snd_kcontrol_new snd_ac97_controls_spdif[5] = {
853 : : {
854 : : .access = SNDRV_CTL_ELEM_ACCESS_READ,
855 : : .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
856 : : .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,CON_MASK),
857 : : .info = snd_ac97_spdif_mask_info,
858 : : .get = snd_ac97_spdif_cmask_get,
859 : : },
860 : : {
861 : : .access = SNDRV_CTL_ELEM_ACCESS_READ,
862 : : .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
863 : : .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,PRO_MASK),
864 : : .info = snd_ac97_spdif_mask_info,
865 : : .get = snd_ac97_spdif_pmask_get,
866 : : },
867 : : {
868 : : .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
869 : : .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
870 : : .info = snd_ac97_spdif_mask_info,
871 : : .get = snd_ac97_spdif_default_get,
872 : : .put = snd_ac97_spdif_default_put,
873 : : },
874 : :
875 : : AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",PLAYBACK,SWITCH),AC97_EXTENDED_STATUS, 2, 1, 0),
876 : : {
877 : : .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
878 : : .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "AC97-SPSA",
879 : : .info = snd_ac97_info_volsw,
880 : : .get = snd_ac97_get_volsw,
881 : : .put = snd_ac97_put_spsa,
882 : : .private_value = AC97_SINGLE_VALUE(AC97_EXTENDED_STATUS, 4, 3, 0)
883 : : },
884 : : };
885 : :
886 : : #define AD18XX_PCM_BITS(xname, codec, lshift, rshift, mask) \
887 : : { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .info = snd_ac97_ad18xx_pcm_info_bits, \
888 : : .get = snd_ac97_ad18xx_pcm_get_bits, .put = snd_ac97_ad18xx_pcm_put_bits, \
889 : : .private_value = (codec) | ((lshift) << 8) | ((rshift) << 12) | ((mask) << 16) }
890 : :
891 : 0 : static int snd_ac97_ad18xx_pcm_info_bits(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
892 : : {
893 : 0 : struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
894 : 0 : int mask = (kcontrol->private_value >> 16) & 0x0f;
895 : 0 : int lshift = (kcontrol->private_value >> 8) & 0x0f;
896 : 0 : int rshift = (kcontrol->private_value >> 12) & 0x0f;
897 : :
898 [ # # ]: 0 : uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;
899 [ # # ][ # # ]: 0 : if (lshift != rshift && (ac97->flags & AC97_STEREO_MUTES))
900 : 0 : uinfo->count = 2;
901 : : else
902 : 0 : uinfo->count = 1;
903 : 0 : uinfo->value.integer.min = 0;
904 : 0 : uinfo->value.integer.max = mask;
905 : 0 : return 0;
906 : : }
907 : :
908 : 0 : static int snd_ac97_ad18xx_pcm_get_bits(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
909 : : {
910 : 0 : struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
911 : 0 : int codec = kcontrol->private_value & 3;
912 : 0 : int lshift = (kcontrol->private_value >> 8) & 0x0f;
913 : 0 : int rshift = (kcontrol->private_value >> 12) & 0x0f;
914 : 0 : int mask = (kcontrol->private_value >> 16) & 0xff;
915 : :
916 : 0 : ucontrol->value.integer.value[0] = mask - ((ac97->spec.ad18xx.pcmreg[codec] >> lshift) & mask);
917 [ # # ][ # # ]: 0 : if (lshift != rshift && (ac97->flags & AC97_STEREO_MUTES))
918 : 0 : ucontrol->value.integer.value[1] = mask - ((ac97->spec.ad18xx.pcmreg[codec] >> rshift) & mask);
919 : 0 : return 0;
920 : : }
921 : :
922 : 0 : static int snd_ac97_ad18xx_pcm_put_bits(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
923 : : {
924 : 0 : struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
925 : 0 : int codec = kcontrol->private_value & 3;
926 : 0 : int lshift = (kcontrol->private_value >> 8) & 0x0f;
927 : 0 : int rshift = (kcontrol->private_value >> 12) & 0x0f;
928 : 0 : int mask = (kcontrol->private_value >> 16) & 0xff;
929 : : unsigned short val, valmask;
930 : :
931 : 0 : val = (mask - (ucontrol->value.integer.value[0] & mask)) << lshift;
932 : 0 : valmask = mask << lshift;
933 [ # # ][ # # ]: 0 : if (lshift != rshift && (ac97->flags & AC97_STEREO_MUTES)) {
934 : 0 : val |= (mask - (ucontrol->value.integer.value[1] & mask)) << rshift;
935 : 0 : valmask |= mask << rshift;
936 : : }
937 : 0 : return snd_ac97_ad18xx_update_pcm_bits(ac97, codec, valmask, val);
938 : : }
939 : :
940 : : #define AD18XX_PCM_VOLUME(xname, codec) \
941 : : { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .info = snd_ac97_ad18xx_pcm_info_volume, \
942 : : .get = snd_ac97_ad18xx_pcm_get_volume, .put = snd_ac97_ad18xx_pcm_put_volume, \
943 : : .private_value = codec }
944 : :
945 : 0 : static int snd_ac97_ad18xx_pcm_info_volume(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
946 : : {
947 : 0 : uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
948 : 0 : uinfo->count = 2;
949 : 0 : uinfo->value.integer.min = 0;
950 : 0 : uinfo->value.integer.max = 31;
951 : 0 : return 0;
952 : : }
953 : :
954 : 0 : static int snd_ac97_ad18xx_pcm_get_volume(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
955 : : {
956 : 0 : struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
957 : 0 : int codec = kcontrol->private_value & 3;
958 : :
959 : 0 : mutex_lock(&ac97->page_mutex);
960 : 0 : ucontrol->value.integer.value[0] = 31 - ((ac97->spec.ad18xx.pcmreg[codec] >> 0) & 31);
961 : 0 : ucontrol->value.integer.value[1] = 31 - ((ac97->spec.ad18xx.pcmreg[codec] >> 8) & 31);
962 : 0 : mutex_unlock(&ac97->page_mutex);
963 : 0 : return 0;
964 : : }
965 : :
966 : 0 : static int snd_ac97_ad18xx_pcm_put_volume(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
967 : : {
968 : 0 : struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
969 : 0 : int codec = kcontrol->private_value & 3;
970 : : unsigned short val1, val2;
971 : :
972 : 0 : val1 = 31 - (ucontrol->value.integer.value[0] & 31);
973 : 0 : val2 = 31 - (ucontrol->value.integer.value[1] & 31);
974 : 0 : return snd_ac97_ad18xx_update_pcm_bits(ac97, codec, 0x1f1f, (val1 << 8) | val2);
975 : : }
976 : :
977 : : static const struct snd_kcontrol_new snd_ac97_controls_ad18xx_pcm[2] = {
978 : : AD18XX_PCM_BITS("PCM Playback Switch", 0, 15, 7, 1),
979 : : AD18XX_PCM_VOLUME("PCM Playback Volume", 0)
980 : : };
981 : :
982 : : static const struct snd_kcontrol_new snd_ac97_controls_ad18xx_surround[2] = {
983 : : AD18XX_PCM_BITS("Surround Playback Switch", 1, 15, 7, 1),
984 : : AD18XX_PCM_VOLUME("Surround Playback Volume", 1)
985 : : };
986 : :
987 : : static const struct snd_kcontrol_new snd_ac97_controls_ad18xx_center[2] = {
988 : : AD18XX_PCM_BITS("Center Playback Switch", 2, 15, 15, 1),
989 : : AD18XX_PCM_BITS("Center Playback Volume", 2, 8, 8, 31)
990 : : };
991 : :
992 : : static const struct snd_kcontrol_new snd_ac97_controls_ad18xx_lfe[2] = {
993 : : AD18XX_PCM_BITS("LFE Playback Switch", 2, 7, 7, 1),
994 : : AD18XX_PCM_BITS("LFE Playback Volume", 2, 0, 0, 31)
995 : : };
996 : :
997 : : /*
998 : : *
999 : : */
1000 : :
1001 : : static void snd_ac97_powerdown(struct snd_ac97 *ac97);
1002 : :
1003 : 0 : static int snd_ac97_bus_free(struct snd_ac97_bus *bus)
1004 : : {
1005 [ # # ]: 0 : if (bus) {
1006 : 0 : snd_ac97_bus_proc_done(bus);
1007 : 0 : kfree(bus->pcms);
1008 [ # # ]: 0 : if (bus->private_free)
1009 : 0 : bus->private_free(bus);
1010 : 0 : kfree(bus);
1011 : : }
1012 : 0 : return 0;
1013 : : }
1014 : :
1015 : 0 : static int snd_ac97_bus_dev_free(struct snd_device *device)
1016 : : {
1017 : 0 : struct snd_ac97_bus *bus = device->device_data;
1018 : 0 : return snd_ac97_bus_free(bus);
1019 : : }
1020 : :
1021 : 0 : static int snd_ac97_free(struct snd_ac97 *ac97)
1022 : : {
1023 [ # # ]: 0 : if (ac97) {
1024 : : #ifdef CONFIG_SND_AC97_POWER_SAVE
1025 : : cancel_delayed_work_sync(&ac97->power_work);
1026 : : #endif
1027 : 0 : snd_ac97_proc_done(ac97);
1028 [ # # ]: 0 : if (ac97->bus)
1029 : 0 : ac97->bus->codec[ac97->num] = NULL;
1030 [ # # ]: 0 : if (ac97->private_free)
1031 : 0 : ac97->private_free(ac97);
1032 : 0 : kfree(ac97);
1033 : : }
1034 : 0 : return 0;
1035 : : }
1036 : :
1037 : 0 : static int snd_ac97_dev_free(struct snd_device *device)
1038 : : {
1039 : 0 : struct snd_ac97 *ac97 = device->device_data;
1040 : 0 : snd_ac97_powerdown(ac97); /* for avoiding click noises during shut down */
1041 : 0 : return snd_ac97_free(ac97);
1042 : : }
1043 : :
1044 : 0 : static int snd_ac97_try_volume_mix(struct snd_ac97 * ac97, int reg)
1045 : : {
1046 : : unsigned short val, mask = AC97_MUTE_MASK_MONO;
1047 : :
1048 [ # # ]: 0 : if (! snd_ac97_valid_reg(ac97, reg))
1049 : : return 0;
1050 : :
1051 [ # # # # : 0 : switch (reg) {
# # # # ]
1052 : : case AC97_MASTER_TONE:
1053 : 0 : return ac97->caps & AC97_BC_BASS_TREBLE ? 1 : 0;
1054 : : case AC97_HEADPHONE:
1055 : 0 : return ac97->caps & AC97_BC_HEADPHONE ? 1 : 0;
1056 : : case AC97_REC_GAIN_MIC:
1057 : 0 : return ac97->caps & AC97_BC_DEDICATED_MIC ? 1 : 0;
1058 : : case AC97_3D_CONTROL:
1059 [ # # ]: 0 : if (ac97->caps & AC97_BC_3D_TECH_ID_MASK) {
1060 : 0 : val = snd_ac97_read(ac97, reg);
1061 : : /* if nonzero - fixed and we can't set it */
1062 : 0 : return val == 0;
1063 : : }
1064 : : return 0;
1065 : : case AC97_CENTER_LFE_MASTER: /* center */
1066 [ # # ]: 0 : if ((ac97->ext_id & AC97_EI_CDAC) == 0)
1067 : : return 0;
1068 : : break;
1069 : : case AC97_CENTER_LFE_MASTER+1: /* lfe */
1070 [ # # ]: 0 : if ((ac97->ext_id & AC97_EI_LDAC) == 0)
1071 : : return 0;
1072 : : reg = AC97_CENTER_LFE_MASTER;
1073 : : mask = 0x0080;
1074 : : break;
1075 : : case AC97_SURROUND_MASTER:
1076 [ # # ]: 0 : if ((ac97->ext_id & AC97_EI_SDAC) == 0)
1077 : : return 0;
1078 : : break;
1079 : : }
1080 : :
1081 : 0 : val = snd_ac97_read(ac97, reg);
1082 [ # # ]: 0 : if (!(val & mask)) {
1083 : : /* nothing seems to be here - mute flag is not set */
1084 : : /* try another test */
1085 : 0 : snd_ac97_write_cache(ac97, reg, val | mask);
1086 : 0 : val = snd_ac97_read(ac97, reg);
1087 : 0 : val = snd_ac97_read(ac97, reg);
1088 [ # # ]: 0 : if (!(val & mask))
1089 : : return 0; /* nothing here */
1090 : : }
1091 : : return 1; /* success, useable */
1092 : : }
1093 : :
1094 : 0 : static void check_volume_resolution(struct snd_ac97 *ac97, int reg, unsigned char *lo_max, unsigned char *hi_max)
1095 : : {
1096 : 0 : unsigned short cbit[3] = { 0x20, 0x10, 0x01 };
1097 : 0 : unsigned char max[3] = { 63, 31, 15 };
1098 : : int i;
1099 : :
1100 : : /* first look up the static resolution table */
1101 [ # # ]: 0 : if (ac97->res_table) {
1102 : : const struct snd_ac97_res_table *tbl;
1103 [ # # ]: 0 : for (tbl = ac97->res_table; tbl->reg; tbl++) {
1104 [ # # ]: 0 : if (tbl->reg == reg) {
1105 : 0 : *lo_max = tbl->bits & 0xff;
1106 : 0 : *hi_max = (tbl->bits >> 8) & 0xff;
1107 : 0 : return;
1108 : : }
1109 : : }
1110 : : }
1111 : :
1112 : 0 : *lo_max = *hi_max = 0;
1113 [ # # ]: 0 : for (i = 0 ; i < ARRAY_SIZE(cbit); i++) {
1114 : : unsigned short val;
1115 : 0 : snd_ac97_write(
1116 : : ac97, reg,
1117 : 0 : AC97_MUTE_MASK_STEREO | cbit[i] | (cbit[i] << 8)
1118 : : );
1119 : : /* Do the read twice due to buffers on some ac97 codecs.
1120 : : * e.g. The STAC9704 returns exactly what you wrote to the register
1121 : : * if you read it immediately. This causes the detect routine to fail.
1122 : : */
1123 : 0 : val = snd_ac97_read(ac97, reg);
1124 : 0 : val = snd_ac97_read(ac97, reg);
1125 [ # # ][ # # ]: 0 : if (! *lo_max && (val & 0x7f) == cbit[i])
1126 : 0 : *lo_max = max[i];
1127 [ # # ][ # # ]: 0 : if (! *hi_max && ((val >> 8) & 0x7f) == cbit[i])
1128 : 0 : *hi_max = max[i];
1129 [ # # ][ # # ]: 0 : if (*lo_max && *hi_max)
1130 : : break;
1131 : : }
1132 : : }
1133 : :
1134 : 0 : static int snd_ac97_try_bit(struct snd_ac97 * ac97, int reg, int bit)
1135 : : {
1136 : : unsigned short mask, val, orig, res;
1137 : :
1138 : 0 : mask = 1 << bit;
1139 : 0 : orig = snd_ac97_read(ac97, reg);
1140 : 0 : val = orig ^ mask;
1141 : 0 : snd_ac97_write(ac97, reg, val);
1142 : 0 : res = snd_ac97_read(ac97, reg);
1143 : 0 : snd_ac97_write_cache(ac97, reg, orig);
1144 : 0 : return res == val;
1145 : : }
1146 : :
1147 : : /* check the volume resolution of center/lfe */
1148 : 0 : static void snd_ac97_change_volume_params2(struct snd_ac97 * ac97, int reg, int shift, unsigned char *max)
1149 : : {
1150 : : unsigned short val, val1;
1151 : :
1152 : 0 : *max = 63;
1153 : 0 : val = AC97_MUTE_MASK_STEREO | (0x20 << shift);
1154 : 0 : snd_ac97_write(ac97, reg, val);
1155 : 0 : val1 = snd_ac97_read(ac97, reg);
1156 [ # # ]: 0 : if (val != val1) {
1157 : 0 : *max = 31;
1158 : : }
1159 : : /* reset volume to zero */
1160 : 0 : snd_ac97_write_cache(ac97, reg, AC97_MUTE_MASK_STEREO);
1161 : 0 : }
1162 : :
1163 : : static inline int printable(unsigned int x)
1164 : : {
1165 : 2 : x &= 0xff;
1166 [ - + ][ - + ]: 3 : if (x < ' ' || x >= 0x71) {
[ - + ]
1167 [ # # ][ # # ]: 0 : if (x <= 0x89)
[ # # ]
1168 : 0 : return x - 0x71 + 'A';
1169 : : return '?';
1170 : : }
1171 : 3 : return x;
1172 : : }
1173 : :
1174 : 0 : static struct snd_kcontrol *snd_ac97_cnew(const struct snd_kcontrol_new *_template,
1175 : : struct snd_ac97 * ac97)
1176 : : {
1177 : : struct snd_kcontrol_new template;
1178 : 0 : memcpy(&template, _template, sizeof(template));
1179 : 0 : template.index = ac97->num;
1180 : 0 : return snd_ctl_new1(&template, ac97);
1181 : : }
1182 : :
1183 : : /*
1184 : : * create mute switch(es) for normal stereo controls
1185 : : */
1186 : 0 : static int snd_ac97_cmute_new_stereo(struct snd_card *card, char *name, int reg,
1187 : : int check_stereo, int check_amix,
1188 : 0 : struct snd_ac97 *ac97)
1189 : : {
1190 : : struct snd_kcontrol *kctl;
1191 : : int err;
1192 : : unsigned short val, val1, mute_mask;
1193 : :
1194 [ # # ]: 0 : if (! snd_ac97_valid_reg(ac97, reg))
1195 : : return 0;
1196 : :
1197 : : mute_mask = AC97_MUTE_MASK_MONO;
1198 : 0 : val = snd_ac97_read(ac97, reg);
1199 [ # # ][ # # ]: 0 : if (check_stereo || (ac97->flags & AC97_STEREO_MUTES)) {
1200 : : /* check whether both mute bits work */
1201 : 0 : val1 = val | AC97_MUTE_MASK_STEREO;
1202 : 0 : snd_ac97_write(ac97, reg, val1);
1203 [ # # ]: 0 : if (val1 == snd_ac97_read(ac97, reg))
1204 : : mute_mask = AC97_MUTE_MASK_STEREO;
1205 : : }
1206 [ # # ]: 0 : if (mute_mask == AC97_MUTE_MASK_STEREO) {
1207 : 0 : struct snd_kcontrol_new tmp = AC97_DOUBLE(name, reg, 15, 7, 1, 1);
1208 [ # # ]: 0 : if (check_amix)
1209 : 0 : tmp.private_value |= (1 << 30);
1210 : 0 : tmp.index = ac97->num;
1211 : 0 : kctl = snd_ctl_new1(&tmp, ac97);
1212 : : } else {
1213 : 0 : struct snd_kcontrol_new tmp = AC97_SINGLE(name, reg, 15, 1, 1);
1214 [ # # ]: 0 : if (check_amix)
1215 : 0 : tmp.private_value |= (1 << 30);
1216 : 0 : tmp.index = ac97->num;
1217 : 0 : kctl = snd_ctl_new1(&tmp, ac97);
1218 : : }
1219 : 0 : err = snd_ctl_add(card, kctl);
1220 [ # # ]: 0 : if (err < 0)
1221 : : return err;
1222 : : /* mute as default */
1223 : 0 : snd_ac97_write_cache(ac97, reg, val | mute_mask);
1224 : 0 : return 0;
1225 : : }
1226 : :
1227 : : /*
1228 : : * set dB information
1229 : : */
1230 : : static const DECLARE_TLV_DB_SCALE(db_scale_4bit, -4500, 300, 0);
1231 : : static const DECLARE_TLV_DB_SCALE(db_scale_5bit, -4650, 150, 0);
1232 : : static const DECLARE_TLV_DB_SCALE(db_scale_6bit, -9450, 150, 0);
1233 : : static const DECLARE_TLV_DB_SCALE(db_scale_5bit_12db_max, -3450, 150, 0);
1234 : : static const DECLARE_TLV_DB_SCALE(db_scale_rec_gain, 0, 150, 0);
1235 : :
1236 : : static const unsigned int *find_db_scale(unsigned int maxval)
1237 : : {
1238 [ # # # # ]: 0 : switch (maxval) {
[ # # # # ]
[ # # # # ]
1239 : : case 0x0f: return db_scale_4bit;
1240 : : case 0x1f: return db_scale_5bit;
1241 : : case 0x3f: return db_scale_6bit;
1242 : : }
1243 : : return NULL;
1244 : : }
1245 : :
1246 : : static void set_tlv_db_scale(struct snd_kcontrol *kctl, const unsigned int *tlv)
1247 : : {
1248 : 0 : kctl->tlv.p = tlv;
1249 [ # # ][ # # ]: 0 : if (tlv)
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1250 : 0 : kctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ;
1251 : : }
1252 : :
1253 : : /*
1254 : : * create a volume for normal stereo/mono controls
1255 : : */
1256 : 0 : static int snd_ac97_cvol_new(struct snd_card *card, char *name, int reg, unsigned int lo_max,
1257 : 0 : unsigned int hi_max, struct snd_ac97 *ac97)
1258 : : {
1259 : : int err;
1260 : : struct snd_kcontrol *kctl;
1261 : :
1262 [ # # ]: 0 : if (! snd_ac97_valid_reg(ac97, reg))
1263 : : return 0;
1264 [ # # ]: 0 : if (hi_max) {
1265 : : /* invert */
1266 : 0 : struct snd_kcontrol_new tmp = AC97_DOUBLE(name, reg, 8, 0, lo_max, 1);
1267 : 0 : tmp.index = ac97->num;
1268 : 0 : kctl = snd_ctl_new1(&tmp, ac97);
1269 : : } else {
1270 : : /* invert */
1271 : 0 : struct snd_kcontrol_new tmp = AC97_SINGLE(name, reg, 0, lo_max, 1);
1272 : 0 : tmp.index = ac97->num;
1273 : 0 : kctl = snd_ctl_new1(&tmp, ac97);
1274 : : }
1275 [ # # ]: 0 : if (!kctl)
1276 : : return -ENOMEM;
1277 [ # # ]: 0 : if (reg >= AC97_PHONE && reg <= AC97_PCM)
1278 : : set_tlv_db_scale(kctl, db_scale_5bit_12db_max);
1279 : : else
1280 : : set_tlv_db_scale(kctl, find_db_scale(lo_max));
1281 : 0 : err = snd_ctl_add(card, kctl);
1282 [ # # ]: 0 : if (err < 0)
1283 : : return err;
1284 : 0 : snd_ac97_write_cache(
1285 : : ac97, reg,
1286 : 0 : (snd_ac97_read(ac97, reg) & AC97_MUTE_MASK_STEREO)
1287 : : | lo_max | (hi_max << 8)
1288 : : );
1289 : 0 : return 0;
1290 : : }
1291 : :
1292 : : /*
1293 : : * create a mute-switch and a volume for normal stereo/mono controls
1294 : : */
1295 : 0 : static int snd_ac97_cmix_new_stereo(struct snd_card *card, const char *pfx,
1296 : : int reg, int check_stereo, int check_amix,
1297 : 0 : struct snd_ac97 *ac97)
1298 : : {
1299 : : int err;
1300 : : char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
1301 : : unsigned char lo_max, hi_max;
1302 : :
1303 [ # # ]: 0 : if (! snd_ac97_valid_reg(ac97, reg))
1304 : : return 0;
1305 : :
1306 [ # # ]: 0 : if (snd_ac97_try_bit(ac97, reg, 15)) {
1307 : 0 : sprintf(name, "%s Switch", pfx);
1308 [ # # ]: 0 : if ((err = snd_ac97_cmute_new_stereo(card, name, reg,
1309 : : check_stereo, check_amix,
1310 : : ac97)) < 0)
1311 : : return err;
1312 : : }
1313 : 0 : check_volume_resolution(ac97, reg, &lo_max, &hi_max);
1314 [ # # ]: 0 : if (lo_max) {
1315 : 0 : sprintf(name, "%s Volume", pfx);
1316 [ # # ]: 0 : if ((err = snd_ac97_cvol_new(card, name, reg, lo_max, hi_max, ac97)) < 0)
1317 : 0 : return err;
1318 : : }
1319 : : return 0;
1320 : : }
1321 : :
1322 : : #define snd_ac97_cmix_new(card, pfx, reg, acheck, ac97) \
1323 : : snd_ac97_cmix_new_stereo(card, pfx, reg, 0, acheck, ac97)
1324 : : #define snd_ac97_cmute_new(card, name, reg, acheck, ac97) \
1325 : : snd_ac97_cmute_new_stereo(card, name, reg, 0, acheck, ac97)
1326 : :
1327 : : static unsigned int snd_ac97_determine_spdif_rates(struct snd_ac97 *ac97);
1328 : :
1329 : 0 : static int snd_ac97_mixer_build(struct snd_ac97 * ac97)
1330 : : {
1331 : 0 : struct snd_card *card = ac97->bus->card;
1332 : : struct snd_kcontrol *kctl;
1333 : : int err;
1334 : : unsigned int idx;
1335 : : unsigned char max;
1336 : :
1337 : : /* build master controls */
1338 : : /* AD claims to remove this control from AD1887, although spec v2.2 does not allow this */
1339 [ # # ]: 0 : if (snd_ac97_try_volume_mix(ac97, AC97_MASTER)) {
1340 [ # # ]: 0 : if (ac97->flags & AC97_HAS_NO_MASTER_VOL)
1341 : 0 : err = snd_ac97_cmute_new(card, "Master Playback Switch",
1342 : : AC97_MASTER, 0, ac97);
1343 : : else
1344 : 0 : err = snd_ac97_cmix_new(card, "Master Playback",
1345 : : AC97_MASTER, 0, ac97);
1346 [ # # ]: 0 : if (err < 0)
1347 : : return err;
1348 : : }
1349 : :
1350 : 0 : ac97->regs[AC97_CENTER_LFE_MASTER] = AC97_MUTE_MASK_STEREO;
1351 : :
1352 : : /* build center controls */
1353 [ # # ]: 0 : if ((snd_ac97_try_volume_mix(ac97, AC97_CENTER_LFE_MASTER))
1354 [ # # ]: 0 : && !(ac97->flags & AC97_AD_MULTI)) {
1355 [ # # ]: 0 : if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_center[0], ac97))) < 0)
1356 : : return err;
1357 [ # # ]: 0 : if ((err = snd_ctl_add(card, kctl = snd_ac97_cnew(&snd_ac97_controls_center[1], ac97))) < 0)
1358 : : return err;
1359 : 0 : snd_ac97_change_volume_params2(ac97, AC97_CENTER_LFE_MASTER, 0, &max);
1360 : 0 : kctl->private_value &= ~(0xff << 16);
1361 : 0 : kctl->private_value |= (int)max << 16;
1362 : : set_tlv_db_scale(kctl, find_db_scale(max));
1363 : 0 : snd_ac97_write_cache(ac97, AC97_CENTER_LFE_MASTER, ac97->regs[AC97_CENTER_LFE_MASTER] | max);
1364 : : }
1365 : :
1366 : : /* build LFE controls */
1367 [ # # ]: 0 : if ((snd_ac97_try_volume_mix(ac97, AC97_CENTER_LFE_MASTER+1))
1368 [ # # ]: 0 : && !(ac97->flags & AC97_AD_MULTI)) {
1369 [ # # ]: 0 : if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_lfe[0], ac97))) < 0)
1370 : : return err;
1371 [ # # ]: 0 : if ((err = snd_ctl_add(card, kctl = snd_ac97_cnew(&snd_ac97_controls_lfe[1], ac97))) < 0)
1372 : : return err;
1373 : 0 : snd_ac97_change_volume_params2(ac97, AC97_CENTER_LFE_MASTER, 8, &max);
1374 : 0 : kctl->private_value &= ~(0xff << 16);
1375 : 0 : kctl->private_value |= (int)max << 16;
1376 : : set_tlv_db_scale(kctl, find_db_scale(max));
1377 : 0 : snd_ac97_write_cache(ac97, AC97_CENTER_LFE_MASTER, ac97->regs[AC97_CENTER_LFE_MASTER] | max << 8);
1378 : : }
1379 : :
1380 : : /* build surround controls */
1381 [ # # ]: 0 : if ((snd_ac97_try_volume_mix(ac97, AC97_SURROUND_MASTER))
1382 [ # # ]: 0 : && !(ac97->flags & AC97_AD_MULTI)) {
1383 : : /* Surround Master (0x38) is with stereo mutes */
1384 [ # # ]: 0 : if ((err = snd_ac97_cmix_new_stereo(card, "Surround Playback",
1385 : : AC97_SURROUND_MASTER, 1, 0,
1386 : : ac97)) < 0)
1387 : : return err;
1388 : : }
1389 : :
1390 : : /* build headphone controls */
1391 [ # # ]: 0 : if (snd_ac97_try_volume_mix(ac97, AC97_HEADPHONE)) {
1392 [ # # ]: 0 : if ((err = snd_ac97_cmix_new(card, "Headphone Playback",
1393 : : AC97_HEADPHONE, 0, ac97)) < 0)
1394 : : return err;
1395 : : }
1396 : :
1397 : : /* build master mono controls */
1398 [ # # ]: 0 : if (snd_ac97_try_volume_mix(ac97, AC97_MASTER_MONO)) {
1399 [ # # ]: 0 : if ((err = snd_ac97_cmix_new(card, "Master Mono Playback",
1400 : : AC97_MASTER_MONO, 0, ac97)) < 0)
1401 : : return err;
1402 : : }
1403 : :
1404 : : /* build master tone controls */
1405 [ # # ]: 0 : if (!(ac97->flags & AC97_HAS_NO_TONE)) {
1406 [ # # ]: 0 : if (snd_ac97_try_volume_mix(ac97, AC97_MASTER_TONE)) {
1407 [ # # ]: 0 : for (idx = 0; idx < 2; idx++) {
1408 [ # # ]: 0 : if ((err = snd_ctl_add(card, kctl = snd_ac97_cnew(&snd_ac97_controls_tone[idx], ac97))) < 0)
1409 : : return err;
1410 [ # # ]: 0 : if (ac97->id == AC97_ID_YMF743 ||
1411 : : ac97->id == AC97_ID_YMF753) {
1412 : 0 : kctl->private_value &= ~(0xff << 16);
1413 : 0 : kctl->private_value |= 7 << 16;
1414 : : }
1415 : : }
1416 : 0 : snd_ac97_write_cache(ac97, AC97_MASTER_TONE, 0x0f0f);
1417 : : }
1418 : : }
1419 : :
1420 : : /* build Beep controls */
1421 [ # # ][ # # ]: 0 : if (!(ac97->flags & AC97_HAS_NO_PC_BEEP) &&
1422 [ # # ]: 0 : ((ac97->flags & AC97_HAS_PC_BEEP) ||
1423 : 0 : snd_ac97_try_volume_mix(ac97, AC97_PC_BEEP))) {
1424 [ # # ]: 0 : for (idx = 0; idx < 2; idx++)
1425 [ # # ]: 0 : if ((err = snd_ctl_add(card, kctl = snd_ac97_cnew(&snd_ac97_controls_pc_beep[idx], ac97))) < 0)
1426 : : return err;
1427 : : set_tlv_db_scale(kctl, db_scale_4bit);
1428 : 0 : snd_ac97_write_cache(
1429 : : ac97,
1430 : : AC97_PC_BEEP,
1431 : 0 : (snd_ac97_read(ac97, AC97_PC_BEEP)
1432 : : | AC97_MUTE_MASK_MONO | 0x001e)
1433 : : );
1434 : : }
1435 : :
1436 : : /* build Phone controls */
1437 [ # # ]: 0 : if (!(ac97->flags & AC97_HAS_NO_PHONE)) {
1438 [ # # ]: 0 : if (snd_ac97_try_volume_mix(ac97, AC97_PHONE)) {
1439 [ # # ]: 0 : if ((err = snd_ac97_cmix_new(card, "Phone Playback",
1440 : : AC97_PHONE, 1, ac97)) < 0)
1441 : : return err;
1442 : : }
1443 : : }
1444 : :
1445 : : /* build MIC controls */
1446 [ # # ]: 0 : if (!(ac97->flags & AC97_HAS_NO_MIC)) {
1447 [ # # ]: 0 : if (snd_ac97_try_volume_mix(ac97, AC97_MIC)) {
1448 [ # # ]: 0 : if ((err = snd_ac97_cmix_new(card, "Mic Playback",
1449 : : AC97_MIC, 1, ac97)) < 0)
1450 : : return err;
1451 [ # # ]: 0 : if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_mic_boost, ac97))) < 0)
1452 : : return err;
1453 : : }
1454 : : }
1455 : :
1456 : : /* build Line controls */
1457 [ # # ]: 0 : if (snd_ac97_try_volume_mix(ac97, AC97_LINE)) {
1458 [ # # ]: 0 : if ((err = snd_ac97_cmix_new(card, "Line Playback",
1459 : : AC97_LINE, 1, ac97)) < 0)
1460 : : return err;
1461 : : }
1462 : :
1463 : : /* build CD controls */
1464 [ # # ]: 0 : if (!(ac97->flags & AC97_HAS_NO_CD)) {
1465 [ # # ]: 0 : if (snd_ac97_try_volume_mix(ac97, AC97_CD)) {
1466 [ # # ]: 0 : if ((err = snd_ac97_cmix_new(card, "CD Playback",
1467 : : AC97_CD, 1, ac97)) < 0)
1468 : : return err;
1469 : : }
1470 : : }
1471 : :
1472 : : /* build Video controls */
1473 [ # # ]: 0 : if (!(ac97->flags & AC97_HAS_NO_VIDEO)) {
1474 [ # # ]: 0 : if (snd_ac97_try_volume_mix(ac97, AC97_VIDEO)) {
1475 [ # # ]: 0 : if ((err = snd_ac97_cmix_new(card, "Video Playback",
1476 : : AC97_VIDEO, 1, ac97)) < 0)
1477 : : return err;
1478 : : }
1479 : : }
1480 : :
1481 : : /* build Aux controls */
1482 [ # # ]: 0 : if (!(ac97->flags & AC97_HAS_NO_AUX)) {
1483 [ # # ]: 0 : if (snd_ac97_try_volume_mix(ac97, AC97_AUX)) {
1484 [ # # ]: 0 : if ((err = snd_ac97_cmix_new(card, "Aux Playback",
1485 : : AC97_AUX, 1, ac97)) < 0)
1486 : : return err;
1487 : : }
1488 : : }
1489 : :
1490 : : /* build PCM controls */
1491 [ # # ]: 0 : if (ac97->flags & AC97_AD_MULTI) {
1492 : : unsigned short init_val;
1493 [ # # ]: 0 : if (ac97->flags & AC97_STEREO_MUTES)
1494 : : init_val = 0x9f9f;
1495 : : else
1496 : : init_val = 0x9f1f;
1497 [ # # ]: 0 : for (idx = 0; idx < 2; idx++)
1498 [ # # ]: 0 : if ((err = snd_ctl_add(card, kctl = snd_ac97_cnew(&snd_ac97_controls_ad18xx_pcm[idx], ac97))) < 0)
1499 : : return err;
1500 : : set_tlv_db_scale(kctl, db_scale_5bit);
1501 : 0 : ac97->spec.ad18xx.pcmreg[0] = init_val;
1502 [ # # ]: 0 : if (ac97->scaps & AC97_SCAP_SURROUND_DAC) {
1503 [ # # ]: 0 : for (idx = 0; idx < 2; idx++)
1504 [ # # ]: 0 : if ((err = snd_ctl_add(card, kctl = snd_ac97_cnew(&snd_ac97_controls_ad18xx_surround[idx], ac97))) < 0)
1505 : : return err;
1506 : : set_tlv_db_scale(kctl, db_scale_5bit);
1507 : 0 : ac97->spec.ad18xx.pcmreg[1] = init_val;
1508 : : }
1509 [ # # ]: 0 : if (ac97->scaps & AC97_SCAP_CENTER_LFE_DAC) {
1510 [ # # ]: 0 : for (idx = 0; idx < 2; idx++)
1511 [ # # ]: 0 : if ((err = snd_ctl_add(card, kctl = snd_ac97_cnew(&snd_ac97_controls_ad18xx_center[idx], ac97))) < 0)
1512 : : return err;
1513 : : set_tlv_db_scale(kctl, db_scale_5bit);
1514 [ # # ]: 0 : for (idx = 0; idx < 2; idx++)
1515 [ # # ]: 0 : if ((err = snd_ctl_add(card, kctl = snd_ac97_cnew(&snd_ac97_controls_ad18xx_lfe[idx], ac97))) < 0)
1516 : : return err;
1517 : : set_tlv_db_scale(kctl, db_scale_5bit);
1518 : 0 : ac97->spec.ad18xx.pcmreg[2] = init_val;
1519 : : }
1520 : 0 : snd_ac97_write_cache(ac97, AC97_PCM, init_val);
1521 : : } else {
1522 [ # # ]: 0 : if (!(ac97->flags & AC97_HAS_NO_STD_PCM)) {
1523 [ # # ]: 0 : if (ac97->flags & AC97_HAS_NO_PCM_VOL)
1524 : 0 : err = snd_ac97_cmute_new(card,
1525 : : "PCM Playback Switch",
1526 : : AC97_PCM, 0, ac97);
1527 : : else
1528 : 0 : err = snd_ac97_cmix_new(card, "PCM Playback",
1529 : : AC97_PCM, 0, ac97);
1530 [ # # ]: 0 : if (err < 0)
1531 : : return err;
1532 : : }
1533 : : }
1534 : :
1535 : : /* build Capture controls */
1536 [ # # ]: 0 : if (!(ac97->flags & AC97_HAS_NO_REC_GAIN)) {
1537 [ # # ]: 0 : if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_control_capture_src, ac97))) < 0)
1538 : : return err;
1539 [ # # ]: 0 : if (snd_ac97_try_bit(ac97, AC97_REC_GAIN, 15)) {
1540 : 0 : err = snd_ac97_cmute_new(card, "Capture Switch",
1541 : : AC97_REC_GAIN, 0, ac97);
1542 [ # # ]: 0 : if (err < 0)
1543 : : return err;
1544 : : }
1545 [ # # ]: 0 : if ((err = snd_ctl_add(card, kctl = snd_ac97_cnew(&snd_ac97_control_capture_vol, ac97))) < 0)
1546 : : return err;
1547 : : set_tlv_db_scale(kctl, db_scale_rec_gain);
1548 : 0 : snd_ac97_write_cache(ac97, AC97_REC_SEL, 0x0000);
1549 : 0 : snd_ac97_write_cache(ac97, AC97_REC_GAIN, 0x0000);
1550 : : }
1551 : : /* build MIC Capture controls */
1552 [ # # ]: 0 : if (snd_ac97_try_volume_mix(ac97, AC97_REC_GAIN_MIC)) {
1553 [ # # ]: 0 : for (idx = 0; idx < 2; idx++)
1554 [ # # ]: 0 : if ((err = snd_ctl_add(card, kctl = snd_ac97_cnew(&snd_ac97_controls_mic_capture[idx], ac97))) < 0)
1555 : : return err;
1556 : : set_tlv_db_scale(kctl, db_scale_rec_gain);
1557 : 0 : snd_ac97_write_cache(ac97, AC97_REC_GAIN_MIC, 0x0000);
1558 : : }
1559 : :
1560 : : /* build PCM out path & mute control */
1561 [ # # ]: 0 : if (snd_ac97_try_bit(ac97, AC97_GENERAL_PURPOSE, 15)) {
1562 [ # # ]: 0 : if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_general[AC97_GENERAL_PCM_OUT], ac97))) < 0)
1563 : : return err;
1564 : : }
1565 : :
1566 : : /* build Simulated Stereo Enhancement control */
1567 [ # # ]: 0 : if (ac97->caps & AC97_BC_SIM_STEREO) {
1568 [ # # ]: 0 : if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_general[AC97_GENERAL_STEREO_ENHANCEMENT], ac97))) < 0)
1569 : : return err;
1570 : : }
1571 : :
1572 : : /* build 3D Stereo Enhancement control */
1573 [ # # ]: 0 : if (snd_ac97_try_bit(ac97, AC97_GENERAL_PURPOSE, 13)) {
1574 [ # # ]: 0 : if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_general[AC97_GENERAL_3D], ac97))) < 0)
1575 : : return err;
1576 : : }
1577 : :
1578 : : /* build Loudness control */
1579 [ # # ]: 0 : if (ac97->caps & AC97_BC_LOUDNESS) {
1580 [ # # ]: 0 : if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_general[AC97_GENERAL_LOUDNESS], ac97))) < 0)
1581 : : return err;
1582 : : }
1583 : :
1584 : : /* build Mono output select control */
1585 [ # # ]: 0 : if (snd_ac97_try_bit(ac97, AC97_GENERAL_PURPOSE, 9)) {
1586 [ # # ]: 0 : if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_general[AC97_GENERAL_MONO], ac97))) < 0)
1587 : : return err;
1588 : : }
1589 : :
1590 : : /* build Mic select control */
1591 [ # # ]: 0 : if (snd_ac97_try_bit(ac97, AC97_GENERAL_PURPOSE, 8)) {
1592 [ # # ]: 0 : if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_general[AC97_GENERAL_MIC], ac97))) < 0)
1593 : : return err;
1594 : : }
1595 : :
1596 : : /* build ADC/DAC loopback control */
1597 [ # # ][ # # ]: 0 : if (enable_loopback && snd_ac97_try_bit(ac97, AC97_GENERAL_PURPOSE, 7)) {
1598 [ # # ]: 0 : if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_general[AC97_GENERAL_LOOPBACK], ac97))) < 0)
1599 : : return err;
1600 : : }
1601 : :
1602 : 0 : snd_ac97_update_bits(ac97, AC97_GENERAL_PURPOSE, ~AC97_GP_DRSS_MASK, 0x0000);
1603 : :
1604 : : /* build 3D controls */
1605 [ # # ]: 0 : if (ac97->build_ops->build_3d) {
1606 : 0 : ac97->build_ops->build_3d(ac97);
1607 : : } else {
1608 [ # # ]: 0 : if (snd_ac97_try_volume_mix(ac97, AC97_3D_CONTROL)) {
1609 : : unsigned short val;
1610 : : val = 0x0707;
1611 : 0 : snd_ac97_write(ac97, AC97_3D_CONTROL, val);
1612 : 0 : val = snd_ac97_read(ac97, AC97_3D_CONTROL);
1613 : 0 : val = val == 0x0606;
1614 [ # # ]: 0 : if ((err = snd_ctl_add(card, kctl = snd_ac97_cnew(&snd_ac97_controls_3d[0], ac97))) < 0)
1615 : : return err;
1616 [ # # ]: 0 : if (val)
1617 : 0 : kctl->private_value = AC97_3D_CONTROL | (9 << 8) | (7 << 16);
1618 [ # # ]: 0 : if ((err = snd_ctl_add(card, kctl = snd_ac97_cnew(&snd_ac97_controls_3d[1], ac97))) < 0)
1619 : : return err;
1620 [ # # ]: 0 : if (val)
1621 : 0 : kctl->private_value = AC97_3D_CONTROL | (1 << 8) | (7 << 16);
1622 : 0 : snd_ac97_write_cache(ac97, AC97_3D_CONTROL, 0x0000);
1623 : : }
1624 : : }
1625 : :
1626 : : /* build S/PDIF controls */
1627 : :
1628 : : /* Hack for ASUS P5P800-VM, which does not indicate S/PDIF capability */
1629 [ # # ]: 0 : if (ac97->subsystem_vendor == 0x1043 &&
1630 : : ac97->subsystem_device == 0x810f)
1631 : 0 : ac97->ext_id |= AC97_EI_SPDIF;
1632 : :
1633 [ # # ][ # # ]: 0 : if ((ac97->ext_id & AC97_EI_SPDIF) && !(ac97->scaps & AC97_SCAP_NO_SPDIF)) {
1634 [ # # ]: 0 : if (ac97->build_ops->build_spdif) {
1635 [ # # ]: 0 : if ((err = ac97->build_ops->build_spdif(ac97)) < 0)
1636 : : return err;
1637 : : } else {
1638 [ # # ]: 0 : for (idx = 0; idx < 5; idx++)
1639 [ # # ]: 0 : if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_spdif[idx], ac97))) < 0)
1640 : : return err;
1641 [ # # ]: 0 : if (ac97->build_ops->build_post_spdif) {
1642 [ # # ]: 0 : if ((err = ac97->build_ops->build_post_spdif(ac97)) < 0)
1643 : : return err;
1644 : : }
1645 : : /* set default PCM S/PDIF params */
1646 : : /* consumer,PCM audio,no copyright,no preemphasis,PCM coder,original,48000Hz */
1647 : 0 : snd_ac97_write_cache(ac97, AC97_SPDIF, 0x2a20);
1648 : 0 : ac97->rates[AC97_RATES_SPDIF] = snd_ac97_determine_spdif_rates(ac97);
1649 : : }
1650 : 0 : ac97->spdif_status = SNDRV_PCM_DEFAULT_CON_SPDIF;
1651 : : }
1652 : :
1653 : : /* build chip specific controls */
1654 [ # # ]: 0 : if (ac97->build_ops->build_specific)
1655 [ # # ]: 0 : if ((err = ac97->build_ops->build_specific(ac97)) < 0)
1656 : : return err;
1657 : :
1658 [ # # ]: 0 : if (snd_ac97_try_bit(ac97, AC97_POWERDOWN, 15)) {
1659 : 0 : kctl = snd_ac97_cnew(&snd_ac97_control_eapd, ac97);
1660 [ # # ]: 0 : if (! kctl)
1661 : : return -ENOMEM;
1662 [ # # ]: 0 : if (ac97->scaps & AC97_SCAP_INV_EAPD)
1663 : : set_inv_eapd(ac97, kctl);
1664 [ # # ]: 0 : if ((err = snd_ctl_add(card, kctl)) < 0)
1665 : 0 : return err;
1666 : : }
1667 : :
1668 : : return 0;
1669 : : }
1670 : :
1671 : 0 : static int snd_ac97_modem_build(struct snd_card *card, struct snd_ac97 * ac97)
1672 : : {
1673 : : int err, idx;
1674 : :
1675 : : /*
1676 : : printk(KERN_DEBUG "AC97_GPIO_CFG = %x\n",
1677 : : snd_ac97_read(ac97,AC97_GPIO_CFG));
1678 : : */
1679 : 0 : snd_ac97_write(ac97, AC97_GPIO_CFG, 0xffff & ~(AC97_GPIO_LINE1_OH));
1680 : 0 : snd_ac97_write(ac97, AC97_GPIO_POLARITY, 0xffff & ~(AC97_GPIO_LINE1_OH));
1681 : 0 : snd_ac97_write(ac97, AC97_GPIO_STICKY, 0xffff);
1682 : 0 : snd_ac97_write(ac97, AC97_GPIO_WAKEUP, 0x0);
1683 : 0 : snd_ac97_write(ac97, AC97_MISC_AFE, 0x0);
1684 : :
1685 : : /* build modem switches */
1686 [ # # ]: 0 : for (idx = 0; idx < ARRAY_SIZE(snd_ac97_controls_modem_switches); idx++)
1687 [ # # ]: 0 : if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_ac97_controls_modem_switches[idx], ac97))) < 0)
1688 : : return err;
1689 : :
1690 : : /* build chip specific controls */
1691 [ # # ]: 0 : if (ac97->build_ops->build_specific)
1692 [ # # ]: 0 : if ((err = ac97->build_ops->build_specific(ac97)) < 0)
1693 : 0 : return err;
1694 : :
1695 : : return 0;
1696 : : }
1697 : :
1698 : 0 : static int snd_ac97_test_rate(struct snd_ac97 *ac97, int reg, int shadow_reg, int rate)
1699 : : {
1700 : : unsigned short val;
1701 : : unsigned int tmp;
1702 : :
1703 : 0 : tmp = ((unsigned int)rate * ac97->bus->clock) / 48000;
1704 : 0 : snd_ac97_write_cache(ac97, reg, tmp & 0xffff);
1705 [ # # ]: 0 : if (shadow_reg)
1706 : 0 : snd_ac97_write_cache(ac97, shadow_reg, tmp & 0xffff);
1707 : 0 : val = snd_ac97_read(ac97, reg);
1708 : 0 : return val == (tmp & 0xffff);
1709 : : }
1710 : :
1711 : 0 : static void snd_ac97_determine_rates(struct snd_ac97 *ac97, int reg, int shadow_reg, unsigned int *r_result)
1712 : : {
1713 : : unsigned int result = 0;
1714 : : unsigned short saved;
1715 : :
1716 [ # # ]: 0 : if (ac97->bus->no_vra) {
1717 : 0 : *r_result = SNDRV_PCM_RATE_48000;
1718 [ # # ][ # # ]: 0 : if ((ac97->flags & AC97_DOUBLE_RATE) &&
1719 : : reg == AC97_PCM_FRONT_DAC_RATE)
1720 : 0 : *r_result |= SNDRV_PCM_RATE_96000;
1721 : 0 : return;
1722 : : }
1723 : :
1724 : 0 : saved = snd_ac97_read(ac97, reg);
1725 [ # # ][ # # ]: 0 : if ((ac97->ext_id & AC97_EI_DRA) && reg == AC97_PCM_FRONT_DAC_RATE)
1726 : 0 : snd_ac97_update_bits(ac97, AC97_EXTENDED_STATUS,
1727 : : AC97_EA_DRA, 0);
1728 : : /* test a non-standard rate */
1729 [ # # ]: 0 : if (snd_ac97_test_rate(ac97, reg, shadow_reg, 11000))
1730 : : result |= SNDRV_PCM_RATE_CONTINUOUS;
1731 : : /* let's try to obtain standard rates */
1732 [ # # ]: 0 : if (snd_ac97_test_rate(ac97, reg, shadow_reg, 8000))
1733 : 0 : result |= SNDRV_PCM_RATE_8000;
1734 [ # # ]: 0 : if (snd_ac97_test_rate(ac97, reg, shadow_reg, 11025))
1735 : 0 : result |= SNDRV_PCM_RATE_11025;
1736 [ # # ]: 0 : if (snd_ac97_test_rate(ac97, reg, shadow_reg, 16000))
1737 : 0 : result |= SNDRV_PCM_RATE_16000;
1738 [ # # ]: 0 : if (snd_ac97_test_rate(ac97, reg, shadow_reg, 22050))
1739 : 0 : result |= SNDRV_PCM_RATE_22050;
1740 [ # # ]: 0 : if (snd_ac97_test_rate(ac97, reg, shadow_reg, 32000))
1741 : 0 : result |= SNDRV_PCM_RATE_32000;
1742 [ # # ]: 0 : if (snd_ac97_test_rate(ac97, reg, shadow_reg, 44100))
1743 : 0 : result |= SNDRV_PCM_RATE_44100;
1744 [ # # ]: 0 : if (snd_ac97_test_rate(ac97, reg, shadow_reg, 48000))
1745 : 0 : result |= SNDRV_PCM_RATE_48000;
1746 [ # # ][ # # ]: 0 : if ((ac97->flags & AC97_DOUBLE_RATE) &&
1747 : : reg == AC97_PCM_FRONT_DAC_RATE) {
1748 : : /* test standard double rates */
1749 : 0 : snd_ac97_update_bits(ac97, AC97_EXTENDED_STATUS,
1750 : : AC97_EA_DRA, AC97_EA_DRA);
1751 [ # # ]: 0 : if (snd_ac97_test_rate(ac97, reg, shadow_reg, 64000 / 2))
1752 : 0 : result |= SNDRV_PCM_RATE_64000;
1753 [ # # ]: 0 : if (snd_ac97_test_rate(ac97, reg, shadow_reg, 88200 / 2))
1754 : 0 : result |= SNDRV_PCM_RATE_88200;
1755 [ # # ]: 0 : if (snd_ac97_test_rate(ac97, reg, shadow_reg, 96000 / 2))
1756 : 0 : result |= SNDRV_PCM_RATE_96000;
1757 : : /* some codecs don't support variable double rates */
1758 [ # # ]: 0 : if (!snd_ac97_test_rate(ac97, reg, shadow_reg, 76100 / 2))
1759 : 0 : result &= ~SNDRV_PCM_RATE_CONTINUOUS;
1760 : 0 : snd_ac97_update_bits(ac97, AC97_EXTENDED_STATUS,
1761 : : AC97_EA_DRA, 0);
1762 : : }
1763 : : /* restore the default value */
1764 : 0 : snd_ac97_write_cache(ac97, reg, saved);
1765 [ # # ]: 0 : if (shadow_reg)
1766 : 0 : snd_ac97_write_cache(ac97, shadow_reg, saved);
1767 : 0 : *r_result = result;
1768 : : }
1769 : :
1770 : : /* check AC97_SPDIF register to accept which sample rates */
1771 : 0 : static unsigned int snd_ac97_determine_spdif_rates(struct snd_ac97 *ac97)
1772 : : {
1773 : : unsigned int result = 0;
1774 : : int i;
1775 : : static unsigned short ctl_bits[] = {
1776 : : AC97_SC_SPSR_44K, AC97_SC_SPSR_32K, AC97_SC_SPSR_48K
1777 : : };
1778 : : static unsigned int rate_bits[] = {
1779 : : SNDRV_PCM_RATE_44100, SNDRV_PCM_RATE_32000, SNDRV_PCM_RATE_48000
1780 : : };
1781 : :
1782 [ # # ]: 0 : for (i = 0; i < (int)ARRAY_SIZE(ctl_bits); i++) {
1783 : 0 : snd_ac97_update_bits(ac97, AC97_SPDIF, AC97_SC_SPSR_MASK, ctl_bits[i]);
1784 [ # # ]: 0 : if ((snd_ac97_read(ac97, AC97_SPDIF) & AC97_SC_SPSR_MASK) == ctl_bits[i])
1785 : 0 : result |= rate_bits[i];
1786 : : }
1787 : 0 : return result;
1788 : : }
1789 : :
1790 : : /* look for the codec id table matching with the given id */
1791 : : static const struct ac97_codec_id *look_for_codec_id(const struct ac97_codec_id *table,
1792 : : unsigned int id)
1793 : : {
1794 : : const struct ac97_codec_id *pid;
1795 : :
1796 [ # # ][ # # ]: 117 : for (pid = table; pid->id; pid++)
[ + - ][ + + ]
1797 [ # # ][ # # ]: 116 : if (pid->id == (id & pid->mask))
[ + + ][ + - ]
1798 : : return pid;
1799 : : return NULL;
1800 : : }
1801 : :
1802 : 0 : void snd_ac97_get_name(struct snd_ac97 *ac97, unsigned int id, char *name, int modem)
1803 : : {
1804 : : const struct ac97_codec_id *pid;
1805 : :
1806 : 1 : sprintf(name, "0x%x %c%c%c", id,
1807 : : printable(id >> 24),
1808 : : printable(id >> 16),
1809 : : printable(id >> 8));
1810 : : pid = look_for_codec_id(snd_ac97_codec_id_vendors, id);
1811 [ + - ]: 1 : if (! pid)
1812 : 1 : return;
1813 : :
1814 : 1 : strcpy(name, pid->name);
1815 [ - + ][ # # ]: 1 : if (ac97 && pid->patch) {
1816 [ # # ][ # # ]: 0 : if ((modem && (pid->flags & AC97_MODEM_PATCH)) ||
[ # # ]
1817 [ # # ]: 0 : (! modem && ! (pid->flags & AC97_MODEM_PATCH)))
1818 : 0 : pid->patch(ac97);
1819 : : }
1820 : :
1821 : : pid = look_for_codec_id(snd_ac97_codec_ids, id);
1822 [ - + ]: 1 : if (pid) {
1823 : 0 : strcat(name, " ");
1824 : 0 : strcat(name, pid->name);
1825 [ # # ]: 0 : if (pid->mask != 0xffffffff)
1826 : 0 : sprintf(name + strlen(name), " rev %d", id & ~pid->mask);
1827 [ # # ][ # # ]: 0 : if (ac97 && pid->patch) {
1828 [ # # ][ # # ]: 0 : if ((modem && (pid->flags & AC97_MODEM_PATCH)) ||
[ # # ]
1829 [ # # ]: 0 : (! modem && ! (pid->flags & AC97_MODEM_PATCH)))
1830 : 0 : pid->patch(ac97);
1831 : : }
1832 : : } else
1833 : 1 : sprintf(name + strlen(name), " id %x", id & 0xff);
1834 : : }
1835 : :
1836 : : /**
1837 : : * snd_ac97_get_short_name - retrieve codec name
1838 : : * @ac97: the codec instance
1839 : : *
1840 : : * Return: The short identifying name of the codec.
1841 : : */
1842 : 0 : const char *snd_ac97_get_short_name(struct snd_ac97 *ac97)
1843 : : {
1844 : : const struct ac97_codec_id *pid;
1845 : :
1846 [ # # ][ # # ]: 0 : for (pid = snd_ac97_codec_ids; pid->id; pid++)
1847 [ # # ][ # # ]: 0 : if (pid->id == (ac97->id & pid->mask))
1848 : 0 : return pid->name;
1849 : : return "unknown codec";
1850 : : }
1851 : :
1852 : : EXPORT_SYMBOL(snd_ac97_get_short_name);
1853 : :
1854 : : /* wait for a while until registers are accessible after RESET
1855 : : * return 0 if ok, negative not ready
1856 : : */
1857 : 0 : static int ac97_reset_wait(struct snd_ac97 *ac97, int timeout, int with_modem)
1858 : : {
1859 : : unsigned long end_time;
1860 : : unsigned short val;
1861 : :
1862 : 0 : end_time = jiffies + timeout;
1863 : : do {
1864 : :
1865 : : /* use preliminary reads to settle the communication */
1866 : 0 : snd_ac97_read(ac97, AC97_RESET);
1867 : 0 : snd_ac97_read(ac97, AC97_VENDOR_ID1);
1868 : 0 : snd_ac97_read(ac97, AC97_VENDOR_ID2);
1869 : : /* modem? */
1870 [ # # ]: 0 : if (with_modem) {
1871 : 0 : val = snd_ac97_read(ac97, AC97_EXTENDED_MID);
1872 [ # # ][ # # ]: 0 : if (val != 0xffff && (val & 1) != 0)
1873 : : return 0;
1874 : : }
1875 [ # # ]: 0 : if (ac97->scaps & AC97_SCAP_DETECT_BY_VENDOR) {
1876 : : /* probably only Xbox issue - all registers are read as zero */
1877 : 0 : val = snd_ac97_read(ac97, AC97_VENDOR_ID1);
1878 [ # # ]: 0 : if (val != 0 && val != 0xffff)
1879 : : return 0;
1880 : : } else {
1881 : : /* because the PCM or MASTER volume registers can be modified,
1882 : : * the REC_GAIN register is used for tests
1883 : : */
1884 : : /* test if we can write to the record gain volume register */
1885 : 0 : snd_ac97_write_cache(ac97, AC97_REC_GAIN, 0x8a05);
1886 [ # # ]: 0 : if ((snd_ac97_read(ac97, AC97_REC_GAIN) & 0x7fff) == 0x0a05)
1887 : : return 0;
1888 : : }
1889 : 0 : schedule_timeout_uninterruptible(1);
1890 [ # # ]: 0 : } while (time_after_eq(end_time, jiffies));
1891 : : return -ENODEV;
1892 : : }
1893 : :
1894 : : /**
1895 : : * snd_ac97_bus - create an AC97 bus component
1896 : : * @card: the card instance
1897 : : * @num: the bus number
1898 : : * @ops: the bus callbacks table
1899 : : * @private_data: private data pointer for the new instance
1900 : : * @rbus: the pointer to store the new AC97 bus instance.
1901 : : *
1902 : : * Creates an AC97 bus component. An struct snd_ac97_bus instance is newly
1903 : : * allocated and initialized.
1904 : : *
1905 : : * The ops table must include valid callbacks (at least read and
1906 : : * write). The other callbacks, wait and reset, are not mandatory.
1907 : : *
1908 : : * The clock is set to 48000. If another clock is needed, set
1909 : : * (*rbus)->clock manually.
1910 : : *
1911 : : * The AC97 bus instance is registered as a low-level device, so you don't
1912 : : * have to release it manually.
1913 : : *
1914 : : * Return: Zero if successful, or a negative error code on failure.
1915 : : */
1916 : 0 : int snd_ac97_bus(struct snd_card *card, int num, struct snd_ac97_bus_ops *ops,
1917 : : void *private_data, struct snd_ac97_bus **rbus)
1918 : : {
1919 : : int err;
1920 : : struct snd_ac97_bus *bus;
1921 : : static struct snd_device_ops dev_ops = {
1922 : : .dev_free = snd_ac97_bus_dev_free,
1923 : : };
1924 : :
1925 [ # # ]: 0 : if (snd_BUG_ON(!card))
1926 : : return -EINVAL;
1927 : : bus = kzalloc(sizeof(*bus), GFP_KERNEL);
1928 [ # # ]: 0 : if (bus == NULL)
1929 : : return -ENOMEM;
1930 : 0 : bus->card = card;
1931 : 0 : bus->num = num;
1932 : 0 : bus->ops = ops;
1933 : 0 : bus->private_data = private_data;
1934 : 0 : bus->clock = 48000;
1935 : 0 : spin_lock_init(&bus->bus_lock);
1936 : 0 : snd_ac97_bus_proc_init(bus);
1937 [ # # ]: 0 : if ((err = snd_device_new(card, SNDRV_DEV_BUS, bus, &dev_ops)) < 0) {
1938 : 0 : snd_ac97_bus_free(bus);
1939 : 0 : return err;
1940 : : }
1941 [ # # ]: 0 : if (rbus)
1942 : 0 : *rbus = bus;
1943 : : return 0;
1944 : : }
1945 : :
1946 : : EXPORT_SYMBOL(snd_ac97_bus);
1947 : :
1948 : : /* stop no dev release warning */
1949 : 0 : static void ac97_device_release(struct device * dev)
1950 : : {
1951 : 0 : }
1952 : :
1953 : : /* register ac97 codec to bus */
1954 : 0 : static int snd_ac97_dev_register(struct snd_device *device)
1955 : : {
1956 : 0 : struct snd_ac97 *ac97 = device->device_data;
1957 : : int err;
1958 : :
1959 : 0 : ac97->dev.bus = &ac97_bus_type;
1960 : 0 : ac97->dev.parent = ac97->bus->card->dev;
1961 : 0 : ac97->dev.release = ac97_device_release;
1962 : 0 : dev_set_name(&ac97->dev, "%d-%d:%s",
1963 : 0 : ac97->bus->card->number, ac97->num,
1964 : : snd_ac97_get_short_name(ac97));
1965 [ # # ]: 0 : if ((err = device_register(&ac97->dev)) < 0) {
1966 : 0 : snd_printk(KERN_ERR "Can't register ac97 bus\n");
1967 : 0 : ac97->dev.bus = NULL;
1968 : 0 : return err;
1969 : : }
1970 : : return 0;
1971 : : }
1972 : :
1973 : : /* disconnect ac97 codec */
1974 : 0 : static int snd_ac97_dev_disconnect(struct snd_device *device)
1975 : : {
1976 : 0 : struct snd_ac97 *ac97 = device->device_data;
1977 [ # # ]: 0 : if (ac97->dev.bus)
1978 : 0 : device_unregister(&ac97->dev);
1979 : 0 : return 0;
1980 : : }
1981 : :
1982 : : /* build_ops to do nothing */
1983 : : static const struct snd_ac97_build_ops null_build_ops;
1984 : :
1985 : : #ifdef CONFIG_SND_AC97_POWER_SAVE
1986 : : static void do_update_power(struct work_struct *work)
1987 : : {
1988 : : update_power_regs(
1989 : : container_of(work, struct snd_ac97, power_work.work));
1990 : : }
1991 : : #endif
1992 : :
1993 : : /**
1994 : : * snd_ac97_mixer - create an Codec97 component
1995 : : * @bus: the AC97 bus which codec is attached to
1996 : : * @template: the template of ac97, including index, callbacks and
1997 : : * the private data.
1998 : : * @rac97: the pointer to store the new ac97 instance.
1999 : : *
2000 : : * Creates an Codec97 component. An struct snd_ac97 instance is newly
2001 : : * allocated and initialized from the template. The codec
2002 : : * is then initialized by the standard procedure.
2003 : : *
2004 : : * The template must include the codec number (num) and address (addr),
2005 : : * and the private data (private_data).
2006 : : *
2007 : : * The ac97 instance is registered as a low-level device, so you don't
2008 : : * have to release it manually.
2009 : : *
2010 : : * Return: Zero if successful, or a negative error code on failure.
2011 : : */
2012 : 0 : int snd_ac97_mixer(struct snd_ac97_bus *bus, struct snd_ac97_template *template, struct snd_ac97 **rac97)
2013 : : {
2014 : : int err;
2015 : 0 : struct snd_ac97 *ac97;
2016 : : struct snd_card *card;
2017 : : char name[64];
2018 : : unsigned long end_time;
2019 : : unsigned int reg;
2020 : : const struct ac97_codec_id *pid;
2021 : : static struct snd_device_ops ops = {
2022 : : .dev_free = snd_ac97_dev_free,
2023 : : .dev_register = snd_ac97_dev_register,
2024 : : .dev_disconnect = snd_ac97_dev_disconnect,
2025 : : };
2026 : :
2027 [ # # ]: 0 : if (rac97)
2028 : 0 : *rac97 = NULL;
2029 [ # # ]: 0 : if (snd_BUG_ON(!bus || !template))
2030 : : return -EINVAL;
2031 [ # # ]: 0 : if (snd_BUG_ON(template->num >= 4))
2032 : : return -EINVAL;
2033 [ # # ]: 0 : if (bus->codec[template->num])
2034 : : return -EBUSY;
2035 : :
2036 : 0 : card = bus->card;
2037 : : ac97 = kzalloc(sizeof(*ac97), GFP_KERNEL);
2038 [ # # ]: 0 : if (ac97 == NULL)
2039 : : return -ENOMEM;
2040 : 0 : ac97->private_data = template->private_data;
2041 : 0 : ac97->private_free = template->private_free;
2042 : 0 : ac97->bus = bus;
2043 : 0 : ac97->pci = template->pci;
2044 : 0 : ac97->num = template->num;
2045 : 0 : ac97->addr = template->addr;
2046 : 0 : ac97->scaps = template->scaps;
2047 : 0 : ac97->res_table = template->res_table;
2048 : 0 : bus->codec[ac97->num] = ac97;
2049 : 0 : mutex_init(&ac97->reg_mutex);
2050 : 0 : mutex_init(&ac97->page_mutex);
2051 : : #ifdef CONFIG_SND_AC97_POWER_SAVE
2052 : : INIT_DELAYED_WORK(&ac97->power_work, do_update_power);
2053 : : #endif
2054 : :
2055 : : #ifdef CONFIG_PCI
2056 : : if (ac97->pci) {
2057 : : pci_read_config_word(ac97->pci, PCI_SUBSYSTEM_VENDOR_ID, &ac97->subsystem_vendor);
2058 : : pci_read_config_word(ac97->pci, PCI_SUBSYSTEM_ID, &ac97->subsystem_device);
2059 : : }
2060 : : #endif
2061 [ # # ]: 0 : if (bus->ops->reset) {
2062 : 0 : bus->ops->reset(ac97);
2063 : 0 : goto __access_ok;
2064 : : }
2065 : :
2066 : 0 : ac97->id = snd_ac97_read(ac97, AC97_VENDOR_ID1) << 16;
2067 : 0 : ac97->id |= snd_ac97_read(ac97, AC97_VENDOR_ID2);
2068 [ # # ]: 0 : if (ac97->id && ac97->id != (unsigned int)-1) {
2069 : : pid = look_for_codec_id(snd_ac97_codec_ids, ac97->id);
2070 [ # # ][ # # ]: 0 : if (pid && (pid->flags & AC97_DEFAULT_POWER_OFF))
2071 : : goto __access_ok;
2072 : : }
2073 : :
2074 : : /* reset to defaults */
2075 [ # # ]: 0 : if (!(ac97->scaps & AC97_SCAP_SKIP_AUDIO))
2076 : 0 : snd_ac97_write(ac97, AC97_RESET, 0);
2077 [ # # ]: 0 : if (!(ac97->scaps & AC97_SCAP_SKIP_MODEM))
2078 : 0 : snd_ac97_write(ac97, AC97_EXTENDED_MID, 0);
2079 [ # # ]: 0 : if (bus->ops->wait)
2080 : 0 : bus->ops->wait(ac97);
2081 : : else {
2082 : 0 : udelay(50);
2083 [ # # ]: 0 : if (ac97->scaps & AC97_SCAP_SKIP_AUDIO)
2084 : 0 : err = ac97_reset_wait(ac97, msecs_to_jiffies(500), 1);
2085 : : else {
2086 : 0 : err = ac97_reset_wait(ac97, msecs_to_jiffies(500), 0);
2087 [ # # ]: 0 : if (err < 0)
2088 : 0 : err = ac97_reset_wait(ac97,
2089 : 0 : msecs_to_jiffies(500), 1);
2090 : : }
2091 [ # # ]: 0 : if (err < 0) {
2092 : 0 : snd_printk(KERN_WARNING "AC'97 %d does not respond - RESET\n", ac97->num);
2093 : : /* proceed anyway - it's often non-critical */
2094 : : }
2095 : : }
2096 : : __access_ok:
2097 : 0 : ac97->id = snd_ac97_read(ac97, AC97_VENDOR_ID1) << 16;
2098 : 0 : ac97->id |= snd_ac97_read(ac97, AC97_VENDOR_ID2);
2099 [ # # ][ # # ]: 0 : if (! (ac97->scaps & AC97_SCAP_DETECT_BY_VENDOR) &&
2100 : 0 : (ac97->id == 0x00000000 || ac97->id == 0xffffffff)) {
2101 : 0 : snd_printk(KERN_ERR "AC'97 %d access is not valid [0x%x], removing mixer.\n", ac97->num, ac97->id);
2102 : 0 : snd_ac97_free(ac97);
2103 : 0 : return -EIO;
2104 : : }
2105 : : pid = look_for_codec_id(snd_ac97_codec_ids, ac97->id);
2106 [ # # ]: 0 : if (pid)
2107 : 0 : ac97->flags |= pid->flags;
2108 : :
2109 : : /* test for AC'97 */
2110 [ # # ]: 0 : if (!(ac97->scaps & AC97_SCAP_SKIP_AUDIO) && !(ac97->scaps & AC97_SCAP_AUDIO)) {
2111 : : /* test if we can write to the record gain volume register */
2112 : 0 : snd_ac97_write_cache(ac97, AC97_REC_GAIN, 0x8a06);
2113 [ # # ]: 0 : if (((err = snd_ac97_read(ac97, AC97_REC_GAIN)) & 0x7fff) == 0x0a06)
2114 : 0 : ac97->scaps |= AC97_SCAP_AUDIO;
2115 : : }
2116 [ # # ]: 0 : if (ac97->scaps & AC97_SCAP_AUDIO) {
2117 : 0 : ac97->caps = snd_ac97_read(ac97, AC97_RESET);
2118 : 0 : ac97->ext_id = snd_ac97_read(ac97, AC97_EXTENDED_ID);
2119 [ # # ]: 0 : if (ac97->ext_id == 0xffff) /* invalid combination */
2120 : 0 : ac97->ext_id = 0;
2121 : : }
2122 : :
2123 : : /* test for MC'97 */
2124 [ # # ]: 0 : if (!(ac97->scaps & AC97_SCAP_SKIP_MODEM) && !(ac97->scaps & AC97_SCAP_MODEM)) {
2125 : 0 : ac97->ext_mid = snd_ac97_read(ac97, AC97_EXTENDED_MID);
2126 [ # # ]: 0 : if (ac97->ext_mid == 0xffff) /* invalid combination */
2127 : 0 : ac97->ext_mid = 0;
2128 [ # # ]: 0 : if (ac97->ext_mid & 1)
2129 : 0 : ac97->scaps |= AC97_SCAP_MODEM;
2130 : : }
2131 : :
2132 [ # # ][ # # ]: 0 : if (!ac97_is_audio(ac97) && !ac97_is_modem(ac97)) {
2133 [ # # ]: 0 : if (!(ac97->scaps & (AC97_SCAP_SKIP_AUDIO|AC97_SCAP_SKIP_MODEM)))
2134 : 0 : snd_printk(KERN_ERR "AC'97 %d access error (not audio or modem codec)\n", ac97->num);
2135 : 0 : snd_ac97_free(ac97);
2136 : 0 : return -EACCES;
2137 : : }
2138 : :
2139 [ # # ]: 0 : if (bus->ops->reset) // FIXME: always skipping?
2140 : : goto __ready_ok;
2141 : :
2142 : : /* FIXME: add powerdown control */
2143 [ # # ]: 0 : if (ac97_is_audio(ac97)) {
2144 : : /* nothing should be in powerdown mode */
2145 : 0 : snd_ac97_write_cache(ac97, AC97_POWERDOWN, 0);
2146 [ # # ]: 0 : if (! (ac97->flags & AC97_DEFAULT_POWER_OFF)) {
2147 : 0 : snd_ac97_write_cache(ac97, AC97_RESET, 0); /* reset to defaults */
2148 : 0 : udelay(100);
2149 : 0 : snd_ac97_write_cache(ac97, AC97_POWERDOWN, 0);
2150 : : }
2151 : : /* nothing should be in powerdown mode */
2152 : 0 : snd_ac97_write_cache(ac97, AC97_GENERAL_PURPOSE, 0);
2153 : 0 : end_time = jiffies + msecs_to_jiffies(5000);
2154 : : do {
2155 [ # # ]: 0 : if ((snd_ac97_read(ac97, AC97_POWERDOWN) & 0x0f) == 0x0f)
2156 : : goto __ready_ok;
2157 : 0 : schedule_timeout_uninterruptible(1);
2158 [ # # ]: 0 : } while (time_after_eq(end_time, jiffies));
2159 : 0 : snd_printk(KERN_WARNING "AC'97 %d analog subsections not ready\n", ac97->num);
2160 : : }
2161 : :
2162 : : /* FIXME: add powerdown control */
2163 [ # # ]: 0 : if (ac97_is_modem(ac97)) {
2164 : : unsigned char tmp;
2165 : :
2166 : : /* nothing should be in powerdown mode */
2167 : : /* note: it's important to set the rate at first */
2168 : : tmp = AC97_MEA_GPIO;
2169 [ # # ]: 0 : if (ac97->ext_mid & AC97_MEI_LINE1) {
2170 : 0 : snd_ac97_write_cache(ac97, AC97_LINE1_RATE, 8000);
2171 : : tmp |= AC97_MEA_ADC1 | AC97_MEA_DAC1;
2172 : : }
2173 [ # # ]: 0 : if (ac97->ext_mid & AC97_MEI_LINE2) {
2174 : 0 : snd_ac97_write_cache(ac97, AC97_LINE2_RATE, 8000);
2175 : 0 : tmp |= AC97_MEA_ADC2 | AC97_MEA_DAC2;
2176 : : }
2177 [ # # ]: 0 : if (ac97->ext_mid & AC97_MEI_HANDSET) {
2178 : 0 : snd_ac97_write_cache(ac97, AC97_HANDSET_RATE, 8000);
2179 : 0 : tmp |= AC97_MEA_HADC | AC97_MEA_HDAC;
2180 : : }
2181 : 0 : snd_ac97_write_cache(ac97, AC97_EXTENDED_MSTATUS, 0);
2182 : 0 : udelay(100);
2183 : : /* nothing should be in powerdown mode */
2184 : 0 : snd_ac97_write_cache(ac97, AC97_EXTENDED_MSTATUS, 0);
2185 : 0 : end_time = jiffies + msecs_to_jiffies(100);
2186 : : do {
2187 [ # # ]: 0 : if ((snd_ac97_read(ac97, AC97_EXTENDED_MSTATUS) & tmp) == tmp)
2188 : : goto __ready_ok;
2189 : 0 : schedule_timeout_uninterruptible(1);
2190 [ # # ]: 0 : } while (time_after_eq(end_time, jiffies));
2191 : 0 : snd_printk(KERN_WARNING "MC'97 %d converters and GPIO not ready (0x%x)\n", ac97->num, snd_ac97_read(ac97, AC97_EXTENDED_MSTATUS));
2192 : : }
2193 : :
2194 : : __ready_ok:
2195 [ # # ]: 0 : if (ac97_is_audio(ac97))
2196 : 0 : ac97->addr = (ac97->ext_id & AC97_EI_ADDR_MASK) >> AC97_EI_ADDR_SHIFT;
2197 : : else
2198 : 0 : ac97->addr = (ac97->ext_mid & AC97_MEI_ADDR_MASK) >> AC97_MEI_ADDR_SHIFT;
2199 [ # # ]: 0 : if (ac97->ext_id & 0x01c9) { /* L/R, MIC, SDAC, LDAC VRA support */
2200 : 0 : reg = snd_ac97_read(ac97, AC97_EXTENDED_STATUS);
2201 : 0 : reg |= ac97->ext_id & 0x01c0; /* LDAC/SDAC/CDAC */
2202 [ # # ]: 0 : if (! bus->no_vra)
2203 : 0 : reg |= ac97->ext_id & 0x0009; /* VRA/VRM */
2204 : 0 : snd_ac97_write_cache(ac97, AC97_EXTENDED_STATUS, reg);
2205 : : }
2206 [ # # ][ # # ]: 0 : if ((ac97->ext_id & AC97_EI_DRA) && bus->dra) {
2207 : : /* Intel controllers require double rate data to be put in
2208 : : * slots 7+8, so let's hope the codec supports it. */
2209 : 0 : snd_ac97_update_bits(ac97, AC97_GENERAL_PURPOSE, AC97_GP_DRSS_MASK, AC97_GP_DRSS_78);
2210 [ # # ]: 0 : if ((snd_ac97_read(ac97, AC97_GENERAL_PURPOSE) & AC97_GP_DRSS_MASK) == AC97_GP_DRSS_78)
2211 : 0 : ac97->flags |= AC97_DOUBLE_RATE;
2212 : : /* restore to slots 10/11 to avoid the confliction with surrounds */
2213 : 0 : snd_ac97_update_bits(ac97, AC97_GENERAL_PURPOSE, AC97_GP_DRSS_MASK, 0);
2214 : : }
2215 [ # # ]: 0 : if (ac97->ext_id & AC97_EI_VRA) { /* VRA support */
2216 : 0 : snd_ac97_determine_rates(ac97, AC97_PCM_FRONT_DAC_RATE, 0, &ac97->rates[AC97_RATES_FRONT_DAC]);
2217 : 0 : snd_ac97_determine_rates(ac97, AC97_PCM_LR_ADC_RATE, 0, &ac97->rates[AC97_RATES_ADC]);
2218 : : } else {
2219 : 0 : ac97->rates[AC97_RATES_FRONT_DAC] = SNDRV_PCM_RATE_48000;
2220 [ # # ]: 0 : if (ac97->flags & AC97_DOUBLE_RATE)
2221 : 0 : ac97->rates[AC97_RATES_FRONT_DAC] |= SNDRV_PCM_RATE_96000;
2222 : 0 : ac97->rates[AC97_RATES_ADC] = SNDRV_PCM_RATE_48000;
2223 : : }
2224 [ # # ]: 0 : if (ac97->ext_id & AC97_EI_SPDIF) {
2225 : : /* codec specific code (patch) should override these values */
2226 : 0 : ac97->rates[AC97_RATES_SPDIF] = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_32000;
2227 : : }
2228 [ # # ]: 0 : if (ac97->ext_id & AC97_EI_VRM) { /* MIC VRA support */
2229 : 0 : snd_ac97_determine_rates(ac97, AC97_PCM_MIC_ADC_RATE, 0, &ac97->rates[AC97_RATES_MIC_ADC]);
2230 : : } else {
2231 : 0 : ac97->rates[AC97_RATES_MIC_ADC] = SNDRV_PCM_RATE_48000;
2232 : : }
2233 [ # # ]: 0 : if (ac97->ext_id & AC97_EI_SDAC) { /* SDAC support */
2234 : 0 : snd_ac97_determine_rates(ac97, AC97_PCM_SURR_DAC_RATE, AC97_PCM_FRONT_DAC_RATE, &ac97->rates[AC97_RATES_SURR_DAC]);
2235 : 0 : ac97->scaps |= AC97_SCAP_SURROUND_DAC;
2236 : : }
2237 [ # # ]: 0 : if (ac97->ext_id & AC97_EI_LDAC) { /* LDAC support */
2238 : 0 : snd_ac97_determine_rates(ac97, AC97_PCM_LFE_DAC_RATE, AC97_PCM_FRONT_DAC_RATE, &ac97->rates[AC97_RATES_LFE_DAC]);
2239 : 0 : ac97->scaps |= AC97_SCAP_CENTER_LFE_DAC;
2240 : : }
2241 : : /* additional initializations */
2242 [ # # ]: 0 : if (bus->ops->init)
2243 : 0 : bus->ops->init(ac97);
2244 : 0 : snd_ac97_get_name(ac97, ac97->id, name, !ac97_is_audio(ac97));
2245 : 0 : snd_ac97_get_name(NULL, ac97->id, name, !ac97_is_audio(ac97)); // ac97->id might be changed in the special setup code
2246 [ # # ]: 0 : if (! ac97->build_ops)
2247 : 0 : ac97->build_ops = &null_build_ops;
2248 : :
2249 [ # # ]: 0 : if (ac97_is_audio(ac97)) {
2250 : : char comp[16];
2251 [ # # ]: 0 : if (card->mixername[0] == '\0') {
2252 : 0 : strcpy(card->mixername, name);
2253 : : } else {
2254 [ # # ]: 0 : if (strlen(card->mixername) + 1 + strlen(name) + 1 <= sizeof(card->mixername)) {
2255 : 0 : strcat(card->mixername, ",");
2256 : 0 : strcat(card->mixername, name);
2257 : : }
2258 : : }
2259 : 0 : sprintf(comp, "AC97a:%08x", ac97->id);
2260 [ # # ]: 0 : if ((err = snd_component_add(card, comp)) < 0) {
2261 : 0 : snd_ac97_free(ac97);
2262 : 0 : return err;
2263 : : }
2264 [ # # ]: 0 : if (snd_ac97_mixer_build(ac97) < 0) {
2265 : 0 : snd_ac97_free(ac97);
2266 : 0 : return -ENOMEM;
2267 : : }
2268 : : }
2269 [ # # ]: 0 : if (ac97_is_modem(ac97)) {
2270 : : char comp[16];
2271 [ # # ]: 0 : if (card->mixername[0] == '\0') {
2272 : 0 : strcpy(card->mixername, name);
2273 : : } else {
2274 [ # # ]: 0 : if (strlen(card->mixername) + 1 + strlen(name) + 1 <= sizeof(card->mixername)) {
2275 : 0 : strcat(card->mixername, ",");
2276 : 0 : strcat(card->mixername, name);
2277 : : }
2278 : : }
2279 : 0 : sprintf(comp, "AC97m:%08x", ac97->id);
2280 [ # # ]: 0 : if ((err = snd_component_add(card, comp)) < 0) {
2281 : 0 : snd_ac97_free(ac97);
2282 : 0 : return err;
2283 : : }
2284 [ # # ]: 0 : if (snd_ac97_modem_build(card, ac97) < 0) {
2285 : 0 : snd_ac97_free(ac97);
2286 : 0 : return -ENOMEM;
2287 : : }
2288 : : }
2289 [ # # ]: 0 : if (ac97_is_audio(ac97))
2290 : 0 : update_power_regs(ac97);
2291 : 0 : snd_ac97_proc_init(ac97);
2292 [ # # ]: 0 : if ((err = snd_device_new(card, SNDRV_DEV_CODEC, ac97, &ops)) < 0) {
2293 : 0 : snd_ac97_free(ac97);
2294 : 0 : return err;
2295 : : }
2296 : 0 : *rac97 = ac97;
2297 : 0 : return 0;
2298 : : }
2299 : :
2300 : : EXPORT_SYMBOL(snd_ac97_mixer);
2301 : :
2302 : : /*
2303 : : * Power down the chip.
2304 : : *
2305 : : * MASTER and HEADPHONE registers are muted but the register cache values
2306 : : * are not changed, so that the values can be restored in snd_ac97_resume().
2307 : : */
2308 : 0 : static void snd_ac97_powerdown(struct snd_ac97 *ac97)
2309 : : {
2310 : : unsigned short power;
2311 : :
2312 [ # # ]: 0 : if (ac97_is_audio(ac97)) {
2313 : : /* some codecs have stereo mute bits */
2314 : 0 : snd_ac97_write(ac97, AC97_MASTER, 0x9f9f);
2315 : 0 : snd_ac97_write(ac97, AC97_HEADPHONE, 0x9f9f);
2316 : : }
2317 : :
2318 : : /* surround, CLFE, mic powerdown */
2319 : 0 : power = ac97->regs[AC97_EXTENDED_STATUS];
2320 [ # # ]: 0 : if (ac97->scaps & AC97_SCAP_SURROUND_DAC)
2321 : 0 : power |= AC97_EA_PRJ;
2322 [ # # ]: 0 : if (ac97->scaps & AC97_SCAP_CENTER_LFE_DAC)
2323 : 0 : power |= AC97_EA_PRI | AC97_EA_PRK;
2324 : 0 : power |= AC97_EA_PRL;
2325 : 0 : snd_ac97_write(ac97, AC97_EXTENDED_STATUS, power);
2326 : :
2327 : : /* powerdown external amplifier */
2328 [ # # ]: 0 : if (ac97->scaps & AC97_SCAP_INV_EAPD)
2329 : 0 : power = ac97->regs[AC97_POWERDOWN] & ~AC97_PD_EAPD;
2330 [ # # ]: 0 : else if (! (ac97->scaps & AC97_SCAP_EAPD_LED))
2331 : 0 : power = ac97->regs[AC97_POWERDOWN] | AC97_PD_EAPD;
2332 : : power |= AC97_PD_PR6; /* Headphone amplifier powerdown */
2333 : 0 : power |= AC97_PD_PR0 | AC97_PD_PR1; /* ADC & DAC powerdown */
2334 : 0 : snd_ac97_write(ac97, AC97_POWERDOWN, power);
2335 : 0 : udelay(100);
2336 : 0 : power |= AC97_PD_PR2; /* Analog Mixer powerdown (Vref on) */
2337 : 0 : snd_ac97_write(ac97, AC97_POWERDOWN, power);
2338 : : if (ac97_is_power_save_mode(ac97)) {
2339 : : power |= AC97_PD_PR3; /* Analog Mixer powerdown */
2340 : : snd_ac97_write(ac97, AC97_POWERDOWN, power);
2341 : : udelay(100);
2342 : : /* AC-link powerdown, internal Clk disable */
2343 : : /* FIXME: this may cause click noises on some boards */
2344 : : power |= AC97_PD_PR4 | AC97_PD_PR5;
2345 : : snd_ac97_write(ac97, AC97_POWERDOWN, power);
2346 : : }
2347 : 0 : }
2348 : :
2349 : :
2350 : : struct ac97_power_reg {
2351 : : unsigned short reg;
2352 : : unsigned short power_reg;
2353 : : unsigned short mask;
2354 : : };
2355 : :
2356 : : enum { PWIDX_ADC, PWIDX_FRONT, PWIDX_CLFE, PWIDX_SURR, PWIDX_MIC, PWIDX_SIZE };
2357 : :
2358 : : static struct ac97_power_reg power_regs[PWIDX_SIZE] = {
2359 : : [PWIDX_ADC] = { AC97_PCM_LR_ADC_RATE, AC97_POWERDOWN, AC97_PD_PR0},
2360 : : [PWIDX_FRONT] = { AC97_PCM_FRONT_DAC_RATE, AC97_POWERDOWN, AC97_PD_PR1},
2361 : : [PWIDX_CLFE] = { AC97_PCM_LFE_DAC_RATE, AC97_EXTENDED_STATUS,
2362 : : AC97_EA_PRI | AC97_EA_PRK},
2363 : : [PWIDX_SURR] = { AC97_PCM_SURR_DAC_RATE, AC97_EXTENDED_STATUS,
2364 : : AC97_EA_PRJ},
2365 : : [PWIDX_MIC] = { AC97_PCM_MIC_ADC_RATE, AC97_EXTENDED_STATUS,
2366 : : AC97_EA_PRL},
2367 : : };
2368 : :
2369 : : #ifdef CONFIG_SND_AC97_POWER_SAVE
2370 : : /**
2371 : : * snd_ac97_update_power - update the powerdown register
2372 : : * @ac97: the codec instance
2373 : : * @reg: the rate register, e.g. AC97_PCM_FRONT_DAC_RATE
2374 : : * @powerup: non-zero when power up the part
2375 : : *
2376 : : * Update the AC97 powerdown register bits of the given part.
2377 : : *
2378 : : * Return: Zero.
2379 : : */
2380 : : int snd_ac97_update_power(struct snd_ac97 *ac97, int reg, int powerup)
2381 : : {
2382 : : int i;
2383 : :
2384 : : if (! ac97)
2385 : : return 0;
2386 : :
2387 : : if (reg) {
2388 : : /* SPDIF requires DAC power, too */
2389 : : if (reg == AC97_SPDIF)
2390 : : reg = AC97_PCM_FRONT_DAC_RATE;
2391 : : for (i = 0; i < PWIDX_SIZE; i++) {
2392 : : if (power_regs[i].reg == reg) {
2393 : : if (powerup)
2394 : : ac97->power_up |= (1 << i);
2395 : : else
2396 : : ac97->power_up &= ~(1 << i);
2397 : : break;
2398 : : }
2399 : : }
2400 : : }
2401 : :
2402 : : if (ac97_is_power_save_mode(ac97) && !powerup)
2403 : : /* adjust power-down bits after two seconds delay
2404 : : * (for avoiding loud click noises for many (OSS) apps
2405 : : * that open/close frequently)
2406 : : */
2407 : : schedule_delayed_work(&ac97->power_work,
2408 : : msecs_to_jiffies(power_save * 1000));
2409 : : else {
2410 : : cancel_delayed_work(&ac97->power_work);
2411 : : update_power_regs(ac97);
2412 : : }
2413 : :
2414 : : return 0;
2415 : : }
2416 : :
2417 : : EXPORT_SYMBOL(snd_ac97_update_power);
2418 : : #endif /* CONFIG_SND_AC97_POWER_SAVE */
2419 : :
2420 : 0 : static void update_power_regs(struct snd_ac97 *ac97)
2421 : : {
2422 : : unsigned int power_up, bits;
2423 : : int i;
2424 : :
2425 : : power_up = (1 << PWIDX_FRONT) | (1 << PWIDX_ADC);
2426 : : power_up |= (1 << PWIDX_MIC);
2427 [ # # ]: 0 : if (ac97->scaps & AC97_SCAP_SURROUND_DAC)
2428 : : power_up |= (1 << PWIDX_SURR);
2429 [ # # ]: 0 : if (ac97->scaps & AC97_SCAP_CENTER_LFE_DAC)
2430 : 0 : power_up |= (1 << PWIDX_CLFE);
2431 : : #ifdef CONFIG_SND_AC97_POWER_SAVE
2432 : : if (ac97_is_power_save_mode(ac97))
2433 : : power_up = ac97->power_up;
2434 : : #endif
2435 : : if (power_up) {
2436 [ # # ]: 0 : if (ac97->regs[AC97_POWERDOWN] & AC97_PD_PR2) {
2437 : : /* needs power-up analog mix and vref */
2438 : 0 : snd_ac97_update_bits(ac97, AC97_POWERDOWN,
2439 : : AC97_PD_PR3, 0);
2440 : 0 : msleep(1);
2441 : 0 : snd_ac97_update_bits(ac97, AC97_POWERDOWN,
2442 : : AC97_PD_PR2, 0);
2443 : : }
2444 : : }
2445 [ # # ]: 0 : for (i = 0; i < PWIDX_SIZE; i++) {
2446 [ # # ]: 0 : if (power_up & (1 << i))
2447 : : bits = 0;
2448 : : else
2449 : 0 : bits = power_regs[i].mask;
2450 : 0 : snd_ac97_update_bits(ac97, power_regs[i].power_reg,
2451 : : power_regs[i].mask, bits);
2452 : : }
2453 : : if (! power_up) {
2454 : : if (! (ac97->regs[AC97_POWERDOWN] & AC97_PD_PR2)) {
2455 : : /* power down analog mix and vref */
2456 : : snd_ac97_update_bits(ac97, AC97_POWERDOWN,
2457 : : AC97_PD_PR2, AC97_PD_PR2);
2458 : : snd_ac97_update_bits(ac97, AC97_POWERDOWN,
2459 : : AC97_PD_PR3, AC97_PD_PR3);
2460 : : }
2461 : : }
2462 : 0 : }
2463 : :
2464 : :
2465 : : #ifdef CONFIG_PM
2466 : : /**
2467 : : * snd_ac97_suspend - General suspend function for AC97 codec
2468 : : * @ac97: the ac97 instance
2469 : : *
2470 : : * Suspends the codec, power down the chip.
2471 : : */
2472 : 0 : void snd_ac97_suspend(struct snd_ac97 *ac97)
2473 : : {
2474 [ # # ]: 0 : if (! ac97)
2475 : 0 : return;
2476 [ # # ]: 0 : if (ac97->build_ops->suspend)
2477 : 0 : ac97->build_ops->suspend(ac97);
2478 : : #ifdef CONFIG_SND_AC97_POWER_SAVE
2479 : : cancel_delayed_work_sync(&ac97->power_work);
2480 : : #endif
2481 : 0 : snd_ac97_powerdown(ac97);
2482 : : }
2483 : :
2484 : : EXPORT_SYMBOL(snd_ac97_suspend);
2485 : :
2486 : : /*
2487 : : * restore ac97 status
2488 : : */
2489 : 0 : static void snd_ac97_restore_status(struct snd_ac97 *ac97)
2490 : : {
2491 : : int i;
2492 : :
2493 [ # # ]: 0 : for (i = 2; i < 0x7c ; i += 2) {
2494 [ # # ]: 0 : if (i == AC97_POWERDOWN || i == AC97_EXTENDED_ID)
2495 : 0 : continue;
2496 : : /* restore only accessible registers
2497 : : * some chip (e.g. nm256) may hang up when unsupported registers
2498 : : * are accessed..!
2499 : : */
2500 [ # # ]: 0 : if (test_bit(i, ac97->reg_accessed)) {
2501 : 0 : snd_ac97_write(ac97, i, ac97->regs[i]);
2502 : 0 : snd_ac97_read(ac97, i);
2503 : : }
2504 : : }
2505 : 0 : }
2506 : :
2507 : : /*
2508 : : * restore IEC958 status
2509 : : */
2510 : 0 : static void snd_ac97_restore_iec958(struct snd_ac97 *ac97)
2511 : : {
2512 [ # # ]: 0 : if (ac97->ext_id & AC97_EI_SPDIF) {
2513 [ # # ]: 0 : if (ac97->regs[AC97_EXTENDED_STATUS] & AC97_EA_SPDIF) {
2514 : : /* reset spdif status */
2515 : 0 : snd_ac97_update_bits(ac97, AC97_EXTENDED_STATUS, AC97_EA_SPDIF, 0);
2516 : 0 : snd_ac97_write(ac97, AC97_EXTENDED_STATUS, ac97->regs[AC97_EXTENDED_STATUS]);
2517 [ # # ]: 0 : if (ac97->flags & AC97_CS_SPDIF)
2518 : 0 : snd_ac97_write(ac97, AC97_CSR_SPDIF, ac97->regs[AC97_CSR_SPDIF]);
2519 : : else
2520 : 0 : snd_ac97_write(ac97, AC97_SPDIF, ac97->regs[AC97_SPDIF]);
2521 : 0 : snd_ac97_update_bits(ac97, AC97_EXTENDED_STATUS, AC97_EA_SPDIF, AC97_EA_SPDIF); /* turn on again */
2522 : : }
2523 : : }
2524 : 0 : }
2525 : :
2526 : : /**
2527 : : * snd_ac97_resume - General resume function for AC97 codec
2528 : : * @ac97: the ac97 instance
2529 : : *
2530 : : * Do the standard resume procedure, power up and restoring the
2531 : : * old register values.
2532 : : */
2533 : 0 : void snd_ac97_resume(struct snd_ac97 *ac97)
2534 : : {
2535 : : unsigned long end_time;
2536 : :
2537 [ # # ]: 0 : if (! ac97)
2538 : 0 : return;
2539 : :
2540 [ # # ]: 0 : if (ac97->bus->ops->reset) {
2541 : 0 : ac97->bus->ops->reset(ac97);
2542 : 0 : goto __reset_ready;
2543 : : }
2544 : :
2545 : 0 : snd_ac97_write(ac97, AC97_POWERDOWN, 0);
2546 [ # # ]: 0 : if (! (ac97->flags & AC97_DEFAULT_POWER_OFF)) {
2547 [ # # ]: 0 : if (!(ac97->scaps & AC97_SCAP_SKIP_AUDIO))
2548 : 0 : snd_ac97_write(ac97, AC97_RESET, 0);
2549 [ # # ]: 0 : else if (!(ac97->scaps & AC97_SCAP_SKIP_MODEM))
2550 : 0 : snd_ac97_write(ac97, AC97_EXTENDED_MID, 0);
2551 : 0 : udelay(100);
2552 : 0 : snd_ac97_write(ac97, AC97_POWERDOWN, 0);
2553 : : }
2554 : 0 : snd_ac97_write(ac97, AC97_GENERAL_PURPOSE, 0);
2555 : :
2556 : 0 : snd_ac97_write(ac97, AC97_POWERDOWN, ac97->regs[AC97_POWERDOWN]);
2557 [ # # ]: 0 : if (ac97_is_audio(ac97)) {
2558 : 0 : ac97->bus->ops->write(ac97, AC97_MASTER, 0x8101);
2559 : 0 : end_time = jiffies + msecs_to_jiffies(100);
2560 : : do {
2561 [ # # ]: 0 : if (snd_ac97_read(ac97, AC97_MASTER) == 0x8101)
2562 : : break;
2563 : 0 : schedule_timeout_uninterruptible(1);
2564 [ # # ]: 0 : } while (time_after_eq(end_time, jiffies));
2565 : : /* FIXME: extra delay */
2566 : 0 : ac97->bus->ops->write(ac97, AC97_MASTER, AC97_MUTE_MASK_MONO);
2567 [ # # ]: 0 : if (snd_ac97_read(ac97, AC97_MASTER) != AC97_MUTE_MASK_MONO)
2568 : 0 : msleep(250);
2569 : : } else {
2570 : 0 : end_time = jiffies + msecs_to_jiffies(100);
2571 : : do {
2572 : 0 : unsigned short val = snd_ac97_read(ac97, AC97_EXTENDED_MID);
2573 [ # # ][ # # ]: 0 : if (val != 0xffff && (val & 1) != 0)
2574 : : break;
2575 : 0 : schedule_timeout_uninterruptible(1);
2576 [ # # ]: 0 : } while (time_after_eq(end_time, jiffies));
2577 : : }
2578 : : __reset_ready:
2579 : :
2580 [ # # ]: 0 : if (ac97->bus->ops->init)
2581 : 0 : ac97->bus->ops->init(ac97);
2582 : :
2583 [ # # ]: 0 : if (ac97->build_ops->resume)
2584 : 0 : ac97->build_ops->resume(ac97);
2585 : : else {
2586 : 0 : snd_ac97_restore_status(ac97);
2587 : 0 : snd_ac97_restore_iec958(ac97);
2588 : : }
2589 : : }
2590 : :
2591 : : EXPORT_SYMBOL(snd_ac97_resume);
2592 : : #endif
2593 : :
2594 : :
2595 : : /*
2596 : : * Hardware tuning
2597 : : */
2598 : 0 : static void set_ctl_name(char *dst, const char *src, const char *suffix)
2599 : : {
2600 [ # # ]: 0 : if (suffix)
2601 : 0 : sprintf(dst, "%s %s", src, suffix);
2602 : : else
2603 : 0 : strcpy(dst, src);
2604 : 0 : }
2605 : :
2606 : : /* remove the control with the given name and optional suffix */
2607 : 0 : static int snd_ac97_remove_ctl(struct snd_ac97 *ac97, const char *name,
2608 : : const char *suffix)
2609 : : {
2610 : : struct snd_ctl_elem_id id;
2611 : 0 : memset(&id, 0, sizeof(id));
2612 : 0 : set_ctl_name(id.name, name, suffix);
2613 : 0 : id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
2614 : 0 : return snd_ctl_remove_id(ac97->bus->card, &id);
2615 : : }
2616 : :
2617 : 0 : static struct snd_kcontrol *ctl_find(struct snd_ac97 *ac97, const char *name, const char *suffix)
2618 : : {
2619 : : struct snd_ctl_elem_id sid;
2620 : 0 : memset(&sid, 0, sizeof(sid));
2621 : 0 : set_ctl_name(sid.name, name, suffix);
2622 : 0 : sid.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
2623 : 0 : return snd_ctl_find_id(ac97->bus->card, &sid);
2624 : : }
2625 : :
2626 : : /* rename the control with the given name and optional suffix */
2627 : 0 : static int snd_ac97_rename_ctl(struct snd_ac97 *ac97, const char *src,
2628 : : const char *dst, const char *suffix)
2629 : : {
2630 : 0 : struct snd_kcontrol *kctl = ctl_find(ac97, src, suffix);
2631 [ # # ]: 0 : if (kctl) {
2632 : 0 : set_ctl_name(kctl->id.name, dst, suffix);
2633 : 0 : return 0;
2634 : : }
2635 : : return -ENOENT;
2636 : : }
2637 : :
2638 : : /* rename both Volume and Switch controls - don't check the return value */
2639 : 0 : static void snd_ac97_rename_vol_ctl(struct snd_ac97 *ac97, const char *src,
2640 : : const char *dst)
2641 : : {
2642 : 0 : snd_ac97_rename_ctl(ac97, src, dst, "Switch");
2643 : 0 : snd_ac97_rename_ctl(ac97, src, dst, "Volume");
2644 : 0 : }
2645 : :
2646 : : /* swap controls */
2647 : 0 : static int snd_ac97_swap_ctl(struct snd_ac97 *ac97, const char *s1,
2648 : : const char *s2, const char *suffix)
2649 : : {
2650 : : struct snd_kcontrol *kctl1, *kctl2;
2651 : 0 : kctl1 = ctl_find(ac97, s1, suffix);
2652 : 0 : kctl2 = ctl_find(ac97, s2, suffix);
2653 [ # # ]: 0 : if (kctl1 && kctl2) {
2654 : 0 : set_ctl_name(kctl1->id.name, s2, suffix);
2655 : 0 : set_ctl_name(kctl2->id.name, s1, suffix);
2656 : 0 : return 0;
2657 : : }
2658 : : return -ENOENT;
2659 : : }
2660 : :
2661 : : #if 1
2662 : : /* bind hp and master controls instead of using only hp control */
2663 : 0 : static int bind_hp_volsw_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
2664 : : {
2665 : 0 : int err = snd_ac97_put_volsw(kcontrol, ucontrol);
2666 [ # # ]: 0 : if (err > 0) {
2667 : 0 : unsigned long priv_saved = kcontrol->private_value;
2668 : 0 : kcontrol->private_value = (kcontrol->private_value & ~0xff) | AC97_HEADPHONE;
2669 : 0 : snd_ac97_put_volsw(kcontrol, ucontrol);
2670 : 0 : kcontrol->private_value = priv_saved;
2671 : : }
2672 : 0 : return err;
2673 : : }
2674 : :
2675 : : /* ac97 tune: bind Master and Headphone controls */
2676 : 0 : static int tune_hp_only(struct snd_ac97 *ac97)
2677 : : {
2678 : 0 : struct snd_kcontrol *msw = ctl_find(ac97, "Master Playback Switch", NULL);
2679 : 0 : struct snd_kcontrol *mvol = ctl_find(ac97, "Master Playback Volume", NULL);
2680 [ # # ]: 0 : if (! msw || ! mvol)
2681 : : return -ENOENT;
2682 : 0 : msw->put = bind_hp_volsw_put;
2683 : 0 : mvol->put = bind_hp_volsw_put;
2684 : 0 : snd_ac97_remove_ctl(ac97, "Headphone Playback", "Switch");
2685 : 0 : snd_ac97_remove_ctl(ac97, "Headphone Playback", "Volume");
2686 : 0 : return 0;
2687 : : }
2688 : :
2689 : : #else
2690 : : /* ac97 tune: use Headphone control as master */
2691 : : static int tune_hp_only(struct snd_ac97 *ac97)
2692 : : {
2693 : : if (ctl_find(ac97, "Headphone Playback Switch", NULL) == NULL)
2694 : : return -ENOENT;
2695 : : snd_ac97_remove_ctl(ac97, "Master Playback", "Switch");
2696 : : snd_ac97_remove_ctl(ac97, "Master Playback", "Volume");
2697 : : snd_ac97_rename_vol_ctl(ac97, "Headphone Playback", "Master Playback");
2698 : : return 0;
2699 : : }
2700 : : #endif
2701 : :
2702 : : /* ac97 tune: swap Headphone and Master controls */
2703 : 0 : static int tune_swap_hp(struct snd_ac97 *ac97)
2704 : : {
2705 [ # # ]: 0 : if (ctl_find(ac97, "Headphone Playback Switch", NULL) == NULL)
2706 : : return -ENOENT;
2707 : 0 : snd_ac97_rename_vol_ctl(ac97, "Master Playback", "Line-Out Playback");
2708 : 0 : snd_ac97_rename_vol_ctl(ac97, "Headphone Playback", "Master Playback");
2709 : 0 : return 0;
2710 : : }
2711 : :
2712 : : /* ac97 tune: swap Surround and Master controls */
2713 : 0 : static int tune_swap_surround(struct snd_ac97 *ac97)
2714 : : {
2715 [ # # # # ]: 0 : if (snd_ac97_swap_ctl(ac97, "Master Playback", "Surround Playback", "Switch") ||
2716 : 0 : snd_ac97_swap_ctl(ac97, "Master Playback", "Surround Playback", "Volume"))
2717 : : return -ENOENT;
2718 : : return 0;
2719 : : }
2720 : :
2721 : : /* ac97 tune: set up mic sharing for AD codecs */
2722 : 0 : static int tune_ad_sharing(struct snd_ac97 *ac97)
2723 : : {
2724 : : unsigned short scfg;
2725 [ # # ]: 0 : if ((ac97->id & 0xffffff00) != 0x41445300) {
2726 : 0 : snd_printk(KERN_ERR "ac97_quirk AD_SHARING is only for AD codecs\n");
2727 : 0 : return -EINVAL;
2728 : : }
2729 : : /* Turn on OMS bit to route microphone to back panel */
2730 : 0 : scfg = snd_ac97_read(ac97, AC97_AD_SERIAL_CFG);
2731 : 0 : snd_ac97_write_cache(ac97, AC97_AD_SERIAL_CFG, scfg | 0x0200);
2732 : 0 : return 0;
2733 : : }
2734 : :
2735 : : static const struct snd_kcontrol_new snd_ac97_alc_jack_detect =
2736 : : AC97_SINGLE("Jack Detect", AC97_ALC650_CLOCK, 5, 1, 0);
2737 : :
2738 : : /* ac97 tune: set up ALC jack-select */
2739 : 0 : static int tune_alc_jack(struct snd_ac97 *ac97)
2740 : : {
2741 [ # # ]: 0 : if ((ac97->id & 0xffffff00) != 0x414c4700) {
2742 : 0 : snd_printk(KERN_ERR "ac97_quirk ALC_JACK is only for Realtek codecs\n");
2743 : 0 : return -EINVAL;
2744 : : }
2745 : 0 : snd_ac97_update_bits(ac97, 0x7a, 0x20, 0x20); /* select jack detect function */
2746 : 0 : snd_ac97_update_bits(ac97, 0x7a, 0x01, 0x01); /* Line-out auto mute */
2747 [ # # ]: 0 : if (ac97->id == AC97_ID_ALC658D)
2748 : 0 : snd_ac97_update_bits(ac97, 0x74, 0x0800, 0x0800);
2749 : 0 : return snd_ctl_add(ac97->bus->card, snd_ac97_cnew(&snd_ac97_alc_jack_detect, ac97));
2750 : : }
2751 : :
2752 : : /* ac97 tune: inversed EAPD bit */
2753 : 0 : static int tune_inv_eapd(struct snd_ac97 *ac97)
2754 : : {
2755 : 0 : struct snd_kcontrol *kctl = ctl_find(ac97, "External Amplifier", NULL);
2756 [ # # ]: 0 : if (! kctl)
2757 : : return -ENOENT;
2758 : : set_inv_eapd(ac97, kctl);
2759 : 0 : return 0;
2760 : : }
2761 : :
2762 : 0 : static int master_mute_sw_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
2763 : : {
2764 : 0 : int err = snd_ac97_put_volsw(kcontrol, ucontrol);
2765 [ # # ]: 0 : if (err > 0) {
2766 : 0 : struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
2767 : 0 : int shift = (kcontrol->private_value >> 8) & 0x0f;
2768 : 0 : int rshift = (kcontrol->private_value >> 12) & 0x0f;
2769 : : unsigned short mask;
2770 [ # # ]: 0 : if (shift != rshift)
2771 : : mask = AC97_MUTE_MASK_STEREO;
2772 : : else
2773 : : mask = AC97_MUTE_MASK_MONO;
2774 [ # # ]: 0 : snd_ac97_update_bits(ac97, AC97_POWERDOWN, AC97_PD_EAPD,
2775 : 0 : (ac97->regs[AC97_MASTER] & mask) == mask ?
2776 : : AC97_PD_EAPD : 0);
2777 : : }
2778 : 0 : return err;
2779 : : }
2780 : :
2781 : : /* ac97 tune: EAPD controls mute LED bound with the master mute */
2782 : 0 : static int tune_mute_led(struct snd_ac97 *ac97)
2783 : : {
2784 : 0 : struct snd_kcontrol *msw = ctl_find(ac97, "Master Playback Switch", NULL);
2785 [ # # ]: 0 : if (! msw)
2786 : : return -ENOENT;
2787 : 0 : msw->put = master_mute_sw_put;
2788 : 0 : snd_ac97_remove_ctl(ac97, "External Amplifier", NULL);
2789 : 0 : snd_ac97_update_bits(
2790 : : ac97, AC97_POWERDOWN,
2791 : : AC97_PD_EAPD, AC97_PD_EAPD /* mute LED on */
2792 : : );
2793 : 0 : ac97->scaps |= AC97_SCAP_EAPD_LED;
2794 : 0 : return 0;
2795 : : }
2796 : :
2797 : 0 : static int hp_master_mute_sw_put(struct snd_kcontrol *kcontrol,
2798 : : struct snd_ctl_elem_value *ucontrol)
2799 : : {
2800 : 0 : int err = bind_hp_volsw_put(kcontrol, ucontrol);
2801 [ # # ]: 0 : if (err > 0) {
2802 : 0 : struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
2803 : 0 : int shift = (kcontrol->private_value >> 8) & 0x0f;
2804 : 0 : int rshift = (kcontrol->private_value >> 12) & 0x0f;
2805 : : unsigned short mask;
2806 [ # # ]: 0 : if (shift != rshift)
2807 : : mask = AC97_MUTE_MASK_STEREO;
2808 : : else
2809 : : mask = AC97_MUTE_MASK_MONO;
2810 [ # # ]: 0 : snd_ac97_update_bits(ac97, AC97_POWERDOWN, AC97_PD_EAPD,
2811 : 0 : (ac97->regs[AC97_MASTER] & mask) == mask ?
2812 : : AC97_PD_EAPD : 0);
2813 : : }
2814 : 0 : return err;
2815 : : }
2816 : :
2817 : 0 : static int tune_hp_mute_led(struct snd_ac97 *ac97)
2818 : : {
2819 : 0 : struct snd_kcontrol *msw = ctl_find(ac97, "Master Playback Switch", NULL);
2820 : 0 : struct snd_kcontrol *mvol = ctl_find(ac97, "Master Playback Volume", NULL);
2821 [ # # ]: 0 : if (! msw || ! mvol)
2822 : : return -ENOENT;
2823 : 0 : msw->put = hp_master_mute_sw_put;
2824 : 0 : mvol->put = bind_hp_volsw_put;
2825 : 0 : snd_ac97_remove_ctl(ac97, "External Amplifier", NULL);
2826 : 0 : snd_ac97_remove_ctl(ac97, "Headphone Playback", "Switch");
2827 : 0 : snd_ac97_remove_ctl(ac97, "Headphone Playback", "Volume");
2828 : 0 : snd_ac97_update_bits(
2829 : : ac97, AC97_POWERDOWN,
2830 : : AC97_PD_EAPD, AC97_PD_EAPD /* mute LED on */
2831 : : );
2832 : 0 : return 0;
2833 : : }
2834 : :
2835 : : struct quirk_table {
2836 : : const char *name;
2837 : : int (*func)(struct snd_ac97 *);
2838 : : };
2839 : :
2840 : : static struct quirk_table applicable_quirks[] = {
2841 : : { "none", NULL },
2842 : : { "hp_only", tune_hp_only },
2843 : : { "swap_hp", tune_swap_hp },
2844 : : { "swap_surround", tune_swap_surround },
2845 : : { "ad_sharing", tune_ad_sharing },
2846 : : { "alc_jack", tune_alc_jack },
2847 : : { "inv_eapd", tune_inv_eapd },
2848 : : { "mute_led", tune_mute_led },
2849 : : { "hp_mute_led", tune_hp_mute_led },
2850 : : };
2851 : :
2852 : : /* apply the quirk with the given type */
2853 : : static int apply_quirk(struct snd_ac97 *ac97, int type)
2854 : : {
2855 [ # # ]: 0 : if (type <= 0)
[ # # # # ]
2856 : : return 0;
2857 [ # # ][ # # ]: 0 : else if (type >= ARRAY_SIZE(applicable_quirks))
[ # # ]
2858 : : return -EINVAL;
2859 [ # # ][ # # ]: 0 : if (applicable_quirks[type].func)
[ # # ]
2860 : 0 : return applicable_quirks[type].func(ac97);
2861 : : return 0;
2862 : : }
2863 : :
2864 : : /* apply the quirk with the given name */
2865 : 0 : static int apply_quirk_str(struct snd_ac97 *ac97, const char *typestr)
2866 : : {
2867 : : int i;
2868 : : struct quirk_table *q;
2869 : :
2870 [ # # ]: 0 : for (i = 0; i < ARRAY_SIZE(applicable_quirks); i++) {
2871 : 0 : q = &applicable_quirks[i];
2872 [ # # ][ # # ]: 0 : if (q->name && ! strcmp(typestr, q->name))
2873 : 0 : return apply_quirk(ac97, i);
2874 : : }
2875 : : /* for compatibility, accept the numbers, too */
2876 [ # # ]: 0 : if (*typestr >= '0' && *typestr <= '9')
2877 : 0 : return apply_quirk(ac97, (int)simple_strtoul(typestr, NULL, 10));
2878 : : return -EINVAL;
2879 : : }
2880 : :
2881 : : /**
2882 : : * snd_ac97_tune_hardware - tune up the hardware
2883 : : * @ac97: the ac97 instance
2884 : : * @quirk: quirk list
2885 : : * @override: explicit quirk value (overrides the list if non-NULL)
2886 : : *
2887 : : * Do some workaround for each pci device, such as renaming of the
2888 : : * headphone (true line-out) control as "Master".
2889 : : * The quirk-list must be terminated with a zero-filled entry.
2890 : : *
2891 : : * Return: Zero if successful, or a negative error code on failure.
2892 : : */
2893 : :
2894 : 0 : int snd_ac97_tune_hardware(struct snd_ac97 *ac97, struct ac97_quirk *quirk, const char *override)
2895 : : {
2896 : : int result;
2897 : :
2898 : : /* quirk overriden? */
2899 [ # # ][ # # ]: 0 : if (override && strcmp(override, "-1") && strcmp(override, "default")) {
[ # # ]
2900 : 0 : result = apply_quirk_str(ac97, override);
2901 [ # # ]: 0 : if (result < 0)
2902 : 0 : snd_printk(KERN_ERR "applying quirk type %s failed (%d)\n", override, result);
2903 : 0 : return result;
2904 : : }
2905 : :
2906 [ # # ]: 0 : if (! quirk)
2907 : : return -EINVAL;
2908 : :
2909 [ # # ]: 0 : for (; quirk->subvendor; quirk++) {
2910 [ # # ]: 0 : if (quirk->subvendor != ac97->subsystem_vendor)
2911 : 0 : continue;
2912 [ # # ][ # # ]: 0 : if ((! quirk->mask && quirk->subdevice == ac97->subsystem_device) ||
[ # # ]
2913 : 0 : quirk->subdevice == (quirk->mask & ac97->subsystem_device)) {
2914 [ # # ][ # # ]: 0 : if (quirk->codec_id && quirk->codec_id != ac97->id)
2915 : 0 : continue;
2916 : : snd_printdd("ac97 quirk for %s (%04x:%04x)\n", quirk->name, ac97->subsystem_vendor, ac97->subsystem_device);
2917 : 0 : result = apply_quirk(ac97, quirk->type);
2918 [ # # ]: 0 : if (result < 0)
2919 : 0 : snd_printk(KERN_ERR "applying quirk type %d for %s failed (%d)\n", quirk->type, quirk->name, result);
2920 : 0 : return result;
2921 : : }
2922 : : }
2923 : : return 0;
2924 : : }
2925 : :
2926 : : EXPORT_SYMBOL(snd_ac97_tune_hardware);
2927 : :
2928 : : /*
2929 : : * INIT part
2930 : : */
2931 : :
2932 : 0 : static int __init alsa_ac97_init(void)
2933 : : {
2934 : 0 : return 0;
2935 : : }
2936 : :
2937 : 0 : static void __exit alsa_ac97_exit(void)
2938 : : {
2939 : 0 : }
2940 : :
2941 : : module_init(alsa_ac97_init)
2942 : : module_exit(alsa_ac97_exit)
|