fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git] / sound / pci / hda / hda_proc.c
index 4d5db7f..17df4d0 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/pci.h>
 #include <sound/core.h>
 #include "hda_codec.h"
+#include "hda_local.h"
 
 static const char *get_wid_type_name(unsigned int wid_value)
 {
@@ -44,17 +45,16 @@ static const char *get_wid_type_name(unsigned int wid_value)
        if (names[wid_value])
                return names[wid_value];
        else
-               return "UNKOWN Widget";
+               return "UNKNOWN Widget";
 }
 
-static void print_amp_caps(snd_info_buffer_t *buffer,
+static void print_amp_caps(struct snd_info_buffer *buffer,
                           struct hda_codec *codec, hda_nid_t nid, int dir)
 {
        unsigned int caps;
-       if (dir == HDA_OUTPUT)
-               caps = snd_hda_param_read(codec, nid, AC_PAR_AMP_OUT_CAP);
-       else
-               caps = snd_hda_param_read(codec, nid, AC_PAR_AMP_IN_CAP);
+       caps = snd_hda_param_read(codec, nid,
+                                 dir == HDA_OUTPUT ?
+                                   AC_PAR_AMP_OUT_CAP : AC_PAR_AMP_IN_CAP);
        if (caps == -1 || caps == 0) {
                snd_iprintf(buffer, "N/A\n");
                return;
@@ -66,26 +66,71 @@ static void print_amp_caps(snd_info_buffer_t *buffer,
                    (caps & AC_AMPCAP_MUTE) >> AC_AMPCAP_MUTE_SHIFT);
 }
 
-static void print_amp_vals(snd_info_buffer_t *buffer,
+static void print_amp_vals(struct snd_info_buffer *buffer,
                           struct hda_codec *codec, hda_nid_t nid,
-                          int dir, int stereo)
+                          int dir, int stereo, int indices)
 {
        unsigned int val;
-       if (stereo) {
+       int i;
+
+       dir = dir == HDA_OUTPUT ? AC_AMP_GET_OUTPUT : AC_AMP_GET_INPUT;
+       for (i = 0; i < indices; i++) {
+               snd_iprintf(buffer, " [");
+               if (stereo) {
+                       val = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_AMP_GAIN_MUTE,
+                                                AC_AMP_GET_LEFT | dir | i);
+                       snd_iprintf(buffer, "0x%02x ", val);
+               }
                val = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_AMP_GAIN_MUTE,
-                                         AC_AMP_GET_LEFT |
-                                        (dir == HDA_OUTPUT ? AC_AMP_GET_OUTPUT :
-                                         AC_AMP_GET_INPUT));
-               snd_iprintf(buffer, "0x%02x ", val);
+                                        AC_AMP_GET_RIGHT | dir | i);
+               snd_iprintf(buffer, "0x%02x]", val);
        }
-       val = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_AMP_GAIN_MUTE,
-                                AC_AMP_GET_RIGHT |
-                                (dir == HDA_OUTPUT ? AC_AMP_GET_OUTPUT :
-                                 AC_AMP_GET_INPUT));
-       snd_iprintf(buffer, "0x%02x\n", val);
+       snd_iprintf(buffer, "\n");
+}
+
+static void print_pcm_rates(struct snd_info_buffer *buffer, unsigned int pcm)
+{
+       static unsigned int rates[] = {
+               8000, 11025, 16000, 22050, 32000, 44100, 48000, 88200,
+               96000, 176400, 192000, 384000
+       };
+       int i;
+
+       pcm &= AC_SUPPCM_RATES;
+       snd_iprintf(buffer, "    rates [0x%x]:", pcm);
+       for (i = 0; i < ARRAY_SIZE(rates); i++) 
+               if (pcm & (1 << i))
+                       snd_iprintf(buffer, " %d", rates[i]);
+       snd_iprintf(buffer, "\n");
+}
+
+static void print_pcm_bits(struct snd_info_buffer *buffer, unsigned int pcm)
+{
+       static unsigned int bits[] = { 8, 16, 20, 24, 32 };
+       int i;
+
+       pcm = (pcm >> 16) & 0xff;
+       snd_iprintf(buffer, "    bits [0x%x]:", pcm);
+       for (i = 0; i < ARRAY_SIZE(bits); i++)
+               if (pcm & (1 << i))
+                       snd_iprintf(buffer, " %d", bits[i]);
+       snd_iprintf(buffer, "\n");
+}
+
+static void print_pcm_formats(struct snd_info_buffer *buffer,
+                             unsigned int streams)
+{
+       snd_iprintf(buffer, "    formats [0x%x]:", streams & 0xf);
+       if (streams & AC_SUPFMT_PCM)
+               snd_iprintf(buffer, " PCM");
+       if (streams & AC_SUPFMT_FLOAT32)
+               snd_iprintf(buffer, " FLOAT");
+       if (streams & AC_SUPFMT_AC3)
+               snd_iprintf(buffer, " AC3");
+       snd_iprintf(buffer, "\n");
 }
 
