diff options
author | Andrew Paprocki <andrew@ishiboo.com> | 2008-01-18 06:51:11 -0500 |
---|---|---|
committer | Jaroslav Kysela <perex@perex.cz> | 2008-01-31 11:30:04 -0500 |
commit | 797760ab14db4e82a50c06a9916dd5c6147b415b (patch) | |
tree | c60c279c9dbbe81d399a0d6a7648cfacb2bef60d | |
parent | e0059549345903195d6eb796c22048204c40a785 (diff) |
[ALSA] hda_proc - Add a number of new settings to proc codec output
This patch adds additional output to the /proc codec#X info.
The following pieces of information are added to the output:
- Balanced, L/R swap, trigger, impedance sense pin capabilities
- Vref pin capabilities
- Current Vref pin widget control setting
- Default configuration association, sequence, and misc bit test
- EAPD/BTL bits conveying balanced mode, EAPD, and L/R swap
- Power state modified to show state name as well as setting vs actual value
- GPIO parameter output on Audio Function Group, including enumeration of IO
pins which are indicated present (Any I and O pins are not output at this
time)
- Stripe and L/R swap widget capabilities
- All digital converter bits: enable, validity, validity config, preemphasis,
copyright, non-audio, professional, generation level, and content category
- Converter stream and channel values for in/out widgets
- SDI select value for in widgets
- Unsolicited response widget capability tag and enabled bit
- Delay widget capability value
- Processing widget capability benign bit and number of coefficients
- Realtek Define Registers: processing coefficient, coefficient index
[Also, fixed space/tab issues and make codes a bit more readable
-- Takashi]
Signed-off-by: Andrew Paprocki <andrew@ishiboo.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
-rw-r--r-- | sound/pci/hda/hda_codec.h | 42 | ||||
-rw-r--r-- | sound/pci/hda/hda_proc.c | 351 |
2 files changed, 343 insertions, 50 deletions
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h index 719e46f6fb36..eb4a2ae792e9 100644 --- a/sound/pci/hda/hda_codec.h +++ b/sound/pci/hda/hda_codec.h | |||
@@ -84,7 +84,9 @@ enum { | |||
84 | #define AC_VERB_GET_GPIO_DATA 0x0f15 | 84 | #define AC_VERB_GET_GPIO_DATA 0x0f15 |
85 | #define AC_VERB_GET_GPIO_MASK 0x0f16 | 85 | #define AC_VERB_GET_GPIO_MASK 0x0f16 |
86 | #define AC_VERB_GET_GPIO_DIRECTION 0x0f17 | 86 | #define AC_VERB_GET_GPIO_DIRECTION 0x0f17 |
87 | #define AC_VERB_GET_GPIO_WAKE_MASK 0x0f18 | ||
87 | #define AC_VERB_GET_GPIO_UNSOLICITED_RSP_MASK 0x0f19 | 88 | #define AC_VERB_GET_GPIO_UNSOLICITED_RSP_MASK 0x0f19 |
89 | #define AC_VERB_GET_GPIO_STICKY_MASK 0x0f1a | ||
88 | #define AC_VERB_GET_CONFIG_DEFAULT 0x0f1c | 90 | #define AC_VERB_GET_CONFIG_DEFAULT 0x0f1c |
89 | /* f20: AFG/MFG */ | 91 | /* f20: AFG/MFG */ |
90 | #define AC_VERB_GET_SUBSYSTEM_ID 0x0f20 | 92 | #define AC_VERB_GET_SUBSYSTEM_ID 0x0f20 |
@@ -112,7 +114,9 @@ enum { | |||
112 | #define AC_VERB_SET_GPIO_DATA 0x715 | 114 | #define AC_VERB_SET_GPIO_DATA 0x715 |
113 | #define AC_VERB_SET_GPIO_MASK 0x716 | 115 | #define AC_VERB_SET_GPIO_MASK 0x716 |
114 | #define AC_VERB_SET_GPIO_DIRECTION 0x717 | 116 | #define AC_VERB_SET_GPIO_DIRECTION 0x717 |
117 | #define AC_VERB_SET_GPIO_WAKE_MASK 0x718 | ||
115 | #define AC_VERB_SET_GPIO_UNSOLICITED_RSP_MASK 0x719 | 118 | #define AC_VERB_SET_GPIO_UNSOLICITED_RSP_MASK 0x719 |
119 | #define AC_VERB_SET_GPIO_STICKY_MASK 0x71a | ||
116 | #define AC_VERB_SET_CONFIG_DEFAULT_BYTES_0 0x71c | 120 | #define AC_VERB_SET_CONFIG_DEFAULT_BYTES_0 0x71c |
117 | #define AC_VERB_SET_CONFIG_DEFAULT_BYTES_1 0x71d | 121 | #define AC_VERB_SET_CONFIG_DEFAULT_BYTES_1 0x71d |
118 | #define AC_VERB_SET_CONFIG_DEFAULT_BYTES_2 0x71e | 122 | #define AC_VERB_SET_CONFIG_DEFAULT_BYTES_2 0x71e |
@@ -185,6 +189,27 @@ enum { | |||
185 | #define AC_SUPFMT_FLOAT32 (1<<1) | 189 | #define AC_SUPFMT_FLOAT32 (1<<1) |
186 | #define AC_SUPFMT_AC3 (1<<2) | 190 | #define AC_SUPFMT_AC3 (1<<2) |
187 | 191 | ||
192 | /* GP I/O count */ | ||
193 | #define AC_GPIO_IO_COUNT (0xff<<0) | ||
194 | #define AC_GPIO_O_COUNT (0xff<<8) | ||
195 | #define AC_GPIO_O_COUNT_SHIFT 8 | ||
196 | #define AC_GPIO_I_COUNT (0xff<<16) | ||
197 | #define AC_GPIO_I_COUNT_SHIFT 16 | ||
198 | #define AC_GPIO_UNSOLICITED (1<<30) | ||
199 | #define AC_GPIO_WAKE (1<<31) | ||
200 | |||
201 | /* Converter stream, channel */ | ||
202 | #define AC_CONV_CHANNEL (0xf<<0) | ||
203 | #define AC_CONV_STREAM (0xf<<4) | ||
204 | #define AC_CONV_STREAM_SHIFT 4 | ||
205 | |||
206 | /* Input converter SDI select */ | ||
207 | #define AC_SDI_SELECT (0xf<<0) | ||
208 | |||
209 | /* Unsolicited response */ | ||
210 | #define AC_UNSOL_TAG (0x3f<<0) | ||
211 | #define AC_UNSOL_ENABLED (1<<7) | ||
212 | |||
188 | /* Pin widget capabilies */ | 213 | /* Pin widget capabilies */ |
189 | #define AC_PINCAP_IMP_SENSE (1<<0) /* impedance sense capable */ | 214 | #define AC_PINCAP_IMP_SENSE (1<<0) /* impedance sense capable */ |
190 | #define AC_PINCAP_TRIG_REQ (1<<1) /* trigger required */ | 215 | #define AC_PINCAP_TRIG_REQ (1<<1) /* trigger required */ |
@@ -230,6 +255,9 @@ enum { | |||
230 | #define AC_PWRST_D3SUP (1<<3) | 255 | #define AC_PWRST_D3SUP (1<<3) |
231 | 256 | ||
232 | /* Power state values */ | 257 | /* Power state values */ |
258 | #define AC_PWRST_SETTING (0xf<<0) | ||
259 | #define AC_PWRST_ACTUAL (0xf<<4) | ||
260 | #define AC_PWRST_ACTUAL_SHIFT 4 | ||
233 | #define AC_PWRST_D0 0x00 | 261 | #define AC_PWRST_D0 0x00 |
234 | #define AC_PWRST_D1 0x01 | 262 | #define AC_PWRST_D1 0x01 |
235 | #define AC_PWRST_D2 0x02 | 263 | #define AC_PWRST_D2 0x02 |
@@ -238,6 +266,7 @@ enum { | |||
238 | /* Processing capabilies */ | 266 | /* Processing capabilies */ |
239 | #define AC_PCAP_BENIGN (1<<0) | 267 | #define AC_PCAP_BENIGN (1<<0) |
240 | #define AC_PCAP_NUM_COEF (0xff<<8) | 268 | #define AC_PCAP_NUM_COEF (0xff<<8) |
269 | #define AC_PCAP_NUM_COEF_SHIFT 8 | ||
241 | 270 | ||
242 | /* Volume knobs capabilities */ | 271 | /* Volume knobs capabilities */ |
243 | #define AC_KNBCAP_NUM_STEPS (0x7f<<0) | 272 | #define AC_KNBCAP_NUM_STEPS (0x7f<<0) |
@@ -274,6 +303,9 @@ enum { | |||
274 | #define AC_DIG1_PROFESSIONAL (1<<6) | 303 | #define AC_DIG1_PROFESSIONAL (1<<6) |
275 | #define AC_DIG1_LEVEL (1<<7) | 304 | #define AC_DIG1_LEVEL (1<<7) |
276 | 305 | ||
306 | /* DIGITAL2 bits */ | ||
307 | #define AC_DIG2_CC (0x7f<<0) | ||
308 | |||
277 | /* Pin widget control - 8bit */ | 309 | /* Pin widget control - 8bit */ |
278 | #define AC_PINCTL_VREFEN (0x7<<0) | 310 | #define AC_PINCTL_VREFEN (0x7<<0) |
279 | #define AC_PINCTL_VREF_HIZ 0 /* Hi-Z */ | 311 | #define AC_PINCTL_VREF_HIZ 0 /* Hi-Z */ |
@@ -288,12 +320,22 @@ enum { | |||
288 | /* Unsolicited response - 8bit */ | 320 | /* Unsolicited response - 8bit */ |
289 | #define AC_USRSP_EN (1<<7) | 321 | #define AC_USRSP_EN (1<<7) |
290 | 322 | ||
323 | /* Pin sense - 32bit */ | ||
324 | #define AC_PINSENSE_IMPEDANCE_MASK (0x7fffffff) | ||
325 | #define AC_PINSENSE_PRESENCE (1<<31) | ||
326 | |||
327 | /* EAPD/BTL enable - 32bit */ | ||
328 | #define AC_EAPDBTL_BALANCED (1<<0) | ||
329 | #define AC_EAPDBTL_EAPD (1<<1) | ||
330 | #define AC_EAPDBTL_LR_SWAP (1<<2) | ||
331 | |||
291 | /* configuration default - 32bit */ | 332 | /* configuration default - 32bit */ |
292 | #define AC_DEFCFG_SEQUENCE (0xf<<0) | 333 | #define AC_DEFCFG_SEQUENCE (0xf<<0) |
293 | #define AC_DEFCFG_DEF_ASSOC (0xf<<4) | 334 | #define AC_DEFCFG_DEF_ASSOC (0xf<<4) |
294 | #define AC_DEFCFG_ASSOC_SHIFT 4 | 335 | #define AC_DEFCFG_ASSOC_SHIFT 4 |
295 | #define AC_DEFCFG_MISC (0xf<<8) | 336 | #define AC_DEFCFG_MISC (0xf<<8) |
296 | #define AC_DEFCFG_MISC_SHIFT 8 | 337 | #define AC_DEFCFG_MISC_SHIFT 8 |
338 | #define AC_DEFCFG_MISC_NO_PRESENCE (1<<0) | ||
297 | #define AC_DEFCFG_COLOR (0xf<<12) | 339 | #define AC_DEFCFG_COLOR (0xf<<12) |
298 | #define AC_DEFCFG_COLOR_SHIFT 12 | 340 | #define AC_DEFCFG_COLOR_SHIFT 12 |
299 | #define AC_DEFCFG_CONN_TYPE (0xf<<16) | 341 | #define AC_DEFCFG_CONN_TYPE (0xf<<16) |
diff --git a/sound/pci/hda/hda_proc.c b/sound/pci/hda/hda_proc.c index 4b8d64498fb1..35a630d1770f 100644 --- a/sound/pci/hda/hda_proc.c +++ b/sound/pci/hda/hda_proc.c | |||
@@ -202,7 +202,8 @@ static const char *get_jack_color(u32 cfg) | |||
202 | } | 202 | } |
203 | 203 | ||
204 | static void print_pin_caps(struct snd_info_buffer *buffer, | 204 | static void print_pin_caps(struct snd_info_buffer *buffer, |
205 | struct hda_codec *codec, hda_nid_t nid) | 205 | struct hda_codec *codec, hda_nid_t nid, |
206 | int *supports_vref) | ||
206 | { | 207 | { |
207 | static char *jack_conns[4] = { "Jack", "N/A", "Fixed", "Both" }; | 208 | static char *jack_conns[4] = { "Jack", "N/A", "Fixed", "Both" }; |
208 | static char *jack_types[16] = { | 209 | static char *jack_types[16] = { |
@@ -226,7 +227,45 @@ static void print_pin_caps(struct snd_info_buffer *buffer, | |||
226 | snd_iprintf(buffer, " EAPD"); | 227 | snd_iprintf(buffer, " EAPD"); |
227 | if (caps & AC_PINCAP_PRES_DETECT) | 228 | if (caps & AC_PINCAP_PRES_DETECT) |
228 | snd_iprintf(buffer, " Detect"); | 229 | snd_iprintf(buffer, " Detect"); |
230 | if (caps & AC_PINCAP_BALANCE) | ||
231 | snd_iprintf(buffer, " Balanced"); | ||
232 | if (caps & AC_PINCAP_LR_SWAP) | ||
233 | snd_iprintf(buffer, " R/L"); | ||
234 | if (caps & AC_PINCAP_TRIG_REQ) | ||
235 | snd_iprintf(buffer, " Trigger"); | ||
236 | if (caps & AC_PINCAP_IMP_SENSE) | ||
237 | snd_iprintf(buffer, " ImpSense"); | ||
229 | snd_iprintf(buffer, "\n"); | 238 | snd_iprintf(buffer, "\n"); |
239 | if (caps & AC_PINCAP_VREF) { | ||
240 | unsigned int vref = | ||
241 | (caps & AC_PINCAP_VREF) >> AC_PINCAP_VREF_SHIFT; | ||
242 | snd_iprintf(buffer, " Vref caps:"); | ||
243 | if (vref & AC_PINCAP_VREF_HIZ) | ||
244 | snd_iprintf(buffer, " HIZ"); | ||
245 | if (vref & AC_PINCAP_VREF_50) | ||
246 | snd_iprintf(buffer, " 50"); | ||
247 | if (vref & AC_PINCAP_VREF_GRD) | ||
248 | snd_iprintf(buffer, " GRD"); | ||
249 | if (vref & AC_PINCAP_VREF_80) | ||
250 | snd_iprintf(buffer, " 80"); | ||
251 | if (vref & AC_PINCAP_VREF_100) | ||
252 | snd_iprintf(buffer, " 100"); | ||
253 | snd_iprintf(buffer, "\n"); | ||
254 | *supports_vref = 1; | ||
255 | } else | ||
256 | *supports_vref = 0; | ||
257 | if (caps & AC_PINCAP_EAPD) { | ||
258 | val = snd_hda_codec_read(codec, nid, 0, | ||
259 | AC_VERB_GET_EAPD_BTLENABLE, 0); | ||
260 | snd_iprintf(buffer, " EAPD 0x%x:", val); | ||
261 | if (val & AC_EAPDBTL_BALANCED) | ||
262 | snd_iprintf(buffer, " BALANCED"); | ||
263 | if (val & AC_EAPDBTL_EAPD) | ||
264 | snd_iprintf(buffer, " EAPD"); | ||
265 | if (val & AC_EAPDBTL_LR_SWAP) | ||
266 | snd_iprintf(buffer, " R/L"); | ||
267 | snd_iprintf(buffer, "\n"); | ||
268 | } | ||
230 | caps = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONFIG_DEFAULT, 0); | 269 | caps = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONFIG_DEFAULT, 0); |
231 | snd_iprintf(buffer, " Pin Default 0x%08x: [%s] %s at %s %s\n", caps, | 270 | snd_iprintf(buffer, " Pin Default 0x%08x: [%s] %s at %s %s\n", caps, |
232 | jack_conns[(caps & AC_DEFCFG_PORT_CONN) >> AC_DEFCFG_PORT_CONN_SHIFT], | 271 | jack_conns[(caps & AC_DEFCFG_PORT_CONN) >> AC_DEFCFG_PORT_CONN_SHIFT], |
@@ -236,13 +275,233 @@ static void print_pin_caps(struct snd_info_buffer *buffer, | |||
236 | snd_iprintf(buffer, " Conn = %s, Color = %s\n", | 275 | snd_iprintf(buffer, " Conn = %s, Color = %s\n", |
237 | get_jack_connection(caps), | 276 | get_jack_connection(caps), |
238 | get_jack_color(caps)); | 277 | get_jack_color(caps)); |
239 | if (caps & AC_PINCAP_EAPD) { | 278 | /* Default association and sequence values refer to default grouping |
240 | val = snd_hda_codec_read(codec, nid, 0, | 279 | * of pin complexes and their sequence within the group. This is used |
241 | AC_VERB_GET_EAPD_BTLENABLE, 0); | 280 | * for priority and resource allocation. |
242 | snd_iprintf(buffer, " EAPD: 0x%x\n", val); | 281 | */ |
282 | snd_iprintf(buffer, " DefAssociation = 0x%x, Sequence = 0x%x\n", | ||
283 | (caps & AC_DEFCFG_DEF_ASSOC) >> AC_DEFCFG_ASSOC_SHIFT, | ||
284 | caps & AC_DEFCFG_SEQUENCE); | ||
285 | if (((caps & AC_DEFCFG_MISC) >> AC_DEFCFG_MISC_SHIFT) & | ||
286 | AC_DEFCFG_MISC_NO_PRESENCE) { | ||
287 | /* Miscellaneous bit indicates external hardware does not | ||
288 | * support presence detection even if the pin complex | ||
289 | * indicates it is supported. | ||
290 | */ | ||
291 | snd_iprintf(buffer, " Misc = NO_PRESENCE\n"); | ||
243 | } | 292 | } |
244 | } | 293 | } |
245 | 294 | ||
295 | static void print_pin_ctls(struct snd_info_buffer *buffer, | ||
296 | struct hda_codec *codec, hda_nid_t nid, | ||
297 | int supports_vref) | ||
298 | { | ||
299 | unsigned int pinctls; | ||
300 | |||
301 | pinctls = snd_hda_codec_read(codec, nid, 0, | ||
302 | AC_VERB_GET_PIN_WIDGET_CONTROL, 0); | ||
303 | snd_iprintf(buffer, " Pin-ctls: 0x%02x:", pinctls); | ||
304 | if (pinctls & AC_PINCTL_IN_EN) | ||
305 | snd_iprintf(buffer, " IN"); | ||
306 | if (pinctls & AC_PINCTL_OUT_EN) | ||
307 | snd_iprintf(buffer, " OUT"); | ||
308 | if (pinctls & AC_PINCTL_HP_EN) | ||
309 | snd_iprintf(buffer, " HP"); | ||
310 | if (supports_vref) { | ||
311 | int vref = pinctls & AC_PINCTL_VREFEN; | ||
312 | switch (vref) { | ||
313 | case AC_PINCTL_VREF_HIZ: | ||
314 | snd_iprintf(buffer, " VREF_HIZ"); | ||
315 | break; | ||
316 | case AC_PINCTL_VREF_50: | ||
317 | snd_iprintf(buffer, " VREF_50"); | ||
318 | break; | ||
319 | case AC_PINCTL_VREF_GRD: | ||
320 | snd_iprintf(buffer, " VREF_GRD"); | ||
321 | break; | ||
322 | case AC_PINCTL_VREF_80: | ||
323 | snd_iprintf(buffer, " VREF_80"); | ||
324 | break; | ||
325 | case AC_PINCTL_VREF_100: | ||
326 | snd_iprintf(buffer, " VREF_100"); | ||
327 | break; | ||
328 | } | ||
329 | } | ||
330 | snd_iprintf(buffer, "\n"); | ||
331 | } | ||
332 | |||
333 | static void print_vol_knob(struct snd_info_buffer *buffer, | ||
334 | struct hda_codec *codec, hda_nid_t nid) | ||
335 | { | ||
336 | unsigned int cap = snd_hda_param_read(codec, nid, | ||
337 | AC_PAR_VOL_KNB_CAP); | ||
338 | snd_iprintf(buffer, " Volume-Knob: delta=%d, steps=%d, ", | ||
339 | (cap >> 7) & 1, cap & 0x7f); | ||
340 | cap = snd_hda_codec_read(codec, nid, 0, | ||
341 | AC_VERB_GET_VOLUME_KNOB_CONTROL, 0); | ||
342 | snd_iprintf(buffer, "direct=%d, val=%d\n", | ||
343 | (cap >> 7) & 1, cap & 0x7f); | ||
344 | } | ||
345 | |||
346 | static void print_audio_io(struct snd_info_buffer *buffer, | ||
347 | struct hda_codec *codec, hda_nid_t nid, | ||
348 | unsigned int wid_type) | ||
349 | { | ||
350 | int conv = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONV, 0); | ||
351 | snd_iprintf(buffer, | ||
352 | " Converter: stream=%d, channel=%d\n", | ||
353 | (conv & AC_CONV_STREAM) >> AC_CONV_STREAM_SHIFT, | ||
354 | conv & AC_CONV_CHANNEL); | ||
355 | |||
356 | if (wid_type == AC_WID_AUD_IN && (conv & AC_CONV_CHANNEL) == 0) { | ||
357 | int sdi = snd_hda_codec_read(codec, nid, 0, | ||
358 | AC_VERB_GET_SDI_SELECT, 0); | ||
359 | snd_iprintf(buffer, " SDI-Select: %d\n", | ||
360 | sdi & AC_SDI_SELECT); | ||
361 | } | ||
362 | } | ||
363 | |||
364 | static void print_digital_conv(struct snd_info_buffer *buffer, | ||
365 | struct hda_codec *codec, hda_nid_t nid) | ||
366 | { | ||
367 | unsigned int digi1 = snd_hda_codec_read(codec, nid, 0, | ||
368 | AC_VERB_GET_DIGI_CONVERT_1, 0); | ||
369 | unsigned int digi2 = snd_hda_codec_read(codec, nid, 0, | ||
370 | AC_VERB_GET_DIGI_CONVERT_2, 0); | ||
371 | snd_iprintf(buffer, " Digital:"); | ||
372 | if (digi1 & AC_DIG1_ENABLE) | ||
373 | snd_iprintf(buffer, " Enabled"); | ||
374 | if (digi1 & AC_DIG1_V) | ||
375 | snd_iprintf(buffer, " Validity"); | ||
376 | if (digi1 & AC_DIG1_VCFG) | ||
377 | snd_iprintf(buffer, " ValidityCfg"); | ||
378 | if (digi1 & AC_DIG1_EMPHASIS) | ||
379 | snd_iprintf(buffer, " Preemphasis"); | ||
380 | if (digi1 & AC_DIG1_COPYRIGHT) | ||
381 | snd_iprintf(buffer, " Copyright"); | ||
382 | if (digi1 & AC_DIG1_NONAUDIO) | ||
383 | snd_iprintf(buffer, " Non-Audio"); | ||
384 | if (digi1 & AC_DIG1_PROFESSIONAL) | ||
385 | snd_iprintf(buffer, " Pro"); | ||
386 | if (digi1 & AC_DIG1_LEVEL) | ||
387 | snd_iprintf(buffer, " GenLevel"); | ||
388 | snd_iprintf(buffer, "\n"); | ||
389 | snd_iprintf(buffer, " Digital category: 0x%x\n", digi2 & AC_DIG2_CC); | ||
390 | } | ||
391 | |||
392 | static const char *get_pwr_state(u32 state) | ||
393 | { | ||
394 | static const char *buf[4] = { | ||
395 | "D0", "D1", "D2", "D3" | ||
396 | }; | ||
397 | if (state < 4) | ||
398 | return buf[state]; | ||
399 | return "UNKNOWN"; | ||
400 | } | ||
401 | |||
402 | static void print_power_state(struct snd_info_buffer *buffer, | ||
403 | struct hda_codec *codec, hda_nid_t nid) | ||
404 | { | ||
405 | int pwr = snd_hda_codec_read(codec, nid, 0, | ||
406 | AC_VERB_GET_POWER_STATE, 0); | ||
407 | snd_iprintf(buffer, " Power: setting=%s, actual=%s\n", | ||
408 | get_pwr_state(pwr & AC_PWRST_SETTING), | ||
409 | get_pwr_state((pwr & AC_PWRST_ACTUAL) >> | ||
410 | AC_PWRST_ACTUAL_SHIFT)); | ||
411 | } | ||
412 | |||
413 | static void print_unsol_cap(struct snd_info_buffer *buffer, | ||
414 | struct hda_codec *codec, hda_nid_t nid) | ||
415 | { | ||
416 | int unsol = snd_hda_codec_read(codec, nid, 0, | ||
417 | AC_VERB_GET_UNSOLICITED_RESPONSE, 0); | ||
418 | snd_iprintf(buffer, | ||
419 | " Unsolicited: tag=%02x, enabled=%d\n", | ||
420 | unsol & AC_UNSOL_TAG, | ||
421 | (unsol & AC_UNSOL_ENABLED) ? 1 : 0); | ||
422 | } | ||
423 | |||
424 | static void print_proc_caps(struct snd_info_buffer *buffer, | ||
425 | struct hda_codec *codec, hda_nid_t nid) | ||
426 | { | ||
427 | unsigned int proc_caps = snd_hda_param_read(codec, nid, | ||
428 | AC_PAR_PROC_CAP); | ||
429 | snd_iprintf(buffer, " Processing caps: benign=%d, ncoeff=%d\n", | ||
430 | proc_caps & AC_PCAP_BENIGN, | ||
431 | (proc_caps & AC_PCAP_NUM_COEF) >> AC_PCAP_NUM_COEF_SHIFT); | ||
432 | } | ||
433 | |||
434 | static void print_conn_list(struct snd_info_buffer *buffer, | ||
435 | struct hda_codec *codec, hda_nid_t nid, | ||
436 | unsigned int wid_type, hda_nid_t *conn, | ||
437 | int conn_len) | ||
438 | { | ||
439 | int c, curr = -1; | ||
440 | |||
441 | if (conn_len > 1 && wid_type != AC_WID_AUD_MIX) | ||
442 | curr = snd_hda_codec_read(codec, nid, 0, | ||
443 | AC_VERB_GET_CONNECT_SEL, 0); | ||
444 | snd_iprintf(buffer, " Connection: %d\n", conn_len); | ||
445 | if (conn_len > 0) { | ||
446 | snd_iprintf(buffer, " "); | ||
447 | for (c = 0; c < conn_len; c++) { | ||
448 | snd_iprintf(buffer, " 0x%02x", conn[c]); | ||
449 | if (c == curr) | ||
450 | snd_iprintf(buffer, "*"); | ||
451 | } | ||
452 | snd_iprintf(buffer, "\n"); | ||
453 | } | ||
454 | } | ||
455 | |||
456 | static void print_realtek_coef(struct snd_info_buffer *buffer, | ||
457 | struct hda_codec *codec, hda_nid_t nid) | ||
458 | { | ||
459 | int coeff = snd_hda_codec_read(codec, nid, 0, | ||
460 | AC_VERB_GET_PROC_COEF, 0); | ||
461 | snd_iprintf(buffer, " Processing Coefficient: 0x%02x\n", coeff); | ||
462 | coeff = snd_hda_codec_read(codec, nid, 0, | ||
463 | AC_VERB_GET_COEF_INDEX, 0); | ||
464 | snd_iprintf(buffer, " Coefficient Index: 0x%02x\n", coeff); | ||
465 | } | ||
466 | |||
467 | static void print_gpio(struct snd_info_buffer *buffer, | ||
468 | struct hda_codec *codec, hda_nid_t nid) | ||
469 | { | ||
470 | unsigned int gpio = | ||
471 | snd_hda_param_read(codec, codec->afg, AC_PAR_GPIO_CAP); | ||
472 | unsigned int enable, direction, wake, unsol, sticky, data; | ||
473 | int i, max; | ||
474 | snd_iprintf(buffer, "GPIO: io=%d, o=%d, i=%d, " | ||
475 | "unsolicited=%d, wake=%d\n", | ||
476 | gpio & AC_GPIO_IO_COUNT, | ||
477 | (gpio & AC_GPIO_O_COUNT) >> AC_GPIO_O_COUNT_SHIFT, | ||
478 | (gpio & AC_GPIO_I_COUNT) >> AC_GPIO_I_COUNT_SHIFT, | ||
479 | (gpio & AC_GPIO_UNSOLICITED) ? 1 : 0, | ||
480 | (gpio & AC_GPIO_WAKE) ? 1 : 0); | ||
481 | max = gpio & AC_GPIO_IO_COUNT; | ||
482 | enable = snd_hda_codec_read(codec, nid, 0, | ||
483 | AC_VERB_GET_GPIO_MASK, 0); | ||
484 | direction = snd_hda_codec_read(codec, nid, 0, | ||
485 | AC_VERB_GET_GPIO_DIRECTION, 0); | ||
486 | wake = snd_hda_codec_read(codec, nid, 0, | ||
487 | AC_VERB_GET_GPIO_WAKE_MASK, 0); | ||
488 | unsol = snd_hda_codec_read(codec, nid, 0, | ||
489 | AC_VERB_GET_GPIO_UNSOLICITED_RSP_MASK, 0); | ||
490 | sticky = snd_hda_codec_read(codec, nid, 0, | ||
491 | AC_VERB_GET_GPIO_STICKY_MASK, 0); | ||
492 | data = snd_hda_codec_read(codec, nid, 0, | ||
493 | AC_VERB_GET_GPIO_DATA, 0); | ||
494 | for (i = 0; i < max; ++i) | ||
495 | snd_iprintf(buffer, | ||
496 | " IO[%d]: enable=%d, dir=%d, wake=%d, " | ||
497 | "sticky=%d, data=%d\n", i, | ||
498 | (enable & (1<<i)) ? 1 : 0, | ||
499 | (direction & (1<<i)) ? 1 : 0, | ||
500 | (wake & (1<<i)) ? 1 : 0, | ||
501 | (sticky & (1<<i)) ? 1 : 0, | ||
502 | (data & (1<<i)) ? 1 : 0); | ||
503 | /* FIXME: add GPO and GPI pin information */ | ||
504 | } | ||
246 | 505 | ||
247 | static void print_codec_info(struct snd_info_entry *entry, | 506 | static void print_codec_info(struct snd_info_entry *entry, |
248 | struct snd_info_buffer *buffer) | 507 | struct snd_info_buffer *buffer) |
@@ -280,15 +539,17 @@ static void print_codec_info(struct snd_info_entry *entry, | |||
280 | snd_hda_power_down(codec); | 539 | snd_hda_power_down(codec); |
281 | return; | 540 | return; |
282 | } | 541 | } |
542 | |||
543 | print_gpio(buffer, codec, codec->afg); | ||
544 | |||
283 | for (i = 0; i < nodes; i++, nid++) { | 545 | for (i = 0; i < nodes; i++, nid++) { |
284 | unsigned int wid_caps = | 546 | unsigned int wid_caps = |
285 | snd_hda_param_read(codec, nid, | 547 | snd_hda_param_read(codec, nid, |
286 | AC_PAR_AUDIO_WIDGET_CAP); | 548 | AC_PAR_AUDIO_WIDGET_CAP); |
287 | unsigned int wid_type = | 549 | unsigned int wid_type = |
288 | (wid_caps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; | 550 | (wid_caps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; |
289 | int conn_len = 0; | ||
290 | hda_nid_t conn[HDA_MAX_CONNECTIONS]; | 551 | hda_nid_t conn[HDA_MAX_CONNECTIONS]; |
291 | unsigned int pinctls; | 552 | int conn_len = 0; |
292 | 553 | ||
293 | snd_iprintf(buffer, "Node 0x%02x [%s] wcaps 0x%x:", nid, | 554 | snd_iprintf(buffer, "Node 0x%02x [%s] wcaps 0x%x:", nid, |
294 | get_wid_type_name(wid_type), wid_caps); | 555 | get_wid_type_name(wid_type), wid_caps); |
@@ -302,6 +563,10 @@ static void print_codec_info(struct snd_info_entry *entry, | |||
302 | snd_iprintf(buffer, " Amp-In"); | 563 | snd_iprintf(buffer, " Amp-In"); |
303 | if (wid_caps & AC_WCAP_OUT_AMP) | 564 | if (wid_caps & AC_WCAP_OUT_AMP) |
304 | snd_iprintf(buffer, " Amp-Out"); | 565 | snd_iprintf(buffer, " Amp-Out"); |
566 | if (wid_caps & AC_WCAP_STRIPE) | ||
567 | snd_iprintf(buffer, " Stripe"); | ||
568 | if (wid_caps & AC_WCAP_LR_SWAP) | ||
569 | snd_iprintf(buffer, " R/L"); | ||
305 | snd_iprintf(buffer, "\n"); | 570 | snd_iprintf(buffer, "\n"); |
306 | 571 | ||
307 | /* volume knob is a special widget that always have connection | 572 | /* volume knob is a special widget that always have connection |
@@ -330,33 +595,20 @@ static void print_codec_info(struct snd_info_entry *entry, | |||
330 | } | 595 | } |
331 | 596 | ||
332 | switch (wid_type) { | 597 | switch (wid_type) { |
333 | case AC_WID_PIN: | 598 | case AC_WID_PIN: { |
334 | print_pin_caps(buffer, codec, nid); | 599 | int supports_vref; |
335 | pinctls = snd_hda_codec_read(codec, nid, 0, | 600 | print_pin_caps(buffer, codec, nid, &supports_vref); |
336 | AC_VERB_GET_PIN_WIDGET_CONTROL, | 601 | print_pin_ctls(buffer, codec, nid, supports_vref); |
337 | 0); | ||
338 | snd_iprintf(buffer, " Pin-ctls: 0x%02x:", pinctls); | ||
339 | if (pinctls & AC_PINCTL_IN_EN) | ||
340 | snd_iprintf(buffer, " IN"); | ||
341 | if (pinctls & AC_PINCTL_OUT_EN) | ||
342 | snd_iprintf(buffer, " OUT"); | ||
343 | if (pinctls & AC_PINCTL_HP_EN) | ||
344 | snd_iprintf(buffer, " HP"); | ||
345 | snd_iprintf(buffer, "\n"); | ||
346 | break; | 602 | break; |
603 | } | ||
347 | case AC_WID_VOL_KNB: | 604 | case AC_WID_VOL_KNB: |
348 | pinctls = snd_hda_param_read(codec, nid, | 605 | print_vol_knob(buffer, codec, nid); |
349 | AC_PAR_VOL_KNB_CAP); | ||
350 | snd_iprintf(buffer, " Volume-Knob: delta=%d, " | ||
351 | "steps=%d, ", | ||
352 | (pinctls >> 7) & 1, pinctls & 0x7f); | ||
353 | pinctls = snd_hda_codec_read(codec, nid, 0, | ||
354 | AC_VERB_GET_VOLUME_KNOB_CONTROL, 0); | ||
355 | snd_iprintf(buffer, "direct=%d, val=%d\n", | ||
356 | (pinctls >> 7) & 1, pinctls & 0x7f); | ||
357 | break; | 606 | break; |
358 | case AC_WID_AUD_OUT: | 607 | case AC_WID_AUD_OUT: |
359 | case AC_WID_AUD_IN: | 608 | case AC_WID_AUD_IN: |
609 | print_audio_io(buffer, codec, nid, wid_type); | ||
610 | if (wid_caps & AC_WCAP_DIGITAL) | ||
611 | print_digital_conv(buffer, codec, nid); | ||
360 | if (wid_caps & AC_WCAP_FORMAT_OVRD) { | 612 | if (wid_caps & AC_WCAP_FORMAT_OVRD) { |
361 | snd_iprintf(buffer, " PCM:\n"); | 613 | snd_iprintf(buffer, " PCM:\n"); |
362 | print_pcm_caps(buffer, codec, nid); | 614 | print_pcm_caps(buffer, codec, nid); |
@@ -364,28 +616,27 @@ static void print_codec_info(struct snd_info_entry *entry, | |||
364 | break; | 616 | break; |
365 | } | 617 | } |
366 | 618 | ||
619 | if (wid_caps & AC_WCAP_UNSOL_CAP) | ||
620 | print_unsol_cap(buffer, codec, nid); | ||
621 | |||
367 | if (wid_caps & AC_WCAP_POWER) | 622 | if (wid_caps & AC_WCAP_POWER) |
368 | snd_iprintf(buffer, " Power: 0x%x\n", | 623 | print_power_state(buffer, codec, nid); |
369 | snd_hda_codec_read(codec, nid, 0, | 624 | |
370 | AC_VERB_GET_POWER_STATE, | 625 | if (wid_caps & AC_WCAP_DELAY) |
371 | 0)); | 626 | snd_iprintf(buffer, " Delay: %d samples\n", |
372 | 627 | (wid_caps & AC_WCAP_DELAY) >> | |
373 | if (wid_caps & AC_WCAP_CONN_LIST) { | 628 | AC_WCAP_DELAY_SHIFT); |
374 | int c, curr = -1; | 629 | |
375 | if (conn_len > 1 && wid_type != AC_WID_AUD_MIX) | 630 | if (wid_caps & AC_WCAP_CONN_LIST) |
376 | curr = snd_hda_codec_read(codec, nid, 0, | 631 | print_conn_list(buffer, codec, nid, wid_type, |
377 | AC_VERB_GET_CONNECT_SEL, 0); | 632 | conn, conn_len); |
378 | snd_iprintf(buffer, " Connection: %d\n", conn_len); | 633 | |
379 | if (conn_len > 0) { | 634 | if (wid_caps & AC_WCAP_PROC_WID) |
380 | snd_iprintf(buffer, " "); | 635 | print_proc_caps(buffer, codec, nid); |
381 | for (c = 0; c < conn_len; c++) { | 636 | |
382 | snd_iprintf(buffer, " 0x%02x", conn[c]); | 637 | /* NID 0x20 == Realtek Define Registers */ |
383 | if (c == curr) | 638 | if (codec->vendor_id == 0x10ec && nid == 0x20) |
384 | snd_iprintf(buffer, "*"); | 639 | print_realtek_coef(buffer, codec, nid); |
385 | } | ||
386 | snd_iprintf(buffer, "\n"); | ||
387 | } | ||
388 | } | ||
389 | } | 640 | } |
390 | snd_hda_power_down(codec); | 641 | snd_hda_power_down(codec); |
391 | } | 642 | } |