📄 emumixer.c
字号:
EMU1010_ADC_PADS("ADC3 14dB PAD Audio Dock Capture Switch", EMU_HANA_DOCK_ADC_PAD3), EMU1010_ADC_PADS("ADC1 14dB PAD 0202 Capture Switch", EMU_HANA_0202_ADC_PAD1),};#define snd_emu1010_dac_pads_info snd_ctl_boolean_mono_infostatic int snd_emu1010_dac_pads_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol){ struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); unsigned int mask = kcontrol->private_value & 0xff; ucontrol->value.integer.value[0] = (emu->emu1010.dac_pads & mask) ? 1 : 0; return 0;}static int snd_emu1010_dac_pads_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol){ struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); unsigned int mask = kcontrol->private_value & 0xff; unsigned int val, cache; val = ucontrol->value.integer.value[0]; cache = emu->emu1010.dac_pads; if (val == 1) cache = cache | mask; else cache = cache & ~mask; if (cache != emu->emu1010.dac_pads) { snd_emu1010_fpga_write(emu, EMU_HANA_DAC_PADS, cache ); emu->emu1010.dac_pads = cache; } return 0;}#define EMU1010_DAC_PADS(xname,chid) \{ \ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \ .info = snd_emu1010_dac_pads_info, \ .get = snd_emu1010_dac_pads_get, \ .put = snd_emu1010_dac_pads_put, \ .private_value = chid \}static struct snd_kcontrol_new snd_emu1010_dac_pads[] __devinitdata = { EMU1010_DAC_PADS("DAC1 Audio Dock 14dB PAD Playback Switch", EMU_HANA_DOCK_DAC_PAD1), EMU1010_DAC_PADS("DAC2 Audio Dock 14dB PAD Playback Switch", EMU_HANA_DOCK_DAC_PAD2), EMU1010_DAC_PADS("DAC3 Audio Dock 14dB PAD Playback Switch", EMU_HANA_DOCK_DAC_PAD3), EMU1010_DAC_PADS("DAC4 Audio Dock 14dB PAD Playback Switch", EMU_HANA_DOCK_DAC_PAD4), EMU1010_DAC_PADS("DAC1 0202 14dB PAD Playback Switch", EMU_HANA_0202_DAC_PAD1),};static int snd_emu1010_internal_clock_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo){ static char *texts[4] = { "44100", "48000", "SPDIF", "ADAT" }; uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; uinfo->count = 1; uinfo->value.enumerated.items = 4; 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_emu1010_internal_clock_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol){ struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); ucontrol->value.enumerated.item[0] = emu->emu1010.internal_clock; return 0;}static int snd_emu1010_internal_clock_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol){ struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); unsigned int val; int change = 0; val = ucontrol->value.enumerated.item[0] ; /* Limit: uinfo->value.enumerated.items = 4; */ if (val >= 4) return -EINVAL; change = (emu->emu1010.internal_clock != val); if (change) { emu->emu1010.internal_clock = val; switch (val) { case 0: /* 44100 */ /* Mute all */ snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_MUTE ); /* Default fallback clock 48kHz */ snd_emu1010_fpga_write(emu, EMU_HANA_DEFCLOCK, EMU_HANA_DEFCLOCK_44_1K ); /* Word Clock source, Internal 44.1kHz x1 */ snd_emu1010_fpga_write(emu, EMU_HANA_WCLOCK, EMU_HANA_WCLOCK_INT_44_1K | EMU_HANA_WCLOCK_1X ); /* Set LEDs on Audio Dock */ snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_LEDS_2, EMU_HANA_DOCK_LEDS_2_44K | EMU_HANA_DOCK_LEDS_2_LOCK ); /* Allow DLL to settle */ msleep(10); /* Unmute all */ snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE ); break; case 1: /* 48000 */ /* Mute all */ snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_MUTE ); /* Default fallback clock 48kHz */ snd_emu1010_fpga_write(emu, EMU_HANA_DEFCLOCK, EMU_HANA_DEFCLOCK_48K ); /* Word Clock source, Internal 48kHz x1 */ snd_emu1010_fpga_write(emu, EMU_HANA_WCLOCK, EMU_HANA_WCLOCK_INT_48K | EMU_HANA_WCLOCK_1X ); /* Set LEDs on Audio Dock */ snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_LEDS_2, EMU_HANA_DOCK_LEDS_2_48K | EMU_HANA_DOCK_LEDS_2_LOCK ); /* Allow DLL to settle */ msleep(10); /* Unmute all */ snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE ); break; case 2: /* Take clock from S/PDIF IN */ /* Mute all */ snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_MUTE ); /* Default fallback clock 48kHz */ snd_emu1010_fpga_write(emu, EMU_HANA_DEFCLOCK, EMU_HANA_DEFCLOCK_48K ); /* Word Clock source, sync to S/PDIF input */ snd_emu1010_fpga_write(emu, EMU_HANA_WCLOCK, EMU_HANA_WCLOCK_HANA_SPDIF_IN | EMU_HANA_WCLOCK_1X ); /* Set LEDs on Audio Dock */ snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_LEDS_2, EMU_HANA_DOCK_LEDS_2_EXT | EMU_HANA_DOCK_LEDS_2_LOCK ); /* FIXME: We should set EMU_HANA_DOCK_LEDS_2_LOCK only when clock signal is present and valid */ /* Allow DLL to settle */ msleep(10); /* Unmute all */ snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE ); break; case 3: /* Take clock from ADAT IN */ /* Mute all */ snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_MUTE ); /* Default fallback clock 48kHz */ snd_emu1010_fpga_write(emu, EMU_HANA_DEFCLOCK, EMU_HANA_DEFCLOCK_48K ); /* Word Clock source, sync to ADAT input */ snd_emu1010_fpga_write(emu, EMU_HANA_WCLOCK, EMU_HANA_WCLOCK_HANA_ADAT_IN | EMU_HANA_WCLOCK_1X ); /* Set LEDs on Audio Dock */ snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_LEDS_2, EMU_HANA_DOCK_LEDS_2_EXT | EMU_HANA_DOCK_LEDS_2_LOCK ); /* FIXME: We should set EMU_HANA_DOCK_LEDS_2_LOCK only when clock signal is present and valid */ /* Allow DLL to settle */ msleep(10); /* Unmute all */ snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE ); break; } } return change;}static struct snd_kcontrol_new snd_emu1010_internal_clock ={ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Clock Internal Rate", .count = 1, .info = snd_emu1010_internal_clock_info, .get = snd_emu1010_internal_clock_get, .put = snd_emu1010_internal_clock_put};static int snd_audigy_i2c_capture_source_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo){#if 0 static char *texts[4] = { "Unknown1", "Unknown2", "Mic", "Line" };#endif static char *texts[2] = { "Mic", "Line" }; uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; uinfo->count = 1; uinfo->value.enumerated.items = 2; if (uinfo->value.enumerated.item > 1) uinfo->value.enumerated.item = 1; strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); return 0;}static int snd_audigy_i2c_capture_source_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol){ struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); ucontrol->value.enumerated.item[0] = emu->i2c_capture_source; return 0;}static int snd_audigy_i2c_capture_source_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol){ struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); unsigned int source_id; unsigned int ngain, ogain; u32 gpio; int change = 0; unsigned long flags; u32 source; /* If the capture source has changed, * update the capture volume from the cached value * for the particular source. */ source_id = ucontrol->value.enumerated.item[0]; /* Limit: uinfo->value.enumerated.items = 2; */ /* emu->i2c_capture_volume */ if (source_id >= 2) return -EINVAL; change = (emu->i2c_capture_source != source_id); if (change) { snd_emu10k1_i2c_write(emu, ADC_MUX, 0); /* Mute input */ spin_lock_irqsave(&emu->emu_lock, flags); gpio = inl(emu->port + A_IOCFG); if (source_id==0) outl(gpio | 0x4, emu->port + A_IOCFG); else outl(gpio & ~0x4, emu->port + A_IOCFG); spin_unlock_irqrestore(&emu->emu_lock, flags); ngain = emu->i2c_capture_volume[source_id][0]; /* Left */ ogain = emu->i2c_capture_volume[emu->i2c_capture_source][0]; /* Left */ if (ngain != ogain) snd_emu10k1_i2c_write(emu, ADC_ATTEN_ADCL, ((ngain) & 0xff)); ngain = emu->i2c_capture_volume[source_id][1]; /* Right */ ogain = emu->i2c_capture_volume[emu->i2c_capture_source][1]; /* Right */ if (ngain != ogain) snd_emu10k1_i2c_write(emu, ADC_ATTEN_ADCR, ((ngain) & 0xff)); source = 1 << (source_id + 2); snd_emu10k1_i2c_write(emu, ADC_MUX, source); /* Set source */ emu->i2c_capture_source = source_id; } return change;}static struct snd_kcontrol_new snd_audigy_i2c_capture_source ={ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Capture Source", .info = snd_audigy_i2c_capture_source_info, .get = snd_audigy_i2c_capture_source_get, .put = snd_audigy_i2c_capture_source_put};static int snd_audigy_i2c_volume_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo){ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; uinfo->count = 2; uinfo->value.integer.min = 0; uinfo->value.integer.max = 255; return 0;}static int snd_audigy_i2c_volume_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol){ struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); unsigned int source_id; source_id = kcontrol->private_value; /* Limit: emu->i2c_capture_volume */ /* capture_source: uinfo->value.enumerated.items = 2 */ if (source_id >= 2) return -EINVAL; ucontrol->value.integer.value[0] = emu->i2c_capture_volume[source_id][0]; ucontrol->value.integer.value[1] = emu->i2c_capture_volume[source_id][1]; return 0;}static int snd_audigy_i2c_volume_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol){ struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); unsigned int ogain; unsigned int ngain; unsigned int source_id; int change = 0; source_id = kcontrol->private_value; /* Limit: emu->i2c_capture_volume */ /* capture_source: uinfo->value.enumerated.items = 2 */ if (source_id >= 2) return -EINVAL; ogain = emu->i2c_capture_volume[source_id][0]; /* Left */ ngain = ucontrol->value.integer.value[0]; if (ngain > 0xff) return 0; if (ogain != ngain) { if (emu->i2c_capture_source == source_id) snd_emu10k1_i2c_write(emu, ADC_ATTEN_ADCL, ((ngain) & 0xff) ); emu->i2c_capture_volume[source_id][0] = ngain; change = 1; } ogain = emu->i2c_capture_volume[source_id][1]; /* Right */ ngain = ucontrol->value.integer.value[1]; if (ngain > 0xff) return 0; if (ogain != ngain) { if (emu->i2c_capture_source == source_id) snd_emu10k1_i2c_write(emu, ADC_ATTEN_ADCR, ((ngain) & 0xff)); emu->i2c_capture_volume[source_id][1] = ngain; change = 1; } return change;}#define I2C_VOLUME(xname,chid) \{ \ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \ SNDRV_CTL_ELEM_ACCESS_TLV_READ, \ .info = snd_audigy_i2c_volume_info, \ .get = snd_audigy_i2c_volume_get, \ .put = snd_audigy_i2c_volume_put, \ .tlv = { .p = snd_audigy_db_scale2 }, \ .private_value = chid \}static struct snd_kcontrol_new snd_audigy_i2c_volume_ctls[] __devinitdata = { I2C_VOLUME("Mic Capture Volume", 0), I2C_VOLUME("Line Capture Volume", 0)};#if 0static int snd_audigy_spdif_output_rate_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo){ static char *texts[] = {"44100", "48000", "96000"}; uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; uinfo->count = 1; uinfo->value.enumerated.items = 3; 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_audigy_spdif_output_rate_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol){ struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); unsigned int tmp; unsigned long flags; spin_lock_irqsave(&emu->reg_lock, flags); tmp = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, 0); switch (tmp & A_SPDIF_RATE_MASK) { case A_SPDIF_44100: ucontrol->value.enumerated.item[0] = 0; break; case A_SPDIF_48000: ucontrol->value.enumerated.item[0] = 1; break; case A_SPDIF_96000: ucontrol->value.enumerated.item[0] = 2; break; default: ucontrol->value.enumerated.item[0] = 1; } spin_unlock_irqrestore(&emu->reg_lock, flags); return 0;}static int snd_audigy_spdif_output_rate_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol){ struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); int change; unsigned int reg, val, tmp; unsigned long flags; switch(ucontrol->value.enumerated.item[0]) { case 0: val = A_SPDIF_44100; break; case 1: val = A_SPDIF_48000; break; case 2: val = A_SPDIF_96000; break; default: val = A_SPDIF_48000; break; } spin_lock_irqsave(&emu->reg_lock, flags); reg = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, 0); tmp = reg & ~A_SPDIF_RATE_MASK; tmp |= val; if ((change = (tmp != reg))) snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, 0, tmp); spin_unlock_irqrestore(&emu->reg_lock, flags); return change;}static struct snd_kcontrol_new snd_audigy_spdif_output_rate ={ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Audigy SPDIF Output Sample Rate", .count = 1, .info = snd_audigy_spdif_output_rate_info, .get = snd_audigy_spdif_output_rate_get, .put = snd_audigy_spdif_output_rate_put};#endifstatic int snd_emu10k1_spdif_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol){ struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); int change; unsigned int val; unsigned long flags; /* Limit: emu->spdif_bits */ if (idx >= 3) return -EINVAL; val = (ucontrol->value.iec958.status[0] << 0) | (ucontrol->value.iec958.status[1] << 8) | (ucontrol->value.iec958.status[2] << 16) | (ucontrol->value.iec958.status[3] << 24); spin_lock_irqsave(&emu->reg_lock, flags); change = val != emu->spdif_bits[idx]; if (change) { snd_emu10k1_ptr_write(emu, SPCS0 + idx, 0, val); emu->spdif_bits[idx] = val; } spin_unlock_irqrestore(&emu->reg_lock, flags); return change;}static struct snd_kcontrol_new snd_emu10k1_spdif_mask_control ={
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -