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

📄 cs46xx_lib.c

📁 是关于linux2.5.1的完全源码
💻 C
📖 第 1 页 / 共 5 页
字号:
	if (runtime->periods == CS46XX_FRAGS) {		if (runtime->dma_area != chip->capt.hw_area)			snd_pcm_lib_free_pages(substream);		runtime->dma_area = chip->capt.hw_area;		runtime->dma_addr = chip->capt.hw_addr;		runtime->dma_bytes = chip->capt.hw_size;		substream->ops = &snd_cs46xx_capture_ops;	} else {		if (runtime->dma_area == chip->capt.hw_area) {			runtime->dma_area = NULL;			runtime->dma_addr = 0;			runtime->dma_bytes = 0;		}		if ((err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params))) < 0)			return err;		substream->ops = &snd_cs46xx_capture_indirect_ops;	}	return 0;}static int snd_cs46xx_capture_hw_free(snd_pcm_substream_t * substream){	cs46xx_t *chip = snd_pcm_substream_chip(substream);	snd_pcm_runtime_t *runtime = substream->runtime;	if (runtime->dma_area != chip->capt.hw_area)		snd_pcm_lib_free_pages(substream);	runtime->dma_area = NULL;	runtime->dma_addr = 0;	runtime->dma_bytes = 0;	return 0;}static int snd_cs46xx_capture_prepare(snd_pcm_substream_t * substream){	cs46xx_t *chip = snd_pcm_substream_chip(substream);	snd_pcm_runtime_t *runtime = substream->runtime;	snd_cs46xx_poke(chip, BA1_CBA, chip->capt.hw_addr);	chip->capt.shift = 2;	chip->capt.sw_bufsize = snd_pcm_lib_buffer_bytes(substream);	chip->capt.sw_data = chip->capt.sw_io = chip->capt.sw_ready = 0;	chip->capt.hw_data = chip->capt.hw_io = chip->capt.hw_ready = 0;	chip->capt.appl_ptr = 0;	snd_cs46xx_set_capture_sample_rate(chip, runtime->rate);	return 0;}static void snd_cs46xx_interrupt(int irq, void *dev_id, struct pt_regs *regs){	cs46xx_t *chip = snd_magic_cast(cs46xx_t, dev_id, return);	unsigned int status;	/*	 *  Read the Interrupt Status Register to clear the interrupt	 */	status = snd_cs46xx_peekBA0(chip, BA0_HISR);	if ((status & 0x7fffffff) == 0) {		snd_cs46xx_pokeBA0(chip, BA0_HICR, HICR_CHGM | HICR_IEV);		return;	}	if ((status & HISR_VC0) && chip->pcm) {		if (chip->play.substream)			snd_pcm_period_elapsed(chip->play.substream);	}	if ((status & HISR_VC1) && chip->pcm) {		if (chip->capt.substream)			snd_pcm_period_elapsed(chip->capt.substream);	}	if ((status & HISR_MIDI) && chip->rmidi) {		unsigned char c;				spin_lock(&chip->reg_lock);		while ((snd_cs46xx_peekBA0(chip, BA0_MIDSR) & MIDSR_RBE) == 0) {			c = snd_cs46xx_peekBA0(chip, BA0_MIDRP);			if ((chip->midcr & MIDCR_RIE) == 0)				continue;			snd_rawmidi_receive(chip->midi_input, &c, 1);		}		while ((snd_cs46xx_peekBA0(chip, BA0_MIDSR) & MIDSR_TBF) == 0) {			if ((chip->midcr & MIDCR_TIE) == 0)				break;			if (snd_rawmidi_transmit(chip->midi_output, &c, 1) != 1) {				chip->midcr &= ~MIDCR_TIE;				snd_cs46xx_pokeBA0(chip, BA0_MIDCR, chip->midcr);				break;			}			snd_cs46xx_pokeBA0(chip, BA0_MIDWP, c);		}		spin_unlock(&chip->reg_lock);	}	/*	 *  EOI to the PCI part....reenables interrupts	 */	snd_cs46xx_pokeBA0(chip, BA0_HICR, HICR_CHGM | HICR_IEV);}static snd_pcm_hardware_t snd_cs46xx_playback ={	info:			(SNDRV_PCM_INFO_MMAP |				 SNDRV_PCM_INFO_INTERLEAVED | 				 SNDRV_PCM_INFO_BLOCK_TRANSFER |				 SNDRV_PCM_INFO_RESUME),	formats:		(SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_U8 |				 SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE |				 SNDRV_PCM_FMTBIT_U16_LE | SNDRV_PCM_FMTBIT_U16_BE),	rates:			SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,	rate_min:		5500,	rate_max:		48000,	channels_min:		1,	channels_max:		2,	buffer_bytes_max:	(256 * 1024),	period_bytes_min:	CS46XX_PERIOD_SIZE,	period_bytes_max:	CS46XX_PERIOD_SIZE,	periods_min:		CS46XX_FRAGS,	periods_max:		1024,	fifo_size:		0,};static snd_pcm_hardware_t snd_cs46xx_capture ={	info:			(SNDRV_PCM_INFO_MMAP |				 SNDRV_PCM_INFO_INTERLEAVED |				 SNDRV_PCM_INFO_BLOCK_TRANSFER |				 SNDRV_PCM_INFO_RESUME),	formats:		SNDRV_PCM_FMTBIT_S16_LE,	rates:			SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,	rate_min:		5500,	rate_max:		48000,	channels_min:		2,	channels_max:		2,	buffer_bytes_max:	(256 * 1024),	period_bytes_min:	CS46XX_PERIOD_SIZE,	period_bytes_max:	CS46XX_PERIOD_SIZE,	periods_min:		CS46XX_FRAGS,	periods_max:		1024,	fifo_size:		0,};static int snd_cs46xx_playback_open(snd_pcm_substream_t * substream){	cs46xx_t *chip = snd_pcm_substream_chip(substream);	if ((chip->play.hw_area = snd_malloc_pci_pages(chip->pci, chip->play.hw_size, &chip->play.hw_addr)) == NULL)		return -ENOMEM;	chip->play.substream = substream;	substream->runtime->hw = snd_cs46xx_playback;	if (chip->accept_valid)		substream->runtime->hw.info |= SNDRV_PCM_INFO_MMAP_VALID;	chip->active_ctrl(chip, 1);	chip->amplifier_ctrl(chip, 1);	return 0;}static int snd_cs46xx_capture_open(snd_pcm_substream_t * substream){	cs46xx_t *chip = snd_pcm_substream_chip(substream);	if ((chip->capt.hw_area = snd_malloc_pci_pages(chip->pci, chip->capt.hw_size, &chip->capt.hw_addr)) == NULL)		return -ENOMEM;	chip->capt.substream = substream;	substream->runtime->hw = snd_cs46xx_capture;	if (chip->accept_valid)		substream->runtime->hw.info |= SNDRV_PCM_INFO_MMAP_VALID;	chip->active_ctrl(chip, 1);	chip->amplifier_ctrl(chip, 1);	return 0;}static int snd_cs46xx_playback_close(snd_pcm_substream_t * substream){	cs46xx_t *chip = snd_pcm_substream_chip(substream);	chip->play.substream = NULL;	snd_free_pci_pages(chip->pci, chip->play.hw_size, chip->play.hw_area, chip->play.hw_addr);	chip->active_ctrl(chip, -1);	chip->amplifier_ctrl(chip, -1);	return 0;}static int snd_cs46xx_capture_close(snd_pcm_substream_t * substream){	cs46xx_t *chip = snd_pcm_substream_chip(substream);	chip->capt.substream = NULL;	snd_free_pci_pages(chip->pci, chip->capt.hw_size, chip->capt.hw_area, chip->capt.hw_addr);	chip->active_ctrl(chip, -1);	chip->amplifier_ctrl(chip, -1);	return 0;}snd_pcm_ops_t snd_cs46xx_playback_ops = {	open:			snd_cs46xx_playback_open,	close:			snd_cs46xx_playback_close,	ioctl:			snd_pcm_lib_ioctl,	hw_params:		snd_cs46xx_playback_hw_params,	hw_free:		snd_cs46xx_playback_hw_free,	prepare:		snd_cs46xx_playback_prepare,	trigger:		snd_cs46xx_playback_trigger,	pointer:		snd_cs46xx_playback_direct_pointer,};snd_pcm_ops_t snd_cs46xx_playback_indirect_ops = {	open:			snd_cs46xx_playback_open,	close:			snd_cs46xx_playback_close,	ioctl:			snd_pcm_lib_ioctl,	hw_params:		snd_cs46xx_playback_hw_params,	hw_free:		snd_cs46xx_playback_hw_free,	prepare:		snd_cs46xx_playback_prepare,	trigger:		snd_cs46xx_playback_trigger,	copy:			snd_cs46xx_playback_copy,	pointer:		snd_cs46xx_playback_indirect_pointer,};snd_pcm_ops_t snd_cs46xx_capture_ops = {	open:			snd_cs46xx_capture_open,	close:			snd_cs46xx_capture_close,	ioctl:			snd_pcm_lib_ioctl,	hw_params:		snd_cs46xx_capture_hw_params,	hw_free:		snd_cs46xx_capture_hw_free,	prepare:		snd_cs46xx_capture_prepare,	trigger:		snd_cs46xx_capture_trigger,	pointer:		snd_cs46xx_capture_direct_pointer,};snd_pcm_ops_t snd_cs46xx_capture_indirect_ops = {	open:			snd_cs46xx_capture_open,	close:			snd_cs46xx_capture_close,	ioctl:			snd_pcm_lib_ioctl,	hw_params:		snd_cs46xx_capture_hw_params,	hw_free:		snd_cs46xx_capture_hw_free,	prepare:		snd_cs46xx_capture_prepare,	trigger:		snd_cs46xx_capture_trigger,	copy:			snd_cs46xx_capture_copy,	pointer:		snd_cs46xx_capture_indirect_pointer,};static void snd_cs46xx_pcm_free(snd_pcm_t *pcm){	cs46xx_t *chip = snd_magic_cast(cs46xx_t, pcm->private_data, return);	chip->pcm = NULL;	snd_pcm_lib_preallocate_free_for_all(pcm);}int __devinit snd_cs46xx_pcm(cs46xx_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, "CS46xx", device, 1, 1, &pcm)) < 0)		return err;	pcm->private_data = chip;	pcm->private_free = snd_cs46xx_pcm_free;	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_cs46xx_playback_ops);	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_cs46xx_capture_ops);	/* global setup */	pcm->info_flags = 0;	strcpy(pcm->name, "CS46xx");	chip->pcm = pcm;	snd_pcm_lib_preallocate_pci_pages_for_all(chip->pci, pcm, 64*1024, 256*1024);	if (rpcm)		*rpcm = pcm;	return 0;}/* *  Mixer routines */static void snd_cs46xx_mixer_free_ac97(ac97_t *ac97){	cs46xx_t *chip = snd_magic_cast(cs46xx_t, ac97->private_data, return);	chip->ac97 = NULL;	chip->eapd_switch = NULL;}static int snd_cs46xx_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 = 32767;	return 0;}static int snd_cs46xx_vol_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){	cs46xx_t *chip = snd_kcontrol_chip(kcontrol);	int reg = kcontrol->private_value;	unsigned int val = snd_cs46xx_peek(chip, reg);	ucontrol->value.integer.value[0] = 0xffff - (val >> 16);	ucontrol->value.integer.value[1] = 0xffff - (val & 0xffff);	return 0;}static int snd_cs46xx_vol_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){	cs46xx_t *chip = snd_kcontrol_chip(kcontrol);	int reg = kcontrol->private_value;	unsigned int val = ((0xffff - ucontrol->value.integer.value[0]) << 16 | 			    (0xffff - ucontrol->value.integer.value[1]));	unsigned int old = snd_cs46xx_peek(chip, reg);	int change = (old != val);	if (change)		snd_cs46xx_poke(chip, reg, val);	return change;}static snd_kcontrol_new_t snd_cs46xx_controls[] __devinitdata = {{	iface: SNDRV_CTL_ELEM_IFACE_MIXER,	name: "DAC Volume",	info: snd_cs46xx_vol_info,	get: snd_cs46xx_vol_get,	put: snd_cs46xx_vol_put,	private_value: BA1_PVOL,},{	iface: SNDRV_CTL_ELEM_IFACE_MIXER,	name: "ADC Volume",	info: snd_cs46xx_vol_info,	get: snd_cs46xx_vol_get,	put: snd_cs46xx_vol_put,	private_value: BA1_CVOL,}};int __devinit snd_cs46xx_mixer(cs46xx_t *chip){	snd_card_t *card = chip->card;	ac97_t ac97;	snd_ctl_elem_id_t id;	int err;	int idx;	memset(&ac97, 0, sizeof(ac97));	ac97.write = snd_cs46xx_ac97_write;	ac97.read = snd_cs46xx_ac97_read;	ac97.private_data = chip;	ac97.private_free = snd_cs46xx_mixer_free_ac97;	snd_cs46xx_ac97_write(&ac97, AC97_MASTER, 0x8000);	for (idx = 0; idx < 100; ++idx) {		if (snd_cs46xx_ac97_read(&ac97, AC97_MASTER) == 0x8000)			goto _ok;		set_current_state(TASK_INTERRUPTIBLE);		schedule_timeout(HZ/100);	}	return -ENXIO; _ok:	if ((err = snd_ac97_mixer(card, &ac97, &chip->ac97)) < 0)		return err;	for (idx = 0; idx < sizeof(snd_cs46xx_controls) / 		     sizeof(snd_cs46xx_controls[0]); idx++) {		snd_kcontrol_t *kctl;		kctl = snd_ctl_new1(&snd_cs46xx_controls[idx], chip);		if ((err = snd_ctl_add(card, kctl)) < 0)			return err;	}	/* get EAPD mixer switch (for voyetra hack) */	memset(&id, 0, sizeof(id));	id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;	strcpy(id.name, "External Amplifier Power Down");	chip->eapd_switch = snd_ctl_find_id(chip->card, &id);	return 0;}/* *  RawMIDI interface */static void snd_cs46xx_midi_reset(cs46xx_t *chip){	snd_cs46xx_pokeBA0(chip, BA0_MIDCR, MIDCR_MRST);	udelay(100);	snd_cs46xx_pokeBA0(chip, BA0_MIDCR, chip->midcr);}static int snd_cs46xx_midi_input_open(snd_rawmidi_substream_t * substream){	unsigned long flags;	cs46xx_t *chip = snd_magic_cast(cs46xx_t, substream->rmidi->private_data, return -ENXIO);	chip->active_ctrl(chip, 1);	spin_lock_irqsave(&chip->reg_lock, flags);	chip->uartm |= CS46XX_MODE_INPUT;	chip->midcr |= MIDCR_RXE;	chip->midi_input = substream;	if (!(chip->uartm & CS46XX_MODE_OUTPUT)) {		snd_cs46xx_midi_reset(chip);	} else {		snd_cs46xx_pokeBA0(chip, BA0_MIDCR, chip->midcr);	}	spin_unlock_irqrestore(&chip->reg_lock, flags);	return 0;}static int snd_cs46xx_midi_input_close(snd_rawmidi_substream_t * substream){	unsigned long flags;	cs46xx_t *chip = snd_magic_cast(cs46xx_t, substream->rmidi->private_data, return -ENXIO);	spin_lock_irqsave(&chip->reg_lock, flags);	chip->midcr &= ~(MIDCR_RXE | MIDCR_RIE);	chip->midi_input = NULL;	if (!(chip->uartm & CS46XX_MODE_OUTPUT)) {		snd_cs46xx_midi_reset(chip);	} else {		snd_cs46xx_pokeBA0(chip, BA0_MIDCR, chip->midcr);	}	chip->uartm &= ~CS46XX_MODE_INPUT;	spin_unlock_irqrestore(&chip->reg_lock, flags);	chip->active_ctrl(chip, -1);	return 0;}static int snd_cs46xx_midi_output_open(snd_rawmidi_substream_t * substream){	unsigned long flags;	cs46xx_t *chip = snd_magic_cast(cs46xx_t, substream->rmidi->private_data, return -ENXIO);	chip->active_ctrl(chip, 1);	spin_lock_irqsave(&chip->reg_lock, flags);	chip->uartm |= CS46XX_MODE_OUTPUT;	chip->midcr |= MIDCR_TXE;	chip->midi_output = substream;	if (!(chip->uartm & CS46XX_MODE_INPUT)) {		snd_cs46xx_midi_reset(chip);	} else {		snd_cs46xx_pokeBA0(chip, BA0_MIDCR, chip->midcr);	}	spin_unlock_irqrestore(&chip->reg_lock, flags);	return 0;}static int snd_cs46xx_midi_output_close(snd_rawmidi_substream_t * substream){	unsigned long flags;	cs46xx_t *chip = snd_magic_cast(cs46xx_t, substream->rmidi->private_data, return -ENXIO);	spin_lock_irqsave(&chip->reg_lock, flags);	chip->midcr &= ~(MIDCR_TXE | MIDCR_TIE);	chip->midi_output = NULL;	if (!(chip->uartm & CS46XX_MODE_INPUT)) {		snd_cs46xx_midi_reset(chip);	} else {		snd_cs46xx_pokeBA0(chip, BA0_MIDCR, chip->midcr);	}	chip->uartm &= ~CS46XX_MODE_OUTPUT;	spin_unlock_irqrestore(&chip->reg_lock, flags);	chip->active_ctrl(chip, -1);	return 0;}static void snd_cs46xx_midi_input_trigger(snd_rawmidi_substream_t * substream, int up){	unsigned long flags;	cs46xx_t *chip = snd_magic_cast(cs46xx_t, substream->rmidi->private_data, return);	spin_lock_irqsave(&chip->reg_lock, flags);	if (up) {		if ((chip->midcr & MIDCR_RIE) == 0) {

⌨️ 快捷键说明

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