📄 hdspm.c
字号:
struct snd_ctl_elem_value * ucontrol){ struct hdspm *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(struct hdspm * 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(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *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(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol){ struct hdspm *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(struct hdspm * 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(struct hdspm * 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(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *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; strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); return 0;}static int snd_hdspm_get_clock_source(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol){ struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); ucontrol->value.enumerated.item[0] = hdspm_clock_source(hdspm); return 0;}static int snd_hdspm_put_clock_source(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol){ struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); int change; int val; if (!snd_hdspm_use_is_exclusive(hdspm)) return -EBUSY; val = ucontrol->value.enumerated.item[0]; if (val < 0) val = 0; if (val > 9) val = 9; spin_lock_irq(&hdspm->lock); if (val != hdspm_clock_source(hdspm)) change = (hdspm_set_clock_source(hdspm, val) == 0) ? 1 : 0; else change = 0; spin_unlock_irq(&hdspm->lock); return change;}#define HDSPM_PREF_SYNC_REF(xname, xindex) \{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ .name = xname, \ .index = xindex, \ .info = snd_hdspm_info_pref_sync_ref, \ .get = snd_hdspm_get_pref_sync_ref, \ .put = snd_hdspm_put_pref_sync_ref \}static int hdspm_pref_sync_ref(struct hdspm * hdspm){ /* Notice that this looks at the requested sync source, not the one actually in use. */ if (hdspm->is_aes32) { switch (hdspm->control_register & HDSPM_SyncRefMask) { /* number gives AES index, except for 0 which corresponds to WordClock */ case 0: return 0; case HDSPM_SyncRef0: return 1; case HDSPM_SyncRef1: return 2; case HDSPM_SyncRef1+HDSPM_SyncRef0: return 3; case HDSPM_SyncRef2: return 4; case HDSPM_SyncRef2+HDSPM_SyncRef0: return 5; case HDSPM_SyncRef2+HDSPM_SyncRef1: return 6; case HDSPM_SyncRef2+HDSPM_SyncRef1+HDSPM_SyncRef0: return 7; case HDSPM_SyncRef3: return 8; } } else { switch (hdspm->control_register & HDSPM_SyncRefMask) { case HDSPM_SyncRef_Word: return HDSPM_SYNC_FROM_WORD; case HDSPM_SyncRef_MADI: return HDSPM_SYNC_FROM_MADI; } } return HDSPM_SYNC_FROM_WORD;}static int hdspm_set_pref_sync_ref(struct hdspm * hdspm, int pref){ hdspm->control_register &= ~HDSPM_SyncRefMask; if (hdspm->is_aes32) { switch (pref) { case 0: hdspm->control_register |= 0; break; case 1: hdspm->control_register |= HDSPM_SyncRef0; break; case 2: hdspm->control_register |= HDSPM_SyncRef1; break; case 3: hdspm->control_register |= HDSPM_SyncRef1+HDSPM_SyncRef0; break; case 4: hdspm->control_register |= HDSPM_SyncRef2; break; case 5: hdspm->control_register |= HDSPM_SyncRef2+HDSPM_SyncRef0; break; case 6: hdspm->control_register |= HDSPM_SyncRef2+HDSPM_SyncRef1; break; case 7: hdspm->control_register |= HDSPM_SyncRef2+HDSPM_SyncRef1+HDSPM_SyncRef0; break; case 8: hdspm->control_register |= HDSPM_SyncRef3; break; default: return -1; } } else { switch (pref) { case HDSPM_SYNC_FROM_MADI: hdspm->control_register |= HDSPM_SyncRef_MADI; break; case HDSPM_SYNC_FROM_WORD: hdspm->control_register |= HDSPM_SyncRef_Word; break; default: return -1; } } hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register); return 0;}static int snd_hdspm_info_pref_sync_ref(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo){ struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); if (hdspm->is_aes32) { static char *texts[] = { "Word", "AES1", "AES2", "AES3", "AES4", "AES5", "AES6", "AES7", "AES8" }; uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; uinfo->count = 1; uinfo->value.enumerated.items = 9; 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]); } else { static char *texts[] = { "Word", "MADI" }; 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_pref_sync_ref(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol){ struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); ucontrol->value.enumerated.item[0] = hdspm_pref_sync_ref(hdspm); return 0;}static int snd_hdspm_put_pref_sync_ref(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol){ struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); int change, max; unsigned int val; max = hdspm->is_aes32 ? 9 : 2; if (!snd_hdspm_use_is_exclusive(hdspm)) return -EBUSY; val = ucontrol->value.enumerated.item[0] % max; spin_lock_irq(&hdspm->lock); change = (int) val != hdspm_pref_sync_ref(hdspm); hdspm_set_pref_sync_ref(hdspm, val); spin_unlock_irq(&hdspm->lock); return change;}#define HDSPM_AUTOSYNC_REF(xname, xindex) \{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ .name = xname, \ .index = xindex, \ .access = SNDRV_CTL_ELEM_ACCESS_READ, \ .info = snd_hdspm_info_autosync_ref, \ .get = snd_hdspm_get_autosync_ref, \}static int hdspm_autosync_ref(struct hdspm * hdspm){ if (hdspm->is_aes32) { unsigned int status = hdspm_read(hdspm, HDSPM_statusRegister); unsigned int syncref = (status >> HDSPM_AES32_syncref_bit) & 0xF; if (syncref == 0) return HDSPM_AES32_AUTOSYNC_FROM_WORD; if (syncref <= 8) return syncref; return HDSPM_AES32_AUTOSYNC_FROM_NONE; } else { /* This looks at the autosync selected sync reference */ unsigned int status2 = hdspm_read(hdspm, HDSPM_statusRegister2); switch (status2 & HDSPM_SelSyncRefMask) { case HDSPM_SelSyncRef_WORD: return HDSPM_AUTOSYNC_FROM_WORD; case HDSPM_SelSyncRef_MADI: return HDSPM_AUTOSYNC_FROM_MADI; case HDSPM_SelSyncRef_NVALID: return HDSPM_AUTOSYNC_FROM_NONE; default: return 0; } return 0; }}static int snd_hdspm_info_autosync_ref(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo){ struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); if (hdspm->is_aes32) { static char *texts[] = { "WordClock", "AES1", "AES2", "AES3", "AES4", "AES5", "AES6", "AES7", "AES8", "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]); } else { static char *texts[] = { "WordClock", "MADI", "None" }; uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; uinfo->count = 1; uinfo->value.enumerated.items = 3; 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 + -