aboutsummaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
authorRoman Volkov <v1ron@mail.ru>2014-01-24 07:18:15 -0500
committerClemens Ladisch <clemens@ladisch.de>2014-01-29 14:45:50 -0500
commit2809cb84d1672b639a4a41a0fa077fb554699072 (patch)
tree32b117862dc307aa0f579191ced847d0c54ad528 /sound
parent3dd77654fb1d7f68b9739f3039bad8dbbc0739f8 (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.c2
-rw-r--r--sound/pci/oxygen/xonar_dg.h3
-rw-r--r--sound/pci/oxygen/xonar_dg_mixer.c75
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
30static int output_switch_info(struct snd_kcontrol *ctl, 30/* analog output select */
31
32static 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
57static 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
40static int output_switch_get(struct snd_kcontrol *ctl, 69static 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
52static int output_switch_put(struct snd_kcontrol *ctl, 81static 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,