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

📄 ymfpci_main.c

📁 是关于linux2.5.1的完全源码
💻 C
📖 第 1 页 / 共 4 页
字号:
	pcm->info_flags = 0;	strcpy(pcm->name, "YMFPCI");	chip->pcm = pcm;	snd_pcm_lib_preallocate_pci_pages_for_all(chip->pci, pcm, 64*1024, 256*1024);	if (rpcm)		*rpcm = pcm;	return 0;}static snd_pcm_ops_t snd_ymfpci_capture_ac97_ops = {	open:			snd_ymfpci_capture_ac97_open,	close:			snd_ymfpci_capture_close,	ioctl:			snd_pcm_lib_ioctl,	hw_params:		snd_ymfpci_capture_hw_params,	hw_free:		snd_ymfpci_capture_hw_free,	prepare:		snd_ymfpci_capture_prepare,	trigger:		snd_ymfpci_capture_trigger,	pointer:		snd_ymfpci_capture_pointer,};static void snd_ymfpci_pcm2_free(snd_pcm_t *pcm){	ymfpci_t *chip = snd_magic_cast(ymfpci_t, pcm->private_data, return);	chip->pcm2 = NULL;	snd_pcm_lib_preallocate_free_for_all(pcm);}int __devinit snd_ymfpci_pcm2(ymfpci_t *chip, int device, snd_pcm_t ** rpcm){	snd_pcm_t *pcm;	int err;	if (rpcm)		*rpcm = NULL;	if ((err = snd_pcm_new(chip->card, "YMFPCI - AC'97", device, 0, 1, &pcm)) < 0)		return err;	pcm->private_data = chip;	pcm->private_free = snd_ymfpci_pcm2_free;	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_ymfpci_capture_ac97_ops);	/* global setup */	pcm->info_flags = 0;	strcpy(pcm->name, "YMFPCI - AC'97");	chip->pcm2 = pcm;	snd_pcm_lib_preallocate_pci_pages_for_all(chip->pci, pcm, 64*1024, 256*1024);	if (rpcm)		*rpcm = pcm;	return 0;}static snd_pcm_ops_t snd_ymfpci_playback_spdif_ops = {	open:			snd_ymfpci_playback_spdif_open,	close:			snd_ymfpci_playback_spdif_close,	ioctl:			snd_pcm_lib_ioctl,	hw_params:		snd_ymfpci_playback_hw_params,	hw_free:		snd_ymfpci_playback_hw_free,	prepare:		snd_ymfpci_playback_prepare,	trigger:		snd_ymfpci_playback_trigger,	pointer:		snd_ymfpci_playback_pointer,};static void snd_ymfpci_pcm_spdif_free(snd_pcm_t *pcm){	ymfpci_t *chip = snd_magic_cast(ymfpci_t, pcm->private_data, return);	chip->pcm_spdif = NULL;}int __devinit snd_ymfpci_pcm_spdif(ymfpci_t *chip, int device, snd_pcm_t ** rpcm){	snd_pcm_t *pcm;	int err;	if (rpcm)		*rpcm = NULL;	if ((err = snd_pcm_new(chip->card, "YMFPCI - IEC958", device, 1, 0, &pcm)) < 0)		return err;	pcm->private_data = chip;	pcm->private_free = snd_ymfpci_pcm_spdif_free;	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_ymfpci_playback_spdif_ops);	/* global setup */	pcm->info_flags = 0;	strcpy(pcm->name, "YMFPCI - IEC958");	chip->pcm_spdif = pcm;	if (rpcm)		*rpcm = pcm;	return 0;}static snd_pcm_ops_t snd_ymfpci_playback_4ch_ops = {	open:			snd_ymfpci_playback_4ch_open,	close:			snd_ymfpci_playback_4ch_close,	ioctl:			snd_pcm_lib_ioctl,	hw_params:		snd_ymfpci_playback_hw_params,	hw_free:		snd_ymfpci_playback_hw_free,	prepare:		snd_ymfpci_playback_prepare,	trigger:		snd_ymfpci_playback_trigger,	pointer:		snd_ymfpci_playback_pointer,};static void snd_ymfpci_pcm_4ch_free(snd_pcm_t *pcm){	ymfpci_t *chip = snd_magic_cast(ymfpci_t, pcm->private_data, return);	chip->pcm_4ch = NULL;}int __devinit snd_ymfpci_pcm_4ch(ymfpci_t *chip, int device, snd_pcm_t ** rpcm){	snd_pcm_t *pcm;	int err;	if (rpcm)		*rpcm = NULL;	if ((err = snd_pcm_new(chip->card, "YMFPCI - Rear", device, 1, 0, &pcm)) < 0)		return err;	pcm->private_data = chip;	pcm->private_free = snd_ymfpci_pcm_4ch_free;	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_ymfpci_playback_4ch_ops);	/* global setup */	pcm->info_flags = 0;	strcpy(pcm->name, "YMFPCI - Rear PCM");	chip->pcm_4ch = pcm;	if (rpcm)		*rpcm = pcm;	return 0;}static int snd_ymfpci_spdif_default_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_ymfpci_spdif_default_get(snd_kcontrol_t * kcontrol,					snd_ctl_elem_value_t * ucontrol){	ymfpci_t *chip = snd_kcontrol_chip(kcontrol);	unsigned long flags;	spin_lock_irqsave(&chip->reg_lock, flags);	ucontrol->value.iec958.status[0] = (chip->spdif_bits >> 0) & 0xff;	ucontrol->value.iec958.status[1] = (chip->spdif_bits >> 8) & 0xff;	spin_unlock_irqrestore(&chip->reg_lock, flags);	return 0;}static int snd_ymfpci_spdif_default_put(snd_kcontrol_t * kcontrol,					 snd_ctl_elem_value_t * ucontrol){	ymfpci_t *chip = snd_kcontrol_chip(kcontrol);	unsigned long flags;	unsigned int val;	int change;	val = ((ucontrol->value.iec958.status[0] & 0x3e) << 0) |	      (ucontrol->value.iec958.status[1] << 8);	spin_lock_irqsave(&chip->reg_lock, flags);	change = chip->spdif_bits != val;	chip->spdif_bits = val;	if ((snd_ymfpci_readw(chip, YDSXGR_SPDIFOUTCTRL) & 1) && chip->pcm_spdif == NULL)		snd_ymfpci_writew(chip, YDSXGR_SPDIFOUTSTATUS, chip->spdif_bits);	spin_unlock_irqrestore(&chip->reg_lock, flags);	return change;}static snd_kcontrol_new_t snd_ymfpci_spdif_default __devinitdata ={	iface:		SNDRV_CTL_ELEM_IFACE_PCM,	name:           SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),	info:		snd_ymfpci_spdif_default_info,	get:		snd_ymfpci_spdif_default_get,	put:		snd_ymfpci_spdif_default_put};static int snd_ymfpci_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_ymfpci_spdif_mask_get(snd_kcontrol_t * kcontrol,				      snd_ctl_elem_value_t * ucontrol){	ymfpci_t *chip = snd_kcontrol_chip(kcontrol);	unsigned long flags;	spin_lock_irqsave(&chip->reg_lock, flags);	ucontrol->value.iec958.status[0] = 0x3e;	ucontrol->value.iec958.status[1] = 0xff;	spin_unlock_irqrestore(&chip->reg_lock, flags);	return 0;}static snd_kcontrol_new_t snd_ymfpci_spdif_mask __devinitdata ={	access:		SNDRV_CTL_ELEM_ACCESS_READ,	iface:		SNDRV_CTL_ELEM_IFACE_PCM,	name:           SNDRV_CTL_NAME_IEC958("",PLAYBACK,CON_MASK),	info:		snd_ymfpci_spdif_mask_info,	get:		snd_ymfpci_spdif_mask_get,};static int snd_ymfpci_spdif_stream_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_ymfpci_spdif_stream_get(snd_kcontrol_t * kcontrol,					snd_ctl_elem_value_t * ucontrol){	ymfpci_t *chip = snd_kcontrol_chip(kcontrol);	unsigned long flags;	spin_lock_irqsave(&chip->reg_lock, flags);	ucontrol->value.iec958.status[0] = (chip->spdif_pcm_bits >> 0) & 0xff;	ucontrol->value.iec958.status[1] = (chip->spdif_pcm_bits >> 8) & 0xff;	spin_unlock_irqrestore(&chip->reg_lock, flags);	return 0;}static int snd_ymfpci_spdif_stream_put(snd_kcontrol_t * kcontrol,					snd_ctl_elem_value_t * ucontrol){	ymfpci_t *chip = snd_kcontrol_chip(kcontrol);	unsigned long flags;	unsigned int val;	int change;	val = ((ucontrol->value.iec958.status[0] & 0x3e) << 0) |	      (ucontrol->value.iec958.status[1] << 8);	spin_lock_irqsave(&chip->reg_lock, flags);	change = chip->spdif_pcm_bits != val;	chip->spdif_pcm_bits = val;	if ((snd_ymfpci_readw(chip, YDSXGR_SPDIFOUTCTRL) & 2))		snd_ymfpci_writew(chip, YDSXGR_SPDIFOUTSTATUS, chip->spdif_pcm_bits);	spin_unlock_irqrestore(&chip->reg_lock, flags);	return change;}static snd_kcontrol_new_t snd_ymfpci_spdif_stream __devinitdata ={	access:		SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,	iface:		SNDRV_CTL_ELEM_IFACE_PCM,	name:           SNDRV_CTL_NAME_IEC958("",PLAYBACK,PCM_STREAM),	info:		snd_ymfpci_spdif_stream_info,	get:		snd_ymfpci_spdif_stream_get,	put:		snd_ymfpci_spdif_stream_put};/* *  Mixer controls */#define YMFPCI_SINGLE(xname, xindex, reg) \{ 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 }static int snd_ymfpci_info_single(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo){	unsigned int mask = 1;	switch (kcontrol->private_value) {	case YDSXGR_SPDIFOUTCTRL: break;	case YDSXGR_SPDIFINCTRL: break;	default: return -EINVAL;	}	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_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;	unsigned int shift = 0, mask = 1, invert = 0;		switch (kcontrol->private_value) {	case YDSXGR_SPDIFOUTCTRL: break;	case YDSXGR_SPDIFINCTRL: break;	default: return -EINVAL;	}	ucontrol->value.integer.value[0] = (snd_ymfpci_readl(chip, reg) >> shift) & mask;	if (invert)		ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0];	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);	unsigned long flags;	int reg = kcontrol->private_value;	unsigned int shift = 0, mask = 1, invert = 0;	int change;	unsigned int val, oval;		switch (kcontrol->private_value) {	case YDSXGR_SPDIFOUTCTRL: break;	case YDSXGR_SPDIFINCTRL: break;	default: return -EINVAL;	}	val = (ucontrol->value.integer.value[0] & mask);	if (invert)		val = mask - val;	val <<= shift;	spin_lock_irqsave(&chip->reg_lock, flags);	oval = snd_ymfpci_readl(chip, reg);	val = (oval & ~(mask << shift)) | val;	change = val != oval;	snd_ymfpci_writel(chip, reg, val);	spin_unlock_irqrestore(&chip->reg_lock, flags);	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;	unsigned int mask = 16383;	if (reg < 0x80 || reg >= 0xc0)		return -EINVAL;	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_ymfpci_get_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){	ymfpci_t *chip = snd_kcontrol_chip(kcontrol);	unsigned long flags;	unsigned int reg = kcontrol->private_value;	unsigned int shift_left = 0, shift_right = 16, mask = 16383, invert = 0;	unsigned int val;		if (reg < 0x80 || reg >= 0xc0)		return -EINVAL;	spin_lock_irqsave(&chip->reg_lock, flags);	val = snd_ymfpci_readl(chip, reg);	spin_unlock_irqrestore(&chip->reg_lock, flags);	ucontrol->value.integer.value[0] = (val >> shift_left) & mask;	ucontrol->value.integer.value[1] = (val >> shift_right) & mask;	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_ymfpci_put_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){	ymfpci_t *chip = snd_kcontrol_chip(kcontrol);	unsigned long flags;	unsigned int reg = kcontrol->private_value;	unsigned int shift_left = 0, shift_right = 16, mask = 16383, invert = 0;	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;	if (invert) {		val1 = mask - val1;		val2 = mask - val2;	}	val1 <<= shift_left;	val2 <<= shift_right;	spin_lock_irqsave(&chip->reg_lock, flags);	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_irqrestore(&chip->reg_lock, flags);	return change;}#define YMFPCI_CONTROLS (sizeof(snd_ymfpci_controls)/sizeof(snd_kcontrol_new_t))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(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),YMFPCI_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH), 0, YDSXGR_SPDIFINCTRL)};/* *  Mixer routines */static void snd_ymfpci_mixer_free_ac97(ac97_t *ac97){	ymfpci_t *chip = snd_magic_cast(ymfpci_t, ac97->private_data, return);	chip->ac97 = NULL;}int __devinit snd_ymfpci_mixer(ymfpci_t *chip){	ac97_t ac97;	snd_kcontrol_t *kctl;	int err, idx;	memset(&ac97, 0, sizeof(ac97));	ac97.write = snd_ymfpci_codec_write;	ac97.read = snd_ymfpci_codec_read;	ac97.private_data = chip;	ac97.private_free = snd_ymfpci_mixer_free_ac97;	if ((err = snd_ac97_mixer(chip->card, &ac97, &chip->ac97)) < 0)		return err;	for (idx = 0; idx < 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;	return 0;}/* * joystick support */static int ymfpci_joystick_ports[4] = {	0x201, 0x202, 0x204, 0x205};static void setup_joystick_base(ymfpci_t *chip){	if (chip->pci->device >= 0x0010) /* YMF 744/754 */		pci_write_config_word(chip->pci, PCIR_DSXG_JOYBASE,				      ymfpci_joystick_ports[chip->joystick_port]);	else {		u16 legacy_ctrl2;		pci_read_config_word(chip->pci, PCIR_DSXG_ELEGACY, &legacy_ctrl2);		legacy_ctrl2 &= ~(3 << 6);		legacy_ctrl2 |= chip->joystick_port << 6;		pci_write_config_word(chip->pci, PCIR_DSXG_ELEGACY, legacy_ctrl2);	}}static int snd_ymfpci_joystick_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_joystick_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol){	ymfpci_t *chip = snd_kcontrol_chip(kcontrol);	u16 val;	pci_read_config_word(chip->pci, PCIR_DSXG_LEGACY, &val);	ucontrol->value.integer.value[0] = (val & 0x04) ? 1 : 0;	return 0;}static int snd_ymfpci_joystick_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol){	ymfpci_t *chip = snd_kcontrol_chip(kcontrol);	u16 val, oval;	pci_read_config_word(chip->pci, PCIR_DSXG_LEGACY, &oval);	val = oval & ~0x04;	if (ucontrol->value.integer.value[0])		val |= 0x04;	if (val != oval) {		setup_joystick_base(chip);		pci_write_config_word(chip->pci, PCIR_DSXG_LEGACY, val);		return 1;	}	return 0;}

⌨️ 快捷键说明

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