diff options
author | Roman Volkov <v1ron@mail.ru> | 2014-01-24 07:18:15 -0500 |
---|---|---|
committer | Clemens Ladisch <clemens@ladisch.de> | 2014-01-29 14:45:50 -0500 |
commit | 2809cb84d1672b639a4a41a0fa077fb554699072 (patch) | |
tree | 32b117862dc307aa0f579191ced847d0c54ad528 /sound | |
parent | 3dd77654fb1d7f68b9739f3039bad8dbbc0739f8 (diff) |
ALSA: oxygen: Xonar DG(X): modify playback output select
Change the order of elements in the output select control. This will
reduce the number of relay switches. Change 'put' function to call the
oxygen_update_dac_routing() function. Otherwise multichannel playback
does not work. Also there is a new function to apply settings, this
prevents from duplicating the code.
Signed-off-by: Roman Volkov <v1ron@mail.ru>
Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
Diffstat (limited to 'sound')
-rw-r--r-- | sound/pci/oxygen/xonar_dg.c | 2 | ||||
-rw-r--r-- | sound/pci/oxygen/xonar_dg.h | 3 | ||||
-rw-r--r-- | sound/pci/oxygen/xonar_dg_mixer.c | 75 |
3 files changed, 47 insertions, 33 deletions
diff --git a/sound/pci/oxygen/xonar_dg.c b/sound/pci/oxygen/xonar_dg.c index d12d83554abb..6cec934e6628 100644 --- a/sound/pci/oxygen/xonar_dg.c +++ b/sound/pci/oxygen/xonar_dg.c | |||
@@ -268,7 +268,7 @@ unsigned int adjust_dg_dac_routing(struct oxygen *chip, | |||
268 | struct dg *data = chip->model_data; | 268 | struct dg *data = chip->model_data; |
269 | unsigned int routing = 0; | 269 | unsigned int routing = 0; |
270 | 270 | ||
271 | switch (data->pcm_output) { | 271 | switch (data->output_sel) { |
272 | case PLAYBACK_DST_HP: | 272 | case PLAYBACK_DST_HP: |
273 | case PLAYBACK_DST_HP_FP: | 273 | case PLAYBACK_DST_HP_FP: |
274 | oxygen_write8_masked(chip, OXYGEN_PLAY_ROUTING, | 274 | oxygen_write8_masked(chip, OXYGEN_PLAY_ROUTING, |
diff --git a/sound/pci/oxygen/xonar_dg.h b/sound/pci/oxygen/xonar_dg.h index 0941ca2e0ca2..a5cb75121f40 100644 --- a/sound/pci/oxygen/xonar_dg.h +++ b/sound/pci/oxygen/xonar_dg.h | |||
@@ -27,8 +27,7 @@ struct dg { | |||
27 | /* shadow copy of the CS4245 register space */ | 27 | /* shadow copy of the CS4245 register space */ |
28 | unsigned char cs4245_shadow[17]; | 28 | unsigned char cs4245_shadow[17]; |
29 | /* output select: headphone/speakers */ | 29 | /* output select: headphone/speakers */ |
30 | unsigned char pcm_output; | 30 | unsigned char output_sel; |
31 | unsigned int output_sel; | ||
32 | s8 input_vol[4][2]; | 31 | s8 input_vol[4][2]; |
33 | unsigned int input_sel; | 32 | unsigned int input_sel; |
34 | u8 hp_vol_att; | 33 | u8 hp_vol_att; |
diff --git a/sound/pci/oxygen/xonar_dg_mixer.c b/sound/pci/oxygen/xonar_dg_mixer.c index 7e9fc4af81bd..6dfe63554742 100644 --- a/sound/pci/oxygen/xonar_dg_mixer.c +++ b/sound/pci/oxygen/xonar_dg_mixer.c | |||
@@ -27,17 +27,46 @@ | |||
27 | #include "xonar_dg.h" | 27 | #include "xonar_dg.h" |
28 | #include "cs4245.h" | 28 | #include "cs4245.h" |
29 | 29 | ||
30 | static int output_switch_info(struct snd_kcontrol *ctl, | 30 | /* analog output select */ |
31 | |||
32 | static int output_select_apply(struct oxygen *chip) | ||
33 | { | ||
34 | struct dg *data = chip->model_data; | ||
35 | |||
36 | data->cs4245_shadow[CS4245_SIGNAL_SEL] &= ~CS4245_A_OUT_SEL_MASK; | ||
37 | if (data->output_sel == PLAYBACK_DST_HP) { | ||
38 | /* mute FP (aux output) amplifier, switch rear jack to CS4245 */ | ||
39 | oxygen_set_bits8(chip, OXYGEN_GPIO_DATA, GPIO_HP_REAR); | ||
40 | } else if (data->output_sel == PLAYBACK_DST_HP_FP) { | ||
41 | /* | ||
42 | * Unmute FP amplifier, switch rear jack to CS4361; | ||
43 | * I2S channels 2,3,4 should be inactive. | ||
44 | */ | ||
45 | oxygen_clear_bits8(chip, OXYGEN_GPIO_DATA, GPIO_HP_REAR); | ||
46 | data->cs4245_shadow[CS4245_SIGNAL_SEL] |= CS4245_A_OUT_SEL_DAC; | ||
47 | } else { | ||
48 | /* | ||
49 | * 2.0, 4.0, 5.1: switch to CS4361, mute FP amp., | ||
50 | * and change playback routing. | ||
51 | */ | ||
52 | oxygen_clear_bits8(chip, OXYGEN_GPIO_DATA, GPIO_HP_REAR); | ||
53 | } | ||
54 | return cs4245_write_spi(chip, CS4245_SIGNAL_SEL); | ||
55 | } | ||
56 | |||
57 | static int output_select_info(struct snd_kcontrol *ctl, | ||
31 | struct snd_ctl_elem_info *info) | 58 | struct snd_ctl_elem_info *info) |
32 | { | 59 | { |
33 | static const char *const names[3] = { | 60 | static const char *const names[3] = { |
34 | "Speakers", "Headphones", "FP Headphones" | 61 | "Stereo Headphones", |
62 | "Stereo Headphones FP", | ||
63 | "Multichannel", | ||
35 | }; | 64 | }; |
36 | 65 | ||
37 | return snd_ctl_enum_info(info, 1, 3, names); | 66 | return snd_ctl_enum_info(info, 1, 3, names); |
38 | } | 67 | } |
39 | 68 | ||
40 | static int output_switch_get(struct snd_kcontrol *ctl, | 69 | static int output_select_get(struct snd_kcontrol *ctl, |
41 | struct snd_ctl_elem_value *value) | 70 | struct snd_ctl_elem_value *value) |
42 | { | 71 | { |
43 | struct oxygen *chip = ctl->private_data; | 72 | struct oxygen *chip = ctl->private_data; |
@@ -49,38 +78,24 @@ static int output_switch_get(struct snd_kcontrol *ctl, | |||
49 | return 0; | 78 | return 0; |
50 | } | 79 | } |
51 | 80 | ||
52 | static int output_switch_put(struct snd_kcontrol *ctl, | 81 | static int output_select_put(struct snd_kcontrol *ctl, |
53 | struct snd_ctl_elem_value *value) | 82 | struct snd_ctl_elem_value *value) |
54 | { | 83 | { |
55 | struct oxygen *chip = ctl->private_data; | 84 | struct oxygen *chip = ctl->private_data; |
56 | struct dg *data = chip->model_data; | 85 | struct dg *data = chip->model_data; |
57 | u8 reg; | 86 | unsigned int new = value->value.enumerated.item[0]; |
58 | int changed; | 87 | int changed = 0; |
59 | 88 | int ret; | |
60 | if (value->value.enumerated.item[0] > 2) | ||
61 | return -EINVAL; | ||
62 | 89 | ||
63 | mutex_lock(&chip->mutex); | 90 | mutex_lock(&chip->mutex); |
64 | changed = value->value.enumerated.item[0] != data->output_sel; | 91 | if (data->output_sel != new) { |
65 | if (changed) { | 92 | data->output_sel = new; |
66 | data->output_sel = value->value.enumerated.item[0]; | 93 | ret = output_select_apply(chip); |
67 | 94 | changed = ret >= 0 ? 1 : ret; | |
68 | reg = data->cs4245_shadow[CS4245_SIGNAL_SEL] & | 95 | oxygen_update_dac_routing(chip); |
69 | ~CS4245_A_OUT_SEL_MASK; | ||
70 | reg |= data->output_sel == 2 ? | ||
71 | CS4245_A_OUT_SEL_DAC : CS4245_A_OUT_SEL_HIZ; | ||
72 | cs4245_write_cached(chip, CS4245_SIGNAL_SEL, reg); | ||
73 | |||
74 | cs4245_write_cached(chip, CS4245_DAC_A_CTRL, | ||
75 | data->output_sel ? data->hp_vol_att : 0); | ||
76 | cs4245_write_cached(chip, CS4245_DAC_B_CTRL, | ||
77 | data->output_sel ? data->hp_vol_att : 0); | ||
78 | |||
79 | oxygen_write16_masked(chip, OXYGEN_GPIO_DATA, | ||
80 | data->output_sel == 1 ? GPIO_HP_REAR : 0, | ||
81 | GPIO_HP_REAR); | ||
82 | } | 96 | } |
83 | mutex_unlock(&chip->mutex); | 97 | mutex_unlock(&chip->mutex); |
98 | |||
84 | return changed; | 99 | return changed; |
85 | } | 100 | } |
86 | 101 | ||
@@ -301,9 +316,9 @@ static const struct snd_kcontrol_new dg_controls[] = { | |||
301 | { | 316 | { |
302 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 317 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
303 | .name = "Analog Output Playback Enum", | 318 | .name = "Analog Output Playback Enum", |
304 | .info = output_switch_info, | 319 | .info = output_select_info, |
305 | .get = output_switch_get, | 320 | .get = output_select_get, |
306 | .put = output_switch_put, | 321 | .put = output_select_put, |
307 | }, | 322 | }, |
308 | { | 323 | { |
309 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 324 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |