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

📄 nm256.c

📁 是关于linux2.5.1的完全源码
💻 C
📖 第 1 页 / 共 3 页
字号:
}static intsnd_nm256_capture_trigger(snd_pcm_substream_t *substream, int cmd){	nm256_t *chip = snd_pcm_substream_chip(substream);	nm256_stream_t *s = (nm256_stream_t*)substream->runtime->private_data;	unsigned long flags;	int err = 0;	snd_assert(s != NULL, return -ENXIO);	spin_lock_irqsave(&chip->reg_lock, flags);	switch (cmd) {	case SNDRV_PCM_TRIGGER_START:	case SNDRV_PCM_TRIGGER_RESUME:		if (! s->running) {			snd_nm256_capture_start(chip, s, substream);			s->running = 1;		}		break;	case SNDRV_PCM_TRIGGER_STOP:	case SNDRV_PCM_TRIGGER_SUSPEND:		if (s->running) {			snd_nm256_capture_stop(chip);			s->running = 0;		}		break;	default:		err = -EINVAL;		break;	}	spin_unlock_irqrestore(&chip->reg_lock, flags);	return err;}/* * prepare playback/capture channel */static int snd_nm256_pcm_prepare(snd_pcm_substream_t *substream){	nm256_t *chip = snd_pcm_substream_chip(substream);	snd_pcm_runtime_t *runtime = substream->runtime;	nm256_stream_t *s = (nm256_stream_t*)runtime->private_data;	unsigned long flags;	snd_assert(s, return -ENXIO);	s->dma_size = frames_to_bytes(runtime, substream->runtime->buffer_size);	s->period_size = frames_to_bytes(runtime, substream->runtime->period_size);	s->periods = substream->runtime->periods;	s->cur_period = 0;	spin_lock_irqsave(&chip->reg_lock, flags);	s->running = 0;	snd_nm256_set_format(chip, s, substream);	spin_unlock_irqrestore(&chip->reg_lock, flags);	return 0;}/* * get the current pointer */static snd_pcm_uframes_tsnd_nm256_playback_pointer(snd_pcm_substream_t * substream){	nm256_t *chip = snd_pcm_substream_chip(substream);	nm256_stream_t *s = (nm256_stream_t*)substream->runtime->private_data;	unsigned long curp;	snd_assert(s, return 0);	curp = snd_nm256_readl(chip, NM_PBUFFER_CURRP) - (unsigned long)s->buf;	curp %= s->dma_size;	return bytes_to_frames(substream->runtime, curp);}static snd_pcm_uframes_tsnd_nm256_capture_pointer(snd_pcm_substream_t * substream){	nm256_t *chip = snd_pcm_substream_chip(substream);	nm256_stream_t *s = (nm256_stream_t*)substream->runtime->private_data;	unsigned long curp;	snd_assert(s != NULL, return 0);	curp = snd_nm256_readl(chip, NM_RBUFFER_CURRP) - (unsigned long)s->buf;	curp %= s->dma_size;		return bytes_to_frames(substream->runtime, curp);}#ifndef __i386__/* FIXME: I/O space is not accessible via pointers on all architectures *//* * silence / copy for playback */static intsnd_nm256_playback_silence(snd_pcm_substream_t *substream,			   int channel, /* not used (interleaved data) */			   snd_pcm_uframes_t pos,			   snd_pcm_uframes_t count){	snd_pcm_runtime_t *runtime = substream->runtime;	nm256_stream_t *s = (nm256_stream_t*)runtime->private_data;	count = frames_to_bytes(runtime, count);	pos = frames_to_bytes(runtime, pos);	memset_io(s->bufptr + pos, 0, count);	return 0;}static intsnd_nm256_playback_copy(snd_pcm_substream_t *substream,			int channel, /* not used (interleaved data) */			snd_pcm_uframes_t pos,			void *src,			snd_pcm_uframes_t count){	snd_pcm_runtime_t *runtime = substream->runtime;	nm256_stream_t *s = (nm256_stream_t*)runtime->private_data;	count = frames_to_bytes(runtime, count);	pos = frames_to_bytes(runtime, pos);	if (copy_from_user_toio(s->bufptr + pos, src, count))		return -EFAULT;	return 0;}/* * copy to user */static intsnd_nm256_capture_copy(snd_pcm_substream_t *substream,		       int channel, /* not used (interleaved data) */		       snd_pcm_uframes_t pos,		       void *dst,		       snd_pcm_uframes_t count){	snd_pcm_runtime_t *runtime = substream->runtime;	nm256_stream_t *s = (nm256_stream_t*)runtime->private_data;	count = frames_to_bytes(runtime, count);	pos = frames_to_bytes(runtime, pos);	if (copy_to_user_fromio(dst, s->bufptr + pos, count))		return -EFAULT;	return 0;}#endif /* !__i386__ *//* * update playback/capture watermarks *//* spinlock held! */static voidsnd_nm256_playback_update(nm256_t *chip){	nm256_stream_t *s;	s = &chip->streams[SNDRV_PCM_STREAM_PLAYBACK];	if (s->running && s->substream) {		spin_unlock(&chip->reg_lock);		snd_pcm_period_elapsed(s->substream);		spin_lock(&chip->reg_lock);		snd_nm256_playback_mark(chip, s);	}}/* spinlock held! */static voidsnd_nm256_capture_update(nm256_t *chip){	nm256_stream_t *s;	s = &chip->streams[SNDRV_PCM_STREAM_CAPTURE];	if (s->running && s->substream) {		spin_unlock(&chip->reg_lock);		snd_pcm_period_elapsed(s->substream);		spin_lock(&chip->reg_lock);		snd_nm256_capture_mark(chip, s);	}}/* * hardware info */static snd_pcm_hardware_t snd_nm256_playback ={	info:#ifdef __i386__				SNDRV_PCM_INFO_MMAP|SNDRV_PCM_INFO_MMAP_VALID|#endif				SNDRV_PCM_INFO_INTERLEAVED |				/*SNDRV_PCM_INFO_PAUSE |*/				SNDRV_PCM_INFO_RESUME,	formats:		SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE,	rates:			SNDRV_PCM_RATE_KNOT/*24k*/ | SNDRV_PCM_RATE_8000_48000,	rate_min:		8000,	rate_max:		48000,	channels_min:		1,	channels_max:		2,	periods_min:		2,	periods_max:		1024,	buffer_bytes_max:	128 * 1024,	period_bytes_min:	256,	period_bytes_max:	128 * 1024,};static snd_pcm_hardware_t snd_nm256_capture ={	info:#ifdef __i386__				SNDRV_PCM_INFO_MMAP|SNDRV_PCM_INFO_MMAP_VALID|#endif				SNDRV_PCM_INFO_INTERLEAVED |				/*SNDRV_PCM_INFO_PAUSE |*/				SNDRV_PCM_INFO_RESUME,	formats:		SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE,	rates:			SNDRV_PCM_RATE_KNOT/*24k*/ | SNDRV_PCM_RATE_8000_48000,	rate_min:		8000,	rate_max:		48000,	channels_min:		1,	channels_max:		2,	periods_min:		2,	periods_max:		1024,	buffer_bytes_max:	128 * 1024,	period_bytes_min:	256,	period_bytes_max:	128 * 1024,};/* set dma transfer size */static int snd_nm256_pcm_hw_params(snd_pcm_substream_t *substream, snd_pcm_hw_params_t *hw_params){	/* area and addr are already set and unchanged */	substream->runtime->dma_bytes = params_buffer_bytes(hw_params);	return 0;}/* * open */static void snd_nm256_setup_stream(nm256_t *chip, nm256_stream_t *s,				   snd_pcm_substream_t *substream,				   snd_pcm_hardware_t *hw_ptr){	snd_pcm_runtime_t *runtime = substream->runtime;	s->running = 0;	runtime->hw = *hw_ptr;	runtime->hw.buffer_bytes_max = s->bufsize;	runtime->hw.period_bytes_max = s->bufsize / 2;	runtime->dma_area = (void*) s->bufptr;	runtime->dma_addr = s->bufptr_addr;	runtime->dma_bytes = s->bufsize;	runtime->private_data = s;	s->substream = substream;	snd_pcm_set_sync(substream);	snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,				   &constraints_rates);}static intsnd_nm256_playback_open(snd_pcm_substream_t *substream){	nm256_t *chip = snd_pcm_substream_chip(substream);	snd_nm256_setup_stream(chip, &chip->streams[SNDRV_PCM_STREAM_PLAYBACK],			       substream, &snd_nm256_playback);	return 0;}static intsnd_nm256_capture_open(snd_pcm_substream_t *substream){	nm256_t *chip = snd_pcm_substream_chip(substream);	snd_nm256_setup_stream(chip, &chip->streams[SNDRV_PCM_STREAM_CAPTURE],			       substream, &snd_nm256_capture);	return 0;}/* * close - we don't have to do special.. */static intsnd_nm256_playback_close(snd_pcm_substream_t *substream){	return 0;}static intsnd_nm256_capture_close(snd_pcm_substream_t *substream){	return 0;}/* * create a pcm instance */static snd_pcm_ops_t snd_nm256_playback_ops = {	open:		snd_nm256_playback_open,	close:		snd_nm256_playback_close,	ioctl:		snd_pcm_lib_ioctl,	hw_params:	snd_nm256_pcm_hw_params,	prepare:	snd_nm256_pcm_prepare,	trigger:	snd_nm256_playback_trigger,	pointer:	snd_nm256_playback_pointer,#ifndef __i386__	copy:		snd_nm256_playback_copy,	silence:	snd_nm256_playback_silence,#endif};static snd_pcm_ops_t snd_nm256_capture_ops = {	open:		snd_nm256_capture_open,	close:		snd_nm256_capture_close,	ioctl:		snd_pcm_lib_ioctl,	hw_params:	snd_nm256_pcm_hw_params,	prepare:	snd_nm256_pcm_prepare,	trigger:	snd_nm256_capture_trigger,	pointer:	snd_nm256_capture_pointer,#ifndef __i386__	copy:		snd_nm256_capture_copy,#endif};static int __initsnd_nm256_pcm(nm256_t *chip, int device){	snd_pcm_t *pcm;	int i, err;	for (i = 0; i < 2; i++) {		nm256_stream_t *s = &chip->streams[i];		s->bufptr = chip->buffer +  s->buf - chip->buffer_start;		s->bufptr_addr = chip->buffer_addr + s->buf - chip->buffer_start;	}	err = snd_pcm_new(chip->card, chip->card->driver, device,			  1, 1, &pcm);	if (err < 0)		return err;	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_nm256_playback_ops);	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_nm256_capture_ops);	pcm->private_data = chip;	pcm->info_flags = 0;	chip->pcm = pcm;	return 0;}/*  * Initialize the hardware.  */static voidsnd_nm256_init_chip(nm256_t *chip){	unsigned long flags;	spin_lock_irqsave(&chip->reg_lock, flags);	/* Reset everything. */	snd_nm256_writeb(chip, 0x0, 0x11);	snd_nm256_writew(chip, 0x214, 0);	/* stop sounds.. */	//snd_nm256_playback_stop(chip);	//snd_nm256_capture_stop(chip);	spin_unlock_irqrestore(&chip->reg_lock, flags);}inline static voidsnd_nm256_intr_check(nm256_t *chip){	if (chip->badintrcount++ > 1000) {		/*		 * I'm not sure if the best thing is to stop the card from		 * playing or just release the interrupt (after all, we're in		 * a bad situation, so doing fancy stuff may not be such a good		 * idea).		 *		 * I worry about the card engine continuing to play noise		 * over and over, however--that could become a very		 * obnoxious problem.  And we know that when this usually		 * happens things are fairly safe, it just means the user's		 * inserted a PCMCIA card and someone's spamming us with IRQ 9s.		 */		if (chip->streams[SNDRV_PCM_STREAM_PLAYBACK].running)			snd_nm256_playback_stop(chip);		if (chip->streams[SNDRV_PCM_STREAM_CAPTURE].running)			snd_nm256_capture_stop(chip);		chip->badintrcount = 0;	}}/*  * Handle a potential interrupt for the device referred to by DEV_ID.  * * I don't like the cut-n-paste job here either between the two routines, * but there are sufficient differences between the two interrupt handlers * that parameterizing it isn't all that great either.  (Could use a macro, * I suppose...yucky bleah.) */static voidsnd_nm256_interrupt(int irq, void *dev_id, struct pt_regs *dummy){	nm256_t *chip = snd_magic_cast(nm256_t, dev_id, return);	u16 status;	u8 cbyte;	status = snd_nm256_readw(chip, NM_INT_REG);	/* Not ours. */	if (status == 0) {		snd_nm256_intr_check(chip);		return;	}	chip->badintrcount = 0;	/* Rather boring; check for individual interrupts and process them. */	spin_lock(&chip->reg_lock);	if (status & NM_PLAYBACK_INT) {		status &= ~NM_PLAYBACK_INT;		NM_ACK_INT(chip, NM_PLAYBACK_INT);		snd_nm256_playback_update(chip);	}	if (status & NM_RECORD_INT) {		status &= ~NM_RECORD_INT;		NM_ACK_INT(chip, NM_RECORD_INT);		snd_nm256_capture_update(chip);	}	if (status & NM_MISC_INT_1) {		status &= ~NM_MISC_INT_1;		NM_ACK_INT(chip, NM_MISC_INT_1);		snd_printd("NM256: Got misc interrupt #1\n");		snd_nm256_writew(chip, NM_INT_REG, 0x8000);		cbyte = snd_nm256_readb(chip, 0x400);		snd_nm256_writeb(chip, 0x400, cbyte | 2);	}	if (status & NM_MISC_INT_2) {		status &= ~NM_MISC_INT_2;		NM_ACK_INT(chip, NM_MISC_INT_2);		snd_printd("NM256: Got misc interrupt #2\n");		cbyte = snd_nm256_readb(chip, 0x400);		snd_nm256_writeb(chip, 0x400, cbyte & ~2);	}	/* Unknown interrupt. */	if (status) {		snd_printd("NM256: Fire in the hole! Unknown status 0x%x\n",			   status);		/* Pray. */		NM_ACK_INT(chip, status);	}	spin_unlock(&chip->reg_lock);}/* * Handle a potential interrupt for the device referred to by DEV_ID. * This handler is for the 256ZX, and is very similar to the non-ZX * routine. */static voidsnd_nm256_interrupt_zx(int irq, void *dev_id, struct pt_regs *dummy){	nm256_t *chip = snd_magic_cast(nm256_t, dev_id, return);	u32 status;	u8 cbyte;	status = snd_nm256_readl(chip, NM_INT_REG);	/* Not ours. */	if (status == 0) {		snd_nm256_intr_check(chip);		return;	}	chip->badintrcount = 0;	/* Rather boring; check for individual interrupts and process them. */	spin_lock(&chip->reg_lock);	if (status & NM2_PLAYBACK_INT) {		status &= ~NM2_PLAYBACK_INT;		NM2_ACK_INT(chip, NM2_PLAYBACK_INT);		snd_nm256_playback_update(chip);	}	if (status & NM2_RECORD_INT) {		status &= ~NM2_RECORD_INT;		NM2_ACK_INT(chip, NM2_RECORD_INT);		snd_nm256_capture_update(chip);	}	if (status & NM2_MISC_INT_1) {		status &= ~NM2_MISC_INT_1;		NM2_ACK_INT(chip, NM2_MISC_INT_1);		snd_printd("NM256: Got misc interrupt #1\n");		cbyte = snd_nm256_readb(chip, 0x400);		snd_nm256_writeb(chip, 0x400, cbyte | 2);	}	if (status & NM2_MISC_INT_2) {		status &= ~NM2_MISC_INT_2;		NM2_ACK_INT(chip, NM2_MISC_INT_2);		snd_printd("NM256: Got misc interrupt #2\n");		cbyte = snd_nm256_readb(chip, 0x400);		snd_nm256_writeb(chip, 0x400, cbyte & ~2);	}	/* Unknown interrupt. */	if (status) {		snd_printd("NM256: Fire in the hole! Unknown status 0x%x\n",			   status);		/* Pray. */		NM2_ACK_INT(chip, status);	}	spin_unlock(&chip->reg_lock);}/* * AC97 interface *//* * Waits for the mixer to become ready to be written; returns a zero value * if it timed out. */static intsnd_nm256_ac97_ready(nm256_t *chip){	int timeout = 10;	u32 testaddr;	u16 testb;	testaddr = chip->mixer_status_offset;	testb = chip->mixer_status_mask;	/* 	 * Loop around waiting for the mixer to become ready. 	 */	while (timeout-- > 0) {		if ((snd_nm256_readw(chip, testaddr) & testb) == 0)			return 1;		udelay(100);	}	return 0;}/* */static unsigned short

⌨️ 快捷键说明

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