Skip to content

Commit

Permalink
ALSA: oxygen: fix output routing on Xonar DG
Browse files Browse the repository at this point in the history
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 <clemens@ladisch.de>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
  • Loading branch information
cladisch authored and tiwai committed Jan 31, 2011
1 parent fdbc5d1 commit efbeb07
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 0 deletions.
2 changes: 2 additions & 0 deletions sound/pci/oxygen/oxygen.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
2 changes: 2 additions & 0 deletions sound/pci/oxygen/oxygen_mixer.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 |
Expand Down
36 changes: 36 additions & 0 deletions sound/pci/oxygen/xonar_dg.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -36,6 +41,7 @@
* input 1 <- aux
* input 2 <- front mic
* input 4 <- line/mic
* DAC out -> headphones
* aux out -> front panel headphones
*/

Expand Down Expand Up @@ -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)
{
Expand Down Expand Up @@ -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 |
Expand Down

0 comments on commit efbeb07

Please sign in to comment.