diff options
author | Ben Zhang <benzh@chromium.org> | 2018-09-20 15:18:34 -0400 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2018-09-21 03:38:16 -0700 |
commit | b688036e050b46e4cfc1d38b04667f5af55beaae (patch) | |
tree | 0f7383f8736aecf7160b9ceb6db0f7339101bd6c | |
parent | 2f09bae8667317ae23b7407e0fbf3916af847876 (diff) | |
download | adhd-b688036e050b46e4cfc1d38b04667f5af55beaae.tar.gz |
CRAS: alsa_jack - Monitor UAC2 jack controls
With commit 5a222e849452 ("ALSA: usb-audio: UAC2 jack detection"),
the usb card for a supported UAC2 device will have boolean kcontrols
named "* - Input Jack" and "* - Output Jack" exposing jack status,
where * is the usb terminal name.
If the device provides a string in iTerminal, it'll be used as the
terminal name. Otherwise a standard name is given based on wTerminalType.
See sound/usb/mixer.c get_term_name for the complete list.
Common ones we are interested in are "Headset", "Headphone", "Mic",
"Speaker".
This patch adds the jack names so CRAS can watch the kcontrols for
plug/unplug event.
BUG=b:74149899
TEST=Test dongle with UAC2 jack detect with various headsets on meowth.
Unplug headset but keep usb dongle attached, cras_test_client --dump_s
shows the correct ionode plug status for the usb card.
Test dongles without UAC2 jack detect and verify ionode is set to
plugged by default.
Change-Id: Iba19612841dad5d764b08715a791d1ad64f9e541
Signed-off-by: Ben Zhang <benzh@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/1237315
Reviewed-by: Dylan Reid <dgreid@chromium.org>
-rw-r--r-- | cras/src/server/cras_alsa_io.c | 27 | ||||
-rw-r--r-- | cras/src/server/cras_alsa_jack.c | 18 |
2 files changed, 40 insertions, 5 deletions
diff --git a/cras/src/server/cras_alsa_io.c b/cras/src/server/cras_alsa_io.c index f525c89f..3dafb50e 100644 --- a/cras/src/server/cras_alsa_io.c +++ b/cras/src/server/cras_alsa_io.c @@ -1378,6 +1378,21 @@ static struct alsa_input_node *get_input_node_from_jack( return ain; } +static const struct cras_alsa_jack *get_jack_from_node(struct cras_ionode *node) +{ + const struct cras_alsa_jack *jack = NULL; + + if (node == NULL) + return NULL; + + if (node->dev->direction == CRAS_STREAM_OUTPUT) + jack = ((struct alsa_output_node *)node)->jack; + else if (node->dev->direction == CRAS_STREAM_INPUT) + jack = ((struct alsa_input_node *)node)->jack; + + return jack; +} + /* * Returns the dsp name specified in the ucm config. If there is a dsp * name specified for the jack of the active node, use that. Otherwise @@ -2164,8 +2179,10 @@ int alsa_iodev_legacy_complete_init(struct cras_iodev *iodev) first_plugged_node(&aio->base), 0); - /* Set plugged for the first USB device per card when it appears. */ - if (aio->card_type == ALSA_CARD_TYPE_USB && is_first) + /* Set plugged for the first USB device per card when it appears if + * there is no jack reporting plug status. */ + if (aio->card_type == ALSA_CARD_TYPE_USB && is_first && + !get_jack_from_node(iodev->active_node)) cras_iodev_set_node_attr(iodev->active_node, IONODE_ATTR_PLUGGED, 1); @@ -2251,8 +2268,10 @@ void alsa_iodev_ucm_complete_init(struct cras_iodev *iodev) first_plugged_node(&aio->base), 0); - /* Set plugged for the first USB device per card when it appears. */ - if (aio->card_type == ALSA_CARD_TYPE_USB && aio->is_first) + /* Set plugged for the first USB device per card when it appears if + * there is no jack reporting plug status. */ + if (aio->card_type == ALSA_CARD_TYPE_USB && aio->is_first && + !get_jack_from_node(iodev->active_node)) cras_iodev_set_node_attr(iodev->active_node, IONODE_ATTR_PLUGGED, 1); diff --git a/cras/src/server/cras_alsa_jack.c b/cras/src/server/cras_alsa_jack.c index 70cad544..b74af25d 100644 --- a/cras/src/server/cras_alsa_jack.c +++ b/cras/src/server/cras_alsa_jack.c @@ -74,6 +74,12 @@ struct cras_gpio_jack { * edid_file - File to read the EDID from (if available, HDMI only). * display_info_timer - Timer used to poll display info for HDMI jacks. * display_info_retries - Number of times to retry reading display info. + * + * mixer_output/mixer_input fields are only used to find the node for this + * jack. These are not used for setting volume or mute. There should be a + * 1:1 map between node and jack. node->jack follows the pointer; jack->node + * is done by either searching node->jack pointers or searching the node that + * has the same mixer_control as the jack. */ struct cras_alsa_jack { unsigned is_gpio; /* !0 -> 'gpio' valid @@ -863,6 +869,15 @@ static int is_jack_control_in_list(const char * const *list, return 0; } +/* Check if the given name is a jack created for the connector control of a + * input/output terminal entity on a USB Audio Class 2.0 device. */ +static int is_jack_uac2(const char *jack_name, + enum CRAS_STREAM_DIRECTION direction) +{ + return jack_matches_regex(jack_name, direction == CRAS_STREAM_OUTPUT ? + "^.* - Output Jack$" : "^.* - Input Jack$"); +} + /* Looks for any JACK controls. Monitors any found controls for changes and * decides to route based on plug/unlpug events. */ static int find_jack_controls(struct cras_alsa_jack_list *jack_list) @@ -904,7 +919,8 @@ static int find_jack_controls(struct cras_alsa_jack_list *jack_list) if (iface != SND_CTL_ELEM_IFACE_CARD) continue; name = snd_hctl_elem_get_name(elem); - if (!is_jack_control_in_list(jack_names, num_jack_names, name)) + if (!is_jack_control_in_list(jack_names, num_jack_names, name) && + !is_jack_uac2(name, jack_list->direction)) continue; if (hctl_jack_device_index(name) != jack_list->device_index) continue; |