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

📄 ac97_patch.c

📁 鼎力推荐!本程序是基于嵌入式LUNUX系统开发的源程序代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	if (ac97->id == 0x414c4780) /* ALC658 */		val &= ~(1 << 1); /* Pin 47 is spdif input pin */	else /* ALC655 */		val |= (1 << 1); /* Pin 47 is spdif input pin */	val &= ~(1 << 12); /* vref enable */	snd_ac97_write_cache(ac97, 0x7a, val);	/* set default: spdif-in enabled,	   spdif-in monitor off, spdif-in PCM off	   center on mic off, surround on line-in off	   duplicate front off	*/	snd_ac97_write_cache(ac97, AC97_ALC650_MULTICH, 1<<15);	/* full DAC volume */	snd_ac97_write_cache(ac97, AC97_ALC650_SURR_DAC_VOL, 0x0808);	snd_ac97_write_cache(ac97, AC97_ALC650_LFE_DAC_VOL, 0x0808);	return 0;}#define AC97_ALC850_JACK_SELECT	0x76#define AC97_ALC850_MISC1	0x7astatic int ac97_alc850_surround_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t * ucontrol){        ac97_t *ac97 = snd_kcontrol_chip(kcontrol);        ucontrol->value.integer.value[0] = ((ac97->regs[AC97_ALC850_JACK_SELECT] >> 12) & 7) == 2;        return 0;}static int ac97_alc850_surround_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t * ucontrol){        ac97_t *ac97 = snd_kcontrol_chip(kcontrol);	/* SURR 1kOhm (bit4), Amp (bit5) */	snd_ac97_update_bits(ac97, AC97_ALC850_MISC1, (1<<4)|(1<<5),			     ucontrol->value.integer.value[0] ? (1<<5) : (1<<4));	/* LINE-IN = 0, SURROUND = 2 */	return snd_ac97_update_bits(ac97, AC97_ALC850_JACK_SELECT, 7 << 12,				    ucontrol->value.integer.value[0] ? (2<<12) : (0<<12));}static int ac97_alc850_mic_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t * ucontrol){        ac97_t *ac97 = snd_kcontrol_chip(kcontrol);        ucontrol->value.integer.value[0] = ((ac97->regs[AC97_ALC850_JACK_SELECT] >> 4) & 7) == 2;        return 0;}static int ac97_alc850_mic_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t * ucontrol){        ac97_t *ac97 = snd_kcontrol_chip(kcontrol);	/* Vref disable (bit12), 1kOhm (bit13) */	snd_ac97_update_bits(ac97, AC97_ALC850_MISC1, (1<<12)|(1<<13),			     ucontrol->value.integer.value[0] ? (1<<12) : (1<<13));	/* MIC-IN = 1, CENTER-LFE = 2 */	return snd_ac97_update_bits(ac97, AC97_ALC850_JACK_SELECT, 7 << 4,				    ucontrol->value.integer.value[0] ? (2<<4) : (1<<4));}static const snd_kcontrol_new_t snd_ac97_controls_alc850[] = {	AC97_PAGE_SINGLE("Duplicate Front", AC97_ALC650_MULTICH, 0, 1, 0, 0),	{		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,		.name = "Line-In As Surround",		.info = snd_ac97_info_volsw,		.get = ac97_alc850_surround_get,		.put = ac97_alc850_surround_put,		.private_value = AC97_SINGLE_VALUE(0, 0, 1, 0) /* only mask needed */	},	{		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,		.name = "Mic As Center/LFE",		.info = snd_ac97_info_volsw,		.get = ac97_alc850_mic_get,		.put = ac97_alc850_mic_put,		.private_value = AC97_SINGLE_VALUE(0, 0, 1, 0) /* only mask needed */	},};static int patch_alc850_specific(ac97_t *ac97){	int err;	if ((err = patch_build_controls(ac97, snd_ac97_controls_alc850, ARRAY_SIZE(snd_ac97_controls_alc850))) < 0)		return err;	if (ac97->ext_id & AC97_EI_SPDIF) {		if ((err = patch_build_controls(ac97, snd_ac97_spdif_controls_alc655, ARRAY_SIZE(snd_ac97_spdif_controls_alc655))) < 0)			return err;	}	return 0;}static struct snd_ac97_build_ops patch_alc850_ops = {	.build_specific	= patch_alc850_specific};int patch_alc850(ac97_t *ac97){	ac97->build_ops = &patch_alc850_ops;	ac97->spec.dev_flags = 0; /* for IEC958 playback route - ALC655 compatible */	/* assume only page 0 for writing cache */	snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, AC97_PAGE_VENDOR);	/* adjust default values */	/* set default: spdif-in enabled,	   spdif-in monitor off, spdif-in PCM off	   center on mic off, surround on line-in off	   duplicate front off	*/	snd_ac97_write_cache(ac97, AC97_ALC650_MULTICH, 1<<15);	/* SURR_OUT: on, Surr 1kOhm: on, Surr Amp: off, Front 1kOhm: off	 * Front Amp: on, Vref: enable, Center 1kOhm: on, Mix: on	 */	snd_ac97_write_cache(ac97, 0x7a, (1<<1)|(1<<4)|(0<<5)|(1<<6)|			     (1<<7)|(0<<12)|(1<<13)|(0<<14));	/* detection UIO2,3: all path floating, UIO3: MIC, Vref2: disable,	 * UIO1: FRONT, Vref3: disable, UIO3: LINE, Front-Mic: mute	 */	snd_ac97_write_cache(ac97, 0x76, (0<<0)|(0<<2)|(1<<4)|(1<<7)|(2<<8)|			     (1<<11)|(0<<12)|(1<<15));	/* full DAC volume */	snd_ac97_write_cache(ac97, AC97_ALC650_SURR_DAC_VOL, 0x0808);	snd_ac97_write_cache(ac97, AC97_ALC650_LFE_DAC_VOL, 0x0808);	return 0;}/* * C-Media CM97xx codecs */static const snd_kcontrol_new_t snd_ac97_cm9738_controls[] = {	AC97_SINGLE("Line-In As Surround", AC97_CM9738_VENDOR_CTRL, 10, 1, 0),	AC97_SINGLE("Duplicate Front", AC97_CM9738_VENDOR_CTRL, 13, 1, 0),};static int patch_cm9738_specific(ac97_t * ac97){	return patch_build_controls(ac97, snd_ac97_cm9738_controls, ARRAY_SIZE(snd_ac97_cm9738_controls));}static struct snd_ac97_build_ops patch_cm9738_ops = {	.build_specific	= patch_cm9738_specific};int patch_cm9738(ac97_t * ac97){	ac97->build_ops = &patch_cm9738_ops;	/* FIXME: can anyone confirm below? */	/* CM9738 has no PCM volume although the register reacts */	ac97->flags |= AC97_HAS_NO_PCM_VOL;	snd_ac97_write_cache(ac97, AC97_PCM, 0x8000);	return 0;}static int snd_ac97_cmedia_spdif_playback_source_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo){	static char *texts[] = { "Analog", "Digital" };	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_cmedia_spdif_playback_source_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){	ac97_t *ac97 = snd_kcontrol_chip(kcontrol);	unsigned short val;	val = ac97->regs[AC97_CM9739_SPDIF_CTRL];	ucontrol->value.enumerated.item[0] = (val >> 1) & 0x01;	return 0;}static int snd_ac97_cmedia_spdif_playback_source_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){	ac97_t *ac97 = snd_kcontrol_chip(kcontrol);	return snd_ac97_update_bits(ac97, AC97_CM9739_SPDIF_CTRL,				    0x01 << 1, 				    (ucontrol->value.enumerated.item[0] & 0x01) << 1);}static const snd_kcontrol_new_t snd_ac97_cm9739_controls_spdif[] = {	/* BIT 0: SPDI_EN - always true */	{ /* BIT 1: SPDIFS */		.iface	= SNDRV_CTL_ELEM_IFACE_MIXER,		.name	= SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",		.info	= snd_ac97_cmedia_spdif_playback_source_info,		.get	= snd_ac97_cmedia_spdif_playback_source_get,		.put	= snd_ac97_cmedia_spdif_playback_source_put,	},	/* BIT 2: IG_SPIV */	AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,NONE) "Valid Switch", AC97_CM9739_SPDIF_CTRL, 2, 1, 0),	/* BIT 3: SPI2F */	AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,NONE) "Monitor", AC97_CM9739_SPDIF_CTRL, 3, 1, 0), 	/* BIT 4: SPI2SDI */	AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH), AC97_CM9739_SPDIF_CTRL, 4, 1, 0),	/* BIT 8: SPD32 - 32bit SPDIF - not supported yet */};static int snd_ac97_cm9739_center_mic_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){	ac97_t *ac97 = snd_kcontrol_chip(kcontrol);	if (ac97->regs[AC97_CM9739_MULTI_CHAN] & 0x1000)		ucontrol->value.integer.value[0] = 1;	else		ucontrol->value.integer.value[0] = 0;	return 0;}static int snd_ac97_cm9739_center_mic_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){	ac97_t *ac97 = snd_kcontrol_chip(kcontrol);	return snd_ac97_update_bits(ac97, AC97_CM9739_MULTI_CHAN, 0x3000,				    ucontrol->value.integer.value[0] ? 				    0x1000 : 0x2000);}static const snd_kcontrol_new_t snd_ac97_cm9739_controls[] = {	AC97_SINGLE("Line-In As Surround", AC97_CM9739_MULTI_CHAN, 10, 1, 0),	{		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,		.name = "Mic As Center/LFE",		.info = snd_ac97_info_volsw,		.get = snd_ac97_cm9739_center_mic_get,		.put = snd_ac97_cm9739_center_mic_put,		.private_value = AC97_SINGLE_VALUE(0, 0, 1, 0) /* only mask needed */	},};static int patch_cm9739_specific(ac97_t * ac97){	return patch_build_controls(ac97, snd_ac97_cm9739_controls, ARRAY_SIZE(snd_ac97_cm9739_controls));}static int patch_cm9739_post_spdif(ac97_t * ac97){	return patch_build_controls(ac97, snd_ac97_cm9739_controls_spdif, ARRAY_SIZE(snd_ac97_cm9739_controls_spdif));}static struct snd_ac97_build_ops patch_cm9739_ops = {	.build_specific	= patch_cm9739_specific,	.build_post_spdif = patch_cm9739_post_spdif};int patch_cm9739(ac97_t * ac97){	unsigned short val;	ac97->build_ops = &patch_cm9739_ops;	/* CM9739/A has no Master and PCM volume although the register reacts */	ac97->flags |= AC97_HAS_NO_MASTER_VOL | AC97_HAS_NO_PCM_VOL;	snd_ac97_write_cache(ac97, AC97_MASTER, 0x8000);	snd_ac97_write_cache(ac97, AC97_PCM, 0x8000);	/* check spdif */	val = snd_ac97_read(ac97, AC97_EXTENDED_STATUS);	if (val & AC97_EA_SPCV) {		/* enable spdif in */		snd_ac97_write_cache(ac97, AC97_CM9739_SPDIF_CTRL,				     snd_ac97_read(ac97, AC97_CM9739_SPDIF_CTRL) | 0x01);		ac97->rates[AC97_RATES_SPDIF] = SNDRV_PCM_RATE_48000; /* 48k only */	} else {		ac97->ext_id &= ~AC97_EI_SPDIF; /* disable extended-id */		ac97->rates[AC97_RATES_SPDIF] = 0;	}	/* set-up multi channel */	/* bit 14: 0 = SPDIF, 1 = EAPD */	/* bit 13: enable internal vref output for mic */	/* bit 12: disable center/lfe (swithable) */	/* bit 10: disable surround/line (switchable) */	/* bit 9: mix 2 surround off */	/* bit 4: undocumented; 0 mutes the CM9739A, which defaults to 1 */	/* bit 3: undocumented; surround? */	/* bit 0: dB */	val = snd_ac97_read(ac97, AC97_CM9739_MULTI_CHAN) & (1 << 4);	val |= (1 << 3);	val |= (1 << 13);	if (! (ac97->ext_id & AC97_EI_SPDIF))		val |= (1 << 14);	snd_ac97_write_cache(ac97, AC97_CM9739_MULTI_CHAN, val);	/* FIXME: set up GPIO */	snd_ac97_write_cache(ac97, 0x70, 0x0100);	snd_ac97_write_cache(ac97, 0x72, 0x0020);	/* Special exception for ASUS W1000/CMI9739. It does not have an SPDIF in. */	if (ac97->pci &&	     ac97->subsystem_vendor == 0x1043 &&	     ac97->subsystem_device == 0x1843) {		snd_ac97_write_cache(ac97, AC97_CM9739_SPDIF_CTRL,			snd_ac97_read(ac97, AC97_CM9739_SPDIF_CTRL) & ~0x01);		snd_ac97_write_cache(ac97, AC97_CM9739_MULTI_CHAN,			snd_ac97_read(ac97, AC97_CM9739_MULTI_CHAN) | (1 << 14));	}	return 0;}#define AC97_CM9761_MULTI_CHAN	0x64#define AC97_CM9761_SPDIF_CTRL	0x6cstatic int snd_ac97_cm9761_linein_rear_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){	ac97_t *ac97 = snd_kcontrol_chip(kcontrol);	if (ac97->regs[AC97_CM9739_MULTI_CHAN] & 0x0400)		ucontrol->value.integer.value[0] = 1;	else		ucontrol->value.integer.value[0] = 0;	return 0;}static int snd_ac97_cm9761_linein_rear_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){	ac97_t *ac97 = snd_kcontrol_chip(kcontrol);	unsigned short vals[2][2] = {		{ 0x0008, 0x0400 }, /* off, on */		{ 0x0000, 0x0408 }, /* off, on (9761-82 rev.B) */	};	return snd_ac97_update_bits(ac97, AC97_CM9739_MULTI_CHAN, 0x0408,				    vals[ac97->spec.dev_flags][!!ucontrol->value.integer.value[0]]);}static int snd_ac97_cm9761_center_mic_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){	ac97_t *ac97 = snd_kcontrol_chip(kcontrol);	if (ac97->regs[AC97_CM9739_MULTI_CHAN] & 0x1000)		ucontrol->value.integer.value[0] = 1;	else		ucontrol->value.integer.value[0] = 0;	if (ac97->spec.dev_flags) /* 9761-82 rev.B */		ucontrol->value.integer.value[0] = !ucontrol->value.integer.value[0];	return 0;}static int snd_ac97_cm9761_center_mic_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){	ac97_t *ac97 = snd_kcontrol_chip(kcontrol);	unsigned short vals[2][2] = {		{ 0x2000, 0x1880 }, /* off, on */		{ 0x1000, 0x2880 }, /* off, on (9761-82 rev.B) */	};	return snd_ac97_update_bits(ac97, AC97_CM9739_MULTI_CHAN, 0x3880,				    vals[ac97->spec.dev_flags][!!ucontrol->value.integer.value[0]]);}static const snd_kcontrol_new_t snd_ac97_cm9761_controls[] = {	{		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,		.name = "Line-In As Surround",		.info = snd_ac97_info_volsw,		.get = snd_ac97_cm9761_linein_rear_get,		.put = snd_ac97_cm9761_linein_rear_put,		.private_value = AC97_SINGLE_VALUE(0, 0, 1, 0) /* only mask needed */	},	{		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,		.name = "Mic As Center/LFE",		.info = snd_ac97_info_volsw,		.get = snd_ac97_cm9761_center_mic_get,		.put = snd_ac97_cm9761_center_mic_put,		.private_value = AC97_SINGLE_VALUE(0, 0, 1, 0) /* only mask needed */	},};static int patch_cm9761_specific(ac97_t * ac97){	return patch_build_controls(ac97, snd_ac97_cm9761_controls, ARRAY_SIZE(snd_ac97_cm9761_controls));}static struct snd_ac97_build_ops patch_cm9761_ops = {	.build_specific	= patch_cm9761_specific,	.build_post_spdif = patch_cm9739_post_spdif /* hope it's identical... */};int patch_cm9761(ac97_t *ac97){	unsigned short val;	/* CM9761 has no Master and PCM volume although the register reacts */	ac97->flags |= AC97_HAS_NO_MASTER_VOL | AC97_HAS_NO_PCM_VOL;	snd_ac97_write_cache(ac97, AC97_MASTER, 0x8000);	snd_ac97_write_cache(ac97, AC97_PCM, 0x8000);	ac97->spec.dev_flags = 0; /* 1 = model 82 revision B */	if (ac97->id == AC97_ID_CM9761_82) {		unsigned short tmp;		/* check page 1, reg 0x60 */		val = snd_ac97_read(ac97, AC97_INT_PAGING);		sn

⌨️ 快捷键说明

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