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

📄 hdspm.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	else		target_speed = HDSPM_SPEED_QUAD;	switch (rate) {	case 32000:		rate_bits = HDSPM_Frequency32KHz;		break;	case 44100:		rate_bits = HDSPM_Frequency44_1KHz;		break;	case 48000:		rate_bits = HDSPM_Frequency48KHz;		break;	case 64000:		rate_bits = HDSPM_Frequency64KHz;		break;	case 88200:		rate_bits = HDSPM_Frequency88_2KHz;		break;	case 96000:		rate_bits = HDSPM_Frequency96KHz;		break;	case 128000:		rate_bits = HDSPM_Frequency128KHz;		break;	case 176400:		rate_bits = HDSPM_Frequency176_4KHz;		break;	case 192000:		rate_bits = HDSPM_Frequency192KHz;		break;	default:		return -EINVAL;	}	if (current_speed != target_speed	    && (hdspm->capture_pid >= 0 || hdspm->playback_pid >= 0)) {		snd_printk		    (KERN_ERR "HDSPM: "		     "cannot change from %s speed to %s speed mode "		     "(capture PID = %d, playback PID = %d)\n",		     hdspm_speed_names[current_speed],		     hdspm_speed_names[target_speed],		     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);	/* For AES32, need to set DDS value in FREQ register	   For MADI, also apparently */	hdspm_set_dds_value(hdspm, rate);		if (hdspm->is_aes32 && rate != current_rate)		hdspm_write(hdspm, HDSPM_eeprom_wr, 0);		/* For AES32 and for MADI (at least rev 204), channel_map needs to	 * always be channel_map_madi_ss, whatever the sample rate */	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;	if (sgain > UNITY_GAIN)		gain = UNITY_GAIN;	else if (sgain < 0)		gain = 0;	else		gain = 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);	else		fifo_bytes_used = hdspm_read(hdspm, HDSPM_midiStatusOut0);	fifo_bytes_used &= 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 &&	    !snd_rawmidi_transmit_empty (hmidi->output)) {		n_pending = snd_hdspm_midi_output_possible (hmidi->hdspm,							    hmidi->id);		if (n_pending > 0) {			if (n_pending > (int)sizeof (buf))				n_pending = sizeof (buf);					to_write = snd_rawmidi_transmit (hmidi->output, buf,							 n_pending);			if (to_write > 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){	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);	n_pending = snd_hdspm_midi_input_available (hmidi->hdspm, hmidi->id);	if (n_pending > 0) {		if (hmidi->input) {			if (n_pending > (int)sizeof (buf))				n_pending = sizeof (buf);			for (i = 0; i < n_pending; ++i)				buf[i] = snd_hdspm_midi_read_byte (hmidi->hdspm,								   hmidi->id);			if (n_pending)				snd_rawmidi_receive (hmidi->input, buf,						     n_pending);		} else {			/* flush the MIDI input FIFO */			while (n_pending--)				snd_hdspm_midi_read_byte (hmidi->hdspm,							  hmidi->id);		}	}	hmidi->pending = 0;	if (hmidi->id)		hmidi->hdspm->control_register |= HDSPM_Midi1InterruptEnable;	else		hmidi->hdspm->control_register |= HDSPM_Midi0InterruptEnable;	hdspm_write(hmidi->hdspm, HDSPM_controlRegister,		    hmidi->hdspm->control_register);	spin_unlock_irqrestore (&hmidi->lock, flags);	return snd_hdspm_midi_output_write (hmidi);}static voidsnd_hdspm_midi_input_trigger(struct snd_rawmidi_substream *substream, int up){	struct hdspm *hdspm;	struct hdspm_midi *hmidi;	unsigned long flags;	u32 ie;	hmidi = substream->rmidi->private_data;	hdspm = hmidi->hdspm;	ie = hmidi->id ?		HDSPM_Midi1InterruptEnable : HDSPM_Midi0InterruptEnable;	spin_lock_irqsave (&hdspm->lock, flags);	if (up) {		if (!(hdspm->control_register & ie)) {			snd_hdspm_flush_midi_input (hdspm, hmidi->id);			hdspm->control_register |= ie;		}	} else {		hdspm->control_register &= ~ie;	}	hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);	spin_unlock_irqrestore (&hdspm->lock, flags);}static void snd_hdspm_midi_output_timer(unsigned long data){	struct hdspm_midi *hmidi = (struct hdspm_midi *) data;	unsigned long flags;		snd_hdspm_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 voidsnd_hdspm_midi_output_trigger(struct snd_rawmidi_substream *substream, int up){	struct hdspm_midi *hmidi;	unsigned long flags;	hmidi = substream->rmidi->private_data;	spin_lock_irqsave (&hmidi->lock, flags);	if (up) {		if (!hmidi->istimer) {			init_timer(&hmidi->timer);			hmidi->timer.function = snd_hdspm_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_hdspm_midi_output_write(hmidi);}static int snd_hdspm_midi_input_open(struct snd_rawmidi_substream *substream){	struct hdspm_midi *hmidi;	hmidi = substream->rmidi->private_data;	spin_lock_irq (&hmidi->lock);	snd_hdspm_flush_midi_input (hmidi->hdspm, hmidi->id);	hmidi->input = substream;	spin_unlock_irq (&hmidi->lock);	return 0;}static int snd_hdspm_midi_output_open(struct snd_rawmidi_substream *substream){	struct hdspm_midi *hmidi;	hmidi = substream->rmidi->private_data;	spin_lock_irq (&hmidi->lock);	hmidi->output = substream;	spin_unlock_irq (&hmidi->lock);	return 0;}static int snd_hdspm_midi_input_close(struct snd_rawmidi_substream *substream){	struct hdspm_midi *hmidi;	snd_hdspm_midi_input_trigger (substream, 0);	hmidi = substream->rmidi->private_data;	spin_lock_irq (&hmidi->lock);	hmidi->input = NULL;	spin_unlock_irq (&hmidi->lock);	return 0;}static int snd_hdspm_midi_output_close(struct snd_rawmidi_substream *substream){	struct hdspm_midi *hmidi;	snd_hdspm_midi_output_trigger (substream, 0);	hmidi = substream->rmidi->private_data;	spin_lock_irq (&hmidi->lock);	hmidi->output = NULL;	spin_unlock_irq (&hmidi->lock);	return 0;}static struct snd_rawmidi_ops snd_hdspm_midi_output ={	.open =		snd_hdspm_midi_output_open,	.close =	snd_hdspm_midi_output_close,	.trigger =	snd_hdspm_midi_output_trigger,};static struct snd_rawmidi_ops snd_hdspm_midi_input ={	.open =		snd_hdspm_midi_input_open,	.close =	snd_hdspm_midi_input_close,	.trigger =	snd_hdspm_midi_input_trigger,};static int __devinit snd_hdspm_create_midi (struct snd_card *card,					    struct hdspm *hdspm, int id){	int err;	char buf[32];	hdspm->midi[id].id = id;	hdspm->midi[id].hdspm = hdspm;	spin_lock_init (&hdspm->midi[id].lock);	sprintf (buf, "%s MIDI %d", card->shortname, id+1);	err = snd_rawmidi_new (card, buf, id, 1, 1, &hdspm->midi[id].rmidi);	if (err < 0)		return err;	sprintf (hdspm->midi[id].rmidi->name, "%s MIDI %d", card->id, id+1);	hdspm->midi[id].rmidi->private_data = &hdspm->midi[id];	snd_rawmidi_set_ops(hdspm->midi[id].rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT,			    &snd_hdspm_midi_output);	snd_rawmidi_set_ops(hdspm->midi[id].rmidi, SNDRV_RAWMIDI_STREAM_INPUT,			    &snd_hdspm_midi_input);	hdspm->midi[id].rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT |		SNDRV_RAWMIDI_INFO_INPUT |		SNDRV_RAWMIDI_INFO_DUPLEX;	return 0;}static void hdspm_midi_tasklet(unsigned long arg){	struct hdspm *hdspm = (struct hdspm *)arg;		if (hdspm->midi[0].pending)		snd_hdspm_midi_input_read (&hdspm->midi[0]);	if (hdspm->midi[1].pending)		snd_hdspm_midi_input_read (&hdspm->midi[1]);} /*-----------------------------------------------------------------------------  Status Interface  ----------------------------------------------------------------------------*//* get the system sample rate which is set */#define HDSPM_SYSTEM_SAMPLE_RATE(xname, xindex) \{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \  .name = xname, \  .index = xindex, \  .access = SNDRV_CTL_ELEM_ACCESS_READ, \  .info = snd_hdspm_info_system_sample_rate, \  .get = snd_hdspm_get_system_sample_rate \}static int snd_hdspm_info_system_sample_rate(struct snd_kcontrol *kcontrol,					     struct snd_ctl_elem_info *uinfo){	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;	uinfo->count = 1;	return 0;}static int snd_hdspm_get_system_sample_rate(struct snd_kcontrol *kcontrol,					    struct snd_ctl_elem_value *					    ucontrol){	struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);	ucontrol->value.enumerated.item[0] = hdspm->system_sample_rate;	return 0;}#define HDSPM_AUTOSYNC_SAMPLE_RATE(xname, xindex) \{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \  .name = xname, \  .index = xindex, \  .access = SNDRV_CTL_ELEM_ACCESS_READ, \  .info = snd_hdspm_info_autosync_sample_rate, \  .get = snd_hdspm_get_autosync_sample_rate \}static int snd_hdspm_info_autosync_sample_rate(struct snd_kcontrol *kcontrol,					       struct snd_ctl_elem_info *uinfo){	static char *texts[] = { "32000", "44100", "48000",		"64000", "88200", "96000",		"128000", "176400", "192000",		"None"	};	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;	uinfo->count = 1;	uinfo->value.enumerated.items = 10;	if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)		uinfo->value.enumerated.item =		    uinfo->value.enumerated.items - 1;	strcpy(uinfo->value.enumerated.name,	       texts[uinfo->value.enumerated.item]);	return 0;}static int snd_hdspm_get_autosync_sample_rate(struct snd_kcontrol *kcontrol,

⌨️ 快捷键说明

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