📄 vx222_ops.c
字号:
/* `data' is a value between 0x0 and VX2_AKM_LEVEL_MAX = 0x093, in the case of the AKM codecs, we need a look up table, as there is no linear matching between the driver codec values and the real dBu value */ snd_assert(data < sizeof(vx2_akm_gains_lut), return); switch (reg) { case XX_CODEC_LEVEL_LEFT_REGISTER: val = AKM_CODEC_LEFT_LEVEL_CMD; break; case XX_CODEC_LEVEL_RIGHT_REGISTER: val = AKM_CODEC_RIGHT_LEVEL_CMD; break; default: snd_BUG(); return; } val |= vx2_akm_gains_lut[data]; vx2_write_codec_reg(chip, val);}/* * write codec bit for old VX222 board */static void vx2_old_write_codec_bit(vx_core_t *chip, int codec, unsigned int data){ int i; /* activate access to codec registers */ vx_inl(chip, HIFREQ); for (i = 0; i < 24; i++, data <<= 1) vx_outl(chip, DATA, ((data & 0x800000) ? VX_DATA_CODEC_MASK : 0)); /* Terminate access to codec registers */ vx_inl(chip, RUER);}/* * reset codec bit */static void vx2_reset_codec(vx_core_t *_chip){ struct snd_vx222 *chip = (struct snd_vx222 *)_chip; /* Set the reset CODEC bit to 0. */ vx_outl(chip, CDSP, chip->regCDSP &~ VX_CDSP_CODEC_RESET_MASK); vx_inl(chip, CDSP); snd_vx_delay(_chip, 10); /* Set the reset CODEC bit to 1. */ chip->regCDSP |= VX_CDSP_CODEC_RESET_MASK; vx_outl(chip, CDSP, chip->regCDSP); vx_inl(chip, CDSP); if (_chip->type == VX_TYPE_BOARD) { snd_vx_delay(_chip, 1); return; } snd_vx_delay(_chip, 5); /* additionnel wait time for AKM's */ vx2_write_codec_reg(_chip, AKM_CODEC_POWER_CONTROL_CMD); /* DAC power up, ADC power up, Vref power down */ vx2_write_codec_reg(_chip, AKM_CODEC_CLOCK_FORMAT_CMD); /* default */ vx2_write_codec_reg(_chip, AKM_CODEC_MUTE_CMD); /* Mute = ON ,Deemphasis = OFF */ vx2_write_codec_reg(_chip, AKM_CODEC_RESET_OFF_CMD); /* DAC and ADC normal operation */ if (_chip->type == VX_TYPE_MIC) { /* set up the micro input selector */ chip->regSELMIC = MICRO_SELECT_INPUT_NORM | MICRO_SELECT_PREAMPLI_G_0 | MICRO_SELECT_NOISE_T_52DB; /* reset phantom power supply */ chip->regSELMIC &= ~MICRO_SELECT_PHANTOM_ALIM; vx_outl(_chip, SELMIC, chip->regSELMIC); }}/* * change the audio source */static void vx2_change_audio_source(vx_core_t *_chip, int src){ struct snd_vx222 *chip = (struct snd_vx222 *)_chip; switch (src) { case VX_AUDIO_SRC_DIGITAL: chip->regCFG |= VX_CFG_DATAIN_SEL_MASK; break; default: chip->regCFG &= ~VX_CFG_DATAIN_SEL_MASK; break; } vx_outl(chip, CFG, chip->regCFG);}/* * set the clock source */static void vx2_set_clock_source(vx_core_t *_chip, int source){ struct snd_vx222 *chip = (struct snd_vx222 *)_chip; if (source == INTERNAL_QUARTZ) chip->regCFG &= ~VX_CFG_CLOCKIN_SEL_MASK; else chip->regCFG |= VX_CFG_CLOCKIN_SEL_MASK; vx_outl(chip, CFG, chip->regCFG);}/* * reset the board */static void vx2_reset_board(vx_core_t *_chip, int cold_reset){ struct snd_vx222 *chip = (struct snd_vx222 *)_chip; /* initialize the register values */ chip->regCDSP = VX_CDSP_CODEC_RESET_MASK | VX_CDSP_DSP_RESET_MASK ; chip->regCFG = 0;}/* * input level controls for VX222 Mic *//* Micro level is specified to be adjustable from -96dB to 63 dB (board coded 0x00 ... 318), * 318 = 210 + 36 + 36 + 36 (210 = +9dB variable) (3 * 36 = 3 steps of 18dB pre ampli) * as we will mute if less than -110dB, so let's simply use line input coded levels and add constant offset ! */#define V2_MICRO_LEVEL_RANGE (318 - 255)static void vx2_set_input_level(struct snd_vx222 *chip){ int i, miclevel, preamp; unsigned int data; miclevel = chip->mic_level; miclevel += V2_MICRO_LEVEL_RANGE; /* add 318 - 0xff */ preamp = 0; while (miclevel > 210) { /* limitation to +9dB of 3310 real gain */ preamp++; /* raise pre ampli + 18dB */ miclevel -= (18 * 2); /* lower level 18 dB (*2 because of 0.5 dB steps !) */ } snd_assert(preamp < 4, return); /* set pre-amp level */ chip->regSELMIC &= ~MICRO_SELECT_PREAMPLI_MASK; chip->regSELMIC |= (preamp << MICRO_SELECT_PREAMPLI_OFFSET) & MICRO_SELECT_PREAMPLI_MASK; vx_outl(chip, SELMIC, chip->regSELMIC); data = (unsigned int)miclevel << 16 | (unsigned int)chip->input_level[1] << 8 | (unsigned int)chip->input_level[0]; vx_inl(chip, DATA); /* Activate input level programming */ /* We have to send 32 bits (4 x 8 bits) */ for (i = 0; i < 32; i++, data <<= 1) vx_outl(chip, DATA, ((data & 0x80000000) ? VX_DATA_CODEC_MASK : 0)); vx_inl(chip, RUER); /* Terminate input level programming */}#define MIC_LEVEL_MAX 0xff/* * controls API for input levels *//* input levels */static int vx_input_level_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 = MIC_LEVEL_MAX; return 0;}static int vx_input_level_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol){ vx_core_t *_chip = snd_kcontrol_chip(kcontrol); struct snd_vx222 *chip = (struct snd_vx222 *)_chip; down(&_chip->mixer_mutex); ucontrol->value.integer.value[0] = chip->input_level[0]; ucontrol->value.integer.value[1] = chip->input_level[1]; up(&_chip->mixer_mutex); return 0;}static int vx_input_level_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol){ vx_core_t *_chip = snd_kcontrol_chip(kcontrol); struct snd_vx222 *chip = (struct snd_vx222 *)_chip; down(&_chip->mixer_mutex); if (chip->input_level[0] != ucontrol->value.integer.value[0] || chip->input_level[1] != ucontrol->value.integer.value[1]) { chip->input_level[0] = ucontrol->value.integer.value[0]; chip->input_level[1] = ucontrol->value.integer.value[1]; vx2_set_input_level(chip); up(&_chip->mixer_mutex); return 1; } up(&_chip->mixer_mutex); return 0;}/* mic level */static int vx_mic_level_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 = MIC_LEVEL_MAX; return 0;}static int vx_mic_level_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol){ vx_core_t *_chip = snd_kcontrol_chip(kcontrol); struct snd_vx222 *chip = (struct snd_vx222 *)_chip; ucontrol->value.integer.value[0] = chip->mic_level; return 0;}static int vx_mic_level_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol){ vx_core_t *_chip = snd_kcontrol_chip(kcontrol); struct snd_vx222 *chip = (struct snd_vx222 *)_chip; down(&_chip->mixer_mutex); if (chip->mic_level != ucontrol->value.integer.value[0]) { chip->mic_level = ucontrol->value.integer.value[0]; vx2_set_input_level(chip); up(&_chip->mixer_mutex); return 1; } up(&_chip->mixer_mutex); return 0;}static snd_kcontrol_new_t vx_control_input_level = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Capture Volume", .info = vx_input_level_info, .get = vx_input_level_get, .put = vx_input_level_put,};static snd_kcontrol_new_t vx_control_mic_level = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Mic Capture Volume", .info = vx_mic_level_info, .get = vx_mic_level_get, .put = vx_mic_level_put,};/* * FIXME: compressor/limiter implementation is missing yet... */static int vx2_add_mic_controls(vx_core_t *_chip){ struct snd_vx222 *chip = (struct snd_vx222 *)_chip; int err; if (_chip->type != VX_TYPE_MIC) return 0; /* mute input levels */ chip->input_level[0] = chip->input_level[1] = 0; chip->mic_level = 0; vx2_set_input_level(chip); /* controls */ if ((err = snd_ctl_add(_chip->card, snd_ctl_new1(&vx_control_input_level, chip))) < 0) return err; if ((err = snd_ctl_add(_chip->card, snd_ctl_new1(&vx_control_mic_level, chip))) < 0) return err; return 0;}/* * callbacks */struct snd_vx_ops vx222_ops = { .in8 = vx2_inb, .in32 = vx2_inl, .out8 = vx2_outb, .out32 = vx2_outl, .test_and_ack = vx2_test_and_ack, .validate_irq = vx2_validate_irq, .akm_write = vx2_write_akm, .reset_codec = vx2_reset_codec, .change_audio_source = vx2_change_audio_source, .set_clock_source = vx2_set_clock_source, .load_dsp = vx2_load_dsp, .reset_dsp = vx2_reset_dsp, .reset_board = vx2_reset_board, .dma_write = vx2_dma_write, .dma_read = vx2_dma_read, .add_controls = vx2_add_mic_controls,};/* for old VX222 board */struct snd_vx_ops vx222_old_ops = { .in8 = vx2_inb, .in32 = vx2_inl, .out8 = vx2_outb, .out32 = vx2_outl, .test_and_ack = vx2_test_and_ack, .validate_irq = vx2_validate_irq, .write_codec = vx2_old_write_codec_bit, .reset_codec = vx2_reset_codec, .change_audio_source = vx2_change_audio_source, .set_clock_source = vx2_set_clock_source, .load_dsp = vx2_load_dsp, .reset_dsp = vx2_reset_dsp, .reset_board = vx2_reset_board, .dma_write = vx2_dma_write, .dma_read = vx2_dma_read,};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -