aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/oxygen/oxygen.c
diff options
context:
space:
mode:
authorClemens Ladisch <clemens@ladisch.de>2011-01-10 10:35:38 -0500
committerTakashi Iwai <tiwai@suse.de>2011-01-10 10:47:21 -0500
commit64878dfbf755446f025965b742e56e4739a33b37 (patch)
treeff701324944bd1dc2bd35293a048f9c72140fcbd /sound/pci/oxygen/oxygen.c
parent860cffd57acff68e8bc5465f4dd3b7d338fb8e62 (diff)
ALSA: oxygen: X-Meridian: add S/PDIF source selection
Add a mixer control to select between the on-board and extension board S/PDIF inputs for the X-Meridian (2G). Signed-off-by: Clemens Ladisch <clemens@ladisch.de> Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci/oxygen/oxygen.c')
-rw-r--r--sound/pci/oxygen/oxygen.c77
1 files changed, 75 insertions, 2 deletions
diff --git a/sound/pci/oxygen/oxygen.c b/sound/pci/oxygen/oxygen.c
index 45427d85045e..22cbf3e67ac4 100644
--- a/sound/pci/oxygen/oxygen.c
+++ b/sound/pci/oxygen/oxygen.c
@@ -28,7 +28,13 @@
28 * 28 *
29 * GPIO 0 -> DFS0 of AK5385 29 * GPIO 0 -> DFS0 of AK5385
30 * GPIO 1 -> DFS1 of AK5385 30 * GPIO 1 -> DFS1 of AK5385
31 * GPIO 8 -> enable headphone amplifier on HT-Omega models 31 *
32 * X-Meridian models:
33 * GPIO 4 -> enable extension S/PDIF input
34 * GPIO 6 -> enable on-board S/PDIF input
35 *
36 * Claro models:
37 * GPIO 8 -> enable headphone amplifier
32 * 38 *
33 * CM9780: 39 * CM9780:
34 * 40 *
@@ -124,6 +130,10 @@ MODULE_DEVICE_TABLE(pci, oxygen_ids);
124#define GPIO_AK5385_DFS_DOUBLE 0x0001 130#define GPIO_AK5385_DFS_DOUBLE 0x0001
125#define GPIO_AK5385_DFS_QUAD 0x0002 131#define GPIO_AK5385_DFS_QUAD 0x0002
126 132
133#define GPIO_MERIDIAN_DIG_MASK 0x0050
134#define GPIO_MERIDIAN_DIG_EXT 0x0010
135#define GPIO_MERIDIAN_DIG_BOARD 0x0040
136
127#define GPIO_CLARO_HP 0x0100 137#define GPIO_CLARO_HP 0x0100
128 138
129struct generic_data { 139struct generic_data {
@@ -238,6 +248,10 @@ static void generic_init(struct oxygen *chip)
238 248
239static void meridian_init(struct oxygen *chip) 249static void meridian_init(struct oxygen *chip)
240{ 250{
251 oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL,
252 GPIO_MERIDIAN_DIG_MASK);
253 oxygen_write16_masked(chip, OXYGEN_GPIO_DATA,
254 GPIO_MERIDIAN_DIG_BOARD, GPIO_MERIDIAN_DIG_MASK);
241 ak4396_init(chip); 255 ak4396_init(chip);
242 ak5385_init(chip); 256 ak5385_init(chip);
243} 257}
@@ -506,6 +520,51 @@ static const struct snd_kcontrol_new hpf_control = {
506 .put = hpf_put, 520 .put = hpf_put,
507}; 521};
508 522
523static int meridian_dig_source_info(struct snd_kcontrol *ctl, struct snd_ctl_elem_info *info)
524{
525 static const char *const names[2] = { "On-board", "Extension" };
526
527 return snd_ctl_enum_info(info, 1, 2, names);
528}
529
530static int meridian_dig_source_get(struct snd_kcontrol *ctl, struct snd_ctl_elem_value *value)
531{
532 struct oxygen *chip = ctl->private_data;
533
534 value->value.enumerated.item[0] =
535 !!(oxygen_read16(chip, OXYGEN_GPIO_DATA) &
536 GPIO_MERIDIAN_DIG_EXT);
537 return 0;
538}
539
540static int meridian_dig_source_put(struct snd_kcontrol *ctl, struct snd_ctl_elem_value *value)
541{
542 struct oxygen *chip = ctl->private_data;
543 u16 old_reg, new_reg;
544 int changed;
545
546 mutex_lock(&chip->mutex);
547 old_reg = oxygen_read16(chip, OXYGEN_GPIO_DATA);
548 new_reg = old_reg & ~GPIO_MERIDIAN_DIG_MASK;
549 if (value->value.enumerated.item[0] == 0)
550 new_reg |= GPIO_MERIDIAN_DIG_BOARD;
551 else
552 new_reg |= GPIO_MERIDIAN_DIG_EXT;
553 changed = new_reg != old_reg;
554 if (changed)
555 oxygen_write16(chip, OXYGEN_GPIO_DATA, new_reg);
556 mutex_unlock(&chip->mutex);
557 return changed;
558}
559
560static const struct snd_kcontrol_new meridian_dig_source_control = {
561 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
562 .name = "IEC958 Source Capture Enum",
563 .info = meridian_dig_source_info,
564 .get = meridian_dig_source_get,
565 .put = meridian_dig_source_put,
566};
567
509static int generic_mixer_init(struct oxygen *chip) 568static int generic_mixer_init(struct oxygen *chip)
510{ 569{
511 return snd_ctl_add(chip->card, snd_ctl_new1(&rolloff_control, chip)); 570 return snd_ctl_add(chip->card, snd_ctl_new1(&rolloff_control, chip));
@@ -524,6 +583,20 @@ static int generic_wm8785_mixer_init(struct oxygen *chip)
524 return 0; 583 return 0;
525} 584}
526 585
586static int meridian_mixer_init(struct oxygen *chip)
587{
588 int err;
589
590 err = generic_mixer_init(chip);
591 if (err < 0)
592 return err;
593 err = snd_ctl_add(chip->card,
594 snd_ctl_new1(&meridian_dig_source_control, chip));
595 if (err < 0)
596 return err;
597 return 0;
598}
599
527static void dump_ak4396_registers(struct oxygen *chip, 600static void dump_ak4396_registers(struct oxygen *chip,
528 struct snd_info_buffer *buffer) 601 struct snd_info_buffer *buffer)
529{ 602{
@@ -600,7 +673,7 @@ static int __devinit get_oxygen_model(struct oxygen *chip,
600 switch (id->driver_data) { 673 switch (id->driver_data) {
601 case MODEL_MERIDIAN: 674 case MODEL_MERIDIAN:
602 chip->model.init = meridian_init; 675 chip->model.init = meridian_init;
603 chip->model.mixer_init = generic_mixer_init; 676 chip->model.mixer_init = meridian_mixer_init;
604 chip->model.resume = meridian_resume; 677 chip->model.resume = meridian_resume;
605 chip->model.set_adc_params = set_ak5385_params; 678 chip->model.set_adc_params = set_ak5385_params;
606 chip->model.dump_registers = dump_ak4396_registers; 679 chip->model.dump_registers = dump_ak4396_registers;