diff options
Diffstat (limited to 'sound/pci/oxygen/oxygen_mixer.c')
-rw-r--r-- | sound/pci/oxygen/oxygen_mixer.c | 112 |
1 files changed, 89 insertions, 23 deletions
diff --git a/sound/pci/oxygen/oxygen_mixer.c b/sound/pci/oxygen/oxygen_mixer.c index 2849b36f5f7e..26c7e8bcb229 100644 --- a/sound/pci/oxygen/oxygen_mixer.c +++ b/sound/pci/oxygen/oxygen_mixer.c | |||
@@ -31,7 +31,7 @@ static int dac_volume_info(struct snd_kcontrol *ctl, | |||
31 | struct oxygen *chip = ctl->private_data; | 31 | struct oxygen *chip = ctl->private_data; |
32 | 32 | ||
33 | info->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | 33 | info->type = SNDRV_CTL_ELEM_TYPE_INTEGER; |
34 | info->count = chip->model.dac_channels; | 34 | info->count = chip->model.dac_channels_mixer; |
35 | info->value.integer.min = chip->model.dac_volume_min; | 35 | info->value.integer.min = chip->model.dac_volume_min; |
36 | info->value.integer.max = chip->model.dac_volume_max; | 36 | info->value.integer.max = chip->model.dac_volume_max; |
37 | return 0; | 37 | return 0; |
@@ -44,7 +44,7 @@ static int dac_volume_get(struct snd_kcontrol *ctl, | |||
44 | unsigned int i; | 44 | unsigned int i; |
45 | 45 | ||
46 | mutex_lock(&chip->mutex); | 46 | mutex_lock(&chip->mutex); |
47 | for (i = 0; i < chip->model.dac_channels; ++i) | 47 | for (i = 0; i < chip->model.dac_channels_mixer; ++i) |
48 | value->value.integer.value[i] = chip->dac_volume[i]; | 48 | value->value.integer.value[i] = chip->dac_volume[i]; |
49 | mutex_unlock(&chip->mutex); | 49 | mutex_unlock(&chip->mutex); |
50 | return 0; | 50 | return 0; |
@@ -59,7 +59,7 @@ static int dac_volume_put(struct snd_kcontrol *ctl, | |||
59 | 59 | ||
60 | changed = 0; | 60 | changed = 0; |
61 | mutex_lock(&chip->mutex); | 61 | mutex_lock(&chip->mutex); |
62 | for (i = 0; i < chip->model.dac_channels; ++i) | 62 | for (i = 0; i < chip->model.dac_channels_mixer; ++i) |
63 | if (value->value.integer.value[i] != chip->dac_volume[i]) { | 63 | if (value->value.integer.value[i] != chip->dac_volume[i]) { |
64 | chip->dac_volume[i] = value->value.integer.value[i]; | 64 | chip->dac_volume[i] = value->value.integer.value[i]; |
65 | changed = 1; | 65 | changed = 1; |
@@ -97,6 +97,16 @@ static int dac_mute_put(struct snd_kcontrol *ctl, | |||
97 | return changed; | 97 | return changed; |
98 | } | 98 | } |
99 | 99 | ||
100 | static unsigned int upmix_item_count(struct oxygen *chip) | ||
101 | { | ||
102 | if (chip->model.dac_channels_pcm < 8) | ||
103 | return 2; | ||
104 | else if (chip->model.update_center_lfe_mix) | ||
105 | return 5; | ||
106 | else | ||
107 | return 3; | ||
108 | } | ||
109 | |||
100 | static int upmix_info(struct snd_kcontrol *ctl, struct snd_ctl_elem_info *info) | 110 | static int upmix_info(struct snd_kcontrol *ctl, struct snd_ctl_elem_info *info) |
101 | { | 111 | { |
102 | static const char *const names[5] = { | 112 | static const char *const names[5] = { |
@@ -107,15 +117,9 @@ static int upmix_info(struct snd_kcontrol *ctl, struct snd_ctl_elem_info *info) | |||
107 | "Front+Surround+Center/LFE+Back", | 117 | "Front+Surround+Center/LFE+Back", |
108 | }; | 118 | }; |
109 | struct oxygen *chip = ctl->private_data; | 119 | struct oxygen *chip = ctl->private_data; |
110 | unsigned int count = chip->model.update_center_lfe_mix ? 5 : 3; | 120 | unsigned int count = upmix_item_count(chip); |
111 | 121 | ||
112 | info->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | 122 | return snd_ctl_enum_info(info, 1, count, names); |
113 | info->count = 1; | ||
114 | info->value.enumerated.items = count; | ||
115 | if (info->value.enumerated.item >= count) | ||
116 | info->value.enumerated.item = count - 1; | ||
117 | strcpy(info->value.enumerated.name, names[info->value.enumerated.item]); | ||
118 | return 0; | ||
119 | } | 123 | } |
120 | 124 | ||
121 | static int upmix_get(struct snd_kcontrol *ctl, struct snd_ctl_elem_value *value) | 125 | static int upmix_get(struct snd_kcontrol *ctl, struct snd_ctl_elem_value *value) |
@@ -176,6 +180,8 @@ void oxygen_update_dac_routing(struct oxygen *chip) | |||
176 | (1 << OXYGEN_PLAY_DAC1_SOURCE_SHIFT) | | 180 | (1 << OXYGEN_PLAY_DAC1_SOURCE_SHIFT) | |
177 | (2 << OXYGEN_PLAY_DAC2_SOURCE_SHIFT) | | 181 | (2 << OXYGEN_PLAY_DAC2_SOURCE_SHIFT) | |
178 | (3 << OXYGEN_PLAY_DAC3_SOURCE_SHIFT); | 182 | (3 << OXYGEN_PLAY_DAC3_SOURCE_SHIFT); |
183 | if (chip->model.adjust_dac_routing) | ||
184 | reg_value = chip->model.adjust_dac_routing(chip, reg_value); | ||
179 | oxygen_write16_masked(chip, OXYGEN_PLAY_ROUTING, reg_value, | 185 | oxygen_write16_masked(chip, OXYGEN_PLAY_ROUTING, reg_value, |
180 | OXYGEN_PLAY_DAC0_SOURCE_MASK | | 186 | OXYGEN_PLAY_DAC0_SOURCE_MASK | |
181 | OXYGEN_PLAY_DAC1_SOURCE_MASK | | 187 | OXYGEN_PLAY_DAC1_SOURCE_MASK | |
@@ -188,7 +194,7 @@ void oxygen_update_dac_routing(struct oxygen *chip) | |||
188 | static int upmix_put(struct snd_kcontrol *ctl, struct snd_ctl_elem_value *value) | 194 | static int upmix_put(struct snd_kcontrol *ctl, struct snd_ctl_elem_value *value) |
189 | { | 195 | { |
190 | struct oxygen *chip = ctl->private_data; | 196 | struct oxygen *chip = ctl->private_data; |
191 | unsigned int count = chip->model.update_center_lfe_mix ? 5 : 3; | 197 | unsigned int count = upmix_item_count(chip); |
192 | int changed; | 198 | int changed; |
193 | 199 | ||
194 | if (value->value.enumerated.item[0] >= count) | 200 | if (value->value.enumerated.item[0] >= count) |
@@ -430,30 +436,31 @@ static int spdif_input_default_get(struct snd_kcontrol *ctl, | |||
430 | return 0; | 436 | return 0; |
431 | } | 437 | } |
432 | 438 | ||
433 | static int spdif_loopback_get(struct snd_kcontrol *ctl, | 439 | static int spdif_bit_switch_get(struct snd_kcontrol *ctl, |
434 | struct snd_ctl_elem_value *value) | 440 | struct snd_ctl_elem_value *value) |
435 | { | 441 | { |
436 | struct oxygen *chip = ctl->private_data; | 442 | struct oxygen *chip = ctl->private_data; |
443 | u32 bit = ctl->private_value; | ||
437 | 444 | ||
438 | value->value.integer.value[0] = | 445 | value->value.integer.value[0] = |
439 | !!(oxygen_read32(chip, OXYGEN_SPDIF_CONTROL) | 446 | !!(oxygen_read32(chip, OXYGEN_SPDIF_CONTROL) & bit); |
440 | & OXYGEN_SPDIF_LOOPBACK); | ||
441 | return 0; | 447 | return 0; |
442 | } | 448 | } |
443 | 449 | ||
444 | static int spdif_loopback_put(struct snd_kcontrol *ctl, | 450 | static int spdif_bit_switch_put(struct snd_kcontrol *ctl, |
445 | struct snd_ctl_elem_value *value) | 451 | struct snd_ctl_elem_value *value) |
446 | { | 452 | { |
447 | struct oxygen *chip = ctl->private_data; | 453 | struct oxygen *chip = ctl->private_data; |
454 | u32 bit = ctl->private_value; | ||
448 | u32 oldreg, newreg; | 455 | u32 oldreg, newreg; |
449 | int changed; | 456 | int changed; |
450 | 457 | ||
451 | spin_lock_irq(&chip->reg_lock); | 458 | spin_lock_irq(&chip->reg_lock); |
452 | oldreg = oxygen_read32(chip, OXYGEN_SPDIF_CONTROL); | 459 | oldreg = oxygen_read32(chip, OXYGEN_SPDIF_CONTROL); |
453 | if (value->value.integer.value[0]) | 460 | if (value->value.integer.value[0]) |
454 | newreg = oldreg | OXYGEN_SPDIF_LOOPBACK; | 461 | newreg = oldreg | bit; |
455 | else | 462 | else |
456 | newreg = oldreg & ~OXYGEN_SPDIF_LOOPBACK; | 463 | newreg = oldreg & ~bit; |
457 | changed = newreg != oldreg; | 464 | changed = newreg != oldreg; |
458 | if (changed) | 465 | if (changed) |
459 | oxygen_write32(chip, OXYGEN_SPDIF_CONTROL, newreg); | 466 | oxygen_write32(chip, OXYGEN_SPDIF_CONTROL, newreg); |
@@ -644,6 +651,46 @@ static int ac97_volume_put(struct snd_kcontrol *ctl, | |||
644 | return change; | 651 | return change; |
645 | } | 652 | } |
646 | 653 | ||
654 | static int mic_fmic_source_info(struct snd_kcontrol *ctl, | ||
655 | struct snd_ctl_elem_info *info) | ||
656 | { | ||
657 | static const char *const names[] = { "Mic Jack", "Front Panel" }; | ||
658 | |||
659 | return snd_ctl_enum_info(info, 1, 2, names); | ||
660 | } | ||
661 | |||
662 | static int mic_fmic_source_get(struct snd_kcontrol *ctl, | ||
663 | struct snd_ctl_elem_value *value) | ||
664 | { | ||
665 | struct oxygen *chip = ctl->private_data; | ||
666 | |||
667 | mutex_lock(&chip->mutex); | ||
668 | value->value.enumerated.item[0] = | ||
669 | !!(oxygen_read_ac97(chip, 0, CM9780_JACK) & CM9780_FMIC2MIC); | ||
670 | mutex_unlock(&chip->mutex); | ||
671 | return 0; | ||
672 | } | ||
673 | |||
674 | static int mic_fmic_source_put(struct snd_kcontrol *ctl, | ||
675 | struct snd_ctl_elem_value *value) | ||
676 | { | ||
677 | struct oxygen *chip = ctl->private_data; | ||
678 | u16 oldreg, newreg; | ||
679 | int change; | ||
680 | |||
681 | mutex_lock(&chip->mutex); | ||
682 | oldreg = oxygen_read_ac97(chip, 0, CM9780_JACK); | ||
683 | if (value->value.enumerated.item[0]) | ||
684 | newreg = oldreg | CM9780_FMIC2MIC; | ||
685 | else | ||
686 | newreg = oldreg & ~CM9780_FMIC2MIC; | ||
687 | change = newreg != oldreg; | ||
688 | if (change) | ||
689 | oxygen_write_ac97(chip, 0, CM9780_JACK, newreg); | ||
690 | mutex_unlock(&chip->mutex); | ||
691 | return change; | ||
692 | } | ||
693 | |||
647 | static int ac97_fp_rec_volume_info(struct snd_kcontrol *ctl, | 694 | static int ac97_fp_rec_volume_info(struct snd_kcontrol *ctl, |
648 | struct snd_ctl_elem_info *info) | 695 | struct snd_ctl_elem_info *info) |
649 | { | 696 | { |
@@ -791,8 +838,17 @@ static const struct snd_kcontrol_new spdif_input_controls[] = { | |||
791 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 838 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
792 | .name = SNDRV_CTL_NAME_IEC958("Loopback ", NONE, SWITCH), | 839 | .name = SNDRV_CTL_NAME_IEC958("Loopback ", NONE, SWITCH), |
793 | .info = snd_ctl_boolean_mono_info, | 840 | .info = snd_ctl_boolean_mono_info, |
794 | .get = spdif_loopback_get, | 841 | .get = spdif_bit_switch_get, |
795 | .put = spdif_loopback_put, | 842 | .put = spdif_bit_switch_put, |
843 | .private_value = OXYGEN_SPDIF_LOOPBACK, | ||
844 | }, | ||
845 | { | ||
846 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
847 | .name = SNDRV_CTL_NAME_IEC958("Validity Check ",CAPTURE,SWITCH), | ||
848 | .info = snd_ctl_boolean_mono_info, | ||
849 | .get = spdif_bit_switch_get, | ||
850 | .put = spdif_bit_switch_put, | ||
851 | .private_value = OXYGEN_SPDIF_SPDVALID, | ||
796 | }, | 852 | }, |
797 | }; | 853 | }; |
798 | 854 | ||
@@ -908,6 +964,13 @@ static const struct snd_kcontrol_new ac97_controls[] = { | |||
908 | AC97_VOLUME("Mic Capture Volume", 0, AC97_MIC, 0), | 964 | AC97_VOLUME("Mic Capture Volume", 0, AC97_MIC, 0), |
909 | AC97_SWITCH("Mic Capture Switch", 0, AC97_MIC, 15, 1), | 965 | AC97_SWITCH("Mic Capture Switch", 0, AC97_MIC, 15, 1), |
910 | AC97_SWITCH("Mic Boost (+20dB)", 0, AC97_MIC, 6, 0), | 966 | AC97_SWITCH("Mic Boost (+20dB)", 0, AC97_MIC, 6, 0), |
967 | { | ||
968 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
969 | .name = "Mic Source Capture Enum", | ||
970 | .info = mic_fmic_source_info, | ||
971 | .get = mic_fmic_source_get, | ||
972 | .put = mic_fmic_source_put, | ||
973 | }, | ||
911 | AC97_SWITCH("Line Capture Switch", 0, AC97_LINE, 15, 1), | 974 | AC97_SWITCH("Line Capture Switch", 0, AC97_LINE, 15, 1), |
912 | AC97_VOLUME("CD Capture Volume", 0, AC97_CD, 1), | 975 | AC97_VOLUME("CD Capture Volume", 0, AC97_CD, 1), |
913 | AC97_SWITCH("CD Capture Switch", 0, AC97_CD, 15, 1), | 976 | AC97_SWITCH("CD Capture Switch", 0, AC97_CD, 15, 1), |
@@ -970,7 +1033,10 @@ static int add_controls(struct oxygen *chip, | |||
970 | continue; | 1033 | continue; |
971 | } | 1034 | } |
972 | if (!strcmp(template.name, "Stereo Upmixing") && | 1035 | if (!strcmp(template.name, "Stereo Upmixing") && |
973 | chip->model.dac_channels == 2) | 1036 | chip->model.dac_channels_pcm == 2) |
1037 | continue; | ||
1038 | if (!strcmp(template.name, "Mic Source Capture Enum") && | ||
1039 | !(chip->model.device_config & AC97_FMIC_SWITCH)) | ||
974 | continue; | 1040 | continue; |
975 | if (!strncmp(template.name, "CD Capture ", 11) && | 1041 | if (!strncmp(template.name, "CD Capture ", 11) && |
976 | !(chip->model.device_config & AC97_CD_INPUT)) | 1042 | !(chip->model.device_config & AC97_CD_INPUT)) |