alsa-mixer: autodetect the HDMI jack PCM device
authorTanu Kaskinen <tanuk@iki.fi>
Sun, 8 Oct 2017 16:48:25 +0000 (19:48 +0300)
committerTanu Kaskinen <tanuk@iki.fi>
Tue, 13 Feb 2018 19:33:17 +0000 (21:33 +0200)
This removes the need to hardcode the PCM device index in the HDMI jack
names. The hardcoded values don't work with the Intel HDMI LPE driver.

BugLink: https://bugs.freedesktop.org/show_bug.cgi?id=100488
13 files changed:
src/modules/alsa/alsa-mixer.c
src/modules/alsa/alsa-mixer.h
src/modules/alsa/alsa-sink.c
src/modules/alsa/alsa-source.c
src/modules/alsa/mixer/paths/analog-output.conf.common
src/modules/alsa/mixer/paths/hdmi-output-0.conf
src/modules/alsa/mixer/paths/hdmi-output-1.conf
src/modules/alsa/mixer/paths/hdmi-output-2.conf
src/modules/alsa/mixer/paths/hdmi-output-3.conf
src/modules/alsa/mixer/paths/hdmi-output-4.conf
src/modules/alsa/mixer/paths/hdmi-output-5.conf
src/modules/alsa/mixer/paths/hdmi-output-6.conf
src/modules/alsa/mixer/paths/hdmi-output-7.conf

index 02ab4a611fbc355877ac30bb05435f44a301ce01..eaee7ea0a9d9acc11e40e227537a9e798f22d0da 100644 (file)
@@ -1812,12 +1812,31 @@ static int element_probe(pa_alsa_element *e, snd_mixer_t *m) {
     return 0;
 }
 
