📄 hdspm.c
字号:
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 + -