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

📄 rme32.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
	rme32->playback_periodsize = 0;	spdif = (rme32->wcreg & RME32_WCR_ADAT) == 0;	spin_unlock_irq(&rme32->lock);	if (spdif) {		rme32->spdif_ctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE;		snd_ctl_notify(rme32->card, SNDRV_CTL_EVENT_MASK_VALUE |			       SNDRV_CTL_EVENT_MASK_INFO,			       &rme32->spdif_ctl->id);	}	return 0;}static int snd_rme32_capture_close(struct snd_pcm_substream *substream){	struct rme32 *rme32 = snd_pcm_substream_chip(substream);	spin_lock_irq(&rme32->lock);	rme32->capture_substream = NULL;	rme32->capture_periodsize = 0;	spin_unlock(&rme32->lock);	return 0;}static int snd_rme32_playback_prepare(struct snd_pcm_substream *substream){	struct rme32 *rme32 = snd_pcm_substream_chip(substream);	spin_lock_irq(&rme32->lock);	if (rme32->fullduplex_mode) {		memset(&rme32->playback_pcm, 0, sizeof(rme32->playback_pcm));		rme32->playback_pcm.hw_buffer_size = RME32_BUFFER_SIZE;		rme32->playback_pcm.sw_buffer_size = snd_pcm_lib_buffer_bytes(substream);	} else {		writel(0, rme32->iobase + RME32_IO_RESET_POS);	}	if (rme32->wcreg & RME32_WCR_SEL)		rme32->wcreg &= ~RME32_WCR_MUTE;	writel(rme32->wcreg, rme32->iobase + RME32_IO_CONTROL_REGISTER);	spin_unlock_irq(&rme32->lock);	return 0;}static int snd_rme32_capture_prepare(struct snd_pcm_substream *substream){	struct rme32 *rme32 = snd_pcm_substream_chip(substream);	spin_lock_irq(&rme32->lock);	if (rme32->fullduplex_mode) {		memset(&rme32->capture_pcm, 0, sizeof(rme32->capture_pcm));		rme32->capture_pcm.hw_buffer_size = RME32_BUFFER_SIZE;		rme32->capture_pcm.hw_queue_size = RME32_BUFFER_SIZE / 2;		rme32->capture_pcm.sw_buffer_size = snd_pcm_lib_buffer_bytes(substream);	} else {		writel(0, rme32->iobase + RME32_IO_RESET_POS);	}	spin_unlock_irq(&rme32->lock);	return 0;}static intsnd_rme32_pcm_trigger(struct snd_pcm_substream *substream, int cmd){	struct rme32 *rme32 = snd_pcm_substream_chip(substream);	struct snd_pcm_substream *s;	spin_lock(&rme32->lock);	snd_pcm_group_for_each_entry(s, substream) {		if (s != rme32->playback_substream &&		    s != rme32->capture_substream)			continue;		switch (cmd) {		case SNDRV_PCM_TRIGGER_START:			rme32->running |= (1 << s->stream);			if (rme32->fullduplex_mode) {				/* remember the current DMA position */				if (s == rme32->playback_substream) {					rme32->playback_pcm.hw_io =					rme32->playback_pcm.hw_data = snd_rme32_pcm_byteptr(rme32);				} else {					rme32->capture_pcm.hw_io =					rme32->capture_pcm.hw_data = snd_rme32_pcm_byteptr(rme32);				}			}			break;		case SNDRV_PCM_TRIGGER_STOP:			rme32->running &= ~(1 << s->stream);			break;		}		snd_pcm_trigger_done(s, substream);	}		/* prefill playback buffer */	if (cmd == SNDRV_PCM_TRIGGER_START && rme32->fullduplex_mode) {		snd_pcm_group_for_each_entry(s, substream) {			if (s == rme32->playback_substream) {				s->ops->ack(s);				break;			}		}	}	switch (cmd) {	case SNDRV_PCM_TRIGGER_START:		if (rme32->running && ! RME32_ISWORKING(rme32))			snd_rme32_pcm_start(rme32, 0);		break;	case SNDRV_PCM_TRIGGER_STOP:		if (! rme32->running && RME32_ISWORKING(rme32))			snd_rme32_pcm_stop(rme32, 0);		break;	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:		if (rme32->running && RME32_ISWORKING(rme32))			snd_rme32_pcm_stop(rme32, 1);		break;	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:		if (rme32->running && ! RME32_ISWORKING(rme32))			snd_rme32_pcm_start(rme32, 1);		break;	}	spin_unlock(&rme32->lock);	return 0;}/* pointer callback for halfduplex mode */static snd_pcm_uframes_tsnd_rme32_playback_pointer(struct snd_pcm_substream *substream){	struct rme32 *rme32 = snd_pcm_substream_chip(substream);	return snd_rme32_pcm_byteptr(rme32) >> rme32->playback_frlog;}static snd_pcm_uframes_tsnd_rme32_capture_pointer(struct snd_pcm_substream *substream){	struct rme32 *rme32 = snd_pcm_substream_chip(substream);	return snd_rme32_pcm_byteptr(rme32) >> rme32->capture_frlog;}/* ack and pointer callbacks for fullduplex mode */static void snd_rme32_pb_trans_copy(struct snd_pcm_substream *substream,				    struct snd_pcm_indirect *rec, size_t bytes){	struct rme32 *rme32 = snd_pcm_substream_chip(substream);	memcpy_toio(rme32->iobase + RME32_IO_DATA_BUFFER + rec->hw_data,		    substream->runtime->dma_area + rec->sw_data, bytes);}static int snd_rme32_playback_fd_ack(struct snd_pcm_substream *substream){	struct rme32 *rme32 = snd_pcm_substream_chip(substream);	struct snd_pcm_indirect *rec, *cprec;	rec = &rme32->playback_pcm;	cprec = &rme32->capture_pcm;	spin_lock(&rme32->lock);	rec->hw_queue_size = RME32_BUFFER_SIZE;	if (rme32->running & (1 << SNDRV_PCM_STREAM_CAPTURE))		rec->hw_queue_size -= cprec->hw_ready;	spin_unlock(&rme32->lock);	snd_pcm_indirect_playback_transfer(substream, rec,					   snd_rme32_pb_trans_copy);	return 0;}static void snd_rme32_cp_trans_copy(struct snd_pcm_substream *substream,				    struct snd_pcm_indirect *rec, size_t bytes){	struct rme32 *rme32 = snd_pcm_substream_chip(substream);	memcpy_fromio(substream->runtime->dma_area + rec->sw_data,		      rme32->iobase + RME32_IO_DATA_BUFFER + rec->hw_data,		      bytes);}static int snd_rme32_capture_fd_ack(struct snd_pcm_substream *substream){	struct rme32 *rme32 = snd_pcm_substream_chip(substream);	snd_pcm_indirect_capture_transfer(substream, &rme32->capture_pcm,					  snd_rme32_cp_trans_copy);	return 0;}static snd_pcm_uframes_tsnd_rme32_playback_fd_pointer(struct snd_pcm_substream *substream){	struct rme32 *rme32 = snd_pcm_substream_chip(substream);	return snd_pcm_indirect_playback_pointer(substream, &rme32->playback_pcm,						 snd_rme32_pcm_byteptr(rme32));}static snd_pcm_uframes_tsnd_rme32_capture_fd_pointer(struct snd_pcm_substream *substream){	struct rme32 *rme32 = snd_pcm_substream_chip(substream);	return snd_pcm_indirect_capture_pointer(substream, &rme32->capture_pcm,						snd_rme32_pcm_byteptr(rme32));}/* for halfduplex mode */static struct snd_pcm_ops snd_rme32_playback_spdif_ops = {	.open =		snd_rme32_playback_spdif_open,	.close =	snd_rme32_playback_close,	.ioctl =	snd_pcm_lib_ioctl,	.hw_params =	snd_rme32_playback_hw_params,	.hw_free =	snd_rme32_pcm_hw_free,	.prepare =	snd_rme32_playback_prepare,	.trigger =	snd_rme32_pcm_trigger,	.pointer =	snd_rme32_playback_pointer,	.copy =		snd_rme32_playback_copy,	.silence =	snd_rme32_playback_silence,	.mmap =		snd_pcm_lib_mmap_iomem,};static struct snd_pcm_ops snd_rme32_capture_spdif_ops = {	.open =		snd_rme32_capture_spdif_open,	.close =	snd_rme32_capture_close,	.ioctl =	snd_pcm_lib_ioctl,	.hw_params =	snd_rme32_capture_hw_params,	.hw_free =	snd_rme32_pcm_hw_free,	.prepare =	snd_rme32_capture_prepare,	.trigger =	snd_rme32_pcm_trigger,	.pointer =	snd_rme32_capture_pointer,	.copy =		snd_rme32_capture_copy,	.mmap =		snd_pcm_lib_mmap_iomem,};static struct snd_pcm_ops snd_rme32_playback_adat_ops = {	.open =		snd_rme32_playback_adat_open,	.close =	snd_rme32_playback_close,	.ioctl =	snd_pcm_lib_ioctl,	.hw_params =	snd_rme32_playback_hw_params,	.prepare =	snd_rme32_playback_prepare,	.trigger =	snd_rme32_pcm_trigger,	.pointer =	snd_rme32_playback_pointer,	.copy =		snd_rme32_playback_copy,	.silence =	snd_rme32_playback_silence,	.mmap =		snd_pcm_lib_mmap_iomem,};static struct snd_pcm_ops snd_rme32_capture_adat_ops = {	.open =		snd_rme32_capture_adat_open,	.close =	snd_rme32_capture_close,	.ioctl =	snd_pcm_lib_ioctl,	.hw_params =	snd_rme32_capture_hw_params,	.prepare =	snd_rme32_capture_prepare,	.trigger =	snd_rme32_pcm_trigger,	.pointer =	snd_rme32_capture_pointer,	.copy =		snd_rme32_capture_copy,	.mmap =		snd_pcm_lib_mmap_iomem,};/* for fullduplex mode */static struct snd_pcm_ops snd_rme32_playback_spdif_fd_ops = {	.open =		snd_rme32_playback_spdif_open,	.close =	snd_rme32_playback_close,	.ioctl =	snd_pcm_lib_ioctl,	.hw_params =	snd_rme32_playback_hw_params,	.hw_free =	snd_rme32_pcm_hw_free,	.prepare =	snd_rme32_playback_prepare,	.trigger =	snd_rme32_pcm_trigger,	.pointer =	snd_rme32_playback_fd_pointer,	.ack =		snd_rme32_playback_fd_ack,};static struct snd_pcm_ops snd_rme32_capture_spdif_fd_ops = {	.open =		snd_rme32_capture_spdif_open,	.close =	snd_rme32_capture_close,	.ioctl =	snd_pcm_lib_ioctl,	.hw_params =	snd_rme32_capture_hw_params,	.hw_free =	snd_rme32_pcm_hw_free,	.prepare =	snd_rme32_capture_prepare,	.trigger =	snd_rme32_pcm_trigger,	.pointer =	snd_rme32_capture_fd_pointer,	.ack =		snd_rme32_capture_fd_ack,};static struct snd_pcm_ops snd_rme32_playback_adat_fd_ops = {	.open =		snd_rme32_playback_adat_open,	.close =	snd_rme32_playback_close,	.ioctl =	snd_pcm_lib_ioctl,	.hw_params =	snd_rme32_playback_hw_params,	.prepare =	snd_rme32_playback_prepare,	.trigger =	snd_rme32_pcm_trigger,	.pointer =	snd_rme32_playback_fd_pointer,	.ack =		snd_rme32_playback_fd_ack,};static struct snd_pcm_ops snd_rme32_capture_adat_fd_ops = {	.open =		snd_rme32_capture_adat_open,	.close =	snd_rme32_capture_close,	.ioctl =	snd_pcm_lib_ioctl,	.hw_params =	snd_rme32_capture_hw_params,	.prepare =	snd_rme32_capture_prepare,	.trigger =	snd_rme32_pcm_trigger,	.pointer =	snd_rme32_capture_fd_pointer,	.ack =		snd_rme32_capture_fd_ack,};static void snd_rme32_free(void *private_data){	struct rme32 *rme32 = (struct rme32 *) private_data;	if (rme32 == NULL) {		return;	}	if (rme32->irq >= 0) {		snd_rme32_pcm_stop(rme32, 0);		free_irq(rme32->irq, (void *) rme32);		rme32->irq = -1;	}	if (rme32->iobase) {		iounmap(rme32->iobase);		rme32->iobase = NULL;	}	if (rme32->port) {		pci_release_regions(rme32->pci);		rme32->port = 0;	}	pci_disable_device(rme32->pci);}static void snd_rme32_free_spdif_pcm(struct snd_pcm *pcm){	struct rme32 *rme32 = (struct rme32 *) pcm->private_data;	rme32->spdif_pcm = NULL;}static voidsnd_rme32_free_adat_pcm(struct snd_pcm *pcm){	struct rme32 *rme32 = (struct rme32 *) pcm->private_data;	rme32->adat_pcm = NULL;}static int __devinit snd_rme32_create(struct rme32 * rme32){	struct pci_dev *pci = rme32->pci;	int err;	rme32->irq = -1;	spin_lock_init(&rme32->lock);	if ((err = pci_enable_device(pci)) < 0)		return err;	if ((err = pci_request_regions(pci, "RME32")) < 0)		return err;	rme32->port = pci_resource_start(rme32->pci, 0);	if ((rme32->iobase = ioremap_nocache(rme32->port, RME32_IO_SIZE)) == 0) {		snd_printk(KERN_ERR "unable to remap memory region 0x%lx-0x%lx\n",			   rme32->port, rme32->port + RME32_IO_SIZE - 1);		return -ENOMEM;	}	if (request_irq(pci->irq, snd_rme32_interrupt, IRQF_SHARED,			"RME32", rme32)) {		snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq);		return -EBUSY;	}	rme32->irq = pci->irq;	/* read the card's revision number */	pci_read_config_byte(pci, 8, &rme32->rev);	/* set up ALSA pcm device for S/PDIF */	if ((err = snd_pcm_new(rme32->card, "Digi32 IEC958", 0, 1, 1, &rme32->spdif_pcm)) < 0) {		return err;	}	rme32->spdif_pcm->private_data = rme32;	rme32->spdif_pcm->private_free = snd_rme32_free_spdif_pcm;	strcpy(rme32->spdif_pcm->name, "Digi32 IEC958");	if (rme32->fullduplex_mode) {		snd_pcm_set_ops(rme32->spdif_pcm, SNDRV_PCM_STREAM_PLAYBACK,				&snd_rme32_playback_spdif_fd_ops);		snd_pcm_set_ops(rme32->spdif_pcm, SNDRV_PCM_STREAM_CAPTURE,				&snd_rme32_capture_spdif_fd_ops);		snd_pcm_lib_preallocate_pages_for_all(rme32->spdif_pcm, SNDRV_DMA_TYPE_CONTINUOUS,						      snd_dma_continuous_data(GFP_KERNEL),						      0, RME32_MID_BUFFER_SIZE);		rme32->spdif_pcm->info_flags = SNDRV_PCM_INFO_JOINT_DUPLEX;	} else {		snd_pcm_set_ops(rme32->spdif_pcm, SNDRV_PCM_STREAM_PLAYBACK,				&snd_rme32_playback_spdif_ops);		snd_pcm_set_ops(rme32->spdif_pcm, SNDRV_PCM_STREAM_CAPTURE,				&snd_rme32_capture_spdif_ops);		rme32->spdif_pcm->info_flags = SNDRV_PCM_INFO_HALF_DUPLEX;	}	/* set up ALSA pcm device for ADAT */	if ((pci->device == PCI_DEVICE_ID_RME_DIGI32) ||	    (pci->device == PCI_DEVICE_ID_RME_DIGI32_PRO)) {		/* ADAT is not available on DIGI32 and DIGI32 Pro */		rme32->adat_pcm = NULL;	}	else {		if ((err = snd_pcm_new(rme32->card, "Digi32 ADAT", 1,				       1, 1, &rme32->adat_pcm)) < 0)		{			return err;		}				rme32->adat_pcm->private_data = rme32;		rme32->adat_pcm->private_free = snd_rme32_free_adat_pcm;		strcpy(rme32->adat_pcm->name, "Digi32 ADAT");		if (rme32->fullduplex_mode) {			snd_pcm_set_ops(rme32->adat_pcm, SNDRV_PCM_STREAM_PLAYBACK, 					&snd_rme32_playback_adat_fd_ops);			snd_pcm_set_ops(rme32->adat_pcm, SNDRV_PCM_STREAM_CAPTURE, 					&snd_rme32_capture_adat_fd_ops);			snd_pcm_lib_preallocate_pages_for_all(rme32->adat_pcm, SNDRV_DMA_TYPE_CONTINUOUS,							      snd_dma_continuous_data(GFP_KERNEL),							      0, RME32_MID_BUFFER_SIZE);			rme32->adat_pcm->info_flags = SNDRV_PCM_INFO_JOINT_DUPLEX;		} else {			snd_pcm_set_ops(rme32->adat_pcm, SNDRV_PCM_STREAM_PLAYBACK, 					&snd_rme32_playback_adat_ops);			snd_pcm_set_ops(rme32->adat_pcm, SNDRV_PCM_STREAM_CAPTURE, 					&snd_rme32_capture_adat_ops);			rme32->adat_pcm->info_flags = SNDRV_PCM_INFO_HALF_DUPLEX;		}	}	rme32->playback_periodsize = 0;	rme32->capture_periodsize = 0;	/* make sure playback/capture is stopped, if by some reason active */	snd_rme32_pcm_stop(rme32, 0);        /* reset DAC */        snd_rme32_reset_dac(rme32);	/* reset buffer pointer */	writel(0, rme32->iobase + RME32_IO_RESET_POS);	/* set default values in registers */	rme32->wcreg = RME32_WCR_SEL |	 /* normal playback */		RME32_WCR_INP_0 | /* input select */		RME32_WCR_MUTE;	 /* muting on */	writel(rme32->wcreg, rme32->iobase + RME32_IO_CONTROL_REGISTER);	/* init switch interface */	if ((err = snd_rme32_create_switches(rme32->card, rme32)) < 0) {		return err;	}	/* init proc interface */	snd_rme32_proc_init(rme32);	rme32->capture_substream = NULL;	rme32->playback_substream = NULL;	return 0;}/* * proc interface */static voidsnd_rme32_proc_read(struct snd_info_entry * entry, struct snd_info_buffer *buffer){	int n;	struct rme32 *rme32 = (struct rme32 *) entry->private_data;	rme32->rcreg = readl(rme32->iobase + RME32_IO_CONTROL_REGISTER);	snd_iprintf(buffer, rme32->card->longname);	snd_iprintf(buffer, " (index #%d)\n", rme32->card->number + 1);	snd_iprintf(buffer, "\nGeneral settings\n");	if (rme32->fullduplex_mode)		snd_iprintf(buffer, "  Full-duplex mode\n");	else		snd_iprintf(buffer, "  Half-duplex mode\n");	if (RME32_PRO_WITH_8414(rme32)) {		snd_iprintf(buffer, "  receiver: CS8414\n");	} else {		snd_iprintf(buffer, "  receiver: CS8412\n");	}	if (rme32->wcreg & RME32_WCR_MODE24) {		snd_iprintf(buffer, "  format: 24 bit");	} else {		snd_iprintf(buffer, "  format: 16 bit");	}	if (rme32->wcreg & RME32_WCR_MONO) {		snd_iprintf(buffer, ", Mono\n");	} else {		snd_iprintf(buffer, ", Stereo\n");	}	snd_iprintf(buffer, "\nInput settings\n");	switch (snd_rme32_getinputtype(rme32)) {	case RME32_INPUT_OPTICAL:		snd_iprintf(buffer, "  input: optical");		break;	case RME32_INPUT_COAXIAL:		snd_iprintf(buffer, "  input: coaxial");		break;	case RME32_INPUT_INTERNAL:		snd_iprintf(buffer, "  input: internal");

⌨️ 快捷键说明

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