linux/sound/pci/hda/hda_proc.c
<<
>>
Prefs
   1/*
   2 * Universal Interface for Intel High Definition Audio Codec
   3 * 
   4 * Generic proc interface
   5 *
   6 * Copyright (c) 2004 Takashi Iwai <tiwai@suse.de>
   7 *
   8 *
   9 *  This driver is free software; you can redistribute it and/or modify
  10 *  it under the terms of the GNU General Public License as published by
  11 *  the Free Software Foundation; either version 2 of the License, or
  12 *  (at your option) any later version.
  13 *
  14 *  This driver is distributed in the hope that it will be useful,
  15 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  16 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17 *  GNU General Public License for more details.
  18 *
  19 *  You should have received a copy of the GNU General Public License
  20 *  along with this program; if not, write to the Free Software
  21 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  22 */
  23
  24#include <linux/init.h>
  25#include <sound/core.h>
  26#include "hda_codec.h"
  27#include "hda_local.h"
  28
  29static const char *get_wid_type_name(unsigned int wid_value)
  30{
  31        static char *names[16] = {
  32                [AC_WID_AUD_OUT] = "Audio Output",
  33                [AC_WID_AUD_IN] = "Audio Input",
  34                [AC_WID_AUD_MIX] = "Audio Mixer",
  35                [AC_WID_AUD_SEL] = "Audio Selector",
  36                [AC_WID_PIN] = "Pin Complex",
  37                [AC_WID_POWER] = "Power Widget",
  38                [AC_WID_VOL_KNB] = "Volume Knob Widget",
  39                [AC_WID_BEEP] = "Beep Generator Widget",
  40                [AC_WID_VENDOR] = "Vendor Defined Widget",
  41        };
  42        if (wid_value == -1)
  43                return "UNKNOWN Widget";
  44        wid_value &= 0xf;
  45        if (names[wid_value])
  46                return names[wid_value];
  47        else
  48                return "UNKNOWN Widget";
  49}
  50
  51static void print_amp_caps(struct snd_info_buffer *buffer,
  52                           struct hda_codec *codec, hda_nid_t nid, int dir)
  53{
  54        unsigned int caps;
  55        caps = snd_hda_param_read(codec, nid,
  56                                  dir == HDA_OUTPUT ?
  57                                    AC_PAR_AMP_OUT_CAP : AC_PAR_AMP_IN_CAP);
  58        if (caps == -1 || caps == 0) {
  59                snd_iprintf(buffer, "N/A\n");
  60                return;
  61        }
  62        snd_iprintf(buffer, "ofs=0x%02x, nsteps=0x%02x, stepsize=0x%02x, "
  63                    "mute=%x\n",
  64                    caps & AC_AMPCAP_OFFSET,
  65                    (caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT,
  66                    (caps & AC_AMPCAP_STEP_SIZE) >> AC_AMPCAP_STEP_SIZE_SHIFT,
  67                    (caps & AC_AMPCAP_MUTE) >> AC_AMPCAP_MUTE_SHIFT);
  68}
  69
  70static void print_amp_vals(struct snd_info_buffer *buffer,
  71                           struct hda_codec *codec, hda_nid_t nid,
  72                           int dir, int stereo, int indices)
  73{
  74        unsigned int val;
  75        int i;
  76
  77        dir = dir == HDA_OUTPUT ? AC_AMP_GET_OUTPUT : AC_AMP_GET_INPUT;
  78        for (i = 0; i < indices; i++) {
  79                snd_iprintf(buffer, " [");
  80                if (stereo) {
  81                        val = snd_hda_codec_read(codec, nid, 0,
  82                                                 AC_VERB_GET_AMP_GAIN_MUTE,
  83                                                 AC_AMP_GET_LEFT | dir | i);
  84                        snd_iprintf(buffer, "0x%02x ", val);
  85                }
  86                val = snd_hda_codec_read(codec, nid, 0,
  87                                         AC_VERB_GET_AMP_GAIN_MUTE,
  88                                         AC_AMP_GET_RIGHT | dir | i);
  89                snd_iprintf(buffer, "0x%02x]", val);
  90        }
  91        snd_iprintf(buffer, "\n");
  92}
  93
  94static void print_pcm_rates(struct snd_info_buffer *buffer, unsigned int pcm)
  95{
  96        char buf[SND_PRINT_RATES_ADVISED_BUFSIZE];
  97
  98        pcm &= AC_SUPPCM_RATES;
  99        snd_iprintf(buffer, "    rates [0x%x]:", pcm);
 100        snd_print_pcm_rates(pcm, buf, sizeof(buf));
 101        snd_iprintf(buffer, "%s\n", buf);
 102}
 103
 104static void print_pcm_bits(struct snd_info_buffer *buffer, unsigned int pcm)
 105{
 106        char buf[SND_PRINT_BITS_ADVISED_BUFSIZE];
 107
 108        snd_iprintf(buffer, "    bits [0x%x]:", (pcm >> 16) & 0xff);
 109        snd_print_pcm_bits(pcm, buf, sizeof(buf));
 110        snd_iprintf(buffer, "%s\n", buf);
 111}
 112
 113static void print_pcm_formats(struct snd_info_buffer *buffer,
 114                              unsigned int streams)
 115{
 116        snd_iprintf(buffer, "    formats [0x%x]:", streams & 0xf);
 117        if (streams & AC_SUPFMT_PCM)
 118                snd_iprintf(buffer, " PCM");
 119        if (streams & AC_SUPFMT_FLOAT32)
 120                snd_iprintf(buffer, " FLOAT");
 121        if (streams & AC_SUPFMT_AC3)
 122                snd_iprintf(buffer, " AC3");
 123        snd_iprintf(buffer, "\n");
 124}
 125
 126static void print_pcm_caps(struct snd_info_buffer *buffer,
 127                           struct hda_codec *codec, hda_nid_t nid)
 128{
 129        unsigned int pcm = snd_hda_param_read(codec, nid, AC_PAR_PCM);
 130        unsigned int stream = snd_hda_param_read(codec, nid, AC_PAR_STREAM);
 131        if (pcm == -1 || stream == -1) {
 132                snd_iprintf(buffer, "N/A\n");
 133                return;
 134        }
 135        print_pcm_rates(buffer, pcm);
 136        print_pcm_bits(buffer, pcm);
 137        print_pcm_formats(buffer, stream);
 138}
 139
 140static const char *get_jack_connection(u32 cfg)
 141{
 142        static char *names[16] = {
 143                "Unknown", "1/8", "1/4", "ATAPI",
 144                "RCA", "Optical","Digital", "Analog",
 145                "DIN", "XLR", "RJ11", "Comb",
 146                NULL, NULL, NULL, "Other"
 147        };
 148        cfg = (cfg & AC_DEFCFG_CONN_TYPE) >> AC_DEFCFG_CONN_TYPE_SHIFT;
 149        if (names[cfg])
 150                return names[cfg];
 151        else
 152                return "UNKNOWN";
 153}
 154
 155static const char *get_jack_color(u32 cfg)
 156{
 157        static char *names[16] = {
 158                "Unknown", "Black", "Grey", "Blue",
 159                "Green", "Red", "Orange", "Yellow",
 160                "Purple", "Pink", NULL, NULL,
 161                NULL, NULL, "White", "Other",
 162        };
 163        cfg = (cfg & AC_DEFCFG_COLOR) >> AC_DEFCFG_COLOR_SHIFT;
 164        if (names[cfg])
 165                return names[cfg];
 166        else
 167                return "UNKNOWN";
 168}
 169
 170static void print_pin_caps(struct snd_info_buffer *buffer,
 171                           struct hda_codec *codec, hda_nid_t nid,
 172                           int *supports_vref)
 173{
 174        static char *jack_conns[4] = { "Jack", "N/A", "Fixed", "Both" };
 175        unsigned int caps, val;
 176
 177        caps = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP);
 178        snd_iprintf(buffer, "  Pincap 0x%08x:", caps);
 179        if (caps & AC_PINCAP_IN)
 180                snd_iprintf(buffer, " IN");
 181        if (caps & AC_PINCAP_OUT)
 182                snd_iprintf(buffer, " OUT");
 183        if (caps & AC_PINCAP_HP_DRV)
 184                snd_iprintf(buffer, " HP");
 185        if (caps & AC_PINCAP_EAPD)
 186                snd_iprintf(buffer, " EAPD");
 187        if (caps & AC_PINCAP_PRES_DETECT)
 188                snd_iprintf(buffer, " Detect");
 189        if (caps & AC_PINCAP_BALANCE)
 190                snd_iprintf(buffer, " Balanced");
 191        if (caps & AC_PINCAP_HDMI) {
 192                /* Realtek uses this bit as a different meaning */
 193                if ((codec->vendor_id >> 16) == 0x10ec)
 194                        snd_iprintf(buffer, " R/L");
 195                else
 196                        snd_iprintf(buffer, " HDMI");
 197        }
 198        if (caps & AC_PINCAP_TRIG_REQ)
 199                snd_iprintf(buffer, " Trigger");
 200        if (caps & AC_PINCAP_IMP_SENSE)
 201                snd_iprintf(buffer, " ImpSense");
 202        snd_iprintf(buffer, "\n");
 203        if (caps & AC_PINCAP_VREF) {
 204                unsigned int vref =
 205                        (caps & AC_PINCAP_VREF) >> AC_PINCAP_VREF_SHIFT;
 206                snd_iprintf(buffer, "    Vref caps:");
 207                if (vref & AC_PINCAP_VREF_HIZ)
 208                        snd_iprintf(buffer, " HIZ");
 209                if (vref & AC_PINCAP_VREF_50)
 210                        snd_iprintf(buffer, " 50");
 211                if (vref & AC_PINCAP_VREF_GRD)
 212                        snd_iprintf(buffer, " GRD");
 213                if (vref & AC_PINCAP_VREF_80)
 214                        snd_iprintf(buffer, " 80");
 215                if (vref & AC_PINCAP_VREF_100)
 216                        snd_iprintf(buffer, " 100");
 217                snd_iprintf(buffer, "\n");
 218                *supports_vref = 1;
 219        } else
 220                *supports_vref = 0;
 221        if (caps & AC_PINCAP_EAPD) {
 222                val = snd_hda_codec_read(codec, nid, 0,
 223                                         AC_VERB_GET_EAPD_BTLENABLE, 0);
 224                snd_iprintf(buffer, "  EAPD 0x%x:", val);
 225                if (val & AC_EAPDBTL_BALANCED)
 226                        snd_iprintf(buffer, " BALANCED");
 227                if (val & AC_EAPDBTL_EAPD)
 228                        snd_iprintf(buffer, " EAPD");
 229                if (val & AC_EAPDBTL_LR_SWAP)
 230                        snd_iprintf(buffer, " R/L");
 231                snd_iprintf(buffer, "\n");
 232        }
 233        caps = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONFIG_DEFAULT, 0);
 234        snd_iprintf(buffer, "  Pin Default 0x%08x: [%s] %s at %s %s\n", caps,
 235                    jack_conns[(caps & AC_DEFCFG_PORT_CONN) >> AC_DEFCFG_PORT_CONN_SHIFT],
 236                    snd_hda_get_jack_type(caps),
 237                    snd_hda_get_jack_connectivity(caps),
 238                    snd_hda_get_jack_location(caps));
 239        snd_iprintf(buffer, "    Conn = %s, Color = %s\n",
 240                    get_jack_connection(caps),
 241                    get_jack_color(caps));
 242        /* Default association and sequence values refer to default grouping
 243         * of pin complexes and their sequence within the group. This is used
 244         * for priority and resource allocation.
 245         */
 246        snd_iprintf(buffer, "    DefAssociation = 0x%x, Sequence = 0x%x\n",
 247                    (caps & AC_DEFCFG_DEF_ASSOC) >> AC_DEFCFG_ASSOC_SHIFT,
 248                    caps & AC_DEFCFG_SEQUENCE);
 249        if (((caps & AC_DEFCFG_MISC) >> AC_DEFCFG_MISC_SHIFT) &
 250            AC_DEFCFG_MISC_NO_PRESENCE) {
 251                /* Miscellaneous bit indicates external hardware does not
 252                 * support presence detection even if the pin complex
 253                 * indicates it is supported.
 254                 */
 255                snd_iprintf(buffer, "    Misc = NO_PRESENCE\n");
 256        }
 257}
 258
 259static void print_pin_ctls(struct snd_info_buffer *buffer,
 260                           struct hda_codec *codec, hda_nid_t nid,
 261                           int supports_vref)
 262{
 263        unsigned int pinctls;
 264
 265        pinctls = snd_hda_codec_read(codec, nid, 0,
 266                                     AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
 267        snd_iprintf(buffer, "  Pin-ctls: 0x%02x:", pinctls);
 268        if (pinctls & AC_PINCTL_IN_EN)
 269                snd_iprintf(buffer, " IN");
 270        if (pinctls & AC_PINCTL_OUT_EN)
 271                snd_iprintf(buffer, " OUT");
 272        if (pinctls & AC_PINCTL_HP_EN)
 273                snd_iprintf(buffer, " HP");
 274        if (supports_vref) {
 275                int vref = pinctls & AC_PINCTL_VREFEN;
 276                switch (vref) {
 277                case AC_PINCTL_VREF_HIZ:
 278                        snd_iprintf(buffer, " VREF_HIZ");
 279                        break;
 280                case AC_PINCTL_VREF_50:
 281                        snd_iprintf(buffer, " VREF_50");
 282                        break;
 283                case AC_PINCTL_VREF_GRD:
 284                        snd_iprintf(buffer, " VREF_GRD");
 285                        break;
 286                case AC_PINCTL_VREF_80:
 287                        snd_iprintf(buffer, " VREF_80");
 288                        break;
 289                case AC_PINCTL_VREF_100:
 290                        snd_iprintf(buffer, " VREF_100");
 291                        break;
 292                }
 293        }
 294        snd_iprintf(buffer, "\n");
 295}
 296
 297static void print_vol_knob(struct snd_info_buffer *buffer,
 298                           struct hda_codec *codec, hda_nid_t nid)
 299{
 300        unsigned int cap = snd_hda_param_read(codec, nid,
 301                                              AC_PAR_VOL_KNB_CAP);
 302        snd_iprintf(buffer, "  Volume-Knob: delta=%d, steps=%d, ",
 303                    (cap >> 7) & 1, cap & 0x7f);
 304        cap = snd_hda_codec_read(codec, nid, 0,
 305                                 AC_VERB_GET_VOLUME_KNOB_CONTROL, 0);
 306        snd_iprintf(buffer, "direct=%d, val=%d\n",
 307                    (cap >> 7) & 1, cap & 0x7f);
 308}
 309
 310static void print_audio_io(struct snd_info_buffer *buffer,
 311                           struct hda_codec *codec, hda_nid_t nid,
 312                           unsigned int wid_type)
 313{
 314        int conv = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONV, 0);
 315        snd_iprintf(buffer,
 316                    "  Converter: stream=%d, channel=%d\n",
 317                    (conv & AC_CONV_STREAM) >> AC_CONV_STREAM_SHIFT,
 318                    conv & AC_CONV_CHANNEL);
 319
 320        if (wid_type == AC_WID_AUD_IN && (conv & AC_CONV_CHANNEL) == 0) {
 321                int sdi = snd_hda_codec_read(codec, nid, 0,
 322                                             AC_VERB_GET_SDI_SELECT, 0);
 323                snd_iprintf(buffer, "  SDI-Select: %d\n",
 324                            sdi & AC_SDI_SELECT);
 325        }
 326}
 327
 328static void print_digital_conv(struct snd_info_buffer *buffer,
 329                               struct hda_codec *codec, hda_nid_t nid)
 330{
 331        unsigned int digi1 = snd_hda_codec_read(codec, nid, 0,
 332                                                AC_VERB_GET_DIGI_CONVERT_1, 0);
 333        snd_iprintf(buffer, "  Digital:");
 334        if (digi1 & AC_DIG1_ENABLE)
 335                snd_iprintf(buffer, " Enabled");
 336        if (digi1 & AC_DIG1_V)
 337                snd_iprintf(buffer, " Validity");
 338        if (digi1 & AC_DIG1_VCFG)
 339                snd_iprintf(buffer, " ValidityCfg");
 340        if (digi1 & AC_DIG1_EMPHASIS)
 341                snd_iprintf(buffer, " Preemphasis");
 342        if (digi1 & AC_DIG1_COPYRIGHT)
 343                snd_iprintf(buffer, " Copyright");
 344        if (digi1 & AC_DIG1_NONAUDIO)
 345                snd_iprintf(buffer, " Non-Audio");
 346        if (digi1 & AC_DIG1_PROFESSIONAL)
 347                snd_iprintf(buffer, " Pro");
 348        if (digi1 & AC_DIG1_LEVEL)
 349                snd_iprintf(buffer, " GenLevel");
 350        snd_iprintf(buffer, "\n");
 351        snd_iprintf(buffer, "  Digital category: 0x%x\n",
 352                    (digi1 >> 8) & AC_DIG2_CC);
 353}
 354
 355static const char *get_pwr_state(u32 state)
 356{
 357        static const char *buf[4] = {
 358                "D0", "D1", "D2", "D3"
 359        };
 360        if (state < 4)
 361                return buf[state];
 362        return "UNKNOWN";
 363}
 364
 365static void print_power_state(struct snd_info_buffer *buffer,
 366                              struct hda_codec *codec, hda_nid_t nid)
 367{
 368        int pwr = snd_hda_codec_read(codec, nid, 0,
 369                                     AC_VERB_GET_POWER_STATE, 0);
 370        snd_iprintf(buffer, "  Power: setting=%s, actual=%s\n",
 371                    get_pwr_state(pwr & AC_PWRST_SETTING),
 372                    get_pwr_state((pwr & AC_PWRST_ACTUAL) >>
 373                                  AC_PWRST_ACTUAL_SHIFT));
 374}
 375
 376static void print_unsol_cap(struct snd_info_buffer *buffer,
 377                              struct hda_codec *codec, hda_nid_t nid)
 378{
 379        int unsol = snd_hda_codec_read(codec, nid, 0,
 380                                       AC_VERB_GET_UNSOLICITED_RESPONSE, 0);
 381        snd_iprintf(buffer,
 382                    "  Unsolicited: tag=%02x, enabled=%d\n",
 383                    unsol & AC_UNSOL_TAG,
 384                    (unsol & AC_UNSOL_ENABLED) ? 1 : 0);
 385}
 386
 387static void print_proc_caps(struct snd_info_buffer *buffer,
 388                            struct hda_codec *codec, hda_nid_t nid)
 389{
 390        unsigned int proc_caps = snd_hda_param_read(codec, nid,
 391                                                    AC_PAR_PROC_CAP);
 392        snd_iprintf(buffer, "  Processing caps: benign=%d, ncoeff=%d\n",
 393                    proc_caps & AC_PCAP_BENIGN,
 394                    (proc_caps & AC_PCAP_NUM_COEF) >> AC_PCAP_NUM_COEF_SHIFT);
 395}
 396
 397static void print_conn_list(struct snd_info_buffer *buffer,
 398                            struct hda_codec *codec, hda_nid_t nid,
 399                            unsigned int wid_type, hda_nid_t *conn,
 400                            int conn_len)
 401{
 402        int c, curr = -1;
 403
 404        if (conn_len > 1 &&
 405            wid_type != AC_WID_AUD_MIX &&
 406            wid_type != AC_WID_VOL_KNB &&
 407            wid_type != AC_WID_POWER)
 408                curr = snd_hda_codec_read(codec, nid, 0,
 409                                          AC_VERB_GET_CONNECT_SEL, 0);
 410        snd_iprintf(buffer, "  Connection: %d\n", conn_len);
 411        if (conn_len > 0) {
 412                snd_iprintf(buffer, "    ");
 413                for (c = 0; c < conn_len; c++) {
 414                        snd_iprintf(buffer, " 0x%02x", conn[c]);
 415                        if (c == curr)
 416                                snd_iprintf(buffer, "*");
 417                }
 418                snd_iprintf(buffer, "\n");
 419        }
 420}
 421
 422static void print_gpio(struct snd_info_buffer *buffer,
 423                       struct hda_codec *codec, hda_nid_t nid)
 424{
 425        unsigned int gpio =
 426                snd_hda_param_read(codec, codec->afg, AC_PAR_GPIO_CAP);
 427        unsigned int enable, direction, wake, unsol, sticky, data;
 428        int i, max;
 429        snd_iprintf(buffer, "GPIO: io=%d, o=%d, i=%d, "
 430                    "unsolicited=%d, wake=%d\n",
 431                    gpio & AC_GPIO_IO_COUNT,
 432                    (gpio & AC_GPIO_O_COUNT) >> AC_GPIO_O_COUNT_SHIFT,
 433                    (gpio & AC_GPIO_I_COUNT) >> AC_GPIO_I_COUNT_SHIFT,
 434                    (gpio & AC_GPIO_UNSOLICITED) ? 1 : 0,
 435                    (gpio & AC_GPIO_WAKE) ? 1 : 0);
 436        max = gpio & AC_GPIO_IO_COUNT;
 437        if (!max || max > 8)
 438                return;
 439        enable = snd_hda_codec_read(codec, nid, 0,
 440                                    AC_VERB_GET_GPIO_MASK, 0);
 441        direction = snd_hda_codec_read(codec, nid, 0,
 442                                       AC_VERB_GET_GPIO_DIRECTION, 0);
 443        wake = snd_hda_codec_read(codec, nid, 0,
 444                                  AC_VERB_GET_GPIO_WAKE_MASK, 0);
 445        unsol  = snd_hda_codec_read(codec, nid, 0,
 446                                    AC_VERB_GET_GPIO_UNSOLICITED_RSP_MASK, 0);
 447        sticky = snd_hda_codec_read(codec, nid, 0,
 448                                    AC_VERB_GET_GPIO_STICKY_MASK, 0);
 449        data = snd_hda_codec_read(codec, nid, 0,
 450                                  AC_VERB_GET_GPIO_DATA, 0);
 451        for (i = 0; i < max; ++i)
 452                snd_iprintf(buffer,
 453                            "  IO[%d]: enable=%d, dir=%d, wake=%d, "
 454                            "sticky=%d, data=%d, unsol=%d\n", i,
 455                            (enable & (1<<i)) ? 1 : 0,
 456                            (direction & (1<<i)) ? 1 : 0,
 457                            (wake & (1<<i)) ? 1 : 0,
 458                            (sticky & (1<<i)) ? 1 : 0,
 459                            (data & (1<<i)) ? 1 : 0,
 460                            (unsol & (1<<i)) ? 1 : 0);
 461        /* FIXME: add GPO and GPI pin information */
 462}
 463
 464static void print_codec_info(struct snd_info_entry *entry,
 465                             struct snd_info_buffer *buffer)
 466{
 467        struct hda_codec *codec = entry->private_data;
 468        hda_nid_t nid;
 469        int i, nodes;
 470
 471        snd_iprintf(buffer, "Codec: ");
 472        if (codec->vendor_name && codec->chip_name)
 473                snd_iprintf(buffer, "%s %s\n",
 474                            codec->vendor_name, codec->chip_name);
 475        else
 476                snd_iprintf(buffer, "Not Set\n");
 477        snd_iprintf(buffer, "Address: %d\n", codec->addr);
 478        snd_iprintf(buffer, "Function Id: 0x%x\n", codec->function_id);
 479        snd_iprintf(buffer, "Vendor Id: 0x%08x\n", codec->vendor_id);
 480        snd_iprintf(buffer, "Subsystem Id: 0x%08x\n", codec->subsystem_id);
 481        snd_iprintf(buffer, "Revision Id: 0x%x\n", codec->revision_id);
 482
 483        if (codec->mfg)
 484                snd_iprintf(buffer, "Modem Function Group: 0x%x\n", codec->mfg);
 485        else
 486                snd_iprintf(buffer, "No Modem Function Group found\n");
 487
 488        if (! codec->afg)
 489                return;
 490        snd_hda_power_up(codec);
 491        snd_iprintf(buffer, "Default PCM:\n");
 492        print_pcm_caps(buffer, codec, codec->afg);
 493        snd_iprintf(buffer, "Default Amp-In caps: ");
 494        print_amp_caps(buffer, codec, codec->afg, HDA_INPUT);
 495        snd_iprintf(buffer, "Default Amp-Out caps: ");
 496        print_amp_caps(buffer, codec, codec->afg, HDA_OUTPUT);
 497
 498        nodes = snd_hda_get_sub_nodes(codec, codec->afg, &nid);
 499        if (! nid || nodes < 0) {
 500                snd_iprintf(buffer, "Invalid AFG subtree\n");
 501                snd_hda_power_down(codec);
 502                return;
 503        }
 504
 505        print_gpio(buffer, codec, codec->afg);
 506        if (codec->proc_widget_hook)
 507                codec->proc_widget_hook(buffer, codec, codec->afg);
 508
 509        for (i = 0; i < nodes; i++, nid++) {
 510                unsigned int wid_caps =
 511                        snd_hda_param_read(codec, nid,
 512                                           AC_PAR_AUDIO_WIDGET_CAP);
 513                unsigned int wid_type = get_wcaps_type(wid_caps);
 514                hda_nid_t conn[HDA_MAX_CONNECTIONS];
 515                int conn_len = 0;
 516
 517                snd_iprintf(buffer, "Node 0x%02x [%s] wcaps 0x%x:", nid,
 518                            get_wid_type_name(wid_type), wid_caps);
 519                if (wid_caps & AC_WCAP_STEREO) {
 520                        unsigned int chans = get_wcaps_channels(wid_caps);
 521                        if (chans == 2)
 522                                snd_iprintf(buffer, " Stereo");
 523                        else
 524                                snd_iprintf(buffer, " %d-Channels", chans);
 525                } else
 526                        snd_iprintf(buffer, " Mono");
 527                if (wid_caps & AC_WCAP_DIGITAL)
 528                        snd_iprintf(buffer, " Digital");
 529                if (wid_caps & AC_WCAP_IN_AMP)
 530                        snd_iprintf(buffer, " Amp-In");
 531                if (wid_caps & AC_WCAP_OUT_AMP)
 532                        snd_iprintf(buffer, " Amp-Out");
 533                if (wid_caps & AC_WCAP_STRIPE)
 534                        snd_iprintf(buffer, " Stripe");
 535                if (wid_caps & AC_WCAP_LR_SWAP)
 536                        snd_iprintf(buffer, " R/L");
 537                if (wid_caps & AC_WCAP_CP_CAPS)
 538                        snd_iprintf(buffer, " CP");
 539                snd_iprintf(buffer, "\n");
 540
 541                /* volume knob is a special widget that always have connection
 542                 * list
 543                 */
 544                if (wid_type == AC_WID_VOL_KNB)
 545                        wid_caps |= AC_WCAP_CONN_LIST;
 546
 547                if (wid_caps & AC_WCAP_CONN_LIST)
 548                        conn_len = snd_hda_get_connections(codec, nid, conn,
 549                                                           HDA_MAX_CONNECTIONS);
 550
 551                if (wid_caps & AC_WCAP_IN_AMP) {
 552                        snd_iprintf(buffer, "  Amp-In caps: ");
 553                        print_amp_caps(buffer, codec, nid, HDA_INPUT);
 554                        snd_iprintf(buffer, "  Amp-In vals: ");
 555                        print_amp_vals(buffer, codec, nid, HDA_INPUT,
 556                                       wid_caps & AC_WCAP_STEREO,
 557                                       wid_type == AC_WID_PIN ? 1 : conn_len);
 558                }
 559                if (wid_caps & AC_WCAP_OUT_AMP) {
 560                        snd_iprintf(buffer, "  Amp-Out caps: ");
 561                        print_amp_caps(buffer, codec, nid, HDA_OUTPUT);
 562                        snd_iprintf(buffer, "  Amp-Out vals: ");
 563                        if (wid_type == AC_WID_PIN &&
 564                            codec->pin_amp_workaround)
 565                                print_amp_vals(buffer, codec, nid, HDA_OUTPUT,
 566                                               wid_caps & AC_WCAP_STEREO,
 567                                               conn_len);
 568                        else
 569                                print_amp_vals(buffer, codec, nid, HDA_OUTPUT,
 570                                               wid_caps & AC_WCAP_STEREO, 1);
 571                }
 572
 573                switch (wid_type) {
 574                case AC_WID_PIN: {
 575                        int supports_vref;
 576                        print_pin_caps(buffer, codec, nid, &supports_vref);
 577                        print_pin_ctls(buffer, codec, nid, supports_vref);
 578                        break;
 579                }
 580                case AC_WID_VOL_KNB:
 581                        print_vol_knob(buffer, codec, nid);
 582                        break;
 583                case AC_WID_AUD_OUT:
 584                case AC_WID_AUD_IN:
 585                        print_audio_io(buffer, codec, nid, wid_type);
 586                        if (wid_caps & AC_WCAP_DIGITAL)
 587                                print_digital_conv(buffer, codec, nid);
 588                        if (wid_caps & AC_WCAP_FORMAT_OVRD) {
 589                                snd_iprintf(buffer, "  PCM:\n");
 590                                print_pcm_caps(buffer, codec, nid);
 591                        }
 592                        break;
 593                }
 594
 595                if (wid_caps & AC_WCAP_UNSOL_CAP)
 596                        print_unsol_cap(buffer, codec, nid);
 597
 598                if (wid_caps & AC_WCAP_POWER)
 599                        print_power_state(buffer, codec, nid);
 600
 601                if (wid_caps & AC_WCAP_DELAY)
 602                        snd_iprintf(buffer, "  Delay: %d samples\n",
 603                                    (wid_caps & AC_WCAP_DELAY) >>
 604                                    AC_WCAP_DELAY_SHIFT);
 605
 606                if (wid_caps & AC_WCAP_CONN_LIST)
 607                        print_conn_list(buffer, codec, nid, wid_type,
 608                                        conn, conn_len);
 609
 610                if (wid_caps & AC_WCAP_PROC_WID)
 611                        print_proc_caps(buffer, codec, nid);
 612
 613                if (codec->proc_widget_hook)
 614                        codec->proc_widget_hook(buffer, codec, nid);
 615        }
 616        snd_hda_power_down(codec);
 617}
 618
 619/*
 620 * create a proc read
 621 */
 622int snd_hda_codec_proc_new(struct hda_codec *codec)
 623{
 624        char name[32];
 625        struct snd_info_entry *entry;
 626        int err;
 627
 628        snprintf(name, sizeof(name), "codec#%d", codec->addr);
 629        err = snd_card_proc_new(codec->bus->card, name, &entry);
 630        if (err < 0)
 631                return err;
 632
 633        snd_info_set_text_ops(entry, codec, print_codec_info);
 634        return 0;
 635}
 636
 637
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.