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

📄 ymfpci_main.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 5 页
字号:
	.put =		snd_ymfpci_spdif_stream_put};static int snd_ymfpci_drec_source_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *info){	static char *texts[3] = {"AC'97", "IEC958", "ZV Port"};	info->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;	info->count = 1;	info->value.enumerated.items = 3;	if (info->value.enumerated.item > 2)		info->value.enumerated.item = 2;	strcpy(info->value.enumerated.name, texts[info->value.enumerated.item]);	return 0;}static int snd_ymfpci_drec_source_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *value){	ymfpci_t *chip = snd_kcontrol_chip(kcontrol);	u16 reg;	spin_lock_irq(&chip->reg_lock);	reg = snd_ymfpci_readw(chip, YDSXGR_GLOBALCTRL);	spin_unlock_irq(&chip->reg_lock);	if (!(reg & 0x100))		value->value.enumerated.item[0] = 0;	else		value->value.enumerated.item[0] = 1 + ((reg & 0x200) != 0);	return 0;}static int snd_ymfpci_drec_source_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *value){	ymfpci_t *chip = snd_kcontrol_chip(kcontrol);	u16 reg, old_reg;	spin_lock_irq(&chip->reg_lock);	old_reg = snd_ymfpci_readw(chip, YDSXGR_GLOBALCTRL);	if (value->value.enumerated.item[0] == 0)		reg = old_reg & ~0x100;	else		reg = (old_reg & ~0x300) | 0x100 | ((value->value.enumerated.item[0] == 2) << 9);	snd_ymfpci_writew(chip, YDSXGR_GLOBALCTRL, reg);	spin_unlock_irq(&chip->reg_lock);	return reg != old_reg;}static snd_kcontrol_new_t snd_ymfpci_drec_source __devinitdata = {	.access =	SNDRV_CTL_ELEM_ACCESS_READWRITE,	.iface =	SNDRV_CTL_ELEM_IFACE_MIXER,	.name =		"Direct Recording Source",	.info =		snd_ymfpci_drec_source_info,	.get =		snd_ymfpci_drec_source_get,	.put =		snd_ymfpci_drec_source_put};/* *  Mixer controls */#define YMFPCI_SINGLE(xname, xindex, reg, shift) \{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \  .info = snd_ymfpci_info_single, \  .get = snd_ymfpci_get_single, .put = snd_ymfpci_put_single, \  .private_value = ((reg) | ((shift) << 16)) }static int snd_ymfpci_info_single(snd_kcontrol_t *kcontrol,				  snd_ctl_elem_info_t *uinfo){	int reg = kcontrol->private_value & 0xffff;	switch (reg) {	case YDSXGR_SPDIFOUTCTRL: break;	case YDSXGR_SPDIFINCTRL: break;	default: return -EINVAL;	}	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;	uinfo->count = 1;	uinfo->value.integer.min = 0;	uinfo->value.integer.max = 1;	return 0;}static int snd_ymfpci_get_single(snd_kcontrol_t *kcontrol,				 snd_ctl_elem_value_t *ucontrol){	ymfpci_t *chip = snd_kcontrol_chip(kcontrol);	int reg = kcontrol->private_value & 0xffff;	unsigned int shift = (kcontrol->private_value >> 16) & 0xff;	unsigned int mask = 1;		switch (reg) {	case YDSXGR_SPDIFOUTCTRL: break;	case YDSXGR_SPDIFINCTRL: break;	default: return -EINVAL;	}	ucontrol->value.integer.value[0] =		(snd_ymfpci_readl(chip, reg) >> shift) & mask;	return 0;}static int snd_ymfpci_put_single(snd_kcontrol_t *kcontrol,				 snd_ctl_elem_value_t *ucontrol){	ymfpci_t *chip = snd_kcontrol_chip(kcontrol);	int reg = kcontrol->private_value & 0xffff;	unsigned int shift = (kcontrol->private_value >> 16) & 0xff; 	unsigned int mask = 1;	int change;	unsigned int val, oval;		switch (reg) {	case YDSXGR_SPDIFOUTCTRL: break;	case YDSXGR_SPDIFINCTRL: break;	default: return -EINVAL;	}	val = (ucontrol->value.integer.value[0] & mask);	val <<= shift;	spin_lock_irq(&chip->reg_lock);	oval = snd_ymfpci_readl(chip, reg);	val = (oval & ~(mask << shift)) | val;	change = val != oval;	snd_ymfpci_writel(chip, reg, val);	spin_unlock_irq(&chip->reg_lock);	return change;}#define YMFPCI_DOUBLE(xname, xindex, reg) \{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \  .info = snd_ymfpci_info_double, \  .get = snd_ymfpci_get_double, .put = snd_ymfpci_put_double, \  .private_value = reg }static int snd_ymfpci_info_double(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo){	unsigned int reg = kcontrol->private_value;	if (reg < 0x80 || reg >= 0xc0)		return -EINVAL;	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;	uinfo->count = 2;	uinfo->value.integer.min = 0;	uinfo->value.integer.max = 16383;	return 0;}static int snd_ymfpci_get_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){	ymfpci_t *chip = snd_kcontrol_chip(kcontrol);	unsigned int reg = kcontrol->private_value;	unsigned int shift_left = 0, shift_right = 16, mask = 16383;	unsigned int val;		if (reg < 0x80 || reg >= 0xc0)		return -EINVAL;	spin_lock_irq(&chip->reg_lock);	val = snd_ymfpci_readl(chip, reg);	spin_unlock_irq(&chip->reg_lock);	ucontrol->value.integer.value[0] = (val >> shift_left) & mask;	ucontrol->value.integer.value[1] = (val >> shift_right) & mask;	return 0;}static int snd_ymfpci_put_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){	ymfpci_t *chip = snd_kcontrol_chip(kcontrol);	unsigned int reg = kcontrol->private_value;	unsigned int shift_left = 0, shift_right = 16, mask = 16383;	int change;	unsigned int val1, val2, oval;		if (reg < 0x80 || reg >= 0xc0)		return -EINVAL;	val1 = ucontrol->value.integer.value[0] & mask;	val2 = ucontrol->value.integer.value[1] & mask;	val1 <<= shift_left;	val2 <<= shift_right;	spin_lock_irq(&chip->reg_lock);	oval = snd_ymfpci_readl(chip, reg);	val1 = (oval & ~((mask << shift_left) | (mask << shift_right))) | val1 | val2;	change = val1 != oval;	snd_ymfpci_writel(chip, reg, val1);	spin_unlock_irq(&chip->reg_lock);	return change;}/* * 4ch duplication */static int snd_ymfpci_info_dup4ch(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo){	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;	uinfo->count = 1;	uinfo->value.integer.min = 0;	uinfo->value.integer.max = 1;	return 0;}static int snd_ymfpci_get_dup4ch(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){	ymfpci_t *chip = snd_kcontrol_chip(kcontrol);	ucontrol->value.integer.value[0] = chip->mode_dup4ch;	return 0;}static int snd_ymfpci_put_dup4ch(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){	ymfpci_t *chip = snd_kcontrol_chip(kcontrol);	int change;	change = (ucontrol->value.integer.value[0] != chip->mode_dup4ch);	if (change)		chip->mode_dup4ch = !!ucontrol->value.integer.value[0];	return change;}static snd_kcontrol_new_t snd_ymfpci_controls[] __devinitdata = {YMFPCI_DOUBLE("Wave Playback Volume", 0, YDSXGR_NATIVEDACOUTVOL),YMFPCI_DOUBLE("Wave Capture Volume", 0, YDSXGR_NATIVEDACLOOPVOL),YMFPCI_DOUBLE("Digital Capture Volume", 0, YDSXGR_NATIVEDACINVOL),YMFPCI_DOUBLE("Digital Capture Volume", 1, YDSXGR_NATIVEADCINVOL),YMFPCI_DOUBLE("ADC Playback Volume", 0, YDSXGR_PRIADCOUTVOL),YMFPCI_DOUBLE("ADC Capture Volume", 0, YDSXGR_PRIADCLOOPVOL),YMFPCI_DOUBLE("ADC Playback Volume", 1, YDSXGR_SECADCOUTVOL),YMFPCI_DOUBLE("ADC Capture Volume", 1, YDSXGR_SECADCLOOPVOL),YMFPCI_DOUBLE("FM Legacy Volume", 0, YDSXGR_LEGACYOUTVOL),YMFPCI_DOUBLE(SNDRV_CTL_NAME_IEC958("AC97 ", PLAYBACK,VOLUME), 0, YDSXGR_ZVOUTVOL),YMFPCI_DOUBLE(SNDRV_CTL_NAME_IEC958("", CAPTURE,VOLUME), 0, YDSXGR_ZVLOOPVOL),YMFPCI_DOUBLE(SNDRV_CTL_NAME_IEC958("AC97 ",PLAYBACK,VOLUME), 1, YDSXGR_SPDIFOUTVOL),YMFPCI_DOUBLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,VOLUME), 1, YDSXGR_SPDIFLOOPVOL),YMFPCI_SINGLE(SNDRV_CTL_NAME_IEC958("",PLAYBACK,SWITCH), 0, YDSXGR_SPDIFOUTCTRL, 0),YMFPCI_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH), 0, YDSXGR_SPDIFINCTRL, 0),YMFPCI_SINGLE(SNDRV_CTL_NAME_IEC958("Loop",NONE,NONE), 0, YDSXGR_SPDIFINCTRL, 4),{	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,	.name = "4ch Duplication",	.info = snd_ymfpci_info_dup4ch,	.get = snd_ymfpci_get_dup4ch,	.put = snd_ymfpci_put_dup4ch,},};/* * GPIO */static int snd_ymfpci_get_gpio_out(ymfpci_t *chip, int pin){	u16 reg, mode;	unsigned long flags;	spin_lock_irqsave(&chip->reg_lock, flags);	reg = snd_ymfpci_readw(chip, YDSXGR_GPIOFUNCENABLE);	reg &= ~(1 << (pin + 8));	reg |= (1 << pin);	snd_ymfpci_writew(chip, YDSXGR_GPIOFUNCENABLE, reg);	/* set the level mode for input line */	mode = snd_ymfpci_readw(chip, YDSXGR_GPIOTYPECONFIG);	mode &= ~(3 << (pin * 2));	snd_ymfpci_writew(chip, YDSXGR_GPIOTYPECONFIG, mode);	snd_ymfpci_writew(chip, YDSXGR_GPIOFUNCENABLE, reg | (1 << (pin + 8)));	mode = snd_ymfpci_readw(chip, YDSXGR_GPIOINSTATUS);	spin_unlock_irqrestore(&chip->reg_lock, flags);	return (mode >> pin) & 1;}static int snd_ymfpci_set_gpio_out(ymfpci_t *chip, int pin, int enable){	u16 reg;	unsigned long flags;	spin_lock_irqsave(&chip->reg_lock, flags);	reg = snd_ymfpci_readw(chip, YDSXGR_GPIOFUNCENABLE);	reg &= ~(1 << pin);	reg &= ~(1 << (pin + 8));	snd_ymfpci_writew(chip, YDSXGR_GPIOFUNCENABLE, reg);	snd_ymfpci_writew(chip, YDSXGR_GPIOOUTCTRL, enable << pin);	snd_ymfpci_writew(chip, YDSXGR_GPIOFUNCENABLE, reg | (1 << (pin + 8)));	spin_unlock_irqrestore(&chip->reg_lock, flags);	return 0;}static int snd_ymfpci_gpio_sw_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo){	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;	uinfo->count = 1;	uinfo->value.integer.min = 0;	uinfo->value.integer.max = 1;	return 0;}static int snd_ymfpci_gpio_sw_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol){	ymfpci_t *chip = snd_kcontrol_chip(kcontrol);	int pin = (int)kcontrol->private_value;	ucontrol->value.integer.value[0] = snd_ymfpci_get_gpio_out(chip, pin);	return 0;}static int snd_ymfpci_gpio_sw_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol){	ymfpci_t *chip = snd_kcontrol_chip(kcontrol);	int pin = (int)kcontrol->private_value;	if (snd_ymfpci_get_gpio_out(chip, pin) != ucontrol->value.integer.value[0]) {		snd_ymfpci_set_gpio_out(chip, pin, !!ucontrol->value.integer.value[0]);		ucontrol->value.integer.value[0] = snd_ymfpci_get_gpio_out(chip, pin);		return 1;	}	return 0;}static snd_kcontrol_new_t snd_ymfpci_rear_shared __devinitdata = {	.name = "Shared Rear/Line-In Switch",	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,	.info = snd_ymfpci_gpio_sw_info,	.get = snd_ymfpci_gpio_sw_get,	.put = snd_ymfpci_gpio_sw_put,	.private_value = 2,};/* * PCM voice volume */static int snd_ymfpci_pcm_vol_info(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 = 0x8000;	return 0;}static int snd_ymfpci_pcm_vol_get(snd_kcontrol_t *kcontrol,				  snd_ctl_elem_value_t *ucontrol){	ymfpci_t *chip = snd_kcontrol_chip(kcontrol);	unsigned int subs = kcontrol->id.subdevice;	ucontrol->value.integer.value[0] = chip->pcm_mixer[subs].left;	ucontrol->value.integer.value[1] = chip->pcm_mixer[subs].right;	return 0;}static int snd_ymfpci_pcm_vol_put(snd_kcontrol_t *kcontrol,				  snd_ctl_elem_value_t *ucontrol){	ymfpci_t *chip = snd_kcontrol_chip(kcontrol);	unsigned int subs = kcontrol->id.subdevice;	snd_pcm_substream_t *substream;	unsigned long flags;	if (ucontrol->value.integer.value[0] != chip->pcm_mixer[subs].left ||	    ucontrol->value.integer.value[1] != chip->pcm_mixer[subs].right) {		chip->pcm_mixer[subs].left = ucontrol->value.integer.value[0];		chip->pcm_mixer[subs].right = ucontrol->value.integer.value[1];		substream = (snd_pcm_substream_t *)kcontrol->private_value;		spin_lock_irqsave(&chip->voice_lock, flags);		if (substream->runtime && substream->runtime->private_data) {			ymfpci_pcm_t *ypcm = substream->runtime->private_data;			ypcm->update_pcm_vol = 2;		}		spin_unlock_irqrestore(&chip->voice_lock, flags);		return 1;	}	return 0;}static snd_kcontrol_new_t snd_ymfpci_pcm_volume __devinitdata = {	.iface = SNDRV_CTL_ELEM_IFACE_PCM,	.name = "PCM Playback Volume",	.access = SNDRV_CTL_ELEM_ACCESS_READWRITE |		SNDRV_CTL_ELEM_ACCESS_INACTIVE,	.info = snd_ymfpci_pcm_vol_info,	.get = snd_ymfpci_pcm_vol_get,	.put = snd_ymfpci_pcm_vol_put,};/* *  Mixer routines */static void snd_ymfpci_mixer_free_ac97_bus(ac97_bus_t *bus){	ymfpci_t *chip = bus->private_data;	chip->ac97_bus = NULL;}static void snd_ymfpci_mixer_free_ac97(ac97_t *ac97){	ymfpci_t *chip = ac97->private_data;	chip->ac97 = NULL;}int __devinit snd_ymfpci_mixer(ymfpci_t *chip, int rear_switch){	ac97_template_t ac97;	snd_kcontrol_t *kctl;	snd_pcm_substream_t *substream;	unsigned int idx;	int err;	static ac97_bus_ops_t ops = {		.write = snd_ymfpci_codec_write,		.read = snd_ymfpci_codec_read,	};	if ((err = snd_ac97_bus(chip->card, 0, &ops, chip, &chip->ac97_bus)) < 0)		return err;	chip->ac97_bus->private_free = snd_ymfpci_mixer_free_ac97_bus;	chip->ac97_bus->no_vra = 1; /* YMFPCI doesn't need VRA */	memset(&ac97, 0, sizeof(ac97));	ac97.private_data = chip;	ac97.private_free = snd_ymfpci_mixer_free_ac97;	if ((err = snd_ac97_mixer(chip->ac97_bus, &ac97, &chip->ac97)) < 0)		return err;	/* to be sure */	snd_ac97_update_bits(chip->ac97, AC97_EXTENDED_STATUS,			     AC97_EA_VRA|AC97_EA_VRM, 0);	for (idx = 0; idx < ARRAY_SIZE(snd_ymfpci_controls); idx++) {		if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_ymfpci_controls[idx], chip))) < 0)			return err;	}	/* add S/PDIF control */	snd_assert(chip->pcm_spdif != NULL, return -EIO);	if ((err = snd_ctl_add(chip->card, kctl = snd_ctl_new1(&snd_ymfpci_spdif_default, chip))) < 0)		return err;	kctl->id.device = chip->pcm_spdif->device;	if ((err = snd_ctl_add(chip->card, kctl = snd_ctl_new1(&snd_ymfpci_spdif_mask, chip))) < 0)		return err;	kctl->id.device = chip->pcm_spdif->device;	if ((err = snd_ctl_add(chip->card, kctl = snd_ctl_new1(&snd_ymfpci_spdif_stream, chip))) < 0)		return err;	kctl->id.device = chip->pcm_spdif->device;	chip->spdif_pcm_ctl = kctl;	/* direct recording source */	if (chip->device_id == PCI_DEVICE_ID_YAMAHA_754 &&	    (err = snd_ctl_add(chip->card, kctl = snd_ctl_new1(&snd_ymfpci_drec_source, chip))) < 0)		return err;	/*	 * shared rear/line-in	 */	if (rear_switch) {

⌨️ 快捷键说明

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