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

📄 hdsp.c

📁 优龙2410linux2.6.8内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	int ret = 1;	spin_lock_irqsave(&hdsp->lock, flags);	if ((hdsp->playback_pid != hdsp->capture_pid) &&	    (hdsp->playback_pid >= 0) && (hdsp->capture_pid >= 0)) {		ret = 0;	}	spin_unlock_irqrestore(&hdsp->lock, flags);	return ret;}static inline int hdsp_external_sample_rate (hdsp_t *hdsp){	unsigned int status2 = hdsp_read(hdsp, HDSP_status2Register);	unsigned int rate_bits = status2 & HDSP_systemFrequencyMask;	switch (rate_bits) {	case HDSP_systemFrequency32:   return 32000;	case HDSP_systemFrequency44_1: return 44100;	case HDSP_systemFrequency48:   return 48000;	case HDSP_systemFrequency64:   return 64000;	case HDSP_systemFrequency88_2: return 88200;	case HDSP_systemFrequency96:   return 96000;	default:		return 0;	}}static inline int hdsp_spdif_sample_rate(hdsp_t *hdsp){	unsigned int status = hdsp_read(hdsp, HDSP_statusRegister);	unsigned int rate_bits = (status & HDSP_spdifFrequencyMask);	if (status & HDSP_SPDIFErrorFlag) {		return 0;	}		switch (rate_bits) {	case HDSP_spdifFrequency32KHz: return 32000;	case HDSP_spdifFrequency44_1KHz: return 44100;	case HDSP_spdifFrequency48KHz: return 48000;	case HDSP_spdifFrequency64KHz: return 64000;	case HDSP_spdifFrequency88_2KHz: return 88200;	case HDSP_spdifFrequency96KHz: return 96000;	case HDSP_spdifFrequency128KHz: 		if (hdsp->io_type == H9632) return 128000;		break;	case HDSP_spdifFrequency176_4KHz: 		if (hdsp->io_type == H9632) return 176400;		break;	case HDSP_spdifFrequency192KHz: 		if (hdsp->io_type == H9632) return 192000;		break;	default:		break;	}	snd_printk ("unknown spdif frequency status; bits = 0x%x, status = 0x%x\n", rate_bits, status);	return 0;}static inline void hdsp_compute_period_size(hdsp_t *hdsp){	hdsp->period_bytes = 1 << ((hdsp_decode_latency(hdsp->control_register) + 8));}static snd_pcm_uframes_t hdsp_hw_pointer(hdsp_t *hdsp){	int position;	position = hdsp_read(hdsp, HDSP_statusRegister);	if (!hdsp->precise_ptr) {		return (position & HDSP_BufferID) ? (hdsp->period_bytes / 4) : 0;	}	position &= HDSP_BufferPositionMask;	position /= 4;	position -= 32;	position &= (HDSP_CHANNEL_BUFFER_SAMPLES-1);	return position;}static inline void hdsp_reset_hw_pointer(hdsp_t *hdsp){	hdsp_write (hdsp, HDSP_resetPointer, 0);}static inline void hdsp_start_audio(hdsp_t *s){	s->control_register |= (HDSP_AudioInterruptEnable | HDSP_Start);	hdsp_write(s, HDSP_controlRegister, s->control_register);}static inline void hdsp_stop_audio(hdsp_t *s){	s->control_register &= ~(HDSP_Start | HDSP_AudioInterruptEnable);	hdsp_write(s, HDSP_controlRegister, s->control_register);}static inline void hdsp_silence_playback(hdsp_t *hdsp){	memset(hdsp->playback_buffer, 0, HDSP_DMA_AREA_BYTES);}static int hdsp_set_interrupt_interval(hdsp_t *s, unsigned int frames){	int n;	spin_lock_irq(&s->lock);	frames >>= 7;	n = 0;	while (frames) {		n++;		frames >>= 1;	}	s->control_register &= ~HDSP_LatencyMask;	s->control_register |= hdsp_encode_latency(n);	hdsp_write(s, HDSP_controlRegister, s->control_register);	hdsp_compute_period_size(s);	spin_unlock_irq(&s->lock);	return 0;}static int hdsp_set_rate(hdsp_t *hdsp, int rate, int called_internally){	int reject_if_open = 0;	int current_rate;	int rate_bits;	/* ASSUMPTION: hdsp->lock is either held, or	   there is no need for it (e.g. during module	   initialization).	*/		if (!(hdsp->control_register & HDSP_ClockModeMaster)) {			if (called_internally) {			/* request from ctl or card initialization */			snd_printk("device is not running as a clock master: cannot set sample rate.\n");			return -1;		} else {					/* hw_param request while in AutoSync mode */			int external_freq = hdsp_external_sample_rate(hdsp);			int spdif_freq = hdsp_spdif_sample_rate(hdsp);					if ((spdif_freq == external_freq*2) && (hdsp_autosync_ref(hdsp) >= HDSP_AUTOSYNC_FROM_ADAT1)) {				snd_printk("Detected ADAT in double speed mode\n");			} else if (hdsp->io_type == H9632 && (spdif_freq == external_freq*4) && (hdsp_autosync_ref(hdsp) >= HDSP_AUTOSYNC_FROM_ADAT1)) {				snd_printk("Detected ADAT in quad speed mode\n");						} else if (rate != external_freq) {				snd_printk("No AutoSync source for requested rate\n");				return -1;			}				}		}	current_rate = hdsp->system_sample_rate;	/* Changing from a "single speed" to a "double speed" rate 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.  */	if (rate > 96000 && hdsp->io_type != H9632) {		return -EINVAL;	}		switch (rate) {	case 32000:		if (current_rate > 48000) {			reject_if_open = 1;		}		rate_bits = HDSP_Frequency32KHz;		break;	case 44100:		if (current_rate > 48000) {			reject_if_open = 1;		}		rate_bits = HDSP_Frequency44_1KHz;		break;	case 48000:		if (current_rate > 48000) {			reject_if_open = 1;		}		rate_bits = HDSP_Frequency48KHz;		break;	case 64000:		if (current_rate <= 48000 || current_rate > 96000) {			reject_if_open = 1;		}		rate_bits = HDSP_Frequency64KHz;		break;	case 88200:		if (current_rate <= 48000 || current_rate > 96000) {			reject_if_open = 1;		}		rate_bits = HDSP_Frequency88_2KHz;		break;	case 96000:		if (current_rate <= 48000 || current_rate > 96000) {			reject_if_open = 1;		}		rate_bits = HDSP_Frequency96KHz;		break;	case 128000:		if (current_rate < 128000) {			reject_if_open = 1;		}		rate_bits = HDSP_Frequency128KHz;		break;	case 176400:		if (current_rate < 128000) {			reject_if_open = 1;		}		rate_bits = HDSP_Frequency176_4KHz;		break;	case 192000:		if (current_rate < 128000) {			reject_if_open = 1;		}		rate_bits = HDSP_Frequency192KHz;		break;	default:		return -EINVAL;	}	if (reject_if_open && (hdsp->capture_pid >= 0 || hdsp->playback_pid >= 0)) {		snd_printk ("cannot change speed mode (capture PID = %d, playback PID = %d)\n",			    hdsp->capture_pid,			    hdsp->playback_pid);		return -EBUSY;	}	hdsp->control_register &= ~HDSP_FrequencyMask;	hdsp->control_register |= rate_bits;	hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);	if (rate >= 128000) {		hdsp->channel_map = channel_map_H9632_qs;	} else if (rate > 48000) {		if (hdsp->io_type == H9632) {			hdsp->channel_map = channel_map_H9632_ds;		} else {			hdsp->channel_map = channel_map_ds;		}	} else {		switch (hdsp->io_type) {		case Multiface:			hdsp->channel_map = channel_map_mf_ss;			break;		case Digiface:		case H9652:			hdsp->channel_map = channel_map_df_ss;			break;		case H9632:			hdsp->channel_map = channel_map_H9632_ss;			break;		default:			/* should never happen */			break;		}	}		hdsp->system_sample_rate = rate;	return 0;}static void hdsp_set_thru(hdsp_t *hdsp, int channel, int enable){	hdsp->passthru = 0;	if (channel < 0) {		int i;		/* set thru for all channels */		if (enable) {			for (i = 0; i < hdsp->max_channels; i++) {				hdsp_write_gain (hdsp, hdsp_input_to_output_key(hdsp,i,i), UNITY_GAIN);			}		} else {			for (i = 0; i < hdsp->max_channels; i++) {				hdsp_write_gain (hdsp, hdsp_input_to_output_key(hdsp,i,i), MINUS_INFINITY_GAIN);			}		}	} else {		int mapped_channel;		snd_assert(channel < hdsp->max_channels, return);		mapped_channel = hdsp->channel_map[channel];		snd_assert(mapped_channel > -1, return);		if (enable) {			hdsp_write_gain (hdsp, hdsp_input_to_output_key(hdsp,mapped_channel,mapped_channel), UNITY_GAIN);		} else {			hdsp_write_gain (hdsp, hdsp_input_to_output_key(hdsp,mapped_channel,mapped_channel), MINUS_INFINITY_GAIN);		}	}}static int hdsp_set_passthru(hdsp_t *hdsp, int onoff){	if (onoff) {		hdsp_set_thru(hdsp, -1, 1);		hdsp_reset_hw_pointer(hdsp);		hdsp_silence_playback(hdsp);		/* we don't want interrupts, so do a		   custom version of hdsp_start_audio().		*/		hdsp->control_register |= (HDSP_Start|HDSP_AudioInterruptEnable|hdsp_encode_latency(7));		hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);		hdsp->passthru = 1;	} else {		hdsp_set_thru(hdsp, -1, 0);		hdsp_stop_audio(hdsp);				hdsp->passthru = 0;	}	return 0;}/*----------------------------------------------------------------------------   MIDI  ----------------------------------------------------------------------------*/static inline unsigned char snd_hdsp_midi_read_byte (hdsp_t *hdsp, int id){	/* the hardware already does the relevant bit-mask with 0xff */	if (id) {		return hdsp_read(hdsp, HDSP_midiDataIn1);	} else {		return hdsp_read(hdsp, HDSP_midiDataIn0);	}}static inline void snd_hdsp_midi_write_byte (hdsp_t *hdsp, int id, int val){	/* the hardware already does the relevant bit-mask with 0xff */	if (id) {		hdsp_write(hdsp, HDSP_midiDataOut1, val);	} else {		hdsp_write(hdsp, HDSP_midiDataOut0, val);	}}static inline int snd_hdsp_midi_input_available (hdsp_t *hdsp, int id){	if (id) {		return (hdsp_read(hdsp, HDSP_midiStatusIn1) & 0xff);	} else {		return (hdsp_read(hdsp, HDSP_midiStatusIn0) & 0xff);	}}static inline int snd_hdsp_midi_output_possible (hdsp_t *hdsp, int id){	int fifo_bytes_used;	if (id) {		fifo_bytes_used = hdsp_read(hdsp, HDSP_midiStatusOut1) & 0xff;	} else {		fifo_bytes_used = hdsp_read(hdsp, HDSP_midiStatusOut0) & 0xff;	}	if (fifo_bytes_used < 128) {		return  128 - fifo_bytes_used;	} else {		return 0;	}}static inline void snd_hdsp_flush_midi_input (hdsp_t *hdsp, int id){	while (snd_hdsp_midi_input_available (hdsp, id)) {		snd_hdsp_midi_read_byte (hdsp, id);	}}static int snd_hdsp_midi_output_write (hdsp_midi_t *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_hdsp_midi_output_possible (hmidi->hdsp, 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_hdsp_midi_write_byte (hmidi->hdsp, hmidi->id, buf[i]);				}			}		}	}	spin_unlock_irqrestore (&hmidi->lock, flags);	return 0;}static int snd_hdsp_midi_input_read (hdsp_midi_t *hmidi){	unsigned char buf[128]; /* this buffer is designed to match the MIDI input FIFO size */	unsigned long flags;	int n_pending;	int i;	spin_lock_irqsave (&hmidi->lock, flags);	if ((n_pending = snd_hdsp_midi_input_available (hmidi->hdsp, hmidi->id)) > 0) {		if (hmidi->input) {			if (n_pending > (int)sizeof (buf)) {				n_pending = sizeof (buf);			}			for (i = 0; i < n_pending; ++i) {				buf[i] = snd_hdsp_midi_read_byte (hmidi->hdsp, hmidi->id);			}			if (n_pending) {				snd_rawmidi_receive (hmidi->input, buf, n_pending);			}		} else {			/* flush the MIDI input FIFO */			while (--n_pending) {

⌨️ 快捷键说明

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