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

📄 rme32.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
		rme32->wcreg = (rme32->wcreg | RME32_WCR_FREQ_0) & 			~RME32_WCR_FREQ_1;		break;	case 44100:		rme32->wcreg &= ~RME32_WCR_DS_BM;		rme32->wcreg = (rme32->wcreg | RME32_WCR_FREQ_1) & 			~RME32_WCR_FREQ_0;		break;	case 48000:		rme32->wcreg &= ~RME32_WCR_DS_BM;		rme32->wcreg = (rme32->wcreg | RME32_WCR_FREQ_0) | 			RME32_WCR_FREQ_1;		break;	case 64000:		if (rme32->pci->device != PCI_DEVICE_ID_RME_DIGI32_PRO)			return -EINVAL;		rme32->wcreg |= RME32_WCR_DS_BM;		rme32->wcreg = (rme32->wcreg | RME32_WCR_FREQ_0) & 			~RME32_WCR_FREQ_1;		break;	case 88200:		if (rme32->pci->device != PCI_DEVICE_ID_RME_DIGI32_PRO)			return -EINVAL;		rme32->wcreg |= RME32_WCR_DS_BM;		rme32->wcreg = (rme32->wcreg | RME32_WCR_FREQ_1) & 			~RME32_WCR_FREQ_0;		break;	case 96000:		if (rme32->pci->device != PCI_DEVICE_ID_RME_DIGI32_PRO)			return -EINVAL;		rme32->wcreg |= RME32_WCR_DS_BM;		rme32->wcreg = (rme32->wcreg | RME32_WCR_FREQ_0) | 			RME32_WCR_FREQ_1;		break;	default:		return -EINVAL;	}        if ((!ds && rme32->wcreg & RME32_WCR_DS_BM) ||            (ds && !(rme32->wcreg & RME32_WCR_DS_BM)))        {                /* change to/from double-speed: reset the DAC (if available) */                snd_rme32_reset_dac(rme32);        } else {                writel(rme32->wcreg, rme32->iobase + RME32_IO_CONTROL_REGISTER);	}	return 0;}static int snd_rme32_setclockmode(struct rme32 * rme32, int mode){	switch (mode) {	case RME32_CLOCKMODE_SLAVE:		/* AutoSync */		rme32->wcreg = (rme32->wcreg & ~RME32_WCR_FREQ_0) & 			~RME32_WCR_FREQ_1;		break;	case RME32_CLOCKMODE_MASTER_32:		/* Internal 32.0kHz */		rme32->wcreg = (rme32->wcreg | RME32_WCR_FREQ_0) & 			~RME32_WCR_FREQ_1;		break;	case RME32_CLOCKMODE_MASTER_44:		/* Internal 44.1kHz */		rme32->wcreg = (rme32->wcreg & ~RME32_WCR_FREQ_0) | 			RME32_WCR_FREQ_1;		break;	case RME32_CLOCKMODE_MASTER_48:		/* Internal 48.0kHz */		rme32->wcreg = (rme32->wcreg | RME32_WCR_FREQ_0) | 			RME32_WCR_FREQ_1;		break;	default:		return -EINVAL;	}	writel(rme32->wcreg, rme32->iobase + RME32_IO_CONTROL_REGISTER);	return 0;}static int snd_rme32_getclockmode(struct rme32 * rme32){	return ((rme32->wcreg >> RME32_WCR_BITPOS_FREQ_0) & 1) +	    (((rme32->wcreg >> RME32_WCR_BITPOS_FREQ_1) & 1) << 1);}static int snd_rme32_setinputtype(struct rme32 * rme32, int type){	switch (type) {	case RME32_INPUT_OPTICAL:		rme32->wcreg = (rme32->wcreg & ~RME32_WCR_INP_0) & 			~RME32_WCR_INP_1;		break;	case RME32_INPUT_COAXIAL:		rme32->wcreg = (rme32->wcreg | RME32_WCR_INP_0) & 			~RME32_WCR_INP_1;		break;	case RME32_INPUT_INTERNAL:		rme32->wcreg = (rme32->wcreg & ~RME32_WCR_INP_0) | 			RME32_WCR_INP_1;		break;	case RME32_INPUT_XLR:		rme32->wcreg = (rme32->wcreg | RME32_WCR_INP_0) | 			RME32_WCR_INP_1;		break;	default:		return -EINVAL;	}	writel(rme32->wcreg, rme32->iobase + RME32_IO_CONTROL_REGISTER);	return 0;}static int snd_rme32_getinputtype(struct rme32 * rme32){	return ((rme32->wcreg >> RME32_WCR_BITPOS_INP_0) & 1) +	    (((rme32->wcreg >> RME32_WCR_BITPOS_INP_1) & 1) << 1);}static voidsnd_rme32_setframelog(struct rme32 * rme32, int n_channels, int is_playback){	int frlog;	if (n_channels == 2) {		frlog = 1;	} else {		/* assume 8 channels */		frlog = 3;	}	if (is_playback) {		frlog += (rme32->wcreg & RME32_WCR_MODE24) ? 2 : 1;		rme32->playback_frlog = frlog;	} else {		frlog += (rme32->wcreg & RME32_WCR_MODE24) ? 2 : 1;		rme32->capture_frlog = frlog;	}}static int snd_rme32_setformat(struct rme32 * rme32, int format){	switch (format) {	case SNDRV_PCM_FORMAT_S16_LE:		rme32->wcreg &= ~RME32_WCR_MODE24;		break;	case SNDRV_PCM_FORMAT_S32_LE:		rme32->wcreg |= RME32_WCR_MODE24;		break;	default:		return -EINVAL;	}	writel(rme32->wcreg, rme32->iobase + RME32_IO_CONTROL_REGISTER);	return 0;}static intsnd_rme32_playback_hw_params(struct snd_pcm_substream *substream,			     struct snd_pcm_hw_params *params){	int err, rate, dummy;	struct rme32 *rme32 = snd_pcm_substream_chip(substream);	struct snd_pcm_runtime *runtime = substream->runtime;	if (rme32->fullduplex_mode) {		err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params));		if (err < 0)			return err;	} else {		runtime->dma_area = (void __force *)(rme32->iobase +						     RME32_IO_DATA_BUFFER);		runtime->dma_addr = rme32->port + RME32_IO_DATA_BUFFER;		runtime->dma_bytes = RME32_BUFFER_SIZE;	}	spin_lock_irq(&rme32->lock);	if ((rme32->rcreg & RME32_RCR_KMODE) &&	    (rate = snd_rme32_capture_getrate(rme32, &dummy)) > 0) {		/* AutoSync */		if ((int)params_rate(params) != rate) {			spin_unlock_irq(&rme32->lock);			return -EIO;		}	} else if ((err = snd_rme32_playback_setrate(rme32, params_rate(params))) < 0) {		spin_unlock_irq(&rme32->lock);		return err;	}	if ((err = snd_rme32_setformat(rme32, params_format(params))) < 0) {		spin_unlock_irq(&rme32->lock);		return err;	}	snd_rme32_setframelog(rme32, params_channels(params), 1);	if (rme32->capture_periodsize != 0) {		if (params_period_size(params) << rme32->playback_frlog != rme32->capture_periodsize) {			spin_unlock_irq(&rme32->lock);			return -EBUSY;		}	}	rme32->playback_periodsize = params_period_size(params) << rme32->playback_frlog;	/* S/PDIF setup */	if ((rme32->wcreg & RME32_WCR_ADAT) == 0) {		rme32->wcreg &= ~(RME32_WCR_PRO | RME32_WCR_EMP);		rme32->wcreg |= rme32->wcreg_spdif_stream;		writel(rme32->wcreg, rme32->iobase + RME32_IO_CONTROL_REGISTER);	}	spin_unlock_irq(&rme32->lock);	return 0;}static intsnd_rme32_capture_hw_params(struct snd_pcm_substream *substream,			    struct snd_pcm_hw_params *params){	int err, isadat, rate;	struct rme32 *rme32 = snd_pcm_substream_chip(substream);	struct snd_pcm_runtime *runtime = substream->runtime;	if (rme32->fullduplex_mode) {		err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params));		if (err < 0)			return err;	} else {		runtime->dma_area = (void __force *)rme32->iobase +					RME32_IO_DATA_BUFFER;		runtime->dma_addr = rme32->port + RME32_IO_DATA_BUFFER;		runtime->dma_bytes = RME32_BUFFER_SIZE;	}	spin_lock_irq(&rme32->lock);	/* enable AutoSync for record-preparing */	rme32->wcreg |= RME32_WCR_AUTOSYNC;	writel(rme32->wcreg, rme32->iobase + RME32_IO_CONTROL_REGISTER);	if ((err = snd_rme32_setformat(rme32, params_format(params))) < 0) {		spin_unlock_irq(&rme32->lock);		return err;	}	if ((err = snd_rme32_playback_setrate(rme32, params_rate(params))) < 0) {		spin_unlock_irq(&rme32->lock);		return err;	}	if ((rate = snd_rme32_capture_getrate(rme32, &isadat)) > 0) {                if ((int)params_rate(params) != rate) {			spin_unlock_irq(&rme32->lock);                        return -EIO;                                    }                if ((isadat && runtime->hw.channels_min == 2) ||                    (!isadat && runtime->hw.channels_min == 8)) {			spin_unlock_irq(&rme32->lock);                        return -EIO;                }	}	/* AutoSync off for recording */	rme32->wcreg &= ~RME32_WCR_AUTOSYNC;	writel(rme32->wcreg, rme32->iobase + RME32_IO_CONTROL_REGISTER);	snd_rme32_setframelog(rme32, params_channels(params), 0);	if (rme32->playback_periodsize != 0) {		if (params_period_size(params) << rme32->capture_frlog !=		    rme32->playback_periodsize) {			spin_unlock_irq(&rme32->lock);			return -EBUSY;		}	}	rme32->capture_periodsize =	    params_period_size(params) << rme32->capture_frlog;	spin_unlock_irq(&rme32->lock);	return 0;}static int snd_rme32_pcm_hw_free(struct snd_pcm_substream *substream){	struct rme32 *rme32 = snd_pcm_substream_chip(substream);	if (! rme32->fullduplex_mode)		return 0;	return snd_pcm_lib_free_pages(substream);}static void snd_rme32_pcm_start(struct rme32 * rme32, int from_pause){	if (!from_pause) {		writel(0, rme32->iobase + RME32_IO_RESET_POS);	}	rme32->wcreg |= RME32_WCR_START;	writel(rme32->wcreg, rme32->iobase + RME32_IO_CONTROL_REGISTER);}static void snd_rme32_pcm_stop(struct rme32 * rme32, int to_pause){	/*	 * Check if there is an unconfirmed IRQ, if so confirm it, or else	 * the hardware will not stop generating interrupts	 */	rme32->rcreg = readl(rme32->iobase + RME32_IO_CONTROL_REGISTER);	if (rme32->rcreg & RME32_RCR_IRQ) {		writel(0, rme32->iobase + RME32_IO_CONFIRM_ACTION_IRQ);	}	rme32->wcreg &= ~RME32_WCR_START;	if (rme32->wcreg & RME32_WCR_SEL)		rme32->wcreg |= RME32_WCR_MUTE;	writel(rme32->wcreg, rme32->iobase + RME32_IO_CONTROL_REGISTER);	if (! to_pause)		writel(0, rme32->iobase + RME32_IO_RESET_POS);}static irqreturn_t snd_rme32_interrupt(int irq, void *dev_id){	struct rme32 *rme32 = (struct rme32 *) dev_id;	rme32->rcreg = readl(rme32->iobase + RME32_IO_CONTROL_REGISTER);	if (!(rme32->rcreg & RME32_RCR_IRQ)) {		return IRQ_NONE;	} else {		if (rme32->capture_substream) {			snd_pcm_period_elapsed(rme32->capture_substream);		}		if (rme32->playback_substream) {			snd_pcm_period_elapsed(rme32->playback_substream);		}		writel(0, rme32->iobase + RME32_IO_CONFIRM_ACTION_IRQ);	}	return IRQ_HANDLED;}static unsigned int period_bytes[] = { RME32_BLOCK_SIZE };static struct snd_pcm_hw_constraint_list hw_constraints_period_bytes = {	.count = ARRAY_SIZE(period_bytes),	.list = period_bytes,	.mask = 0};static void snd_rme32_set_buffer_constraint(struct rme32 *rme32, struct snd_pcm_runtime *runtime){	if (! rme32->fullduplex_mode) {		snd_pcm_hw_constraint_minmax(runtime,					     SNDRV_PCM_HW_PARAM_BUFFER_BYTES,					     RME32_BUFFER_SIZE, RME32_BUFFER_SIZE);		snd_pcm_hw_constraint_list(runtime, 0,					   SNDRV_PCM_HW_PARAM_PERIOD_BYTES,					   &hw_constraints_period_bytes);	}}static int snd_rme32_playback_spdif_open(struct snd_pcm_substream *substream){	int rate, dummy;	struct rme32 *rme32 = snd_pcm_substream_chip(substream);	struct snd_pcm_runtime *runtime = substream->runtime;	snd_pcm_set_sync(substream);	spin_lock_irq(&rme32->lock);	if (rme32->playback_substream != NULL) {		spin_unlock_irq(&rme32->lock);		return -EBUSY;	}	rme32->wcreg &= ~RME32_WCR_ADAT;	writel(rme32->wcreg, rme32->iobase + RME32_IO_CONTROL_REGISTER);	rme32->playback_substream = substream;	spin_unlock_irq(&rme32->lock);	if (rme32->fullduplex_mode)		runtime->hw = snd_rme32_spdif_fd_info;	else		runtime->hw = snd_rme32_spdif_info;	if (rme32->pci->device == PCI_DEVICE_ID_RME_DIGI32_PRO) {		runtime->hw.rates |= SNDRV_PCM_RATE_64000 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000;		runtime->hw.rate_max = 96000;	}	if ((rme32->rcreg & RME32_RCR_KMODE) &&	    (rate = snd_rme32_capture_getrate(rme32, &dummy)) > 0) {		/* AutoSync */		runtime->hw.rates = snd_pcm_rate_to_rate_bit(rate);		runtime->hw.rate_min = rate;		runtime->hw.rate_max = rate;	}       	snd_rme32_set_buffer_constraint(rme32, runtime);	rme32->wcreg_spdif_stream = rme32->wcreg_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_spdif_open(struct snd_pcm_substream *substream){	int isadat, rate;	struct rme32 *rme32 = snd_pcm_substream_chip(substream);	struct snd_pcm_runtime *runtime = substream->runtime;	snd_pcm_set_sync(substream);	spin_lock_irq(&rme32->lock);        if (rme32->capture_substream != NULL) {		spin_unlock_irq(&rme32->lock);                return -EBUSY;        }	rme32->capture_substream = substream;	spin_unlock_irq(&rme32->lock);	if (rme32->fullduplex_mode)		runtime->hw = snd_rme32_spdif_fd_info;	else		runtime->hw = snd_rme32_spdif_info;	if (RME32_PRO_WITH_8414(rme32)) {		runtime->hw.rates |= SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000;		runtime->hw.rate_max = 96000;	}	if ((rate = snd_rme32_capture_getrate(rme32, &isadat)) > 0) {		if (isadat) {			return -EIO;		}		runtime->hw.rates = snd_pcm_rate_to_rate_bit(rate);		runtime->hw.rate_min = rate;		runtime->hw.rate_max = rate;	}	snd_rme32_set_buffer_constraint(rme32, runtime);	return 0;}static intsnd_rme32_playback_adat_open(struct snd_pcm_substream *substream){	int rate, dummy;	struct rme32 *rme32 = snd_pcm_substream_chip(substream);	struct snd_pcm_runtime *runtime = substream->runtime;		snd_pcm_set_sync(substream);	spin_lock_irq(&rme32->lock);	        if (rme32->playback_substream != NULL) {		spin_unlock_irq(&rme32->lock);                return -EBUSY;        }	rme32->wcreg |= RME32_WCR_ADAT;	writel(rme32->wcreg, rme32->iobase + RME32_IO_CONTROL_REGISTER);	rme32->playback_substream = substream;	spin_unlock_irq(&rme32->lock);		if (rme32->fullduplex_mode)		runtime->hw = snd_rme32_adat_fd_info;	else		runtime->hw = snd_rme32_adat_info;	if ((rme32->rcreg & RME32_RCR_KMODE) &&	    (rate = snd_rme32_capture_getrate(rme32, &dummy)) > 0) {                /* AutoSync */                runtime->hw.rates = snd_pcm_rate_to_rate_bit(rate);                runtime->hw.rate_min = rate;                runtime->hw.rate_max = rate;	}        	snd_rme32_set_buffer_constraint(rme32, runtime);	return 0;}static intsnd_rme32_capture_adat_open(struct snd_pcm_substream *substream){	int isadat, rate;	struct rme32 *rme32 = snd_pcm_substream_chip(substream);	struct snd_pcm_runtime *runtime = substream->runtime;	if (rme32->fullduplex_mode)		runtime->hw = snd_rme32_adat_fd_info;	else		runtime->hw = snd_rme32_adat_info;	if ((rate = snd_rme32_capture_getrate(rme32, &isadat)) > 0) {		if (!isadat) {			return -EIO;		}                runtime->hw.rates = snd_pcm_rate_to_rate_bit(rate);                runtime->hw.rate_min = rate;                runtime->hw.rate_max = rate;        }	snd_pcm_set_sync(substream);        	spin_lock_irq(&rme32->lock);		if (rme32->capture_substream != NULL) {		spin_unlock_irq(&rme32->lock);		return -EBUSY;        }	rme32->capture_substream = substream;	spin_unlock_irq(&rme32->lock);	snd_rme32_set_buffer_constraint(rme32, runtime);	return 0;}static int snd_rme32_playback_close(struct snd_pcm_substream *substream){	struct rme32 *rme32 = snd_pcm_substream_chip(substream);	int spdif = 0;	spin_lock_irq(&rme32->lock);	rme32->playback_substream = NULL;

⌨️ 快捷键说明

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