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

📄 rme9652.c

📁 优龙2410linux2.6.8内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
			snd_iprintf(buffer, "%2d: off ", i + 1);		}		if (((i + 1) % 8) == 0) {			snd_iprintf(buffer, "\n");		}	}	snd_iprintf(buffer, "\n");}static void __devinit snd_rme9652_proc_init(rme9652_t *rme9652){	snd_info_entry_t *entry;	if (! snd_card_proc_new(rme9652->card, "rme9652", &entry))		snd_info_set_text_ops(entry, rme9652, 1024, snd_rme9652_proc_read);}static void snd_rme9652_free_buffers(rme9652_t *rme9652){	if (rme9652->capture_buffer_unaligned) {		snd_hammerfall_free_buffer(rme9652->pci, RME9652_DMA_AREA_BYTES,					   rme9652->capture_buffer_unaligned,					   rme9652->capture_buffer_addr, 1);	}	if (rme9652->playback_buffer_unaligned) {		snd_hammerfall_free_buffer(rme9652->pci, RME9652_DMA_AREA_BYTES,					   rme9652->playback_buffer_unaligned,					   rme9652->playback_buffer_addr, 0);	}}static int snd_rme9652_free(rme9652_t *rme9652){	if (rme9652->irq >= 0)		rme9652_stop(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 __devinit snd_rme9652_initialize_memory(rme9652_t *rme9652){	void *pb, *cb;	dma_addr_t pb_addr, cb_addr;	unsigned long pb_bus, cb_bus;	cb = snd_hammerfall_get_buffer(rme9652->pci, RME9652_DMA_AREA_BYTES, &cb_addr, 1);	pb = snd_hammerfall_get_buffer(rme9652->pci, RME9652_DMA_AREA_BYTES, &pb_addr, 0);	if (cb == 0 || pb == 0) {		if (cb) {			snd_hammerfall_free_buffer(rme9652->pci, RME9652_DMA_AREA_BYTES, cb, cb_addr, 1);		}		if (pb) {			snd_hammerfall_free_buffer(rme9652->pci, RME9652_DMA_AREA_BYTES, pb, pb_addr, 0);		}		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);}static irqreturn_t 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 IRQ_NONE;	}	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);	}	return IRQ_HANDLED;}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 __user *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);	if (copy_from_user(channel_buf + pos * 4, src, count * 4))		return -EFAULT;	return count;}static int snd_rme9652_capture_copy(snd_pcm_substream_t *substream, int channel,				    snd_pcm_uframes_t pos, void __user *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);	if (copy_to_user(dst, channel_buf + pos * 4, count * 4))		return -EFAULT;	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) {		struct list_head *pos;		snd_pcm_substream_t *s;		snd_pcm_runtime_t *oruntime = other->runtime;		snd_pcm_group_for_each(pos, substream) {			s = snd_pcm_group_substream_entry(pos);			if (s == other) {				oruntime->status->hw_ptr = runtime->status->hw_ptr;				break;			}		}	}	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 ((int)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) {		struct list_head *pos;		snd_pcm_substream_t *s;		snd_pcm_group_for_each(pos, substream) {			s = snd_pcm_group_substream_entry(pos);			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;			}		}		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);		}	} else {		if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) 			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(&rme9652->lock);	if (!rme9652->running)		rme9652_reset_hw_pointer(rme9652);	spin_unlock(&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),	.ra

⌨️ 快捷键说明

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