⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ac97_codec.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	mute_mask = 0x8000;	val = snd_ac97_read(ac97, reg);	if (check_stereo || (ac97->flags & AC97_STEREO_MUTES)) {		/* check whether both mute bits work */		val1 = val | 0x8080;		snd_ac97_write(ac97, reg, val1);		if (val1 == snd_ac97_read(ac97, reg))			mute_mask = 0x8080;	}	if (mute_mask == 0x8080) {		struct snd_kcontrol_new tmp = AC97_DOUBLE(name, reg, 15, 7, 1, 1);		if (check_amix)			tmp.private_value |= (1 << 30);		tmp.index = ac97->num;		kctl = snd_ctl_new1(&tmp, ac97);	} else {		struct snd_kcontrol_new tmp = AC97_SINGLE(name, reg, 15, 1, 1);		if (check_amix)			tmp.private_value |= (1 << 30);		tmp.index = ac97->num;		kctl = snd_ctl_new1(&tmp, ac97);	}	err = snd_ctl_add(card, kctl);	if (err < 0)		return err;	/* mute as default */	snd_ac97_write_cache(ac97, reg, val | mute_mask);	return 0;}/* * set dB information */static const DECLARE_TLV_DB_SCALE(db_scale_4bit, -4500, 300, 0);static const DECLARE_TLV_DB_SCALE(db_scale_5bit, -4650, 150, 0);static const DECLARE_TLV_DB_SCALE(db_scale_6bit, -9450, 150, 0);static const DECLARE_TLV_DB_SCALE(db_scale_5bit_12db_max, -3450, 150, 0);static const DECLARE_TLV_DB_SCALE(db_scale_rec_gain, 0, 150, 0);static const unsigned int *find_db_scale(unsigned int maxval){	switch (maxval) {	case 0x0f: return db_scale_4bit;	case 0x1f: return db_scale_5bit;	case 0x3f: return db_scale_6bit;	}	return NULL;}static void set_tlv_db_scale(struct snd_kcontrol *kctl, const unsigned int *tlv){	kctl->tlv.p = tlv;	if (tlv)		kctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ;}/* * create a volume for normal stereo/mono controls */static int snd_ac97_cvol_new(struct snd_card *card, char *name, int reg, unsigned int lo_max,			     unsigned int hi_max, struct snd_ac97 *ac97){	int err;	struct snd_kcontrol *kctl;	if (! snd_ac97_valid_reg(ac97, reg))		return 0;	if (hi_max) {		/* invert */		struct snd_kcontrol_new tmp = AC97_DOUBLE(name, reg, 8, 0, lo_max, 1);		tmp.index = ac97->num;		kctl = snd_ctl_new1(&tmp, ac97);	} else {		/* invert */		struct snd_kcontrol_new tmp = AC97_SINGLE(name, reg, 0, lo_max, 1);		tmp.index = ac97->num;		kctl = snd_ctl_new1(&tmp, ac97);	}	if (reg >= AC97_PHONE && reg <= AC97_PCM)		set_tlv_db_scale(kctl, db_scale_5bit_12db_max);	else		set_tlv_db_scale(kctl, find_db_scale(lo_max));	err = snd_ctl_add(card, kctl);	if (err < 0)		return err;	snd_ac97_write_cache(ac97, reg,			     (snd_ac97_read(ac97, reg) & 0x8080) |			     lo_max | (hi_max << 8));	return 0;}/* * create a mute-switch and a volume for normal stereo/mono controls */static int snd_ac97_cmix_new_stereo(struct snd_card *card, const char *pfx,				    int reg, int check_stereo, int check_amix,				    struct snd_ac97 *ac97){	int err;	char name[44];	unsigned char lo_max, hi_max;	if (! snd_ac97_valid_reg(ac97, reg))		return 0;	if (snd_ac97_try_bit(ac97, reg, 15)) {		sprintf(name, "%s Switch", pfx);		if ((err = snd_ac97_cmute_new_stereo(card, name, reg,						     check_stereo, check_amix,						     ac97)) < 0)			return err;	}	check_volume_resolution(ac97, reg, &lo_max, &hi_max);	if (lo_max) {		sprintf(name, "%s Volume", pfx);		if ((err = snd_ac97_cvol_new(card, name, reg, lo_max, hi_max, ac97)) < 0)			return err;	}	return 0;}#define snd_ac97_cmix_new(card, pfx, reg, acheck, ac97) \	snd_ac97_cmix_new_stereo(card, pfx, reg, 0, acheck, ac97)#define snd_ac97_cmute_new(card, name, reg, acheck, ac97) \	snd_ac97_cmute_new_stereo(card, name, reg, 0, acheck, ac97)static unsigned int snd_ac97_determine_spdif_rates(struct snd_ac97 *ac97);static int snd_ac97_mixer_build(struct snd_ac97 * ac97){	struct snd_card *card = ac97->bus->card;	struct snd_kcontrol *kctl;	int err;	unsigned int idx;	unsigned char max;	/* build master controls */	/* AD claims to remove this control from AD1887, although spec v2.2 does not allow this */	if (snd_ac97_try_volume_mix(ac97, AC97_MASTER)) {		if (ac97->flags & AC97_HAS_NO_MASTER_VOL)			err = snd_ac97_cmute_new(card, "Master Playback Switch",						 AC97_MASTER, 0, ac97);		else			err = snd_ac97_cmix_new(card, "Master Playback",						AC97_MASTER, 0, ac97);		if (err < 0)			return err;	}	ac97->regs[AC97_CENTER_LFE_MASTER] = 0x8080;	/* build center controls */	if ((snd_ac97_try_volume_mix(ac97, AC97_CENTER_LFE_MASTER)) 		&& !(ac97->flags & AC97_AD_MULTI)) {		if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_center[0], ac97))) < 0)			return err;		if ((err = snd_ctl_add(card, kctl = snd_ac97_cnew(&snd_ac97_controls_center[1], ac97))) < 0)			return err;		snd_ac97_change_volume_params2(ac97, AC97_CENTER_LFE_MASTER, 0, &max);		kctl->private_value &= ~(0xff << 16);		kctl->private_value |= (int)max << 16;		set_tlv_db_scale(kctl, find_db_scale(max));		snd_ac97_write_cache(ac97, AC97_CENTER_LFE_MASTER, ac97->regs[AC97_CENTER_LFE_MASTER] | max);	}	/* build LFE controls */	if ((snd_ac97_try_volume_mix(ac97, AC97_CENTER_LFE_MASTER+1))		&& !(ac97->flags & AC97_AD_MULTI)) {		if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_lfe[0], ac97))) < 0)			return err;		if ((err = snd_ctl_add(card, kctl = snd_ac97_cnew(&snd_ac97_controls_lfe[1], ac97))) < 0)			return err;		snd_ac97_change_volume_params2(ac97, AC97_CENTER_LFE_MASTER, 8, &max);		kctl->private_value &= ~(0xff << 16);		kctl->private_value |= (int)max << 16;		set_tlv_db_scale(kctl, find_db_scale(max));		snd_ac97_write_cache(ac97, AC97_CENTER_LFE_MASTER, ac97->regs[AC97_CENTER_LFE_MASTER] | max << 8);	}	/* build surround controls */	if ((snd_ac97_try_volume_mix(ac97, AC97_SURROUND_MASTER)) 		&& !(ac97->flags & AC97_AD_MULTI)) {		/* Surround Master (0x38) is with stereo mutes */		if ((err = snd_ac97_cmix_new_stereo(card, "Surround Playback",						    AC97_SURROUND_MASTER, 1, 0,						    ac97)) < 0)			return err;	}	/* build headphone controls */	if (snd_ac97_try_volume_mix(ac97, AC97_HEADPHONE)) {		if ((err = snd_ac97_cmix_new(card, "Headphone Playback",					     AC97_HEADPHONE, 0, ac97)) < 0)			return err;	}		/* build master mono controls */	if (snd_ac97_try_volume_mix(ac97, AC97_MASTER_MONO)) {		if ((err = snd_ac97_cmix_new(card, "Master Mono Playback",					     AC97_MASTER_MONO, 0, ac97)) < 0)			return err;	}		/* build master tone controls */	if (!(ac97->flags & AC97_HAS_NO_TONE)) {		if (snd_ac97_try_volume_mix(ac97, AC97_MASTER_TONE)) {			for (idx = 0; idx < 2; idx++) {				if ((err = snd_ctl_add(card, kctl = snd_ac97_cnew(&snd_ac97_controls_tone[idx], ac97))) < 0)					return err;				if (ac97->id == AC97_ID_YMF743 ||				    ac97->id == AC97_ID_YMF753) {					kctl->private_value &= ~(0xff << 16);					kctl->private_value |= 7 << 16;				}			}			snd_ac97_write_cache(ac97, AC97_MASTER_TONE, 0x0f0f);		}	}		/* build PC Speaker controls */	if (!(ac97->flags & AC97_HAS_NO_PC_BEEP) && 		((ac97->flags & AC97_HAS_PC_BEEP) ||	    snd_ac97_try_volume_mix(ac97, AC97_PC_BEEP))) {		for (idx = 0; idx < 2; idx++)			if ((err = snd_ctl_add(card, kctl = snd_ac97_cnew(&snd_ac97_controls_pc_beep[idx], ac97))) < 0)				return err;		set_tlv_db_scale(kctl, db_scale_4bit);		snd_ac97_write_cache(ac97, AC97_PC_BEEP,				     snd_ac97_read(ac97, AC97_PC_BEEP) | 0x801e);	}		/* build Phone controls */	if (!(ac97->flags & AC97_HAS_NO_PHONE)) {		if (snd_ac97_try_volume_mix(ac97, AC97_PHONE)) {			if ((err = snd_ac97_cmix_new(card, "Phone Playback",						     AC97_PHONE, 1, ac97)) < 0)				return err;		}	}		/* build MIC controls */	if (!(ac97->flags & AC97_HAS_NO_MIC)) {		if (snd_ac97_try_volume_mix(ac97, AC97_MIC)) {			if ((err = snd_ac97_cmix_new(card, "Mic Playback",						     AC97_MIC, 1, ac97)) < 0)				return err;			if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_mic_boost, ac97))) < 0)				return err;		}	}	/* build Line controls */	if (snd_ac97_try_volume_mix(ac97, AC97_LINE)) {		if ((err = snd_ac97_cmix_new(card, "Line Playback",					     AC97_LINE, 1, ac97)) < 0)			return err;	}		/* build CD controls */	if (!(ac97->flags & AC97_HAS_NO_CD)) {		if (snd_ac97_try_volume_mix(ac97, AC97_CD)) {			if ((err = snd_ac97_cmix_new(card, "CD Playback",						     AC97_CD, 1, ac97)) < 0)				return err;		}	}		/* build Video controls */	if (!(ac97->flags & AC97_HAS_NO_VIDEO)) {		if (snd_ac97_try_volume_mix(ac97, AC97_VIDEO)) {			if ((err = snd_ac97_cmix_new(card, "Video Playback",						     AC97_VIDEO, 1, ac97)) < 0)				return err;		}	}	/* build Aux controls */	if (!(ac97->flags & AC97_HAS_NO_AUX)) {		if (snd_ac97_try_volume_mix(ac97, AC97_AUX)) {			if ((err = snd_ac97_cmix_new(card, "Aux Playback",						     AC97_AUX, 1, ac97)) < 0)				return err;		}	}	/* build PCM controls */	if (ac97->flags & AC97_AD_MULTI) {		unsigned short init_val;		if (ac97->flags & AC97_STEREO_MUTES)			init_val = 0x9f9f;		else			init_val = 0x9f1f;		for (idx = 0; idx < 2; idx++)			if ((err = snd_ctl_add(card, kctl = snd_ac97_cnew(&snd_ac97_controls_ad18xx_pcm[idx], ac97))) < 0)				return err;		set_tlv_db_scale(kctl, db_scale_5bit);		ac97->spec.ad18xx.pcmreg[0] = init_val;		if (ac97->scaps & AC97_SCAP_SURROUND_DAC) {			for (idx = 0; idx < 2; idx++)				if ((err = snd_ctl_add(card, kctl = snd_ac97_cnew(&snd_ac97_controls_ad18xx_surround[idx], ac97))) < 0)					return err;			set_tlv_db_scale(kctl, db_scale_5bit);			ac97->spec.ad18xx.pcmreg[1] = init_val;		}		if (ac97->scaps & AC97_SCAP_CENTER_LFE_DAC) {			for (idx = 0; idx < 2; idx++)				if ((err = snd_ctl_add(card, kctl = snd_ac97_cnew(&snd_ac97_controls_ad18xx_center[idx], ac97))) < 0)					return err;			set_tlv_db_scale(kctl, db_scale_5bit);			for (idx = 0; idx < 2; idx++)				if ((err = snd_ctl_add(card, kctl = snd_ac97_cnew(&snd_ac97_controls_ad18xx_lfe[idx], ac97))) < 0)					return err;			set_tlv_db_scale(kctl, db_scale_5bit);			ac97->spec.ad18xx.pcmreg[2] = init_val;		}		snd_ac97_write_cache(ac97, AC97_PCM, init_val);	} else {		if (!(ac97->flags & AC97_HAS_NO_STD_PCM)) {			if (ac97->flags & AC97_HAS_NO_PCM_VOL)				err = snd_ac97_cmute_new(card,							 "PCM Playback Switch",							 AC97_PCM, 0, ac97);			else				err = snd_ac97_cmix_new(card, "PCM Playback",							AC97_PCM, 0, ac97);			if (err < 0)				return err;		}	}	/* build Capture controls */	if (!(ac97->flags & AC97_HAS_NO_REC_GAIN)) {		if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_control_capture_src, ac97))) < 0)			return err;		if (snd_ac97_try_bit(ac97, AC97_REC_GAIN, 15)) {			err = snd_ac97_cmute_new(card, "Capture Switch",						 AC97_REC_GAIN, 0, ac97);			if (err < 0)				return err;		}		if ((err = snd_ctl_add(card, kctl = snd_ac97_cnew(&snd_ac97_control_capture_vol, ac97))) < 0)			return err;		set_tlv_db_scale(kctl, db_scale_rec_gain);		snd_ac97_write_cache(ac97, AC97_REC_SEL, 0x0000);		snd_ac97_write_cache(ac97, AC97_REC_GAIN, 0x0000);	}	/* build MIC Capture controls */	if (snd_ac97_try_volume_mix(ac97, AC97_REC_GAIN_MIC)) {		for (idx = 0; idx < 2; idx++)			if ((err = snd_ctl_add(card, kctl = snd_ac97_cnew(&snd_ac97_controls_mic_capture[idx], ac97))) < 0)				return err;		set_tlv_db_scale(kctl, db_scale_rec_gain);		snd_ac97_write_cache(ac97, AC97_REC_GAIN_MIC, 0x0000);	}	/* build PCM out path & mute control */	if (snd_ac97_try_bit(ac97, AC97_GENERAL_PURPOSE, 15)) {		if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_general[AC97_GENERAL_PCM_OUT], ac97))) < 0)			return err;	}	/* build Simulated Stereo Enhancement control */	if (ac97->caps & 0x0008) {		if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_general[AC97_GENERAL_STEREO_ENHANCEMENT], ac97))) < 0)			return err;	}	/* build 3D Stereo Enhancement control */	if (snd_ac97_try_bit(ac97, AC97_GENERAL_PURPOSE, 13)) {		if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_general[AC97_GENERAL_3D], ac97))) < 0)			return err;	}	/* build Loudness control */	if (ac97->caps & 0x0020) {		if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_general[AC97_GENERAL_LOUDNESS], ac97))) < 0)			return err;	}	/* build Mono output select control */	if (snd_ac97_try_bit(ac97, AC97_GENERAL_PURPOSE, 9)) {		if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_general[AC97_GENERAL_MONO], ac97))) < 0)			return err;	}	/* build Mic select control */	if (snd_ac97_try_bit(ac97, AC97_GENERAL_PURPOSE, 8)) {		if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_general[AC97_GENERAL_MIC], ac97))) < 0)			return err;	}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -