linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 1/2] ALSA: usb-audio: Carve out connector value checking into a helper
@ 2021-03-25 12:12 Kai-Heng Feng
  2021-03-25 12:12 ` [PATCH v2 2/2] ALSA: usb-audio: Check connector value on resume Kai-Heng Feng
  0 siblings, 1 reply; 6+ messages in thread
From: Kai-Heng Feng @ 2021-03-25 12:12 UTC (permalink / raw)
  To: tiwai
  Cc: Kai-Heng Feng, Jaroslav Kysela, Mark Brown, Tom Yan, Joe Perches,
	Lars-Peter Clausen, Chris Chiu, moderated list:SOUND, open list

This is preparation for next patch, no functional change intended.

Signed-off-by: Kai-Heng Feng <kai.heng.feng@canonical.com>
---
v2:
 - Only return early when ret < 0.

 sound/usb/mixer.c | 34 +++++++++++++++++++++++++---------
 1 file changed, 25 insertions(+), 9 deletions(-)

diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c
index b004b2e63a5d..5a2d9a768f70 100644
--- a/sound/usb/mixer.c
+++ b/sound/usb/mixer.c
@@ -1446,13 +1446,11 @@ static int mixer_ctl_master_bool_get(struct snd_kcontrol *kcontrol,
 	return 0;
 }
 
-/* get the connectors status and report it as boolean type */
-static int mixer_ctl_connector_get(struct snd_kcontrol *kcontrol,
-				   struct snd_ctl_elem_value *ucontrol)
+static int get_connector_value(struct usb_mixer_elem_info *cval,
+			       char *name, int *val)
 {
-	struct usb_mixer_elem_info *cval = kcontrol->private_data;
 	struct snd_usb_audio *chip = cval->head.mixer->chip;
-	int idx = 0, validx, ret, val;
+	int idx = 0, validx, ret;
 
 	validx = cval->control << 8 | 0;
 
@@ -1467,21 +1465,24 @@ static int mixer_ctl_connector_get(struct snd_kcontrol *kcontrol,
 		ret = snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), UAC2_CS_CUR,
 				      USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
 				      validx, idx, &uac2_conn, sizeof(uac2_conn));
-		val = !!uac2_conn.bNrChannels;
+		if (val)
+			*val = !!uac2_conn.bNrChannels;
 	} else { /* UAC_VERSION_3 */
 		struct uac3_insertion_ctl_blk uac3_conn;
 
 		ret = snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), UAC2_CS_CUR,
 				      USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
 				      validx, idx, &uac3_conn, sizeof(uac3_conn));
-		val = !!uac3_conn.bmConInserted;
+		if (val)
+			*val = !!uac3_conn.bmConInserted;
 	}
 
 	snd_usb_unlock_shutdown(chip);
 
 	if (ret < 0) {
-		if (strstr(kcontrol->id.name, "Speaker")) {
-			ucontrol->value.integer.value[0] = 1;
+		if (name && strstr(name, "Speaker")) {
+			if (val)
+				*val = 1;
 			return 0;
 		}
 error:
@@ -1491,6 +1492,21 @@ static int mixer_ctl_connector_get(struct snd_kcontrol *kcontrol,
 		return filter_error(cval, ret);
 	}
 
+	return ret;
+}
+
+/* get the connectors status and report it as boolean type */
+static int mixer_ctl_connector_get(struct snd_kcontrol *kcontrol,
+				   struct snd_ctl_elem_value *ucontrol)
+{
+	struct usb_mixer_elem_info *cval = kcontrol->private_data;
+	int ret, val;
+
+	ret = get_connector_value(cval, kcontrol->id.name, &val);
+
+	if (ret < 0)
+		return ret;
+
 	ucontrol->value.integer.value[0] = val;
 	return 0;
 }
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH v2 2/2] ALSA: usb-audio: Check connector value on resume
  2021-03-25 12:12 [PATCH v2 1/2] ALSA: usb-audio: Carve out connector value checking into a helper Kai-Heng Feng
@ 2021-03-25 12:12 ` Kai-Heng Feng
  2021-03-25 13:41   ` Takashi Iwai
  0 siblings, 1 reply; 6+ messages in thread
From: Kai-Heng Feng @ 2021-03-25 12:12 UTC (permalink / raw)
  To: tiwai
  Cc: Kai-Heng Feng, Jaroslav Kysela, Pavel Skripkin, Chris Chiu,
	Mark Brown, Lars-Peter Clausen, Tom Yan, Joe Perches,
	moderated list:SOUND, open list

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.

While at it, also remove reset-resume path to consolidate mixer resume
path.

Signed-off-by: Kai-Heng Feng <kai.heng.feng@canonical.com>
---
v2:
 - Remove reset-resume.
 - Fold the connector checking to the mixer resume callback.

 sound/usb/card.c  | 16 +++-------------
 sound/usb/mixer.c | 27 +++++++++++++++------------
 sound/usb/mixer.h |  2 +-
 3 files changed, 19 insertions(+), 26 deletions(-)

diff --git a/sound/usb/card.c b/sound/usb/card.c
index 0826a437f8fc..552a57c00799 100644
--- a/sound/usb/card.c
+++ b/sound/usb/card.c
@@ -1014,7 +1014,7 @@ static int usb_audio_suspend(struct usb_interface *intf, pm_message_t message)
 	return 0;
 }
 
-static int __usb_audio_resume(struct usb_interface *intf, bool reset_resume)
+static int usb_audio_resume(struct usb_interface *intf)
 {
 	struct snd_usb_audio *chip = usb_get_intfdata(intf);
 	struct snd_usb_stream *as;
@@ -1040,7 +1040,7 @@ static int __usb_audio_resume(struct usb_interface *intf, bool reset_resume)
 	 * we just notify and restart the mixers
 	 */
 	list_for_each_entry(mixer, &chip->mixer_list, list) {
-		err = snd_usb_mixer_resume(mixer, reset_resume);
+		err = snd_usb_mixer_resume(mixer);
 		if (err < 0)
 			goto err_out;
 	}
@@ -1060,16 +1060,6 @@ static int __usb_audio_resume(struct usb_interface *intf, bool reset_resume)
 	atomic_dec(&chip->active); /* allow autopm after this point */
 	return err;
 }
-
-static int usb_audio_resume(struct usb_interface *intf)
-{
-	return __usb_audio_resume(intf, false);
-}
-
-static int usb_audio_reset_resume(struct usb_interface *intf)
-{
-	return __usb_audio_resume(intf, true);
-}
 #else
 #define usb_audio_suspend	NULL
 #define usb_audio_resume	NULL
@@ -1095,7 +1085,7 @@ static struct usb_driver usb_audio_driver = {
 	.disconnect =	usb_audio_disconnect,
 	.suspend =	usb_audio_suspend,
 	.resume =	usb_audio_resume,
-	.reset_resume =	usb_audio_reset_resume,
+	.reset_resume =	usb_audio_resume,
 	.id_table =	usb_audio_ids,
 	.supports_autosuspend = 1,
 };
diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c
index 5a2d9a768f70..7468c8d2b158 100644
--- a/sound/usb/mixer.c
+++ b/sound/usb/mixer.c
@@ -3601,11 +3601,16 @@ int snd_usb_mixer_suspend(struct usb_mixer_interface *mixer)
 	return 0;
 }
 
-static int restore_mixer_value(struct usb_mixer_elem_list *list)
+static int resume_mixer(struct usb_mixer_elem_list *list)
 {
 	struct usb_mixer_elem_info *cval = mixer_elem_list_to_info(list);
 	int c, err, idx;
 
+	/* 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);
+
+	/* restore other mixer value */
 	if (cval->cmask) {
 		idx = 0;
 		for (c = 0; c < MAX_CHANNELS; c++) {
@@ -3631,20 +3636,18 @@ static int restore_mixer_value(struct usb_mixer_elem_list *list)
 	return 0;
 }
 
-int snd_usb_mixer_resume(struct usb_mixer_interface *mixer, bool reset_resume)
+int snd_usb_mixer_resume(struct usb_mixer_interface *mixer)
 {
 	struct usb_mixer_elem_list *list;
 	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 (list->resume) {
+				err = list->resume(list);
+				if (err < 0)
+					return err;
 			}
 		}
 	}
@@ -3663,6 +3666,6 @@ 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 = resume_mixer;
 #endif
 }
diff --git a/sound/usb/mixer.h b/sound/usb/mixer.h
index c29e27ac43a7..7584c4762823 100644
--- a/sound/usb/mixer.h
+++ b/sound/usb/mixer.h
@@ -120,7 +120,7 @@ int snd_usb_mixer_vol_tlv(struct snd_kcontrol *kcontrol, int op_flag,
 
 #ifdef CONFIG_PM
 int snd_usb_mixer_suspend(struct usb_mixer_interface *mixer);
-int snd_usb_mixer_resume(struct usb_mixer_interface *mixer, bool reset_resume);
+int snd_usb_mixer_resume(struct usb_mixer_interface *mixer);
 #endif
 
 int snd_usb_set_cur_mix_value(struct usb_mixer_elem_info *cval, int channel,
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH v2 2/2] ALSA: usb-audio: Check connector value on resume
  2021-03-25 12:12 ` [PATCH v2 2/2] ALSA: usb-audio: Check connector value on resume Kai-Heng Feng
