summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Zhang <benzh@chromium.org>2018-09-20 15:18:34 -0400
committerchrome-bot <chrome-bot@chromium.org>2018-09-21 03:38:16 -0700
commitb688036e050b46e4cfc1d38b04667f5af55beaae (patch)
tree0f7383f8736aecf7160b9ceb6db0f7339101bd6c
parent2f09bae8667317ae23b7407e0fbf3916af847876 (diff)
downloadadhd-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.c27
-rw-r--r--cras/src/server/cras_alsa_jack.c18
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;