📄 cs46xx_lib.c
字号:
static int snd_cs46xx_vol_iec958_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){ cs46xx_t *chip = snd_kcontrol_chip(kcontrol); int change = 0; if (chip->dsp_spos_instance->spdif_input_volume_left != ucontrol->value.integer.value[0] || chip->dsp_spos_instance->spdif_input_volume_right!= ucontrol->value.integer.value[1]) { cs46xx_dsp_set_iec958_volume (chip, ucontrol->value.integer.value[0], ucontrol->value.integer.value[1]); change = 1; } return change;}#endifstatic int snd_mixer_boolean_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_cs46xx_iec958_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol){ cs46xx_t *chip = snd_kcontrol_chip(kcontrol); int reg = kcontrol->private_value; if (reg == CS46XX_MIXER_SPDIF_OUTPUT_ELEMENT) ucontrol->value.integer.value[0] = (chip->dsp_spos_instance->spdif_status_out & DSP_SPDIF_STATUS_OUTPUT_ENABLED); else ucontrol->value.integer.value[0] = chip->dsp_spos_instance->spdif_status_in; return 0;}static int snd_cs46xx_iec958_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol){ cs46xx_t *chip = snd_kcontrol_chip(kcontrol); int change, res; switch (kcontrol->private_value) { case CS46XX_MIXER_SPDIF_OUTPUT_ELEMENT: down (&chip->spos_mutex); change = (chip->dsp_spos_instance->spdif_status_out & DSP_SPDIF_STATUS_OUTPUT_ENABLED); if (ucontrol->value.integer.value[0] && !change) cs46xx_dsp_enable_spdif_out(chip); else if (change && !ucontrol->value.integer.value[0]) cs46xx_dsp_disable_spdif_out(chip); res = (change != (chip->dsp_spos_instance->spdif_status_out & DSP_SPDIF_STATUS_OUTPUT_ENABLED)); up (&chip->spos_mutex); break; case CS46XX_MIXER_SPDIF_INPUT_ELEMENT: change = chip->dsp_spos_instance->spdif_status_in; if (ucontrol->value.integer.value[0] && !change) { cs46xx_dsp_enable_spdif_in(chip); /* restore volume */ } else if (change && !ucontrol->value.integer.value[0]) cs46xx_dsp_disable_spdif_in(chip); res = (change != chip->dsp_spos_instance->spdif_status_in); break; default: res = -EINVAL; snd_assert(0, (void)0); } return res;}static int snd_cs46xx_adc_capture_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol){ cs46xx_t *chip = snd_kcontrol_chip(kcontrol); dsp_spos_instance_t * ins = chip->dsp_spos_instance; if (ins->adc_input != NULL) ucontrol->value.integer.value[0] = 1; else ucontrol->value.integer.value[0] = 0; return 0;}static int snd_cs46xx_adc_capture_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol){ cs46xx_t *chip = snd_kcontrol_chip(kcontrol); dsp_spos_instance_t * ins = chip->dsp_spos_instance; int change = 0; if (ucontrol->value.integer.value[0] && !ins->adc_input) { cs46xx_dsp_enable_adc_capture(chip); change = 1; } else if (!ucontrol->value.integer.value[0] && ins->adc_input) { cs46xx_dsp_disable_adc_capture(chip); change = 1; } return change;}static int snd_cs46xx_pcm_capture_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol){ cs46xx_t *chip = snd_kcontrol_chip(kcontrol); dsp_spos_instance_t * ins = chip->dsp_spos_instance; if (ins->pcm_input != NULL) ucontrol->value.integer.value[0] = 1; else ucontrol->value.integer.value[0] = 0; return 0;}static int snd_cs46xx_pcm_capture_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol){ cs46xx_t *chip = snd_kcontrol_chip(kcontrol); dsp_spos_instance_t * ins = chip->dsp_spos_instance; int change = 0; if (ucontrol->value.integer.value[0] && !ins->pcm_input) { cs46xx_dsp_enable_pcm_capture(chip); change = 1; } else if (!ucontrol->value.integer.value[0] && ins->pcm_input) { cs46xx_dsp_disable_pcm_capture(chip); change = 1; } return change;}static int snd_herc_spdif_select_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol){ cs46xx_t *chip = snd_kcontrol_chip(kcontrol); int val1 = snd_cs46xx_peekBA0(chip, BA0_EGPIODR); if (val1 & EGPIODR_GPOE0) ucontrol->value.integer.value[0] = 1; else ucontrol->value.integer.value[0] = 0; return 0;}/* * Game Theatre XP card - EGPIO[0] is used to select SPDIF input optical or coaxial. */ static int snd_herc_spdif_select_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol){ cs46xx_t *chip = snd_kcontrol_chip(kcontrol); int val1 = snd_cs46xx_peekBA0(chip, BA0_EGPIODR); int val2 = snd_cs46xx_peekBA0(chip, BA0_EGPIOPTR); if (ucontrol->value.integer.value[0]) { /* optical is default */ snd_cs46xx_pokeBA0(chip, BA0_EGPIODR, EGPIODR_GPOE0 | val1); /* enable EGPIO0 output */ snd_cs46xx_pokeBA0(chip, BA0_EGPIOPTR, EGPIOPTR_GPPT0 | val2); /* open-drain on output */ } else { /* coaxial */ snd_cs46xx_pokeBA0(chip, BA0_EGPIODR, val1 & ~EGPIODR_GPOE0); /* disable */ snd_cs46xx_pokeBA0(chip, BA0_EGPIOPTR, val2 & ~EGPIOPTR_GPPT0); /* disable */ } /* checking diff from the EGPIO direction register should be enough */ return (val1 != (int)snd_cs46xx_peekBA0(chip, BA0_EGPIODR));}static int snd_cs46xx_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_cs46xx_spdif_default_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){ cs46xx_t *chip = snd_kcontrol_chip(kcontrol); dsp_spos_instance_t * ins = chip->dsp_spos_instance; down (&chip->spos_mutex); ucontrol->value.iec958.status[0] = _wrap_all_bits((ins->spdif_csuv_default >> 24) & 0xff); ucontrol->value.iec958.status[1] = _wrap_all_bits((ins->spdif_csuv_default >> 16) & 0xff); ucontrol->value.iec958.status[2] = 0; ucontrol->value.iec958.status[3] = _wrap_all_bits((ins->spdif_csuv_default) & 0xff); up (&chip->spos_mutex); return 0;}static int snd_cs46xx_spdif_default_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){ cs46xx_t * chip = snd_kcontrol_chip(kcontrol); dsp_spos_instance_t * ins = chip->dsp_spos_instance; unsigned int val; int change; down (&chip->spos_mutex); val = ((unsigned int)_wrap_all_bits(ucontrol->value.iec958.status[0]) << 24) | ((unsigned int)_wrap_all_bits(ucontrol->value.iec958.status[2]) << 16) | ((unsigned int)_wrap_all_bits(ucontrol->value.iec958.status[3])) | /* left and right validity bit */ (1 << 13) | (1 << 12); change = (unsigned int)ins->spdif_csuv_default != val; ins->spdif_csuv_default = val; if ( !(ins->spdif_status_out & DSP_SPDIF_STATUS_PLAYBACK_OPEN) ) cs46xx_poke_via_dsp (chip,SP_SPDOUT_CSUV,val); up (&chip->spos_mutex); return change;}static int snd_cs46xx_spdif_mask_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){ ucontrol->value.iec958.status[0] = 0xff; ucontrol->value.iec958.status[1] = 0xff; ucontrol->value.iec958.status[2] = 0x00; ucontrol->value.iec958.status[3] = 0xff; return 0;}static int snd_cs46xx_spdif_stream_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){ cs46xx_t *chip = snd_kcontrol_chip(kcontrol); dsp_spos_instance_t * ins = chip->dsp_spos_instance; down (&chip->spos_mutex); ucontrol->value.iec958.status[0] = _wrap_all_bits((ins->spdif_csuv_stream >> 24) & 0xff); ucontrol->value.iec958.status[1] = _wrap_all_bits((ins->spdif_csuv_stream >> 16) & 0xff); ucontrol->value.iec958.status[2] = 0; ucontrol->value.iec958.status[3] = _wrap_all_bits((ins->spdif_csuv_stream) & 0xff); up (&chip->spos_mutex); return 0;}static int snd_cs46xx_spdif_stream_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){ cs46xx_t * chip = snd_kcontrol_chip(kcontrol); dsp_spos_instance_t * ins = chip->dsp_spos_instance; unsigned int val; int change; down (&chip->spos_mutex); val = ((unsigned int)_wrap_all_bits(ucontrol->value.iec958.status[0]) << 24) | ((unsigned int)_wrap_all_bits(ucontrol->value.iec958.status[1]) << 16) | ((unsigned int)_wrap_all_bits(ucontrol->value.iec958.status[3])) | /* left and right validity bit */ (1 << 13) | (1 << 12); change = ins->spdif_csuv_stream != val; ins->spdif_csuv_stream = val; if ( ins->spdif_status_out & DSP_SPDIF_STATUS_PLAYBACK_OPEN ) cs46xx_poke_via_dsp (chip,SP_SPDOUT_CSUV,val); up (&chip->spos_mutex); return change;}#endif /* CONFIG_SND_CS46XX_NEW_DSP */#ifdef CONFIG_SND_CS46XX_DEBUG_GPIOstatic int snd_cs46xx_egpio_select_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo){ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; uinfo->count = 1; uinfo->value.integer.min = 0; uinfo->value.integer.max = 8; return 0;}static int snd_cs46xx_egpio_select_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol){ cs46xx_t *chip = snd_kcontrol_chip(kcontrol); ucontrol->value.integer.value[0] = chip->current_gpio; return 0;}static int snd_cs46xx_egpio_select_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol){ cs46xx_t *chip = snd_kcontrol_chip(kcontrol); int change = (chip->current_gpio != ucontrol->value.integer.value[0]); chip->current_gpio = ucontrol->value.integer.value[0]; return change;}static int snd_cs46xx_egpio_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol){ cs46xx_t *chip = snd_kcontrol_chip(kcontrol); int reg = kcontrol->private_value; snd_printdd ("put: reg = %04x, gpio %02x\n",reg,chip->current_gpio); ucontrol->value.integer.value[0] = (snd_cs46xx_peekBA0(chip, reg) & (1 << chip->current_gpio)) ? 1 : 0; return 0;}static int snd_cs46xx_egpio_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol){ cs46xx_t *chip = snd_kcontrol_chip(kcontrol); int reg = kcontrol->private_value; int val = snd_cs46xx_peekBA0(chip, reg); int oldval = val; snd_printdd ("put: reg = %04x, gpio %02x\n",reg,chip->current_gpio); if (ucontrol->value.integer.value[0]) val |= (1 << chip->current_gpio); else val &= ~(1 << chip->current_gpio); snd_cs46xx_pokeBA0(chip, reg,val); snd_printdd ("put: val %08x oldval %08x\n",val,oldval); return (oldval != val);}#endif /* CONFIG_SND_CS46XX_DEBUG_GPIO */static snd_kcontrol_new_t snd_cs46xx_controls[] __devinitdata = {{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "DAC Volume", .info = snd_cs46xx_vol_info,#ifndef CONFIG_SND_CS46XX_NEW_DSP .get = snd_cs46xx_vol_get, .put = snd_cs46xx_vol_put, .private_value = BA1_PVOL,#else .get = snd_cs46xx_vol_dac_get, .put = snd_cs46xx_vol_dac_put,#endif},{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "ADC Volume", .info = snd_cs46xx_vol_info, .get = snd_cs46xx_vol_get, .put = snd_cs46xx_vol_put,#ifndef CONFIG_SND_CS46XX_NEW_DSP .private_value = BA1_CVOL,#else .private_value = (VARIDECIMATE_SCB_ADDR + 0xE) << 2,#endif},#ifdef CONFIG_SND_CS46XX_NEW_DSP{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "ADC Capture Switch", .info = snd_mixer_boolean_info, .get = snd_cs46xx_adc_capture_get, .put = snd_cs46xx_adc_capture_put},{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "DAC Capture Switch", .info = snd_mixer_boolean_info, .get = snd_cs46xx_pcm_capture_get, .put = snd_cs46xx_pcm_capture_put},{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "IEC958 Output Switch", .info = snd_mixer_boolean_info, .get = snd_cs46xx_iec958_get, .put = snd_cs46xx_iec958_put, .private_value = CS46XX_MIXER_SPDIF_OUTPUT_ELEMENT,},{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "IEC958 Input Switch", .info = snd_mixer_boolean_info, .get = snd_cs46xx_iec958_get, .put = snd_cs46xx_iec958_put, .private_value = CS46XX_MIXER_SPDIF_INPUT_ELEMENT,},#if 0/* Input IEC958 volume does not work for the moment. (Benny) */{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "IEC958 Input Volume", .info = snd_cs46xx_vol_info, .get = snd_cs46xx_vol_iec958_get, .put = snd_cs46xx_vol_iec958_put, .private_value = (ASYNCRX_SCB_ADDR + 0xE) << 2,},#endif{ .iface = SNDRV_CTL_ELEM_IFACE_PCM, .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT), .info = snd_cs46xx_spdif_info, .get = snd_cs46xx_spdif_default_get, .put = snd_cs46xx_spdif_default_put,},{ .iface = SNDRV_CTL_ELEM_IFACE_PCM, .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,MASK), .info = snd_cs46xx_spdif_info, .get = snd_cs46xx_spdif_mask_get, .access = SNDRV_CTL_ELEM_ACCESS_READ},{ .iface = SNDRV_CTL_ELEM_IFACE_PCM, .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,PCM_STREAM), .info = snd_cs46xx_spdif_info, .get = snd_cs46xx_spdif_stream_get, .put = snd_cs46xx_spdif_stream_put},#endif#ifdef CONFIG_SND_CS46XX_DEBUG_GPIO{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "EGPIO select", .info = snd_cs46xx_egpio_select_info, .get = snd_cs46xx_egpio_select_get, .put = snd_cs46xx_egpio_select_
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -