summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2013-02-11 12:28:45 +0100
committerTakashi Iwai <tiwai@suse.de>2013-02-21 17:52:17 +0100
commitf5f45589f81c46d4ca4cbbe089441a0f7ac5e197 (patch)
treed85cec4c9f4200a8cda078c4657edf3ebf6871be
parent8c6da54073b2c966d9a4e137ba4d521eac92816f (diff)
downloadalsa-lib-f5f45589f81c46d4ca4cbbe089441a0f7ac5e197.tar.gz
Add workaround for conflicting IEC958 controls for HD-audio
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>
-rw-r--r--src/conf/cards/HDA-Intel.conf16
-rw-r--r--src/control/setup.c19
2 files changed, 32 insertions, 3 deletions
diff --git a/src/conf/cards/HDA-Intel.conf b/src/conf/cards/HDA-Intel.conf
index d4f2667e..3957c124 100644
--- a/src/conf/cards/HDA-Intel.conf
+++ b/src/conf/cards/HDA-Intel.conf
@@ -113,6 +113,22 @@ HDA-Intel.pcm.iec958.0 {
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
preserve true
value [ $AES0 $AES1 $AES2 $AES3 ]
diff --git a/src/control/setup.c b/src/control/setup.c
index bd3599de..f23bf2c9 100644
--- a/src/control/setup.c
+++ b/src/control/setup.c
@@ -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;