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

📄 ymfpci_main.c

📁 是关于linux2.5.1的完全源码
💻 C
📖 第 1 页 / 共 4 页
字号:
					bank->eff3_gain =					bank->eff3_gain_end = cpu_to_le32(0x40000000);				} else {					bank->format |= cpu_to_le32(1);					bank->eff2_gain =					bank->eff2_gain_end = cpu_to_le32(0x40000000);				}			}		}	}}static int snd_ymfpci_ac3_init(ymfpci_t *chip){	unsigned char *ptr;	dma_addr_t ptr_addr;	if (chip->ac3_tmp_base != NULL)		return -EBUSY;	if ((ptr = snd_malloc_pci_pages(chip->pci, 4096, &ptr_addr)) == NULL)		return -ENOMEM;	chip->ac3_tmp_base = ptr;	chip->ac3_tmp_base_addr = ptr_addr;	chip->bank_effect[3][0]->base =	chip->bank_effect[3][1]->base = cpu_to_le32(chip->ac3_tmp_base_addr);	chip->bank_effect[3][0]->loop_end =	chip->bank_effect[3][1]->loop_end = cpu_to_le32(1024);	chip->bank_effect[4][0]->base =	chip->bank_effect[4][1]->base = cpu_to_le32(chip->ac3_tmp_base_addr + 2048);	chip->bank_effect[4][0]->loop_end =	chip->bank_effect[4][1]->loop_end = cpu_to_le32(1024);	spin_lock_irq(&chip->reg_lock);	snd_ymfpci_writel(chip, YDSXGR_MAPOFEFFECT,			  snd_ymfpci_readl(chip, YDSXGR_MAPOFEFFECT) | 3 << 3);	spin_unlock_irq(&chip->reg_lock);	return 0;}static int snd_ymfpci_ac3_done(ymfpci_t *chip){	spin_lock_irq(&chip->reg_lock);	snd_ymfpci_writel(chip, YDSXGR_MAPOFEFFECT,			  snd_ymfpci_readl(chip, YDSXGR_MAPOFEFFECT) & ~(3 << 3));	spin_unlock_irq(&chip->reg_lock);	snd_ymfpci_irq_wait(chip);	if (chip->ac3_tmp_base) {		snd_free_pci_pages(chip->pci, 4096, chip->ac3_tmp_base, chip->ac3_tmp_base_addr);		chip->ac3_tmp_base = NULL;	}	return 0;}static int snd_ymfpci_playback_hw_params(snd_pcm_substream_t * substream,					 snd_pcm_hw_params_t * hw_params){	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);	int err;	if ((err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params))) < 0)		return err;	if ((err = snd_ymfpci_pcm_voice_alloc(ypcm, params_channels(hw_params))) < 0)		return err;	if (ypcm->spdif || ypcm->mode4ch)		if ((err = snd_ymfpci_ac3_init(chip)) < 0)			return err;	return 0;}static int snd_ymfpci_playback_hw_free(snd_pcm_substream_t * substream){	ymfpci_t *chip = snd_pcm_substream_chip(substream);	snd_pcm_runtime_t *runtime = substream->runtime;	ymfpci_pcm_t *ypcm;			if (runtime->private_data == NULL)		return 0;	ypcm = snd_magic_cast(ymfpci_pcm_t, runtime->private_data, return -ENXIO);	/* wait, until the PCI operations are not finished */	snd_ymfpci_irq_wait(chip);	snd_pcm_lib_free_pages(substream);	if (ypcm->voices[1]) {		snd_ymfpci_voice_free(chip, ypcm->voices[1]);		ypcm->voices[1] = NULL;	}	if (ypcm->voices[0]) {		snd_ymfpci_voice_free(chip, ypcm->voices[0]);		ypcm->voices[0] = NULL;	}	if (ypcm->spdif || ypcm->mode4ch)		snd_ymfpci_ac3_done(chip);	return 0;}static int snd_ymfpci_playback_prepare(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);	int nvoice;	ypcm->period_size = runtime->period_size;	ypcm->buffer_size = runtime->buffer_size;	ypcm->period_pos = 0;	ypcm->last_pos = 0;	for (nvoice = 0; nvoice < runtime->channels; nvoice++)		snd_ymfpci_pcm_init_voice(ypcm->voices[nvoice],					  runtime->channels == 2,					  runtime->rate,					  snd_pcm_format_width(runtime->format) == 16,					  runtime->dma_addr,					  ypcm->buffer_size,					  ypcm->spdif || ypcm->mode4ch);	return 0;}static int snd_ymfpci_capture_hw_params(snd_pcm_substream_t * substream,					snd_pcm_hw_params_t * hw_params){	return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));}static int snd_ymfpci_capture_hw_free(snd_pcm_substream_t * substream){	ymfpci_t *chip = snd_pcm_substream_chip(substream);	/* wait, until the PCI operations are not finished */	snd_ymfpci_irq_wait(chip);	return snd_pcm_lib_free_pages(substream);}static int snd_ymfpci_capture_prepare(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);	snd_ymfpci_capture_bank_t * bank;	int nbank;	u32 rate, format;	ypcm->period_size = runtime->period_size;	ypcm->buffer_size = runtime->buffer_size;	ypcm->period_pos = 0;	ypcm->last_pos = 0;	ypcm->shift = 0;	rate = ((48000 * 4096) / runtime->rate) - 1;	format = 0;	if (runtime->channels == 2) {		format |= 2;		ypcm->shift++;	}	if (snd_pcm_format_width(runtime->format) == 8)		format |= 1;	else		ypcm->shift++;	switch (ypcm->capture_bank_number) {	case 0:		snd_ymfpci_writel(chip, YDSXGR_RECFORMAT, format);		snd_ymfpci_writel(chip, YDSXGR_RECSLOTSR, rate);		break;	case 1:		snd_ymfpci_writel(chip, YDSXGR_ADCFORMAT, format);		snd_ymfpci_writel(chip, YDSXGR_ADCSLOTSR, rate);		break;	}	for (nbank = 0; nbank < 2; nbank++) {		bank = chip->bank_capture[ypcm->capture_bank_number][nbank];		bank->base = cpu_to_le32(runtime->dma_addr);		bank->loop_end = cpu_to_le32(ypcm->buffer_size << ypcm->shift);		bank->start = 0;		bank->num_of_loops = 0;	}	return 0;}static snd_pcm_uframes_t snd_ymfpci_playback_pointer(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);	ymfpci_voice_t *voice = ypcm->voices[0];	if (!(ypcm->running && voice))		return 0;	return le32_to_cpu(voice->bank[chip->active_bank].start);}static snd_pcm_uframes_t snd_ymfpci_capture_pointer(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->running)		return 0;	return le32_to_cpu(chip->bank_capture[ypcm->capture_bank_number][chip->active_bank]->start) >> ypcm->shift;}static void snd_ymfpci_irq_wait(ymfpci_t *chip){	wait_queue_t wait;	int loops = 4;	while (loops-- > 0) {		if ((snd_ymfpci_readl(chip, YDSXGR_MODE) & 3) == 0)		 	continue;		init_waitqueue_entry(&wait, current);		add_wait_queue(&chip->interrupt_sleep, &wait);		atomic_inc(&chip->interrupt_sleep_count);		set_current_state(TASK_UNINTERRUPTIBLE);		schedule_timeout(HZ/20);		remove_wait_queue(&chip->interrupt_sleep, &wait);	}}static void snd_ymfpci_interrupt(int irq, void *dev_id, struct pt_regs *regs){	ymfpci_t *chip = snd_magic_cast(ymfpci_t, dev_id, return);	u32 status, nvoice, mode;	ymfpci_voice_t *voice;	status = snd_ymfpci_readl(chip, YDSXGR_STATUS);	if (status & 0x80000000) {		chip->active_bank = snd_ymfpci_readl(chip, YDSXGR_CTRLSELECT) & 1;		spin_lock(&chip->voice_lock);		for (nvoice = 0; nvoice < YDSXG_PLAYBACK_VOICES; nvoice++) {			voice = &chip->voices[nvoice];			if (voice->interrupt)				voice->interrupt(chip, voice);		}		for (nvoice = 0; nvoice < YDSXG_CAPTURE_VOICES; nvoice++) {			if (chip->capture_substream[nvoice])				snd_ymfpci_pcm_capture_interrupt(chip->capture_substream[nvoice]);		}#if 0		for (nvoice = 0; nvoice < YDSXG_EFFECT_VOICES; nvoice++) {			if (chip->effect_substream[nvoice])				snd_ymfpci_pcm_effect_interrupt(chip->effect_substream[nvoice]);		}#endif		spin_unlock(&chip->voice_lock);		spin_lock(&chip->reg_lock);		snd_ymfpci_writel(chip, YDSXGR_STATUS, 0x80000000);		mode = snd_ymfpci_readl(chip, YDSXGR_MODE) | 2;		snd_ymfpci_writel(chip, YDSXGR_MODE, mode);		spin_unlock(&chip->reg_lock);		if (atomic_read(&chip->interrupt_sleep_count)) {			atomic_set(&chip->interrupt_sleep_count, 0);			wake_up(&chip->interrupt_sleep);		}	}	status = snd_ymfpci_readl(chip, YDSXGR_INTFLAG);	if (status & 1) {		/* timer handler */		snd_ymfpci_writel(chip, YDSXGR_INTFLAG, ~0);	}	if (chip->rawmidi)		snd_mpu401_uart_interrupt(irq, chip->rawmidi->private_data, regs);}static snd_pcm_hardware_t snd_ymfpci_playback ={	info:			(SNDRV_PCM_INFO_MMAP |				 SNDRV_PCM_INFO_MMAP_VALID | 				 SNDRV_PCM_INFO_INTERLEAVED |				 SNDRV_PCM_INFO_BLOCK_TRANSFER |				 SNDRV_PCM_INFO_PAUSE |				 SNDRV_PCM_INFO_RESUME),	formats:		SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE,	rates:			SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,	rate_min:		8000,	rate_max:		48000,	channels_min:		1,	channels_max:		2,	buffer_bytes_max:	256 * 1024, /* FIXME: enough? */	period_bytes_min:	64,	period_bytes_max:	256 * 1024, /* FIXME: enough? */	periods_min:		3,	periods_max:		1024,	fifo_size:		0,};static snd_pcm_hardware_t snd_ymfpci_capture ={	info:			(SNDRV_PCM_INFO_MMAP |				 SNDRV_PCM_INFO_MMAP_VALID |				 SNDRV_PCM_INFO_INTERLEAVED |				 SNDRV_PCM_INFO_BLOCK_TRANSFER |				 SNDRV_PCM_INFO_PAUSE |				 SNDRV_PCM_INFO_RESUME),	formats:		SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE,	rates:			SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,	rate_min:		8000,	rate_max:		48000,	channels_min:		1,	channels_max:		2,	buffer_bytes_max:	256 * 1024, /* FIXME: enough? */	period_bytes_min:	64,	period_bytes_max:	256 * 1024, /* FIXME: enough? */	periods_min:		3,	periods_max:		1024,	fifo_size:		0,};static void snd_ymfpci_pcm_free_substream(snd_pcm_runtime_t *runtime){	ymfpci_pcm_t *ypcm = snd_magic_cast(ymfpci_pcm_t, runtime->private_data, return);		if (ypcm)		snd_magic_kfree(ypcm);}static int snd_ymfpci_playback_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;	ypcm = snd_magic_kcalloc(ymfpci_pcm_t, 0, GFP_KERNEL);	if (ypcm == NULL)		return -ENOMEM;	ypcm->chip = chip;	ypcm->type = PLAYBACK_VOICE;	ypcm->substream = substream;	runtime->hw = snd_ymfpci_playback;	runtime->private_data = ypcm;	runtime->private_free = snd_ymfpci_pcm_free_substream;	/* FIXME? True value is 256/48 = 5.33333 ms */	snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIOD_TIME, 5333, UINT_MAX);	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(substream)) < 0)		return err;	ypcm = snd_magic_cast(ymfpci_pcm_t, runtime->private_data, return 0);	ypcm->spdif = 1;	spin_lock_irqsave(&chip->reg_lock, flags);	snd_ymfpci_writew(chip, YDSXGR_SPDIFOUTCTRL,			  snd_ymfpci_readw(chip, YDSXGR_SPDIFOUTCTRL) | 2);	snd_ymfpci_writel(chip, YDSXGR_MODE,			  snd_ymfpci_readl(chip, YDSXGR_MODE) | (1 << 30));	chip->spdif_pcm_bits = chip->spdif_bits;	snd_ymfpci_writel(chip, YDSXGR_SPDIFOUTSTATUS, chip->spdif_pcm_bits);	spin_unlock_irqrestore(&chip->reg_lock, flags);	chip->spdif_pcm_ctl->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);	/* FIXME? True value is 256/48 = 5.33333 ms */	snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIOD_TIME, 5333, UINT_MAX);	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(substream)) < 0)		return err;	ypcm = snd_magic_cast(ymfpci_pcm_t, runtime->private_data, return 0);	ypcm->mode4ch = 1;	spin_lock_irqsave(&chip->reg_lock, flags);	snd_ymfpci_writew(chip, YDSXGR_SECCONFIG,			  (snd_ymfpci_readw(chip, YDSXGR_SECCONFIG) & ~0x0030) | 0x0010);	snd_ymfpci_writel(chip, YDSXGR_MODE,			  snd_ymfpci_readl(chip, YDSXGR_MODE) | (1 << 30));	spin_unlock_irqrestore(&chip->reg_lock, flags);	/* FIXME? True value is 256/48 = 5.33333 ms */	snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIOD_TIME, 5333, UINT_MAX);	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(snd_pcm_substream_t * substream){	return 0;}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);	snd_ymfpci_writel(chip, YDSXGR_MODE,			  snd_ymfpci_readl(chip, YDSXGR_MODE) & ~(1 << 30));	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->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(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);	snd_ymfpci_writel(chip, YDSXGR_MODE,			  snd_ymfpci_readl(chip, YDSXGR_MODE) & ~(1 << 30));	snd_ymfpci_writew(chip, YDSXGR_SECCONFIG,			  (snd_ymfpci_readw(chip, YDSXGR_SECCONFIG) & ~0x0330) | 0x0010);	spin_unlock_irqrestore(&chip->reg_lock, flags);	return snd_ymfpci_playback_close(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 */

⌨️ 快捷键说明

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