[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[cdi-devel] [PATCH 4/9] hdaudio: Debug output for every widget



Even for non-output widgets, gather some data and print it in debug
mode.

Signed-off-by: Kevin Wolf <kevin@xxxxxxxxxx>
---
 hdaudio/device.h | 25 +++++++++++++++++
 hdaudio/main.c   | 84 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 108 insertions(+), 1 deletion(-)

diff --git a/hdaudio/device.h b/hdaudio/device.h
index 6af4ddc..eb4746c 100644
--- a/hdaudio/device.h
+++ b/hdaudio/device.h
@@ -177,19 +177,44 @@ enum codec_verbs {
     VERB_GET_PARAMETER      = 0xf0000,
     VERB_SET_STREAM_CHANNEL = 0x70600,
     VERB_SET_FORMAT         = 0x20000,
+    VERB_GET_AMP_GAIN_MUTE  = 0xb0000,
     VERB_SET_AMP_GAIN_MUTE  = 0x30000,
+    VERB_GET_CONN_LIST      = 0xf0200,
+    VERB_GET_CONN_SELECT    = 0xf0100,
+    VERB_GET_EAPD_BTL       = 0xf0c00,
 };
 
 enum codec_parameters {
     PARAM_NODE_COUNT        = 0x04,
     PARAM_FN_GROUP_TYPE     = 0x05,
     PARAM_AUDIO_WID_CAP     = 0x09,
+    PARAM_CONN_LIST_LEN     = 0x0e,
+    PARAM_OUT_AMP_CAP       = 0x12,
 };
 
 enum fn_group_type {
     FN_GROUP_AUDIO          = 0x01,
 };
 
+enum widget_type {
+    WIDGET_OUTPUT           = 0x0,
+    WIDGET_INPUT            = 0x1,
+    WIDGET_MIXER            = 0x2,
+    WIDGET_SELECTOR         = 0x3,
+    WIDGET_PIN              = 0x4,
+    WIDGET_POWER            = 0x5,
+    WIDGET_VOLUME_KNOB      = 0x6,
+    WIDGET_BEEP_GEN         = 0x7,
+    WIDGET_VENDOR_DEFINED   = 0xf,
+};
+
+enum widget_capabilities {
+    WIDGET_CAP_POWER_CNTRL  = (1 << 10),
+
+    WIDGET_CAP_TYPE_SHIFT   = 20,
+    WIDGET_CAP_TYPE_MASK    = (0xf << 20),
+};
+
 enum sample_format {
     SR_48_KHZ               = 0,
     SR_44_KHZ               = (1 << 14),
diff --git a/hdaudio/main.c b/hdaudio/main.c
index 313f59b..416aa80 100644
--- a/hdaudio/main.c
+++ b/hdaudio/main.c
@@ -215,6 +215,53 @@ static void init_output_widget(struct hda_device* hda)
     configure_output_widget(hda);
 }
 
+#ifdef DEBUG
+static void widget_dump_connections(struct hda_device* hda, int codec, int nid)
+{
+    uint32_t num_conn;
+    uint32_t sel;
+    int i;
+
+    num_conn = codec_query(hda, codec, nid,
+                           VERB_GET_PARAMETER | PARAM_CONN_LIST_LEN);
+    if (!num_conn) {
+        return;
+    }
+
+    DPRINTF("        conn:");
+
+    for (i = 0; i < (num_conn & 0x7f); i++) {
+        uint32_t conn;
+        bool range;
+        int idx, shift;
+
+        if (num_conn & 0x80) {
+            idx = i & ~3;
+            shift = 8 * (i & 3);
+        } else {
+            idx = i & ~1;
+            shift = 8 * (i & 1);
+        }
+
+        conn = codec_query(hda, codec, nid, VERB_GET_CONN_LIST | idx);
+        conn >>= shift;
+
+        if (num_conn & 0x80) {
+            range = conn & 0x8000;
+            conn &= 0x7fff;
+        } else {
+            range = conn & 0x80;
+            conn &= 0x7f;
+        }
+
+        printf("%c%d", range ? '-' : ' ', conn);
+    }
+
+    sel = codec_query(hda, codec, nid, VERB_GET_CONN_SELECT);
+    printf(" [current: %d]\n", sel);
+}
+#endif
+
 static void widget_init(struct hda_device* hda, int codec, int nid)
 {
     uint32_t widget_cap;
@@ -225,8 +272,42 @@ static void widget_init(struct hda_device* hda, int codec, int nid)
         return;
     }
 
+#ifdef DEBUG
+    enum widget_type type;
+    uint32_t eapd_btl;
+    uint32_t amp_gain;
+    uint32_t amp_cap;
+    const char* s;
+
+    type = (widget_cap & WIDGET_CAP_TYPE_MASK) >> WIDGET_CAP_TYPE_SHIFT;
+
+    switch (type) {
+        case 0:     s = "output"; break;
+        case 1:     s = "input"; break;
+        case 2:     s = "mixer"; break;
+        case 3:     s = "selector"; break;
+        case 4:     s = "pin complex"; break;
+        case 5:     s = "power"; break;
+        case 6:     s = "volume knob"; break;
+        case 7:     s = "beep generator"; break;
+        case 15:    s = "vendor defined"; break;
+        default:    s = "unknown"; break;
+    }
+
+    amp_gain = codec_query(hda, codec, nid,
+                           VERB_GET_AMP_GAIN_MUTE | 0x8000) << 8;
+    amp_gain |= codec_query(hda, codec, nid, VERB_GET_AMP_GAIN_MUTE | 0xa000);
+    amp_cap = codec_query(hda, codec, nid,
+                          VERB_GET_PARAMETER | PARAM_OUT_AMP_CAP);
+    eapd_btl = codec_query(hda, codec, nid, VERB_GET_EAPD_BTL);
+
+    DPRINTF("    %s at ID %d; cap %x, eapd %x, amp %x/%x\n",
+            s, nid, widget_cap, eapd_btl, amp_gain, amp_cap);
+
+    widget_dump_connections(hda, codec, nid);
+#endif
+
     if ((widget_cap & 0xf00000) == 0) {
-        DPRINTF("    Audio output at ID %d!\n", nid);
         if (!hda->output.nid) {
             DPRINTF("    * Using output at ID %d!\n", nid);
             hda->output.codec = codec;
@@ -270,6 +351,7 @@ static int codec_enumerate_widgets(struct hda_device* hda, int codec)
         for (j = 0; j < num_widgets; j++) {
             widget_init(hda, codec, widgets_start + j);
         }
+        DPRINTF("\n");
     }
 
     return hda->output.nid ? 0 : -1;
-- 
2.1.4