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

📄 hdsp.c

📁 linux 内核源代码
💻 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 int hdsp_external_sample_rate (struct hdsp *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 int hdsp_spdif_sample_rate(struct hdsp *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 ("Hammerfall-DSP: unknown spdif frequency status; bits = 0x%x, status = 0x%x\n", rate_bits, status);	return 0;}static void hdsp_compute_period_size(struct hdsp *hdsp){	hdsp->period_bytes = 1 << ((hdsp_decode_latency(hdsp->control_register) + 8));}static snd_pcm_uframes_t hdsp_hw_pointer(struct hdsp *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(struct hdsp *hdsp){	hdsp_write (hdsp, HDSP_resetPointer, 0);	if (hdsp->io_type == H9632 && hdsp->firmware_rev >= 152)		/* HDSP_resetPointer = HDSP_freqReg, which is strange and		 * requires (?) to write again DDS value after a reset pointer		 * (at least, it works like this) */		hdsp_write (hdsp, HDSP_freqReg, hdsp->dds_value);}static void hdsp_start_audio(struct hdsp *s){	s->control_register |= (HDSP_AudioInterruptEnable | HDSP_Start);	hdsp_write(s, HDSP_controlRegister, s->control_register);}static void hdsp_stop_audio(struct hdsp *s){	s->control_register &= ~(HDSP_Start | HDSP_AudioInterruptEnable);	hdsp_write(s, HDSP_controlRegister, s->control_register);}static void hdsp_silence_playback(struct hdsp *hdsp){	memset(hdsp->playback_buffer, 0, HDSP_DMA_AREA_BYTES);}static int hdsp_set_interrupt_interval(struct hdsp *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 void hdsp_set_dds_value(struct hdsp *hdsp, int rate){	u64 n;	u32 r;		if (rate >= 112000)		rate /= 4;	else if (rate >= 56000)		rate /= 2;	n = DDS_NUMERATOR;	div64_32(&n, rate, &r);	/* n should be less than 2^32 for being written to FREQ register */	snd_assert((n >> 32) == 0);	/* HDSP_freqReg and HDSP_resetPointer are the same, so keep the DDS	   value to write it after a reset */	hdsp->dds_value = n;	hdsp_write(hdsp, HDSP_freqReg, hdsp->dds_value);}static int hdsp_set_rate(struct hdsp *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);	/* For HDSP9632 rev 152, need to set DDS value in FREQ register */	if (hdsp->io_type == H9632 && hdsp->firmware_rev >= 152)		hdsp_set_dds_value(hdsp, rate);	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 (struct hdsp *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 (struct hdsp *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 (struct hdsp *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 (struct hdsp *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 (struct hdsp *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 (struct hdsp_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_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 (struct hdsp_midi *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(struct snd_rawmidi_substream *substream, int up){	struct hdsp *hdsp;	struct hdsp_midi *hmidi;	unsigned long flags;	u32 ie;	hmidi = (struct hdsp_midi *) 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){	struct hdsp_midi *hmidi = (struct hdsp_midi *) data;	unsigned long flags;		snd_hdsp_midi_output_write(hmidi);	spin_lock_irqsave (&hmidi->lock, flags);	/* this does not bump hmidi->istimer, because the

⌨️ 快捷键说明

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