]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blame - sound/pci/hda/hda_proc.c
UBUNTU: Ubuntu-5.15.0-39.42
[mirror_ubuntu-jammy-kernel.git] / sound / pci / hda / hda_proc.c
CommitLineData
d0fa1179 1// SPDX-License-Identifier: GPL-2.0-or-later
1da177e4
LT
2/*
3 * Universal Interface for Intel High Definition Audio Codec
4 *
5 * Generic proc interface
6 *
7 * Copyright (c) 2004 Takashi Iwai <tiwai@suse.de>
1da177e4
LT
8 */
9
1da177e4 10#include <linux/init.h>
4eea3091 11#include <linux/slab.h>
1da177e4 12#include <sound/core.h>
cd262518 13#include <linux/module.h>
be57bfff 14#include <sound/hda_codec.h>
18612048 15#include "hda_local.h"
1da177e4 16
cd262518
DH
17static int dump_coef = -1;
18module_param(dump_coef, int, 0644);
19MODULE_PARM_DESC(dump_coef, "Dump processing coefficients in codec proc file (-1=auto, 0=disable, 1=enable)");
20
9ba17b4d
TI
21/* always use noncached version */
22#define param_read(codec, nid, parm) \
23 snd_hdac_read_parm_uncached(&(codec)->core, nid, parm)
24
1da177e4
LT
25static const char *get_wid_type_name(unsigned int wid_value)
26{
cc75cdfe 27 static const char * const names[16] = {
1da177e4
LT
28 [AC_WID_AUD_OUT] = "Audio Output",
29 [AC_WID_AUD_IN] = "Audio Input",
30 [AC_WID_AUD_MIX] = "Audio Mixer",
31 [AC_WID_AUD_SEL] = "Audio Selector",
32 [AC_WID_PIN] = "Pin Complex",
33 [AC_WID_POWER] = "Power Widget",
34 [AC_WID_VOL_KNB] = "Volume Knob Widget",
35 [AC_WID_BEEP] = "Beep Generator Widget",
36 [AC_WID_VENDOR] = "Vendor Defined Widget",
37 };
3a90274d
TI
38 if (wid_value == -1)
39 return "UNKNOWN Widget";
1da177e4
LT
40 wid_value &= 0xf;
41 if (names[wid_value])
42 return names[wid_value];
43 else
3bc89529 44 return "UNKNOWN Widget";
1da177e4
LT
45}
46
5b0cb1d8
JK
47static void print_nid_array(struct snd_info_buffer *buffer,
48 struct hda_codec *codec, hda_nid_t nid,
49 struct snd_array *array)
3911a4c1
JK
50{
51 int i;
5b0cb1d8 52 struct hda_nid_item *items = array->list, *item;
3911a4c1 53 struct snd_kcontrol *kctl;
5b0cb1d8
JK
54 for (i = 0; i < array->used; i++) {
55 item = &items[i];
56 if (item->nid == nid) {
57 kctl = item->kctl;
3911a4c1
JK
58 snd_iprintf(buffer,
59 " Control: name=\"%s\", index=%i, device=%i\n",
5b0cb1d8
JK
60 kctl->id.name, kctl->id.index + item->index,
61 kctl->id.device);
9e3fd871
JK
62 if (item->flags & HDA_NID_ITEM_AMP)
63 snd_iprintf(buffer,
64 " ControlAmp: chs=%lu, dir=%s, "
65 "idx=%lu, ofs=%lu\n",
66 get_amp_channels(kctl),
67 get_amp_direction(kctl) ? "Out" : "In",
68 get_amp_index(kctl),
69 get_amp_offset(kctl));
3911a4c1
JK
70 }
71 }
72}
73
74static void print_nid_pcms(struct snd_info_buffer *buffer,
75 struct hda_codec *codec, hda_nid_t nid)
76{
bbbc7e85 77 int type;
3911a4c1 78 struct hda_pcm *cpcm;
bbbc7e85
TI
79
80 list_for_each_entry(cpcm, &codec->pcm_list_head, list) {
3911a4c1
JK
81 for (type = 0; type < 2; type++) {
82 if (cpcm->stream[type].nid != nid || cpcm->pcm == NULL)
83 continue;
84 snd_iprintf(buffer, " Device: name=\"%s\", "
85 "type=\"%s\", device=%i\n",
86 cpcm->name,
87 snd_hda_pcm_type_name[cpcm->pcm_type],
88 cpcm->pcm->device);
89 }
90 }
91}
92
c8b6bf9b 93static void print_amp_caps(struct snd_info_buffer *buffer,
1da177e4
LT
94 struct hda_codec *codec, hda_nid_t nid, int dir)
95{
96 unsigned int caps;
9ba17b4d
TI
97 caps = param_read(codec, nid, dir == HDA_OUTPUT ?
98 AC_PAR_AMP_OUT_CAP : AC_PAR_AMP_IN_CAP);
1da177e4
LT
99 if (caps == -1 || caps == 0) {
100 snd_iprintf(buffer, "N/A\n");
101 return;
102 }
d01ce99f
TI
103 snd_iprintf(buffer, "ofs=0x%02x, nsteps=0x%02x, stepsize=0x%02x, "
104 "mute=%x\n",
1da177e4
LT
105 caps & AC_AMPCAP_OFFSET,
106 (caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT,
107 (caps & AC_AMPCAP_STEP_SIZE) >> AC_AMPCAP_STEP_SIZE_SHIFT,
108 (caps & AC_AMPCAP_MUTE) >> AC_AMPCAP_MUTE_SHIFT);
109}
110
cc261738
TI
111/* is this a stereo widget or a stereo-to-mono mix? */
112static bool is_stereo_amps(struct hda_codec *codec, hda_nid_t nid,
113 int dir, unsigned int wcaps, int indices)
114{
115 hda_nid_t conn;
116
117 if (wcaps & AC_WCAP_STEREO)
118 return true;
119 /* check for a stereo-to-mono mix; it must be:
120 * only a single connection, only for input, and only a mixer widget
121 */
122 if (indices != 1 || dir != HDA_INPUT ||
123 get_wcaps_type(wcaps) != AC_WID_AUD_MIX)
124 return false;
125
126 if (snd_hda_get_raw_connections(codec, nid, &conn, 1) < 0)
127 return false;
128 /* the connection source is a stereo? */
129 wcaps = snd_hda_param_read(codec, conn, AC_PAR_AUDIO_WIDGET_CAP);
130 return !!(wcaps & AC_WCAP_STEREO);
131}
132
c8b6bf9b 133static void print_amp_vals(struct snd_info_buffer *buffer,
1da177e4 134 struct hda_codec *codec, hda_nid_t nid,
cc261738 135 int dir, unsigned int wcaps, int indices)
1da177e4
LT
136{
137 unsigned int val;
cc261738 138 bool stereo;
3e289f16
TI
139 int i;
140
cc261738
TI
141 stereo = is_stereo_amps(codec, nid, dir, wcaps, indices);
142
7f0e2f8b 143 dir = dir == HDA_OUTPUT ? AC_AMP_GET_OUTPUT : AC_AMP_GET_INPUT;
3e289f16
TI
144 for (i = 0; i < indices; i++) {
145 snd_iprintf(buffer, " [");
2f179721
TI
146 val = snd_hda_codec_read(codec, nid, 0,
147 AC_VERB_GET_AMP_GAIN_MUTE,
148 AC_AMP_GET_LEFT | dir | i);
149 snd_iprintf(buffer, "0x%02x", val);
3e289f16 150 if (stereo) {
d01ce99f
TI
151 val = snd_hda_codec_read(codec, nid, 0,
152 AC_VERB_GET_AMP_GAIN_MUTE,
2f179721
TI
153 AC_AMP_GET_RIGHT | dir | i);
154 snd_iprintf(buffer, " 0x%02x", val);
3e289f16 155 }
2f179721 156 snd_iprintf(buffer, "]");
1da177e4 157 }
3e289f16 158 snd_iprintf(buffer, "\n");
1da177e4
LT
159}
160
33deeca3
WF
161static void print_pcm_rates(struct snd_info_buffer *buffer, unsigned int pcm)
162{
bf82326f 163 static const unsigned int rates[] = {
f71ff0d7
TI
164 8000, 11025, 16000, 22050, 32000, 44100, 48000, 88200,
165 96000, 176400, 192000, 384000
166 };
167 int i;
d39b4352 168
b90d7760
TI
169 pcm &= AC_SUPPCM_RATES;
170 snd_iprintf(buffer, " rates [0x%x]:", pcm);
f71ff0d7
TI
171 for (i = 0; i < ARRAY_SIZE(rates); i++)
172 if (pcm & (1 << i))
173 snd_iprintf(buffer, " %d", rates[i]);
174 snd_iprintf(buffer, "\n");
b90d7760
TI
175}
176
d39b4352
WF
177static void print_pcm_bits(struct snd_info_buffer *buffer, unsigned int pcm)
178{
179 char buf[SND_PRINT_BITS_ADVISED_BUFSIZE];
b90d7760 180
b0e6481a 181 snd_iprintf(buffer, " bits [0x%x]:", (pcm >> 16) & 0xff);
d39b4352
WF
182 snd_print_pcm_bits(pcm, buf, sizeof(buf));
183 snd_iprintf(buffer, "%s\n", buf);
b90d7760
TI
184}
185
186static void print_pcm_formats(struct snd_info_buffer *buffer,
187 unsigned int streams)
188{
189 snd_iprintf(buffer, " formats [0x%x]:", streams & 0xf);
190 if (streams & AC_SUPFMT_PCM)
191 snd_iprintf(buffer, " PCM");
192 if (streams & AC_SUPFMT_FLOAT32)
193 snd_iprintf(buffer, " FLOAT");
194 if (streams & AC_SUPFMT_AC3)
195 snd_iprintf(buffer, " AC3");
196 snd_iprintf(buffer, "\n");
197}
198
c8b6bf9b 199static void print_pcm_caps(struct snd_info_buffer *buffer,
1da177e4
LT
200 struct hda_codec *codec, hda_nid_t nid)
201{
9ba17b4d
TI
202 unsigned int pcm = param_read(codec, nid, AC_PAR_PCM);
203 unsigned int stream = param_read(codec, nid, AC_PAR_STREAM);
1da177e4
LT
204 if (pcm == -1 || stream == -1) {
205 snd_iprintf(buffer, "N/A\n");
206 return;
207 }
b90d7760
TI
208 print_pcm_rates(buffer, pcm);
209 print_pcm_bits(buffer, pcm);
210 print_pcm_formats(buffer, stream);
1da177e4
LT
211}
212
1da177e4
LT
213static const char *get_jack_connection(u32 cfg)
214{
cc75cdfe 215 static const char * const names[16] = {
1da177e4
LT
216 "Unknown", "1/8", "1/4", "ATAPI",
217 "RCA", "Optical","Digital", "Analog",
218 "DIN", "XLR", "RJ11", "Comb",
219 NULL, NULL, NULL, "Other"
220 };
221 cfg = (cfg & AC_DEFCFG_CONN_TYPE) >> AC_DEFCFG_CONN_TYPE_SHIFT;
222 if (names[cfg])
223 return names[cfg];
224 else
225 return "UNKNOWN";
226}
227
228static const char *get_jack_color(u32 cfg)
229{
cc75cdfe 230 static const char * const names[16] = {
1da177e4
LT
231 "Unknown", "Black", "Grey", "Blue",
232 "Green", "Red", "Orange", "Yellow",
233 "Purple", "Pink", NULL, NULL,
234 NULL, NULL, "White", "Other",
235 };
236 cfg = (cfg & AC_DEFCFG_COLOR) >> AC_DEFCFG_COLOR_SHIFT;
237 if (names[cfg])
238 return names[cfg];
239 else
240 return "UNKNOWN";
241}
242
d2c6b63d
TI
243/*
244 * Parse the pin default config value and returns the string of the
245 * jack location, e.g. "Rear", "Front", etc.
246 */
247static const char *get_jack_location(u32 cfg)
248{
cc75cdfe 249 static const char * const bases[7] = {
d2c6b63d
TI
250 "N/A", "Rear", "Front", "Left", "Right", "Top", "Bottom",
251 };
cc75cdfe 252 static const unsigned char specials_idx[] = {
d2c6b63d
TI
253 0x07, 0x08,
254 0x17, 0x18, 0x19,
255 0x37, 0x38
256 };
cc75cdfe 257 static const char * const specials[] = {
d2c6b63d
TI
258 "Rear Panel", "Drive Bar",
259 "Riser", "HDMI", "ATAPI",
260 "Mobile-In", "Mobile-Out"
261 };
262 int i;
263
264 cfg = (cfg & AC_DEFCFG_LOCATION) >> AC_DEFCFG_LOCATION_SHIFT;
265 if ((cfg & 0x0f) < 7)
266 return bases[cfg & 0x0f];
267 for (i = 0; i < ARRAY_SIZE(specials_idx); i++) {
268 if (cfg == specials_idx[i])
269 return specials[i];
270 }
271 return "UNKNOWN";
272}
273
274/*
275 * Parse the pin default config value and returns the string of the
276 * jack connectivity, i.e. external or internal connection.
277 */
278static const char *get_jack_connectivity(u32 cfg)
279{
cc75cdfe
TI
280 static const char * const jack_locations[4] = {
281 "Ext", "Int", "Sep", "Oth"
282 };
d2c6b63d
TI
283
284 return jack_locations[(cfg >> (AC_DEFCFG_LOCATION_SHIFT + 4)) & 3];
285}
286
287/*
288 * Parse the pin default config value and returns the string of the
289 * jack type, i.e. the purpose of the jack, such as Line-Out or CD.
290 */
291static const char *get_jack_type(u32 cfg)
292{
cc75cdfe 293 static const char * const jack_types[16] = {
d2c6b63d
TI
294 "Line Out", "Speaker", "HP Out", "CD",
295 "SPDIF Out", "Digital Out", "Modem Line", "Modem Hand",
296 "Line In", "Aux", "Mic", "Telephony",
297 "SPDIF In", "Digital In", "Reserved", "Other"
298 };
299
300 return jack_types[(cfg & AC_DEFCFG_DEVICE)
301 >> AC_DEFCFG_DEVICE_SHIFT];
302}
303
c8b6bf9b 304static void print_pin_caps(struct snd_info_buffer *buffer,
797760ab
AP
305 struct hda_codec *codec, hda_nid_t nid,
306 int *supports_vref)
1da177e4 307{
cc75cdfe
TI
308 static const char * const jack_conns[4] = {
309 "Jack", "N/A", "Fixed", "Both"
310 };
e97a5167 311 unsigned int caps, val;
1da177e4 312
9ba17b4d 313 caps = param_read(codec, nid, AC_PAR_PIN_CAP);
0481f453 314 snd_iprintf(buffer, " Pincap 0x%08x:", caps);
1da177e4
LT
315 if (caps & AC_PINCAP_IN)
316 snd_iprintf(buffer, " IN");
317 if (caps & AC_PINCAP_OUT)
318 snd_iprintf(buffer, " OUT");
319 if (caps & AC_PINCAP_HP_DRV)
320 snd_iprintf(buffer, " HP");
5885492a
TI
321 if (caps & AC_PINCAP_EAPD)
322 snd_iprintf(buffer, " EAPD");
323 if (caps & AC_PINCAP_PRES_DETECT)
324 snd_iprintf(buffer, " Detect");
797760ab
AP
325 if (caps & AC_PINCAP_BALANCE)
326 snd_iprintf(buffer, " Balanced");
c4920606
TI
327 if (caps & AC_PINCAP_HDMI) {
328 /* Realtek uses this bit as a different meaning */
7639a06c 329 if ((codec->core.vendor_id >> 16) == 0x10ec)
c4920606 330 snd_iprintf(buffer, " R/L");
b923528e
WF
331 else {
332 if (caps & AC_PINCAP_HBR)
333 snd_iprintf(buffer, " HBR");
c4920606 334 snd_iprintf(buffer, " HDMI");
b923528e 335 }
c4920606 336 }
728765b3
WF
337 if (caps & AC_PINCAP_DP)
338 snd_iprintf(buffer, " DP");
797760ab
AP
339 if (caps & AC_PINCAP_TRIG_REQ)
340 snd_iprintf(buffer, " Trigger");
341 if (caps & AC_PINCAP_IMP_SENSE)
342 snd_iprintf(buffer, " ImpSense");
1da177e4 343 snd_iprintf(buffer, "\n");
797760ab
AP
344 if (caps & AC_PINCAP_VREF) {
345 unsigned int vref =
346 (caps & AC_PINCAP_VREF) >> AC_PINCAP_VREF_SHIFT;
347 snd_iprintf(buffer, " Vref caps:");
348 if (vref & AC_PINCAP_VREF_HIZ)
349 snd_iprintf(buffer, " HIZ");
350 if (vref & AC_PINCAP_VREF_50)
351 snd_iprintf(buffer, " 50");
352 if (vref & AC_PINCAP_VREF_GRD)
353 snd_iprintf(buffer, " GRD");
354 if (vref & AC_PINCAP_VREF_80)
355 snd_iprintf(buffer, " 80");
356 if (vref & AC_PINCAP_VREF_100)
357 snd_iprintf(buffer, " 100");
358 snd_iprintf(buffer, "\n");
359 *supports_vref = 1;
360 } else
361 *supports_vref = 0;
362 if (caps & AC_PINCAP_EAPD) {
363 val = snd_hda_codec_read(codec, nid, 0,
364 AC_VERB_GET_EAPD_BTLENABLE, 0);
365 snd_iprintf(buffer, " EAPD 0x%x:", val);
366 if (val & AC_EAPDBTL_BALANCED)
367 snd_iprintf(buffer, " BALANCED");
368 if (val & AC_EAPDBTL_EAPD)
369 snd_iprintf(buffer, " EAPD");
370 if (val & AC_EAPDBTL_LR_SWAP)
371 snd_iprintf(buffer, " R/L");
372 snd_iprintf(buffer, "\n");
373 }
1da177e4 374 caps = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONFIG_DEFAULT, 0);
b0c95f51
TI
375 snd_iprintf(buffer, " Pin Default 0x%08x: [%s] %s at %s %s\n", caps,
376 jack_conns[(caps & AC_DEFCFG_PORT_CONN) >> AC_DEFCFG_PORT_CONN_SHIFT],
d2c6b63d
TI
377 get_jack_type(caps),
378 get_jack_connectivity(caps),
379 get_jack_location(caps));
1da177e4
LT
380 snd_iprintf(buffer, " Conn = %s, Color = %s\n",
381 get_jack_connection(caps),
382 get_jack_color(caps));
797760ab
AP
383 /* Default association and sequence values refer to default grouping
384 * of pin complexes and their sequence within the group. This is used
385 * for priority and resource allocation.
386 */
387 snd_iprintf(buffer, " DefAssociation = 0x%x, Sequence = 0x%x\n",
388 (caps & AC_DEFCFG_DEF_ASSOC) >> AC_DEFCFG_ASSOC_SHIFT,
389 caps & AC_DEFCFG_SEQUENCE);
390 if (((caps & AC_DEFCFG_MISC) >> AC_DEFCFG_MISC_SHIFT) &
391 AC_DEFCFG_MISC_NO_PRESENCE) {
392 /* Miscellaneous bit indicates external hardware does not
393 * support presence detection even if the pin complex
394 * indicates it is supported.
395 */
396 snd_iprintf(buffer, " Misc = NO_PRESENCE\n");
e97a5167 397 }
1da177e4
LT
398}
399
797760ab
AP
400static void print_pin_ctls(struct snd_info_buffer *buffer,
401 struct hda_codec *codec, hda_nid_t nid,
402 int supports_vref)
403{
404 unsigned int pinctls;
405
406 pinctls = snd_hda_codec_read(codec, nid, 0,
407 AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
408 snd_iprintf(buffer, " Pin-ctls: 0x%02x:", pinctls);
409 if (pinctls & AC_PINCTL_IN_EN)
410 snd_iprintf(buffer, " IN");
411 if (pinctls & AC_PINCTL_OUT_EN)
412 snd_iprintf(buffer, " OUT");
413 if (pinctls & AC_PINCTL_HP_EN)
414 snd_iprintf(buffer, " HP");
415 if (supports_vref) {
416 int vref = pinctls & AC_PINCTL_VREFEN;
417 switch (vref) {
418 case AC_PINCTL_VREF_HIZ:
419 snd_iprintf(buffer, " VREF_HIZ");
420 break;
421 case AC_PINCTL_VREF_50:
422 snd_iprintf(buffer, " VREF_50");
423 break;
424 case AC_PINCTL_VREF_GRD:
425 snd_iprintf(buffer, " VREF_GRD");
426 break;
427 case AC_PINCTL_VREF_80:
428 snd_iprintf(buffer, " VREF_80");
429 break;
430 case AC_PINCTL_VREF_100:
431 snd_iprintf(buffer, " VREF_100");
432 break;
433 }
434 }
435 snd_iprintf(buffer, "\n");
436}
437
438static void print_vol_knob(struct snd_info_buffer *buffer,
439 struct hda_codec *codec, hda_nid_t nid)
440{
9ba17b4d 441 unsigned int cap = param_read(codec, nid, AC_PAR_VOL_KNB_CAP);
797760ab
AP
442 snd_iprintf(buffer, " Volume-Knob: delta=%d, steps=%d, ",
443 (cap >> 7) & 1, cap & 0x7f);
444 cap = snd_hda_codec_read(codec, nid, 0,
445 AC_VERB_GET_VOLUME_KNOB_CONTROL, 0);
446 snd_iprintf(buffer, "direct=%d, val=%d\n",
447 (cap >> 7) & 1, cap & 0x7f);
448}
449
450static void print_audio_io(struct snd_info_buffer *buffer,
451 struct hda_codec *codec, hda_nid_t nid,
452 unsigned int wid_type)
453{
3911a4c1 454 int conv = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONV, 0);
797760ab
AP
455 snd_iprintf(buffer,
456 " Converter: stream=%d, channel=%d\n",
457 (conv & AC_CONV_STREAM) >> AC_CONV_STREAM_SHIFT,
458 conv & AC_CONV_CHANNEL);
459
460 if (wid_type == AC_WID_AUD_IN && (conv & AC_CONV_CHANNEL) == 0) {
461 int sdi = snd_hda_codec_read(codec, nid, 0,
462 AC_VERB_GET_SDI_SELECT, 0);
463 snd_iprintf(buffer, " SDI-Select: %d\n",
464 sdi & AC_SDI_SELECT);
465 }
466}
467
468static void print_digital_conv(struct snd_info_buffer *buffer,
469 struct hda_codec *codec, hda_nid_t nid)
470{
471 unsigned int digi1 = snd_hda_codec_read(codec, nid, 0,
472 AC_VERB_GET_DIGI_CONVERT_1, 0);
61525979
WX
473 unsigned char digi2 = digi1 >> 8;
474 unsigned char digi3 = digi1 >> 16;
475
797760ab
AP
476 snd_iprintf(buffer, " Digital:");
477 if (digi1 & AC_DIG1_ENABLE)
478 snd_iprintf(buffer, " Enabled");
479 if (digi1 & AC_DIG1_V)
480 snd_iprintf(buffer, " Validity");
481 if (digi1 & AC_DIG1_VCFG)
482 snd_iprintf(buffer, " ValidityCfg");
483 if (digi1 & AC_DIG1_EMPHASIS)
484 snd_iprintf(buffer, " Preemphasis");
485 if (digi1 & AC_DIG1_COPYRIGHT)
088c820b 486 snd_iprintf(buffer, " Non-Copyright");
797760ab
AP
487 if (digi1 & AC_DIG1_NONAUDIO)
488 snd_iprintf(buffer, " Non-Audio");
489 if (digi1 & AC_DIG1_PROFESSIONAL)
490 snd_iprintf(buffer, " Pro");
491 if (digi1 & AC_DIG1_LEVEL)
492 snd_iprintf(buffer, " GenLevel");
61525979
WX
493 if (digi3 & AC_DIG3_KAE)
494 snd_iprintf(buffer, " KAE");
797760ab 495 snd_iprintf(buffer, "\n");
a1855d80 496 snd_iprintf(buffer, " Digital category: 0x%x\n",
61525979
WX
497 digi2 & AC_DIG2_CC);
498 snd_iprintf(buffer, " IEC Coding Type: 0x%x\n",
499 digi3 & AC_DIG3_ICT);
797760ab
AP
500}
501
502static const char *get_pwr_state(u32 state)
503{
167d2d55
TI
504 static const char * const buf[] = {
505 "D0", "D1", "D2", "D3", "D3cold"
797760ab 506 };
167d2d55 507 if (state < ARRAY_SIZE(buf))
797760ab
AP
508 return buf[state];
509 return "UNKNOWN";
510}
511
512static void print_power_state(struct snd_info_buffer *buffer,
513 struct hda_codec *codec, hda_nid_t nid)
514{
cc75cdfe 515 static const char * const names[] = {
83d605fd
WF
516 [ilog2(AC_PWRST_D0SUP)] = "D0",
517 [ilog2(AC_PWRST_D1SUP)] = "D1",
518 [ilog2(AC_PWRST_D2SUP)] = "D2",
519 [ilog2(AC_PWRST_D3SUP)] = "D3",
520 [ilog2(AC_PWRST_D3COLDSUP)] = "D3cold",
521 [ilog2(AC_PWRST_S3D3COLDSUP)] = "S3D3cold",
522 [ilog2(AC_PWRST_CLKSTOP)] = "CLKSTOP",
523 [ilog2(AC_PWRST_EPSS)] = "EPSS",
524 };
525
9ba17b4d 526 int sup = param_read(codec, nid, AC_PAR_POWER_STATE);
797760ab
AP
527 int pwr = snd_hda_codec_read(codec, nid, 0,
528 AC_VERB_GET_POWER_STATE, 0);
1d260d7b
TI
529 if (sup != -1) {
530 int i;
531
532 snd_iprintf(buffer, " Power states: ");
533 for (i = 0; i < ARRAY_SIZE(names); i++) {
534 if (sup & (1U << i))
535 snd_iprintf(buffer, " %s", names[i]);
536 }
537 snd_iprintf(buffer, "\n");
538 }
83d605fd 539
ce63f3ba 540 snd_iprintf(buffer, " Power: setting=%s, actual=%s",
797760ab
AP
541 get_pwr_state(pwr & AC_PWRST_SETTING),
542 get_pwr_state((pwr & AC_PWRST_ACTUAL) >>
543 AC_PWRST_ACTUAL_SHIFT));
ce63f3ba
WX
544 if (pwr & AC_PWRST_ERROR)
545 snd_iprintf(buffer, ", Error");
546 if (pwr & AC_PWRST_CLK_STOP_OK)
547 snd_iprintf(buffer, ", Clock-stop-OK");
548 if (pwr & AC_PWRST_SETTING_RESET)
549 snd_iprintf(buffer, ", Setting-reset");
550 snd_iprintf(buffer, "\n");
797760ab
AP
551}
552
553static void print_unsol_cap(struct snd_info_buffer *buffer,
554 struct hda_codec *codec, hda_nid_t nid)
555{
556 int unsol = snd_hda_codec_read(codec, nid, 0,
557 AC_VERB_GET_UNSOLICITED_RESPONSE, 0);
558 snd_iprintf(buffer,
559 " Unsolicited: tag=%02x, enabled=%d\n",
560 unsol & AC_UNSOL_TAG,
561 (unsol & AC_UNSOL_ENABLED) ? 1 : 0);
562}
563
cd262518
DH
564static inline bool can_dump_coef(struct hda_codec *codec)
565{
566 switch (dump_coef) {
567 case 0: return false;
568 case 1: return true;
569 default: return codec->dump_coef;
570 }
571}
572
797760ab
AP
573static void print_proc_caps(struct snd_info_buffer *buffer,
574 struct hda_codec *codec, hda_nid_t nid)
575{
cd262518 576 unsigned int i, ncoeff, oldindex;
9ba17b4d 577 unsigned int proc_caps = param_read(codec, nid, AC_PAR_PROC_CAP);
cd262518 578 ncoeff = (proc_caps & AC_PCAP_NUM_COEF) >> AC_PCAP_NUM_COEF_SHIFT;
797760ab 579 snd_iprintf(buffer, " Processing caps: benign=%d, ncoeff=%d\n",
cd262518
DH
580 proc_caps & AC_PCAP_BENIGN, ncoeff);
581
582 if (!can_dump_coef(codec))
583 return;
584
585 /* Note: This is racy - another process could run in parallel and change
586 the coef index too. */
587 oldindex = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_COEF_INDEX, 0);
588 for (i = 0; i < ncoeff; i++) {
589 unsigned int val;
590 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_COEF_INDEX, i);
591 val = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_PROC_COEF,
592 0);
593 snd_iprintf(buffer, " Coeff 0x%02x: 0x%04x\n", i, val);
594 }
595 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_COEF_INDEX, oldindex);
797760ab
AP
596}
597
598static void print_conn_list(struct snd_info_buffer *buffer,
599 struct hda_codec *codec, hda_nid_t nid,
600 unsigned int wid_type, hda_nid_t *conn,
601 int conn_len)
602{
603 int c, curr = -1;
8b2c7a5c
WX
604 const hda_nid_t *list;
605 int cache_len;
797760ab 606
07a1e813
TI
607 if (conn_len > 1 &&
608 wid_type != AC_WID_AUD_MIX &&
609 wid_type != AC_WID_VOL_KNB &&
610 wid_type != AC_WID_POWER)
797760ab
AP
611 curr = snd_hda_codec_read(codec, nid, 0,
612 AC_VERB_GET_CONNECT_SEL, 0);
613 snd_iprintf(buffer, " Connection: %d\n", conn_len);
614 if (conn_len > 0) {
615 snd_iprintf(buffer, " ");
616 for (c = 0; c < conn_len; c++) {
617 snd_iprintf(buffer, " 0x%02x", conn[c]);
618 if (c == curr)
619 snd_iprintf(buffer, "*");
620 }
621 snd_iprintf(buffer, "\n");
622 }
8b2c7a5c
WX
623
624 /* Get Cache connections info */
625 cache_len = snd_hda_get_conn_list(codec, nid, &list);
f4d77031
DC
626 if (cache_len >= 0 && (cache_len != conn_len ||
627 memcmp(list, conn, conn_len) != 0)) {
8b2c7a5c
WX
628 snd_iprintf(buffer, " In-driver Connection: %d\n", cache_len);
629 if (cache_len > 0) {
630 snd_iprintf(buffer, " ");
631 for (c = 0; c < cache_len; c++)
632 snd_iprintf(buffer, " 0x%02x", list[c]);
633 snd_iprintf(buffer, "\n");
634 }
635 }
797760ab
AP
636}
637
797760ab
AP
638static void print_gpio(struct snd_info_buffer *buffer,
639 struct hda_codec *codec, hda_nid_t nid)
640{
641 unsigned int gpio =
9ba17b4d 642 param_read(codec, codec->core.afg, AC_PAR_GPIO_CAP);
797760ab
AP
643 unsigned int enable, direction, wake, unsol, sticky, data;
644 int i, max;
645 snd_iprintf(buffer, "GPIO: io=%d, o=%d, i=%d, "
646 "unsolicited=%d, wake=%d\n",
647 gpio & AC_GPIO_IO_COUNT,
648 (gpio & AC_GPIO_O_COUNT) >> AC_GPIO_O_COUNT_SHIFT,
649 (gpio & AC_GPIO_I_COUNT) >> AC_GPIO_I_COUNT_SHIFT,
650 (gpio & AC_GPIO_UNSOLICITED) ? 1 : 0,
651 (gpio & AC_GPIO_WAKE) ? 1 : 0);
652 max = gpio & AC_GPIO_IO_COUNT;
c4dc5071
TI
653 if (!max || max > 8)
654 return;
797760ab
AP
655 enable = snd_hda_codec_read(codec, nid, 0,
656 AC_VERB_GET_GPIO_MASK, 0);
657 direction = snd_hda_codec_read(codec, nid, 0,
658 AC_VERB_GET_GPIO_DIRECTION, 0);
659 wake = snd_hda_codec_read(codec, nid, 0,
660 AC_VERB_GET_GPIO_WAKE_MASK, 0);
661 unsol = snd_hda_codec_read(codec, nid, 0,
662 AC_VERB_GET_GPIO_UNSOLICITED_RSP_MASK, 0);
663 sticky = snd_hda_codec_read(codec, nid, 0,
664 AC_VERB_GET_GPIO_STICKY_MASK, 0);
665 data = snd_hda_codec_read(codec, nid, 0,
666 AC_VERB_GET_GPIO_DATA, 0);
667 for (i = 0; i < max; ++i)
668 snd_iprintf(buffer,
669 " IO[%d]: enable=%d, dir=%d, wake=%d, "
85639646 670 "sticky=%d, data=%d, unsol=%d\n", i,
797760ab
AP
671 (enable & (1<<i)) ? 1 : 0,
672 (direction & (1<<i)) ? 1 : 0,
673 (wake & (1<<i)) ? 1 : 0,
674 (sticky & (1<<i)) ? 1 : 0,
85639646
TI
675 (data & (1<<i)) ? 1 : 0,
676 (unsol & (1<<i)) ? 1 : 0);
797760ab 677 /* FIXME: add GPO and GPI pin information */
5b0cb1d8
JK
678 print_nid_array(buffer, codec, nid, &codec->mixers);
679 print_nid_array(buffer, codec, nid, &codec->nids);
797760ab 680}
1da177e4 681
19bb4f78
KV
682static void print_dpmst_connections(struct snd_info_buffer *buffer, struct hda_codec *codec,
683 hda_nid_t nid, int dev_num)
684{
685 int c, conn_len, curr, dev_id_saved;
686 hda_nid_t *conn;
687
688 conn_len = snd_hda_get_num_raw_conns(codec, nid);
689 if (conn_len <= 0)
690 return;
691
692 conn = kmalloc_array(conn_len, sizeof(hda_nid_t), GFP_KERNEL);
693 if (!conn)
694 return;
695
696 dev_id_saved = snd_hda_get_dev_select(codec, nid);
697
698 snd_hda_set_dev_select(codec, nid, dev_num);
699 curr = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONNECT_SEL, 0);
700 if (snd_hda_get_raw_connections(codec, nid, conn, conn_len) < 0)
701 goto out;
702
703 for (c = 0; c < conn_len; c++) {
704 snd_iprintf(buffer, " 0x%02x", conn[c]);
705 if (c == curr)
706 snd_iprintf(buffer, "*");
707 }
708
709out:
710 kfree(conn);
711 snd_hda_set_dev_select(codec, nid, dev_id_saved);
712}
713
7a624ea5
ML
714static void print_device_list(struct snd_info_buffer *buffer,
715 struct hda_codec *codec, hda_nid_t nid)
716{
717 int i, curr = -1;
718 u8 dev_list[AC_MAX_DEV_LIST_LEN];
719 int devlist_len;
720
721 devlist_len = snd_hda_get_devices(codec, nid, dev_list,
722 AC_MAX_DEV_LIST_LEN);
723 snd_iprintf(buffer, " Devices: %d\n", devlist_len);
724 if (devlist_len <= 0)
725 return;
726
727 curr = snd_hda_codec_read(codec, nid, 0,
728 AC_VERB_GET_DEVICE_SEL, 0);
729
730 for (i = 0; i < devlist_len; i++) {
731 if (i == curr)
732 snd_iprintf(buffer, " *");
733 else
734 snd_iprintf(buffer, " ");
735
736 snd_iprintf(buffer,
19bb4f78 737 "Dev %02d: PD = %d, ELDV = %d, IA = %d, Connections [", i,
7a624ea5
ML
738 !!(dev_list[i] & AC_DE_PD),
739 !!(dev_list[i] & AC_DE_ELDV),
740 !!(dev_list[i] & AC_DE_IA));
19bb4f78
KV
741
742 print_dpmst_connections(buffer, codec, nid, i);
743
744 snd_iprintf(buffer, " ]\n");
7a624ea5
ML
745 }
746}
747
7639a06c
TI
748static void print_codec_core_info(struct hdac_device *codec,
749 struct snd_info_buffer *buffer)
1da177e4 750{
812a2cca
TI
751 snd_iprintf(buffer, "Codec: ");
752 if (codec->vendor_name && codec->chip_name)
753 snd_iprintf(buffer, "%s %s\n",
754 codec->vendor_name, codec->chip_name);
755 else
756 snd_iprintf(buffer, "Not Set\n");
1da177e4 757 snd_iprintf(buffer, "Address: %d\n", codec->addr);
79c944ad
JK
758 if (codec->afg)
759 snd_iprintf(buffer, "AFG Function Id: 0x%x (unsol %u)\n",
760 codec->afg_function_id, codec->afg_unsol);
761 if (codec->mfg)
762 snd_iprintf(buffer, "MFG Function Id: 0x%x (unsol %u)\n",
763 codec->mfg_function_id, codec->mfg_unsol);
234b4346
PB
764 snd_iprintf(buffer, "Vendor Id: 0x%08x\n", codec->vendor_id);
765 snd_iprintf(buffer, "Subsystem Id: 0x%08x\n", codec->subsystem_id);
1da177e4 766 snd_iprintf(buffer, "Revision Id: 0x%x\n", codec->revision_id);
e25c05f1
JP
767
768 if (codec->mfg)
769 snd_iprintf(buffer, "Modem Function Group: 0x%x\n", codec->mfg);
770 else
771 snd_iprintf(buffer, "No Modem Function Group found\n");
7639a06c
TI
772}
773
774static void print_codec_info(struct snd_info_entry *entry,
775 struct snd_info_buffer *buffer)
776{
777 struct hda_codec *codec = entry->private_data;
778 hda_nid_t nid, fg;
779 int i, nodes;
e25c05f1 780
7639a06c
TI
781 print_codec_core_info(&codec->core, buffer);
782 fg = codec->core.afg;
783 if (!fg)
ec9e1c5c 784 return;
cb53c626 785 snd_hda_power_up(codec);
b90d7760 786 snd_iprintf(buffer, "Default PCM:\n");
7639a06c 787 print_pcm_caps(buffer, codec, fg);
1da177e4 788 snd_iprintf(buffer, "Default Amp-In caps: ");
7639a06c 789 print_amp_caps(buffer, codec, fg, HDA_INPUT);
1da177e4 790 snd_iprintf(buffer, "Default Amp-Out caps: ");
7639a06c
TI
791 print_amp_caps(buffer, codec, fg, HDA_OUTPUT);
792 snd_iprintf(buffer, "State of AFG node 0x%02x:\n", fg);
793 print_power_state(buffer, codec, fg);
1da177e4 794
7639a06c 795 nodes = snd_hda_get_sub_nodes(codec, fg, &nid);
1da177e4
LT
796 if (! nid || nodes < 0) {
797 snd_iprintf(buffer, "Invalid AFG subtree\n");
cb53c626 798 snd_hda_power_down(codec);
1da177e4
LT
799 return;
800 }
797760ab 801
7639a06c 802 print_gpio(buffer, codec, fg);
2d34e1b3 803 if (codec->proc_widget_hook)
7639a06c 804 codec->proc_widget_hook(buffer, codec, fg);
797760ab 805
1da177e4 806 for (i = 0; i < nodes; i++, nid++) {
d01ce99f 807 unsigned int wid_caps =
9ba17b4d 808 param_read(codec, nid, AC_PAR_AUDIO_WIDGET_CAP);
a22d543a 809 unsigned int wid_type = get_wcaps_type(wid_caps);
4eea3091 810 hda_nid_t *conn = NULL;
797760ab 811 int conn_len = 0;
3e289f16 812
1da177e4
LT
813 snd_iprintf(buffer, "Node 0x%02x [%s] wcaps 0x%x:", nid,
814 get_wid_type_name(wid_type), wid_caps);
c4920606 815 if (wid_caps & AC_WCAP_STEREO) {
fd72d008 816 unsigned int chans = get_wcaps_channels(wid_caps);
c4920606
TI
817 if (chans == 2)
818 snd_iprintf(buffer, " Stereo");
819 else
820 snd_iprintf(buffer, " %d-Channels", chans);
821 } else
1da177e4
LT
822 snd_iprintf(buffer, " Mono");
823 if (wid_caps & AC_WCAP_DIGITAL)
824 snd_iprintf(buffer, " Digital");
825 if (wid_caps & AC_WCAP_IN_AMP)
826 snd_iprintf(buffer, " Amp-In");
827 if (wid_caps & AC_WCAP_OUT_AMP)
828 snd_iprintf(buffer, " Amp-Out");
797760ab
AP
829 if (wid_caps & AC_WCAP_STRIPE)
830 snd_iprintf(buffer, " Stripe");
831 if (wid_caps & AC_WCAP_LR_SWAP)
832 snd_iprintf(buffer, " R/L");
c4920606
TI
833 if (wid_caps & AC_WCAP_CP_CAPS)
834 snd_iprintf(buffer, " CP");
1da177e4
LT
835 snd_iprintf(buffer, "\n");
836
5b0cb1d8
JK
837 print_nid_array(buffer, codec, nid, &codec->mixers);
838 print_nid_array(buffer, codec, nid, &codec->nids);
3911a4c1
JK
839 print_nid_pcms(buffer, codec, nid);
840
e1716139
TI
841 /* volume knob is a special widget that always have connection
842 * list
843 */
844 if (wid_type == AC_WID_VOL_KNB)
845 wid_caps |= AC_WCAP_CONN_LIST;
846
4eea3091
TI
847 if (wid_caps & AC_WCAP_CONN_LIST) {
848 conn_len = snd_hda_get_num_raw_conns(codec, nid);
849 if (conn_len > 0) {
6da2ec56
KC
850 conn = kmalloc_array(conn_len,
851 sizeof(hda_nid_t),
852 GFP_KERNEL);
4eea3091
TI
853 if (!conn)
854 return;
855 if (snd_hda_get_raw_connections(codec, nid, conn,
856 conn_len) < 0)
857 conn_len = 0;
858 }
859 }
3e289f16 860
1da177e4
LT
861 if (wid_caps & AC_WCAP_IN_AMP) {
862 snd_iprintf(buffer, " Amp-In caps: ");
863 print_amp_caps(buffer, codec, nid, HDA_INPUT);
864 snd_iprintf(buffer, " Amp-In vals: ");
4f32456e
MK
865 if (wid_type == AC_WID_PIN ||
866 (codec->single_adc_amp &&
867 wid_type == AC_WID_AUD_IN))
868 print_amp_vals(buffer, codec, nid, HDA_INPUT,
cc261738 869 wid_caps, 1);
4f32456e
MK
870 else
871 print_amp_vals(buffer, codec, nid, HDA_INPUT,
cc261738 872 wid_caps, conn_len);
1da177e4
LT
873 }
874 if (wid_caps & AC_WCAP_OUT_AMP) {
875 snd_iprintf(buffer, " Amp-Out caps: ");
876 print_amp_caps(buffer, codec, nid, HDA_OUTPUT);
877 snd_iprintf(buffer, " Amp-Out vals: ");
9421f954
TI
878 if (wid_type == AC_WID_PIN &&
879 codec->pin_amp_workaround)
880 print_amp_vals(buffer, codec, nid, HDA_OUTPUT,
cc261738 881 wid_caps, conn_len);
9421f954
TI
882 else
883 print_amp_vals(buffer, codec, nid, HDA_OUTPUT,
cc261738 884 wid_caps, 1);
1da177e4
LT
885 }
886
e97a5167 887 switch (wid_type) {
797760ab
AP
888 case AC_WID_PIN: {
889 int supports_vref;
890 print_pin_caps(buffer, codec, nid, &supports_vref);
891 print_pin_ctls(buffer, codec, nid, supports_vref);
e97a5167 892 break;
797760ab 893 }
e97a5167 894 case AC_WID_VOL_KNB:
797760ab 895 print_vol_knob(buffer, codec, nid);
e97a5167
TI
896 break;
897 case AC_WID_AUD_OUT:
898 case AC_WID_AUD_IN:
797760ab
AP
899 print_audio_io(buffer, codec, nid, wid_type);
900 if (wid_caps & AC_WCAP_DIGITAL)
901 print_digital_conv(buffer, codec, nid);
e97a5167
TI
902 if (wid_caps & AC_WCAP_FORMAT_OVRD) {
903 snd_iprintf(buffer, " PCM:\n");
904 print_pcm_caps(buffer, codec, nid);
905 }
906 break;
1da177e4
LT
907 }
908
797760ab
AP
909 if (wid_caps & AC_WCAP_UNSOL_CAP)
910 print_unsol_cap(buffer, codec, nid);
911
b7027cc2 912 if (wid_caps & AC_WCAP_POWER)
797760ab
AP
913 print_power_state(buffer, codec, nid);
914
915 if (wid_caps & AC_WCAP_DELAY)
916 snd_iprintf(buffer, " Delay: %d samples\n",
917 (wid_caps & AC_WCAP_DELAY) >>
918 AC_WCAP_DELAY_SHIFT);
919
7a624ea5
ML
920 if (wid_type == AC_WID_PIN && codec->dp_mst)
921 print_device_list(buffer, codec, nid);
922
797760ab
AP
923 if (wid_caps & AC_WCAP_CONN_LIST)
924 print_conn_list(buffer, codec, nid, wid_type,
925 conn, conn_len);
926
927 if (wid_caps & AC_WCAP_PROC_WID)
928 print_proc_caps(buffer, codec, nid);
929
daead538
TI
930 if (codec->proc_widget_hook)
931 codec->proc_widget_hook(buffer, codec, nid);
4eea3091
TI
932
933 kfree(conn);
1da177e4 934 }
cb53c626 935 snd_hda_power_down(codec);
1da177e4
LT
936}
937
938/*
939 * create a proc read
940 */
941int snd_hda_codec_proc_new(struct hda_codec *codec)
942{
943 char name[32];
1da177e4 944
7639a06c 945 snprintf(name, sizeof(name), "codec#%d", codec->core.addr);
47f2769b 946 return snd_card_ro_proc_new(codec->card, name, codec, print_codec_info);
1da177e4
LT
947}
948