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

📄 rme9652.c

📁 是关于linux2.5.1的完全源码
💻 C
📖 第 1 页 / 共 5 页
字号:
		snd_rme9652_free_buffer(rme9652->dev, rme9652->playback_buffer_unaligned);#endif	}}static int snd_rme9652_free(rme9652_t *rme9652){	if (rme9652->irq >= 0)		rme9652_stop(rme9652);	snd_rme9652_proc_done(rme9652);	snd_rme9652_free_buffers(rme9652);	if (rme9652->iobase)		iounmap((void *) rme9652->iobase);	if (rme9652->res_port) {		release_resource(rme9652->res_port);		kfree_nocheck(rme9652->res_port);	}	if (rme9652->irq >= 0)		free_irq(rme9652->irq, (void *)rme9652);	return 0;}static int __init snd_rme9652_initialize_memory(rme9652_t *rme9652){	void *pb, *cb;	dma_addr_t pb_addr, cb_addr;	unsigned long pb_bus, cb_bus;#ifndef RME9652_PREALLOCATE_MEMORY	cb = snd_malloc_pci_pages(rme9652->pci, RME9652_DMA_AREA_BYTES, &cb_addr);	pb = snd_malloc_pci_pages(rme9652->pci, RME9652_DMA_AREA_BYTES, &pb_addr);#else	cb = snd_rme9652_get_buffer(rme9652->dev, &cb_addr);	pb = snd_rme9652_get_buffer(rme9652->dev, &pb_addr);#endif	if (cb == 0 || pb == 0) {		if (cb) {#ifdef RME9652_PREALLOCATE_MEMORY			snd_rme9652_free_buffer(rme9652->dev, cb);#else			snd_free_pci_pages(rme9652->pci, RME9652_DMA_AREA_BYTES, cb, cb_addr);#endif		}		if (pb) {#ifdef RME9652_PREALLOCATE_MEMORY			snd_rme9652_free_buffer(rme9652->dev, pb);#else			snd_free_pci_pages(rme9652->pci, RME9652_DMA_AREA_BYTES, pb, pb_addr);#endif		}		printk(KERN_ERR "%s: no buffers available\n", rme9652->card_name);		return -ENOMEM;	}	/* save raw addresses for use when freeing memory later */	rme9652->capture_buffer_unaligned = cb;	rme9652->playback_buffer_unaligned = pb;	rme9652->capture_buffer_addr = cb_addr;	rme9652->playback_buffer_addr = pb_addr;	/* Align to bus-space 64K boundary */	cb_bus = (cb_addr + 0xFFFF) & ~0xFFFFl;	pb_bus = (pb_addr + 0xFFFF) & ~0xFFFFl;	/* Tell the card where it is */	rme9652_write(rme9652, RME9652_rec_buffer, cb_bus);	rme9652_write(rme9652, RME9652_play_buffer, pb_bus);	rme9652->capture_buffer = cb + (cb_bus - cb_addr);	rme9652->playback_buffer = pb + (pb_bus - pb_addr);	return 0;}static void snd_rme9652_set_defaults(rme9652_t *rme9652){	unsigned int k;	/* ASSUMPTION: rme9652->lock is either held, or	   there is no need to hold it (e.g. during module	   initalization).	 */	/* set defaults:	   SPDIF Input via Coax 	   autosync clock mode	   maximum latency (7 = 8192 samples, 64Kbyte buffer,	   which implies 2 4096 sample, 32Kbyte periods).	   	   if rev 1.5, initialize the S/PDIF receiver.	 */	rme9652->control_register =	    RME9652_inp_0 | rme9652_encode_latency(7);	rme9652_write(rme9652, RME9652_control_register, rme9652->control_register);	rme9652_reset_hw_pointer(rme9652);	rme9652_compute_period_size(rme9652);	/* default: thru off for all channels */	for (k = 0; k < RME9652_NCHANNELS; ++k)		rme9652_write(rme9652, RME9652_thru_base + k * 4, 0);	rme9652->thru_bits = 0;	rme9652->passthru = 0;	/* set a default rate so that the channel map is set up */	rme9652_set_rate(rme9652, 48000);}void snd_rme9652_interrupt(int irq, void *dev_id, struct pt_regs *regs){	rme9652_t *rme9652 = (rme9652_t *) dev_id;	if (!(rme9652_read(rme9652, RME9652_status_register) & RME9652_IRQ)) {		return;	}	rme9652_write(rme9652, RME9652_irq_clear, 0);	if (rme9652->capture_substream) {		snd_pcm_period_elapsed(rme9652->pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream);	}	if (rme9652->playback_substream) {		snd_pcm_period_elapsed(rme9652->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream);	}}static snd_pcm_uframes_t snd_rme9652_hw_pointer(snd_pcm_substream_t *substream){	rme9652_t *rme9652 = _snd_pcm_substream_chip(substream);	return rme9652_hw_pointer(rme9652);}static char *rme9652_channel_buffer_location(rme9652_t *rme9652,					     int stream,					     int channel){	int mapped_channel;        snd_assert(channel >= 0 || channel < RME9652_NCHANNELS, return NULL);        	if ((mapped_channel = rme9652->channel_map[channel]) < 0) {		return NULL;	}		if (stream == SNDRV_PCM_STREAM_CAPTURE) {		return rme9652->capture_buffer +			(mapped_channel * RME9652_CHANNEL_BUFFER_BYTES);	} else {		return rme9652->playback_buffer +			(mapped_channel * RME9652_CHANNEL_BUFFER_BYTES);	}}static int snd_rme9652_playback_copy(snd_pcm_substream_t *substream, int channel,				     snd_pcm_uframes_t pos, void *src, snd_pcm_uframes_t count){	rme9652_t *rme9652 = _snd_pcm_substream_chip(substream);	char *channel_buf;	snd_assert(pos + count <= RME9652_CHANNEL_BUFFER_BYTES / 4, return -EINVAL);	channel_buf = rme9652_channel_buffer_location (rme9652,						       substream->pstr->stream,						       channel);	snd_assert(channel_buf != NULL, return -EIO);	copy_from_user(channel_buf + pos * 4, src, count * 4);	return count;}static int snd_rme9652_capture_copy(snd_pcm_substream_t *substream, int channel,				    snd_pcm_uframes_t pos, void *dst, snd_pcm_uframes_t count){	rme9652_t *rme9652 = _snd_pcm_substream_chip(substream);	char *channel_buf;	snd_assert(pos + count <= RME9652_CHANNEL_BUFFER_BYTES / 4, return -EINVAL);	channel_buf = rme9652_channel_buffer_location (rme9652,						       substream->pstr->stream,						       channel);	snd_assert(channel_buf != NULL, return -EIO);	copy_to_user(dst, channel_buf + pos * 4, count * 4);	return count;}static int snd_rme9652_hw_silence(snd_pcm_substream_t *substream, int channel,				  snd_pcm_uframes_t pos, snd_pcm_uframes_t count){	rme9652_t *rme9652 = _snd_pcm_substream_chip(substream);	char *channel_buf;	channel_buf = rme9652_channel_buffer_location (rme9652,						       substream->pstr->stream,						       channel);	snd_assert(channel_buf != NULL, return -EIO);	memset(channel_buf + pos * 4, 0, count * 4);	return count;}static int snd_rme9652_reset(snd_pcm_substream_t *substream){	snd_pcm_runtime_t *runtime = substream->runtime;	rme9652_t *rme9652 = _snd_pcm_substream_chip(substream);	snd_pcm_substream_t *other;	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)		other = rme9652->capture_substream;	else		other = rme9652->playback_substream;	if (rme9652->running)		runtime->status->hw_ptr = rme9652_hw_pointer(rme9652);	else		runtime->status->hw_ptr = 0;	if (other) {		snd_pcm_substream_t *s = substream;		snd_pcm_runtime_t *oruntime = other->runtime;		do {			s = s->link_next;			if (s == other) {				oruntime->status->hw_ptr = runtime->status->hw_ptr;				break;			}		} while (s != substream);	}	return 0;}static int snd_rme9652_hw_params(snd_pcm_substream_t *substream,				 snd_pcm_hw_params_t *params){	rme9652_t *rme9652 = _snd_pcm_substream_chip(substream);	int err;	pid_t this_pid;	pid_t other_pid;	spin_lock_irq(&rme9652->lock);	if (substream->pstr->stream == SNDRV_PCM_STREAM_PLAYBACK) {		rme9652->control_register &= ~(RME9652_PRO | RME9652_Dolby | RME9652_EMP);		rme9652_write(rme9652, RME9652_control_register, rme9652->control_register |= rme9652->creg_spdif_stream);		this_pid = rme9652->playback_pid;		other_pid = rme9652->capture_pid;	} else {		this_pid = rme9652->capture_pid;		other_pid = rme9652->playback_pid;	}	if ((other_pid > 0) && (this_pid != other_pid)) {		/* The other stream is open, and not by the same		   task as this one. Make sure that the parameters		   that matter are the same.		 */		if (params_rate(params) !=		    rme9652_adat_sample_rate(rme9652)) {			spin_unlock_irq(&rme9652->lock);			_snd_pcm_hw_param_setempty(params, SNDRV_PCM_HW_PARAM_RATE);			return -EBUSY;		}		if (params_period_size(params) != rme9652->period_bytes / 4) {			spin_unlock_irq(&rme9652->lock);			_snd_pcm_hw_param_setempty(params, SNDRV_PCM_HW_PARAM_PERIOD_SIZE);			return -EBUSY;		}		/* We're fine. */		spin_unlock_irq(&rme9652->lock); 		return 0;	} else {		spin_unlock_irq(&rme9652->lock);	}	/* how to make sure that the rate matches an externally-set one ?	 */	if ((err = rme9652_set_rate(rme9652, params_rate(params))) < 0) {		_snd_pcm_hw_param_setempty(params, SNDRV_PCM_HW_PARAM_RATE);		return err;	}	if ((err = rme9652_set_interrupt_interval(rme9652, params_period_size(params))) < 0) {		_snd_pcm_hw_param_setempty(params, SNDRV_PCM_HW_PARAM_PERIOD_SIZE);		return err;	}	return 0;}static int snd_rme9652_channel_info(snd_pcm_substream_t *substream,				    snd_pcm_channel_info_t *info){	rme9652_t *rme9652 = _snd_pcm_substream_chip(substream);	int chn;	snd_assert(info->channel < RME9652_NCHANNELS, return -EINVAL);	if ((chn = rme9652->channel_map[info->channel]) < 0) {		return -EINVAL;	}	info->offset = chn * RME9652_CHANNEL_BUFFER_BYTES;	info->first = 0;	info->step = 32;	return 0;}static int snd_rme9652_ioctl(snd_pcm_substream_t *substream,			     unsigned int cmd, void *arg){	switch (cmd) {	case SNDRV_PCM_IOCTL1_RESET:	{		return snd_rme9652_reset(substream);	}	case SNDRV_PCM_IOCTL1_CHANNEL_INFO:	{		snd_pcm_channel_info_t *info = arg;		return snd_rme9652_channel_info(substream, info);	}	default:		break;	}	return snd_pcm_lib_ioctl(substream, cmd, arg);}static void rme9652_silence_playback(rme9652_t *rme9652){	memset(rme9652->playback_buffer, 0, RME9652_DMA_AREA_BYTES);}static int snd_rme9652_trigger(snd_pcm_substream_t *substream,			       int cmd){	rme9652_t *rme9652 = _snd_pcm_substream_chip(substream);	snd_pcm_substream_t *other;	int running;	spin_lock(&rme9652->lock);	running = rme9652->running;	switch (cmd) {	case SNDRV_PCM_TRIGGER_START:		running |= 1 << substream->stream;		break;	case SNDRV_PCM_TRIGGER_STOP:		running &= ~(1 << substream->stream);		break;	default:		snd_BUG();		spin_unlock(&rme9652->lock);		return -EINVAL;	}	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)		other = rme9652->capture_substream;	else		other = rme9652->playback_substream;	if (other) {		snd_pcm_substream_t *s = substream;		do {			s = s->link_next;			if (s == other) {				snd_pcm_trigger_done(s, substream);				if (cmd == SNDRV_PCM_TRIGGER_START)					running |= 1 << s->stream;				else					running &= ~(1 << s->stream);				goto _ok;			}		} while (s != substream);		if (cmd == SNDRV_PCM_TRIGGER_START) {			if (!(running & (1 << SNDRV_PCM_STREAM_PLAYBACK)) &&			    substream->stream == SNDRV_PCM_STREAM_CAPTURE)				rme9652_silence_playback(rme9652);		} else {			if (running &&			    substream->stream == SNDRV_PCM_STREAM_PLAYBACK)				rme9652_silence_playback(rme9652);		}	} _ok:	snd_pcm_trigger_done(substream, substream);	if (!rme9652->running && running)		rme9652_start(rme9652);	else if (rme9652->running && !running)		rme9652_stop(rme9652);	rme9652->running = running;	spin_unlock(&rme9652->lock);	return 0;}static int snd_rme9652_prepare(snd_pcm_substream_t *substream){	rme9652_t *rme9652 = _snd_pcm_substream_chip(substream);	int result = 0;	spin_lock_irq(&rme9652->lock);	if (!rme9652->running)		rme9652_reset_hw_pointer(rme9652);	spin_unlock_irq(&rme9652->lock);	return result;}static snd_pcm_hardware_t snd_rme9652_playback_subinfo ={	info:			(SNDRV_PCM_INFO_MMAP |				 SNDRV_PCM_INFO_MMAP_VALID |				 SNDRV_PCM_INFO_NONINTERLEAVED |				 SNDRV_PCM_INFO_SYNC_START |				 SNDRV_PCM_INFO_DOUBLE),	formats:		SNDRV_PCM_FMTBIT_S32_LE,	rates:			(SNDRV_PCM_RATE_44100 | 				 SNDRV_PCM_RATE_48000 | 				 SNDRV_PCM_RATE_88200 | 				 SNDRV_PCM_RATE_96000),	rate_min:		44100,	rate_max:		96000,	channels_min:		10,	channels_max:		26,	buffer_bytes_max:	1024*1024,	period_bytes_min:	1,	period_bytes_max:	1024*1024,	periods_min:		2,	periods_max:		2,	fifo_size:		0,};static snd_pcm_hardware_t snd_rme9652_capture_subinfo ={	info:			(SNDRV_PCM_INFO_MMAP |				 SNDRV_PCM_INFO_MMAP_VALID |				 SNDRV_PCM_INFO_NONINTERLEAVED |				 SNDRV_PCM_INFO_SYNC_START),	formats:		SNDRV_PCM_FMTBIT_S32_LE,	rates:			(SNDRV_PCM_RATE_44100 | 				 SNDRV_PCM_RATE_48000 | 				 SNDRV_PCM_RATE_88200 | 				 SNDRV_PCM_

⌨️ 快捷键说明

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