@ 2021-03-25 13:41   ` Takashi Iwai
  2021-03-25 13:55     ` Kai-Heng Feng
  0 siblings, 1 reply; 6+ messages in thread
From: Takashi Iwai @ 2021-03-25 13:41 UTC (permalink / raw)
  To: Kai-Heng Feng
  Cc: tiwai, Jaroslav Kysela, Pavel Skripkin, Chris Chiu, Mark Brown,
	Lars-Peter Clausen, Tom Yan, Joe Perches, moderated list:SOUND,
	open list

On Thu, 25 Mar 2021 13:12:48 +0100,
Kai-Heng Feng wrote:
> 
> 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.
> 
> While at it, also remove reset-resume path to consolidate mixer resume
> path.
> 
> Signed-off-by: Kai-Heng Feng <kai.heng.feng@canonical.com>
> ---
> v2:
>  - Remove reset-resume.
>  - Fold the connector checking to the mixer resume callback.

That's not what I meant exactly...  I meant to put both into the
single resume callback, but handle each part conditionally depending
on reset_resume argument.

But this turned out to need more changes in mixer_quirks.c
unnecessarily.  Maybe adding the two resume functions is a better
approach in the end, but not for the specific connection thing but
generically both resume and reset_resume callbacks.  Something like
below.


thanks,

Takashi


diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c
index b004b2e63a5d..1dab281bb269 100644
--- a/sound/usb/mixer.c
+++ b/sound/usb/mixer.c
@@ -3615,20 +3615,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 = list->resume(list);
+				if (err < 0)
+					return err;
 			}
 		}
 	}
@@ -3647,6 +3670,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);

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH v2 2/2] ALSA: usb-audio: Check connector value on resume
  2021-03-25 13:41   ` Takashi Iwai
@ 2021-03-25 13:55     ` Kai-Heng Feng
  2021-03-25 14:24       ` Kai-Heng Feng
  0 siblings, 1 reply; 6+ messages in thread
From: Kai-Heng Feng @ 2021-03-25 13:55 UTC (permalink / raw)
  To: Takashi Iwai
  Cc: Takashi Iwai, Jaroslav Kysela, Pavel Skripkin, Chris Chiu,
	Mark Brown, Lars-Peter Clausen, Tom Yan, Joe Perches,
	moderated list:SOUND, open list

On Thu, Mar 25, 2021 at 9:41 PM Takashi Iwai <tiwai@suse.de> wrote:
>
> On Thu, 25 Mar 2021 13:12:48 +0100,
> Kai-Heng Feng wrote:
> >
> > 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.
> >
> > While at it, also remove reset-resume path to consolidate mixer resume
> > path.
> >
> > Signed-off-by: Kai-Heng Feng <kai.heng.feng@canonical.com>
> > ---
> > v2:
> >  - Remove reset-resume.
> >  - Fold the connector checking to the mixer resume callback.
>
> That's not what I meant exactly...  I meant to put both into the
> single resume callback, but handle each part conditionally depending
> on reset_resume argument.

OK, I get what you mean now.

>
> But this turned out to need more changes in mixer_quirks.c
> unnecessarily.  Maybe adding the two resume functions is a better
> approach in the end, but not for the specific connection thing but
> generically both resume and reset_resume callbacks.  Something like
> below.

This approach looks good. Let me send another one.

Kai-Heng

>
>
> thanks,
>
> Takashi
>
>
> diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c
> index b004b2e63a5d..1dab281bb269 100644
> --- a/sound/usb/mixer.c
> +++ b/sound/usb/mixer.c
> @@ -3615,20 +3615,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 = list->resume(list);
> +                               if (err < 0)
> +                                       return err;
>                         }
>                 }
>         }
> @@ -3647,6 +3670,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);

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH v2 2/2] ALSA: usb-audio: Check connector value on resume
  2021-03-25 13:55     ` Kai-Heng Feng
@ 2021-03-25 14:24       ` Kai-Heng Feng
  2021-03-25 14:30         ` Takashi Iwai
  0 siblings, 1 reply; 6+ messages in thread
From: Kai-Heng Feng @ 2021-03-25 14:24 UTC (permalink / raw)
  To: Takashi Iwai
  Cc: Takashi Iwai, Jaroslav Kysela, Pavel Skripkin, Chris Chiu,
	Mark Brown, Lars-Peter Clausen, Tom Yan, Joe Perches,
	moderated list:SOUND, open list

