diff options
-rw-r--r-- | sound/pci/oxygen/oxygen.h | 1 | ||||
-rw-r--r-- | sound/pci/oxygen/oxygen_mixer.c | 33 | ||||
-rw-r--r-- | sound/pci/oxygen/oxygen_pcm.c | 6 | ||||
-rw-r--r-- | sound/pci/oxygen/xonar_cs43xx.c | 39 |
4 files changed, 58 insertions, 21 deletions
diff --git a/sound/pci/oxygen/oxygen.h b/sound/pci/oxygen/oxygen.h index bd615dbffadb..2ac3b3c8253f 100644 --- a/sound/pci/oxygen/oxygen.h +++ b/sound/pci/oxygen/oxygen.h | |||
@@ -84,6 +84,7 @@ struct oxygen_model { | |||
84 | struct snd_pcm_hw_params *params); | 84 | struct snd_pcm_hw_params *params); |
85 | void (*update_dac_volume)(struct oxygen *chip); | 85 | void (*update_dac_volume)(struct oxygen *chip); |
86 | void (*update_dac_mute)(struct oxygen *chip); | 86 | void (*update_dac_mute)(struct oxygen *chip); |
87 | void (*update_center_lfe_mix)(struct oxygen *chip, bool mixed); | ||
87 | void (*gpio_changed)(struct oxygen *chip); | 88 | void (*gpio_changed)(struct oxygen *chip); |
88 | void (*uart_input)(struct oxygen *chip); | 89 | void (*uart_input)(struct oxygen *chip); |
89 | void (*ac97_switch)(struct oxygen *chip, | 90 | void (*ac97_switch)(struct oxygen *chip, |
diff --git a/sound/pci/oxygen/oxygen_mixer.c b/sound/pci/oxygen/oxygen_mixer.c index e8e911a86c8e..5dfb5fb73381 100644 --- a/sound/pci/oxygen/oxygen_mixer.c +++ b/sound/pci/oxygen/oxygen_mixer.c | |||
@@ -99,11 +99,15 @@ static int dac_mute_put(struct snd_kcontrol *ctl, | |||
99 | 99 | ||
100 | static int upmix_info(struct snd_kcontrol *ctl, struct snd_ctl_elem_info *info) | 100 | static int upmix_info(struct snd_kcontrol *ctl, struct snd_ctl_elem_info *info) |
101 | { | 101 | { |
102 | static const char *const names[3] = { | 102 | static const char *const names[5] = { |
103 | "Front", "Front+Surround", "Front+Surround+Back" | 103 | "Front", |
104 | "Front+Surround", | ||
105 | "Front+Surround+Back", | ||
106 | "Front+Surround+Center/LFE", | ||
107 | "Front+Surround+Center/LFE+Back", | ||
104 | }; | 108 | }; |
105 | struct oxygen *chip = ctl->private_data; | 109 | struct oxygen *chip = ctl->private_data; |
106 | unsigned int count = 2 + (chip->model.dac_channels == 8); | 110 | unsigned int count = chip->model.update_center_lfe_mix ? 5 : 3; |
107 | 111 | ||
108 | info->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | 112 | info->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; |
109 | info->count = 1; | 113 | info->count = 1; |
@@ -127,7 +131,7 @@ static int upmix_get(struct snd_kcontrol *ctl, struct snd_ctl_elem_value *value) | |||
127 | void oxygen_update_dac_routing(struct oxygen *chip) | 131 | void oxygen_update_dac_routing(struct oxygen *chip) |
128 | { | 132 | { |
129 | /* DAC 0: front, DAC 1: surround, DAC 2: center/LFE, DAC 3: back */ | 133 | /* DAC 0: front, DAC 1: surround, DAC 2: center/LFE, DAC 3: back */ |
130 | static const unsigned int reg_values[3] = { | 134 | static const unsigned int reg_values[5] = { |
131 | /* stereo -> front */ | 135 | /* stereo -> front */ |
132 | (0 << OXYGEN_PLAY_DAC0_SOURCE_SHIFT) | | 136 | (0 << OXYGEN_PLAY_DAC0_SOURCE_SHIFT) | |
133 | (1 << OXYGEN_PLAY_DAC1_SOURCE_SHIFT) | | 137 | (1 << OXYGEN_PLAY_DAC1_SOURCE_SHIFT) | |
@@ -143,6 +147,16 @@ void oxygen_update_dac_routing(struct oxygen *chip) | |||
143 | (0 << OXYGEN_PLAY_DAC1_SOURCE_SHIFT) | | 147 | (0 << OXYGEN_PLAY_DAC1_SOURCE_SHIFT) | |
144 | (2 << OXYGEN_PLAY_DAC2_SOURCE_SHIFT) | | 148 | (2 << OXYGEN_PLAY_DAC2_SOURCE_SHIFT) | |
145 | (0 << OXYGEN_PLAY_DAC3_SOURCE_SHIFT), | 149 | (0 << OXYGEN_PLAY_DAC3_SOURCE_SHIFT), |
150 | /* stereo -> front+surround+center/LFE */ | ||
151 | (0 << OXYGEN_PLAY_DAC0_SOURCE_SHIFT) | | ||
152 | (0 << OXYGEN_PLAY_DAC1_SOURCE_SHIFT) | | ||
153 | (0 << OXYGEN_PLAY_DAC2_SOURCE_SHIFT) | | ||
154 | (3 << OXYGEN_PLAY_DAC3_SOURCE_SHIFT), | ||
155 | /* stereo -> front+surround+center/LFE+back */ | ||
156 | (0 << OXYGEN_PLAY_DAC0_SOURCE_SHIFT) | | ||
157 | (0 << OXYGEN_PLAY_DAC1_SOURCE_SHIFT) | | ||
158 | (0 << OXYGEN_PLAY_DAC2_SOURCE_SHIFT) | | ||
159 | (0 << OXYGEN_PLAY_DAC3_SOURCE_SHIFT), | ||
146 | }; | 160 | }; |
147 | u8 channels; | 161 | u8 channels; |
148 | unsigned int reg_value; | 162 | unsigned int reg_value; |
@@ -167,22 +181,23 @@ void oxygen_update_dac_routing(struct oxygen *chip) | |||
167 | OXYGEN_PLAY_DAC1_SOURCE_MASK | | 181 | OXYGEN_PLAY_DAC1_SOURCE_MASK | |
168 | OXYGEN_PLAY_DAC2_SOURCE_MASK | | 182 | OXYGEN_PLAY_DAC2_SOURCE_MASK | |
169 | OXYGEN_PLAY_DAC3_SOURCE_MASK); | 183 | OXYGEN_PLAY_DAC3_SOURCE_MASK); |
184 | if (chip->model.update_center_lfe_mix) | ||
185 | chip->model.update_center_lfe_mix(chip, chip->dac_routing > 2); | ||
170 | } | 186 | } |
171 | 187 | ||
172 | static int upmix_put(struct snd_kcontrol *ctl, struct snd_ctl_elem_value *value) | 188 | static int upmix_put(struct snd_kcontrol *ctl, struct snd_ctl_elem_value *value) |
173 | { | 189 | { |
174 | struct oxygen *chip = ctl->private_data; | 190 | struct oxygen *chip = ctl->private_data; |
175 | unsigned int count = 2 + (chip->model.dac_channels == 8); | 191 | unsigned int count = chip->model.update_center_lfe_mix ? 5 : 3; |
176 | int changed; | 192 | int changed; |
177 | 193 | ||
194 | if (value->value.enumerated.item[0] >= count) | ||
195 | return -EINVAL; | ||
178 | mutex_lock(&chip->mutex); | 196 | mutex_lock(&chip->mutex); |
179 | changed = value->value.enumerated.item[0] != chip->dac_routing; | 197 | changed = value->value.enumerated.item[0] != chip->dac_routing; |
180 | if (changed) { | 198 | if (changed) { |
181 | chip->dac_routing = min(value->value.enumerated.item[0], | 199 | chip->dac_routing = value->value.enumerated.item[0]; |
182 | count - 1); | ||
183 | spin_lock_irq(&chip->reg_lock); | ||
184 | oxygen_update_dac_routing(chip); | 200 | oxygen_update_dac_routing(chip); |
185 | spin_unlock_irq(&chip->reg_lock); | ||
186 | } | 201 | } |
187 | mutex_unlock(&chip->mutex); | 202 | mutex_unlock(&chip->mutex); |
188 | return changed; | 203 | return changed; |
diff --git a/sound/pci/oxygen/oxygen_pcm.c b/sound/pci/oxygen/oxygen_pcm.c index ef2345d82b86..1e98333366df 100644 --- a/sound/pci/oxygen/oxygen_pcm.c +++ b/sound/pci/oxygen/oxygen_pcm.c | |||
@@ -435,6 +435,7 @@ static int oxygen_spdif_hw_params(struct snd_pcm_substream *substream, | |||
435 | if (err < 0) | 435 | if (err < 0) |
436 | return err; | 436 | return err; |
437 | 437 | ||
438 | mutex_lock(&chip->mutex); | ||
438 | spin_lock_irq(&chip->reg_lock); | 439 | spin_lock_irq(&chip->reg_lock); |
439 | oxygen_clear_bits32(chip, OXYGEN_SPDIF_CONTROL, | 440 | oxygen_clear_bits32(chip, OXYGEN_SPDIF_CONTROL, |
440 | OXYGEN_SPDIF_OUT_ENABLE); | 441 | OXYGEN_SPDIF_OUT_ENABLE); |
@@ -446,6 +447,7 @@ static int oxygen_spdif_hw_params(struct snd_pcm_substream *substream, | |||
446 | OXYGEN_SPDIF_OUT_RATE_MASK); | 447 | OXYGEN_SPDIF_OUT_RATE_MASK); |
447 | oxygen_update_spdif_source(chip); | 448 | oxygen_update_spdif_source(chip); |
448 | spin_unlock_irq(&chip->reg_lock); | 449 | spin_unlock_irq(&chip->reg_lock); |
450 | mutex_unlock(&chip->mutex); | ||
449 | return 0; | 451 | return 0; |
450 | } | 452 | } |
451 | 453 | ||
@@ -459,6 +461,7 @@ static int oxygen_multich_hw_params(struct snd_pcm_substream *substream, | |||
459 | if (err < 0) | 461 | if (err < 0) |
460 | return err; | 462 | return err; |
461 | 463 | ||
464 | mutex_lock(&chip->mutex); | ||
462 | spin_lock_irq(&chip->reg_lock); | 465 | spin_lock_irq(&chip->reg_lock); |
463 | oxygen_write8_masked(chip, OXYGEN_PLAY_CHANNELS, | 466 | oxygen_write8_masked(chip, OXYGEN_PLAY_CHANNELS, |
464 | oxygen_play_channels(hw_params), | 467 | oxygen_play_channels(hw_params), |
@@ -475,12 +478,11 @@ static int oxygen_multich_hw_params(struct snd_pcm_substream *substream, | |||
475 | OXYGEN_I2S_FORMAT_MASK | | 478 | OXYGEN_I2S_FORMAT_MASK | |
476 | OXYGEN_I2S_MCLK_MASK | | 479 | OXYGEN_I2S_MCLK_MASK | |
477 | OXYGEN_I2S_BITS_MASK); | 480 | OXYGEN_I2S_BITS_MASK); |
478 | oxygen_update_dac_routing(chip); | ||
479 | oxygen_update_spdif_source(chip); | 481 | oxygen_update_spdif_source(chip); |
480 | spin_unlock_irq(&chip->reg_lock); | 482 | spin_unlock_irq(&chip->reg_lock); |
481 | 483 | ||
482 | mutex_lock(&chip->mutex); | ||
483 | chip->model.set_dac_params(chip, hw_params); | 484 | chip->model.set_dac_params(chip, hw_params); |
485 | oxygen_update_dac_routing(chip); | ||
484 | mutex_unlock(&chip->mutex); | 486 | mutex_unlock(&chip->mutex); |
485 | return 0; | 487 | return 0; |
486 | } | 488 | } |
diff --git a/sound/pci/oxygen/xonar_cs43xx.c b/sound/pci/oxygen/xonar_cs43xx.c index 8fb5797577dd..0fa05ed6681d 100644 --- a/sound/pci/oxygen/xonar_cs43xx.c +++ b/sound/pci/oxygen/xonar_cs43xx.c | |||
@@ -67,6 +67,7 @@ struct xonar_cs43xx { | |||
67 | struct xonar_generic generic; | 67 | struct xonar_generic generic; |
68 | u8 cs4398_fm; | 68 | u8 cs4398_fm; |
69 | u8 cs4362a_fm; | 69 | u8 cs4362a_fm; |
70 | u8 cs4362a_fm_c; | ||
70 | }; | 71 | }; |
71 | 72 | ||
72 | static void cs4398_write(struct oxygen *chip, u8 reg, u8 value) | 73 | static void cs4398_write(struct oxygen *chip, u8 reg, u8 value) |
@@ -128,7 +129,7 @@ static void cs43xx_init(struct oxygen *chip) | |||
128 | cs4362a_write(chip, 0x04, CS4362A_RMP_DN | CS4362A_DEM_NONE); | 129 | cs4362a_write(chip, 0x04, CS4362A_RMP_DN | CS4362A_DEM_NONE); |
129 | cs4362a_write(chip, 0x05, 0); | 130 | cs4362a_write(chip, 0x05, 0); |
130 | cs4362a_write(chip, 0x06, data->cs4362a_fm); | 131 | cs4362a_write(chip, 0x06, data->cs4362a_fm); |
131 | cs4362a_write(chip, 0x09, data->cs4362a_fm); | 132 | cs4362a_write(chip, 0x09, data->cs4362a_fm_c); |
132 | cs4362a_write(chip, 0x0c, data->cs4362a_fm); | 133 | cs4362a_write(chip, 0x0c, data->cs4362a_fm); |
133 | update_cs43xx_volume(chip); | 134 | update_cs43xx_volume(chip); |
134 | update_cs43xx_mute(chip); | 135 | update_cs43xx_mute(chip); |
@@ -146,6 +147,7 @@ static void xonar_d1_init(struct oxygen *chip) | |||
146 | data->cs4398_fm = CS4398_FM_SINGLE | CS4398_DEM_NONE | CS4398_DIF_LJUST; | 147 | data->cs4398_fm = CS4398_FM_SINGLE | CS4398_DEM_NONE | CS4398_DIF_LJUST; |
147 | data->cs4362a_fm = CS4362A_FM_SINGLE | | 148 | data->cs4362a_fm = CS4362A_FM_SINGLE | |
148 | CS4362A_ATAPI_B_R | CS4362A_ATAPI_A_L; | 149 | CS4362A_ATAPI_B_R | CS4362A_ATAPI_A_L; |
150 | data->cs4362a_fm_c = data->cs4362a_fm; | ||
149 | 151 | ||
150 | oxygen_write16(chip, OXYGEN_2WIRE_BUS_STATUS, | 152 | oxygen_write16(chip, OXYGEN_2WIRE_BUS_STATUS, |
151 | OXYGEN_2WIRE_LENGTH_8 | | 153 | OXYGEN_2WIRE_LENGTH_8 | |
@@ -202,25 +204,41 @@ static void set_cs43xx_params(struct oxygen *chip, | |||
202 | struct snd_pcm_hw_params *params) | 204 | struct snd_pcm_hw_params *params) |
203 | { | 205 | { |
204 | struct xonar_cs43xx *data = chip->model_data; | 206 | struct xonar_cs43xx *data = chip->model_data; |
207 | u8 cs4398_fm, cs4362a_fm; | ||
205 | 208 | ||
206 | data->cs4398_fm = CS4398_DEM_NONE | CS4398_DIF_LJUST; | ||
207 | data->cs4362a_fm = CS4362A_ATAPI_B_R | CS4362A_ATAPI_A_L; | ||
208 | if (params_rate(params) <= 50000) { | 209 | if (params_rate(params) <= 50000) { |
209 | data->cs4398_fm |= CS4398_FM_SINGLE; | 210 | cs4398_fm = CS4398_FM_SINGLE; |
210 | data->cs4362a_fm |= CS4362A_FM_SINGLE; | 211 | cs4362a_fm = CS4362A_FM_SINGLE; |
211 | } else if (params_rate(params) <= 100000) { | 212 | } else if (params_rate(params) <= 100000) { |
212 | data->cs4398_fm |= CS4398_FM_DOUBLE; | 213 | cs4398_fm = CS4398_FM_DOUBLE; |
213 | data->cs4362a_fm |= CS4362A_FM_DOUBLE; | 214 | cs4362a_fm = CS4362A_FM_DOUBLE; |
214 | } else { | 215 | } else { |
215 | data->cs4398_fm |= CS4398_FM_QUAD; | 216 | cs4398_fm = CS4398_FM_QUAD; |
216 | data->cs4362a_fm |= CS4362A_FM_QUAD; | 217 | cs4362a_fm = CS4362A_FM_QUAD; |
217 | } | 218 | } |
219 | data->cs4398_fm = CS4398_DEM_NONE | CS4398_DIF_LJUST | cs4398_fm; | ||
220 | data->cs4362a_fm = | ||
221 | (data->cs4362a_fm & ~CS4362A_FM_MASK) | cs4362a_fm; | ||
222 | data->cs4362a_fm_c = | ||
223 | (data->cs4362a_fm_c & ~CS4362A_FM_MASK) | cs4362a_fm; | ||
218 | cs4398_write(chip, 2, data->cs4398_fm); | 224 | cs4398_write(chip, 2, data->cs4398_fm); |
219 | cs4362a_write(chip, 0x06, data->cs4362a_fm); | 225 | cs4362a_write(chip, 0x06, data->cs4362a_fm); |
220 | cs4362a_write(chip, 0x09, data->cs4362a_fm); | 226 | cs4362a_write(chip, 0x09, data->cs4362a_fm_c); |
221 | cs4362a_write(chip, 0x0c, data->cs4362a_fm); | 227 | cs4362a_write(chip, 0x0c, data->cs4362a_fm); |
222 | } | 228 | } |
223 | 229 | ||
230 | static void update_cs43xx_center_lfe_mix(struct oxygen *chip, bool mixed) | ||
231 | { | ||
232 | struct xonar_cs43xx *data = chip->model_data; | ||
233 | |||
234 | data->cs4362a_fm_c &= ~CS4362A_ATAPI_MASK; | ||
235 | if (mixed) | ||
236 | data->cs4362a_fm_c |= CS4362A_ATAPI_B_LR | CS4362A_ATAPI_A_LR; | ||
237 | else | ||
238 | data->cs4362a_fm_c |= CS4362A_ATAPI_B_R | CS4362A_ATAPI_A_L; | ||
239 | cs4362a_write(chip, 0x09, data->cs4362a_fm_c); | ||
240 | } | ||
241 | |||
224 | static const struct snd_kcontrol_new front_panel_switch = { | 242 | static const struct snd_kcontrol_new front_panel_switch = { |
225 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 243 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
226 | .name = "Front Panel Switch", | 244 | .name = "Front Panel Switch", |
@@ -269,6 +287,7 @@ static const struct oxygen_model model_xonar_d1 = { | |||
269 | .set_adc_params = xonar_set_cs53x1_params, | 287 | .set_adc_params = xonar_set_cs53x1_params, |
270 | .update_dac_volume = update_cs43xx_volume, | 288 | .update_dac_volume = update_cs43xx_volume, |
271 | .update_dac_mute = update_cs43xx_mute, | 289 | .update_dac_mute = update_cs43xx_mute, |
290 | .update_center_lfe_mix = update_cs43xx_center_lfe_mix, | ||
272 | .ac97_switch = xonar_d1_line_mic_ac97_switch, | 291 | .ac97_switch = xonar_d1_line_mic_ac97_switch, |
273 | .dac_tlv = cs4362a_db_scale, | 292 | .dac_tlv = cs4362a_db_scale, |
274 | .model_data_size = sizeof(struct xonar_cs43xx), | 293 | .model_data_size = sizeof(struct xonar_cs43xx), |