]> git.alsa-project.org Git - alsa-lib.git/commitdiff
Add workaround for conflicting IEC958 controls for HD-audio
authorTakashi Iwai <tiwai@suse.de>
Mon, 11 Feb 2013 11:28:45 +0000 (12:28 +0100)
committerTakashi Iwai <tiwai@suse.de>
Thu, 21 Feb 2013 16:52:17 +0000 (17:52 +0100)
When both an SPDIF and an HDMI output are present on HD-audio, both
try to access IEC958 controls with index=0 although one of them must
be wrong.  For avoiding this conflict, the recent kernel code (3.9 and
3.8 stable) moves the IEC958 controls of an SPDIF with index=16 once
when the conflict happens.

In this patch, the corresponding support is added in alsa-lib side.
The new "skip_rest" boolean flag is added to the hooked element
definition which indicates that the rest of element array will be
ignored once when this element is present and evaluated.  With this
new flag, the HD-audio config takes index=16 primarily, then take
index=0 as fallback.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
src/conf/cards/HDA-Intel.conf
src/control/setup.c

index d4f2667ebbf4dcc7396ba2fb1c77ad7924236168..3957c124d0357fabe4838951e1634d35668e9d8d 100644 (file)
@@ -111,6 +111,22 @@ HDA-Intel.pcm.iec958.0 {
                hooks.0 {
                        type ctl_elems
                        hook_args [
+                       {
+                               name "IEC958 Playback Default"
+                               index 16
+                               optional true
+                               lock true
+                               preserve true
+                               value [ $AES0 $AES1 $AES2 $AES3 ]
+                       }
+                       {
+                               name "IEC958 Playback Switch"
+                               index 16
+                               optional true
+                               value true
+                               # if this element is present, skip the rest
+                               skip_rest true
+                       }
                        {
                                name "IEC958 Playback Default"
                                lock true
index bd3599de58e141823ea676aa04a8bdd45b3e0b6d..f23bf2c90bce7471aa741c7d90961aad7a2b1420 100644 (file)
@@ -396,7 +396,7 @@ static int snd_config_get_ctl_elem_value(snd_config_t *conf,
        return 0;
 }
 
-static int add_elem(snd_sctl_t *h, snd_config_t *_conf, snd_config_t *private_data)
+static int add_elem(snd_sctl_t *h, snd_config_t *_conf, snd_config_t *private_data, int *quit)
 {
        snd_config_t *conf;
        snd_config_iterator_t i, next;
@@ -408,6 +408,7 @@ static int add_elem(snd_sctl_t *h, snd_config_t *_conf, snd_config_t *private_da
        int lock = 0;
        int preserve = 0;
        int optional = 0;
+       int skip_rest = 0;
        snd_config_t *value = NULL, *mask = NULL;
        snd_sctl_elem_t *elem = NULL;
        int err;
@@ -491,6 +492,13 @@ static int add_elem(snd_sctl_t *h, snd_config_t *_conf, snd_config_t *private_da
                        optional = err;
                        continue;
                }
+               if (strcmp(id, "skip_rest") == 0) {
+                       err = snd_config_get_bool(n);
+                       if (err < 0)
+                               goto _err;
+                       skip_rest = err;
+                       continue;
+               }
                SNDERR("Unknown field %s", id);
                return -EINVAL;
        }
@@ -539,6 +547,9 @@ static int add_elem(snd_sctl_t *h, snd_config_t *_conf, snd_config_t *private_da
                if (! optional)
                        SNDERR("Cannot obtain info for CTL elem (%s,'%s',%li,%li,%li): %s", snd_ctl_elem_iface_name(iface), name, index, device, subdevice, snd_strerror(err));
                goto _err;
+       } else {
+               if (skip_rest)
+                       *quit = 1;
        }
        snd_ctl_elem_value_set_id(elem->val, elem->id);
        snd_ctl_elem_value_set_id(elem->old, elem->id);
@@ -594,7 +605,7 @@ int snd_sctl_build(snd_sctl_t **sctl, snd_ctl_t *handle, snd_config_t *conf, snd
 {
        snd_sctl_t *h;
        snd_config_iterator_t i, next;
-       int err;
+       int err, quit = 0;
 
        assert(sctl);
        assert(handle);
@@ -614,11 +625,13 @@ int snd_sctl_build(snd_sctl_t **sctl, snd_ctl_t *handle, snd_config_t *conf, snd
        INIT_LIST_HEAD(&h->elems);
        snd_config_for_each(i, next, conf) {
                snd_config_t *n = snd_config_iterator_entry(i);
-               err = add_elem(h, n, private_data);
+               err = add_elem(h, n, private_data, &quit);
                if (err < 0) {
                        free_elems(h);
                        return err;
                }
+               if (quit)
+                       break;
        }
        *sctl = h;
        return 0;