📄 cs4236_lib.c
字号:
#define CS4235_OUTPUT_ACCU(xname, xindex) \{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ .info = snd_cs4236_info_double, \ .get = snd_cs4235_get_output_accu, .put = snd_cs4235_put_output_accu, \ .private_value = 3 << 24 }static inline int snd_cs4235_mixer_output_accu_get_volume(int vol){ switch ((vol >> 5) & 3) { case 0: return 1; case 1: return 3; case 2: return 2; case 3: return 0; } return 3;}static inline int snd_cs4235_mixer_output_accu_set_volume(int vol){ switch (vol & 3) { case 0: return 3 << 5; case 1: return 0 << 5; case 2: return 2 << 5; case 3: return 1 << 5; } return 1 << 5;}static int snd_cs4235_get_output_accu(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){ cs4231_t *chip = snd_kcontrol_chip(kcontrol); unsigned long flags; spin_lock_irqsave(&chip->reg_lock, flags); ucontrol->value.integer.value[0] = snd_cs4235_mixer_output_accu_get_volume(chip->image[CS4235_LEFT_MASTER]); ucontrol->value.integer.value[1] = snd_cs4235_mixer_output_accu_get_volume(chip->image[CS4235_RIGHT_MASTER]); spin_unlock_irqrestore(&chip->reg_lock, flags); return 0;}static int snd_cs4235_put_output_accu(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){ cs4231_t *chip = snd_kcontrol_chip(kcontrol); unsigned long flags; int change; unsigned short val1, val2; val1 = snd_cs4235_mixer_output_accu_set_volume(ucontrol->value.integer.value[0]); val2 = snd_cs4235_mixer_output_accu_set_volume(ucontrol->value.integer.value[1]); spin_lock_irqsave(&chip->reg_lock, flags); val1 = (chip->image[CS4235_LEFT_MASTER] & ~(3 << 5)) | val1; val2 = (chip->image[CS4235_RIGHT_MASTER] & ~(3 << 5)) | val2; change = val1 != chip->image[CS4235_LEFT_MASTER] || val2 != chip->image[CS4235_RIGHT_MASTER]; snd_cs4231_out(chip, CS4235_LEFT_MASTER, val1); snd_cs4231_out(chip, CS4235_RIGHT_MASTER, val2); spin_unlock_irqrestore(&chip->reg_lock, flags); return change;}static snd_kcontrol_new_t snd_cs4236_controls[] = {CS4236_DOUBLE("Master Digital Playback Switch", 0, CS4236_LEFT_MASTER, CS4236_RIGHT_MASTER, 7, 7, 1, 1),CS4236_DOUBLE("Master Digital Capture Switch", 0, CS4236_DAC_MUTE, CS4236_DAC_MUTE, 7, 6, 1, 1),CS4236_MASTER_DIGITAL("Master Digital Volume", 0),CS4236_DOUBLE("Capture Boost Volume", 0, CS4236_LEFT_MIX_CTRL, CS4236_RIGHT_MIX_CTRL, 5, 5, 3, 1),CS4231_DOUBLE("PCM Playback Switch", 0, CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 7, 7, 1, 1),CS4231_DOUBLE("PCM Playback Volume", 0, CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 0, 0, 63, 1),CS4236_DOUBLE("DSP Playback Switch", 0, CS4236_LEFT_DSP, CS4236_RIGHT_DSP, 7, 7, 1, 1),CS4236_DOUBLE("DSP Playback Volume", 0, CS4236_LEFT_DSP, CS4236_RIGHT_DSP, 0, 0, 63, 1),CS4236_DOUBLE("FM Playback Switch", 0, CS4236_LEFT_FM, CS4236_RIGHT_FM, 7, 7, 1, 1),CS4236_DOUBLE("FM Playback Volume", 0, CS4236_LEFT_FM, CS4236_RIGHT_FM, 0, 0, 63, 1),CS4236_DOUBLE("Wavetable Playback Switch", 0, CS4236_LEFT_WAVE, CS4236_RIGHT_WAVE, 7, 7, 1, 1),CS4236_DOUBLE("Wavetable Playback Volume", 0, CS4236_LEFT_WAVE, CS4236_RIGHT_WAVE, 0, 0, 63, 1),CS4231_DOUBLE("Synth Playback Switch", 0, CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 7, 7, 1, 1),CS4231_DOUBLE("Synth Volume", 0, CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 0, 0, 31, 1),CS4231_DOUBLE("Synth Capture Switch", 0, CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 6, 6, 1, 1),CS4231_DOUBLE("Synth Capture Bypass", 0, CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 5, 5, 1, 1),CS4236_DOUBLE("Mic Playback Switch", 0, CS4236_LEFT_MIC, CS4236_RIGHT_MIC, 6, 6, 1, 1),CS4236_DOUBLE("Mic Capture Switch", 0, CS4236_LEFT_MIC, CS4236_RIGHT_MIC, 7, 7, 1, 1),CS4236_DOUBLE("Mic Volume", 0, CS4236_LEFT_MIC, CS4236_RIGHT_MIC, 0, 0, 31, 1),CS4236_DOUBLE("Mic Playback Boost", 0, CS4236_LEFT_MIC, CS4236_RIGHT_MIC, 5, 5, 1, 0),CS4231_DOUBLE("Line Playback Switch", 0, CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 7, 7, 1, 1),CS4231_DOUBLE("Line Volume", 0, CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 0, 0, 31, 1),CS4231_DOUBLE("Line Capture Switch", 0, CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 6, 6, 1, 1),CS4231_DOUBLE("Line Capture Bypass", 0, CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 5, 5, 1, 1),CS4231_DOUBLE("CD Playback Switch", 0, CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 7, 7, 1, 1),CS4231_DOUBLE("CD Volume", 0, CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 0, 0, 31, 1),CS4231_DOUBLE("CD Capture Switch", 0, CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 6, 6, 1, 1),CS4236_DOUBLE1("Mono Output Playback Switch", 0, CS4231_MONO_CTRL, CS4236_RIGHT_MIX_CTRL, 6, 7, 1, 1),CS4236_DOUBLE1("Mono Playback Switch", 0, CS4231_MONO_CTRL, CS4236_LEFT_MIX_CTRL, 7, 7, 1, 1),CS4231_SINGLE("Mono Playback Volume", 0, CS4231_MONO_CTRL, 0, 15, 1),CS4231_SINGLE("Mono Playback Bypass", 0, CS4231_MONO_CTRL, 5, 1, 0),CS4231_DOUBLE("Capture Volume", 0, CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 0, 0, 15, 0),CS4231_DOUBLE("Analog Loopback Capture Switch", 0, CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 7, 7, 1, 0),CS4231_SINGLE("Digital Loopback Playback Switch", 0, CS4231_LOOPBACK, 0, 1, 0),CS4236_DOUBLE1("Digital Loopback Playback Volume", 0, CS4231_LOOPBACK, CS4236_RIGHT_LOOPBACK, 2, 0, 63, 1)};static snd_kcontrol_new_t snd_cs4235_controls[] = {CS4231_DOUBLE("Master Switch", 0, CS4235_LEFT_MASTER, CS4235_RIGHT_MASTER, 7, 7, 1, 1),CS4231_DOUBLE("Master Volume", 0, CS4235_LEFT_MASTER, CS4235_RIGHT_MASTER, 0, 0, 31, 1),CS4235_OUTPUT_ACCU("Playback Volume", 0),CS4236_DOUBLE("Master Digital Playback Switch", 0, CS4236_LEFT_MASTER, CS4236_RIGHT_MASTER, 7, 7, 1, 1),CS4236_DOUBLE("Master Digital Capture Switch", 0, CS4236_DAC_MUTE, CS4236_DAC_MUTE, 7, 6, 1, 1),CS4236_MASTER_DIGITAL("Master Digital Volume", 0),CS4231_DOUBLE("Master Digital Playback Switch", 1, CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 7, 7, 1, 1),CS4231_DOUBLE("Master Digital Capture Switch", 1, CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 6, 6, 1, 1),CS4231_DOUBLE("Master Digital Volume", 1, CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 0, 0, 31, 1),CS4236_DOUBLE("Capture Volume", 0, CS4236_LEFT_MIX_CTRL, CS4236_RIGHT_MIX_CTRL, 5, 5, 3, 1),CS4231_DOUBLE("PCM Switch", 0, CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 7, 7, 1, 1),CS4231_DOUBLE("PCM Volume", 0, CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 0, 0, 63, 1),CS4236_DOUBLE("DSP Switch", 0, CS4236_LEFT_DSP, CS4236_RIGHT_DSP, 7, 7, 1, 1),CS4236_DOUBLE("FM Switch", 0, CS4236_LEFT_FM, CS4236_RIGHT_FM, 7, 7, 1, 1),CS4236_DOUBLE("Wavetable Switch", 0, CS4236_LEFT_WAVE, CS4236_RIGHT_WAVE, 7, 7, 1, 1),CS4236_DOUBLE("Mic Capture Switch", 0, CS4236_LEFT_MIC, CS4236_RIGHT_MIC, 7, 7, 1, 1),CS4236_DOUBLE("Mic Playback Switch", 0, CS4236_LEFT_MIC, CS4236_RIGHT_MIC, 6, 6, 1, 1),CS4236_SINGLE("Mic Volume", 0, CS4236_LEFT_MIC, 0, 31, 1),CS4236_SINGLE("Mic Playback Boost", 0, CS4236_LEFT_MIC, 5, 1, 0),CS4231_DOUBLE("Aux Playback Switch", 0, CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 7, 7, 1, 1),CS4231_DOUBLE("Aux Capture Switch", 0, CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 6, 6, 1, 1),CS4231_DOUBLE("Aux Volume", 0, CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 0, 0, 31, 1),CS4231_DOUBLE("Aux Playback Switch", 1, CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 7, 7, 1, 1),CS4231_DOUBLE("Aux Capture Switch", 1, CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 6, 6, 1, 1),CS4231_DOUBLE("Aux Volume", 1, CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 0, 0, 31, 1),CS4236_DOUBLE1("Master Mono Switch", 0, CS4231_MONO_CTRL, CS4236_RIGHT_MIX_CTRL, 6, 7, 1, 1),CS4236_DOUBLE1("Mono Switch", 0, CS4231_MONO_CTRL, CS4236_LEFT_MIX_CTRL, 7, 7, 1, 1),CS4231_SINGLE("Mono Volume", 0, CS4231_MONO_CTRL, 0, 15, 1),CS4231_DOUBLE("Analog Loopback Switch", 0, CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 7, 7, 1, 0),};#define CS4236_IEC958_ENABLE(xname, xindex) \{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ .info = snd_cs4236_info_single, \ .get = snd_cs4236_get_iec958_switch, .put = snd_cs4236_put_iec958_switch, \ .private_value = 1 << 16 }static int snd_cs4236_get_iec958_switch(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){ cs4231_t *chip = snd_kcontrol_chip(kcontrol); unsigned long flags; spin_lock_irqsave(&chip->reg_lock, flags); ucontrol->value.integer.value[0] = chip->image[CS4231_ALT_FEATURE_1] & 0x02 ? 1 : 0;#if 0 printk("get valid: ALT = 0x%x, C3 = 0x%x, C4 = 0x%x, C5 = 0x%x, C6 = 0x%x, C8 = 0x%x\n", snd_cs4231_in(chip, CS4231_ALT_FEATURE_1), snd_cs4236_ctrl_in(chip, 3), snd_cs4236_ctrl_in(chip, 4), snd_cs4236_ctrl_in(chip, 5), snd_cs4236_ctrl_in(chip, 6), snd_cs4236_ctrl_in(chip, 8));#endif spin_unlock_irqrestore(&chip->reg_lock, flags); return 0;}static int snd_cs4236_put_iec958_switch(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){ cs4231_t *chip = snd_kcontrol_chip(kcontrol); unsigned long flags; int change; unsigned short enable, val; enable = ucontrol->value.integer.value[0] & 1; down(&chip->mce_mutex); snd_cs4231_mce_up(chip); spin_lock_irqsave(&chip->reg_lock, flags); val = (chip->image[CS4231_ALT_FEATURE_1] & ~0x0e) | (0<<2) | (enable << 1); change = val != chip->image[CS4231_ALT_FEATURE_1]; snd_cs4231_out(chip, CS4231_ALT_FEATURE_1, val); val = snd_cs4236_ctrl_in(chip, 4) | 0xc0; snd_cs4236_ctrl_out(chip, 4, val); udelay(100); val &= ~0x40; snd_cs4236_ctrl_out(chip, 4, val); spin_unlock_irqrestore(&chip->reg_lock, flags); snd_cs4231_mce_down(chip); up(&chip->mce_mutex);#if 0 printk("set valid: ALT = 0x%x, C3 = 0x%x, C4 = 0x%x, C5 = 0x%x, C6 = 0x%x, C8 = 0x%x\n", snd_cs4231_in(chip, CS4231_ALT_FEATURE_1), snd_cs4236_ctrl_in(chip, 3), snd_cs4236_ctrl_in(chip, 4), snd_cs4236_ctrl_in(chip, 5), snd_cs4236_ctrl_in(chip, 6), snd_cs4236_ctrl_in(chip, 8));#endif return change;}static snd_kcontrol_new_t snd_cs4236_iec958_controls[] = {CS4236_IEC958_ENABLE("IEC958 Output Enable", 0),CS4236_SINGLEC("IEC958 Output Validity", 0, 4, 4, 1, 0),CS4236_SINGLEC("IEC958 Output User", 0, 4, 5, 1, 0),CS4236_SINGLEC("IEC958 Output CSBR", 0, 4, 6, 1, 0),CS4236_SINGLEC("IEC958 Output Channel Status Low", 0, 5, 1, 127, 0),CS4236_SINGLEC("IEC958 Output Channel Status High", 0, 6, 0, 255, 0)};static snd_kcontrol_new_t snd_cs4236_3d_controls_cs4235[] = {CS4236_SINGLEC("3D Control - Switch", 0, 3, 4, 1, 0),CS4236_SINGLEC("3D Control - Space", 0, 2, 4, 15, 1)};static snd_kcontrol_new_t snd_cs4236_3d_controls_cs4237[] = {CS4236_SINGLEC("3D Control - Switch", 0, 3, 7, 1, 0),CS4236_SINGLEC("3D Control - Space", 0, 2, 4, 15, 1),CS4236_SINGLEC("3D Control - Center", 0, 2, 0, 15, 1),CS4236_SINGLEC("3D Control - Mono", 0, 3, 6, 1, 0),CS4236_SINGLEC("3D Control - IEC958", 0, 3, 5, 1, 0)};static snd_kcontrol_new_t snd_cs4236_3d_controls_cs4238[] = {CS4236_SINGLEC("3D Control - Switch", 0, 3, 4, 1, 0),CS4236_SINGLEC("3D Control - Space", 0, 2, 4, 15, 1),CS4236_SINGLEC("3D Control - Volume", 0, 2, 0, 15, 1),CS4236_SINGLEC("3D Control - IEC958", 0, 3, 5, 1, 0)};int snd_cs4236_mixer(cs4231_t *chip){ snd_card_t *card; unsigned int idx, count; int err; snd_kcontrol_new_t *kcontrol; snd_assert(chip != NULL && chip->card != NULL, return -EINVAL); card = chip->card; strcpy(card->mixername, snd_cs4231_chip_id(chip)); if (chip->hardware == CS4231_HW_CS4235 || chip->hardware == CS4231_HW_CS4239) { for (idx = 0; idx < ARRAY_SIZE(snd_cs4235_controls); idx++) { if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_cs4235_controls[idx], chip))) < 0) return err; } } else { for (idx = 0; idx < ARRAY_SIZE(snd_cs4236_controls); idx++) { if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_cs4236_controls[idx], chip))) < 0) return err; } } switch (chip->hardware) { case CS4231_HW_CS4235: case CS4231_HW_CS4239: count = ARRAY_SIZE(snd_cs4236_3d_controls_cs4235); kcontrol = snd_cs4236_3d_controls_cs4235; break; case CS4231_HW_CS4237B: count = ARRAY_SIZE(snd_cs4236_3d_controls_cs4237); kcontrol = snd_cs4236_3d_controls_cs4237; break; case CS4231_HW_CS4238B: count = ARRAY_SIZE(snd_cs4236_3d_controls_cs4238); kcontrol = snd_cs4236_3d_controls_cs4238; break; default: count = 0; kcontrol = NULL; } for (idx = 0; idx < count; idx++, kcontrol++) { if ((err = snd_ctl_add(card, snd_ctl_new1(kcontrol, chip))) < 0) return err; } if (chip->hardware == CS4231_HW_CS4237B || chip->hardware == CS4231_HW_CS4238B) { for (idx = 0; idx < ARRAY_SIZE(snd_cs4236_iec958_controls); idx++) { if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_cs4236_iec958_controls[idx], chip))) < 0) return err; } } return 0;}EXPORT_SYMBOL(snd_cs4236_create);EXPORT_SYMBOL(snd_cs4236_pcm);EXPORT_SYMBOL(snd_cs4236_mixer);/* * INIT part */static int __init alsa_cs4236_init(void){ return 0;}static void __exit alsa_cs4236_exit(void){}module_init(alsa_cs4236_init)module_exit(alsa_cs4236_exit)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -