diff options
author | Clemens Ladisch <clemens@ladisch.de> | 2011-01-10 10:35:38 -0500 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2011-01-10 10:47:21 -0500 |
commit | 64878dfbf755446f025965b742e56e4739a33b37 (patch) | |
tree | ff701324944bd1dc2bd35293a048f9c72140fcbd /sound/pci/oxygen/oxygen.c | |
parent | 860cffd57acff68e8bc5465f4dd3b7d338fb8e62 (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.c | 77 |
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 | ||
129 | struct generic_data { | 139 | struct generic_data { |
@@ -238,6 +248,10 @@ static void generic_init(struct oxygen *chip) | |||
238 | 248 | ||
239 | static void meridian_init(struct oxygen *chip) | 249 | static 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 | ||
523 | static 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 | |||
530 | static 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 | |||
540 | static 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 | |||
560 | static 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 | |||
509 | static int generic_mixer_init(struct oxygen *chip) | 568 | static 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 | ||
586 | static 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 | |||
527 | static void dump_ak4396_registers(struct oxygen *chip, | 600 | static 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; |