📄 hdsp.c
字号:
snd_hdsp_midi_output_trigger (substream, 0); hmidi = (hdsp_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_hdsp_midi_output ={ .open = snd_hdsp_midi_output_open, .close = snd_hdsp_midi_output_close, .trigger = snd_hdsp_midi_output_trigger,};static snd_rawmidi_ops_t snd_hdsp_midi_input ={ .open = snd_hdsp_midi_input_open, .close = snd_hdsp_midi_input_close, .trigger = snd_hdsp_midi_input_trigger,};static int __devinit snd_hdsp_create_midi (snd_card_t *card, hdsp_t *hdsp, int id){ char buf[32]; hdsp->midi[id].id = id; hdsp->midi[id].rmidi = NULL; hdsp->midi[id].input = NULL; hdsp->midi[id].output = NULL; hdsp->midi[id].hdsp = hdsp; hdsp->midi[id].istimer = 0; hdsp->midi[id].pending = 0; spin_lock_init (&hdsp->midi[id].lock); sprintf (buf, "%s MIDI %d", card->shortname, id+1); if (snd_rawmidi_new (card, buf, id, 1, 1, &hdsp->midi[id].rmidi) < 0) return -1; sprintf (hdsp->midi[id].rmidi->name, "%s MIDI %d", card->id, id+1); hdsp->midi[id].rmidi->private_data = &hdsp->midi[id]; snd_rawmidi_set_ops (hdsp->midi[id].rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &snd_hdsp_midi_output); snd_rawmidi_set_ops (hdsp->midi[id].rmidi, SNDRV_RAWMIDI_STREAM_INPUT, &snd_hdsp_midi_input); hdsp->midi[id].rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT | SNDRV_RAWMIDI_INFO_INPUT | SNDRV_RAWMIDI_INFO_DUPLEX; return 0;}/*----------------------------------------------------------------------------- Control Interface ----------------------------------------------------------------------------*/static u32 snd_hdsp_convert_from_aes(snd_aes_iec958_t *aes){ u32 val = 0; val |= (aes->status[0] & IEC958_AES0_PROFESSIONAL) ? HDSP_SPDIFProfessional : 0; val |= (aes->status[0] & IEC958_AES0_NONAUDIO) ? HDSP_SPDIFNonAudio : 0; if (val & HDSP_SPDIFProfessional) val |= (aes->status[0] & IEC958_AES0_PRO_EMPHASIS_5015) ? HDSP_SPDIFEmphasis : 0; else val |= (aes->status[0] & IEC958_AES0_CON_EMPHASIS_5015) ? HDSP_SPDIFEmphasis : 0; return val;}static void snd_hdsp_convert_to_aes(snd_aes_iec958_t *aes, u32 val){ aes->status[0] = ((val & HDSP_SPDIFProfessional) ? IEC958_AES0_PROFESSIONAL : 0) | ((val & HDSP_SPDIFNonAudio) ? IEC958_AES0_NONAUDIO : 0); if (val & HDSP_SPDIFProfessional) aes->status[0] |= (val & HDSP_SPDIFEmphasis) ? IEC958_AES0_PRO_EMPHASIS_5015 : 0; else aes->status[0] |= (val & HDSP_SPDIFEmphasis) ? IEC958_AES0_CON_EMPHASIS_5015 : 0;}static int snd_hdsp_control_spdif_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo){ uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; uinfo->count = 1; return 0;}static int snd_hdsp_control_spdif_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){ hdsp_t *hdsp = snd_kcontrol_chip(kcontrol); snd_hdsp_convert_to_aes(&ucontrol->value.iec958, hdsp->creg_spdif); return 0;}static int snd_hdsp_control_spdif_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){ hdsp_t *hdsp = snd_kcontrol_chip(kcontrol); int change; u32 val; val = snd_hdsp_convert_from_aes(&ucontrol->value.iec958); spin_lock_irq(&hdsp->lock); change = val != hdsp->creg_spdif; hdsp->creg_spdif = val; spin_unlock_irq(&hdsp->lock); return change;}static int snd_hdsp_control_spdif_stream_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo){ uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; uinfo->count = 1; return 0;}static int snd_hdsp_control_spdif_stream_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){ hdsp_t *hdsp = snd_kcontrol_chip(kcontrol); snd_hdsp_convert_to_aes(&ucontrol->value.iec958, hdsp->creg_spdif_stream); return 0;}static int snd_hdsp_control_spdif_stream_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){ hdsp_t *hdsp = snd_kcontrol_chip(kcontrol); int change; u32 val; val = snd_hdsp_convert_from_aes(&ucontrol->value.iec958); spin_lock_irq(&hdsp->lock); change = val != hdsp->creg_spdif_stream; hdsp->creg_spdif_stream = val; hdsp->control_register &= ~(HDSP_SPDIFProfessional | HDSP_SPDIFNonAudio | HDSP_SPDIFEmphasis); hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register |= val); spin_unlock_irq(&hdsp->lock); return change;}static int snd_hdsp_control_spdif_mask_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo){ uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; uinfo->count = 1; return 0;}static int snd_hdsp_control_spdif_mask_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){ ucontrol->value.iec958.status[0] = kcontrol->private_value; return 0;}#define HDSP_SPDIF_IN(xname, xindex) \{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ .name = xname, \ .index = xindex, \ .info = snd_hdsp_info_spdif_in, \ .get = snd_hdsp_get_spdif_in, \ .put = snd_hdsp_put_spdif_in }static unsigned int hdsp_spdif_in(hdsp_t *hdsp){ return hdsp_decode_spdif_in(hdsp->control_register & HDSP_SPDIFInputMask);}static int hdsp_set_spdif_input(hdsp_t *hdsp, int in){ hdsp->control_register &= ~HDSP_SPDIFInputMask; hdsp->control_register |= hdsp_encode_spdif_in(in); hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register); return 0;}static int snd_hdsp_info_spdif_in(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo){ static char *texts[4] = {"Optical", "Coaxial", "Internal", "AES"}; hdsp_t *hdsp = snd_kcontrol_chip(kcontrol); uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; uinfo->count = 1; uinfo->value.enumerated.items = ((hdsp->io_type == H9632) ? 4 : 3); if (uinfo->value.enumerated.item > ((hdsp->io_type == H9632) ? 3 : 2)) uinfo->value.enumerated.item = ((hdsp->io_type == H9632) ? 3 : 2); strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); return 0;}static int snd_hdsp_get_spdif_in(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){ hdsp_t *hdsp = snd_kcontrol_chip(kcontrol); ucontrol->value.enumerated.item[0] = hdsp_spdif_in(hdsp); return 0;}static int snd_hdsp_put_spdif_in(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){ hdsp_t *hdsp = snd_kcontrol_chip(kcontrol); int change; unsigned int val; if (!snd_hdsp_use_is_exclusive(hdsp)) return -EBUSY; val = ucontrol->value.enumerated.item[0] % ((hdsp->io_type == H9632) ? 4 : 3); spin_lock_irq(&hdsp->lock); change = val != hdsp_spdif_in(hdsp); if (change) hdsp_set_spdif_input(hdsp, val); spin_unlock_irq(&hdsp->lock); return change;}#define HDSP_SPDIF_OUT(xname, xindex) \{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ .info = snd_hdsp_info_spdif_bits, \ .get = snd_hdsp_get_spdif_out, .put = snd_hdsp_put_spdif_out }static int hdsp_spdif_out(hdsp_t *hdsp){ return (hdsp->control_register & HDSP_SPDIFOpticalOut) ? 1 : 0;}static int hdsp_set_spdif_output(hdsp_t *hdsp, int out){ if (out) hdsp->control_register |= HDSP_SPDIFOpticalOut; else hdsp->control_register &= ~HDSP_SPDIFOpticalOut; hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register); return 0;}static int snd_hdsp_info_spdif_bits(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo){ uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; uinfo->count = 1; uinfo->value.integer.min = 0; uinfo->value.integer.max = 1; return 0;}static int snd_hdsp_get_spdif_out(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){ hdsp_t *hdsp = snd_kcontrol_chip(kcontrol); ucontrol->value.integer.value[0] = hdsp_spdif_out(hdsp); return 0;}static int snd_hdsp_put_spdif_out(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){ hdsp_t *hdsp = snd_kcontrol_chip(kcontrol); int change; unsigned int val; if (!snd_hdsp_use_is_exclusive(hdsp)) return -EBUSY; val = ucontrol->value.integer.value[0] & 1; spin_lock_irq(&hdsp->lock); change = (int)val != hdsp_spdif_out(hdsp); hdsp_set_spdif_output(hdsp, val); spin_unlock_irq(&hdsp->lock); return change;}#define HDSP_SPDIF_PROFESSIONAL(xname, xindex) \{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ .info = snd_hdsp_info_spdif_bits, \ .get = snd_hdsp_get_spdif_professional, .put = snd_hdsp_put_spdif_professional }static int hdsp_spdif_professional(hdsp_t *hdsp){ return (hdsp->control_register & HDSP_SPDIFProfessional) ? 1 : 0;}static int hdsp_set_spdif_professional(hdsp_t *hdsp, int val){ if (val) hdsp->control_register |= HDSP_SPDIFProfessional; else hdsp->control_register &= ~HDSP_SPDIFProfessional; hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register); return 0;}static int snd_hdsp_get_spdif_professional(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){ hdsp_t *hdsp = snd_kcontrol_chip(kcontrol); ucontrol->value.integer.value[0] = hdsp_spdif_professional(hdsp); return 0;}static int snd_hdsp_put_spdif_professional(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){ hdsp_t *hdsp = snd_kcontrol_chip(kcontrol); int change; unsigned int val; if (!snd_hdsp_use_is_exclusive(hdsp)) return -EBUSY; val = ucontrol->value.integer.value[0] & 1; spin_lock_irq(&hdsp->lock); change = (int)val != hdsp_spdif_professional(hdsp); hdsp_set_spdif_professional(hdsp, val); spin_unlock_irq(&hdsp->lock); return change;}#define HDSP_SPDIF_EMPHASIS(xname, xindex) \{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ .info = snd_hdsp_info_spdif_bits, \ .get = snd_hdsp_get_spdif_emphasis, .put = snd_hdsp_put_spdif_emphasis }static int hdsp_spdif_emphasis(hdsp_t *hdsp){ return (hdsp->control_register & HDSP_SPDIFEmphasis) ? 1 : 0;}static int hdsp_set_spdif_emphasis(hdsp_t *hdsp, int val){ if (val) hdsp->control_register |= HDSP_SPDIFEmphasis; else hdsp->control_register &= ~HDSP_SPDIFEmphasis; hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register); return 0;}static int snd_hdsp_get_spdif_emphasis(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){ hdsp_t *hdsp = snd_kcontrol_chip(kcontrol); ucontrol->value.integer.value[0] = hdsp_spdif_emphasis(hdsp); return 0;}static int snd_hdsp_put_spdif_emphasis(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){ hdsp_t *hdsp = snd_kcontrol_chip(kcontrol); int change; unsigned int val; if (!snd_hdsp_use_is_exclusive(hdsp)) return -EBUSY; val = ucontrol->value.integer.value[0] & 1; spin_lock_irq(&hdsp->lock); change = (int)val != hdsp_spdif_emphasis(hdsp); hdsp_set_spdif_emphasis(hdsp, val); spin_unlock_irq(&hdsp->lock); return change;}#define HDSP_SPDIF_NON_AUDIO(xname, xindex) \{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ .info = snd_hdsp_info_spdif_bits, \ .get = snd_hdsp_get_spdif_nonaudio, .put = snd_hdsp_put_spdif_nonaudio }static int hdsp_spdif_nonaudio(hdsp_t *hdsp){ return (hdsp->control_register & HDSP_SPDIFNonAudio) ? 1 : 0;}static int hdsp_set_spdif_nonaudio(hdsp_t *hdsp, int val){ if (val) hdsp->control_register |= HDSP_SPDIFNonAudio; else hdsp->control_register &= ~HDSP_SPDIFNonAudio; hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register); return 0;}static int snd_hdsp_get_spdif_nonaudio(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){ hdsp_t *hdsp = snd_kcontrol_chip(kcontrol); ucontrol->value.integer.value[0] = hdsp_spdif_nonaudio(hdsp); return 0;}static int snd_hdsp_put_spdif_nonaudio(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){ hdsp_t *hdsp = snd_kcontrol_chip(kcontrol); int change; unsigned int val; if (!snd_hdsp_use_is_exclusive(hdsp)) return -EBUSY; val = ucontrol->value.integer.value[0] & 1; spin_lock_irq(&hdsp->lock); change = (int)val != hdsp_spdif_nonaudio(hdsp); hdsp_set_spdif_nonaudio(hdsp, val); spin_unlock_irq(&hdsp->lock); return change;}#define HDSP_SPDIF_SAMPLE_RATE(xname, xindex) \{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ .name = xname, \ .index = xindex, \ .access = SNDRV_CTL_ELEM_ACCESS_READ, \ .info = snd_hdsp_info_spdif_sample_rate, \ .get = snd_hdsp_get_spdif_sample_rate \}static int snd_hdsp_info_spdif_sample_rate(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo){ static char *texts[] = {"32000", "44100", "48000", "64000", "88200", "96000", "None", "128000", "176400", "192000"}; hdsp_t *hdsp = snd_kcontrol_chip(kcontrol); uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; uinfo->count = 1; uinfo->value.enumerated.items = (hdsp->io_type == H9632) ? 10 : 7; 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_hdsp_get_spdif_sample_rate(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){ hdsp_t *hdsp = snd_kcontrol_chip(kcontrol); switch (hdsp_spdif_sample_rate(hdsp)) { 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] = 7;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -