ymfpci_main.c

来自「优龙2410linux2.6.8内核源代码」· C语言 代码 · 共 2,233 行 · 第 1/5 页

C
2,233
字号
	ypcm->output_front = 1;	ypcm->output_rear = chip->mode_dup4ch ? 1 : 0;	spin_lock_irqsave(&chip->reg_lock, flags);	if (ypcm->output_rear) {		ymfpci_open_extension(chip);		chip->rear_opened++;	}	spin_unlock_irqrestore(&chip->reg_lock, flags);	return 0;}static int snd_ymfpci_playback_spdif_open(snd_pcm_substream_t * substream){	ymfpci_t *chip = snd_pcm_substream_chip(substream);	snd_pcm_runtime_t *runtime = substream->runtime;	ymfpci_pcm_t *ypcm;	unsigned long flags;	int err;		if ((err = snd_ymfpci_playback_open_1(substream)) < 0)		return err;	ypcm = snd_magic_cast(ymfpci_pcm_t, runtime->private_data, return 0);	ypcm->output_front = 0;	ypcm->output_rear = 1;	spin_lock_irqsave(&chip->reg_lock, flags);	snd_ymfpci_writew(chip, YDSXGR_SPDIFOUTCTRL,			  snd_ymfpci_readw(chip, YDSXGR_SPDIFOUTCTRL) | 2);	ymfpci_open_extension(chip);	chip->spdif_pcm_bits = chip->spdif_bits;	snd_ymfpci_writew(chip, YDSXGR_SPDIFOUTSTATUS, chip->spdif_pcm_bits);	chip->spdif_opened++;	spin_unlock_irqrestore(&chip->reg_lock, flags);	chip->spdif_pcm_ctl->vd[0].access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE;	snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE |		       SNDRV_CTL_EVENT_MASK_INFO, &chip->spdif_pcm_ctl->id);	return 0;}static int snd_ymfpci_playback_4ch_open(snd_pcm_substream_t * substream){	ymfpci_t *chip = snd_pcm_substream_chip(substream);	snd_pcm_runtime_t *runtime = substream->runtime;	ymfpci_pcm_t *ypcm;	unsigned long flags;	int err;		if ((err = snd_ymfpci_playback_open_1(substream)) < 0)		return err;	ypcm = snd_magic_cast(ymfpci_pcm_t, runtime->private_data, return 0);	ypcm->output_front = 0;	ypcm->output_rear = 1;	spin_lock_irqsave(&chip->reg_lock, flags);	ymfpci_open_extension(chip);	chip->rear_opened++;	spin_unlock_irqrestore(&chip->reg_lock, flags);	return 0;}static int snd_ymfpci_capture_open(snd_pcm_substream_t * substream,				   u32 capture_bank_number){	ymfpci_t *chip = snd_pcm_substream_chip(substream);	snd_pcm_runtime_t *runtime = substream->runtime;	ymfpci_pcm_t *ypcm;	ypcm = snd_magic_kcalloc(ymfpci_pcm_t, 0, GFP_KERNEL);	if (ypcm == NULL)		return -ENOMEM;	ypcm->chip = chip;	ypcm->type = capture_bank_number + CAPTURE_REC;	ypcm->substream = substream;		ypcm->capture_bank_number = capture_bank_number;	chip->capture_substream[capture_bank_number] = substream;	runtime->hw = snd_ymfpci_capture;	/* FIXME? True value is 256/48 = 5.33333 ms */	snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIOD_TIME, 5333, UINT_MAX);	runtime->private_data = ypcm;	runtime->private_free = snd_ymfpci_pcm_free_substream;	snd_ymfpci_hw_start(chip);	return 0;}static int snd_ymfpci_capture_rec_open(snd_pcm_substream_t * substream){	return snd_ymfpci_capture_open(substream, 0);}static int snd_ymfpci_capture_ac97_open(snd_pcm_substream_t * substream){	return snd_ymfpci_capture_open(substream, 1);}static int snd_ymfpci_playback_close_1(snd_pcm_substream_t * substream){	return 0;}static int snd_ymfpci_playback_close(snd_pcm_substream_t * substream){	ymfpci_t *chip = snd_pcm_substream_chip(substream);	ymfpci_pcm_t *ypcm = snd_magic_cast(ymfpci_pcm_t, substream->runtime->private_data, return -ENXIO);	unsigned long flags;	spin_lock_irqsave(&chip->reg_lock, flags);	if (ypcm->output_rear && chip->rear_opened > 0) {		chip->rear_opened--;		ymfpci_close_extension(chip);	}	spin_unlock_irqrestore(&chip->reg_lock, flags);	return snd_ymfpci_playback_close_1(substream);}static int snd_ymfpci_playback_spdif_close(snd_pcm_substream_t * substream){	ymfpci_t *chip = snd_pcm_substream_chip(substream);	unsigned long flags;	spin_lock_irqsave(&chip->reg_lock, flags);	chip->spdif_opened = 0;	ymfpci_close_extension(chip);	snd_ymfpci_writew(chip, YDSXGR_SPDIFOUTCTRL,			  snd_ymfpci_readw(chip, YDSXGR_SPDIFOUTCTRL) & ~2);	snd_ymfpci_writew(chip, YDSXGR_SPDIFOUTSTATUS, chip->spdif_bits);	spin_unlock_irqrestore(&chip->reg_lock, flags);	chip->spdif_pcm_ctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE;	snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE |		       SNDRV_CTL_EVENT_MASK_INFO, &chip->spdif_pcm_ctl->id);	return snd_ymfpci_playback_close_1(substream);}static int snd_ymfpci_playback_4ch_close(snd_pcm_substream_t * substream){	ymfpci_t *chip = snd_pcm_substream_chip(substream);	unsigned long flags;	spin_lock_irqsave(&chip->reg_lock, flags);	if (chip->rear_opened > 0) {		chip->rear_opened--;		ymfpci_close_extension(chip);	}	spin_unlock_irqrestore(&chip->reg_lock, flags);	return snd_ymfpci_playback_close_1(substream);}static int snd_ymfpci_capture_close(snd_pcm_substream_t * substream){	ymfpci_t *chip = snd_pcm_substream_chip(substream);	snd_pcm_runtime_t *runtime = substream->runtime;	ymfpci_pcm_t *ypcm = snd_magic_cast(ymfpci_pcm_t, runtime->private_data, return -ENXIO);	if (ypcm != NULL) {		chip->capture_substream[ypcm->capture_bank_number] = NULL;		snd_ymfpci_hw_stop(chip);	}	return 0;}static snd_pcm_ops_t snd_ymfpci_playback_ops = {	.open =			snd_ymfpci_playback_open,	.close =		snd_ymfpci_playback_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 snd_pcm_ops_t snd_ymfpci_capture_rec_ops = {	.open =			snd_ymfpci_capture_rec_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_pcm_free(snd_pcm_t *pcm){	ymfpci_t *chip = snd_magic_cast(ymfpci_t, pcm->private_data, return);	chip->pcm = NULL;	snd_pcm_lib_preallocate_free_for_all(pcm);}int __devinit snd_ymfpci_pcm(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", device, 32, 1, &pcm)) < 0)		return err;	pcm->private_data = chip;	pcm->private_free = snd_ymfpci_pcm_free;	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_ymfpci_playback_ops);	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_ymfpci_capture_rec_ops);	/* global setup */	pcm->info_flags = 0;	strcpy(pcm->name, "YMFPCI");	chip->pcm = pcm;	snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,					      snd_dma_pci_data(chip->pci), 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 - PCM2", 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;	sprintf(pcm->name, "YMFPCI - %s",		chip->device_id == PCI_DEVICE_ID_YAMAHA_754 ? "Direct Recording" : "AC'97");	chip->pcm2 = pcm;	snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,					      snd_dma_pci_data(chip->pci), 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;	snd_pcm_lib_preallocate_free_for_all(pcm);}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;	snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,					      snd_dma_pci_data(chip->pci), 64*1024, 256*1024);	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;	snd_pcm_lib_preallocate_free_for_all(pcm);}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;	snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,					      snd_dma_pci_data(chip->pci), 64*1024, 256*1024);	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;}

⌨️ 快捷键说明

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