aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/oxygen
diff options
context:
space:
mode:
Diffstat (limited to 'sound/pci/oxygen')
-rw-r--r--sound/pci/oxygen/oxygen_lib.c16
-rw-r--r--sound/pci/oxygen/oxygen_mixer.c156
2 files changed, 164 insertions, 8 deletions
diff --git a/sound/pci/oxygen/oxygen_lib.c b/sound/pci/oxygen/oxygen_lib.c
index 78c21155218e..a1abb50eedb5 100644
--- a/sound/pci/oxygen/oxygen_lib.c
+++ b/sound/pci/oxygen/oxygen_lib.c
@@ -267,20 +267,20 @@ static void oxygen_init(struct oxygen *chip)
267 (OXYGEN_FORMAT_16 << OXYGEN_MULTICH_FORMAT_SHIFT)); 267 (OXYGEN_FORMAT_16 << OXYGEN_MULTICH_FORMAT_SHIFT));
268 oxygen_write8(chip, OXYGEN_REC_CHANNELS, OXYGEN_REC_CHANNELS_2_2_2); 268 oxygen_write8(chip, OXYGEN_REC_CHANNELS, OXYGEN_REC_CHANNELS_2_2_2);
269 oxygen_write16(chip, OXYGEN_I2S_MULTICH_FORMAT, 269 oxygen_write16(chip, OXYGEN_I2S_MULTICH_FORMAT,
270 OXYGEN_RATE_48000 | OXYGEN_I2S_FORMAT_LJUST | 270 OXYGEN_RATE_48000 | chip->model->dac_i2s_format |
271 OXYGEN_I2S_MCLK_128 | OXYGEN_I2S_BITS_16 | 271 OXYGEN_I2S_MCLK_256 | OXYGEN_I2S_BITS_16 |
272 OXYGEN_I2S_MASTER | OXYGEN_I2S_BCLK_64); 272 OXYGEN_I2S_MASTER | OXYGEN_I2S_BCLK_64);
273 oxygen_write16(chip, OXYGEN_I2S_A_FORMAT, 273 oxygen_write16(chip, OXYGEN_I2S_A_FORMAT,
274 OXYGEN_RATE_48000 | OXYGEN_I2S_FORMAT_LJUST | 274 OXYGEN_RATE_48000 | chip->model->adc_i2s_format |
275 OXYGEN_I2S_MCLK_128 | OXYGEN_I2S_BITS_16 | 275 OXYGEN_I2S_MCLK_256 | OXYGEN_I2S_BITS_16 |
276 OXYGEN_I2S_MASTER | OXYGEN_I2S_BCLK_64); 276 OXYGEN_I2S_MASTER | OXYGEN_I2S_BCLK_64);
277 oxygen_write16(chip, OXYGEN_I2S_B_FORMAT, 277 oxygen_write16(chip, OXYGEN_I2S_B_FORMAT,
278 OXYGEN_RATE_48000 | OXYGEN_I2S_FORMAT_LJUST | 278 OXYGEN_RATE_48000 | chip->model->adc_i2s_format |
279 OXYGEN_I2S_MCLK_128 | OXYGEN_I2S_BITS_16 | 279 OXYGEN_I2S_MCLK_256 | OXYGEN_I2S_BITS_16 |
280 OXYGEN_I2S_MASTER | OXYGEN_I2S_BCLK_64); 280 OXYGEN_I2S_MASTER | OXYGEN_I2S_BCLK_64);
281 oxygen_write16(chip, OXYGEN_I2S_C_FORMAT, 281 oxygen_write16(chip, OXYGEN_I2S_C_FORMAT,
282 OXYGEN_RATE_48000 | OXYGEN_I2S_FORMAT_LJUST | 282 OXYGEN_RATE_48000 | chip->model->adc_i2s_format |
283 OXYGEN_I2S_MCLK_128 | OXYGEN_I2S_BITS_16 | 283 OXYGEN_I2S_MCLK_256 | OXYGEN_I2S_BITS_16 |
284 OXYGEN_I2S_MASTER | OXYGEN_I2S_BCLK_64); 284 OXYGEN_I2S_MASTER | OXYGEN_I2S_BCLK_64);
285 oxygen_write32_masked(chip, OXYGEN_SPDIF_CONTROL, 285 oxygen_write32_masked(chip, OXYGEN_SPDIF_CONTROL,
286 OXYGEN_SPDIF_SENSE_MASK | 286 OXYGEN_SPDIF_SENSE_MASK |
diff --git a/sound/pci/oxygen/oxygen_mixer.c b/sound/pci/oxygen/oxygen_mixer.c
index a8e4623415d9..4e77b79b3b6e 100644
--- a/sound/pci/oxygen/oxygen_mixer.c
+++ b/sound/pci/oxygen/oxygen_mixer.c
@@ -446,6 +446,50 @@ static int spdif_loopback_put(struct snd_kcontrol *ctl,
446 return changed; 446 return changed;
447} 447}
448 448
449static int monitor_volume_info(struct snd_kcontrol *ctl,
450 struct snd_ctl_elem_info *info)
451{
452 info->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
453 info->count = 1;
454 info->value.integer.min = 0;
455 info->value.integer.max = 1;
456 return 0;
457}
458
459static int monitor_get(struct snd_kcontrol *ctl,
460 struct snd_ctl_elem_value *value)
461{
462 struct oxygen *chip = ctl->private_data;
463 u8 bit = ctl->private_value;
464 int invert = ctl->private_value & (1 << 8);
465
466 value->value.integer.value[0] =
467 !!invert ^ !!(oxygen_read8(chip, OXYGEN_ADC_MONITOR) & bit);
468 return 0;
469}
470
471static int monitor_put(struct snd_kcontrol *ctl,
472 struct snd_ctl_elem_value *value)
473{
474 struct oxygen *chip = ctl->private_data;
475 u8 bit = ctl->private_value;
476 int invert = ctl->private_value & (1 << 8);
477 u8 oldreg, newreg;
478 int changed;
479
480 spin_lock_irq(&chip->reg_lock);
481 oldreg = oxygen_read8(chip, OXYGEN_ADC_MONITOR);
482 if ((!!value->value.integer.value[0] ^ !!invert) != 0)
483 newreg = oldreg | bit;
484 else
485 newreg = oldreg & ~bit;
486 changed = newreg != oldreg;
487 if (changed)
488 oxygen_write8(chip, OXYGEN_ADC_MONITOR, newreg);
489 spin_unlock_irq(&chip->reg_lock);
490 return changed;
491}
492
449static int ac97_switch_get(struct snd_kcontrol *ctl, 493static int ac97_switch_get(struct snd_kcontrol *ctl,
450 struct snd_ctl_elem_value *value) 494 struct snd_ctl_elem_value *value)
451{ 495{
@@ -608,6 +652,7 @@ static int ac97_fp_rec_volume_put(struct snd_kcontrol *ctl,
608 .private_value = ((codec) << 24) | (index), \ 652 .private_value = ((codec) << 24) | (index), \
609 } 653 }
610 654
655static DECLARE_TLV_DB_SCALE(monitor_db_scale, -1000, 1000, 0);
611static DECLARE_TLV_DB_SCALE(ac97_db_scale, -3450, 150, 0); 656static DECLARE_TLV_DB_SCALE(ac97_db_scale, -3450, 150, 0);
612static DECLARE_TLV_DB_SCALE(ac97_rec_db_scale, 0, 150, 0); 657static DECLARE_TLV_DB_SCALE(ac97_rec_db_scale, 0, 150, 0);
613 658
@@ -692,6 +737,93 @@ static const struct snd_kcontrol_new controls[] = {
692 }, 737 },
693}; 738};
694 739
740static const struct snd_kcontrol_new monitor_a_controls[] = {
741 {
742 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
743 .name = "Analog Input Monitor Switch",
744 .info = snd_ctl_boolean_mono_info,
745 .get = monitor_get,
746 .put = monitor_put,
747 .private_value = OXYGEN_ADC_MONITOR_A,
748 },
749 {
750 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
751 .name = "Analog Input Monitor Volume",
752 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
753 SNDRV_CTL_ELEM_ACCESS_TLV_READ,
754 .info = monitor_volume_info,
755 .get = monitor_get,
756 .put = monitor_put,
757 .private_value = OXYGEN_ADC_MONITOR_A_HALF_VOL | (1 << 8),
758 .tlv = { .p = monitor_db_scale, },
759 },
760};
761static const struct snd_kcontrol_new monitor_b_controls[] = {
762 {
763 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
764 .name = "Analog Input Monitor Switch",
765 .info = snd_ctl_boolean_mono_info,
766 .get = monitor_get,
767 .put = monitor_put,
768 .private_value = OXYGEN_ADC_MONITOR_B,
769 },
770 {
771 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
772 .name = "Analog Input Monitor Volume",
773 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
774 SNDRV_CTL_ELEM_ACCESS_TLV_READ,
775 .info = monitor_volume_info,
776 .get = monitor_get,
777 .put = monitor_put,
778 .private_value = OXYGEN_ADC_MONITOR_B_HALF_VOL | (1 << 8),
779 .tlv = { .p = monitor_db_scale, },
780 },
781};
782static const struct snd_kcontrol_new monitor_2nd_b_controls[] = {
783 {
784 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
785 .name = "Analog Input Monitor Switch",
786 .index = 1,
787 .info = snd_ctl_boolean_mono_info,
788 .get = monitor_get,
789 .put = monitor_put,
790 .private_value = OXYGEN_ADC_MONITOR_B,
791 },
792 {
793 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
794 .name = "Analog Input Monitor Volume",
795 .index = 1,
796 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
797 SNDRV_CTL_ELEM_ACCESS_TLV_READ,
798 .info = monitor_volume_info,
799 .get = monitor_get,
800 .put = monitor_put,
801 .private_value = OXYGEN_ADC_MONITOR_B_HALF_VOL | (1 << 8),
802 .tlv = { .p = monitor_db_scale, },
803 },
804};
805static const struct snd_kcontrol_new monitor_c_controls[] = {
806 {
807 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
808 .name = "Digital Input Monitor Switch",
809 .info = snd_ctl_boolean_mono_info,
810 .get = monitor_get,
811 .put = monitor_put,
812 .private_value = OXYGEN_ADC_MONITOR_C,
813 },
814 {
815 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
816 .name = "Digital Input Monitor Volume",
817 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
818 SNDRV_CTL_ELEM_ACCESS_TLV_READ,
819 .info = monitor_volume_info,
820 .get = monitor_get,
821 .put = monitor_put,
822 .private_value = OXYGEN_ADC_MONITOR_C_HALF_VOL | (1 << 8),
823 .tlv = { .p = monitor_db_scale, },
824 },
825};
826
695static const struct snd_kcontrol_new ac97_controls[] = { 827static const struct snd_kcontrol_new ac97_controls[] = {
696 AC97_VOLUME("Mic Capture Volume", 0, AC97_MIC), 828 AC97_VOLUME("Mic Capture Volume", 0, AC97_MIC),
697 AC97_SWITCH("Mic Capture Switch", 0, AC97_MIC, 15, 1), 829 AC97_SWITCH("Mic Capture Switch", 0, AC97_MIC, 15, 1),
@@ -778,6 +910,30 @@ int oxygen_mixer_init(struct oxygen *chip)
778 err = add_controls(chip, controls, ARRAY_SIZE(controls)); 910 err = add_controls(chip, controls, ARRAY_SIZE(controls));
779 if (err < 0) 911 if (err < 0)
780 return err; 912 return err;
913 if (chip->model->used_channels & OXYGEN_CHANNEL_A) {
914 err = add_controls(chip, monitor_a_controls,
915 ARRAY_SIZE(monitor_a_controls));
916 if (err < 0)
917 return err;
918 } else if (chip->model->used_channels & OXYGEN_CHANNEL_B) {
919 err = add_controls(chip, monitor_b_controls,
920 ARRAY_SIZE(monitor_b_controls));
921 if (err < 0)
922 return err;
923 }
924 if ((chip->model->used_channels & (OXYGEN_CHANNEL_A | OXYGEN_CHANNEL_B))
925 == (OXYGEN_CHANNEL_A | OXYGEN_CHANNEL_B)) {
926 err = add_controls(chip, monitor_2nd_b_controls,
927 ARRAY_SIZE(monitor_2nd_b_controls));
928 if (err < 0)
929 return err;
930 }
931 if (chip->model->used_channels & OXYGEN_CHANNEL_C) {
932 err = add_controls(chip, monitor_c_controls,
933 ARRAY_SIZE(monitor_c_controls));
934 if (err < 0)
935 return err;
936 }
781 if (chip->has_ac97_0) { 937 if (chip->has_ac97_0) {
782 err = add_controls(chip, ac97_controls, 938 err = add_controls(chip, ac97_controls,
783 ARRAY_SIZE(ac97_controls)); 939 ARRAY_SIZE(ac97_controls));