forked from mirrors/linux
		
	ALSA: hda - Remove the use of set_fs()
set_fs() is used in HD-audio vmaster code to retrieve the TLV data of each slave kctl. Since the slave is supposed to be a standard amp kctl, we can call directly the supposed tlv callback instead of the indirect call, so that we can remove the set_fs() hack. Reviewed-by: Takashi Sakamoto <o-takashi@sakamocchi.jp> Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
		
							parent
							
								
									3db9e970e3
								
							
						
					
					
						commit
						99b5c5bb9a
					
				
					 1 changed files with 31 additions and 28 deletions
				
			
		| 
						 | 
					@ -1477,6 +1477,30 @@ int snd_hda_mixer_amp_volume_put(struct snd_kcontrol *kcontrol,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
EXPORT_SYMBOL_GPL(snd_hda_mixer_amp_volume_put);
 | 
					EXPORT_SYMBOL_GPL(snd_hda_mixer_amp_volume_put);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* inquiry the amp caps and convert to TLV */
 | 
				
			||||||
 | 
					static void get_ctl_amp_tlv(struct snd_kcontrol *kcontrol, unsigned int *tlv)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
 | 
				
			||||||
 | 
						hda_nid_t nid = get_amp_nid(kcontrol);
 | 
				
			||||||
 | 
						int dir = get_amp_direction(kcontrol);
 | 
				
			||||||
 | 
						unsigned int ofs = get_amp_offset(kcontrol);
 | 
				
			||||||
 | 
						bool min_mute = get_amp_min_mute(kcontrol);
 | 
				
			||||||
 | 
						u32 caps, val1, val2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						caps = query_amp_caps(codec, nid, dir);
 | 
				
			||||||
 | 
						val2 = (caps & AC_AMPCAP_STEP_SIZE) >> AC_AMPCAP_STEP_SIZE_SHIFT;
 | 
				
			||||||
 | 
						val2 = (val2 + 1) * 25;
 | 
				
			||||||
 | 
						val1 = -((caps & AC_AMPCAP_OFFSET) >> AC_AMPCAP_OFFSET_SHIFT);
 | 
				
			||||||
 | 
						val1 += ofs;
 | 
				
			||||||
 | 
						val1 = ((int)val1) * ((int)val2);
 | 
				
			||||||
 | 
						if (min_mute || (caps & AC_AMPCAP_MIN_MUTE))
 | 
				
			||||||
 | 
							val2 |= TLV_DB_SCALE_MUTE;
 | 
				
			||||||
 | 
						tlv[0] = SNDRV_CTL_TLVT_DB_SCALE;
 | 
				
			||||||
 | 
						tlv[1] = 2 * sizeof(unsigned int);
 | 
				
			||||||
 | 
						tlv[2] = val1;
 | 
				
			||||||
 | 
						tlv[3] = val2;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * snd_hda_mixer_amp_volume_put - TLV callback for a standard AMP mixer volume
 | 
					 * snd_hda_mixer_amp_volume_put - TLV callback for a standard AMP mixer volume
 | 
				
			||||||
 * @kcontrol: ctl element
 | 
					 * @kcontrol: ctl element
 | 
				
			||||||
| 
						 | 
					@ -1490,30 +1514,12 @@ EXPORT_SYMBOL_GPL(snd_hda_mixer_amp_volume_put);
 | 
				
			||||||
int snd_hda_mixer_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag,
 | 
					int snd_hda_mixer_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag,
 | 
				
			||||||
			  unsigned int size, unsigned int __user *_tlv)
 | 
								  unsigned int size, unsigned int __user *_tlv)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
 | 
						unsigned int tlv[4];
 | 
				
			||||||
	hda_nid_t nid = get_amp_nid(kcontrol);
 | 
					 | 
				
			||||||
	int dir = get_amp_direction(kcontrol);
 | 
					 | 
				
			||||||
	unsigned int ofs = get_amp_offset(kcontrol);
 | 
					 | 
				
			||||||
	bool min_mute = get_amp_min_mute(kcontrol);
 | 
					 | 
				
			||||||
	u32 caps, val1, val2;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (size < 4 * sizeof(unsigned int))
 | 
						if (size < 4 * sizeof(unsigned int))
 | 
				
			||||||
		return -ENOMEM;
 | 
							return -ENOMEM;
 | 
				
			||||||
	caps = query_amp_caps(codec, nid, dir);
 | 
						get_ctl_amp_tlv(kcontrol, tlv);
 | 
				
			||||||
	val2 = (caps & AC_AMPCAP_STEP_SIZE) >> AC_AMPCAP_STEP_SIZE_SHIFT;
 | 
						if (copy_to_user(_tlv, tlv, sizeof(tlv)))
 | 
				
			||||||
	val2 = (val2 + 1) * 25;
 | 
					 | 
				
			||||||
	val1 = -((caps & AC_AMPCAP_OFFSET) >> AC_AMPCAP_OFFSET_SHIFT);
 | 
					 | 
				
			||||||
	val1 += ofs;
 | 
					 | 
				
			||||||
	val1 = ((int)val1) * ((int)val2);
 | 
					 | 
				
			||||||
	if (min_mute || (caps & AC_AMPCAP_MIN_MUTE))
 | 
					 | 
				
			||||||
		val2 |= TLV_DB_SCALE_MUTE;
 | 
					 | 
				
			||||||
	if (put_user(SNDRV_CTL_TLVT_DB_SCALE, _tlv))
 | 
					 | 
				
			||||||
		return -EFAULT;
 | 
					 | 
				
			||||||
	if (put_user(2 * sizeof(unsigned int), _tlv + 1))
 | 
					 | 
				
			||||||
		return -EFAULT;
 | 
					 | 
				
			||||||
	if (put_user(val1, _tlv + 2))
 | 
					 | 
				
			||||||
		return -EFAULT;
 | 
					 | 
				
			||||||
	if (put_user(val2, _tlv + 3))
 | 
					 | 
				
			||||||
		return -EFAULT;
 | 
							return -EFAULT;
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -1807,13 +1813,10 @@ static int get_kctl_0dB_offset(struct hda_codec *codec,
 | 
				
			||||||
	const int *tlv = NULL;
 | 
						const int *tlv = NULL;
 | 
				
			||||||
	int val = -1;
 | 
						int val = -1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (kctl->vd[0].access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK) {
 | 
						if ((kctl->vd[0].access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK) &&
 | 
				
			||||||
		/* FIXME: set_fs() hack for obtaining user-space TLV data */
 | 
						    kctl->tlv.c == snd_hda_mixer_amp_tlv) {
 | 
				
			||||||
		mm_segment_t fs = get_fs();
 | 
							get_ctl_amp_tlv(kctl, _tlv);
 | 
				
			||||||
		set_fs(get_ds());
 | 
							tlv = _tlv;
 | 
				
			||||||
		if (!kctl->tlv.c(kctl, 0, sizeof(_tlv), _tlv))
 | 
					 | 
				
			||||||
			tlv = _tlv;
 | 
					 | 
				
			||||||
		set_fs(fs);
 | 
					 | 
				
			||||||
	} else if (kctl->vd[0].access & SNDRV_CTL_ELEM_ACCESS_TLV_READ)
 | 
						} else if (kctl->vd[0].access & SNDRV_CTL_ELEM_ACCESS_TLV_READ)
 | 
				
			||||||
		tlv = kctl->tlv.p;
 | 
							tlv = kctl->tlv.p;
 | 
				
			||||||
	if (tlv && tlv[0] == SNDRV_CTL_TLVT_DB_SCALE) {
 | 
						if (tlv && tlv[0] == SNDRV_CTL_TLVT_DB_SCALE) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue