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

📄 rme96.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
		break;	case SNDRV_PCM_FORMAT_S32_LE:		rme96->wcreg |= RME96_WCR_MODE24_2;		break;	default:		return -EINVAL;	}	writel(rme96->wcreg, rme96->iobase + RME96_IO_CONTROL_REGISTER);	return 0;}static voidsnd_rme96_set_period_properties(struct rme96 *rme96,				size_t period_bytes){	switch (period_bytes) {	case RME96_LARGE_BLOCK_SIZE:		rme96->wcreg &= ~RME96_WCR_ISEL;		break;	case RME96_SMALL_BLOCK_SIZE:		rme96->wcreg |= RME96_WCR_ISEL;		break;	default:		snd_BUG();		break;	}	rme96->wcreg &= ~RME96_WCR_IDIS;	writel(rme96->wcreg, rme96->iobase + RME96_IO_CONTROL_REGISTER);}static intsnd_rme96_playback_hw_params(struct snd_pcm_substream *substream,			     struct snd_pcm_hw_params *params){	struct rme96 *rme96 = snd_pcm_substream_chip(substream);	struct snd_pcm_runtime *runtime = substream->runtime;	int err, rate, dummy;	runtime->dma_area = (void __force *)(rme96->iobase +					     RME96_IO_PLAY_BUFFER);	runtime->dma_addr = rme96->port + RME96_IO_PLAY_BUFFER;	runtime->dma_bytes = RME96_BUFFER_SIZE;	spin_lock_irq(&rme96->lock);	if (!(rme96->wcreg & RME96_WCR_MASTER) &&            snd_rme96_getinputtype(rme96) != RME96_INPUT_ANALOG &&	    (rate = snd_rme96_capture_getrate(rme96, &dummy)) > 0)	{                /* slave clock */                if ((int)params_rate(params) != rate) {			spin_unlock_irq(&rme96->lock);			return -EIO;                                    }	} else if ((err = snd_rme96_playback_setrate(rme96, params_rate(params))) < 0) {		spin_unlock_irq(&rme96->lock);		return err;	}	if ((err = snd_rme96_playback_setformat(rme96, params_format(params))) < 0) {		spin_unlock_irq(&rme96->lock);		return err;	}	snd_rme96_setframelog(rme96, params_channels(params), 1);	if (rme96->capture_periodsize != 0) {		if (params_period_size(params) << rme96->playback_frlog !=		    rme96->capture_periodsize)		{			spin_unlock_irq(&rme96->lock);			return -EBUSY;		}	}	rme96->playback_periodsize =		params_period_size(params) << rme96->playback_frlog;	snd_rme96_set_period_properties(rme96, rme96->playback_periodsize);	/* S/PDIF setup */	if ((rme96->wcreg & RME96_WCR_ADAT) == 0) {		rme96->wcreg &= ~(RME96_WCR_PRO | RME96_WCR_DOLBY | RME96_WCR_EMP);		writel(rme96->wcreg |= rme96->wcreg_spdif_stream, rme96->iobase + RME96_IO_CONTROL_REGISTER);	}	spin_unlock_irq(&rme96->lock);			return 0;}static intsnd_rme96_capture_hw_params(struct snd_pcm_substream *substream,			    struct snd_pcm_hw_params *params){	struct rme96 *rme96 = snd_pcm_substream_chip(substream);	struct snd_pcm_runtime *runtime = substream->runtime;	int err, isadat, rate;		runtime->dma_area = (void __force *)(rme96->iobase +					     RME96_IO_REC_BUFFER);	runtime->dma_addr = rme96->port + RME96_IO_REC_BUFFER;	runtime->dma_bytes = RME96_BUFFER_SIZE;	spin_lock_irq(&rme96->lock);	if ((err = snd_rme96_capture_setformat(rme96, params_format(params))) < 0) {		spin_unlock_irq(&rme96->lock);		return err;	}	if (snd_rme96_getinputtype(rme96) == RME96_INPUT_ANALOG) {		if ((err = snd_rme96_capture_analog_setrate(rme96,							    params_rate(params))) < 0)		{			spin_unlock_irq(&rme96->lock);			return err;		}	} else if ((rate = snd_rme96_capture_getrate(rme96, &isadat)) > 0) {                if ((int)params_rate(params) != rate) {			spin_unlock_irq(&rme96->lock);			return -EIO;                                    }                if ((isadat && runtime->hw.channels_min == 2) ||                    (!isadat && runtime->hw.channels_min == 8))                {			spin_unlock_irq(&rme96->lock);			return -EIO;                }        }	snd_rme96_setframelog(rme96, params_channels(params), 0);	if (rme96->playback_periodsize != 0) {		if (params_period_size(params) << rme96->capture_frlog !=		    rme96->playback_periodsize)		{			spin_unlock_irq(&rme96->lock);			return -EBUSY;		}	}	rme96->capture_periodsize =		params_period_size(params) << rme96->capture_frlog;	snd_rme96_set_period_properties(rme96, rme96->capture_periodsize);	spin_unlock_irq(&rme96->lock);	return 0;}static voidsnd_rme96_playback_start(struct rme96 *rme96,			 int from_pause){	if (!from_pause) {		writel(0, rme96->iobase + RME96_IO_RESET_PLAY_POS);	}	rme96->wcreg |= RME96_WCR_START;	writel(rme96->wcreg, rme96->iobase + RME96_IO_CONTROL_REGISTER);}static voidsnd_rme96_capture_start(struct rme96 *rme96,			int from_pause){	if (!from_pause) {		writel(0, rme96->iobase + RME96_IO_RESET_REC_POS);	}	rme96->wcreg |= RME96_WCR_START_2;	writel(rme96->wcreg, rme96->iobase + RME96_IO_CONTROL_REGISTER);}static voidsnd_rme96_playback_stop(struct rme96 *rme96){	/*	 * Check if there is an unconfirmed IRQ, if so confirm it, or else	 * the hardware will not stop generating interrupts	 */	rme96->rcreg = readl(rme96->iobase + RME96_IO_CONTROL_REGISTER);	if (rme96->rcreg & RME96_RCR_IRQ) {		writel(0, rme96->iobase + RME96_IO_CONFIRM_PLAY_IRQ);	}		rme96->wcreg &= ~RME96_WCR_START;	writel(rme96->wcreg, rme96->iobase + RME96_IO_CONTROL_REGISTER);}static voidsnd_rme96_capture_stop(struct rme96 *rme96){	rme96->rcreg = readl(rme96->iobase + RME96_IO_CONTROL_REGISTER);	if (rme96->rcreg & RME96_RCR_IRQ_2) {		writel(0, rme96->iobase + RME96_IO_CONFIRM_REC_IRQ);	}		rme96->wcreg &= ~RME96_WCR_START_2;	writel(rme96->wcreg, rme96->iobase + RME96_IO_CONTROL_REGISTER);}static irqreturn_tsnd_rme96_interrupt(int irq,		    void *dev_id){	struct rme96 *rme96 = (struct rme96 *)dev_id;	rme96->rcreg = readl(rme96->iobase + RME96_IO_CONTROL_REGISTER);	/* fastpath out, to ease interrupt sharing */	if (!((rme96->rcreg & RME96_RCR_IRQ) ||	      (rme96->rcreg & RME96_RCR_IRQ_2)))	{		return IRQ_NONE;	}		if (rme96->rcreg & RME96_RCR_IRQ) {		/* playback */                snd_pcm_period_elapsed(rme96->playback_substream);		writel(0, rme96->iobase + RME96_IO_CONFIRM_PLAY_IRQ);	}	if (rme96->rcreg & RME96_RCR_IRQ_2) {		/* capture */		snd_pcm_period_elapsed(rme96->capture_substream);				writel(0, rme96->iobase + RME96_IO_CONFIRM_REC_IRQ);	}	return IRQ_HANDLED;}static unsigned int period_bytes[] = { RME96_SMALL_BLOCK_SIZE, RME96_LARGE_BLOCK_SIZE };static struct snd_pcm_hw_constraint_list hw_constraints_period_bytes = {	.count = ARRAY_SIZE(period_bytes),	.list = period_bytes,	.mask = 0};static voidrme96_set_buffer_size_constraint(struct rme96 *rme96,				 struct snd_pcm_runtime *runtime){	unsigned int size;	snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_BYTES,				     RME96_BUFFER_SIZE, RME96_BUFFER_SIZE);	if ((size = rme96->playback_periodsize) != 0 ||	    (size = rme96->capture_periodsize) != 0)		snd_pcm_hw_constraint_minmax(runtime,					     SNDRV_PCM_HW_PARAM_PERIOD_BYTES,					     size, size);	else		snd_pcm_hw_constraint_list(runtime, 0,					   SNDRV_PCM_HW_PARAM_PERIOD_BYTES,					   &hw_constraints_period_bytes);}static intsnd_rme96_playback_spdif_open(struct snd_pcm_substream *substream){        int rate, dummy;	struct rme96 *rme96 = snd_pcm_substream_chip(substream);	struct snd_pcm_runtime *runtime = substream->runtime;	spin_lock_irq(&rme96->lock);	        if (rme96->playback_substream != NULL) {		spin_unlock_irq(&rme96->lock);                return -EBUSY;        }	rme96->wcreg &= ~RME96_WCR_ADAT;	writel(rme96->wcreg, rme96->iobase + RME96_IO_CONTROL_REGISTER);	rme96->playback_substream = substream;	spin_unlock_irq(&rme96->lock);	runtime->hw = snd_rme96_playback_spdif_info;	if (!(rme96->wcreg & RME96_WCR_MASTER) &&            snd_rme96_getinputtype(rme96) != RME96_INPUT_ANALOG &&	    (rate = snd_rme96_capture_getrate(rme96, &dummy)) > 0)	{                /* slave clock */                runtime->hw.rates = snd_pcm_rate_to_rate_bit(rate);                runtime->hw.rate_min = rate;                runtime->hw.rate_max = rate;	}        	rme96_set_buffer_size_constraint(rme96, runtime);	rme96->wcreg_spdif_stream = rme96->wcreg_spdif;	rme96->spdif_ctl->vd[0].access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE;	snd_ctl_notify(rme96->card, SNDRV_CTL_EVENT_MASK_VALUE |		       SNDRV_CTL_EVENT_MASK_INFO, &rme96->spdif_ctl->id);	return 0;}static intsnd_rme96_capture_spdif_open(struct snd_pcm_substream *substream){        int isadat, rate;	struct rme96 *rme96 = snd_pcm_substream_chip(substream);	struct snd_pcm_runtime *runtime = substream->runtime;	runtime->hw = snd_rme96_capture_spdif_info;        if (snd_rme96_getinputtype(rme96) != RME96_INPUT_ANALOG &&            (rate = snd_rme96_capture_getrate(rme96, &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;        }        	spin_lock_irq(&rme96->lock);        if (rme96->capture_substream != NULL) {		spin_unlock_irq(&rme96->lock);                return -EBUSY;        }	rme96->capture_substream = substream;	spin_unlock_irq(&rme96->lock);		rme96_set_buffer_size_constraint(rme96, runtime);	return 0;}static intsnd_rme96_playback_adat_open(struct snd_pcm_substream *substream){        int rate, dummy;	struct rme96 *rme96 = snd_pcm_substream_chip(substream);	struct snd_pcm_runtime *runtime = substream->runtime;        		spin_lock_irq(&rme96->lock);	        if (rme96->playback_substream != NULL) {		spin_unlock_irq(&rme96->lock);                return -EBUSY;        }	rme96->wcreg |= RME96_WCR_ADAT;	writel(rme96->wcreg, rme96->iobase + RME96_IO_CONTROL_REGISTER);	rme96->playback_substream = substream;	spin_unlock_irq(&rme96->lock);		runtime->hw = snd_rme96_playback_adat_info;	if (!(rme96->wcreg & RME96_WCR_MASTER) &&            snd_rme96_getinputtype(rme96) != RME96_INPUT_ANALOG &&	    (rate = snd_rme96_capture_getrate(rme96, &dummy)) > 0)	{                /* slave clock */                runtime->hw.rates = snd_pcm_rate_to_rate_bit(rate);                runtime->hw.rate_min = rate;                runtime->hw.rate_max = rate;	}        	rme96_set_buffer_size_constraint(rme96, runtime);	return 0;}static intsnd_rme96_capture_adat_open(struct snd_pcm_substream *substream){        int isadat, rate;	struct rme96 *rme96 = snd_pcm_substream_chip(substream);	struct snd_pcm_runtime *runtime = substream->runtime;	runtime->hw = snd_rme96_capture_adat_info;        if (snd_rme96_getinputtype(rme96) == RME96_INPUT_ANALOG) {                /* makes no sense to use analog input. Note that analog                   expension cards AEB4/8-I are RME96_INPUT_INTERNAL */                return -EIO;        }        if ((rate = snd_rme96_capture_getrate(rme96, &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;        }        	spin_lock_irq(&rme96->lock);	        if (rme96->capture_substream != NULL) {		spin_unlock_irq(&rme96->lock);                return -EBUSY;        }	rme96->capture_substream = substream;	spin_unlock_irq(&rme96->lock);	rme96_set_buffer_size_constraint(rme96, runtime);	return 0;}static intsnd_rme96_playback_close(struct snd_pcm_substream *substream){	struct rme96 *rme96 = snd_pcm_substream_chip(substream);	int spdif = 0;	spin_lock_irq(&rme96->lock);		if (RME96_ISPLAYING(rme96)) {		snd_rme96_playback_stop(rme96);	}	rme96->playback_substream = NULL;	rme96->playback_periodsize = 0;	spdif = (rme96->wcreg & RME96_WCR_ADAT) == 0;	spin_unlock_irq(&rme96->lock);	if (spdif) {		rme96->spdif_ctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE;		snd_ctl_notify(rme96->card, SNDRV_CTL_EVENT_MASK_VALUE |			       SNDRV_CTL_EVENT_MASK_INFO, &rme96->spdif_ctl->id);	}	return 0;}static intsnd_rme96_capture_close(struct snd_pcm_substream *substream){	struct rme96 *rme96 = snd_pcm_substream_chip(substream);		spin_lock_irq(&rme96->lock);		if (RME96_ISRECORDING(rme96)) {		snd_rme96_capture_stop(rme96);	}	rme96->capture_substream = NULL;	rme96->capture_periodsize = 0;	spin_unlock_irq(&rme96->lock);	return 0;}static intsnd_rme96_playback_prepare(struct snd_pcm_substream *substream){	struct rme96 *rme96 = snd_pcm_substream_chip(substream);		spin_lock_irq(&rme96->lock);		if (RME96_ISPLAYING(rme96)) {		snd_rme96_playback_stop(rme96);	}	writel(0, rme96->iobase + RME96_IO_RESET_PLAY_POS);	spin_unlock_irq(&rme96->lock);	return 0;}static intsnd_rme96_capture_prepare(struct snd_pcm_substream *substream){	struct rme96 *rme96 = snd_pcm_substream_chip(substream);		spin_lock_irq(&rme96->lock);		if (RME96_ISRECORDING(rme96)) {		snd_rme96_capture_stop(rme96);	}	writel(0, rme96->iobase + RME96_IO_RESET_REC_POS);	spin_unlock_irq(&rme96->lock);	return 0;}static intsnd_rme96_playback_trigger(struct snd_pcm_substream *substream, 			   int cmd){	struct rme96 *rme96 = snd_pcm_substream_chip(substream);	switch (cmd) {	case SNDRV_PCM_TRIGGER_START:		if (!RME96_ISPLAYING(rme96)) {			if (substream != rme96->playback_substream) {				return -EBUSY;			}			snd_rme96_playback_start(rme96, 0);		}		break;	case SNDRV_PCM_TRIGGER_STOP:		if (RME96_ISPLAYING(rme96)) {			if (substream != rme96->playback_substream) {				return -EBUSY;

⌨️ 快捷键说明

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