]> git.alsa-project.org Git - alsa.git/commitdiff
hda-analyzer: More changes regarding proc interface
authorJaroslav Kysela <perex@perex.cz>
Thu, 28 Jan 2010 12:16:32 +0000 (13:16 +0100)
committerJaroslav Kysela <perex@perex.cz>
Thu, 28 Jan 2010 12:35:21 +0000 (13:35 +0100)
- add support for gziped & bzip2ed files files
- add support for alsa-info.sh contents

Signed-off-by: Jaroslav Kysela <perex@perex.cz>
hda-analyzer/hda_analyzer.py
hda-analyzer/hda_codec.py
hda-analyzer/hda_proc.py
hda-analyzer/run.py

index 15943be18fc07ff94f28c0779fa0753effd0bad3..406cf117ae2ea13882c55c4bb37d7b46bf13f56c 100755 (executable)
@@ -32,7 +32,7 @@ DIFF_FILE = "/tmp/hda-analyze.diff"
 from hda_codec import HDACodec, HDA_card_list, \
                       EAPDBTL_BITS, PIN_WIDGET_CONTROL_BITS, \
                       PIN_WIDGET_CONTROL_VREF, DIG1_BITS, GPIO_IDS
-from hda_proc import HDACodecProc
+from hda_proc import DecodeProcFile, HDACodecProc
 
 CODEC_TREE = {}
 DIFF_TREE = {}
@@ -52,8 +52,8 @@ def read_nodes2(card, codec):
   if not card in CODEC_TREE:
     CODEC_TREE[card] = {}
     DIFF_TREE[card] = {}
-  CODEC_TREE[card][codec] = c
-  DIFF_TREE[card][codec] = c.dump()
+  CODEC_TREE[card][c.device] = c
+  DIFF_TREE[card][c.device] = c.dump()
 
 def read_nodes3(card, codec, proc_file):
   c = HDACodecProc(card, codec, proc_file)
@@ -61,8 +61,8 @@ def read_nodes3(card, codec, proc_file):
   if not card in CODEC_TREE:
     CODEC_TREE[card] = {}
     DIFF_TREE[card] = {}
-  CODEC_TREE[card][codec] = c
-  DIFF_TREE[card][codec] = c.dump()
+  CODEC_TREE[card][c.device] = c
+  DIFF_TREE[card][c.device] = c.dump()
 
 def read_nodes(proc_files):
   l = HDA_card_list()
@@ -73,9 +73,33 @@ def read_nodes(proc_files):
   for f in proc_files:
     a = f.split('+')
     idx = 0
+    if len(a) == 1:
+      proc_file = DecodeProcFile(a[0])
+      if proc_file.find("ALSA Information Script") > 0:
+        a = []
+        pos = proc_file.find('HDA-Intel Codec information')
+        if pos >= 0:
+          proc_file = proc_file[pos:]
+          pos = proc_file.find('--startcollapse--')
+          proc_file = proc_file[pos+18:]
+          pos = proc_file.find('--endcollapse--')
+          proc_file = proc_file[:pos]
+          while 1:
+            pos = proc_file.find('\nCodec: ')
+            if pos < 0:
+              break
+            proc_file = proc_file[pos:]
+            pos = proc_file[1:].find('\nCodec: ')
+            if pos < 0:
+              pos = len(proc_file)-2
+            read_nodes3(card, idx, proc_file[:pos+2])
+            proc_file = proc_file[pos:]
+            card += 1
     for i in a:
-      read_nodes3(card, idx, i)
+      proc_file = DecodeProcFile(i)
+      read_nodes3(card, idx, proc_file)
       idx += 1
+    card += 1
   cnt = 0
   for c in CODEC_TREE:
     if len(CODEC_TREE[c]) > 0:
index 3359e791e61ba7ebe92bb8c6dd7baa7c76de200e..f021250bf027e0abb3d5b6f527009d1ec076d94b 100644 (file)
@@ -229,6 +229,8 @@ DIG1_BITS = {
   'LEVEL': 7
 }
 
