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

📄 ac97_codec.c

📁 是关于linux2.5.1的完全源码
💻 C
📖 第 1 页 / 共 5 页
字号:
	static char *texts3[2] = { "Mic1", "Mic2" };	char **texts = NULL;	int reg = kcontrol->private_value & 0xff;	int shift = (kcontrol->private_value >> 8) & 0xff;	switch (reg) {	case AC97_GENERAL_PURPOSE:		switch (shift) {		case 15: texts = texts1; break;		case 9: texts = texts2; break;		case 8: texts = texts3; break;		}	}	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;	uinfo->count = 1;	uinfo->value.enumerated.items = 2;	if (uinfo->value.enumerated.item > 1)		uinfo->value.enumerated.item = 1;	strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);	return 0;}static int snd_ac97_get_enum_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){	ac97_t *ac97 = snd_kcontrol_chip(kcontrol);	unsigned short val;	int reg = kcontrol->private_value & 0xff;	int shift = (kcontrol->private_value >> 8) & 0xff;	int invert = (kcontrol->private_value >> 24) & 0xff;		val = (ac97->regs[reg] >> shift) & 1;	if (invert)		val ^= 1;	ucontrol->value.enumerated.item[0] = val;	return 0;}static int snd_ac97_put_enum_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){	ac97_t *ac97 = snd_kcontrol_chip(kcontrol);	unsigned short val;	int reg = kcontrol->private_value & 0xff;	int shift = (kcontrol->private_value >> 8) & 0xff;	int invert = (kcontrol->private_value >> 24) & 0xff;		if (ucontrol->value.enumerated.item[0] > 1)		return -EINVAL;	val = !!ucontrol->value.enumerated.item[0];	if (invert)		val = !val;	return snd_ac97_update_bits(ac97, reg, 1 << shift, val << shift);}#define AC97_SINGLE(xname, reg, shift, mask, invert) \{ iface: SNDRV_CTL_ELEM_IFACE_MIXER, name: xname, info: snd_ac97_info_single, \  get: snd_ac97_get_single, put: snd_ac97_put_single, \  private_value: reg | (shift << 8) | (mask << 16) | (invert << 24) }static int snd_ac97_info_single(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo){	int mask = (kcontrol->private_value >> 16) & 0xff;	uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;	uinfo->count = 1;	uinfo->value.integer.min = 0;	uinfo->value.integer.max = mask;	return 0;}static int snd_ac97_get_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){	ac97_t *ac97 = snd_kcontrol_chip(kcontrol);	int reg = kcontrol->private_value & 0xff;	int shift = (kcontrol->private_value >> 8) & 0xff;	int mask = (kcontrol->private_value >> 16) & 0xff;	int invert = (kcontrol->private_value >> 24) & 0xff;		ucontrol->value.integer.value[0] = (ac97->regs[reg] >> shift) & mask;	if (invert)		ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0];	return 0;}static int snd_ac97_put_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){	ac97_t *ac97 = snd_kcontrol_chip(kcontrol);	int reg = kcontrol->private_value & 0xff;	int shift = (kcontrol->private_value >> 8) & 0xff;	int mask = (kcontrol->private_value >> 16) & 0xff;	int invert = (kcontrol->private_value >> 24) & 0xff;	unsigned short val;		val = (ucontrol->value.integer.value[0] & mask);	if (invert)		val = mask - val;	return snd_ac97_update_bits(ac97, reg, mask << shift, val << shift);}#define AC97_DOUBLE(xname, reg, shift_left, shift_right, mask, invert) \{ iface: SNDRV_CTL_ELEM_IFACE_MIXER, name: (xname), info: snd_ac97_info_double, \  get: snd_ac97_get_double, put: snd_ac97_put_double, \  private_value: reg | (shift_left << 8) | (shift_right << 12) | (mask << 16) | (invert << 24) }static int snd_ac97_info_double(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo){	int mask = (kcontrol->private_value >> 16) & 0xff;	uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;	uinfo->count = 2;	uinfo->value.integer.min = 0;	uinfo->value.integer.max = mask;	return 0;}static int snd_ac97_get_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){	ac97_t *ac97 = snd_kcontrol_chip(kcontrol);	int reg = kcontrol->private_value & 0xff;	int shift_left = (kcontrol->private_value >> 8) & 0x0f;	int shift_right = (kcontrol->private_value >> 12) & 0x0f;	int mask = (kcontrol->private_value >> 16) & 0xff;	int invert = (kcontrol->private_value >> 24) & 0xff;		spin_lock(&ac97->reg_lock);	ucontrol->value.integer.value[0] = (ac97->regs[reg] >> shift_left) & mask;	ucontrol->value.integer.value[1] = (ac97->regs[reg] >> shift_right) & mask;	spin_unlock(&ac97->reg_lock);	if (invert) {		ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0];		ucontrol->value.integer.value[1] = mask - ucontrol->value.integer.value[1];	}	return 0;}static int snd_ac97_put_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){	ac97_t *ac97 = snd_kcontrol_chip(kcontrol);	int reg = kcontrol->private_value & 0xff;	int shift_left = (kcontrol->private_value >> 8) & 0x0f;	int shift_right = (kcontrol->private_value >> 12) & 0x0f;	int mask = (kcontrol->private_value >> 16) & 0xff;	int invert = (kcontrol->private_value >> 24) & 0xff;	unsigned short val1, val2;		val1 = ucontrol->value.integer.value[0] & mask;	val2 = ucontrol->value.integer.value[1] & mask;	if (invert) {		val1 = mask - val1;		val2 = mask - val2;	}	return snd_ac97_update_bits(ac97, reg, 				    (mask << shift_left) | (mask << shift_right),				    (val1 << shift_left) | (val2 << shift_right));}static const snd_kcontrol_new_t snd_ac97_controls_master[2] = {AC97_SINGLE("Master Playback Switch", AC97_MASTER, 15, 1, 1),AC97_DOUBLE("Master Playback Volume", AC97_MASTER, 8, 0, 31, 1)};static const snd_kcontrol_new_t snd_ac97_controls_headphone[2] = {AC97_SINGLE("Headphone Playback Switch", AC97_HEADPHONE, 15, 1, 1),AC97_DOUBLE("Headphone Playback Volume", AC97_HEADPHONE, 8, 0, 31, 1)};static const snd_kcontrol_new_t snd_ac97_controls_master_mono[2] = {AC97_SINGLE("Master Mono Playback Switch", AC97_MASTER_MONO, 15, 1, 1),AC97_SINGLE("Master Mono Playback Volume", AC97_MASTER_MONO, 0, 31, 1)};static const snd_kcontrol_new_t snd_ac97_controls_tone[2] = {AC97_SINGLE("Tone Control - Bass", AC97_MASTER_TONE, 8, 15, 1),AC97_SINGLE("Tone Control - Treble", AC97_MASTER_TONE, 0, 15, 1)};static const snd_kcontrol_new_t snd_ac97_controls_pc_beep[2] = {AC97_SINGLE("PC Speaker Playback Switch", AC97_PC_BEEP, 15, 1, 1),AC97_SINGLE("PC Speaker Playback Volume", AC97_PC_BEEP, 1, 15, 1)};static const snd_kcontrol_new_t snd_ac97_controls_phone[2] = {AC97_SINGLE("Phone Playback Switch", AC97_PHONE, 15, 1, 1),AC97_SINGLE("Phone Playback Volume", AC97_PHONE, 0, 15, 1)};static const snd_kcontrol_new_t snd_ac97_controls_mic[3] = {AC97_SINGLE("Mic Playback Switch", AC97_MIC, 15, 1, 1),AC97_SINGLE("Mic Playback Volume", AC97_MIC, 0, 15, 1),AC97_SINGLE("Mic Boost (+20dB)", AC97_MIC, 6, 1, 0)};static const snd_kcontrol_new_t snd_ac97_controls_line[2] = {AC97_SINGLE("Line Playback Switch", AC97_LINE, 15, 1, 1),AC97_DOUBLE("Line Playback Volume", AC97_LINE, 8, 0, 31, 1)};static const snd_kcontrol_new_t snd_ac97_controls_cd[2] = {AC97_SINGLE("CD Playback Switch", AC97_CD, 15, 1, 1),AC97_DOUBLE("CD Playback Volume", AC97_CD, 8, 0, 31, 1)};static const snd_kcontrol_new_t snd_ac97_controls_video[2] = {AC97_SINGLE("Video Playback Switch", AC97_VIDEO, 15, 1, 1),AC97_DOUBLE("Video Playback Volume", AC97_VIDEO, 8, 0, 31, 1)};static const snd_kcontrol_new_t snd_ac97_controls_aux[2] = {AC97_SINGLE("Aux Playback Switch", AC97_AUX, 15, 1, 1),AC97_DOUBLE("Aux Playback Volume", AC97_AUX, 8, 0, 31, 1)};static const snd_kcontrol_new_t snd_ac97_controls_pcm[2] = {AC97_SINGLE("PCM Playback Switch", AC97_PCM, 15, 1, 1),AC97_DOUBLE("PCM Playback Volume", AC97_PCM, 8, 0, 31, 1)};static const snd_kcontrol_new_t snd_ac97_controls_capture[3] = {{	iface: SNDRV_CTL_ELEM_IFACE_MIXER,	name: "Capture Source",	info: snd_ac97_info_mux,	get: snd_ac97_get_mux,	put: snd_ac97_put_mux,},AC97_SINGLE("Capture Switch", AC97_REC_GAIN, 15, 1, 1),AC97_DOUBLE("Capture Volume", AC97_REC_GAIN, 8, 0, 15, 0)};static const snd_kcontrol_new_t snd_ac97_controls_mic_capture[2] = {AC97_SINGLE("Mic Capture Switch", AC97_REC_GAIN_MIC, 15, 1, 1),AC97_SINGLE("Mic Capture Volume", AC97_REC_GAIN_MIC, 0, 15, 0)};typedef enum {	AC97_GENERAL_PCM_OUT = 0,	AC97_GENERAL_STEREO_ENHANCEMENT,	AC97_GENERAL_3D,	AC97_GENERAL_LOUDNESS,	AC97_GENERAL_MONO,	AC97_GENERAL_MIC,	AC97_GENERAL_LOOPBACK} ac97_general_index_t;static const snd_kcontrol_new_t snd_ac97_controls_general[7] = {AC97_ENUM_DOUBLE("PCM Out Path & Mute", AC97_GENERAL_PURPOSE, 15, 0),AC97_SINGLE("Simulated Stereo Enhancement", AC97_GENERAL_PURPOSE, 14, 1, 0),AC97_SINGLE("3D Control - Switch", AC97_GENERAL_PURPOSE, 13, 1, 0),AC97_SINGLE("Loudness (bass boost)", AC97_GENERAL_PURPOSE, 12, 1, 0),AC97_ENUM_DOUBLE("Mono Output Select", AC97_GENERAL_PURPOSE, 9, 0),AC97_ENUM_DOUBLE("Mic Select", AC97_GENERAL_PURPOSE, 8, 0),AC97_SINGLE("ADC/DAC Loopback", AC97_GENERAL_PURPOSE, 7, 1, 0)};static const snd_kcontrol_new_t snd_ac97_controls_3d[2] = {AC97_SINGLE("3D Control - Center", AC97_3D_CONTROL, 8, 15, 0),AC97_SINGLE("3D Control - Depth", AC97_3D_CONTROL, 0, 15, 0)};static const snd_kcontrol_new_t snd_ac97_controls_center[2] = {AC97_SINGLE("Center Playback Switch", AC97_CENTER_LFE_MASTER, 7, 1, 1),AC97_SINGLE("Center Playback Volume", AC97_CENTER_LFE_MASTER, 0, 31, 1)};static const snd_kcontrol_new_t snd_ac97_controls_lfe[2] = {AC97_SINGLE("LFE Playback Switch", AC97_CENTER_LFE_MASTER, 15, 1, 1),AC97_SINGLE("LFE Playback Volume", AC97_CENTER_LFE_MASTER, 8, 31, 1)};static const snd_kcontrol_new_t snd_ac97_controls_surround[2] = {AC97_DOUBLE("Surround Playback Switch", AC97_SURROUND_MASTER, 15, 7, 1, 1),AC97_DOUBLE("Surround Playback Volume", AC97_SURROUND_MASTER, 8, 0, 31, 1),};static const snd_kcontrol_new_t snd_ac97_sigmatel_controls[] = {AC97_SINGLE("Sigmatel DAC 6dB Attenuate", AC97_SIGMATEL_ANALOG, 1, 1, 0),AC97_SINGLE("Sigmatel ADC 6dB Attenuate", AC97_SIGMATEL_ANALOG, 0, 1, 0)};static const snd_kcontrol_new_t snd_ac97_control_eapd =AC97_SINGLE("External Amplifier Power Down", AC97_POWERDOWN, 15, 1, 0);static int snd_ac97_spdif_mask_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo){	uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;	uinfo->count = 1;	return 0;}                        static int snd_ac97_spdif_cmask_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t * ucontrol){	ucontrol->value.iec958.status[0] = IEC958_AES0_PROFESSIONAL |					   IEC958_AES0_NONAUDIO |					   IEC958_AES0_CON_EMPHASIS_5015 |					   IEC958_AES0_CON_NOT_COPYRIGHT;	ucontrol->value.iec958.status[1] = IEC958_AES1_CON_CATEGORY |					   IEC958_AES1_CON_ORIGINAL;	ucontrol->value.iec958.status[3] = IEC958_AES3_CON_FS;	return 0;}                        static int snd_ac97_spdif_pmask_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t * ucontrol){	/* FIXME: AC'97 spec doesn't say which bits are used for what */	ucontrol->value.iec958.status[0] = IEC958_AES0_PROFESSIONAL |					   IEC958_AES0_NONAUDIO |					   IEC958_AES0_PRO_FS |					   IEC958_AES0_PRO_EMPHASIS_5015;	return 0;}static int snd_ac97_spdif_default_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t * ucontrol){	ac97_t *ac97 = snd_kcontrol_chip(kcontrol);	spin_lock(&ac97->reg_lock);	ucontrol->value.iec958.status[0] = ac97->spdif_status & 0xff;	ucontrol->value.iec958.status[1] = (ac97->spdif_status >> 8) & 0xff;	ucontrol->value.iec958.status[2] = (ac97->spdif_status >> 16) & 0xff;	ucontrol->value.iec958.status[3] = (ac97->spdif_status >> 24) & 0xff;	spin_unlock(&ac97->reg_lock);	return 0;}                        static int snd_ac97_spdif_default_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t * ucontrol){	ac97_t *ac97 = snd_kcontrol_chip(kcontrol);	unsigned int new = 0;	unsigned short val = 0;	int change = 0;	spin_lock(&ac97->reg_lock);	new = val = ucontrol->value.iec958.status[0] & (IEC958_AES0_PROFESSIONAL|IEC958_AES0_NONAUDIO);	if (ucontrol->value.iec958.status[0] & IEC958_AES0_PROFESSIONAL) {		new |= ucontrol->value.iec958.status[0] & (IEC958_AES0_PRO_FS|IEC958_AES0_PRO_EMPHASIS_5015);		switch (new & IEC958_AES0_PRO_FS) {		case IEC958_AES0_PRO_FS_44100: val |= 0<<12; break;		case IEC958_AES0_PRO_FS_32000: val |= 2<<12; break;		case IEC958_AES0_PRO_FS_48000: val |= 1<<12; break;		default:		       val |= 1<<12; break;		}		if ((new & IEC958_AES0_PRO_EMPHASIS) == IEC958_AES0_PRO_EMPHASIS_5015)			val |= 1<<3;	} else {		new |= ucontrol->value.iec958.status[0] & (IEC958_AES0_CON_EMPHASIS_5015|IEC958_AES0_CON_NOT_COPYRIGHT);		new |= ((ucontrol->value.iec958.status[1] & (IEC958_AES1_CON_CATEGORY|IEC958_AES1_CON_ORIGINAL)) << 8);		new |= ((ucontrol->value.iec958.status[3] & IEC958_AES3_CON_FS) << 8);		if ((new & IEC958_AES0_CON_EMPHASIS) == IEC958_AES0_CON_EMPHASIS_5015)			val |= 1<<3;		if (!(new & IEC958_AES0_CON_NOT_COPYRIGHT))			val |= 1<<2;		val |= ((new >> 8) & 0xff) << 4;	// category + original		switch ((new >> 24) & 0xff) {		case IEC958_AES3_CON_FS_44100: val |= 0<<12; break;		case IEC958_AES3_CON_FS_48000: val |= 2<<12; break;		case IEC958_AES3_CON_FS_32000: val |= 3<<12; break;		default:		       val |= 1<<12; break;		}	}	change = snd_ac97_update_bits(ac97, AC97_SPDIF, 0x3fff, val);	change |= ac97->spdif_status != new;	ac97->spdif_status = new;	spin_unlock(&ac97->reg_lock);	return change;}static const snd_kcontrol_new_t snd_ac97_controls_spdif[5] = {	{		access: SNDRV_CTL_ELEM_ACCESS_READ,		iface: SNDRV_CTL_ELEM_IFACE_MIXER,		name: SNDRV_CTL_NAME_IEC958("",PLAYBACK,CON_MASK),		info: snd_ac97_spdif_mask_info,		get: snd_ac97_spdif_cmask_get,	},	{		access: SNDRV_CTL_ELEM_ACCESS_READ,		iface: SNDRV_CTL_ELEM_IFACE_MIXER,		name: SNDRV_CTL_NAME_IEC958("",PLAYBACK,PRO_MASK),		info: snd_ac97_spdif_mask_info,		get: snd_ac97_spdif_pmask_get,	},	{		iface: SNDRV_CTL_ELEM_IFACE_MIXER,		name: SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),		info: snd_ac97_spdif_mask_info,		get: snd_ac97_spdif_default_get,		put: snd_ac97_spdif_default_put,	},	AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",PLAYBACK,SWITCH),AC97_EXTENDED_STATUS, 2, 1, 0),

⌨️ 快捷键说明

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