mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	ALSA: usb-audio: Initialize every feature unit once at probe time
So far we used to read the current value of the mixer element dynamically at the first access, and the error from a GET_CUR message is treated as a fatal error (unless QUIRK_IGNORE_CTL_ERROR is set). It's rather inconvenient, as most of GET_CUR errors are no fatal, and we can continue operation with assumption of some fixed value. This patch makes the USB-audio driver to change the behavior at probe time; now it tries to initialize the current value of each mixer element that is built from a feature unit (those for typically for mixer volumes and switches). When a read failure happens, it tries to set the known minimum value. After that point, a cached value is used always, hence we won't hit GET_CUR message error any longer. The error from GET_CUR message is still shown as a warning normally, but only once at the probe time, and it'll keep operating. If the message is confirmed to be harmless, it can be shut up by QUIRK_IGNORE_CTL_ERROR quirk flag, too. Tested-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Link: https://lore.kernel.org/r/20211014130636.17860-4-tiwai@suse.de Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
		
							parent
							
								
									509975c778
								
							
						
					
					
						commit
						b96681bd58
					
				
					 1 changed files with 33 additions and 1 deletions
				
			
		| 
						 | 
				
			
			@ -1199,12 +1199,32 @@ static void volume_control_quirks(struct usb_mixer_elem_info *cval,
 | 
			
		|||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* forcibly initialize the current mixer value; if GET_CUR fails, set to
 | 
			
		||||
 * the minimum as default
 | 
			
		||||
 */
 | 
			
		||||
static void init_cur_mix_raw(struct usb_mixer_elem_info *cval, int ch, int idx)
 | 
			
		||||
{
 | 
			
		||||
	int val, err;
 | 
			
		||||
 | 
			
		||||
	err = snd_usb_get_cur_mix_value(cval, ch, idx, &val);
 | 
			
		||||
	if (!err)
 | 
			
		||||
		return;
 | 
			
		||||
	if (!cval->head.mixer->ignore_ctl_error)
 | 
			
		||||
		usb_audio_warn(cval->head.mixer->chip,
 | 
			
		||||
			       "%d:%d: failed to get current value for ch %d (%d)\n",
 | 
			
		||||
			       cval->head.id, mixer_ctrl_intf(cval->head.mixer),
 | 
			
		||||
			       ch, err);
 | 
			
		||||
	snd_usb_set_cur_mix_value(cval, ch, idx, cval->min);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * retrieve the minimum and maximum values for the specified control
 | 
			
		||||
 */
 | 
			
		||||
static int get_min_max_with_quirks(struct usb_mixer_elem_info *cval,
 | 
			
		||||
				   int default_min, struct snd_kcontrol *kctl)
 | 
			
		||||
{
 | 
			
		||||
	int i, idx;
 | 
			
		||||
 | 
			
		||||
	/* for failsafe */
 | 
			
		||||
	cval->min = default_min;
 | 
			
		||||
	cval->max = cval->min + 1;
 | 
			
		||||
| 
						 | 
				
			
			@ -1217,7 +1237,6 @@ static int get_min_max_with_quirks(struct usb_mixer_elem_info *cval,
 | 
			
		|||
	} else {
 | 
			
		||||
		int minchn = 0;
 | 
			
		||||
		if (cval->cmask) {
 | 
			
		||||
			int i;
 | 
			
		||||
			for (i = 0; i < MAX_CHANNELS; i++)
 | 
			
		||||
				if (cval->cmask & (1 << i)) {
 | 
			
		||||
					minchn = i + 1;
 | 
			
		||||
| 
						 | 
				
			
			@ -1318,6 +1337,19 @@ static int get_min_max_with_quirks(struct usb_mixer_elem_info *cval,
 | 
			
		|||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* initialize all elements */
 | 
			
		||||
	if (!cval->cmask) {
 | 
			
		||||
		init_cur_mix_raw(cval, 0, 0);
 | 
			
		||||
	} else {
 | 
			
		||||
		idx = 0;
 | 
			
		||||
		for (i = 0; i < MAX_CHANNELS; i++) {
 | 
			
		||||
			if (cval->cmask & (1 << i)) {
 | 
			
		||||
				init_cur_mix_raw(cval, i + 1, idx);
 | 
			
		||||
				idx++;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue