mirror of
https://github.com/rd-stuffs/msm-4.14.git
synced 2025-02-20 11:45:48 +08:00
ALSA: usb-audio: Resume mixer values properly
Implement reset_resume callback so that the mixer values are properly restored. Still no boot quirks are called, so it might not work well on some devices. Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
parent
63f4b3a475
commit
400362f1d8
@ -691,12 +691,12 @@ static int usb_audio_suspend(struct usb_interface *intf, pm_message_t message)
|
|||||||
}
|
}
|
||||||
|
|
||||||
list_for_each_entry(mixer, &chip->mixer_list, list)
|
list_for_each_entry(mixer, &chip->mixer_list, list)
|
||||||
snd_usb_mixer_inactivate(mixer);
|
snd_usb_mixer_suspend(mixer);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int usb_audio_resume(struct usb_interface *intf)
|
static int __usb_audio_resume(struct usb_interface *intf, bool reset_resume)
|
||||||
{
|
{
|
||||||
struct snd_usb_audio *chip = usb_get_intfdata(intf);
|
struct snd_usb_audio *chip = usb_get_intfdata(intf);
|
||||||
struct usb_mixer_interface *mixer;
|
struct usb_mixer_interface *mixer;
|
||||||
@ -711,7 +711,7 @@ static int usb_audio_resume(struct usb_interface *intf)
|
|||||||
* we just notify and restart the mixers
|
* we just notify and restart the mixers
|
||||||
*/
|
*/
|
||||||
list_for_each_entry(mixer, &chip->mixer_list, list) {
|
list_for_each_entry(mixer, &chip->mixer_list, list) {
|
||||||
err = snd_usb_mixer_activate(mixer);
|
err = snd_usb_mixer_resume(mixer, reset_resume);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
goto err_out;
|
goto err_out;
|
||||||
}
|
}
|
||||||
@ -723,9 +723,20 @@ static int usb_audio_resume(struct usb_interface *intf)
|
|||||||
err_out:
|
err_out:
|
||||||
return err;
|
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
|
#else
|
||||||
#define usb_audio_suspend NULL
|
#define usb_audio_suspend NULL
|
||||||
#define usb_audio_resume NULL
|
#define usb_audio_resume NULL
|
||||||
|
#define usb_audio_reset_resume NULL
|
||||||
#endif /* CONFIG_PM */
|
#endif /* CONFIG_PM */
|
||||||
|
|
||||||
static struct usb_device_id usb_audio_ids [] = {
|
static struct usb_device_id usb_audio_ids [] = {
|
||||||
@ -747,6 +758,7 @@ static struct usb_driver usb_audio_driver = {
|
|||||||
.disconnect = usb_audio_disconnect,
|
.disconnect = usb_audio_disconnect,
|
||||||
.suspend = usb_audio_suspend,
|
.suspend = usb_audio_suspend,
|
||||||
.resume = usb_audio_resume,
|
.resume = usb_audio_resume,
|
||||||
|
.reset_resume = usb_audio_reset_resume,
|
||||||
.id_table = usb_audio_ids,
|
.id_table = usb_audio_ids,
|
||||||
.supports_autosuspend = 1,
|
.supports_autosuspend = 1,
|
||||||
};
|
};
|
||||||
|
@ -2299,26 +2299,6 @@ requeue:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* stop any bus activity of a mixer */
|
|
||||||
void snd_usb_mixer_inactivate(struct usb_mixer_interface *mixer)
|
|
||||||
{
|
|
||||||
usb_kill_urb(mixer->urb);
|
|
||||||
usb_kill_urb(mixer->rc_urb);
|
|
||||||
}
|
|
||||||
|
|
||||||
int snd_usb_mixer_activate(struct usb_mixer_interface *mixer)
|
|
||||||
{
|
|
||||||
int err;
|
|
||||||
|
|
||||||
if (mixer->urb) {
|
|
||||||
err = usb_submit_urb(mixer->urb, GFP_NOIO);
|
|
||||||
if (err < 0)
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* create the handler for the optional status interrupt endpoint */
|
/* create the handler for the optional status interrupt endpoint */
|
||||||
static int snd_usb_mixer_status_create(struct usb_mixer_interface *mixer)
|
static int snd_usb_mixer_status_create(struct usb_mixer_interface *mixer)
|
||||||
{
|
{
|
||||||
@ -2417,3 +2397,82 @@ void snd_usb_mixer_disconnect(struct list_head *p)
|
|||||||
usb_kill_urb(mixer->urb);
|
usb_kill_urb(mixer->urb);
|
||||||
usb_kill_urb(mixer->rc_urb);
|
usb_kill_urb(mixer->rc_urb);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_PM
|
||||||
|
/* stop any bus activity of a mixer */
|
||||||
|
static void snd_usb_mixer_inactivate(struct usb_mixer_interface *mixer)
|
||||||
|
{
|
||||||
|
usb_kill_urb(mixer->urb);
|
||||||
|
usb_kill_urb(mixer->rc_urb);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int snd_usb_mixer_activate(struct usb_mixer_interface *mixer)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
|
||||||
|
if (mixer->urb) {
|
||||||
|
err = usb_submit_urb(mixer->urb, GFP_NOIO);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int snd_usb_mixer_suspend(struct usb_mixer_interface *mixer)
|
||||||
|
{
|
||||||
|
snd_usb_mixer_inactivate(mixer);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int restore_mixer_value(struct usb_mixer_elem_info *cval)
|
||||||
|
{
|
||||||
|
int c, err, idx;
|
||||||
|
|
||||||
|
if (cval->cmask) {
|
||||||
|
idx = 0;
|
||||||
|
for (c = 0; c < MAX_CHANNELS; c++) {
|
||||||
|
if (!(cval->cmask & (1 << c)))
|
||||||
|
continue;
|
||||||
|
if (cval->cached & (1 << c)) {
|
||||||
|
err = set_cur_mix_value(cval, c + 1, idx,
|
||||||
|
cval->cache_val[idx]);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
idx++;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* master */
|
||||||
|
if (cval->cached) {
|
||||||
|
err = set_cur_mix_value(cval, 0, 0, *cval->cache_val);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int snd_usb_mixer_resume(struct usb_mixer_interface *mixer, bool reset_resume)
|
||||||
|
{
|
||||||
|
struct usb_mixer_elem_info *cval;
|
||||||
|
int id, err;
|
||||||
|
|
||||||
|
/* FIXME: any mixer quirks? */
|
||||||
|
|
||||||
|
if (reset_resume) {
|
||||||
|
/* restore cached mixer values */
|
||||||
|
for (id = 0; id < MAX_ID_ELEMS; id++) {
|
||||||
|
for (cval = mixer->id_elems[id]; cval;
|
||||||
|
cval = cval->next_id_elem) {
|
||||||
|
err = restore_mixer_value(cval);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return snd_usb_mixer_activate(mixer);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
@ -63,8 +63,6 @@ void snd_usb_mixer_notify_id(struct usb_mixer_interface *mixer, int unitid);
|
|||||||
|
|
||||||
int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval,
|
int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval,
|
||||||
int request, int validx, int value_set);
|
int request, int validx, int value_set);
|
||||||
void snd_usb_mixer_inactivate(struct usb_mixer_interface *mixer);
|
|
||||||
int snd_usb_mixer_activate(struct usb_mixer_interface *mixer);
|
|
||||||
|
|
||||||
int snd_usb_mixer_add_control(struct usb_mixer_interface *mixer,
|
int snd_usb_mixer_add_control(struct usb_mixer_interface *mixer,
|
||||||
struct snd_kcontrol *kctl);
|
struct snd_kcontrol *kctl);
|
||||||
@ -72,4 +70,9 @@ int snd_usb_mixer_add_control(struct usb_mixer_interface *mixer,
|
|||||||
int snd_usb_mixer_vol_tlv(struct snd_kcontrol *kcontrol, int op_flag,
|
int snd_usb_mixer_vol_tlv(struct snd_kcontrol *kcontrol, int op_flag,
|
||||||
unsigned int size, unsigned int __user *_tlv);
|
unsigned int size, unsigned int __user *_tlv);
|
||||||
|
|
||||||
|
#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);
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* __USBMIXER_H */
|
#endif /* __USBMIXER_H */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user