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), |
