Received: by 2002:a05:6a10:9848:0:0:0:0 with SMTP id x8csp610083pxf; Thu, 25 Mar 2021 10:04:26 -0700 (PDT) X-Google-Smtp-Source: ABdhPJweH4BD8EynNqVzYyeo7AmfwhdKLryeaZKjBrhOmPWg95sSoc3bPUGIb/+qVWqAoGKRbWwO X-Received: by 2002:a17:906:d8d3:: with SMTP id re19mr10693438ejb.440.1616691866232; Thu, 25 Mar 2021 10:04:26 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1616691866; cv=none; d=google.com; s=arc-20160816; b=MKnnpOUxwcXnrehslRxzhk1GZz5Kd4pVqbHxlZ29BH0EzjalXO0tA5oXJ/dWWhC07o Ssi5UuH2MP/lOH/Aip6tHUXZssM6fWrxejy5rR/XwTpHdS1uCpxqobLflj/3skPDgWd1 L8J85/6Wn4KE6c4OIOGtwM7U7dDkFyMy49mt/ziMDkqRVxTKrEkuZQEplP9shP48/Ehw mhh8qAjbX5XfZA8sXdPPJgkqH9JL8edOn189biyMT2p6kIxJN5imUtZm6pzBWB2vNeER mT8ZvE3etNcu8cu89UEVl6eMQzlgsD3r0EFuUoPsUjJXFMaNRWtNeRDdzxnzww2dXH+O pbsQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from; bh=I4KTNY508hszX1qBK2RqDqa134HwyekVJYls4ZzQH9c=; b=GrWtQSAZKEZExUCKgQC3Ju25zksW/+AgP+0yW5HKIk6Hy1gJ2hTqnLZHI9AdiwlOhx C1k+6jDbmrqFQnItXSMx/RWbY/KX/o0SGXv+zRH8abYITZMJ1M+KdtNuOD5EsvAk90P1 B16K0adm6TIBChR8b6xkglht9Cp9JFsDI00wsx25/U+xQqMaEmRpJmMNZcGj7Gxj5CU5 MACO3moheJdtc/uBwqvjGWa6/YeFGn6e6owPdS5tO8GVGxFs8PqTj4oDtRbld59sYsRP oyVDyRWeqp000Pr1MPiAh6p8GLYTa8xFV/SfPTe9FemFLHllibxoS9gXS6+zjFczTGO8 rKkw== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=canonical.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id j20si4799952ejs.411.2021.03.25.10.04.00; Thu, 25 Mar 2021 10:04:26 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=canonical.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229904AbhCYRAW (ORCPT + 99 others); Thu, 25 Mar 2021 13:00:22 -0400 Received: from youngberry.canonical.com ([91.189.89.112]:35540 "EHLO youngberry.canonical.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229642AbhCYRAP (ORCPT ); Thu, 25 Mar 2021 13:00:15 -0400 Received: from 1-171-92-165.dynamic-ip.hinet.net ([1.171.92.165] helo=localhost) by youngberry.canonical.com with esmtpsa (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.86_2) (envelope-from ) id 1lPTKZ-0003Ut-Ua; Thu, 25 Mar 2021 16:59:36 +0000 From: Kai-Heng Feng To: tiwai@suse.com Cc: Kai-Heng Feng , Takashi Iwai , Jaroslav Kysela , Joe Perches , Mark Brown , Chris Chiu , Tom Yan , Lars-Peter Clausen , Thomas Ebeling , =?UTF-8?q?Franti=C5=A1ek=20Ku=C4=8Dera?= , Xiyu Yang , Olivia Mackintosh , alsa-devel@alsa-project.org (moderated list:SOUND), linux-kernel@vger.kernel.org (open list) Subject: [PATCH v3 2/2] ALSA: usb-audio: Check connector value on resume Date: Fri, 26 Mar 2021 00:59:13 +0800 Message-Id: <20210325165918.22593-2-kai.heng.feng@canonical.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20210325165918.22593-1-kai.heng.feng@canonical.com> References: <20210325165918.22593-1-kai.heng.feng@canonical.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Rear Mic on Lenovo P620 cannot record after S3, despite that there's no error and the other two functions of the USB audio, Line In and Line Out, work just fine. The mic starts to work again after running userspace app like "alsactl store". Following the lead, the evidence shows that as soon as connector status is queried, the mic can work again. So also check connector value on resume to "wake up" the USB audio to make it functional. This can be device specific, however I think this generic approach may benefit more than one device. Now the resume callback checks connector, and a new callback, reset_resume, to also restore switches and volumes. Suggested-by: Takashi Iwai Signed-off-by: Kai-Heng Feng --- v3: - New callback to handle resume and reset-resume separately. v2: - Remove reset-resume. - Fold the connector checking to the mixer resume callback. sound/usb/mixer.c | 44 +++++++++++++++++++++++++++++++--------- sound/usb/mixer.h | 1 + sound/usb/mixer_quirks.c | 2 +- 3 files changed, 36 insertions(+), 11 deletions(-) diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c index 5a2d9a768f70..2faf5767c7f8 100644 --- a/sound/usb/mixer.c +++ b/sound/usb/mixer.c @@ -3631,20 +3631,43 @@ static int restore_mixer_value(struct usb_mixer_elem_list *list) return 0; } +static int default_mixer_resume(struct usb_mixer_elem_list *list) +{ + struct usb_mixer_elem_info *cval = mixer_elem_list_to_info(list); + + /* get connector value to "wake up" the USB audio */ + if (cval->val_type == USB_MIXER_BOOLEAN && cval->channels == 1) + get_connector_value(cval, NULL, NULL); + + return 0; +} + +static int default_mixer_reset_resume(struct usb_mixer_elem_list *list) +{ + int err = default_mixer_resume(list); + + if (err < 0) + return err; + return restore_mixer_value(list); +} + int snd_usb_mixer_resume(struct usb_mixer_interface *mixer, bool reset_resume) { struct usb_mixer_elem_list *list; + usb_mixer_elem_resume_func_t f; int id, err; - if (reset_resume) { - /* restore cached mixer values */ - for (id = 0; id < MAX_ID_ELEMS; id++) { - for_each_mixer_elem(list, mixer, id) { - if (list->resume) { - err = list->resume(list); - if (err < 0) - return err; - } + /* restore cached mixer values */ + for (id = 0; id < MAX_ID_ELEMS; id++) { + for_each_mixer_elem(list, mixer, id) { + if (reset_resume) + f = list->reset_resume; + else + f = list->resume; + if (f) { + err = f(list); + if (err < 0) + return err; } } } @@ -3663,6 +3686,7 @@ void snd_usb_mixer_elem_init_std(struct usb_mixer_elem_list *list, list->id = unitid; list->dump = snd_usb_mixer_dump_cval; #ifdef CONFIG_PM - list->resume = restore_mixer_value; + list->resume = default_mixer_resume; + list->reset_resume = default_mixer_reset_resume; #endif } diff --git a/sound/usb/mixer.h b/sound/usb/mixer.h index c29e27ac43a7..e5a01f17bf3c 100644 --- a/sound/usb/mixer.h +++ b/sound/usb/mixer.h @@ -69,6 +69,7 @@ struct usb_mixer_elem_list { bool is_std_info; usb_mixer_elem_dump_func_t dump; usb_mixer_elem_resume_func_t resume; + usb_mixer_elem_resume_func_t reset_resume; }; /* iterate over mixer element list of the given unit id */ diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c index ffd922327ae4..b7f9c2fded05 100644 --- a/sound/usb/mixer_quirks.c +++ b/sound/usb/mixer_quirks.c @@ -151,7 +151,7 @@ static int add_single_ctl_with_resume(struct usb_mixer_interface *mixer, *listp = list; list->mixer = mixer; list->id = id; - list->resume = resume; + list->reset_resume = resume; kctl = snd_ctl_new1(knew, list); if (!kctl) { kfree(list); -- 2.30.2