-static void print_pcm_caps(snd_info_buffer_t *buffer,
+static void print_pcm_caps(struct snd_info_buffer *buffer,
                           struct hda_codec *codec, hda_nid_t nid)
 {
        unsigned int pcm = snd_hda_param_read(codec, nid, AC_PAR_PCM);
@@ -94,8 +139,9 @@ static void print_pcm_caps(snd_info_buffer_t *buffer,
                snd_iprintf(buffer, "N/A\n");
                return;
        }
-       snd_iprintf(buffer, "rates 0x%03x, bits 0x%02x, types 0x%x\n",
-                   pcm & AC_SUPPCM_RATES, (pcm >> 16) & 0xff, stream & 0xf);
+       print_pcm_rates(buffer, pcm);
+       print_pcm_bits(buffer, pcm);
+       print_pcm_formats(buffer, stream);
 }
 
 static const char *get_jack_location(u32 cfg)
@@ -154,9 +200,10 @@ static const char *get_jack_color(u32 cfg)
                return "UNKNOWN";
 }
 
-static void print_pin_caps(snd_info_buffer_t *buffer,
+static void print_pin_caps(struct snd_info_buffer *buffer,
                           struct hda_codec *codec, hda_nid_t nid)
 {
+       static char *jack_conns[4] = { "Jack", "N/A", "Fixed", "Both" };
        static char *jack_types[16] = {
                "Line Out", "Speaker", "HP Out", "CD",
                "SPDIF Out", "Digital Out", "Modem Line", "Modem Hand",
@@ -174,9 +221,14 @@ static void print_pin_caps(snd_info_buffer_t *buffer,
                snd_iprintf(buffer, " OUT");
        if (caps & AC_PINCAP_HP_DRV)
                snd_iprintf(buffer, " HP");
+       if (caps & AC_PINCAP_EAPD)
+               snd_iprintf(buffer, " EAPD");
+       if (caps & AC_PINCAP_PRES_DETECT)
+               snd_iprintf(buffer, " Detect");
        snd_iprintf(buffer, "\n");
        caps = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONFIG_DEFAULT, 0);
-       snd_iprintf(buffer, "  Pin Default 0x%08x: %s at %s %s\n", caps,
+       snd_iprintf(buffer, "  Pin Default 0x%08x: [%s] %s at %s %s\n", caps,
+                   jack_conns[(caps & AC_DEFCFG_PORT_CONN) >> AC_DEFCFG_PORT_CONN_SHIFT],
                    jack_types[(caps & AC_DEFCFG_DEVICE) >> AC_DEFCFG_DEVICE_SHIFT],
                    jack_locations[(caps >> (AC_DEFCFG_LOCATION_SHIFT + 4)) & 3],
                    get_jack_location(caps));
@@ -186,7 +238,7 @@ static void print_pin_caps(snd_info_buffer_t *buffer,
 }
 
 
-static void print_codec_info(snd_info_entry_t *entry, snd_info_buffer_t *buffer)
+static void print_codec_info(struct snd_info_entry *entry, struct snd_info_buffer *buffer)
 {
        struct hda_codec *codec = entry->private_data;
        char buf[32];
@@ -199,7 +251,9 @@ static void print_codec_info(snd_info_entry_t *entry, snd_info_buffer_t *buffer)
        snd_iprintf(buffer, "Vendor Id: 0x%x\n", codec->vendor_id);
        snd_iprintf(buffer, "Subsystem Id: 0x%x\n", codec->subsystem_id);
        snd_iprintf(buffer, "Revision Id: 0x%x\n", codec->revision_id);
-       snd_iprintf(buffer, "Default PCM: ");
+       if (! codec->afg)
+               return;
+       snd_iprintf(buffer, "Default PCM:\n");
        print_pcm_caps(buffer, codec, codec->afg);
        snd_iprintf(buffer, "Default Amp-In caps: ");
        print_amp_caps(buffer, codec, codec->afg, HDA_INPUT);
@@ -215,6 +269,9 @@ static void print_codec_info(snd_info_entry_t *entry, snd_info_buffer_t *buffer)
                unsigned int wid_caps = snd_hda_param_read(codec, nid,
                                                           AC_PAR_AUDIO_WIDGET_CAP);
                unsigned int wid_type = (wid_caps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT;
+               int conn_len = 0; 
+               hda_nid_t conn[HDA_MAX_CONNECTIONS];
+
                snd_iprintf(buffer, "Node 0x%02x [%s] wcaps 0x%x:", nid,
                            get_wid_type_name(wid_type), wid_caps);
                if (wid_caps & AC_WCAP_STEREO)
@@ -229,19 +286,23 @@ static void print_codec_info(snd_info_entry_t *entry, snd_info_buffer_t *buffer)
                        snd_iprintf(buffer, " Amp-Out");
                snd_iprintf(buffer, "\n");
 
+               if (wid_caps & AC_WCAP_CONN_LIST)
+                       conn_len = snd_hda_get_connections(codec, nid, conn,
+                                                          HDA_MAX_CONNECTIONS);
+
                if (wid_caps & AC_WCAP_IN_AMP) {
                        snd_iprintf(buffer, "  Amp-In caps: ");
                        print_amp_caps(buffer, codec, nid, HDA_INPUT);
                        snd_iprintf(buffer, "  Amp-In vals: ");
                        print_amp_vals(buffer, codec, nid, HDA_INPUT,
-                                      wid_caps & AC_WCAP_STEREO);
+                                      wid_caps & AC_WCAP_STEREO, conn_len);
                }
                if (wid_caps & AC_WCAP_OUT_AMP) {
                        snd_iprintf(buffer, "  Amp-Out caps: ");
                        print_amp_caps(buffer, codec, nid, HDA_OUTPUT);
                        snd_iprintf(buffer, "  Amp-Out vals: ");
                        print_amp_vals(buffer, codec, nid, HDA_OUTPUT,
-                                      wid_caps & AC_WCAP_STEREO);
+                                      wid_caps & AC_WCAP_STEREO, 1);
                }
 
                if (wid_type == AC_WID_PIN) {
@@ -260,19 +321,27 @@ static void print_codec_info(snd_info_entry_t *entry, snd_info_buffer_t *buffer)
 
                if ((wid_type == AC_WID_AUD_OUT || wid_type == AC_WID_AUD_IN) &&
                    (wid_caps & AC_WCAP_FORMAT_OVRD)) {
-                       snd_iprintf(buffer, "  PCM: ");
+                       snd_iprintf(buffer, "  PCM:\n");
                        print_pcm_caps(buffer, codec, nid);
                }
 
+               if (wid_caps & AC_WCAP_POWER)
+                       snd_iprintf(buffer, "  Power: 0x%x\n",
+                                   snd_hda_codec_read(codec, nid, 0,
+                                                      AC_VERB_GET_POWER_STATE, 0));
+
                if (wid_caps & AC_WCAP_CONN_LIST) {
-                       hda_nid_t conn[HDA_MAX_CONNECTIONS];
-                       int c, conn_len;
-                       conn_len = snd_hda_get_connections(codec, nid, conn,
-                                                          HDA_MAX_CONNECTIONS);
+                       int c, curr = -1;
+                       if (conn_len > 1 && wid_type != AC_WID_AUD_MIX)
+                               curr = snd_hda_codec_read(codec, nid, 0,
+                                       AC_VERB_GET_CONNECT_SEL, 0);
                        snd_iprintf(buffer, "  Connection: %d\n", conn_len);
                        snd_iprintf(buffer, "    ");
-                       for (c = 0; c < conn_len; c++)
+                       for (c = 0; c < conn_len; c++) {
                                snd_iprintf(buffer, " 0x%02x", conn[c]);
+                               if (c == curr)
+                                       snd_iprintf(buffer, "*");
+                       }
                        snd_iprintf(buffer, "\n");
                }
        }
@@ -284,7 +353,7 @@ static void print_codec_info(snd_info_entry_t *entry, snd_info_buffer_t *buffer)
 int snd_hda_codec_proc_new(struct hda_codec *codec)
 {
        char name[32];
-       snd_info_entry_t *entry;
+       struct snd_info_entry *entry;
        int err;
 
        snprintf(name, sizeof(name), "codec#%d", codec->addr);
@@ -292,7 +361,7 @@ int snd_hda_codec_proc_new(struct hda_codec *codec)
        if (err < 0)
                return err;
 
-       snd_info_set_text_ops(entry, codec, 32 * 1024, print_codec_info);
+       snd_info_set_text_ops(entry, codec, print_codec_info);
        return 0;
 }