+POWER_STATES = ["D0", "D1", "D2", "D3", "D3cold", "S3D3cold", "CLKSTOP", "EPSS"]
+
 class HDAAmpCaps:
 
   def __init__(self, codec, nid, dir):
@@ -497,15 +499,20 @@ class HDANode:
       self.unsol_tag = unsol & 0x3f
       self.unsol_enabled = (unsol & (1 << 7)) and True or False
     if self.power:
-      states = ["D0", "D1", "D2", "D3"]
+      pwr = self.codec.param_read(self.nid, PARAMS['POWER_STATE'])
+      self.pwr_state = pwr
+      self.pwr_states = []
+      for a in range(len(POWER_STATES)):
+        if pwr & (1 << a):
+          self.pwr_states.append(POWER_STATES[a])
       pwr = self.codec.rw(self.nid, VERBS['GET_POWER_STATE'], 0)
       self.pwr = pwr
       if self.origin_pwr == None:
         self.origin_pwr = pwr
       self.pwr_setting = pwr & 0x0f
       self.pwr_actual = (pwr >> 4) & 0x0f
-      self.pwr_setting_name = self.pwr_setting < 4 and states[self.pwr_setting] or "UNKNOWN"
-      self.pwr_actual_name = self.pwr_actual < 4 and states[self.pwr_actual] or "UNKNOWN"
+      self.pwr_setting_name = self.pwr_setting < 4 and POWER_STATES[self.pwr_setting] or "UNKNOWN"
+      self.pwr_actual_name = self.pwr_actual < 4 and POWER_STATES[self.pwr_actual] or "UNKNOWN"
     # NID 0x20 == Realtek Define Registers
     if self.codec.vendor_id == 0x10ec and self.nid == 0x20:
       self.realtek_coeff_proc = self.codec.rw(self.nid, VERBS['GET_PROC_COEF'], 0)
@@ -1057,6 +1064,9 @@ class HDACodec:
       return "  Unsolicited: tag=0x%02x, enabled=%d\n" % (node.unsol_tag, node.unsol_enabled and 1 or 0)
 
     def print_power_state(node):
+      str = ""
+      if node.pwr_states:
+        str = "  Power states: %s\n" % ' '.join(node.pwr_states)
       return "  Power: setting=%s, actual=%s\n" % (node.pwr_setting_name, node.pwr_actual_name)
 
     def print_digital_conv(node):
index 3a5f5091a9a0a796537270db178de7b3a56a44a9..ab911ddd08956c09dac149a1bf77557979c9be5f 100644 (file)
@@ -19,8 +19,36 @@ SET_VERBS = {
   VERBS['SET_SDI_SELECT']: VERBS['GET_SDI_SELECT'],
   VERBS['SET_PIN_WIDGET_CONTROL']: VERBS['GET_PIN_WIDGET_CONTROL'],
   VERBS['SET_CONNECT_SEL']: VERBS['GET_CONNECT_SEL'],
+  VERBS['SET_EAPD_BTLENABLE']: VERBS['GET_EAPD_BTLENABLE'],
+  VERBS['SET_POWER_STATE']: VERBS['GET_POWER_STATE'],
 }
 
+def DecodeProcFile(proc_file):
+  if len(proc_file) < 256:
+    fd = open(proc_file)
+  proc_file = fd.read(1024*1024)
+  fd.close()
+  if proc_file.find('Subsystem Id:') < 0:
+      p = None
+      try:
+        from gzip import GzipFile
+        from StringIO import StringIO
+        s = StringIO(proc_file)
+        gz = GzipFile(mode='r', fileobj=s)
+        p = gz.read(1024*1024)
+        gz.close()
+      except:
+        pass
+      if p is None:
+        try:
+          from bz2 import decompress
+          p = decompress(proc_file)
+        except:
+          pass
+      if not p is None:
+        proc_file = p
+  return proc_file
+
 class HDACardProc:
 
   def __init__(self, card):
@@ -55,7 +83,7 @@ class HDABaseProc:
       while ok:
         ok = False
         for a in self.delim:
-          if rem[0] == a:
+          if rem and rem[0] == a:
             rem = rem[1:]
             ok = True
       return rem.strip(), res.strip()
@@ -125,6 +153,8 @@ class ProcNode(HDABaseProc):
     self.params = {}
     self.verbs = {}
     self.controls = []
+    if wcaps & (1 << 10):
+      self.add_param(PARAMS['POWER_STATE'], 0)
 
   def rw(self, verb, param):
     if verb in self.verbs:
@@ -201,7 +231,7 @@ class ProcNode(HDABaseProc):
       'Pro': DIG1_BITS['PROFESSIONAL'],
       'GenLevel': DIG1_BITS['LEVEL']
     }
-    bits = 0
+    xbits = 0
     a = line.split(' ')
     for b in a:
       b = b.strip()
@@ -209,8 +239,8 @@ class ProcNode(HDABaseProc):
         return
       if not b in bits:
         self.wrongfile('unknown dig1 bit %s' % repr(b))
-      bits |= 1 << bits[b]
-    self.add_verb(VERBS['GET_DIGI_CONVERT_1'], bits)
+      xbits |= 1 << bits[b]
+    self.add_verb(VERBS['GET_DIGI_CONVERT_1'], xbits)
 
   def add_digitalcategory(self, line):
     line, res = self.decodeintw(line)
@@ -301,6 +331,31 @@ class ProcNode(HDABaseProc):
     line, tmp1 = self.decodeintw(line, '')
     self.add_verb(VERBS['GET_PIN_WIDGET_CONTROL'], tmp1)
 
+  def add_eapd(self, line):
+    line, tmp1 = self.decodeintw(line, '')
+    self.add_verb(VERBS['GET_EAPD_BTLENABLE'], tmp1)
+
+  def add_power(self, line):
+    line, setting = self.decodestrw(line, 'setting=')
+    line, actual = self.decodestrw(line, 'actual=')
+    if setting in POWER_STATES:
+      setting = POWER_STATES.index(setting)
+    else:
+      self.wrongfile('power setting %s' % setting)
+    if actual in POWER_STATES:
+      actual = POWER_STATES.index(actual)
+    else:
+      self.wrongfile('power actual %s' % actual)
+    self.add_verb(VERBS['GET_POWER_STATE'], (setting & 0x0f) | ((actual & 0x0f) << 4))
+  
+  def add_powerstates(self, line):
+    a = line.strip().split(' ')
+    tmp1
+    for b in a:
+      if b in POWER_STATES:
+        tmp1 |= 1 << POWER_STATES.index(b)
+    self.add_parm(PARAMS['POWER_STATE'], tmp1)
+
   def dump_extra(self):
     str = ''
     if self.device:
@@ -316,10 +371,6 @@ class HDACodecProc(HDACodec, HDABaseProc):
     self.card = card
     self.device = device
     self.mcard = HDACardProc(card)
-    if len(proc_file) < 256:
-      fd = open(proc_file)
-      proc_file = fd.read(1024*1024)
-      fd.close()
     self.proc_codec_id = None
     self.parse(proc_file)
     if self.proc_codec_id:
@@ -377,10 +428,7 @@ class HDACodecProc(HDACodec, HDABaseProc):
     
       def writeval(str, idx, var):
         res, val = self.decodeintw(str, var + '=')
-        if not self.proc_gpio.has_key(var):
-          self.proc_gpio[var] = 0
-        if val:
-          self.proc_gpio[var] |= 1 << idx
+        self.proc_gpio[var] |= 1 << idx
         return res
     
       res = lines[idx]
@@ -398,7 +446,9 @@ class HDACodecProc(HDACodec, HDABaseProc):
     idx, self.proc_codec_id = lookfor(idx, 'Codec: ')
     idx, tmp = lookforint(idx, 'Address: ')
     self.device = tmp # really?
-    idx, self.proc_function_id = lookforint(idx, 'Function Id: ')
+    self.proc_function_id = None
+    if lines[idx].startswith('Function Id: '):
+      idx, self.proc_function_id = lookforint(idx, 'Function Id: ')
     idx, self.proc_vendor_id = lookforint(idx, 'Vendor Id: ')
     idx, self.proc_subsystem_id = lookforint(idx, 'Subsystem Id: ')
     idx, self.proc_revision_id = lookforint(idx, 'Revision Id:' )
@@ -408,9 +458,13 @@ class HDACodecProc(HDACodec, HDABaseProc):
     if nomfg:
       idx += 1
     else:
+      if self.proc_function_id is None:
+        self.proc_function_id = 2
       idx, self.proc_modem_grp = lookforint(idx, 'Modem Function Group: ')
       self.proc_afd = -1
       return
+    if self.proc_function_id is None:
+      self.proc_function_id = 1
     if not lines[idx].startswith('Default PCM:'):
       self.wrongfile('default pcm expected')
     idx, tmp1 = decodeint(idx+1, '    rates [')
@@ -419,10 +473,22 @@ class HDACodecProc(HDACodec, HDABaseProc):
     idx, self.proc_pcm_stream = decodeint(idx, '    formats [')
     idx, self.proc_amp_caps_in = decodeampcap(idx, 'Default Amp-In caps: ')
     idx, self.proc_amp_caps_out = decodeampcap(idx, 'Default Amp-Out caps: ')
-    idx, self.proc_gpio_cap = decodegpiocap(idx, 'GPIO: ')
-    self.proc_gpio = {}
-    while lines[idx].startswith('  IO['):
-      idx = decodegpio(idx, '  IO[')
+    self.proc_gpio = {
+      'enable': 0,
+      'dir': 0,
+      'wake': 0,
+      'sticky': 0,
+      'data': 0,
+      'unsol': 0
+    }
+    self.proc_gpio_cap = 0
+    if lines[idx].startswith('GPIO: '):
+      idx, self.proc_gpio_cap = decodegpiocap(idx, 'GPIO: ')
+      while lines[idx].startswith('  IO['):
+        idx = decodegpio(idx, '  IO[')
+    if lines[idx].strip() == 'Invalid AFG subtree':
+      print "Invalid AFG subtree for codec %s?" % self.proc_codec_id
+      return
     node = None
     while idx < len(lines):
       line = lines[idx]
@@ -481,6 +547,12 @@ class HDACodecProc(HDACodec, HDABaseProc):
           pass
         elif line.startswith('  Pin-ctls: '):
           node.add_pinctls(line[12:])
+        elif line.startswith('  EAPD '):
+          node.add_eapd(line[7:])
+        elif line.startswith('  Power states: '):
+          node.add_powerstates(line[16:])
+        elif line.startswith('  Power: '):
+          node.add_power(line[9:])
         else:
           self.wrongfile(line)
         idx += 1
@@ -519,7 +591,9 @@ class HDACodecProc(HDACodec, HDABaseProc):
     if nid == AC_NODE_ROOT:
       return self.proc_afd, 1
     elif nid == self.proc_afd:
-      return len(self.proc_nids), self.proc_nids.keys()[0]
+      if self.proc_nids:
+        return len(self.proc_nids), self.proc_nids.keys()[0]
+      return 0, 0
     raise ValueError, "unimplemented get_sub_nodes(0x%x)" % nid
 
   def get_wcap(self, nid):
index 50b25c6eb66e37fb9a888362d3f281e654fd84ee..4d4a1a7544a0591563cc8fc860e451a38158b466 100755 (executable)
@@ -1,7 +1,7 @@
 #!/usr/bin/env python
 
 URL="http://git.alsa-project.org/?p=alsa.git;a=blob_plain;f=hda-analyzer/"
-FILES=["hda_analyzer.py", "hda_codec.py"]
+FILES=["hda_analyzer.py", "hda_codec.py", "hda_proc.py"]
 
 try:
   import gobject