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

📄 hdsp.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 5 页
字号:
		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 ("Hammerfall-DSP: unknown spdif frequency status; bits = 0x%x, status = 0x%x\n", rate_bits, status);	return 0;}static 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 &= (hdsp->period_bytes/2) - 1;	return position;}static void hdsp_reset_hw_pointer(hdsp_t *hdsp){	hdsp_write (hdsp, HDSP_resetPointer, 0);}static void hdsp_start_audio(hdsp_t *s){	s->control_register |= (HDSP_AudioInterruptEnable | HDSP_Start);	hdsp_write(s, HDSP_controlRegister, s->control_register);}static void hdsp_stop_audio(hdsp_t *s){	s->control_register &= ~(HDSP_Start | HDSP_AudioInterruptEnable);	hdsp_write(s, HDSP_controlRegister, s->control_register);}static 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(KERN_ERR "Hammerfall-DSP: 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(KERN_INFO "Hammerfall-DSP: 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(KERN_INFO "Hammerfall-DSP: Detected ADAT in quad speed mode\n");						else if (rate != external_freq) {				snd_printk(KERN_INFO "Hammerfall-DSP: 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 ("Hammerfall-DSP: 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;}/*----------------------------------------------------------------------------   MIDI  ----------------------------------------------------------------------------*/static 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 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 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 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 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)				snd_hdsp_midi_read_byte (hmidi->hdsp, hmidi->id);		}	}	hmidi->pending = 0;	if (hmidi->id)		hmidi->hdsp->control_register |= HDSP_Midi1InterruptEnable;	else		hmidi->hdsp->control_register |= HDSP_Midi0InterruptEnable;	hdsp_write(hmidi->hdsp, HDSP_controlRegister, hmidi->hdsp->control_register);	spin_unlock_irqrestore (&hmidi->lock, flags);	return snd_hdsp_midi_output_write (hmidi);}static void snd_hdsp_midi_input_trigger(snd_rawmidi_substream_t * substream, int up){	hdsp_t *hdsp;	hdsp_midi_t *hmidi;	unsigned long flags;	u32 ie;	hmidi = (hdsp_midi_t *) substream->rmidi->private_data;	hdsp = hmidi->hdsp;	ie = hmidi->id ? HDSP_Midi1InterruptEnable : HDSP_Midi0InterruptEnable;	spin_lock_irqsave (&hdsp->lock, flags);	if (up) {		if (!(hdsp->control_register & ie)) {			snd_hdsp_flush_midi_input (hdsp, hmidi->id);			hdsp->control_register |= ie;		}	} else {		hdsp->control_register &= ~ie;		tasklet_kill(&hdsp->midi_tasklet);	}	hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);	spin_unlock_irqrestore (&hdsp->lock, flags);}static void snd_hdsp_midi_output_timer(unsigned long data){	hdsp_midi_t *hmidi = (hdsp_midi_t *) data;	unsigned long flags;		snd_hdsp_midi_output_write(hmidi);	spin_lock_irqsave (&hmidi->lock, flags);	/* this does not bump hmidi->istimer, because the	   kernel automatically removed the timer when it	   expired, and we are now adding it back, thus	   leaving istimer wherever it was set before.  	*/	if (hmidi->istimer) {		hmidi->timer.expires = 1 + jiffies;		add_timer(&hmidi->timer);	}	spin_unlock_irqrestore (&hmidi->lock, flags);}static void snd_hdsp_midi_output_trigger(snd_rawmidi_substream_t * substream, int up){	hdsp_midi_t *hmidi;	unsigned long flags;	hmidi = (hdsp_midi_t *) substream->rmidi->private_data;	spin_lock_irqsave (&hmidi->lock, flags);	if (up) {		if (!hmidi->istimer) {			init_timer(&hmidi->timer);			hmidi->timer.function = snd_hdsp_midi_output_timer;			hmidi->timer.data = (unsigned long) hmidi;			hmidi->timer.expires = 1 + jiffies;			add_timer(&hmidi->timer);			hmidi->istimer++;		}	} else {		if (hmidi->istimer && --hmidi->istimer <= 0)			del_timer (&hmidi->timer);	}	spin_unlock_irqrestore (&hmidi->lock, flags);	if (up)		snd_hdsp_midi_output_write(hmidi);}static int snd_hdsp_midi_input_open(snd_rawmidi_substream_t * substream){	hdsp_midi_t *hmidi;	hmidi = (hdsp_midi_t *) substream->rmidi->private_data;	spin_lock_irq (&hmidi->lock);	snd_hdsp_flush_midi_input (hmidi->hdsp, hmidi->id);	hmidi->input = substream;	spin_unlock_irq (&hmidi->lock);	return 0;}static int snd_hdsp_midi_output_open(snd_rawmidi_substream_t * substream){	hdsp_midi_t *hmidi;	hmidi = (hdsp_midi_t *) substream->rmidi->private_data;	spin_lock_irq (&hmidi->lock);	hmidi->output = substream;	spin_unlock_irq (&hmidi->lock);	return 0;}static int snd_hdsp_midi_input_close(snd_rawmidi_substream_t * substream){	hdsp_midi_t *hmidi;	snd_hdsp_midi_input_trigger (substream, 0);	hmidi = (hdsp_midi_t *) substream->rmidi->private_data;	spin_lock_irq (&hmidi->lock);	hmidi->input = NULL;	spin_unlock_irq (&hmidi->lock);	return 0;}static int snd_hdsp_midi_output_close(snd_rawmidi_substream_t * substream){	hdsp_midi_t *hmidi;

⌨️ 快捷键说明

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