here's a patch to power down unused widgets.  should be safe, but my
devices don't support this (about half of all azalia codecs support power
modes on the individual widgets) so please test that this doesn't somehow
break the ability to use your soundcard.

-- 
[email protected]
SDF Public Access UNIX System - http://sdf.lonestar.org

Index: azalia.c
===================================================================
RCS file: /cvs/src/sys/dev/pci/azalia.c,v
retrieving revision 1.131
diff -u azalia.c
--- azalia.c    12 May 2009 09:32:28 -0000      1.131
+++ azalia.c    12 May 2009 21:52:18 -0000
@@ -214,6 +214,7 @@
 int    azalia_codec_select_micadc(codec_t *);
 int    azalia_codec_select_spkrdac(codec_t *);
 int    azalia_codec_find_inputmixer(codec_t *);
+int    azalia_codec_pd_disabled(codec_t *);
 
 int    azalia_widget_init(widget_t *, const codec_t *, int);
 int    azalia_widget_label_widgets(codec_t *);
@@ -1391,6 +1392,10 @@
        if (err)
                return err;
 
+       err = azalia_codec_pd_disabled(this);
+       if (err)
+               return err;
+
        return 0;
 }
 
@@ -2054,6 +2059,46 @@
 
        return 0;
 }
+
+int
+azalia_codec_pd_disabled(codec_t *this)
+{
+       uint32_t result, state;
+       int nid, err;
+
+       FOR_EACH_WIDGET(this, nid) {
+               /* never power down a power widget */
+               if (this->w[nid].type == COP_AWTYPE_POWER)
+                       continue;
+               if (this->w[nid].enable)
+                       continue;
+               if (!(this->w[nid].widgetcap & COP_AWCAP_POWER))
+                       continue;
+               err = this->comresp(this, nid, CORB_GET_PARAMETER,
+                   COP_SUPPORTED_POWER_STATES, &result);
+               if (err)
+                       continue;
+               state = CORB_PS_D3;
+               if (!(result & (1 << state))) {
+                       state = CORB_PS_D2;
+                       if (!(result & (1 << state))) {
+                               state = CORB_PS_D1;
+                               if (!(result & (1 << state))) {
+                                       continue;
+                               }
+                       }
+               }
+               err = this->comresp(this, nid, CORB_SET_POWER_STATE,
+                   state, &result);
+               if (err) {
+                       DPRINTF(("%s: error powering down 0x%2.2x\n",
+                           XNAME(this->az), nid));
+                       continue;
+               }
+       }
+       return(0);
+}
+
 
 int
 azalia_codec_delete(codec_t *this)

Reply via email to