📄 ice1724.c
字号:
return 0;}static int snd_vt1724_spdif_maskp_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){ ucontrol->value.iec958.status[0] = IEC958_AES0_NONAUDIO | IEC958_AES0_PROFESSIONAL | IEC958_AES0_PRO_FS | IEC958_AES0_PRO_EMPHASIS; return 0;}static snd_kcontrol_new_t snd_vt1724_spdif_maskc __devinitdata ={ .access = SNDRV_CTL_ELEM_ACCESS_READ, .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,CON_MASK), .info = snd_vt1724_spdif_info, .get = snd_vt1724_spdif_maskc_get,};static snd_kcontrol_new_t snd_vt1724_spdif_maskp __devinitdata ={ .access = SNDRV_CTL_ELEM_ACCESS_READ, .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .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(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_vt1724_spdif_sw_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){ ice1712_t *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(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){ ice1712_t *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 snd_kcontrol_new_t 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 = "IEC958 Output 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(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;}int snd_vt1724_gpio_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){ ice1712_t *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(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){ ice1712_t *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(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * 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: -- */ }; ice1712_t *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(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){ ice1712_t *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(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){ ice1712_t *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 snd_kcontrol_new_t 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(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_vt1724_pro_rate_locking_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){ ucontrol->value.integer.value[0] = PRO_RATE_LOCKED; return 0;}static int snd_vt1724_pro_rate_locking_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){ ice1712_t *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 snd_kcontrol_new_t 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(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_vt1724_pro_rate_reset_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){ ucontrol->value.integer.value[0] = PRO_RATE_RESET ? 1 : 0; return 0;}static int snd_vt1724_pro_rate_reset_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){ ice1712_t *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 snd_kcontrol_new_t 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(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * 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(ice1712_t *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(ice1712_t *ice, unsigned int val, int shift){ unsigned int old_val, nval; int change; static unsigned char xroute[8] = { 0, /* PCM */ 2, /* PSDIN0 Left */ 3, /* PSDIN0 Right */ 6, /* SPDIN Left */ 7, /* SPDIN Right */ }; nval = xroute[val % 5]; val = old_val = inl(ICEMT1724(ice, ROUTE_PLAYBACK)); val &= ~(0x07 << shift); val |= nval << shift; change = val != old_val; if (change) outl(val, ICEMT1724(ice, ROUTE_PLAYBACK)); return change;}static int snd_vt1724_pro_route_analog_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *ucontrol){ ice1712_t *ice = snd_kcontrol_chip(kcontrol); int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); ucontrol->value.enumerated.item[0] = get_route_val(ice, analog_route_shift(idx)); return 0;}static int snd_vt1724_pro_route_analog_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *ucontrol){ ice1712_t *ice = snd_kcontrol_chip(kcontrol); int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); return put_route_val(ice, ucontrol->value.enumerated.item[0], analog_route_shift(idx));}static int snd_vt1724_pro_route_spdif_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *ucontrol){ ice1712_t *ice = snd_kcontrol_chip(kcontrol); int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); ucontrol->value.enumerated.item[0] = get_route_val(ice, digital_route_shift(idx)); return 0;}static int snd_vt1724_pro_route_spdif_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *ucontrol){ ice1712_t *ice = snd_kcontrol_chip(kcontrol); int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); return put_route_val(ice, ucontrol->value.enumerated.item[0], digital_route_shift(idx));}static snd_kcontrol_new_t snd_vt1724_mixer_pro_analog_route __devinitdata = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "H/W Playback Route", .info = snd_vt1724_pro_route_info, .get = snd_vt1724_pro_route_analog_get, .put = snd_vt1724_pro_route_analog_put,};static snd_kcontrol_new_t snd_vt1724_mixer_pro_spdif_route __devinitdata = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Route", .info = snd_vt1724_pro_route_info, .get = snd_vt1724_pro_route_spdif_get, .put = snd_vt1724_pro_route_spdif_put, .count = 2,};static int snd_vt1724_pro_peak_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo){ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; uinfo->count = 22; /* FIXME: for compatibility with ice1712... */ uinfo->value.integer.min = 0; uinfo->value.integer.max = 255; return 0;}static int snd_vt1724_pro_peak_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){ ice1712_t *ice = snd_kcontrol_chip(kcontrol); int idx; spin_lock_irq(&ice->reg_lock); for (idx = 0; idx < 22; idx++) { outb(idx, ICEMT1724(ice, MONITOR_PEAKINDEX)); ucontrol->value.integer.value[idx] = inb(ICEMT1724(ice, MONITOR_PEAKDATA)); } spin_unlock_irq(&ice->reg_lock); return 0;}static snd_kcontrol_new_t snd_vt1724_mixer_pro_peak __devinitdata = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Multi Track Peak", .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, .info = snd_vt1724_pro_peak_info,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -