📄 ice1724.c
字号:
static void decode_spdif_bits(struct snd_aes_iec958 *diga, unsigned int val){ memset(diga->status, 0, sizeof(diga->status)); diga->status[0] = val & 0x03; /* professional, non-audio */ if (val & 0x01) { /* professional */ if (val & (1U << 3)) diga->status[0] |= IEC958_AES0_PRO_EMPHASIS_5015; switch ((val >> 12) & 0x7) { case 0: break; case 2: diga->status[0] |= IEC958_AES0_PRO_FS_32000; break; default: diga->status[0] |= IEC958_AES0_PRO_FS_48000; break; } } else { /* consumer */ diga->status[0] |= val & (1U << 2); /* copyright */ if (val & (1U << 3)) diga->status[0] |= IEC958_AES0_CON_EMPHASIS_5015; diga->status[1] |= (val >> 4) & 0x3f; /* category */ diga->status[3] |= (val >> 12) & 0x07; /* fs */ }}static int snd_vt1724_spdif_default_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol){ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); unsigned int val; val = inw(ICEMT1724(ice, SPDIF_CTRL)); decode_spdif_bits(&ucontrol->value.iec958, val); return 0;}static int snd_vt1724_spdif_default_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol){ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); unsigned int val, old; val = encode_spdif_bits(&ucontrol->value.iec958); spin_lock_irq(&ice->reg_lock); old = inw(ICEMT1724(ice, SPDIF_CTRL)); if (val != old) update_spdif_bits(ice, val); spin_unlock_irq(&ice->reg_lock); return (val != old);}static struct snd_kcontrol_new snd_vt1724_spdif_default __devinitdata ={ .iface = SNDRV_CTL_ELEM_IFACE_PCM, .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT), .info = snd_vt1724_spdif_info, .get = snd_vt1724_spdif_default_get, .put = snd_vt1724_spdif_default_put};static int snd_vt1724_spdif_maskc_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol){ ucontrol->value.iec958.status[0] = IEC958_AES0_NONAUDIO | IEC958_AES0_PROFESSIONAL | IEC958_AES0_CON_NOT_COPYRIGHT | IEC958_AES0_CON_EMPHASIS; ucontrol->value.iec958.status[1] = IEC958_AES1_CON_ORIGINAL | IEC958_AES1_CON_CATEGORY; ucontrol->value.iec958.status[3] = IEC958_AES3_CON_FS; return 0;}static int snd_vt1724_spdif_maskp_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol){ ucontrol->value.iec958.status[0] = IEC958_AES0_NONAUDIO | IEC958_AES0_PROFESSIONAL | IEC958_AES0_PRO_FS | IEC958_AES0_PRO_EMPHASIS; return 0;}static struct snd_kcontrol_new snd_vt1724_spdif_maskc __devinitdata ={ .access = SNDRV_CTL_ELEM_ACCESS_READ, .iface = SNDRV_CTL_ELEM_IFACE_PCM, .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,CON_MASK), .info = snd_vt1724_spdif_info, .get = snd_vt1724_spdif_maskc_get,};static struct snd_kcontrol_new snd_vt1724_spdif_maskp __devinitdata ={ .access = SNDRV_CTL_ELEM_ACCESS_READ, .iface = SNDRV_CTL_ELEM_IFACE_PCM, .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,PRO_MASK), .info = snd_vt1724_spdif_info, .get = snd_vt1724_spdif_maskp_get,};static int snd_vt1724_spdif_sw_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *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_vt1724_spdif_sw_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol){ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); ucontrol->value.integer.value[0] = inb(ICEREG1724(ice, SPDIF_CFG)) & VT1724_CFG_SPDIF_OUT_EN ? 1 : 0; return 0;}static int snd_vt1724_spdif_sw_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol){ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); unsigned char old, val; spin_lock_irq(&ice->reg_lock); old = val = inb(ICEREG1724(ice, SPDIF_CFG)); val &= ~VT1724_CFG_SPDIF_OUT_EN; if (ucontrol->value.integer.value[0]) val |= VT1724_CFG_SPDIF_OUT_EN; if (old != val) outb(val, ICEREG1724(ice, SPDIF_CFG)); spin_unlock_irq(&ice->reg_lock); return old != val;}static struct snd_kcontrol_new snd_vt1724_spdif_switch __devinitdata ={ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, /* FIXME: the following conflict with IEC958 Playback Route */ // .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,SWITCH), .name = SNDRV_CTL_NAME_IEC958("Output ",NONE,SWITCH), .info = snd_vt1724_spdif_sw_info, .get = snd_vt1724_spdif_sw_get, .put = snd_vt1724_spdif_sw_put};#if 0 /* NOT USED YET *//* * GPIO access from extern */int snd_vt1724_gpio_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo){ uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; uinfo->count = 1; uinfo->value.integer.min = 0; uinfo->value.integer.max = 1; return 0;}int snd_vt1724_gpio_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol){ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); int shift = kcontrol->private_value & 0xff; int invert = (kcontrol->private_value & (1<<24)) ? 1 : 0; snd_ice1712_save_gpio_status(ice); ucontrol->value.integer.value[0] = (snd_ice1712_gpio_read(ice) & (1 << shift) ? 1 : 0) ^ invert; snd_ice1712_restore_gpio_status(ice); return 0;}int snd_ice1712_gpio_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol){ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); int shift = kcontrol->private_value & 0xff; int invert = (kcontrol->private_value & (1<<24)) ? mask : 0; unsigned int val, nval; if (kcontrol->private_value & (1 << 31)) return -EPERM; nval = (ucontrol->value.integer.value[0] ? (1 << shift) : 0) ^ invert; snd_ice1712_save_gpio_status(ice); val = snd_ice1712_gpio_read(ice); nval |= val & ~(1 << shift); if (val != nval) snd_ice1712_gpio_write(ice, nval); snd_ice1712_restore_gpio_status(ice); return val != nval;}#endif /* NOT USED YET *//* * rate */static int snd_vt1724_pro_internal_clock_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo){ static char *texts_1724[] = { "8000", /* 0: 6 */ "9600", /* 1: 3 */ "11025", /* 2: 10 */ "12000", /* 3: 2 */ "16000", /* 4: 5 */ "22050", /* 5: 9 */ "24000", /* 6: 1 */ "32000", /* 7: 4 */ "44100", /* 8: 8 */ "48000", /* 9: 0 */ "64000", /* 10: 15 */ "88200", /* 11: 11 */ "96000", /* 12: 7 */ "176400", /* 13: 12 */ "192000", /* 14: 14 */ "IEC958 Input", /* 15: -- */ }; static char *texts_1720[] = { "8000", /* 0: 6 */ "9600", /* 1: 3 */ "11025", /* 2: 10 */ "12000", /* 3: 2 */ "16000", /* 4: 5 */ "22050", /* 5: 9 */ "24000", /* 6: 1 */ "32000", /* 7: 4 */ "44100", /* 8: 8 */ "48000", /* 9: 0 */ "64000", /* 10: 15 */ "88200", /* 11: 11 */ "96000", /* 12: 7 */ "IEC958 Input", /* 13: -- */ }; struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; uinfo->count = 1; uinfo->value.enumerated.items = ice->vt1720 ? 14 : 16; if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1; strcpy(uinfo->value.enumerated.name, ice->vt1720 ? texts_1720[uinfo->value.enumerated.item] : texts_1724[uinfo->value.enumerated.item]); return 0;}static int snd_vt1724_pro_internal_clock_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol){ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); static unsigned char xlate[16] = { 9, 6, 3, 1, 7, 4, 0, 12, 8, 5, 2, 11, 13, 255, 14, 10 }; unsigned char val; spin_lock_irq(&ice->reg_lock); if (is_spdif_master(ice)) { ucontrol->value.enumerated.item[0] = ice->vt1720 ? 13 : 15; } else { val = xlate[inb(ICEMT1724(ice, RATE)) & 15]; if (val == 255) { snd_BUG(); val = 0; } ucontrol->value.enumerated.item[0] = val; } spin_unlock_irq(&ice->reg_lock); return 0;}static int snd_vt1724_pro_internal_clock_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol){ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); unsigned char oval; int rate; int change = 0; int spdif = ice->vt1720 ? 13 : 15; spin_lock_irq(&ice->reg_lock); oval = inb(ICEMT1724(ice, RATE)); if (ucontrol->value.enumerated.item[0] == spdif) { outb(oval | VT1724_SPDIF_MASTER, ICEMT1724(ice, RATE)); } else { rate = rates[ucontrol->value.integer.value[0] % 15]; if (rate <= get_max_rate(ice)) { PRO_RATE_DEFAULT = rate; spin_unlock_irq(&ice->reg_lock); snd_vt1724_set_pro_rate(ice, PRO_RATE_DEFAULT, 1); spin_lock_irq(&ice->reg_lock); } } change = inb(ICEMT1724(ice, RATE)) != oval; spin_unlock_irq(&ice->reg_lock); if ((oval & VT1724_SPDIF_MASTER) != (inb(ICEMT1724(ice, RATE)) & VT1724_SPDIF_MASTER)) { /* notify akm chips as well */ if (is_spdif_master(ice)) { unsigned int i; for (i = 0; i < ice->akm_codecs; i++) { if (ice->akm[i].ops.set_rate_val) ice->akm[i].ops.set_rate_val(&ice->akm[i], 0); } } } return change;}static struct snd_kcontrol_new snd_vt1724_pro_internal_clock __devinitdata = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Multi Track Internal Clock", .info = snd_vt1724_pro_internal_clock_info, .get = snd_vt1724_pro_internal_clock_get, .put = snd_vt1724_pro_internal_clock_put};static int snd_vt1724_pro_rate_locking_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *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_vt1724_pro_rate_locking_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol){ ucontrol->value.integer.value[0] = PRO_RATE_LOCKED; return 0;}static int snd_vt1724_pro_rate_locking_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol){ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); int change = 0, nval; nval = ucontrol->value.integer.value[0] ? 1 : 0; spin_lock_irq(&ice->reg_lock); change = PRO_RATE_LOCKED != nval; PRO_RATE_LOCKED = nval; spin_unlock_irq(&ice->reg_lock); return change;}static struct snd_kcontrol_new snd_vt1724_pro_rate_locking __devinitdata = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Multi Track Rate Locking", .info = snd_vt1724_pro_rate_locking_info, .get = snd_vt1724_pro_rate_locking_get, .put = snd_vt1724_pro_rate_locking_put};static int snd_vt1724_pro_rate_reset_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *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_vt1724_pro_rate_reset_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol){ ucontrol->value.integer.value[0] = PRO_RATE_RESET ? 1 : 0; return 0;}static int snd_vt1724_pro_rate_reset_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol){ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); int change = 0, nval; nval = ucontrol->value.integer.value[0] ? 1 : 0; spin_lock_irq(&ice->reg_lock); change = PRO_RATE_RESET != nval; PRO_RATE_RESET = nval; spin_unlock_irq(&ice->reg_lock); return change;}static struct snd_kcontrol_new snd_vt1724_pro_rate_reset __devinitdata = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Multi Track Rate Reset", .info = snd_vt1724_pro_rate_reset_info, .get = snd_vt1724_pro_rate_reset_get, .put = snd_vt1724_pro_rate_reset_put};/* * routing */static int snd_vt1724_pro_route_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo){ static char *texts[] = { "PCM Out", /* 0 */ "H/W In 0", "H/W In 1", /* 1-2 */ "IEC958 In L", "IEC958 In R", /* 3-4 */ }; uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; uinfo->count = 1; uinfo->value.enumerated.items = 5; 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 inline int analog_route_shift(int idx){ return (idx % 2) * 12 + ((idx / 2) * 3) + 8;}static inline int digital_route_shift(int idx){ return idx * 3;}static int get_route_val(struct snd_ice1712 *ice, int shift){ unsigned long val; unsigned char eitem; static unsigned char xlate[8] = { 0, 255, 1, 2, 255, 255, 3, 4, }; val = inl(ICEMT1724(ice, ROUTE_PLAYBACK)); val >>= shift; val &= 7; //we now have 3 bits per output eitem = xlate[val]; if (eitem == 255) { snd_BUG(); return 0; } return eitem;}static int put_route_val(struct snd_ice1712 *ice, unsigned int val, int shift){ unsigned int old_val, nval; int change;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -