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

📄 ac97_codec.c

📁 是关于linux2.5.1的完全源码
💻 C
📖 第 1 页 / 共 5 页
字号:
	AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "AC97-SPSA",AC97_EXTENDED_STATUS, 4, 3, 0)};#define AD18XX_PCM_BITS(xname, codec, shift, mask) \{ iface: SNDRV_CTL_ELEM_IFACE_MIXER, name: xname, info: snd_ac97_ad18xx_pcm_info_bits, \  get: snd_ac97_ad18xx_pcm_get_bits, put: snd_ac97_ad18xx_pcm_put_bits, \  private_value: codec | (shift << 8) | (mask << 16) }static int snd_ac97_ad18xx_pcm_info_bits(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_ad18xx_pcm_get_bits(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){	ac97_t *ac97 = snd_kcontrol_chip(kcontrol);	int codec = kcontrol->private_value & 3;	int shift = (kcontrol->private_value >> 8) & 0xff;	int mask = (kcontrol->private_value >> 16) & 0xff;		ucontrol->value.integer.value[0] = mask - ((ac97->spec.ad18xx.pcmreg[codec] >> shift) & mask);	return 0;}static int snd_ac97_ad18xx_pcm_put_bits(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){	ac97_t *ac97 = snd_kcontrol_chip(kcontrol);	int codec = kcontrol->private_value & 3;	int shift = (kcontrol->private_value >> 8) & 0xff;	int mask = (kcontrol->private_value >> 16) & 0xff;	unsigned short val;		val = mask - (ucontrol->value.integer.value[0] & mask);	return snd_ac97_ad18xx_update_pcm_bits(ac97, codec, mask << shift, val << shift);}#define AD18XX_PCM_VOLUME(xname, codec) \{ iface: SNDRV_CTL_ELEM_IFACE_MIXER, name: xname, info: snd_ac97_ad18xx_pcm_info_volume, \  get: snd_ac97_ad18xx_pcm_get_volume, put: snd_ac97_ad18xx_pcm_put_volume, \  private_value: codec }static int snd_ac97_ad18xx_pcm_info_volume(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo){	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;	uinfo->count = 2;	uinfo->value.integer.min = 0;	uinfo->value.integer.max = 31;	return 0;}static int snd_ac97_ad18xx_pcm_get_volume(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){	ac97_t *ac97 = snd_kcontrol_chip(kcontrol);	int codec = kcontrol->private_value & 3;		spin_lock(&ac97->reg_lock);	ucontrol->value.integer.value[0] = 31 - ((ac97->spec.ad18xx.pcmreg[codec] >> 0) & 31);	ucontrol->value.integer.value[1] = 31 - ((ac97->spec.ad18xx.pcmreg[codec] >> 8) & 31);	spin_unlock(&ac97->reg_lock);	return 0;}static int snd_ac97_ad18xx_pcm_put_volume(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){	ac97_t *ac97 = snd_kcontrol_chip(kcontrol);	int codec = kcontrol->private_value & 3;	unsigned short val1, val2;		val1 = 31 - (ucontrol->value.integer.value[0] & 31);	val2 = 31 - (ucontrol->value.integer.value[1] & 31);	return snd_ac97_ad18xx_update_pcm_bits(ac97, codec, 0x1f1f, (val1 << 8) | val2);}static const snd_kcontrol_new_t snd_ac97_controls_ad18xx_pcm[2] = {AD18XX_PCM_BITS("PCM Playback Switch", 0, 15, 1),AD18XX_PCM_VOLUME("PCM Playback Volume", 0)};static const snd_kcontrol_new_t snd_ac97_controls_ad18xx_surround[2] = {AD18XX_PCM_BITS("Surround Playback Switch", 1, 15, 1),AD18XX_PCM_VOLUME("Surround Playback Volume", 1)};static const snd_kcontrol_new_t snd_ac97_controls_ad18xx_center[2] = {AD18XX_PCM_BITS("Center Playback Switch", 2, 15, 1),AD18XX_PCM_BITS("Center Playback Volume", 2, 8, 31)};static const snd_kcontrol_new_t snd_ac97_controls_ad18xx_lfe[1] = {AD18XX_PCM_BITS("LFE Playback Volume", 2, 0, 31)};/* * */static int snd_ac97_free(ac97_t *ac97){	if (ac97) {		snd_ac97_proc_done(ac97);		if (ac97->private_free)			ac97->private_free(ac97);		snd_magic_kfree(ac97);	}	return 0;}static int snd_ac97_dev_free(snd_device_t *device){	ac97_t *ac97 = snd_magic_cast(ac97_t, device->device_data, return -ENXIO);	return snd_ac97_free(ac97);}static int snd_ac97_try_volume_mix(ac97_t * ac97, int reg){	unsigned short val, mask = 0x8000;	switch (reg) {	case AC97_MASTER_TONE:		return ac97->caps & 0x04 ? 1 : 0;	case AC97_HEADPHONE:		return ac97->caps & 0x10 ? 1 : 0;	case AC97_REC_GAIN_MIC:		return ac97->caps & 0x01 ? 1 : 0;	case AC97_3D_CONTROL:		if (ac97->caps & 0x7c00) {			val = snd_ac97_read(ac97, reg);			/* if nonzero - fixed and we can't set it */			return val == 0;		}		return 0;	case AC97_CENTER_LFE_MASTER:	/* center */		if ((ac97->ext_id & 0x40) == 0)			return 0;		break;	case AC97_CENTER_LFE_MASTER+1:	/* lfe */		if ((ac97->ext_id & 0x100) == 0)			return 0;		reg = AC97_CENTER_LFE_MASTER;		mask = 0x0080;		break;	case AC97_SURROUND_MASTER:		if ((ac97->ext_id & 0x80) == 0)			return 0;		break;	}	val = snd_ac97_read(ac97, reg);	if (!(val & mask)) {		/* nothing seems to be here - mute flag is not set */		/* try another test */		snd_ac97_write_cache_test(ac97, reg, val | mask);		val = snd_ac97_read(ac97, reg);		if (!(val & mask))			return 0;	/* nothing here */	}	return 1;		/* success, useable */}static int snd_ac97_try_bit(ac97_t * ac97, int reg, int bit){	unsigned short mask, val, orig, res;	mask = 1 << bit;	orig = snd_ac97_read(ac97, reg);	val = orig ^ mask;	snd_ac97_write(ac97, reg, val);	res = snd_ac97_read(ac97, reg);	snd_ac97_write_cache(ac97, reg, orig);	return res == val;}static void snd_ac97_change_volume_params1(ac97_t * ac97, int reg, unsigned char *max){	unsigned short val, val1;	*max = 63;	val = 0x8000 | 0x0020;	snd_ac97_write(ac97, reg, val);	val1 = snd_ac97_read(ac97, reg);	if (val != val1) {		*max = 31;	}	/* reset volume to zero */	snd_ac97_write_cache(ac97, reg, 0x8000);}static void snd_ac97_change_volume_params2(ac97_t * ac97, int reg, int shift, unsigned char *max){	unsigned short val, val1;	*max = 63;	val = 0x8080 | (0x20 << shift);	snd_ac97_write(ac97, reg, val);	val1 = snd_ac97_read(ac97, reg);	if (val != val1) {		*max = 31;	}	/* reset volume to zero */	snd_ac97_write_cache(ac97, reg, 0x8080);}static inline int printable(unsigned int x){	x &= 0xff;	if (x < ' ' || x >= 0x71) {		if (x <= 0x89)			return x - 0x71 + 'A';		return '?';	}	return x;}static snd_kcontrol_t *snd_ac97_cnew(const snd_kcontrol_new_t *_template, ac97_t * ac97){	snd_kcontrol_new_t template;	memcpy(&template, _template, sizeof(template));	snd_runtime_check(!template.index, return NULL);	template.index = ac97->num;	return snd_ctl_new1(&template, ac97);}static int snd_ac97_mixer_build(snd_card_t * card, ac97_t * ac97){	snd_kcontrol_t *kctl;	int err, idx;	unsigned char max;	/* build master controls */	/* AD claims to remove this control from AD1887, although spec v2.2 don't allow this */	if (snd_ac97_try_volume_mix(ac97, AC97_MASTER)) {		if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_master[0], ac97))) < 0)			return err;		if ((err = snd_ctl_add(card, kctl = snd_ac97_cnew(&snd_ac97_controls_master[1], ac97))) < 0)			return err;		snd_ac97_change_volume_params1(ac97, AC97_MASTER, &max);		kctl->private_value &= ~(0xff << 16);		kctl->private_value |= (int)max << 16;		snd_ac97_write_cache(ac97, AC97_MASTER, 0x8000 | max | (max << 8));	}	ac97->regs[AC97_CENTER_LFE_MASTER] = 0x8080;	/* build center controls */	if (snd_ac97_try_volume_mix(ac97, AC97_CENTER_LFE_MASTER)) {		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;		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)) {		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;		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)) {		if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_surround[0], ac97))) < 0)			return err;		if ((err = snd_ctl_add(card, kctl = snd_ac97_cnew(&snd_ac97_controls_surround[1], ac97))) < 0)			return err;		snd_ac97_change_volume_params2(ac97, AC97_SURROUND_MASTER, 0, &max);		kctl->private_value &= ~(0xff << 16);		kctl->private_value |= (int)max << 16;		snd_ac97_write_cache(ac97, AC97_SURROUND_MASTER, 0x8080 | max | (max << 8));	}	/* build headphone controls */	if (snd_ac97_try_volume_mix(ac97, AC97_HEADPHONE)) {		if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_headphone[0], ac97))) < 0)			return err;		if ((err = snd_ctl_add(card, kctl = snd_ac97_cnew(&snd_ac97_controls_headphone[1], ac97))) < 0)			return err;		snd_ac97_change_volume_params1(ac97, AC97_HEADPHONE, &max);		kctl->private_value &= ~(0xff << 16);		kctl->private_value |= (int)max << 16;		snd_ac97_write_cache(ac97, AC97_HEADPHONE, 0x8000 | max | (max << 8));	}		/* build master mono controls */	if (snd_ac97_try_volume_mix(ac97, AC97_MASTER_MONO)) {		if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_master_mono[0], ac97))) < 0)			return err;		if ((err = snd_ctl_add(card, kctl = snd_ac97_cnew(&snd_ac97_controls_master_mono[1], ac97))) < 0)			return err;		snd_ac97_change_volume_params1(ac97, AC97_MASTER_MONO, &max);		kctl->private_value &= ~(0xff << 16);		kctl->private_value |= (int)max << 16;		snd_ac97_write_cache(ac97, AC97_MASTER_MONO, 0x8000 | max);	}		/* build master tone controls */	if (snd_ac97_try_volume_mix(ac97, AC97_MASTER_TONE)) {		for (idx = 0; idx < 2; idx++)			if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_tone[idx], ac97))) < 0)				return err;		snd_ac97_write_cache(ac97, AC97_MASTER_TONE, 0x0f0f);	}		/* build PC Speaker controls */	if ((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, snd_ac97_cnew(&snd_ac97_controls_pc_beep[idx], ac97))) < 0)				return err;		snd_ac97_write_cache(ac97, AC97_PC_BEEP, 0x801e);	}		/* build Phone controls */	if (snd_ac97_try_volume_mix(ac97, AC97_PHONE)) {		for (idx = 0; idx < 2; idx++)			if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_phone[idx], ac97))) < 0)				return err;		snd_ac97_write_cache(ac97, AC97_PHONE, 0x801f);	}		/* build MIC controls */	for (idx = 0; idx < 3; idx++)		if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_mic[idx], ac97))) < 0)			return err;	snd_ac97_write_cache(ac97, AC97_MIC, 0x801f);	/* build Line controls */	for (idx = 0; idx < 2; idx++)		if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_line[idx], ac97))) < 0)			return err;	snd_ac97_write_cache(ac97, AC97_LINE, 0x9f1f);		/* build CD controls */	for (idx = 0; idx < 2; idx++)		if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_cd[idx], ac97))) < 0)			return err;	snd_ac97_write_cache(ac97, AC97_CD, 0x9f1f);		/* build Video controls */	if (snd_ac97_try_volume_mix(ac97, AC97_VIDEO)) {		for (idx = 0; idx < 2; idx++)			if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_video[idx], ac97))) < 0)				return err;		snd_ac97_write_cache(ac97, AC97_VIDEO, 0x9f1f);	}	/* build Aux controls */	if (snd_ac97_try_volume_mix(ac97, AC97_AUX)) {		for (idx = 0; idx < 2; idx++)			if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_aux[idx], ac97))) < 0)				return err;		snd_ac97_write_cache(ac97, AC97_AUX, 0x9f1f);	}	/* build PCM controls */	if (ac97->flags & AC97_AD_MULTI) {		for (idx = 0; idx < 2; idx++)			if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_ad18xx_pcm[idx], ac97))) < 0)				return err;		ac97->spec.ad18xx.pcmreg[0] = 0x9f1f;		if (ac97->scaps & AC97_SCAP_SURROUND_DAC) {			for (idx = 0; idx < 2; idx++)				if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_ad18xx_surround[idx], ac97))) < 0)					return err;			ac97->spec.ad18xx.pcmreg[1] = 0x9f1f;		}		if (ac97->scaps & AC97_SCAP_CENTER_LFE_DAC) {			for (idx = 0; idx < 2; idx++)				if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_ad18xx_center[idx], ac97))) < 0)					return err;			if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_ad18xx_lfe[0], ac97))) < 0)				return err;			ac97->spec.ad18xx.pcmreg[2] = 0x9f1f;		}	} else {

⌨️ 快捷键说明

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