On Thu, Mar 25, 2021 at 9:55 PM Kai-Heng Feng
<kai.heng.feng@canonical.com> wrote:
>
> On Thu, Mar 25, 2021 at 9:41 PM Takashi Iwai <tiwai@suse.de> wrote:
> >
> > On Thu, 25 Mar 2021 13:12:48 +0100,
> > Kai-Heng Feng wrote:
> > >
> > > 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.
> > >
> > > While at it, also remove reset-resume path to consolidate mixer resume
> > > path.
> > >
> > > Signed-off-by: Kai-Heng Feng <kai.heng.feng@canonical.com>
> > > ---
> > > v2:
> > >  - Remove reset-resume.
> > >  - Fold the connector checking to the mixer resume callback.
> >
> > That's not what I meant exactly...  I meant to put both into the
> > single resume callback, but handle each part conditionally depending
> > on reset_resume argument.
>
> OK, I get what you mean now.
>
> >
> > But this turned out to need more changes in mixer_quirks.c
> > unnecessarily.  Maybe adding the two resume functions is a better
> > approach in the end, but not for the specific connection thing but
> > generically both resume and reset_resume callbacks.  Something like
> > below.
>
> This approach looks good. Let me send another one.

Actually, it works really well and I don't I think I should send the
code you wrote.
Is it possible to push your version with my commit log, and with my tested tag?

Tested-by: Kai-Heng Feng <kai.heng.feng@canonical.com>

> Kai-Heng
>
> >
> >
> > thanks,
> >
> > Takashi
> >
> >
> > diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c
> > index b004b2e63a5d..1dab281bb269 100644
> > --- a/sound/usb/mixer.c
> > +++ b/sound/usb/mixer.c
> > @@ -3615,20 +3615,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 = list->resume(list);
> > +                               if (err < 0)
> > +                                       return err;
> >                         }
> >                 }
> >         }
> > @@ -3647,6 +3670,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);

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH v2 2/2] ALSA: usb-audio: Check connector value on resume
  2021-03-25 14:24       ` Kai-Heng Feng
@ 2021-03-25 14:30         ` Takashi Iwai
  0 siblings, 0 replies; 6+ messages in thread
From: Takashi Iwai @ 2021-03-25 14:30 UTC (permalink / raw)
  To: Kai-Heng Feng
  Cc: Takashi Iwai, Jaroslav Kysela, Pavel Skripkin, Chris Chiu,
	Mark Brown, Lars-Peter Clausen, Tom Yan, Joe Perches,
	moderated list:SOUND, open list

On Thu, 25 Mar 2021 15:24:42 +0100,
Kai-Heng Feng wrote:
> 
> On Thu, Mar 25, 2021 at 9:55 PM Kai-Heng Feng
> <kai.heng.feng@canonical.com> wrote:
> >
> > On Thu, Mar 25, 2021 at 9:41 PM Takashi Iwai <tiwai@suse.de> wrote:
> > >
> > > On Thu, 25 Mar 2021 13:12:48 +0100,
> > > Kai-Heng Feng wrote:
> > > >
> > > > 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.
> > > >
> > > > While at it, also remove reset-resume path to consolidate mixer resume
> > > > path.
> > > >
> > > > Signed-off-by: Kai-Heng Feng <kai.heng.feng@canonical.com>
> > > > ---
> > > > v2:
> > > >  - Remove reset-resume.
> > > >  - Fold the connector checking to the mixer resume callback.
> > >
> > > That's not what I meant exactly...  I meant to put both into the
> > > single resume callback, but handle each part conditionally depending
> > > on reset_resume argument.
> >
> > OK, I get what you mean now.
> >
> > >
> > > But this turned out to need more changes in mixer_quirks.c
> > > unnecessarily.  Maybe adding the two resume functions is a better
> > > approach in the end, but not for the specific connection thing but
> > > generically both resume and reset_resume callbacks.  Something like
> > > below.
> >
> > This approach looks good. Let me send another one.
> 
> Actually, it works really well and I don't I think I should send the
> code you wrote.
> Is it possible to push your version with my commit log, and with my tested tag?
> 
> Tested-by: Kai-Heng Feng <kai.heng.feng@canonical.com>

Heh, I'm too lazy to write up the whole commit.  Could you just fold
into yours and submit a v3 series?  I don't mind who is credited as
the author, just put me as Suggested-by or such, if any.


thanks,

Takashi

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2021-03-25 14:30 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-03-25 12:12 [PATCH v2 1/2] ALSA: usb-audio: Carve out connector value checking into a helper Kai-Heng Feng
2021-03-25 12:12 ` [PATCH v2 2/2] ALSA: usb-audio: Check connector value on resume Kai-Heng Feng
2021-03-25 13:41   ` Takashi Iwai
2021-03-25 13:55     ` Kai-Heng Feng
2021-03-25 14:24       ` Kai-Heng Feng
2021-03-25 14:30         ` Takashi Iwai

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).