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

📄 hdspm.c

📁 底层驱动开发
💻 C
📖 第 1 页 / 共 5 页
字号:
	spin_lock_irqsave (&hmidi->lock, flags);	if ((n_pending = snd_hdspm_midi_input_available (hmidi->hdspm, 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_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 void snd_hdspm_midi_input_trigger(snd_rawmidi_substream_t * substream, int up){	hdspm_t *hdspm;	hdspm_midi_t *hmidi;	unsigned long flags;	u32 ie;	hmidi = (hdspm_midi_t *) 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){	hdspm_midi_t *hmidi = (hdspm_midi_t *) 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 void snd_hdspm_midi_output_trigger(snd_rawmidi_substream_t * substream, int up){	hdspm_midi_t *hmidi;	unsigned long flags;	hmidi = (hdspm_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_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(snd_rawmidi_substream_t * substream){	hdspm_midi_t *hmidi;	hmidi = (hdspm_midi_t *) 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(snd_rawmidi_substream_t * substream){	hdspm_midi_t *hmidi;	hmidi = (hdspm_midi_t *) 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(snd_rawmidi_substream_t * substream){	hdspm_midi_t *hmidi;	snd_hdspm_midi_input_trigger (substream, 0);	hmidi = (hdspm_midi_t *) 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(snd_rawmidi_substream_t * substream){	hdspm_midi_t *hmidi;	snd_hdspm_midi_output_trigger (substream, 0);	hmidi = (hdspm_midi_t *) substream->rmidi->private_data;	spin_lock_irq (&hmidi->lock);	hmidi->output = NULL;	spin_unlock_irq (&hmidi->lock);	return 0;}static snd_rawmidi_ops_t snd_hdspm_midi_output ={	.open =		snd_hdspm_midi_output_open,	.close =	snd_hdspm_midi_output_close,	.trigger =	snd_hdspm_midi_output_trigger,};static snd_rawmidi_ops_t 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 (snd_card_t *card, hdspm_t *hdspm, int id){	int err;	char buf[32];	hdspm->midi[id].id = id;	hdspm->midi[id].rmidi = NULL;	hdspm->midi[id].input = NULL;	hdspm->midi[id].output = NULL;	hdspm->midi[id].hdspm = hdspm;	hdspm->midi[id].istimer = 0;	hdspm->midi[id].pending = 0;	spin_lock_init (&hdspm->midi[id].lock);	sprintf (buf, "%s MIDI %d", card->shortname, id+1);	if ((err = snd_rawmidi_new (card, buf, id, 1, 1, &hdspm->midi[id].rmidi)) < 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){	hdspm_t *hdspm = (hdspm_t *)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(snd_kcontrol_t * kcontrol,					     snd_ctl_elem_info_t * uinfo){	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;	uinfo->count = 1;	return 0;}static int snd_hdspm_get_system_sample_rate(snd_kcontrol_t * kcontrol,					    snd_ctl_elem_value_t *					    ucontrol){	hdspm_t *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(snd_kcontrol_t * kcontrol,					       snd_ctl_elem_info_t * 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(snd_kcontrol_t * kcontrol,					      snd_ctl_elem_value_t *					      ucontrol){	hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);	switch (hdspm_external_sample_rate(hdspm)) {	case 32000:		ucontrol->value.enumerated.item[0] = 0;		break;	case 44100:		ucontrol->value.enumerated.item[0] = 1;		break;	case 48000:		ucontrol->value.enumerated.item[0] = 2;		break;	case 64000:		ucontrol->value.enumerated.item[0] = 3;		break;	case 88200:		ucontrol->value.enumerated.item[0] = 4;		break;	case 96000:		ucontrol->value.enumerated.item[0] = 5;		break;	case 128000:		ucontrol->value.enumerated.item[0] = 6;		break;	case 176400:		ucontrol->value.enumerated.item[0] = 7;		break;	case 192000:		ucontrol->value.enumerated.item[0] = 8;		break;	default:		ucontrol->value.enumerated.item[0] = 9;	}	return 0;}#define HDSPM_SYSTEM_CLOCK_MODE(xname, xindex) \{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \  .name = xname, \  .index = xindex, \  .access = SNDRV_CTL_ELEM_ACCESS_READ, \  .info = snd_hdspm_info_system_clock_mode, \  .get = snd_hdspm_get_system_clock_mode, \}static int hdspm_system_clock_mode(hdspm_t * hdspm){        /* Always reflect the hardware info, rme is never wrong !!!! */	if (hdspm->control_register & HDSPM_ClockModeMaster)		return 0;	return 1;}static int snd_hdspm_info_system_clock_mode(snd_kcontrol_t * kcontrol,					    snd_ctl_elem_info_t * uinfo){	static char *texts[] = { "Master", "Slave" };	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;	uinfo->count = 1;	uinfo->value.enumerated.items = 2;	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_system_clock_mode(snd_kcontrol_t * kcontrol,					   snd_ctl_elem_value_t * ucontrol){	hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);	ucontrol->value.enumerated.item[0] =	    hdspm_system_clock_mode(hdspm);	return 0;}#define HDSPM_CLOCK_SOURCE(xname, xindex) \{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \  .name = xname, \  .index = xindex, \  .info = snd_hdspm_info_clock_source, \  .get = snd_hdspm_get_clock_source, \  .put = snd_hdspm_put_clock_source \}static int hdspm_clock_source(hdspm_t * hdspm){	if (hdspm->control_register & HDSPM_ClockModeMaster) {		switch (hdspm->system_sample_rate) {		case 32000:			return 1;		case 44100:			return 2;		case 48000:			return 3;		case 64000:			return 4;		case 88200:			return 5;		case 96000:			return 6;		case 128000:			return 7;		case 176400:			return 8;		case 192000:			return 9;		default:			return 3;		}	} else {		return 0;	}}static int hdspm_set_clock_source(hdspm_t * hdspm, int mode){	int rate;	switch (mode) {	case HDSPM_CLOCK_SOURCE_AUTOSYNC:		if (hdspm_external_sample_rate(hdspm) != 0) {			hdspm->control_register &= ~HDSPM_ClockModeMaster;			hdspm_write(hdspm, HDSPM_controlRegister,				    hdspm->control_register);			return 0;		}		return -1;	case HDSPM_CLOCK_SOURCE_INTERNAL_32KHZ:		rate = 32000;		break;	case HDSPM_CLOCK_SOURCE_INTERNAL_44_1KHZ:		rate = 44100;		break;	case HDSPM_CLOCK_SOURCE_INTERNAL_48KHZ:		rate = 48000;		break;	case HDSPM_CLOCK_SOURCE_INTERNAL_64KHZ:		rate = 64000;		break;	case HDSPM_CLOCK_SOURCE_INTERNAL_88_2KHZ:		rate = 88200;		break;	case HDSPM_CLOCK_SOURCE_INTERNAL_96KHZ:		rate = 96000;		break;	case HDSPM_CLOCK_SOURCE_INTERNAL_128KHZ:		rate = 128000;		break;	case HDSPM_CLOCK_SOURCE_INTERNAL_176_4KHZ:		rate = 176400;		break;	case HDSPM_CLOCK_SOURCE_INTERNAL_192KHZ:		rate = 192000;		break;	default:		rate = 44100;	}	hdspm->control_register |= HDSPM_ClockModeMaster;	hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);	hdspm_set_rate(hdspm, rate, 1);	return 0;}static int snd_hdspm_info_clock_source(snd_kcontrol_t * kcontrol,				       snd_ctl_elem_info_t * uinfo){	static char *texts[] = { "AutoSync",		"Internal 32.0 kHz", "Internal 44.1 kHz",		    "Internal 48.0 kHz",		"Internal 64.0 kHz", "Internal 88.2 kHz",		    "Internal 96.0 kHz",		"Internal 128.0 kHz", "Internal 176.4 kHz",		    "Internal 192.0 kHz"	};	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;

⌨️ 快捷键说明

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