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

📄 rme96.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
 * edge of CLATCH after the last data bit clocks in the whole data word. * A fast processor could probably drive the SPI interface faster than the * DAC can handle (3MHz for the 1855, unknown for the 1852).  The udelay(1) * limits the data rate to 500KHz and only causes a delay of 33 microsecs. * * NOTE: increased delay from 1 to 10, since there where problems setting * the volume. */static voidsnd_rme96_write_SPI(struct rme96 *rme96, u16 val){	int i;	for (i = 0; i < 16; i++) {		if (val & 0x8000) {			rme96->areg |= RME96_AR_CDATA;		} else {			rme96->areg &= ~RME96_AR_CDATA;		}		rme96->areg &= ~(RME96_AR_CCLK | RME96_AR_CLATCH);		writel(rme96->areg, rme96->iobase + RME96_IO_ADDITIONAL_REG);		udelay(10);		rme96->areg |= RME96_AR_CCLK;		writel(rme96->areg, rme96->iobase + RME96_IO_ADDITIONAL_REG);		udelay(10);		val <<= 1;	}	rme96->areg &= ~(RME96_AR_CCLK | RME96_AR_CDATA);	rme96->areg |= RME96_AR_CLATCH;	writel(rme96->areg, rme96->iobase + RME96_IO_ADDITIONAL_REG);	udelay(10);	rme96->areg &= ~RME96_AR_CLATCH;	writel(rme96->areg, rme96->iobase + RME96_IO_ADDITIONAL_REG);}static voidsnd_rme96_apply_dac_volume(struct rme96 *rme96){	if (RME96_DAC_IS_1852(rme96)) {		snd_rme96_write_SPI(rme96, (rme96->vol[0] << 2) | 0x0);		snd_rme96_write_SPI(rme96, (rme96->vol[1] << 2) | 0x2);	} else if (RME96_DAC_IS_1855(rme96)) {		snd_rme96_write_SPI(rme96, (rme96->vol[0] & 0x3FF) | 0x000);		snd_rme96_write_SPI(rme96, (rme96->vol[1] & 0x3FF) | 0x400);	}}static voidsnd_rme96_reset_dac(struct rme96 *rme96){	writel(rme96->wcreg | RME96_WCR_PD,	       rme96->iobase + RME96_IO_CONTROL_REGISTER);	writel(rme96->wcreg, rme96->iobase + RME96_IO_CONTROL_REGISTER);}static intsnd_rme96_getmontracks(struct rme96 *rme96){	return ((rme96->wcreg >> RME96_WCR_BITPOS_MONITOR_0) & 1) +		(((rme96->wcreg >> RME96_WCR_BITPOS_MONITOR_1) & 1) << 1);}static intsnd_rme96_setmontracks(struct rme96 *rme96,		       int montracks){	if (montracks & 1) {		rme96->wcreg |= RME96_WCR_MONITOR_0;	} else {		rme96->wcreg &= ~RME96_WCR_MONITOR_0;	}	if (montracks & 2) {		rme96->wcreg |= RME96_WCR_MONITOR_1;	} else {		rme96->wcreg &= ~RME96_WCR_MONITOR_1;	}	writel(rme96->wcreg, rme96->iobase + RME96_IO_CONTROL_REGISTER);	return 0;}static intsnd_rme96_getattenuation(struct rme96 *rme96){	return ((rme96->wcreg >> RME96_WCR_BITPOS_GAIN_0) & 1) +		(((rme96->wcreg >> RME96_WCR_BITPOS_GAIN_1) & 1) << 1);}static intsnd_rme96_setattenuation(struct rme96 *rme96,			 int attenuation){	switch (attenuation) {	case 0:		rme96->wcreg = (rme96->wcreg & ~RME96_WCR_GAIN_0) &			~RME96_WCR_GAIN_1;		break;	case 1:		rme96->wcreg = (rme96->wcreg | RME96_WCR_GAIN_0) &			~RME96_WCR_GAIN_1;		break;	case 2:		rme96->wcreg = (rme96->wcreg & ~RME96_WCR_GAIN_0) |			RME96_WCR_GAIN_1;		break;	case 3:		rme96->wcreg = (rme96->wcreg | RME96_WCR_GAIN_0) |			RME96_WCR_GAIN_1;		break;	default:		return -EINVAL;	}	writel(rme96->wcreg, rme96->iobase + RME96_IO_CONTROL_REGISTER);	return 0;}static intsnd_rme96_capture_getrate(struct rme96 *rme96,			  int *is_adat){		int n, rate;	*is_adat = 0;	if (rme96->areg & RME96_AR_ANALOG) {		/* Analog input, overrides S/PDIF setting */		n = ((rme96->areg >> RME96_AR_BITPOS_F0) & 1) +			(((rme96->areg >> RME96_AR_BITPOS_F1) & 1) << 1);		switch (n) {		case 1:			rate = 32000;			break;		case 2:			rate = 44100;			break;		case 3:			rate = 48000;			break;		default:			return -1;		}		return (rme96->areg & RME96_AR_BITPOS_F2) ? rate << 1 : rate;	}	rme96->rcreg = readl(rme96->iobase + RME96_IO_CONTROL_REGISTER);	if (rme96->rcreg & RME96_RCR_LOCK) {		/* ADAT rate */		*is_adat = 1;		if (rme96->rcreg & RME96_RCR_T_OUT) {			return 48000;		}		return 44100;	}	if (rme96->rcreg & RME96_RCR_VERF) {		return -1;	}		/* S/PDIF rate */	n = ((rme96->rcreg >> RME96_RCR_BITPOS_F0) & 1) +		(((rme96->rcreg >> RME96_RCR_BITPOS_F1) & 1) << 1) +		(((rme96->rcreg >> RME96_RCR_BITPOS_F2) & 1) << 2);		switch (n) {	case 0:				if (rme96->rcreg & RME96_RCR_T_OUT) {			return 64000;		}		return -1;	case 3: return 96000;	case 4: return 88200;	case 5: return 48000;	case 6: return 44100;	case 7: return 32000;	default:		break;	}	return -1;}static intsnd_rme96_playback_getrate(struct rme96 *rme96){	int rate, dummy;	if (!(rme96->wcreg & RME96_WCR_MASTER) &&            snd_rme96_getinputtype(rme96) != RME96_INPUT_ANALOG &&	    (rate = snd_rme96_capture_getrate(rme96, &dummy)) > 0)	{	        /* slave clock */	        return rate;	}	rate = ((rme96->wcreg >> RME96_WCR_BITPOS_FREQ_0) & 1) +		(((rme96->wcreg >> RME96_WCR_BITPOS_FREQ_1) & 1) << 1);	switch (rate) {	case 1:		rate = 32000;		break;	case 2:		rate = 44100;		break;	case 3:		rate = 48000;		break;	default:		return -1;	}	return (rme96->wcreg & RME96_WCR_DS) ? rate << 1 : rate;}static intsnd_rme96_playback_setrate(struct rme96 *rme96,			   int rate){	int ds;	ds = rme96->wcreg & RME96_WCR_DS;	switch (rate) {	case 32000:		rme96->wcreg &= ~RME96_WCR_DS;		rme96->wcreg = (rme96->wcreg | RME96_WCR_FREQ_0) &			~RME96_WCR_FREQ_1;		break;	case 44100:		rme96->wcreg &= ~RME96_WCR_DS;		rme96->wcreg = (rme96->wcreg | RME96_WCR_FREQ_1) &			~RME96_WCR_FREQ_0;		break;	case 48000:		rme96->wcreg &= ~RME96_WCR_DS;		rme96->wcreg = (rme96->wcreg | RME96_WCR_FREQ_0) |			RME96_WCR_FREQ_1;		break;	case 64000:		rme96->wcreg |= RME96_WCR_DS;		rme96->wcreg = (rme96->wcreg | RME96_WCR_FREQ_0) &			~RME96_WCR_FREQ_1;		break;	case 88200:		rme96->wcreg |= RME96_WCR_DS;		rme96->wcreg = (rme96->wcreg | RME96_WCR_FREQ_1) &			~RME96_WCR_FREQ_0;		break;	case 96000:		rme96->wcreg |= RME96_WCR_DS;		rme96->wcreg = (rme96->wcreg | RME96_WCR_FREQ_0) |			RME96_WCR_FREQ_1;		break;	default:		return -EINVAL;	}	if ((!ds && rme96->wcreg & RME96_WCR_DS) ||	    (ds && !(rme96->wcreg & RME96_WCR_DS)))	{		/* change to/from double-speed: reset the DAC (if available) */		snd_rme96_reset_dac(rme96);	} else {		writel(rme96->wcreg, rme96->iobase + RME96_IO_CONTROL_REGISTER);	}	return 0;}static intsnd_rme96_capture_analog_setrate(struct rme96 *rme96,				 int rate){	switch (rate) {	case 32000:		rme96->areg = ((rme96->areg | RME96_AR_FREQPAD_0) &			       ~RME96_AR_FREQPAD_1) & ~RME96_AR_FREQPAD_2;		break;	case 44100:		rme96->areg = ((rme96->areg & ~RME96_AR_FREQPAD_0) |			       RME96_AR_FREQPAD_1) & ~RME96_AR_FREQPAD_2;		break;	case 48000:		rme96->areg = ((rme96->areg | RME96_AR_FREQPAD_0) |			       RME96_AR_FREQPAD_1) & ~RME96_AR_FREQPAD_2;		break;	case 64000:		if (rme96->rev < 4) {			return -EINVAL;		}		rme96->areg = ((rme96->areg | RME96_AR_FREQPAD_0) &			       ~RME96_AR_FREQPAD_1) | RME96_AR_FREQPAD_2;		break;	case 88200:		if (rme96->rev < 4) {			return -EINVAL;		}		rme96->areg = ((rme96->areg & ~RME96_AR_FREQPAD_0) |			       RME96_AR_FREQPAD_1) | RME96_AR_FREQPAD_2;		break;	case 96000:		rme96->areg = ((rme96->areg | RME96_AR_FREQPAD_0) |			       RME96_AR_FREQPAD_1) | RME96_AR_FREQPAD_2;		break;	default:		return -EINVAL;	}	writel(rme96->areg, rme96->iobase + RME96_IO_ADDITIONAL_REG);	return 0;}static intsnd_rme96_setclockmode(struct rme96 *rme96,		       int mode){	switch (mode) {	case RME96_CLOCKMODE_SLAVE:	        /* AutoSync */ 		rme96->wcreg &= ~RME96_WCR_MASTER;		rme96->areg &= ~RME96_AR_WSEL;		break;	case RME96_CLOCKMODE_MASTER:	        /* Internal */		rme96->wcreg |= RME96_WCR_MASTER;		rme96->areg &= ~RME96_AR_WSEL;		break;	case RME96_CLOCKMODE_WORDCLOCK:		/* Word clock is a master mode */		rme96->wcreg |= RME96_WCR_MASTER; 		rme96->areg |= RME96_AR_WSEL;		break;	default:		return -EINVAL;	}	writel(rme96->wcreg, rme96->iobase + RME96_IO_CONTROL_REGISTER);	writel(rme96->areg, rme96->iobase + RME96_IO_ADDITIONAL_REG);	return 0;}static intsnd_rme96_getclockmode(struct rme96 *rme96){	if (rme96->areg & RME96_AR_WSEL) {		return RME96_CLOCKMODE_WORDCLOCK;	}	return (rme96->wcreg & RME96_WCR_MASTER) ? RME96_CLOCKMODE_MASTER :		RME96_CLOCKMODE_SLAVE;}static intsnd_rme96_setinputtype(struct rme96 *rme96,		       int type){	int n;	switch (type) {	case RME96_INPUT_OPTICAL:		rme96->wcreg = (rme96->wcreg & ~RME96_WCR_INP_0) &			~RME96_WCR_INP_1;		break;	case RME96_INPUT_COAXIAL:		rme96->wcreg = (rme96->wcreg | RME96_WCR_INP_0) &			~RME96_WCR_INP_1;		break;	case RME96_INPUT_INTERNAL:		rme96->wcreg = (rme96->wcreg & ~RME96_WCR_INP_0) |			RME96_WCR_INP_1;		break;	case RME96_INPUT_XLR:		if ((rme96->pci->device != PCI_DEVICE_ID_RME_DIGI96_8_PAD_OR_PST &&		     rme96->pci->device != PCI_DEVICE_ID_RME_DIGI96_8_PRO) ||		    (rme96->pci->device == PCI_DEVICE_ID_RME_DIGI96_8_PAD_OR_PST &&		     rme96->rev > 4))		{			/* Only Digi96/8 PRO and Digi96/8 PAD supports XLR */			return -EINVAL;		}		rme96->wcreg = (rme96->wcreg | RME96_WCR_INP_0) |			RME96_WCR_INP_1;		break;	case RME96_INPUT_ANALOG:		if (!RME96_HAS_ANALOG_IN(rme96)) {			return -EINVAL;		}		rme96->areg |= RME96_AR_ANALOG;		writel(rme96->areg, rme96->iobase + RME96_IO_ADDITIONAL_REG);		if (rme96->rev < 4) {			/*			 * Revision less than 004 does not support 64 and			 * 88.2 kHz			 */			if (snd_rme96_capture_getrate(rme96, &n) == 88200) {				snd_rme96_capture_analog_setrate(rme96, 44100);			}			if (snd_rme96_capture_getrate(rme96, &n) == 64000) {				snd_rme96_capture_analog_setrate(rme96, 32000);			}		}		return 0;	default:		return -EINVAL;	}	if (type != RME96_INPUT_ANALOG && RME96_HAS_ANALOG_IN(rme96)) {		rme96->areg &= ~RME96_AR_ANALOG;		writel(rme96->areg, rme96->iobase + RME96_IO_ADDITIONAL_REG);	}	writel(rme96->wcreg, rme96->iobase + RME96_IO_CONTROL_REGISTER);	return 0;}static intsnd_rme96_getinputtype(struct rme96 *rme96){	if (rme96->areg & RME96_AR_ANALOG) {		return RME96_INPUT_ANALOG;	}	return ((rme96->wcreg >> RME96_WCR_BITPOS_INP_0) & 1) +		(((rme96->wcreg >> RME96_WCR_BITPOS_INP_1) & 1) << 1);}static voidsnd_rme96_setframelog(struct rme96 *rme96,		      int n_channels,		      int is_playback){	int frlog;		if (n_channels == 2) {		frlog = 1;	} else {		/* assume 8 channels */		frlog = 3;	}	if (is_playback) {		frlog += (rme96->wcreg & RME96_WCR_MODE24) ? 2 : 1;		rme96->playback_frlog = frlog;	} else {		frlog += (rme96->wcreg & RME96_WCR_MODE24_2) ? 2 : 1;		rme96->capture_frlog = frlog;	}}static intsnd_rme96_playback_setformat(struct rme96 *rme96,			     int format){	switch (format) {	case SNDRV_PCM_FORMAT_S16_LE:		rme96->wcreg &= ~RME96_WCR_MODE24;		break;	case SNDRV_PCM_FORMAT_S32_LE:		rme96->wcreg |= RME96_WCR_MODE24;		break;	default:		return -EINVAL;	}	writel(rme96->wcreg, rme96->iobase + RME96_IO_CONTROL_REGISTER);	return 0;}static intsnd_rme96_capture_setformat(struct rme96 *rme96,			    int format){	switch (format) {	case SNDRV_PCM_FORMAT_S16_LE:		rme96->wcreg &= ~RME96_WCR_MODE24_2;

⌨️ 快捷键说明

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