-static int jack_probe(pa_alsa_jack *j, snd_mixer_t *m) {
+static int jack_probe(pa_alsa_jack *j, pa_alsa_mapping *mapping, snd_mixer_t *m) {
     bool has_control;
 
     pa_assert(j);
     pa_assert(j->path);
 
+    if (j->append_pcm_to_name) {
+        char *new_name;
+
+        if (!mapping) {
+            /* This could also be an assertion, because this should never
+             * happen. At the time of writing, mapping can only be NULL when
+             * module-alsa-sink/source synthesizes a path, and those
+             * synthesized paths never have any jacks, so jack_probe() should
+             * never be called with a NULL mapping. */
+            pa_log("Jack %s: append_pcm_to_name is set, but mapping is NULL. Can't use this jack.", j->name);
+            return -1;
+        }
+
+        new_name = pa_sprintf_malloc("%s,pcm=%i Jack", j->name, mapping->hw_device_index);
+        pa_xfree(j->alsa_name);
+        j->alsa_name = new_name;
+        j->append_pcm_to_name = false;
+    }
+
     has_control = pa_alsa_mixer_find(m, j->alsa_name, 0) != NULL;
     pa_alsa_jack_set_has_control(j, has_control);
 
@@ -2326,6 +2345,30 @@ static int jack_parse_state(pa_config_parser_state *state) {
     return 0;
 }
 
+static int jack_parse_append_pcm_to_name(pa_config_parser_state *state) {
+    pa_alsa_path *path;
+    pa_alsa_jack *jack;
+    int b;
+
+    pa_assert(state);
+
+    path = state->userdata;
+    if (!(jack = jack_get(path, state->section))) {
+        pa_log("[%s:%u] Option 'append_pcm_to_name' not expected in section '%s'",
+               state->filename, state->lineno, state->section);
+        return -1;
+    }
+
+    b = pa_parse_boolean(state->rvalue);
+    if (b < 0) {
+        pa_log("[%s:%u] Invalid value for 'append_pcm_to_name': %s", state->filename, state->lineno, state->rvalue);
+        return -1;
+    }
+
+    jack->append_pcm_to_name = b;
+    return 0;
+}
+
 static int element_set_option(pa_alsa_element *e, snd_mixer_t *m, int alsa_idx) {
     snd_mixer_selem_id_t *sid;
     snd_mixer_elem_t *me;
@@ -2534,6 +2577,7 @@ pa_alsa_path* pa_alsa_path_new(const char *paths_dir, const char *fname, pa_alsa
         /* [Jack ...] */
         { "state.plugged",       jack_parse_state,                  NULL, NULL },
         { "state.unplugged",     jack_parse_state,                  NULL, NULL },
+        { "append-pcm-to-name",  jack_parse_append_pcm_to_name,     NULL, NULL },
 
         /* [Element ...] */
         { "switch",              element_parse_switch,              NULL, NULL },
@@ -2746,7 +2790,7 @@ static void path_create_settings(pa_alsa_path *p) {
     element_create_settings(p->elements, NULL);
 }
 
-int pa_alsa_path_probe(pa_alsa_path *p, snd_mixer_t *m, bool ignore_dB) {
+int pa_alsa_path_probe(pa_alsa_path *p, pa_alsa_mapping *mapping, snd_mixer_t *m, bool ignore_dB) {
     pa_alsa_element *e;
     pa_alsa_jack *j;
     double min_dB[PA_CHANNEL_POSITION_MAX], max_dB[PA_CHANNEL_POSITION_MAX];
@@ -2766,7 +2810,7 @@ int pa_alsa_path_probe(pa_alsa_path *p, snd_mixer_t *m, bool ignore_dB) {
     pa_log_debug("Probing path '%s'", p->name);
 
     PA_LLIST_FOREACH(j, p->jacks) {
-        if (jack_probe(j, m) < 0) {
+        if (jack_probe(j, mapping, m) < 0) {
             p->supported = false;
             pa_log_debug("Probe of jack '%s' failed.", j->alsa_name);
             return -1;
@@ -3968,9 +4012,8 @@ static void mapping_paths_probe(pa_alsa_mapping *m, pa_alsa_profile *profile,
     }
 
     PA_HASHMAP_FOREACH(p, ps->paths, state) {
-        if (pa_alsa_path_probe(p, mixer_handle, m->profile_set->ignore_dB) < 0) {
+        if (pa_alsa_path_probe(p, m, mixer_handle, m->profile_set->ignore_dB) < 0)
             pa_hashmap_remove(ps->paths, p);
-        }
     }
 
     path_set_condense(ps, mixer_handle);
index 0f1c5b91f69828c7dd6072708c15f9bcd246d7c1..c64f42b706e08aa622dcd10aad9e39e88c69d305 100644 (file)
@@ -171,6 +171,8 @@ struct pa_alsa_jack {
 
     pa_dynarray *ucm_devices; /* pa_alsa_ucm_device */
     pa_dynarray *ucm_hw_mute_devices; /* pa_alsa_ucm_device */
+
+    bool append_pcm_to_name;
 };
 
 pa_alsa_jack *pa_alsa_jack_new(pa_alsa_path *path, const char *name);
@@ -234,7 +236,7 @@ void pa_alsa_element_dump(pa_alsa_element *e);
 
 pa_alsa_path *pa_alsa_path_new(const char *paths_dir, const char *fname, pa_alsa_direction_t direction);
 pa_alsa_path *pa_alsa_path_synthesize(const char *element, pa_alsa_direction_t direction);
-int pa_alsa_path_probe(pa_alsa_path *p, snd_mixer_t *m, bool ignore_dB);
+int pa_alsa_path_probe(pa_alsa_path *p, pa_alsa_mapping *mapping, snd_mixer_t *m, bool ignore_dB);
 void pa_alsa_path_dump(pa_alsa_path *p);
 int pa_alsa_path_get_volume(pa_alsa_path *p, snd_mixer_t *m, const pa_channel_map *cm, pa_cvolume *v);
 int pa_alsa_path_get_mute(pa_alsa_path *path, snd_mixer_t *m, bool *muted);
index a80caab2e7945b76a5eee7e386c585cac4b47860..8786c98b7046647b11a01d3f1efbdb766427e3f7 100644 (file)
@@ -1922,7 +1922,7 @@ static void find_mixer(struct userdata *u, pa_alsa_mapping *mapping, const char
         if (!(u->mixer_path = pa_alsa_path_synthesize(element, PA_ALSA_DIRECTION_OUTPUT)))
             goto fail;
 
-        if (pa_alsa_path_probe(u->mixer_path, u->mixer_handle, ignore_dB) < 0)
+        if (pa_alsa_path_probe(u->mixer_path, NULL, u->mixer_handle, ignore_dB) < 0)
             goto fail;
 
         pa_log_debug("Probed mixer path %s:", u->mixer_path->name);
index 3f87a4792da2dbe99f1da747688c7392b2725f37..ba369284c29c0bf020e9b1d63d58dd9ddcccdedb 100644 (file)
@@ -1617,7 +1617,7 @@ static void find_mixer(struct userdata *u, pa_alsa_mapping *mapping, const char
         if (!(u->mixer_path = pa_alsa_path_synthesize(element, PA_ALSA_DIRECTION_INPUT)))
             goto fail;
 
-        if (pa_alsa_path_probe(u->mixer_path, u->mixer_handle, ignore_dB) < 0)
+        if (pa_alsa_path_probe(u->mixer_path, NULL, u->mixer_handle, ignore_dB) < 0)
             goto fail;
 
         pa_log_debug("Probed mixer path %s:", u->mixer_path->name);
index 17b45278a3d5f0a7526a9c92848536d3d79491e5..baf37660e9663b30d73ce87d979a1cb5da729c31 100644 (file)
 ;                                      # the required-any are present.
 ; state.plugged = yes | no | unknown   # Normally a plugged jack would mean the port becomes available, and an unplugged means it's
 ; state.unplugged = yes | no | unknown # unavailable, but the port status can be overridden by specifying state.plugged and/or state.unplugged.
+; append-pcm-to-name = no | yes        # Add ",pcm=N" to the jack name? N is the hw PCM device index. HDMI jacks have
+;                                      # the PCM device index in their name, but different drivers use different
+;                                      # numbering schemes, so we can't hardcode the full jack name in our configuration
+;                                      # files.
 
 [Element PCM]
 switch = mute
index 331014709a3e4f86c700fd119b5667440195176b..a87205cea51ce580b67c13a05919dda716f48b64 100644 (file)
@@ -6,5 +6,6 @@ eld-device = 3
 [Properties]
 device.icon_name = video-display
 
-[Jack HDMI/DP,pcm=3]
+[Jack HDMI/DP]
+append-pcm-to-name = yes
 required = ignore
index d81ee789ca4e3ea8de9977fcb3d72d425ac0c7cc..b513ffd70318274d0c93fc10ef6c7c7a445b4e82 100644 (file)
@@ -6,5 +6,6 @@ eld-device = 7
 [Properties]
 device.icon_name = video-display
 
-[Jack HDMI/DP,pcm=7]
+[Jack HDMI/DP]
+append-pcm-to-name = yes
 required = ignore
index 349812fc2e2bb9a8a8e38d5cdf60365c72343a71..a2386650e42c5adf67677b6e14a5e0e16fac4320 100644 (file)
@@ -6,5 +6,6 @@ eld-device = 8
 [Properties]
 device.icon_name = video-display
 
-[Jack HDMI/DP,pcm=8]
+[Jack HDMI/DP]
+append-pcm-to-name = yes
 required = ignore
index 81463c9463e8812b0c27d470c251c1c748dbb6ae..edceb36e162c166d0b4b00e91f03a3454de43fda 100644 (file)
@@ -6,5 +6,6 @@ eld-device = 9
 [Properties]
 device.icon_name = video-display
 
-[Jack HDMI/DP,pcm=9]
+[Jack HDMI/DP]
+append-pcm-to-name = yes
 required = ignore
index d61ec7547f1e4512e691be2372fd1e1927aa82c4..0d1401eef49dd52e091dde70bf53e3b9e3c64e91 100644 (file)
@@ -6,5 +6,6 @@ eld-device = 10
 [Properties]
 device.icon_name = video-display
 
-[Jack HDMI/DP,pcm=10]
+[Jack HDMI/DP]
+append-pcm-to-name = yes
 required = ignore
index 02c15e893354fed833ed831711f4ee03952acf41..883cccc203f9a477f20089720e94cb384f5a3cc4 100644 (file)
@@ -6,5 +6,6 @@ eld-device = 11
 [Properties]
 device.icon_name = video-display
 
-[Jack HDMI/DP,pcm=11]
+[Jack HDMI/DP]
+append-pcm-to-name = yes
 required = ignore
index 188a1adb3848758861053b1d8cfe54eedafe92a4..d8ac2f55c0de2de4537f2173924e1a072e099d15 100644 (file)
@@ -6,5 +6,6 @@ eld-device = 12
 [Properties]
 device.icon_name = video-display
 
-[Jack HDMI/DP,pcm=12]
+[Jack HDMI/DP]
+append-pcm-to-name = yes
 required = ignore
index 80f4e3722456969f6accde196b99a4f8d4c27645..dd090855f204bf510375eb69da33aa264d8b8ae2 100644 (file)
@@ -6,5 +6,6 @@ eld-device = 13
 [Properties]
 device.icon_name = video-display
 
-[Jack HDMI/DP,pcm=13]
+[Jack HDMI/DP]
+append-pcm-to-name = yes
 required = ignore