root/sound/pci/hda/hda_proc.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. get_wid_type_name
  2. print_nid_array
  3. print_nid_pcms
  4. print_amp_caps
  5. is_stereo_amps
  6. print_amp_vals
  7. print_pcm_rates
  8. print_pcm_bits
  9. print_pcm_formats
  10. print_pcm_caps
  11. get_jack_connection
  12. get_jack_color
  13. get_jack_location
  14. get_jack_connectivity
  15. get_jack_type
  16. print_pin_caps
  17. print_pin_ctls
  18. print_vol_knob
  19. print_audio_io
  20. print_digital_conv
  21. get_pwr_state
  22. print_power_state
  23. print_unsol_cap
  24. can_dump_coef
  25. print_proc_caps
  26. print_conn_list
  27. print_gpio
  28. print_device_list
  29. print_codec_core_info
  30. print_codec_info
  31. snd_hda_codec_proc_new

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   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>
   8  */
   9 
  10 #include <linux/init.h>
  11 #include <linux/slab.h>
  12 #include <sound/core.h>
  13 #include <linux/module.h>
  14 #include <sound/hda_codec.h>
  15 #include "hda_local.h"
  16 
  17 static int dump_coef = -1;
  18 module_param(dump_coef, int, 0644);
  19 MODULE_PARM_DESC(dump_coef, "Dump processing coefficients in codec proc file (-1=auto, 0=disable, 1=enable)");
  20 
  21 /* always use noncached version */
  22 #define param_read(codec, nid, parm) \
  23         snd_hdac_read_parm_uncached(&(codec)->core, nid, parm)
  24 
  25 static const char *get_wid_type_name(unsigned int wid_value)
  26 {
  27         static const char * const names[16] = {
  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         };
  38         if (wid_value == -1)
  39                 return "UNKNOWN Widget";
  40         wid_value &= 0xf;
  41         if (names[wid_value])
  42                 return names[wid_value];
  43         else
  44                 return "UNKNOWN Widget";
  45 }
  46 
  47 static void print_nid_array(struct snd_info_buffer *buffer,
  48                             struct hda_codec *codec, hda_nid_t nid,
  49                             struct snd_array *array)
  50 {
  51         int i;
  52         struct hda_nid_item *items = array->list, *item;
  53         struct snd_kcontrol *kctl;
  54         for (i = 0; i < array->used; i++) {
  55                 item = &items[i];
  56                 if (item->nid == nid) {
  57                         kctl = item->kctl;
  58                         snd_iprintf(buffer,
  59                           "  Control: name=\"%s\", index=%i, device=%i\n",
  60                           kctl->id.name, kctl->id.index + item->index,
  61                           kctl->id.device);
  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));
  70                 }
  71         }
  72 }
  73 
  74 static void print_nid_pcms(struct snd_info_buffer *buffer,
  75                            struct hda_codec *codec, hda_nid_t nid)
  76 {
  77         int type;
  78         struct hda_pcm *cpcm;
  79 
  80         list_for_each_entry(cpcm, &codec->pcm_list_head, list) {
  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 
  93 static void print_amp_caps(struct snd_info_buffer *buffer,
  94                            struct hda_codec *codec, hda_nid_t nid, int dir)
  95 {
  96         unsigned int caps;
  97         caps = param_read(codec, nid, dir == HDA_OUTPUT ?
  98                           AC_PAR_AMP_OUT_CAP : AC_PAR_AMP_IN_CAP);
  99         if (caps == -1 || caps == 0) {
 100                 snd_iprintf(buffer, "N/A\n");
 101                 return;
 102         }
 103         snd_iprintf(buffer, "ofs=0x%02x, nsteps=0x%02x, stepsize=0x%02x, "
 104                     "mute=%x\n",
 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 
 111 /* is this a stereo widget or a stereo-to-mono mix? */
 112 static 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 
 133 static void print_amp_vals(struct snd_info_buffer *buffer,
 134                            struct hda_codec *codec, hda_nid_t nid,
 135                            int dir, unsigned int wcaps, int indices)
 136 {
 137         unsigned int val;
 138         bool stereo;
 139         int i;
 140 
 141         stereo = is_stereo_amps(codec, nid, dir, wcaps, indices);
 142 
 143         dir = dir == HDA_OUTPUT ? AC_AMP_GET_OUTPUT : AC_AMP_GET_INPUT;
 144         for (i = 0; i < indices; i++) {
 145                 snd_iprintf(buffer, " [");
 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);
 150                 if (stereo) {
 151                         val = snd_hda_codec_read(codec, nid, 0,
 152                                                  AC_VERB_GET_AMP_GAIN_MUTE,
 153                                                  AC_AMP_GET_RIGHT | dir | i);
 154                         snd_iprintf(buffer, " 0x%02x", val);
 155                 }
 156                 snd_iprintf(buffer, "]");
 157         }
 158         snd_iprintf(buffer, "\n");
 159 }
 160 
 161 static void print_pcm_rates(struct snd_info_buffer *buffer, unsigned int pcm)
 162 {
 163         static unsigned int rates[] = {
 164                 8000, 11025, 16000, 22050, 32000, 44100, 48000, 88200,
 165                 96000, 176400, 192000, 384000
 166         };
 167         int i;
 168 
 169         pcm &= AC_SUPPCM_RATES;
 170         snd_iprintf(buffer, "    rates [0x%x]:", pcm);
 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");
 175 }
 176 
 177 static void print_pcm_bits(struct snd_info_buffer *buffer, unsigned int pcm)
 178 {
 179         char buf[SND_PRINT_BITS_ADVISED_BUFSIZE];
 180 
 181         snd_iprintf(buffer, "    bits [0x%x]:", (pcm >> 16) & 0xff);
 182         snd_print_pcm_bits(pcm, buf, sizeof(buf));
 183         snd_iprintf(buffer, "%s\n", buf);
 184 }
 185 
 186 static 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 
 199 static void print_pcm_caps(struct snd_info_buffer *buffer,
 200                            struct hda_codec *codec, hda_nid_t nid)
 201 {
 202         unsigned int pcm = param_read(codec, nid, AC_PAR_PCM);
 203         unsigned int stream = param_read(codec, nid, AC_PAR_STREAM);
 204         if (pcm == -1 || stream == -1) {
 205                 snd_iprintf(buffer, "N/A\n");
 206                 return;
 207         }
 208         print_pcm_rates(buffer, pcm);
 209         print_pcm_bits(buffer, pcm);
 210         print_pcm_formats(buffer, stream);
 211 }
 212 
 213 static const char *get_jack_connection(u32 cfg)
 214 {
 215         static const char * const names[16] = {
 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 
 228 static const char *get_jack_color(u32 cfg)
 229 {
 230         static const char * const names[16] = {
 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 
 243 /*
 244  * Parse the pin default config value and returns the string of the
 245  * jack location, e.g. "Rear", "Front", etc.
 246  */
 247 static const char *get_jack_location(u32 cfg)
 248 {
 249         static const char * const bases[7] = {
 250                 "N/A", "Rear", "Front", "Left", "Right", "Top", "Bottom",
 251         };
 252         static const unsigned char specials_idx[] = {
 253                 0x07, 0x08,
 254                 0x17, 0x18, 0x19,
 255                 0x37, 0x38
 256         };
 257         static const char * const specials[] = {
 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  */
 278 static const char *get_jack_connectivity(u32 cfg)
 279 {
 280         static const char * const jack_locations[4] = {
 281                 "Ext", "Int", "Sep", "Oth"
 282         };
 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  */
 291 static const char *get_jack_type(u32 cfg)
 292 {
 293         static const char * const jack_types[16] = {
 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 
 304 static void print_pin_caps(struct snd_info_buffer *buffer,
 305                            struct hda_codec *codec, hda_nid_t nid,
 306                            int *supports_vref)
 307 {
 308         static const char * const jack_conns[4] = {
 309                 "Jack", "N/A", "Fixed", "Both"
 310         };
 311         unsigned int caps, val;
 312 
 313         caps = param_read(codec, nid, AC_PAR_PIN_CAP);
 314         snd_iprintf(buffer, "  Pincap 0x%08x:", caps);
 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");
 321         if (caps & AC_PINCAP_EAPD)
 322                 snd_iprintf(buffer, " EAPD");
 323         if (caps & AC_PINCAP_PRES_DETECT)
 324                 snd_iprintf(buffer, " Detect");
 325         if (caps & AC_PINCAP_BALANCE)
 326                 snd_iprintf(buffer, " Balanced");
 327         if (caps & AC_PINCAP_HDMI) {
 328                 /* Realtek uses this bit as a different meaning */
 329                 if ((codec->core.vendor_id >> 16) == 0x10ec)
 330                         snd_iprintf(buffer, " R/L");
 331                 else {
 332                         if (caps & AC_PINCAP_HBR)
 333                                 snd_iprintf(buffer, " HBR");
 334                         snd_iprintf(buffer, " HDMI");
 335                 }
 336         }
 337         if (caps & AC_PINCAP_DP)
 338                 snd_iprintf(buffer, " DP");
 339         if (caps & AC_PINCAP_TRIG_REQ)
 340                 snd_iprintf(buffer, " Trigger");
 341         if (caps & AC_PINCAP_IMP_SENSE)
 342                 snd_iprintf(buffer, " ImpSense");
 343         snd_iprintf(buffer, "\n");
 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         }
 374         caps = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONFIG_DEFAULT, 0);
 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],
 377                     get_jack_type(caps),
 378                     get_jack_connectivity(caps),
 379                     get_jack_location(caps));
 380         snd_iprintf(buffer, "    Conn = %s, Color = %s\n",
 381                     get_jack_connection(caps),
 382                     get_jack_color(caps));
 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");
 397         }
 398 }
 399 
 400 static 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 
 438 static void print_vol_knob(struct snd_info_buffer *buffer,
 439                            struct hda_codec *codec, hda_nid_t nid)
 440 {
 441         unsigned int cap = param_read(codec, nid, AC_PAR_VOL_KNB_CAP);
 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 
 450 static void print_audio_io(struct snd_info_buffer *buffer,
 451                            struct hda_codec *codec, hda_nid_t nid,
 452                            unsigned int wid_type)
 453 {
 454         int conv = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONV, 0);
 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 
 468 static 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);
 473         unsigned char digi2 = digi1 >> 8;
 474         unsigned char digi3 = digi1 >> 16;
 475 
 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)
 486                 snd_iprintf(buffer, " Non-Copyright");
 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");
 493         if (digi3 & AC_DIG3_KAE)
 494                 snd_iprintf(buffer, " KAE");
 495         snd_iprintf(buffer, "\n");
 496         snd_iprintf(buffer, "  Digital category: 0x%x\n",
 497                     digi2 & AC_DIG2_CC);
 498         snd_iprintf(buffer, "  IEC Coding Type: 0x%x\n",
 499                         digi3 & AC_DIG3_ICT);
 500 }
 501 
 502 static const char *get_pwr_state(u32 state)
 503 {
 504         static const char * const buf[] = {
 505                 "D0", "D1", "D2", "D3", "D3cold"
 506         };
 507         if (state < ARRAY_SIZE(buf))
 508                 return buf[state];
 509         return "UNKNOWN";
 510 }
 511 
 512 static void print_power_state(struct snd_info_buffer *buffer,
 513                               struct hda_codec *codec, hda_nid_t nid)
 514 {
 515         static const char * const names[] = {
 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 
 526         int sup = param_read(codec, nid, AC_PAR_POWER_STATE);
 527         int pwr = snd_hda_codec_read(codec, nid, 0,
 528                                      AC_VERB_GET_POWER_STATE, 0);
 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         }
 539 
 540         snd_iprintf(buffer, "  Power: setting=%s, actual=%s",
 541                     get_pwr_state(pwr & AC_PWRST_SETTING),
 542                     get_pwr_state((pwr & AC_PWRST_ACTUAL) >>
 543                                   AC_PWRST_ACTUAL_SHIFT));
 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");
 551 }
 552 
 553 static 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 
 564 static 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 
 573 static void print_proc_caps(struct snd_info_buffer *buffer,
 574                             struct hda_codec *codec, hda_nid_t nid)
 575 {
 576         unsigned int i, ncoeff, oldindex;
 577         unsigned int proc_caps = param_read(codec, nid, AC_PAR_PROC_CAP);
 578         ncoeff = (proc_caps & AC_PCAP_NUM_COEF) >> AC_PCAP_NUM_COEF_SHIFT;
 579         snd_iprintf(buffer, "  Processing caps: benign=%d, ncoeff=%d\n",
 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);
 596 }
 597 
 598 static 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;
 604         const hda_nid_t *list;
 605         int cache_len;
 606 
 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)
 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         }
 623 
 624         /* Get Cache connections info */
 625         cache_len = snd_hda_get_conn_list(codec, nid, &list);
 626         if (cache_len >= 0 && (cache_len != conn_len ||
 627                               memcmp(list, conn, conn_len) != 0)) {
 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         }
 636 }
 637 
 638 static void print_gpio(struct snd_info_buffer *buffer,
 639                        struct hda_codec *codec, hda_nid_t nid)
 640 {
 641         unsigned int gpio =
 642                 param_read(codec, codec->core.afg, AC_PAR_GPIO_CAP);
 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;
 653         if (!max || max > 8)
 654                 return;
 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, "
 670                             "sticky=%d, data=%d, unsol=%d\n", i,
 671                             (enable & (1<<i)) ? 1 : 0,
 672                             (direction & (1<<i)) ? 1 : 0,
 673                             (wake & (1<<i)) ? 1 : 0,
 674                             (sticky & (1<<i)) ? 1 : 0,
 675                             (data & (1<<i)) ? 1 : 0,
 676                             (unsol & (1<<i)) ? 1 : 0);
 677         /* FIXME: add GPO and GPI pin information */
 678         print_nid_array(buffer, codec, nid, &codec->mixers);
 679         print_nid_array(buffer, codec, nid, &codec->nids);
 680 }
 681 
 682 static void print_device_list(struct snd_info_buffer *buffer,
 683                             struct hda_codec *codec, hda_nid_t nid)
 684 {
 685         int i, curr = -1;
 686         u8 dev_list[AC_MAX_DEV_LIST_LEN];
 687         int devlist_len;
 688 
 689         devlist_len = snd_hda_get_devices(codec, nid, dev_list,
 690                                         AC_MAX_DEV_LIST_LEN);
 691         snd_iprintf(buffer, "  Devices: %d\n", devlist_len);
 692         if (devlist_len <= 0)
 693                 return;
 694 
 695         curr = snd_hda_codec_read(codec, nid, 0,
 696                                 AC_VERB_GET_DEVICE_SEL, 0);
 697 
 698         for (i = 0; i < devlist_len; i++) {
 699                 if (i == curr)
 700                         snd_iprintf(buffer, "    *");
 701                 else
 702                         snd_iprintf(buffer, "     ");
 703 
 704                 snd_iprintf(buffer,
 705                         "Dev %02d: PD = %d, ELDV = %d, IA = %d\n", i,
 706                         !!(dev_list[i] & AC_DE_PD),
 707                         !!(dev_list[i] & AC_DE_ELDV),
 708                         !!(dev_list[i] & AC_DE_IA));
 709         }
 710 }
 711 
 712 static void print_codec_core_info(struct hdac_device *codec,
 713                                   struct snd_info_buffer *buffer)
 714 {
 715         snd_iprintf(buffer, "Codec: ");
 716         if (codec->vendor_name && codec->chip_name)
 717                 snd_iprintf(buffer, "%s %s\n",
 718                             codec->vendor_name, codec->chip_name);
 719         else
 720                 snd_iprintf(buffer, "Not Set\n");
 721         snd_iprintf(buffer, "Address: %d\n", codec->addr);
 722         if (codec->afg)
 723                 snd_iprintf(buffer, "AFG Function Id: 0x%x (unsol %u)\n",
 724                         codec->afg_function_id, codec->afg_unsol);
 725         if (codec->mfg)
 726                 snd_iprintf(buffer, "MFG Function Id: 0x%x (unsol %u)\n",
 727                         codec->mfg_function_id, codec->mfg_unsol);
 728         snd_iprintf(buffer, "Vendor Id: 0x%08x\n", codec->vendor_id);
 729         snd_iprintf(buffer, "Subsystem Id: 0x%08x\n", codec->subsystem_id);
 730         snd_iprintf(buffer, "Revision Id: 0x%x\n", codec->revision_id);
 731 
 732         if (codec->mfg)
 733                 snd_iprintf(buffer, "Modem Function Group: 0x%x\n", codec->mfg);
 734         else
 735                 snd_iprintf(buffer, "No Modem Function Group found\n");
 736 }
 737 
 738 static void print_codec_info(struct snd_info_entry *entry,
 739                              struct snd_info_buffer *buffer)
 740 {
 741         struct hda_codec *codec = entry->private_data;
 742         hda_nid_t nid, fg;
 743         int i, nodes;
 744 
 745         print_codec_core_info(&codec->core, buffer);
 746         fg = codec->core.afg;
 747         if (!fg)
 748                 return;
 749         snd_hda_power_up(codec);
 750         snd_iprintf(buffer, "Default PCM:\n");
 751         print_pcm_caps(buffer, codec, fg);
 752         snd_iprintf(buffer, "Default Amp-In caps: ");
 753         print_amp_caps(buffer, codec, fg, HDA_INPUT);
 754         snd_iprintf(buffer, "Default Amp-Out caps: ");
 755         print_amp_caps(buffer, codec, fg, HDA_OUTPUT);
 756         snd_iprintf(buffer, "State of AFG node 0x%02x:\n", fg);
 757         print_power_state(buffer, codec, fg);
 758 
 759         nodes = snd_hda_get_sub_nodes(codec, fg, &nid);
 760         if (! nid || nodes < 0) {
 761                 snd_iprintf(buffer, "Invalid AFG subtree\n");
 762                 snd_hda_power_down(codec);
 763                 return;
 764         }
 765 
 766         print_gpio(buffer, codec, fg);
 767         if (codec->proc_widget_hook)
 768                 codec->proc_widget_hook(buffer, codec, fg);
 769 
 770         for (i = 0; i < nodes; i++, nid++) {
 771                 unsigned int wid_caps =
 772                         param_read(codec, nid, AC_PAR_AUDIO_WIDGET_CAP);
 773                 unsigned int wid_type = get_wcaps_type(wid_caps);
 774                 hda_nid_t *conn = NULL;
 775                 int conn_len = 0;
 776 
 777                 snd_iprintf(buffer, "Node 0x%02x [%s] wcaps 0x%x:", nid,
 778                             get_wid_type_name(wid_type), wid_caps);
 779                 if (wid_caps & AC_WCAP_STEREO) {
 780                         unsigned int chans = get_wcaps_channels(wid_caps);
 781                         if (chans == 2)
 782                                 snd_iprintf(buffer, " Stereo");
 783                         else
 784                                 snd_iprintf(buffer, " %d-Channels", chans);
 785                 } else
 786                         snd_iprintf(buffer, " Mono");
 787                 if (wid_caps & AC_WCAP_DIGITAL)
 788                         snd_iprintf(buffer, " Digital");
 789                 if (wid_caps & AC_WCAP_IN_AMP)
 790                         snd_iprintf(buffer, " Amp-In");
 791                 if (wid_caps & AC_WCAP_OUT_AMP)
 792                         snd_iprintf(buffer, " Amp-Out");
 793                 if (wid_caps & AC_WCAP_STRIPE)
 794                         snd_iprintf(buffer, " Stripe");
 795                 if (wid_caps & AC_WCAP_LR_SWAP)
 796                         snd_iprintf(buffer, " R/L");
 797                 if (wid_caps & AC_WCAP_CP_CAPS)
 798                         snd_iprintf(buffer, " CP");
 799                 snd_iprintf(buffer, "\n");
 800 
 801                 print_nid_array(buffer, codec, nid, &codec->mixers);
 802                 print_nid_array(buffer, codec, nid, &codec->nids);
 803                 print_nid_pcms(buffer, codec, nid);
 804 
 805                 /* volume knob is a special widget that always have connection
 806                  * list
 807                  */
 808                 if (wid_type == AC_WID_VOL_KNB)
 809                         wid_caps |= AC_WCAP_CONN_LIST;
 810 
 811                 if (wid_caps & AC_WCAP_CONN_LIST) {
 812                         conn_len = snd_hda_get_num_raw_conns(codec, nid);
 813                         if (conn_len > 0) {
 814                                 conn = kmalloc_array(conn_len,
 815                                                      sizeof(hda_nid_t),
 816                                                      GFP_KERNEL);
 817                                 if (!conn)
 818                                         return;
 819                                 if (snd_hda_get_raw_connections(codec, nid, conn,
 820                                                                 conn_len) < 0)
 821                                         conn_len = 0;
 822                         }
 823                 }
 824 
 825                 if (wid_caps & AC_WCAP_IN_AMP) {
 826                         snd_iprintf(buffer, "  Amp-In caps: ");
 827                         print_amp_caps(buffer, codec, nid, HDA_INPUT);
 828                         snd_iprintf(buffer, "  Amp-In vals: ");
 829                         if (wid_type == AC_WID_PIN ||
 830                             (codec->single_adc_amp &&
 831                              wid_type == AC_WID_AUD_IN))
 832                                 print_amp_vals(buffer, codec, nid, HDA_INPUT,
 833                                                wid_caps, 1);
 834                         else
 835                                 print_amp_vals(buffer, codec, nid, HDA_INPUT,
 836                                                wid_caps, conn_len);
 837                 }
 838                 if (wid_caps & AC_WCAP_OUT_AMP) {
 839                         snd_iprintf(buffer, "  Amp-Out caps: ");
 840                         print_amp_caps(buffer, codec, nid, HDA_OUTPUT);
 841                         snd_iprintf(buffer, "  Amp-Out vals: ");
 842                         if (wid_type == AC_WID_PIN &&
 843                             codec->pin_amp_workaround)
 844                                 print_amp_vals(buffer, codec, nid, HDA_OUTPUT,
 845                                                wid_caps, conn_len);
 846                         else
 847                                 print_amp_vals(buffer, codec, nid, HDA_OUTPUT,
 848                                                wid_caps, 1);
 849                 }
 850 
 851                 switch (wid_type) {
 852                 case AC_WID_PIN: {
 853                         int supports_vref;
 854                         print_pin_caps(buffer, codec, nid, &supports_vref);
 855                         print_pin_ctls(buffer, codec, nid, supports_vref);
 856                         break;
 857                 }
 858                 case AC_WID_VOL_KNB:
 859                         print_vol_knob(buffer, codec, nid);
 860                         break;
 861                 case AC_WID_AUD_OUT:
 862                 case AC_WID_AUD_IN:
 863                         print_audio_io(buffer, codec, nid, wid_type);
 864                         if (wid_caps & AC_WCAP_DIGITAL)
 865                                 print_digital_conv(buffer, codec, nid);
 866                         if (wid_caps & AC_WCAP_FORMAT_OVRD) {
 867                                 snd_iprintf(buffer, "  PCM:\n");
 868                                 print_pcm_caps(buffer, codec, nid);
 869                         }
 870                         break;
 871                 }
 872 
 873                 if (wid_caps & AC_WCAP_UNSOL_CAP)
 874                         print_unsol_cap(buffer, codec, nid);
 875 
 876                 if (wid_caps & AC_WCAP_POWER)
 877                         print_power_state(buffer, codec, nid);
 878 
 879                 if (wid_caps & AC_WCAP_DELAY)
 880                         snd_iprintf(buffer, "  Delay: %d samples\n",
 881                                     (wid_caps & AC_WCAP_DELAY) >>
 882                                     AC_WCAP_DELAY_SHIFT);
 883 
 884                 if (wid_type == AC_WID_PIN && codec->dp_mst)
 885                         print_device_list(buffer, codec, nid);
 886 
 887                 if (wid_caps & AC_WCAP_CONN_LIST)
 888                         print_conn_list(buffer, codec, nid, wid_type,
 889                                         conn, conn_len);
 890 
 891                 if (wid_caps & AC_WCAP_PROC_WID)
 892                         print_proc_caps(buffer, codec, nid);
 893 
 894                 if (codec->proc_widget_hook)
 895                         codec->proc_widget_hook(buffer, codec, nid);
 896 
 897                 kfree(conn);
 898         }
 899         snd_hda_power_down(codec);
 900 }
 901 
 902 /*
 903  * create a proc read
 904  */
 905 int snd_hda_codec_proc_new(struct hda_codec *codec)
 906 {
 907         char name[32];
 908 
 909         snprintf(name, sizeof(name), "codec#%d", codec->core.addr);
 910         return snd_card_ro_proc_new(codec->card, name, codec, print_codec_info);
 911 }
 912 

/* [<][>][^][v][top][bottom][index][help] */