diff --git a/sound/pci/oxygen/oxygen.h b/sound/pci/oxygen/oxygen.h index c2ae63d17cd2c893523092908dc98925f03753ee..f53897a708b449e97da2a2d3a835e18eed5afdc0 100644 --- a/sound/pci/oxygen/oxygen.h +++ b/sound/pci/oxygen/oxygen.h @@ -92,6 +92,8 @@ struct oxygen_model { void (*update_dac_volume)(struct oxygen *chip); void (*update_dac_mute)(struct oxygen *chip); void (*update_center_lfe_mix)(struct oxygen *chip, bool mixed); + unsigned int (*adjust_dac_routing)(struct oxygen *chip, + unsigned int play_routing); void (*gpio_changed)(struct oxygen *chip); void (*uart_input)(struct oxygen *chip); void (*ac97_switch)(struct oxygen *chip, diff --git a/sound/pci/oxygen/oxygen_mixer.c b/sound/pci/oxygen/oxygen_mixer.c index 9bff14d5895dd72af1df2dafb4b354bb309eced7..26c7e8bcb229361b03397e52a59c37eb183ed18d 100644 --- a/sound/pci/oxygen/oxygen_mixer.c +++ b/sound/pci/oxygen/oxygen_mixer.c @@ -180,6 +180,8 @@ void oxygen_update_dac_routing(struct oxygen *chip) (1 << OXYGEN_PLAY_DAC1_SOURCE_SHIFT) | (2 << OXYGEN_PLAY_DAC2_SOURCE_SHIFT) | (3 << OXYGEN_PLAY_DAC3_SOURCE_SHIFT); + if (chip->model.adjust_dac_routing) + reg_value = chip->model.adjust_dac_routing(chip, reg_value); oxygen_write16_masked(chip, OXYGEN_PLAY_ROUTING, reg_value, OXYGEN_PLAY_DAC0_SOURCE_MASK | OXYGEN_PLAY_DAC1_SOURCE_MASK | diff --git a/sound/pci/oxygen/xonar_dg.c b/sound/pci/oxygen/xonar_dg.c index e1fa602eba795c5db577bc18f4cc00e5680262d0..bc6eb58be380108dc56c15418f1102a617469434 100644 --- a/sound/pci/oxygen/xonar_dg.c +++ b/sound/pci/oxygen/xonar_dg.c @@ -24,6 +24,11 @@ * * SPI 0 -> CS4245 * + * I²S 1 -> CS4245 + * I²S 2 -> CS4361 (center/LFE) + * I²S 3 -> CS4361 (surround) + * I²S 4 -> CS4361 (front) + * * GPIO 3 <- ? * GPIO 4 <- headphone detect * GPIO 5 -> route input jack to line-in (0) or mic-in (1) @@ -36,6 +41,7 @@ * input 1 <- aux * input 2 <- front mic * input 4 <- line/mic + * DAC out -> headphones * aux out -> front panel headphones */ @@ -207,6 +213,35 @@ static void set_cs4245_adc_params(struct oxygen *chip, cs4245_write_cached(chip, CS4245_ADC_CTRL, value); } +static inline unsigned int shift_bits(unsigned int value, + unsigned int shift_from, + unsigned int shift_to, + unsigned int mask) +{ + if (shift_from < shift_to) + return (value << (shift_to - shift_from)) & mask; + else + return (value >> (shift_from - shift_to)) & mask; +} + +static unsigned int adjust_dg_dac_routing(struct oxygen *chip, + unsigned int play_routing) +{ + return (play_routing & OXYGEN_PLAY_DAC0_SOURCE_MASK) | + shift_bits(play_routing, + OXYGEN_PLAY_DAC2_SOURCE_SHIFT, + OXYGEN_PLAY_DAC1_SOURCE_SHIFT, + OXYGEN_PLAY_DAC1_SOURCE_MASK) | + shift_bits(play_routing, + OXYGEN_PLAY_DAC1_SOURCE_SHIFT, + OXYGEN_PLAY_DAC2_SOURCE_SHIFT, + OXYGEN_PLAY_DAC2_SOURCE_MASK) | + shift_bits(play_routing, + OXYGEN_PLAY_DAC0_SOURCE_SHIFT, + OXYGEN_PLAY_DAC3_SOURCE_SHIFT, + OXYGEN_PLAY_DAC3_SOURCE_MASK); +} + static int output_switch_info(struct snd_kcontrol *ctl, struct snd_ctl_elem_info *info) { @@ -557,6 +592,7 @@ struct oxygen_model model_xonar_dg = { .resume = dg_resume, .set_dac_params = set_cs4245_dac_params, .set_adc_params = set_cs4245_adc_params, + .adjust_dac_routing = adjust_dg_dac_routing, .dump_registers = dump_cs4245_registers, .model_data_size = sizeof(struct dg), .device_config = PLAYBACK_0_TO_I2S |