From efbeb0718126d277c9d7e902eec8da956acf4bd6 Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Mon, 31 Jan 2011 11:47:52 +0100 Subject: [PATCH] ALSA: oxygen: fix output routing on Xonar DG This card uses separate I2S outputs for the front speakers and headphones, and reverses the order of the three speaker outputs. To work around this, add a model-specific callback to adjust the controller's playback routing. Signed-off-by: Clemens Ladisch Signed-off-by: Takashi Iwai --- sound/pci/oxygen/oxygen.h | 2 ++ sound/pci/oxygen/oxygen_mixer.c | 2 ++ sound/pci/oxygen/xonar_dg.c | 36 +++++++++++++++++++++++++++++++++ 3 files changed, 40 insertions(+) diff --git a/sound/pci/oxygen/oxygen.h b/sound/pci/oxygen/oxygen.h index c2ae63d17cd..f53897a708b 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 9bff14d5895..26c7e8bcb22 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 e1fa602eba7..bc6eb58be38 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 | -- 2.20.1