aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci
diff options
context:
space:
mode:
authorClemens Ladisch <clemens@ladisch.de>2008-03-19 03:17:33 -0400
committerTakashi Iwai <tiwai@suse.de>2008-04-24 06:00:27 -0400
commitfa5d8106cb52e5df28673f59cc25af520dc83382 (patch)
treeb00c97309fddb285ff0ba5e61957ecaad4e46504 /sound/pci
parent33fa724e291d3cc6c319f7db487e6e084ef5d4b5 (diff)
[ALSA] oxygen: add monitor controls
Add controls to enable monitoring of the analog and digital inputs. To allow monitoring after loading the driver when nothing has been played back or recorded yet, the I2S input and outputs are initialized to a valid configuration. Signed-off-by: Clemens Ladisch <clemens@ladisch.de> Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci')
-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));