📄 ice1712.c
字号:
return 0;}int snd_ice1712_gpio_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){ ice1712_t *ice = snd_kcontrol_chip(kcontrol); unsigned char mask = 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) & mask ? 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); unsigned char mask = 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] ? mask : 0) ^ invert; snd_ice1712_save_gpio_status(ice); val = snd_ice1712_gpio_read(ice); nval |= val & ~mask; if (val != nval) snd_ice1712_gpio_write(ice, nval); snd_ice1712_restore_gpio_status(ice); return val != nval;}/* * rate */static int snd_ice1712_pro_internal_clock_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo){ static char *texts[] = { "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: -- */ }; uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; uinfo->count = 1; uinfo->value.enumerated.items = 14; 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_ice1712_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, 255, 255, 255, 10 }; unsigned char val; spin_lock_irq(&ice->reg_lock); if (is_spdif_master(ice)) { ucontrol->value.enumerated.item[0] = 13; } else { val = xlate[inb(ICEMT(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_ice1712_pro_internal_clock_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){ ice1712_t *ice = snd_kcontrol_chip(kcontrol); static unsigned int xrate[13] = { 8000, 9600, 11025, 12000, 1600, 22050, 24000, 32000, 44100, 48000, 64000, 88200, 96000 }; unsigned char oval; int change = 0; spin_lock_irq(&ice->reg_lock); oval = inb(ICEMT(ice, RATE)); if (ucontrol->value.enumerated.item[0] == 13) { outb(oval | ICE1712_SPDIF_MASTER, ICEMT(ice, RATE)); } else { PRO_RATE_DEFAULT = xrate[ucontrol->value.integer.value[0] % 13]; spin_unlock_irq(&ice->reg_lock); snd_ice1712_set_pro_rate(ice, PRO_RATE_DEFAULT, 1); spin_lock_irq(&ice->reg_lock); } change = inb(ICEMT(ice, RATE)) != oval; spin_unlock_irq(&ice->reg_lock); if ((oval & ICE1712_SPDIF_MASTER) != (inb(ICEMT(ice, RATE)) & ICE1712_SPDIF_MASTER)) { /* change CS8427 clock source too */ if (ice->cs8427) { snd_ice1712_cs8427_set_input_clock(ice, is_spdif_master(ice)); } /* notify ak4524 chip 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_ice1712_pro_internal_clock __devinitdata = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Multi Track Internal Clock", .info = snd_ice1712_pro_internal_clock_info, .get = snd_ice1712_pro_internal_clock_get, .put = snd_ice1712_pro_internal_clock_put};static int snd_ice1712_pro_internal_clock_default_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo){ static char *texts[] = { "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: -- */ }; uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; uinfo->count = 1; uinfo->value.enumerated.items = 13; 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_ice1712_pro_internal_clock_default_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){ int val; static unsigned int xrate[13] = { 8000, 9600, 11025, 12000, 1600, 22050, 24000, 32000, 44100, 48000, 64000, 88200, 96000 }; for (val = 0; val < 13; val++) { if (xrate[val] == PRO_RATE_DEFAULT) break; } ucontrol->value.enumerated.item[0] = val; return 0;}static int snd_ice1712_pro_internal_clock_default_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){ static unsigned int xrate[13] = { 8000, 9600, 11025, 12000, 1600, 22050, 24000, 32000, 44100, 48000, 64000, 88200, 96000 }; unsigned char oval; int change = 0; oval = PRO_RATE_DEFAULT; PRO_RATE_DEFAULT = xrate[ucontrol->value.integer.value[0] % 13]; change = PRO_RATE_DEFAULT != oval; return change;}static snd_kcontrol_new_t snd_ice1712_pro_internal_clock_default __devinitdata = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Multi Track Internal Clock Default", .info = snd_ice1712_pro_internal_clock_default_info, .get = snd_ice1712_pro_internal_clock_default_get, .put = snd_ice1712_pro_internal_clock_default_put};static int snd_ice1712_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_ice1712_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_ice1712_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_ice1712_pro_rate_locking __devinitdata = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Multi Track Rate Locking", .info = snd_ice1712_pro_rate_locking_info, .get = snd_ice1712_pro_rate_locking_get, .put = snd_ice1712_pro_rate_locking_put};static int snd_ice1712_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_ice1712_pro_rate_reset_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){ ucontrol->value.integer.value[0] = PRO_RATE_RESET; return 0;}static int snd_ice1712_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_ice1712_pro_rate_reset __devinitdata = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Multi Track Rate Reset", .info = snd_ice1712_pro_rate_reset_info, .get = snd_ice1712_pro_rate_reset_get, .put = snd_ice1712_pro_rate_reset_put};/* * routing */static int snd_ice1712_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", "H/W In 2", "H/W In 3", /* 1-4 */ "H/W In 4", "H/W In 5", "H/W In 6", "H/W In 7", /* 5-8 */ "IEC958 In L", "IEC958 In R", /* 9-10 */ "Digital Mixer", /* 11 - optional */ }; uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; uinfo->count = 1; uinfo->value.enumerated.items = snd_ctl_get_ioffidx(kcontrol, &uinfo->id) < 2 ? 12 : 11; 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_ice1712_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); unsigned int val, cval; spin_lock_irq(&ice->reg_lock); val = inw(ICEMT(ice, ROUTE_PSDOUT03)); cval = inl(ICEMT(ice, ROUTE_CAPTURE)); spin_unlock_irq(&ice->reg_lock); val >>= ((idx % 2) * 8) + ((idx / 2) * 2); val &= 3; cval >>= ((idx / 2) * 8) + ((idx % 2) * 4); if (val == 1 && idx < 2) ucontrol->value.enumerated.item[0] = 11; else if (val == 2) ucontrol->value.enumerated.item[0] = (cval & 7) + 1; else if (val == 3) ucontrol->value.enumerated.item[0] = ((cval >> 3) & 1) + 9; else ucontrol->value.enumerated.item[0] = 0; return 0;}static int snd_ice1712_pro_route_analog_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *ucontrol){ ice1712_t *ice = snd_kcontrol_chip(kcontrol); int change, shift; int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); unsigned int val, old_val, nval; /* update PSDOUT */ if (ucontrol->value.enumerated.item[0] >= 11) nval = idx < 2 ? 1 : 0; /* dig mixer (or pcm) */ else if (ucontrol->value.enumerated.item[0] >= 9) nval = 3; /* spdif in */ else if (ucontrol->value.enumerated.item[0] >= 1) nval = 2; /* analog in */ else nval = 0; /* pcm */ shift = ((idx % 2) * 8) + ((idx / 2) * 2); spin_lock_irq(&ice->reg_lock); val = old_val = inw(ICEMT(ice, ROUTE_PSDOUT03)); val &= ~(0x03 << shift); val |= nval << shift; change = val != old_val; if (change) outw(val, ICEMT(ice, ROUTE_PSDOUT03)); spin_unlock_irq(&ice->reg_lock); if (nval < 2) /* dig mixer of pcm */ return change; /* update CAPTURE */ spin_lock_irq(&ice->reg_lock); val = old_val = inl(ICEMT(ice, ROUTE_CAPTURE)); shift = ((idx / 2) * 8) + ((idx % 2) * 4); if (nval == 2) { /* analog in */ nval = ucontrol->value.enumerated.item[0] - 1; val &= ~(0x07 << shift); val |= nval << shift; } else { /* spdif in */ nval = (ucontrol->value.enumerated.item[0] - 9) << 3; val &= ~(0x08 << shift); val |= nval << shift; } if (val != old_val) { change = 1; outl(val, ICEMT(ice, ROUTE_CAPTURE)); } spin_unlock_irq(&ice->reg_lock); return change;}static int snd_ice1712_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); unsigned int val, cval; val = inw(ICEMT(ice, ROUTE_SPDOUT)); cval = (val >> (idx * 4 + 8)) & 0x0f; val = (val >> (idx * 2)) & 0x03; if (val == 1) ucontrol->value.enumerated.item[0] = 11; else if (val == 2) ucontrol->value.enumerated.item[0] = (cval & 7) + 1; else if (val == 3) ucontrol->value.enumerated.item[0] = ((cval >> 3) & 1) + 9; else ucontrol->value.enumerated.item[0] = 0; return 0;}static int snd_ice1712_pro_route_spdif_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *ucontrol){ ice1712_t *ice = snd_kcontrol_chip(kcontrol); int change, shift; int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); unsigned int val, old_val, nval; /* update SPDOUT */ spin_lock_irq(&ice->reg_lock); val = old_val = inw(ICEMT(ice, ROUTE_SPDOUT)); if (ucontrol->value.enumerated.item[0] >= 11) nval = 1; else if (ucontrol->value.enumerated.item[0] >= 9) nval = 3; else if (ucontrol->value.enumerated.item[0] >= 1) nval = 2; else nval = 0; shift = idx * 2; val &= ~(0x03 << shift); val |= nval << shift; shift = idx * 4 + 8; if (nval == 2) { nval = ucontrol->value.enumerated.item[0] - 1; val &= ~(0x07 << shift); val |= nval << shift; } else if (nval == 3) { nval = (ucontrol->value.enumerated.item[0] - 9) << 3; val &= ~(0x08 << shift); val |= nval << shift; } change = val != old_val; if (change) outw(val, ICEMT(ice, ROUTE_SPDOUT)); spin_unlock_irq(&ice->reg_lock); return change;}static snd_kcontrol_new_t snd_ice1712_mixer_pro_analog_route __devinitdata = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "H/W Playback Route", .info = snd_ice1712_pro_route_info, .get = snd_ice1712_pro_route_analog_get, .put = snd_ice1712_pro_route_analog_put,};static snd_kcontrol_new_t snd_ice1712_mixer_pro_spdif_route __devinitda
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -