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

📄 emu10k1x.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 4 页
字号:
/* close callback */static int snd_emu10k1x_playback_close(snd_pcm_substream_t *substream){	return 0;}/* hw_params callback */static int snd_emu10k1x_pcm_hw_params(snd_pcm_substream_t *substream,				      snd_pcm_hw_params_t * hw_params){	snd_pcm_runtime_t *runtime = substream->runtime;	emu10k1x_pcm_t *epcm = runtime->private_data;	if (! epcm->voice) {		epcm->voice = &epcm->emu->voices[substream->pcm->device];		epcm->voice->use = 1;		epcm->voice->epcm = epcm;	}	return snd_pcm_lib_malloc_pages(substream,					params_buffer_bytes(hw_params));}/* hw_free callback */static int snd_emu10k1x_pcm_hw_free(snd_pcm_substream_t *substream){	snd_pcm_runtime_t *runtime = substream->runtime;	emu10k1x_pcm_t *epcm;	if (runtime->private_data == NULL)		return 0;		epcm = runtime->private_data;	if (epcm->voice) {		epcm->voice->use = 0;		epcm->voice->epcm = NULL;		epcm->voice = NULL;	}	return snd_pcm_lib_free_pages(substream);}/* prepare callback */static int snd_emu10k1x_pcm_prepare(snd_pcm_substream_t *substream){	emu10k1x_t *emu = snd_pcm_substream_chip(substream);	snd_pcm_runtime_t *runtime = substream->runtime;	emu10k1x_pcm_t *epcm = runtime->private_data;	int voice = epcm->voice->number;	u32 *table_base = (u32 *)(emu->dma_buffer.area+1024*voice);	u32 period_size_bytes = frames_to_bytes(runtime, runtime->period_size);	int i;		for(i=0; i < runtime->periods; i++) {		*table_base++=runtime->dma_addr+(i*period_size_bytes);		*table_base++=period_size_bytes<<16;	}	snd_emu10k1x_ptr_write(emu, PLAYBACK_LIST_ADDR, voice, emu->dma_buffer.addr+1024*voice);	snd_emu10k1x_ptr_write(emu, PLAYBACK_LIST_SIZE, voice, (runtime->periods - 1) << 19);	snd_emu10k1x_ptr_write(emu, PLAYBACK_LIST_PTR, voice, 0);	snd_emu10k1x_ptr_write(emu, PLAYBACK_POINTER, voice, 0);	snd_emu10k1x_ptr_write(emu, PLAYBACK_UNKNOWN1, voice, 0);	snd_emu10k1x_ptr_write(emu, PLAYBACK_UNKNOWN2, voice, 0);	snd_emu10k1x_ptr_write(emu, PLAYBACK_DMA_ADDR, voice, runtime->dma_addr);	snd_emu10k1x_ptr_write(emu, PLAYBACK_PERIOD_SIZE, voice, frames_to_bytes(runtime, runtime->period_size)<<16);	return 0;}/* trigger callback */static int snd_emu10k1x_pcm_trigger(snd_pcm_substream_t *substream,				    int cmd){	emu10k1x_t *emu = snd_pcm_substream_chip(substream);	snd_pcm_runtime_t *runtime = substream->runtime;	emu10k1x_pcm_t *epcm = runtime->private_data;	int channel = epcm->voice->number;	int result = 0;//	snd_printk(KERN_INFO "trigger - emu10k1x = 0x%x, cmd = %i, pointer = %d\n", (int)emu, cmd, (int)substream->ops->pointer(substream));	switch (cmd) {	case SNDRV_PCM_TRIGGER_START:		if(runtime->periods == 2)			snd_emu10k1x_intr_enable(emu, (INTE_CH_0_LOOP | INTE_CH_0_HALF_LOOP) << channel);		else			snd_emu10k1x_intr_enable(emu, INTE_CH_0_LOOP << channel);		epcm->running = 1;		snd_emu10k1x_ptr_write(emu, TRIGGER_CHANNEL, 0, snd_emu10k1x_ptr_read(emu, TRIGGER_CHANNEL, 0)|(TRIGGER_CHANNEL_0<<channel));		break;	case SNDRV_PCM_TRIGGER_STOP:		epcm->running = 0;		snd_emu10k1x_intr_disable(emu, (INTE_CH_0_LOOP | INTE_CH_0_HALF_LOOP) << channel);		snd_emu10k1x_ptr_write(emu, TRIGGER_CHANNEL, 0, snd_emu10k1x_ptr_read(emu, TRIGGER_CHANNEL, 0) & ~(TRIGGER_CHANNEL_0<<channel));		break;	default:		result = -EINVAL;		break;	}	return result;}/* pointer callback */static snd_pcm_uframes_tsnd_emu10k1x_pcm_pointer(snd_pcm_substream_t *substream){	emu10k1x_t *emu = snd_pcm_substream_chip(substream);	snd_pcm_runtime_t *runtime = substream->runtime;	emu10k1x_pcm_t *epcm = runtime->private_data;	int channel = epcm->voice->number;	snd_pcm_uframes_t ptr = 0, ptr1 = 0, ptr2= 0,ptr3 = 0,ptr4 = 0;	if (!epcm->running)		return 0;	ptr3 = snd_emu10k1x_ptr_read(emu, PLAYBACK_LIST_PTR, channel);	ptr1 = snd_emu10k1x_ptr_read(emu, PLAYBACK_POINTER, channel);	ptr4 = snd_emu10k1x_ptr_read(emu, PLAYBACK_LIST_PTR, channel);	if(ptr4 == 0 && ptr1 == frames_to_bytes(runtime, runtime->buffer_size))		return 0;		if (ptr3 != ptr4) 		ptr1 = snd_emu10k1x_ptr_read(emu, PLAYBACK_POINTER, channel);	ptr2 = bytes_to_frames(runtime, ptr1);	ptr2 += (ptr4 >> 3) * runtime->period_size;	ptr = ptr2;	if (ptr >= runtime->buffer_size)		ptr -= runtime->buffer_size;	return ptr;}/* operators */static snd_pcm_ops_t snd_emu10k1x_playback_ops = {	.open =        snd_emu10k1x_playback_open,	.close =       snd_emu10k1x_playback_close,	.ioctl =       snd_pcm_lib_ioctl,	.hw_params =   snd_emu10k1x_pcm_hw_params,	.hw_free =     snd_emu10k1x_pcm_hw_free,	.prepare =     snd_emu10k1x_pcm_prepare,	.trigger =     snd_emu10k1x_pcm_trigger,	.pointer =     snd_emu10k1x_pcm_pointer,};/* open_capture callback */static int snd_emu10k1x_pcm_open_capture(snd_pcm_substream_t *substream){	emu10k1x_t *chip = snd_pcm_substream_chip(substream);	emu10k1x_pcm_t *epcm;	snd_pcm_runtime_t *runtime = substream->runtime;	int err;	if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0)                return err;	if ((err = snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 64)) < 0)                return err;	epcm = kzalloc(sizeof(*epcm), GFP_KERNEL);	if (epcm == NULL)		return -ENOMEM;	epcm->emu = chip;	epcm->substream = substream;	runtime->private_data = epcm;	runtime->private_free = snd_emu10k1x_pcm_free_substream;	runtime->hw = snd_emu10k1x_capture_hw;	return 0;}/* close callback */static int snd_emu10k1x_pcm_close_capture(snd_pcm_substream_t *substream){	return 0;}/* hw_params callback */static int snd_emu10k1x_pcm_hw_params_capture(snd_pcm_substream_t *substream,					      snd_pcm_hw_params_t * hw_params){	snd_pcm_runtime_t *runtime = substream->runtime;	emu10k1x_pcm_t *epcm = runtime->private_data;	if (! epcm->voice) {		if (epcm->emu->capture_voice.use)			return -EBUSY;		epcm->voice = &epcm->emu->capture_voice;		epcm->voice->epcm = epcm;		epcm->voice->use = 1;	}	return snd_pcm_lib_malloc_pages(substream,					params_buffer_bytes(hw_params));}/* hw_free callback */static int snd_emu10k1x_pcm_hw_free_capture(snd_pcm_substream_t *substream){	snd_pcm_runtime_t *runtime = substream->runtime;	emu10k1x_pcm_t *epcm;	if (runtime->private_data == NULL)		return 0;	epcm = runtime->private_data;	if (epcm->voice) {		epcm->voice->use = 0;		epcm->voice->epcm = NULL;		epcm->voice = NULL;	}	return snd_pcm_lib_free_pages(substream);}/* prepare capture callback */static int snd_emu10k1x_pcm_prepare_capture(snd_pcm_substream_t *substream){	emu10k1x_t *emu = snd_pcm_substream_chip(substream);	snd_pcm_runtime_t *runtime = substream->runtime;	snd_emu10k1x_ptr_write(emu, CAPTURE_DMA_ADDR, 0, runtime->dma_addr);	snd_emu10k1x_ptr_write(emu, CAPTURE_BUFFER_SIZE, 0, frames_to_bytes(runtime, runtime->buffer_size)<<16); // buffer size in bytes	snd_emu10k1x_ptr_write(emu, CAPTURE_POINTER, 0, 0);	snd_emu10k1x_ptr_write(emu, CAPTURE_UNKNOWN, 0, 0);	return 0;}/* trigger_capture callback */static int snd_emu10k1x_pcm_trigger_capture(snd_pcm_substream_t *substream,					    int cmd){	emu10k1x_t *emu = snd_pcm_substream_chip(substream);	snd_pcm_runtime_t *runtime = substream->runtime;	emu10k1x_pcm_t *epcm = runtime->private_data;	int result = 0;	switch (cmd) {	case SNDRV_PCM_TRIGGER_START:		snd_emu10k1x_intr_enable(emu, INTE_CAP_0_LOOP | 					 INTE_CAP_0_HALF_LOOP);		snd_emu10k1x_ptr_write(emu, TRIGGER_CHANNEL, 0, snd_emu10k1x_ptr_read(emu, TRIGGER_CHANNEL, 0)|TRIGGER_CAPTURE);		epcm->running = 1;		break;	case SNDRV_PCM_TRIGGER_STOP:		epcm->running = 0;		snd_emu10k1x_intr_disable(emu, INTE_CAP_0_LOOP | 					  INTE_CAP_0_HALF_LOOP);		snd_emu10k1x_ptr_write(emu, TRIGGER_CHANNEL, 0, snd_emu10k1x_ptr_read(emu, TRIGGER_CHANNEL, 0) & ~(TRIGGER_CAPTURE));		break;	default:		result = -EINVAL;		break;	}	return result;}/* pointer_capture callback */static snd_pcm_uframes_tsnd_emu10k1x_pcm_pointer_capture(snd_pcm_substream_t *substream){	emu10k1x_t *emu = snd_pcm_substream_chip(substream);	snd_pcm_runtime_t *runtime = substream->runtime;	emu10k1x_pcm_t *epcm = runtime->private_data;	snd_pcm_uframes_t ptr;	if (!epcm->running)		return 0;	ptr = bytes_to_frames(runtime, snd_emu10k1x_ptr_read(emu, CAPTURE_POINTER, 0));	if (ptr >= runtime->buffer_size)		ptr -= runtime->buffer_size;	return ptr;}static snd_pcm_ops_t snd_emu10k1x_capture_ops = {	.open =        snd_emu10k1x_pcm_open_capture,	.close =       snd_emu10k1x_pcm_close_capture,	.ioctl =       snd_pcm_lib_ioctl,	.hw_params =   snd_emu10k1x_pcm_hw_params_capture,	.hw_free =     snd_emu10k1x_pcm_hw_free_capture,	.prepare =     snd_emu10k1x_pcm_prepare_capture,	.trigger =     snd_emu10k1x_pcm_trigger_capture,	.pointer =     snd_emu10k1x_pcm_pointer_capture,};static unsigned short snd_emu10k1x_ac97_read(ac97_t *ac97,					     unsigned short reg){	emu10k1x_t *emu = ac97->private_data;	unsigned long flags;	unsigned short val;  	spin_lock_irqsave(&emu->emu_lock, flags);	outb(reg, emu->port + AC97ADDRESS);	val = inw(emu->port + AC97DATA);	spin_unlock_irqrestore(&emu->emu_lock, flags);	return val;}static void snd_emu10k1x_ac97_write(ac97_t *ac97,				    unsigned short reg, unsigned short val){	emu10k1x_t *emu = ac97->private_data;	unsigned long flags;  	spin_lock_irqsave(&emu->emu_lock, flags);	outb(reg, emu->port + AC97ADDRESS);	outw(val, emu->port + AC97DATA);	spin_unlock_irqrestore(&emu->emu_lock, flags);}static int snd_emu10k1x_ac97(emu10k1x_t *chip){	ac97_bus_t *pbus;	ac97_template_t ac97;	int err;	static ac97_bus_ops_t ops = {		.write = snd_emu10k1x_ac97_write,		.read = snd_emu10k1x_ac97_read,	};  	if ((err = snd_ac97_bus(chip->card, 0, &ops, NULL, &pbus)) < 0)		return err;	pbus->no_vra = 1; /* we don't need VRA */	memset(&ac97, 0, sizeof(ac97));	ac97.private_data = chip;	ac97.scaps = AC97_SCAP_NO_SPDIF;	return snd_ac97_mixer(pbus, &ac97, &chip->ac97);}static int snd_emu10k1x_free(emu10k1x_t *chip){	snd_emu10k1x_ptr_write(chip, TRIGGER_CHANNEL, 0, 0);	// disable interrupts	outl(0, chip->port + INTE);	// disable audio	outl(HCFG_LOCKSOUNDCACHE, chip->port + HCFG);	// release the i/o port	release_and_free_resource(chip->res_port);	// release the irq	if (chip->irq >= 0)		free_irq(chip->irq, (void *)chip);	// release the DMA	if (chip->dma_buffer.area) {		snd_dma_free_pages(&chip->dma_buffer);	}	pci_disable_device(chip->pci);	// release the data	kfree(chip);	return 0;}static int snd_emu10k1x_dev_free(snd_device_t *device){	emu10k1x_t *chip = device->device_data;	return snd_emu10k1x_free(chip);}static irqreturn_t snd_emu10k1x_interrupt(int irq, void *dev_id,					  struct pt_regs *regs){	unsigned int status;	emu10k1x_t *chip = dev_id;	emu10k1x_voice_t *pvoice = chip->voices;	int i;	int mask;	status = inl(chip->port + IPR);	if(status) {		// capture interrupt		if(status & (IPR_CAP_0_LOOP | IPR_CAP_0_HALF_LOOP)) {			emu10k1x_voice_t *pvoice = &chip->capture_voice;			if(pvoice->use)				snd_emu10k1x_pcm_interrupt(chip, pvoice);			else				snd_emu10k1x_intr_disable(chip, 							  INTE_CAP_0_LOOP |							  INTE_CAP_0_HALF_LOOP);		}				mask = IPR_CH_0_LOOP|IPR_CH_0_HALF_LOOP;		for(i = 0; i < 3; i++) {			if(status & mask) {				if(pvoice->use)					snd_emu10k1x_pcm_interrupt(chip, pvoice);				else 					snd_emu10k1x_intr_disable(chip, mask);			}			pvoice++;			mask <<= 1;		}

⌨️ 快捷键说明

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