Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/sound/pci/ac97/ac97_proc.c
10818 views
1
/*
2
* Copyright (c) by Jaroslav Kysela <[email protected]>
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/mutex.h>
26
27
#include <sound/core.h>
28
#include <sound/ac97_codec.h>
29
#include <sound/asoundef.h>
30
#include "ac97_local.h"
31
#include "ac97_id.h"
32
33
/*
34
* proc interface
35
*/
36
37
static void snd_ac97_proc_read_functions(struct snd_ac97 *ac97, struct snd_info_buffer *buffer)
38
{
39
int header = 0, function;
40
unsigned short info, sense_info;
41
static const char *function_names[12] = {
42
"Master Out", "AUX Out", "Center/LFE Out", "SPDIF Out",
43
"Phone In", "Mic 1", "Mic 2", "Line In", "CD In", "Video In",
44
"Aux In", "Mono Out"
45
};
46
static const char *locations[8] = {
47
"Rear I/O Panel", "Front Panel", "Motherboard", "Dock/External",
48
"reserved", "reserved", "reserved", "NC/unused"
49
};
50
51
for (function = 0; function < 12; ++function) {
52
snd_ac97_write(ac97, AC97_FUNC_SELECT, function << 1);
53
info = snd_ac97_read(ac97, AC97_FUNC_INFO);
54
if (!(info & 0x0001))
55
continue;
56
if (!header) {
57
snd_iprintf(buffer, "\n Gain Inverted Buffer delay Location\n");
58
header = 1;
59
}
60
sense_info = snd_ac97_read(ac97, AC97_SENSE_INFO);
61
snd_iprintf(buffer, "%-17s: %3d.%d dBV %c %2d/fs %s\n",
62
function_names[function],
63
(info & 0x8000 ? -1 : 1) * ((info & 0x7000) >> 12) * 3 / 2,
64
((info & 0x0800) >> 11) * 5,
65
info & 0x0400 ? 'X' : '-',
66
(info & 0x03e0) >> 5,
67
locations[sense_info >> 13]);
68
}
69
}
70
71
static const char *snd_ac97_stereo_enhancements[] =
72
{
73
/* 0 */ "No 3D Stereo Enhancement",
74
/* 1 */ "Analog Devices Phat Stereo",
75
/* 2 */ "Creative Stereo Enhancement",
76
/* 3 */ "National Semi 3D Stereo Enhancement",
77
/* 4 */ "YAMAHA Ymersion",
78
/* 5 */ "BBE 3D Stereo Enhancement",
79
/* 6 */ "Crystal Semi 3D Stereo Enhancement",
80
/* 7 */ "Qsound QXpander",
81
/* 8 */ "Spatializer 3D Stereo Enhancement",
82
/* 9 */ "SRS 3D Stereo Enhancement",
83
/* 10 */ "Platform Tech 3D Stereo Enhancement",
84
/* 11 */ "AKM 3D Audio",
85
/* 12 */ "Aureal Stereo Enhancement",
86
/* 13 */ "Aztech 3D Enhancement",
87
/* 14 */ "Binaura 3D Audio Enhancement",
88
/* 15 */ "ESS Technology Stereo Enhancement",
89
/* 16 */ "Harman International VMAx",
90
/* 17 */ "Nvidea/IC Ensemble/KS Waves 3D Stereo Enhancement",
91
/* 18 */ "Philips Incredible Sound",
92
/* 19 */ "Texas Instruments 3D Stereo Enhancement",
93
/* 20 */ "VLSI Technology 3D Stereo Enhancement",
94
/* 21 */ "TriTech 3D Stereo Enhancement",
95
/* 22 */ "Realtek 3D Stereo Enhancement",
96
/* 23 */ "Samsung 3D Stereo Enhancement",
97
/* 24 */ "Wolfson Microelectronics 3D Enhancement",
98
/* 25 */ "Delta Integration 3D Enhancement",
99
/* 26 */ "SigmaTel 3D Enhancement",
100
/* 27 */ "IC Ensemble/KS Waves",
101
/* 28 */ "Rockwell 3D Stereo Enhancement",
102
/* 29 */ "Reserved 29",
103
/* 30 */ "Reserved 30",
104
/* 31 */ "Reserved 31"
105
};
106
107
static void snd_ac97_proc_read_main(struct snd_ac97 *ac97, struct snd_info_buffer *buffer, int subidx)
108
{
109
char name[64];
110
unsigned short val, tmp, ext, mext;
111
static const char *spdif_slots[4] = { " SPDIF=3/4", " SPDIF=7/8", " SPDIF=6/9", " SPDIF=10/11" };
112
static const char *spdif_rates[4] = { " Rate=44.1kHz", " Rate=res", " Rate=48kHz", " Rate=32kHz" };
113
static const char *spdif_rates_cs4205[4] = { " Rate=48kHz", " Rate=44.1kHz", " Rate=res", " Rate=res" };
114
static const char *double_rate_slots[4] = { "10/11", "7/8", "reserved", "reserved" };
115
116
snd_ac97_get_name(NULL, ac97->id, name, 0);
117
snd_iprintf(buffer, "%d-%d/%d: %s\n\n", ac97->addr, ac97->num, subidx, name);
118
119
if ((ac97->scaps & AC97_SCAP_AUDIO) == 0)
120
goto __modem;
121
122
snd_iprintf(buffer, "PCI Subsys Vendor: 0x%04x\n",
123
ac97->subsystem_vendor);
124
snd_iprintf(buffer, "PCI Subsys Device: 0x%04x\n\n",
125
ac97->subsystem_device);
126
127
snd_iprintf(buffer, "Flags: %x\n", ac97->flags);
128
129
if ((ac97->ext_id & AC97_EI_REV_MASK) >= AC97_EI_REV_23) {
130
val = snd_ac97_read(ac97, AC97_INT_PAGING);
131
snd_ac97_update_bits(ac97, AC97_INT_PAGING,
132
AC97_PAGE_MASK, AC97_PAGE_1);
133
tmp = snd_ac97_read(ac97, AC97_CODEC_CLASS_REV);
134
snd_iprintf(buffer, "Revision : 0x%02x\n", tmp & 0xff);
135
snd_iprintf(buffer, "Compat. Class : 0x%02x\n", (tmp >> 8) & 0x1f);
136
snd_iprintf(buffer, "Subsys. Vendor ID: 0x%04x\n",
137
snd_ac97_read(ac97, AC97_PCI_SVID));
138
snd_iprintf(buffer, "Subsys. ID : 0x%04x\n\n",
139
snd_ac97_read(ac97, AC97_PCI_SID));
140
snd_ac97_update_bits(ac97, AC97_INT_PAGING,
141
AC97_PAGE_MASK, val & AC97_PAGE_MASK);
142
}
143
144
// val = snd_ac97_read(ac97, AC97_RESET);
145
val = ac97->caps;
146
snd_iprintf(buffer, "Capabilities :%s%s%s%s%s%s\n",
147
val & AC97_BC_DEDICATED_MIC ? " -dedicated MIC PCM IN channel-" : "",
148
val & AC97_BC_RESERVED1 ? " -reserved1-" : "",
149
val & AC97_BC_BASS_TREBLE ? " -bass & treble-" : "",
150
val & AC97_BC_SIM_STEREO ? " -simulated stereo-" : "",
151
val & AC97_BC_HEADPHONE ? " -headphone out-" : "",
152
val & AC97_BC_LOUDNESS ? " -loudness-" : "");
153
tmp = ac97->caps & AC97_BC_DAC_MASK;
154
snd_iprintf(buffer, "DAC resolution : %s%s%s%s\n",
155
tmp == AC97_BC_16BIT_DAC ? "16-bit" : "",
156
tmp == AC97_BC_18BIT_DAC ? "18-bit" : "",
157
tmp == AC97_BC_20BIT_DAC ? "20-bit" : "",
158
tmp == AC97_BC_DAC_MASK ? "???" : "");
159
tmp = ac97->caps & AC97_BC_ADC_MASK;
160
snd_iprintf(buffer, "ADC resolution : %s%s%s%s\n",
161
tmp == AC97_BC_16BIT_ADC ? "16-bit" : "",
162
tmp == AC97_BC_18BIT_ADC ? "18-bit" : "",
163
tmp == AC97_BC_20BIT_ADC ? "20-bit" : "",
164
tmp == AC97_BC_ADC_MASK ? "???" : "");
165
snd_iprintf(buffer, "3D enhancement : %s\n",
166
snd_ac97_stereo_enhancements[(val >> 10) & 0x1f]);
167
snd_iprintf(buffer, "\nCurrent setup\n");
168
val = snd_ac97_read(ac97, AC97_MIC);
169
snd_iprintf(buffer, "Mic gain : %s [%s]\n", val & 0x0040 ? "+20dB" : "+0dB", ac97->regs[AC97_MIC] & 0x0040 ? "+20dB" : "+0dB");
170
val = snd_ac97_read(ac97, AC97_GENERAL_PURPOSE);
171
snd_iprintf(buffer, "POP path : %s 3D\n"
172
"Sim. stereo : %s\n"
173
"3D enhancement : %s\n"
174
"Loudness : %s\n"
175
"Mono output : %s\n"
176
"Mic select : %s\n"
177
"ADC/DAC loopback : %s\n",
178
val & 0x8000 ? "post" : "pre",
179
val & 0x4000 ? "on" : "off",
180
val & 0x2000 ? "on" : "off",
181
val & 0x1000 ? "on" : "off",
182
val & 0x0200 ? "Mic" : "MIX",
183
val & 0x0100 ? "Mic2" : "Mic1",
184
val & 0x0080 ? "on" : "off");
185
if (ac97->ext_id & AC97_EI_DRA)
186
snd_iprintf(buffer, "Double rate slots: %s\n",
187
double_rate_slots[(val >> 10) & 3]);
188
189
ext = snd_ac97_read(ac97, AC97_EXTENDED_ID);
190
if (ext == 0)
191
goto __modem;
192
193
snd_iprintf(buffer, "Extended ID : codec=%i rev=%i%s%s%s%s DSA=%i%s%s%s%s\n",
194
(ext & AC97_EI_ADDR_MASK) >> AC97_EI_ADDR_SHIFT,
195
(ext & AC97_EI_REV_MASK) >> AC97_EI_REV_SHIFT,
196
ext & AC97_EI_AMAP ? " AMAP" : "",
197
ext & AC97_EI_LDAC ? " LDAC" : "",
198
ext & AC97_EI_SDAC ? " SDAC" : "",
199
ext & AC97_EI_CDAC ? " CDAC" : "",
200
(ext & AC97_EI_DACS_SLOT_MASK) >> AC97_EI_DACS_SLOT_SHIFT,
201
ext & AC97_EI_VRM ? " VRM" : "",
202
ext & AC97_EI_SPDIF ? " SPDIF" : "",
203
ext & AC97_EI_DRA ? " DRA" : "",
204
ext & AC97_EI_VRA ? " VRA" : "");
205
val = snd_ac97_read(ac97, AC97_EXTENDED_STATUS);
206
snd_iprintf(buffer, "Extended status :%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
207
val & AC97_EA_PRL ? " PRL" : "",
208
val & AC97_EA_PRK ? " PRK" : "",
209
val & AC97_EA_PRJ ? " PRJ" : "",
210
val & AC97_EA_PRI ? " PRI" : "",
211
val & AC97_EA_SPCV ? " SPCV" : "",
212
val & AC97_EA_MDAC ? " MADC" : "",
213
val & AC97_EA_LDAC ? " LDAC" : "",
214
val & AC97_EA_SDAC ? " SDAC" : "",
215
val & AC97_EA_CDAC ? " CDAC" : "",
216
ext & AC97_EI_SPDIF ? spdif_slots[(val & AC97_EA_SPSA_SLOT_MASK) >> AC97_EA_SPSA_SLOT_SHIFT] : "",
217
val & AC97_EA_VRM ? " VRM" : "",
218
val & AC97_EA_SPDIF ? " SPDIF" : "",
219
val & AC97_EA_DRA ? " DRA" : "",
220
val & AC97_EA_VRA ? " VRA" : "");
221
if (ext & AC97_EI_VRA) { /* VRA */
222
val = snd_ac97_read(ac97, AC97_PCM_FRONT_DAC_RATE);
223
snd_iprintf(buffer, "PCM front DAC : %iHz\n", val);
224
if (ext & AC97_EI_SDAC) {
225
val = snd_ac97_read(ac97, AC97_PCM_SURR_DAC_RATE);
226
snd_iprintf(buffer, "PCM Surr DAC : %iHz\n", val);
227
}
228
if (ext & AC97_EI_LDAC) {
229
val = snd_ac97_read(ac97, AC97_PCM_LFE_DAC_RATE);
230
snd_iprintf(buffer, "PCM LFE DAC : %iHz\n", val);
231
}
232
val = snd_ac97_read(ac97, AC97_PCM_LR_ADC_RATE);
233
snd_iprintf(buffer, "PCM ADC : %iHz\n", val);
234
}
235
if (ext & AC97_EI_VRM) {
236
val = snd_ac97_read(ac97, AC97_PCM_MIC_ADC_RATE);
237
snd_iprintf(buffer, "PCM MIC ADC : %iHz\n", val);
238
}
239
if ((ext & AC97_EI_SPDIF) || (ac97->flags & AC97_CS_SPDIF) ||
240
(ac97->id == AC97_ID_YMF743)) {
241
if (ac97->flags & AC97_CS_SPDIF)
242
val = snd_ac97_read(ac97, AC97_CSR_SPDIF);
243
else if (ac97->id == AC97_ID_YMF743) {
244
val = snd_ac97_read(ac97, AC97_YMF7X3_DIT_CTRL);
245
val = 0x2000 | (val & 0xff00) >> 4 | (val & 0x38) >> 2;
246
} else
247
val = snd_ac97_read(ac97, AC97_SPDIF);
248
249
snd_iprintf(buffer, "SPDIF Control :%s%s%s%s Category=0x%x Generation=%i%s%s%s\n",
250
val & AC97_SC_PRO ? " PRO" : " Consumer",
251
val & AC97_SC_NAUDIO ? " Non-audio" : " PCM",
252
val & AC97_SC_COPY ? "" : " Copyright",
253
val & AC97_SC_PRE ? " Preemph50/15" : "",
254
(val & AC97_SC_CC_MASK) >> AC97_SC_CC_SHIFT,
255
(val & AC97_SC_L) >> 11,
256
(ac97->flags & AC97_CS_SPDIF) ?
257
spdif_rates_cs4205[(val & AC97_SC_SPSR_MASK) >> AC97_SC_SPSR_SHIFT] :
258
spdif_rates[(val & AC97_SC_SPSR_MASK) >> AC97_SC_SPSR_SHIFT],
259
(ac97->flags & AC97_CS_SPDIF) ?
260
(val & AC97_SC_DRS ? " Validity" : "") :
261
(val & AC97_SC_DRS ? " DRS" : ""),
262
(ac97->flags & AC97_CS_SPDIF) ?
263
(val & AC97_SC_V ? " Enabled" : "") :
264
(val & AC97_SC_V ? " Validity" : ""));
265
/* ALC650 specific*/
266
if ((ac97->id & 0xfffffff0) == 0x414c4720 &&
267
(snd_ac97_read(ac97, AC97_ALC650_CLOCK) & 0x01)) {
268
val = snd_ac97_read(ac97, AC97_ALC650_SPDIF_INPUT_STATUS2);
269
if (val & AC97_ALC650_CLOCK_LOCK) {
270
val = snd_ac97_read(ac97, AC97_ALC650_SPDIF_INPUT_STATUS1);
271
snd_iprintf(buffer, "SPDIF In Status :%s%s%s%s Category=0x%x Generation=%i",
272
val & AC97_ALC650_PRO ? " PRO" : " Consumer",
273
val & AC97_ALC650_NAUDIO ? " Non-audio" : " PCM",
274
val & AC97_ALC650_COPY ? "" : " Copyright",
275
val & AC97_ALC650_PRE ? " Preemph50/15" : "",
276
(val & AC97_ALC650_CC_MASK) >> AC97_ALC650_CC_SHIFT,
277
(val & AC97_ALC650_L) >> 15);
278
val = snd_ac97_read(ac97, AC97_ALC650_SPDIF_INPUT_STATUS2);
279
snd_iprintf(buffer, "%s Accuracy=%i%s%s\n",
280
spdif_rates[(val & AC97_ALC650_SPSR_MASK) >> AC97_ALC650_SPSR_SHIFT],
281
(val & AC97_ALC650_CLOCK_ACCURACY) >> AC97_ALC650_CLOCK_SHIFT,
282
(val & AC97_ALC650_CLOCK_LOCK ? " Locked" : " Unlocked"),
283
(val & AC97_ALC650_V ? " Validity?" : ""));
284
} else {
285
snd_iprintf(buffer, "SPDIF In Status : Not Locked\n");
286
}
287
}
288
}
289
if ((ac97->ext_id & AC97_EI_REV_MASK) >= AC97_EI_REV_23) {
290
val = snd_ac97_read(ac97, AC97_INT_PAGING);
291
snd_ac97_update_bits(ac97, AC97_INT_PAGING,
292
AC97_PAGE_MASK, AC97_PAGE_1);
293
snd_ac97_proc_read_functions(ac97, buffer);
294
snd_ac97_update_bits(ac97, AC97_INT_PAGING,
295
AC97_PAGE_MASK, val & AC97_PAGE_MASK);
296
}
297
298
299
__modem:
300
mext = snd_ac97_read(ac97, AC97_EXTENDED_MID);
301
if (mext == 0)
302
return;
303
304
snd_iprintf(buffer, "Extended modem ID: codec=%i%s%s%s%s%s\n",
305
(mext & AC97_MEI_ADDR_MASK) >> AC97_MEI_ADDR_SHIFT,
306
mext & AC97_MEI_CID2 ? " CID2" : "",
307
mext & AC97_MEI_CID1 ? " CID1" : "",
308
mext & AC97_MEI_HANDSET ? " HSET" : "",
309
mext & AC97_MEI_LINE2 ? " LIN2" : "",
310
mext & AC97_MEI_LINE1 ? " LIN1" : "");
311
val = snd_ac97_read(ac97, AC97_EXTENDED_MSTATUS);
312
snd_iprintf(buffer, "Modem status :%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
313
val & AC97_MEA_GPIO ? " GPIO" : "",
314
val & AC97_MEA_MREF ? " MREF" : "",
315
val & AC97_MEA_ADC1 ? " ADC1" : "",
316
val & AC97_MEA_DAC1 ? " DAC1" : "",
317
val & AC97_MEA_ADC2 ? " ADC2" : "",
318
val & AC97_MEA_DAC2 ? " DAC2" : "",
319
val & AC97_MEA_HADC ? " HADC" : "",
320
val & AC97_MEA_HDAC ? " HDAC" : "",
321
val & AC97_MEA_PRA ? " PRA(GPIO)" : "",
322
val & AC97_MEA_PRB ? " PRB(res)" : "",
323
val & AC97_MEA_PRC ? " PRC(ADC1)" : "",
324
val & AC97_MEA_PRD ? " PRD(DAC1)" : "",
325
val & AC97_MEA_PRE ? " PRE(ADC2)" : "",
326
val & AC97_MEA_PRF ? " PRF(DAC2)" : "",
327
val & AC97_MEA_PRG ? " PRG(HADC)" : "",
328
val & AC97_MEA_PRH ? " PRH(HDAC)" : "");
329
if (mext & AC97_MEI_LINE1) {
330
val = snd_ac97_read(ac97, AC97_LINE1_RATE);
331
snd_iprintf(buffer, "Line1 rate : %iHz\n", val);
332
}
333
if (mext & AC97_MEI_LINE2) {
334
val = snd_ac97_read(ac97, AC97_LINE2_RATE);
335
snd_iprintf(buffer, "Line2 rate : %iHz\n", val);
336
}
337
if (mext & AC97_MEI_HANDSET) {
338
val = snd_ac97_read(ac97, AC97_HANDSET_RATE);
339
snd_iprintf(buffer, "Headset rate : %iHz\n", val);
340
}
341
}
342
343
static void snd_ac97_proc_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer)
344
{
345
struct snd_ac97 *ac97 = entry->private_data;
346
347
mutex_lock(&ac97->page_mutex);
348
if ((ac97->id & 0xffffff40) == AC97_ID_AD1881) { // Analog Devices AD1881/85/86
349
int idx;
350
for (idx = 0; idx < 3; idx++)
351
if (ac97->spec.ad18xx.id[idx]) {
352
/* select single codec */
353
snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 0x7000,
354
ac97->spec.ad18xx.unchained[idx] | ac97->spec.ad18xx.chained[idx]);
355
snd_ac97_proc_read_main(ac97, buffer, idx);
356
snd_iprintf(buffer, "\n\n");
357
}
358
/* select all codecs */
359
snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 0x7000, 0x7000);
360
361
snd_iprintf(buffer, "\nAD18XX configuration\n");
362
snd_iprintf(buffer, "Unchained : 0x%04x,0x%04x,0x%04x\n",
363
ac97->spec.ad18xx.unchained[0],
364
ac97->spec.ad18xx.unchained[1],
365
ac97->spec.ad18xx.unchained[2]);
366
snd_iprintf(buffer, "Chained : 0x%04x,0x%04x,0x%04x\n",
367
ac97->spec.ad18xx.chained[0],
368
ac97->spec.ad18xx.chained[1],
369
ac97->spec.ad18xx.chained[2]);
370
} else {
371
snd_ac97_proc_read_main(ac97, buffer, 0);
372
}
373
mutex_unlock(&ac97->page_mutex);
374
}
375
376
#ifdef CONFIG_SND_DEBUG
377
/* direct register write for debugging */
378
static void snd_ac97_proc_regs_write(struct snd_info_entry *entry, struct snd_info_buffer *buffer)
379
{
380
struct snd_ac97 *ac97 = entry->private_data;
381
char line[64];
382
unsigned int reg, val;
383
mutex_lock(&ac97->page_mutex);
384
while (!snd_info_get_line(buffer, line, sizeof(line))) {
385
if (sscanf(line, "%x %x", &reg, &val) != 2)
386
continue;
387
/* register must be even */
388
if (reg < 0x80 && (reg & 1) == 0 && val <= 0xffff)
389
snd_ac97_write_cache(ac97, reg, val);
390
}
391
mutex_unlock(&ac97->page_mutex);
392
}
393
#endif
394
395
static void snd_ac97_proc_regs_read_main(struct snd_ac97 *ac97, struct snd_info_buffer *buffer, int subidx)
396
{
397
int reg, val;
398
399
for (reg = 0; reg < 0x80; reg += 2) {
400
val = snd_ac97_read(ac97, reg);
401
snd_iprintf(buffer, "%i:%02x = %04x\n", subidx, reg, val);
402
}
403
}
404
405
static void snd_ac97_proc_regs_read(struct snd_info_entry *entry,
406
struct snd_info_buffer *buffer)
407
{
408
struct snd_ac97 *ac97 = entry->private_data;
409
410
mutex_lock(&ac97->page_mutex);
411
if ((ac97->id & 0xffffff40) == AC97_ID_AD1881) { // Analog Devices AD1881/85/86
412
413
int idx;
414
for (idx = 0; idx < 3; idx++)
415
if (ac97->spec.ad18xx.id[idx]) {
416
/* select single codec */
417
snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 0x7000,
418
ac97->spec.ad18xx.unchained[idx] | ac97->spec.ad18xx.chained[idx]);
419
snd_ac97_proc_regs_read_main(ac97, buffer, idx);
420
}
421
/* select all codecs */
422
snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 0x7000, 0x7000);
423
} else {
424
snd_ac97_proc_regs_read_main(ac97, buffer, 0);
425
}
426
mutex_unlock(&ac97->page_mutex);
427
}
428
429
void snd_ac97_proc_init(struct snd_ac97 * ac97)
430
{
431
struct snd_info_entry *entry;
432
char name[32];
433
const char *prefix;
434
435
if (ac97->bus->proc == NULL)
436
return;
437
prefix = ac97_is_audio(ac97) ? "ac97" : "mc97";
438
sprintf(name, "%s#%d-%d", prefix, ac97->addr, ac97->num);
439
if ((entry = snd_info_create_card_entry(ac97->bus->card, name, ac97->bus->proc)) != NULL) {
440
snd_info_set_text_ops(entry, ac97, snd_ac97_proc_read);
441
if (snd_info_register(entry) < 0) {
442
snd_info_free_entry(entry);
443
entry = NULL;
444
}
445
}
446
ac97->proc = entry;
447
sprintf(name, "%s#%d-%d+regs", prefix, ac97->addr, ac97->num);
448
if ((entry = snd_info_create_card_entry(ac97->bus->card, name, ac97->bus->proc)) != NULL) {
449
snd_info_set_text_ops(entry, ac97, snd_ac97_proc_regs_read);
450
#ifdef CONFIG_SND_DEBUG
451
entry->mode |= S_IWUSR;
452
entry->c.text.write = snd_ac97_proc_regs_write;
453
#endif
454
if (snd_info_register(entry) < 0) {
455
snd_info_free_entry(entry);
456
entry = NULL;
457
}
458
}
459
ac97->proc_regs = entry;
460
}
461
462
void snd_ac97_proc_done(struct snd_ac97 * ac97)
463
{
464
snd_info_free_entry(ac97->proc_regs);
465
ac97->proc_regs = NULL;
466
snd_info_free_entry(ac97->proc);
467
ac97->proc = NULL;
468
}
469
470
void snd_ac97_bus_proc_init(struct snd_ac97_bus * bus)
471
{
472
struct snd_info_entry *entry;
473
char name[32];
474
475
sprintf(name, "codec97#%d", bus->num);
476
if ((entry = snd_info_create_card_entry(bus->card, name, bus->card->proc_root)) != NULL) {
477
entry->mode = S_IFDIR | S_IRUGO | S_IXUGO;
478
if (snd_info_register(entry) < 0) {
479
snd_info_free_entry(entry);
480
entry = NULL;
481
}
482
}
483
bus->proc = entry;
484
}
485
486
void snd_ac97_bus_proc_done(struct snd_ac97_bus * bus)
487
{
488
snd_info_free_entry(bus->proc);
489
bus->proc = NULL;
490
}
491
492