📄 ice1712.c
字号:
ice1712_t *ice = snd_kcontrol_chip(kcontrol); int index = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id) + kcontrol->private_value; spin_lock_irq(&ice->reg_lock); ucontrol->value.integer.value[0] = !((ice->pro_volumes[index] >> 15) & 1); ucontrol->value.integer.value[1] = !((ice->pro_volumes[index] >> 31) & 1); spin_unlock_irq(&ice->reg_lock); return 0;}static int snd_ice1712_pro_mixer_switch_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){ ice1712_t *ice = snd_kcontrol_chip(kcontrol); int index = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id) + kcontrol->private_value; unsigned int nval, change; nval = (ucontrol->value.integer.value[0] ? 0 : 0x00008000) | (ucontrol->value.integer.value[1] ? 0 : 0x80000000); spin_lock_irq(&ice->reg_lock); nval |= ice->pro_volumes[index] & ~0x80008000; change = nval != ice->pro_volumes[index]; ice->pro_volumes[index] = nval; snd_ice1712_update_volume(ice, index); spin_unlock_irq(&ice->reg_lock); return change;}static int snd_ice1712_pro_mixer_volume_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo){ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; uinfo->count = 2; uinfo->value.integer.min = 0; uinfo->value.integer.max = 96; return 0;}static int snd_ice1712_pro_mixer_volume_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){ ice1712_t *ice = snd_kcontrol_chip(kcontrol); int index = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id) + kcontrol->private_value; spin_lock_irq(&ice->reg_lock); ucontrol->value.integer.value[0] = (ice->pro_volumes[index] >> 0) & 127; ucontrol->value.integer.value[1] = (ice->pro_volumes[index] >> 16) & 127; spin_unlock_irq(&ice->reg_lock); return 0;}static int snd_ice1712_pro_mixer_volume_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){ ice1712_t *ice = snd_kcontrol_chip(kcontrol); int index = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id) + kcontrol->private_value; unsigned int nval, change; nval = (ucontrol->value.integer.value[0] & 127) | ((ucontrol->value.integer.value[1] & 127) << 16); spin_lock_irq(&ice->reg_lock); nval |= ice->pro_volumes[index] & ~0x007f007f; change = nval != ice->pro_volumes[index]; ice->pro_volumes[index] = nval; snd_ice1712_update_volume(ice, index); spin_unlock_irq(&ice->reg_lock); return change;}static snd_kcontrol_new_t snd_ice1712_multi_playback_ctrls[] __devinitdata = { { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Multi Playback Switch", .info = snd_ice1712_pro_mixer_switch_info, .get = snd_ice1712_pro_mixer_switch_get, .put = snd_ice1712_pro_mixer_switch_put, .private_value = 0, .count = 10, }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Multi Playback Volume", .info = snd_ice1712_pro_mixer_volume_info, .get = snd_ice1712_pro_mixer_volume_get, .put = snd_ice1712_pro_mixer_volume_put, .private_value = 0, .count = 10, },};static snd_kcontrol_new_t snd_ice1712_multi_capture_analog_switch __devinitdata = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "H/W Multi Capture Switch", .info = snd_ice1712_pro_mixer_switch_info, .get = snd_ice1712_pro_mixer_switch_get, .put = snd_ice1712_pro_mixer_switch_put, .private_value = 10,};static snd_kcontrol_new_t snd_ice1712_multi_capture_spdif_switch __devinitdata = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = SNDRV_CTL_NAME_IEC958("Multi ",CAPTURE,SWITCH), .info = snd_ice1712_pro_mixer_switch_info, .get = snd_ice1712_pro_mixer_switch_get, .put = snd_ice1712_pro_mixer_switch_put, .private_value = 18, .count = 2,};static snd_kcontrol_new_t snd_ice1712_multi_capture_analog_volume __devinitdata = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "H/W Multi Capture Volume", .info = snd_ice1712_pro_mixer_volume_info, .get = snd_ice1712_pro_mixer_volume_get, .put = snd_ice1712_pro_mixer_volume_put, .private_value = 10,};static snd_kcontrol_new_t snd_ice1712_multi_capture_spdif_volume __devinitdata = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = SNDRV_CTL_NAME_IEC958("Multi ",CAPTURE,VOLUME), .info = snd_ice1712_pro_mixer_volume_info, .get = snd_ice1712_pro_mixer_volume_get, .put = snd_ice1712_pro_mixer_volume_put, .private_value = 18, .count = 2,};static int __devinit snd_ice1712_build_pro_mixer(ice1712_t *ice){ snd_card_t * card = ice->card; unsigned int idx; int err; /* multi-channel mixer */ for (idx = 0; idx < ARRAY_SIZE(snd_ice1712_multi_playback_ctrls); idx++) { err = snd_ctl_add(card, snd_ctl_new1(&snd_ice1712_multi_playback_ctrls[idx], ice)); if (err < 0) return err; } if (ice->num_total_adcs > 0) { snd_kcontrol_new_t tmp = snd_ice1712_multi_capture_analog_switch; tmp.count = ice->num_total_adcs; err = snd_ctl_add(card, snd_ctl_new1(&tmp, ice)); if (err < 0) return err; } err = snd_ctl_add(card, snd_ctl_new1(&snd_ice1712_multi_capture_spdif_switch, ice)); if (err < 0) return err; if (ice->num_total_adcs > 0) { snd_kcontrol_new_t tmp = snd_ice1712_multi_capture_analog_volume; tmp.count = ice->num_total_adcs; err = snd_ctl_add(card, snd_ctl_new1(&tmp, ice)); if (err < 0) return err; } err = snd_ctl_add(card, snd_ctl_new1(&snd_ice1712_multi_capture_spdif_volume, ice)); if (err < 0) return err; /* initialize volumes */ for (idx = 0; idx < 10; idx++) { ice->pro_volumes[idx] = 0x80008000; /* mute */ snd_ice1712_update_volume(ice, idx); } for (idx = 10; idx < 10 + ice->num_total_adcs; idx++) { ice->pro_volumes[idx] = 0x80008000; /* mute */ snd_ice1712_update_volume(ice, idx); } for (idx = 18; idx < 20; idx++) { ice->pro_volumes[idx] = 0x80008000; /* mute */ snd_ice1712_update_volume(ice, idx); } return 0;}static void snd_ice1712_mixer_free_ac97(ac97_t *ac97){ ice1712_t *ice = ac97->private_data; ice->ac97 = NULL;}static int __devinit snd_ice1712_ac97_mixer(ice1712_t * ice){ int err, bus_num = 0; ac97_template_t ac97; ac97_bus_t *pbus; static ac97_bus_ops_t con_ops = { .write = snd_ice1712_ac97_write, .read = snd_ice1712_ac97_read, }; static ac97_bus_ops_t pro_ops = { .write = snd_ice1712_pro_ac97_write, .read = snd_ice1712_pro_ac97_read, }; if (ice_has_con_ac97(ice)) { if ((err = snd_ac97_bus(ice->card, bus_num++, &con_ops, NULL, &pbus)) < 0) return err; memset(&ac97, 0, sizeof(ac97)); ac97.private_data = ice; ac97.private_free = snd_ice1712_mixer_free_ac97; if ((err = snd_ac97_mixer(pbus, &ac97, &ice->ac97)) < 0) printk(KERN_WARNING "ice1712: cannot initialize ac97 for consumer, skipped\n"); else { if ((err = snd_ctl_add(ice->card, snd_ctl_new1(&snd_ice1712_mixer_digmix_route_ac97, ice))) < 0) return err; return 0; } } if (! (ice->eeprom.data[ICE_EEP1_ACLINK] & ICE1712_CFG_PRO_I2S)) { if ((err = snd_ac97_bus(ice->card, bus_num, &pro_ops, NULL, &pbus)) < 0) return err; memset(&ac97, 0, sizeof(ac97)); ac97.private_data = ice; ac97.private_free = snd_ice1712_mixer_free_ac97; if ((err = snd_ac97_mixer(pbus, &ac97, &ice->ac97)) < 0) printk(KERN_WARNING "ice1712: cannot initialize pro ac97, skipped\n"); else return 0; } /* I2S mixer only */ strcat(ice->card->mixername, "ICE1712 - multitrack"); return 0;}/* * */static inline unsigned int eeprom_double(ice1712_t *ice, int idx){ return (unsigned int)ice->eeprom.data[idx] | ((unsigned int)ice->eeprom.data[idx + 1] << 8);}static void snd_ice1712_proc_read(snd_info_entry_t *entry, snd_info_buffer_t * buffer){ ice1712_t *ice = entry->private_data; unsigned int idx; snd_iprintf(buffer, "%s\n\n", ice->card->longname); snd_iprintf(buffer, "EEPROM:\n"); snd_iprintf(buffer, " Subvendor : 0x%x\n", ice->eeprom.subvendor); snd_iprintf(buffer, " Size : %i bytes\n", ice->eeprom.size); snd_iprintf(buffer, " Version : %i\n", ice->eeprom.version); snd_iprintf(buffer, " Codec : 0x%x\n", ice->eeprom.data[ICE_EEP1_CODEC]); snd_iprintf(buffer, " ACLink : 0x%x\n", ice->eeprom.data[ICE_EEP1_ACLINK]); snd_iprintf(buffer, " I2S ID : 0x%x\n", ice->eeprom.data[ICE_EEP1_I2SID]); snd_iprintf(buffer, " S/PDIF : 0x%x\n", ice->eeprom.data[ICE_EEP1_SPDIF]); snd_iprintf(buffer, " GPIO mask : 0x%x\n", ice->eeprom.gpiomask); snd_iprintf(buffer, " GPIO state : 0x%x\n", ice->eeprom.gpiostate); snd_iprintf(buffer, " GPIO direction : 0x%x\n", ice->eeprom.gpiodir); snd_iprintf(buffer, " AC'97 main : 0x%x\n", eeprom_double(ice, ICE_EEP1_AC97_MAIN_LO)); snd_iprintf(buffer, " AC'97 pcm : 0x%x\n", eeprom_double(ice, ICE_EEP1_AC97_PCM_LO)); snd_iprintf(buffer, " AC'97 record : 0x%x\n", eeprom_double(ice, ICE_EEP1_AC97_REC_LO)); snd_iprintf(buffer, " AC'97 record src : 0x%x\n", ice->eeprom.data[ICE_EEP1_AC97_RECSRC]); for (idx = 0; idx < 4; idx++) snd_iprintf(buffer, " DAC ID #%i : 0x%x\n", idx, ice->eeprom.data[ICE_EEP1_DAC_ID + idx]); for (idx = 0; idx < 4; idx++) snd_iprintf(buffer, " ADC ID #%i : 0x%x\n", idx, ice->eeprom.data[ICE_EEP1_ADC_ID + idx]); for (idx = 0x1c; idx < ice->eeprom.size; idx++) snd_iprintf(buffer, " Extra #%02i : 0x%x\n", idx, ice->eeprom.data[idx]); snd_iprintf(buffer, "\nRegisters:\n"); snd_iprintf(buffer, " PSDOUT03 : 0x%04x\n", (unsigned)inw(ICEMT(ice, ROUTE_PSDOUT03))); snd_iprintf(buffer, " CAPTURE : 0x%08x\n", inl(ICEMT(ice, ROUTE_CAPTURE))); snd_iprintf(buffer, " SPDOUT : 0x%04x\n", (unsigned)inw(ICEMT(ice, ROUTE_SPDOUT))); snd_iprintf(buffer, " RATE : 0x%02x\n", (unsigned)inb(ICEMT(ice, RATE)));}static void __devinit snd_ice1712_proc_init(ice1712_t * ice){ snd_info_entry_t *entry; if (! snd_card_proc_new(ice->card, "ice1712", &entry)) snd_info_set_text_ops(entry, ice, 1024, snd_ice1712_proc_read);}/* * */static int snd_ice1712_eeprom_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo){ uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES; uinfo->count = sizeof(ice1712_eeprom_t); return 0;}static int snd_ice1712_eeprom_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){ ice1712_t *ice = snd_kcontrol_chip(kcontrol); memcpy(ucontrol->value.bytes.data, &ice->eeprom, sizeof(ice->eeprom)); return 0;}static snd_kcontrol_new_t snd_ice1712_eeprom __devinitdata = { .iface = SNDRV_CTL_ELEM_IFACE_CARD, .name = "ICE1712 EEPROM", .access = SNDRV_CTL_ELEM_ACCESS_READ, .info = snd_ice1712_eeprom_info, .get = snd_ice1712_eeprom_get};/* */static int snd_ice1712_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_ice1712_spdif_default_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){ ice1712_t *ice = snd_kcontrol_chip(kcontrol); if (ice->spdif.ops.default_get) ice->spdif.ops.default_get(ice, ucontrol); return 0;}static int snd_ice1712_spdif_default_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){ ice1712_t *ice = snd_kcontrol_chip(kcontrol); if (ice->spdif.ops.default_put) return ice->spdif.ops.default_put(ice, ucontrol); return 0;}static snd_kcontrol_new_t snd_ice1712_spdif_default __devinitdata ={ .iface = SNDRV_CTL_ELEM_IFACE_PCM, .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT), .info = snd_ice1712_spdif_info, .get = snd_ice1712_spdif_default_get, .put = snd_ice1712_spdif_default_put};static int snd_ice1712_spdif_maskc_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){ ice1712_t *ice = snd_kcontrol_chip(kcontrol); if (ice->spdif.ops.default_get) { 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; } else { ucontrol->value.iec958.status[0] = 0xff; ucontrol->value.iec958.status[1] = 0xff; ucontrol->value.iec958.status[2] = 0xff; ucontrol->value.iec958.status[3] = 0xff; ucontrol->value.iec958.status[4] = 0xff; } return 0;}static int snd_ice1712_spdif_maskp_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){ ice1712_t *ice = snd_kcontrol_chip(kcontrol); if (ice->spdif.ops.default_get) { ucontrol->value.iec958.status[0] = IEC958_AES0_NONAUDIO | IEC958_AES0_PROFESSIONAL | IEC958_AES0_PRO_FS | IEC958_AES0_PRO_EMPHASIS; ucontrol->value.iec958.status[1] = IEC958_AES1_PRO_MODE; } else { ucontrol->value.iec958.status[0] = 0xff; ucontrol->value.iec958.status[1] = 0xff; ucontrol->value.iec958.status[2] = 0xff; ucontrol->value.iec958.status[3] = 0xff; ucontrol->value.iec958.status[4] = 0xff; } return 0;}static snd_kcontrol_new_t snd_ice1712_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_ice1712_spdif_info, .get = snd_ice1712_spdif_maskc_get,};static snd_kcontrol_new_t snd_ice1712_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_ice1712_spdif_info, .get = snd_ice1712_spdif_maskp_get,};static int snd_ice1712_spdif_stream_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){ ice1712_t *ice = snd_kcontrol_chip(kcontrol); if (ice->spdif.ops.stream_get) ice->spdif.ops.stream_get(ice, ucontrol); return 0;}static int snd_ice1712_spdif_stream_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){ ice1712_t *ice = snd_kcontrol_chip(kcontrol); if (ice->spdif.ops.stream_put) return ice->spdif.ops.stream_put(ice, ucontrol); return 0;}static snd_kcontrol_new_t snd_ice1712_spdif_stream __devinitdata ={ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE, .iface = SNDRV_CTL_ELEM_IFACE_PCM, .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,PCM_STREAM), .info = snd_ice1712_spdif_info, .get = snd_ice1712_spdif_stream_get, .put = snd_ice1712_spdif_stream_put};int snd_ice1712_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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -