Author: mav
Date: Fri Jan 22 09:31:10 2010
New Revision: 202789
URL: http://svn.freebsd.org/changeset/base/202789

Log:
  - Improve tracer, to handle more cases of input-to-output monitoring
  loopback.
  - Change the meaning of "mix" OSS control. Now it controls loopback level,
  according to comments in soundcard.h.
  - Allow AD1981HD codecs to use playback mixer. Now driver should be able to
  really use it.
  - Fix bug in shared muters operation.

Modified:
  head/sys/dev/sound/pci/hda/hdac.c

Modified: head/sys/dev/sound/pci/hda/hdac.c
==============================================================================
--- head/sys/dev/sound/pci/hda/hdac.c   Fri Jan 22 09:30:09 2010        
(r202788)
+++ head/sys/dev/sound/pci/hda/hdac.c   Fri Jan 22 09:31:10 2010        
(r202789)
@@ -86,7 +86,7 @@
 
 #include "mixer_if.h"
 
-#define HDA_DRV_TEST_REV       "20100112_0140"
+#define HDA_DRV_TEST_REV       "20100122_0141"
 
 SND_DECLARE_FILE("$FreeBSD$");
 
@@ -3934,8 +3934,8 @@ hdac_audio_ctl_ossmixer_set(struct snd_m
                                rvol = rvol * pdevinfo->right[j] / 100;
                        }
                }
-               mute = (left == 0) ? HDA_AMP_MUTE_LEFT : 0;
-               mute |= (right == 0) ? HDA_AMP_MUTE_RIGHT : 0;
+               mute = (lvol == 0) ? HDA_AMP_MUTE_LEFT : 0;
+               mute |= (rvol == 0) ? HDA_AMP_MUTE_RIGHT : 0;
                lvol = (lvol * ctl->step + 50) / 100;
                rvol = (rvol * ctl->step + 50) / 100;
                hdac_audio_ctl_amp_set(ctl, mute, lvol, rvol);
@@ -4757,37 +4757,6 @@ hdac_vendor_patch_parse(struct hdac_devi
        }
 
        switch (id) {
-#if 0
-       case HDA_CODEC_ALC883:
-               /*
-                * nid: 24/25 = External (jack) or Internal (fixed) Mic.
-                *              Clear vref cap for jack connectivity.
-                */
-               w = hdac_widget_get(devinfo, 24);
-               if (w != NULL && w->enable != 0 && w->type ==
-                   HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX &&
-                   (w->wclass.pin.config &
-                   HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK) ==
-                   HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_JACK)
-                       w->wclass.pin.cap &= ~(
-                           HDA_PARAM_PIN_CAP_VREF_CTRL_100_MASK |
-                           HDA_PARAM_PIN_CAP_VREF_CTRL_80_MASK |
-                           HDA_PARAM_PIN_CAP_VREF_CTRL_50_MASK);
-               w = hdac_widget_get(devinfo, 25);
-               if (w != NULL && w->enable != 0 && w->type ==
-                   HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX &&
-                   (w->wclass.pin.config &
-                   HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK) ==
-                   HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_JACK)
-                       w->wclass.pin.cap &= ~(
-                           HDA_PARAM_PIN_CAP_VREF_CTRL_100_MASK |
-                           HDA_PARAM_PIN_CAP_VREF_CTRL_80_MASK |
-                           HDA_PARAM_PIN_CAP_VREF_CTRL_50_MASK);
-               /*
-                * nid: 26 = Line-in, leave it alone.
-                */
-               break;
-#endif
        case HDA_CODEC_AD1983:
                /*
                 * This codec has several possible usages, but none
@@ -4900,10 +4869,19 @@ hdac_vendor_patch_parse(struct hdac_devi
                w = hdac_widget_get(devinfo, 31);
                if (w != NULL)
                        w->enable = 0;
-               /* Disable playback mixer, use direct bypass. */
-               w = hdac_widget_get(devinfo, 14);
+               /* Disable direct playback, use mixer. */
+               w = hdac_widget_get(devinfo, 5);
                if (w != NULL)
-                       w->enable = 0;
+                       w->connsenable[0] = 0;
+               w = hdac_widget_get(devinfo, 6);
+               if (w != NULL)
+                       w->connsenable[0] = 0;
+               w = hdac_widget_get(devinfo, 9);
+               if (w != NULL)
+                       w->connsenable[0] = 0;
+               w = hdac_widget_get(devinfo, 24);
+               if (w != NULL)
+                       w->connsenable[0] = 0;
                break;
        }
 }
@@ -5279,6 +5257,8 @@ hdac_audio_trace_to_out(struct hdac_devi
                                    " %*snid %d found output association %d\n",
                                        depth + 1, "", w->nid, w->bindas);
                        );
+                       if (w->bindas >= 0)
+                               w->pflags |= HDA_ADC_MONITOR;
                        return (1);
                } else {
                        HDA_BOOTHVERBOSE(
@@ -5321,7 +5301,7 @@ hdac_audio_trace_to_out(struct hdac_devi
                }
                break;
        }
-       if (res)
+       if (res && w->bindas == -1)
                w->bindas = -2;
 
        HDA_BOOTHVERBOSE(
@@ -5368,11 +5348,39 @@ hdac_audio_trace_as_extra(struct hdac_de
                                    " nid %d is input monitor\n",
                                        w->nid);
                        );
-                       w->pflags |= HDA_ADC_MONITOR;
                        w->ossdev = SOUND_MIXER_IMIX;
                }
        }
 
+       /* Other inputs monitor */
+       /* Find input pins supplying signal for output associations.
+          Hope it will be input monitoring. */
+       HDA_BOOTVERBOSE(
+               device_printf(devinfo->codec->sc->dev,
+                   "Tracing other input monitors\n");
+       );
+       for (j = devinfo->startnode; j < devinfo->endnode; j++) {
+               w = hdac_widget_get(devinfo, j);
+               if (w == NULL || w->enable == 0)
+                       continue;
+               if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX)
+                       continue;
+               if (w->bindas < 0 || as[w->bindas].dir != HDA_CTL_IN)
+                       continue;
+               HDA_BOOTVERBOSE(
+                       device_printf(devinfo->codec->sc->dev,
+                           " Tracing nid %d to out\n",
+                           j);
+               );
+               if (hdac_audio_trace_to_out(devinfo, w->nid, 0)) {
+                       HDA_BOOTVERBOSE(
+                               device_printf(devinfo->codec->sc->dev,
+                                   " nid %d is input monitor\n",
+                                       w->nid);
+                       );
+               }
+       }
+
        /* Beeper */
        HDA_BOOTVERBOSE(
                device_printf(devinfo->codec->sc->dev,
@@ -5748,6 +5756,7 @@ hdac_audio_disable_notselected(struct hd
 static void
 hdac_audio_disable_crossas(struct hdac_devinfo *devinfo)
 {
+       struct hdac_audio_as *ases = devinfo->function.audio.as;
        struct hdac_widget *w, *cw;
        struct hdac_audio_ctl *ctl;
        int i, j;
@@ -5770,7 +5779,10 @@ hdac_audio_disable_crossas(struct hdac_d
                        cw = hdac_widget_get(devinfo, w->conns[j]);
                        if (cw == NULL || w->enable == 0)
                                continue;
-                       if (cw->bindas == -2)
+                       if (cw->bindas == -2 || 
+                           ((w->pflags & HDA_ADC_MONITOR) &&
+                            cw->bindas >= 0 &&
+                            ases[cw->bindas].dir == HDA_CTL_IN))
                                continue;
                        if (w->bindas == cw->bindas &&
                            (w->bindseqmask & cw->bindseqmask) != 0)
@@ -5789,8 +5801,12 @@ hdac_audio_disable_crossas(struct hdac_d
        while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) {
                if (ctl->enable == 0 || ctl->childwidget == NULL)
                        continue;
-               if (ctl->widget->bindas == -2 ||
-                   ctl->childwidget->bindas == -2)
+               if (ctl->widget->bindas == -2) 
+                       continue;
+               if (ctl->childwidget->bindas == -2 ||
+                   ((ctl->widget->pflags & HDA_ADC_MONITOR) &&
+                    ctl->childwidget->bindas >= 0 &&
+                    ases[ctl->childwidget->bindas].dir == HDA_CTL_IN))
                        continue;
                if (ctl->widget->bindas != ctl->childwidget->bindas ||
                    (ctl->widget->bindseqmask & ctl->childwidget->bindseqmask) 
== 0) {
@@ -5909,7 +5925,7 @@ hdac_audio_ctl_source_amp(struct hdac_de
  * Find controls to control amplification for destination.
  */
 static void
-hdac_audio_ctl_dest_amp(struct hdac_devinfo *devinfo, nid_t nid,
+hdac_audio_ctl_dest_amp(struct hdac_devinfo *devinfo, nid_t nid, int index,
     int ossdev, int depth, int need)
 {
        struct hdac_audio_as *as = devinfo->function.audio.as;
@@ -5968,6 +5984,8 @@ hdac_audio_ctl_dest_amp(struct hdac_devi
                int tneed = need;
                if (w->connsenable[i] == 0)
                        continue;
+               if (index >= 0 && i != index)
+                       continue;
                ctl = hdac_audio_ctl_amp_get(devinfo, w->nid,
                    HDA_CTL_IN, i, 1);
                if (ctl) {
@@ -5977,7 +5995,7 @@ hdac_audio_ctl_dest_amp(struct hdac_devi
                                ctl->possmask |= (1 << ossdev);
                        tneed &= ~HDA_CTL_GIVE(ctl);
                }
-               hdac_audio_ctl_dest_amp(devinfo, w->conns[i], ossdev,
+               hdac_audio_ctl_dest_amp(devinfo, w->conns[i], -1, ossdev,
                    depth + 1, tneed);
        }
 }
@@ -6184,8 +6202,8 @@ hdac_audio_assign_mixers(struct hdac_dev
 {
        struct hdac_audio_as *as = devinfo->function.audio.as;
        struct hdac_audio_ctl *ctl;
-       struct hdac_widget *w;
-       int i;
+       struct hdac_widget *w, *cw;
+       int i, j;
 
        /* Assign mixers to the tree. */
        for (i = devinfo->startnode; i < devinfo->endnode; i++) {
@@ -6200,24 +6218,30 @@ hdac_audio_assign_mixers(struct hdac_dev
                                continue;
                        hdac_audio_ctl_source_amp(devinfo, w->nid, -1,
                            w->ossdev, 1, 0, 1);
-               } else if ((w->pflags & HDA_ADC_MONITOR) != 0) {
-                       if (w->ossdev < 0)
-                               continue;
-                       if (hdac_audio_ctl_source_amp(devinfo, w->nid, -1,
-                           w->ossdev, 1, 0, 1)) {
-                               /* If we are unable to control input monitor
-                                  as source - try to control it as 
destination. */
-                               hdac_audio_ctl_dest_amp(devinfo, w->nid,
-                                   w->ossdev, 0, 1);
-                       }
                } else if (w->type == 
HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT) {
-                       hdac_audio_ctl_dest_amp(devinfo, w->nid,
+                       hdac_audio_ctl_dest_amp(devinfo, w->nid, -1,
                            SOUND_MIXER_RECLEV, 0, 1);
                } else if (w->type == 
HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX &&
                    as[w->bindas].dir == HDA_CTL_OUT) {
-                       hdac_audio_ctl_dest_amp(devinfo, w->nid,
+                       hdac_audio_ctl_dest_amp(devinfo, w->nid, -1,
                            SOUND_MIXER_VOLUME, 0, 1);
                }
+               if (w->pflags & HDA_ADC_MONITOR) {
+                       for (j = 0; j < w->nconns; j++) {
+                               if (!w->connsenable[j])
+                                   continue;
+                               cw = hdac_widget_get(devinfo, w->conns[j]);
+                               if (cw == NULL || cw->enable == 0)
+                                   continue;
+                               if (cw->bindas == -1)
+                                   continue;
+                               if (cw->bindas >= 0 &&
+                                   as[cw->bindas].dir != HDA_CTL_IN)
+                                       continue;
+                               hdac_audio_ctl_dest_amp(devinfo,
+                                   w->nid, j, SOUND_MIXER_IMIX, 0, 1);
+                       }
+               }
        }
        /* Treat unrequired as possible. */
        i = 0;
@@ -7160,7 +7184,7 @@ hdac_dump_mix(struct hdac_pcm_devinfo *p
                w = hdac_widget_get(devinfo, i);
                if (w == NULL || w->enable == 0)
                        continue;
-               if ((w->pflags & HDA_ADC_MONITOR) == 0)
+               if (w->ossdev != SOUND_MIXER_IMIX)
                        continue;
                if (printed == 0) {
                        printed = 1;
@@ -8126,7 +8150,7 @@ hdac_pcm_attach(device_t dev)
                hdac_dump_ctls(pdevinfo, "Line-in Volume", SOUND_MASK_LINE);
                hdac_dump_ctls(pdevinfo, "Speaker/Beep Volume", 
SOUND_MASK_SPEAKER);
                hdac_dump_ctls(pdevinfo, "Recording Level", SOUND_MASK_RECLEV);
-               hdac_dump_ctls(pdevinfo, "Input Mix Level", SOUND_MASK_IMIX);
+               hdac_dump_ctls(pdevinfo, "Input Monitoring Level", 
SOUND_MASK_IMIX);
                hdac_dump_ctls(pdevinfo, NULL, 0);
                device_printf(dev, "\n");
        );
_______________________________________________
[email protected] mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "[email protected]"

Reply via email to