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

📄 hdspm.c

📁 LINUX 2.6.17.4的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
{	return readl(hdspm->iobase + reg);}/* for each output channel (chan) I have an Input (in) and Playback (pb) Fader    mixer is write only on hardware so we have to cache him for read    each fader is a u32, but uses only the first 16 bit */static inline int hdspm_read_in_gain(struct hdspm * hdspm, unsigned int chan,				     unsigned int in){	if (chan >= HDSPM_MIXER_CHANNELS || in >= HDSPM_MIXER_CHANNELS)		return 0;	return hdspm->mixer->ch[chan].in[in];}static inline int hdspm_read_pb_gain(struct hdspm * hdspm, unsigned int chan,				     unsigned int pb){	if (chan >= HDSPM_MIXER_CHANNELS || pb >= HDSPM_MIXER_CHANNELS)		return 0;	return hdspm->mixer->ch[chan].pb[pb];}static inline int hdspm_write_in_gain(struct hdspm * hdspm, unsigned int chan,				      unsigned int in, unsigned short data){	if (chan >= HDSPM_MIXER_CHANNELS || in >= HDSPM_MIXER_CHANNELS)		return -1;	hdspm_write(hdspm,		    HDSPM_MADI_mixerBase +		    ((in + 128 * chan) * sizeof(u32)),		    (hdspm->mixer->ch[chan].in[in] = data & 0xFFFF));	return 0;}static inline int hdspm_write_pb_gain(struct hdspm * hdspm, unsigned int chan,				      unsigned int pb, unsigned short data){	if (chan >= HDSPM_MIXER_CHANNELS || pb >= HDSPM_MIXER_CHANNELS)		return -1;	hdspm_write(hdspm,		    HDSPM_MADI_mixerBase +		    ((64 + pb + 128 * chan) * sizeof(u32)),		    (hdspm->mixer->ch[chan].pb[pb] = data & 0xFFFF));	return 0;}/* enable DMA for specific channels, now available for DSP-MADI */static inline void snd_hdspm_enable_in(struct hdspm * hdspm, int i, int v){	hdspm_write(hdspm, HDSPM_inputEnableBase + (4 * i), v);}static inline void snd_hdspm_enable_out(struct hdspm * hdspm, int i, int v){	hdspm_write(hdspm, HDSPM_outputEnableBase + (4 * i), v);}/* check if same process is writing and reading */static inline int snd_hdspm_use_is_exclusive(struct hdspm * hdspm){	unsigned long flags;	int ret = 1;	spin_lock_irqsave(&hdspm->lock, flags);	if ((hdspm->playback_pid != hdspm->capture_pid) &&	    (hdspm->playback_pid >= 0) && (hdspm->capture_pid >= 0)) {		ret = 0;	}	spin_unlock_irqrestore(&hdspm->lock, flags);	return ret;}/* check for external sample rate */static inline int hdspm_external_sample_rate(struct hdspm * hdspm){	unsigned int status2 = hdspm_read(hdspm, HDSPM_statusRegister2);	unsigned int status = hdspm_read(hdspm, HDSPM_statusRegister);	unsigned int rate_bits;	int rate = 0;	/* if wordclock has synced freq and wordclock is valid */	if ((status2 & HDSPM_wcLock) != 0 &&	    (status & HDSPM_SelSyncRef0) == 0) {		rate_bits = status2 & HDSPM_wcFreqMask;		switch (rate_bits) {		case HDSPM_wcFreq32:			rate = 32000;			break;		case HDSPM_wcFreq44_1:			rate = 44100;			break;		case HDSPM_wcFreq48:			rate = 48000;			break;		case HDSPM_wcFreq64:			rate = 64000;			break;		case HDSPM_wcFreq88_2:			rate = 88200;			break;		case HDSPM_wcFreq96:			rate = 96000;			break;			/* Quadspeed Bit missing ???? */		default:			rate = 0;			break;		}	}	/* if rate detected and Syncref is Word than have it, word has priority to MADI */	if (rate != 0	    && (status2 & HDSPM_SelSyncRefMask) == HDSPM_SelSyncRef_WORD)		return rate;	/* maby a madi input (which is taken if sel sync is madi) */	if (status & HDSPM_madiLock) {		rate_bits = status & HDSPM_madiFreqMask;		switch (rate_bits) {		case HDSPM_madiFreq32:			rate = 32000;			break;		case HDSPM_madiFreq44_1:			rate = 44100;			break;		case HDSPM_madiFreq48:			rate = 48000;			break;		case HDSPM_madiFreq64:			rate = 64000;			break;		case HDSPM_madiFreq88_2:			rate = 88200;			break;		case HDSPM_madiFreq96:			rate = 96000;			break;		case HDSPM_madiFreq128:			rate = 128000;			break;		case HDSPM_madiFreq176_4:			rate = 176400;			break;		case HDSPM_madiFreq192:			rate = 192000;			break;		default:			rate = 0;			break;		}	}	return rate;}/* Latency function */static inline void hdspm_compute_period_size(struct hdspm * hdspm){	hdspm->period_bytes =	    1 << ((hdspm_decode_latency(hdspm->control_register) + 8));}static snd_pcm_uframes_t hdspm_hw_pointer(struct hdspm * hdspm){	int position;	position = hdspm_read(hdspm, HDSPM_statusRegister);	if (!hdspm->precise_ptr) {		return (position & HDSPM_BufferID) ? (hdspm->period_bytes /						      4) : 0;	}	/* hwpointer comes in bytes and is 64Bytes accurate (by docu since PCI Burst)	   i have experimented that it is at most 64 Byte to much for playing 	   so substraction of 64 byte should be ok for ALSA, but use it only	   for application where you know what you do since if you come to	   near with record pointer it can be a disaster */	position &= HDSPM_BufferPositionMask;	position = ((position - 64) % (2 * hdspm->period_bytes)) / 4;	return position;}static inline void hdspm_start_audio(struct hdspm * s){	s->control_register |= (HDSPM_AudioInterruptEnable | HDSPM_Start);	hdspm_write(s, HDSPM_controlRegister, s->control_register);}static inline void hdspm_stop_audio(struct hdspm * s){	s->control_register &= ~(HDSPM_Start | HDSPM_AudioInterruptEnable);	hdspm_write(s, HDSPM_controlRegister, s->control_register);}/* should I silence all or only opened ones ? doit all for first even is 4MB*/static inline void hdspm_silence_playback(struct hdspm * hdspm){	int i;	int n = hdspm->period_bytes;	void *buf = hdspm->playback_buffer;	snd_assert(buf != NULL, return);	for (i = 0; i < HDSPM_MAX_CHANNELS; i++) {		memset(buf, 0, n);		buf += HDSPM_CHANNEL_BUFFER_BYTES;	}}static int hdspm_set_interrupt_interval(struct hdspm * s, unsigned int frames){	int n;	spin_lock_irq(&s->lock);	frames >>= 7;	n = 0;	while (frames) {		n++;		frames >>= 1;	}	s->control_register &= ~HDSPM_LatencyMask;	s->control_register |= hdspm_encode_latency(n);	hdspm_write(s, HDSPM_controlRegister, s->control_register);	hdspm_compute_period_size(s);	spin_unlock_irq(&s->lock);	return 0;}/* dummy set rate lets see what happens */static int hdspm_set_rate(struct hdspm * hdspm, int rate, int called_internally){	int reject_if_open = 0;	int current_rate;	int rate_bits;	int not_set = 0;	/* ASSUMPTION: hdspm->lock is either set, or there is no need for	   it (e.g. during module initialization).	 */	if (!(hdspm->control_register & HDSPM_ClockModeMaster)) {	        /* SLAVE --- */ 		if (called_internally) {        	  /* request from ctl or card initialization 	             just make a warning an remember setting 		     for future master mode switching */    			snd_printk			    (KERN_WARNING "HDSPM: Warning: device is not running as a clock master.\n");			not_set = 1;		} else {			/* hw_param request while in AutoSync mode */			int external_freq =			    hdspm_external_sample_rate(hdspm);			if ((hdspm_autosync_ref(hdspm) ==			     HDSPM_AUTOSYNC_FROM_NONE)) {				snd_printk(KERN_WARNING "HDSPM: Detected no Externel Sync \n");				not_set = 1;			} else if (rate != external_freq) {				snd_printk				    (KERN_WARNING "HDSPM: Warning: No AutoSync source for requested rate\n");				not_set = 1;			}		}	}	current_rate = hdspm->system_sample_rate;	/* Changing between Singe, Double and Quad speed is not	   allowed if any substreams are open. This is because such a change	   causes a shift in the location of the DMA buffers and a reduction	   in the number of available buffers.	   Note that a similar but essentially insoluble problem exists for	   externally-driven rate changes. All we can do is to flag rate	   changes in the read/write routines.  	 */	switch (rate) {	case 32000:		if (current_rate > 48000) {			reject_if_open = 1;		}		rate_bits = HDSPM_Frequency32KHz;		break;	case 44100:		if (current_rate > 48000) {			reject_if_open = 1;		}		rate_bits = HDSPM_Frequency44_1KHz;		break;	case 48000:		if (current_rate > 48000) {			reject_if_open = 1;		}		rate_bits = HDSPM_Frequency48KHz;		break;	case 64000:		if (current_rate <= 48000) {			reject_if_open = 1;		}		rate_bits = HDSPM_Frequency64KHz;		break;	case 88200:		if (current_rate <= 48000) {			reject_if_open = 1;		}		rate_bits = HDSPM_Frequency88_2KHz;		break;	case 96000:		if (current_rate <= 48000) {			reject_if_open = 1;		}		rate_bits = HDSPM_Frequency96KHz;		break;	default:		return -EINVAL;	}	if (reject_if_open	    && (hdspm->capture_pid >= 0 || hdspm->playback_pid >= 0)) {		snd_printk		    (KERN_ERR "HDSPM: cannot change between single- and double-speed mode (capture PID = %d, playback PID = %d)\n",		     hdspm->capture_pid, hdspm->playback_pid);		return -EBUSY;	}	hdspm->control_register &= ~HDSPM_FrequencyMask;	hdspm->control_register |= rate_bits;	hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);	if (rate > 64000)		hdspm->channel_map = channel_map_madi_qs;	else if (rate > 48000)		hdspm->channel_map = channel_map_madi_ds;	else 		hdspm->channel_map = channel_map_madi_ss;	hdspm->system_sample_rate = rate;	if (not_set != 0)		return -1;	return 0;}/* mainly for init to 0 on load */static void all_in_all_mixer(struct hdspm * hdspm, int sgain){	int i, j;	unsigned int gain =	    (sgain > UNITY_GAIN) ? UNITY_GAIN : (sgain < 0) ? 0 : sgain;	for (i = 0; i < HDSPM_MIXER_CHANNELS; i++)		for (j = 0; j < HDSPM_MIXER_CHANNELS; j++) {			hdspm_write_in_gain(hdspm, i, j, gain);			hdspm_write_pb_gain(hdspm, i, j, gain);		}}/*----------------------------------------------------------------------------   MIDI  ----------------------------------------------------------------------------*/static inline unsigned char snd_hdspm_midi_read_byte (struct hdspm *hdspm, int id){	/* the hardware already does the relevant bit-mask with 0xff */	if (id)		return hdspm_read(hdspm, HDSPM_midiDataIn1);	else		return hdspm_read(hdspm, HDSPM_midiDataIn0);}static inline void snd_hdspm_midi_write_byte (struct hdspm *hdspm, int id, int val){	/* the hardware already does the relevant bit-mask with 0xff */	if (id)		return hdspm_write(hdspm, HDSPM_midiDataOut1, val);	else		return hdspm_write(hdspm, HDSPM_midiDataOut0, val);}static inline int snd_hdspm_midi_input_available (struct hdspm *hdspm, int id){	if (id)		return (hdspm_read(hdspm, HDSPM_midiStatusIn1) & 0xff);	else		return (hdspm_read(hdspm, HDSPM_midiStatusIn0) & 0xff);}static inline int snd_hdspm_midi_output_possible (struct hdspm *hdspm, int id){	int fifo_bytes_used;	if (id)		fifo_bytes_used = hdspm_read(hdspm, HDSPM_midiStatusOut1) & 0xff;	else		fifo_bytes_used = hdspm_read(hdspm, HDSPM_midiStatusOut0) & 0xff;	if (fifo_bytes_used < 128)		return  128 - fifo_bytes_used;	else		return 0;}static inline void snd_hdspm_flush_midi_input (struct hdspm *hdspm, int id){	while (snd_hdspm_midi_input_available (hdspm, id))		snd_hdspm_midi_read_byte (hdspm, id);}static int snd_hdspm_midi_output_write (struct hdspm_midi *hmidi){	unsigned long flags;	int n_pending;	int to_write;	int i;	unsigned char buf[128];	/* Output is not interrupt driven */			spin_lock_irqsave (&hmidi->lock, flags);	if (hmidi->output) {		if (!snd_rawmidi_transmit_empty (hmidi->output)) {			if ((n_pending = snd_hdspm_midi_output_possible (hmidi->hdspm, hmidi->id)) > 0) {				if (n_pending > (int)sizeof (buf))					n_pending = sizeof (buf);								if ((to_write = snd_rawmidi_transmit (hmidi->output, buf, n_pending)) > 0) {					for (i = 0; i < to_write; ++i) 						snd_hdspm_midi_write_byte (hmidi->hdspm, hmidi->id, buf[i]);				}			}		}	}	spin_unlock_irqrestore (&hmidi->lock, flags);	return 0;}static int snd_hdspm_midi_input_read (struct hdspm_midi *hmidi)

⌨️ 快捷键说明

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