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 <clemens@ladisch.de>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
Clemens Ladisch 2011-01-31 11:47:52 +01:00 коммит произвёл Takashi Iwai
Родитель fdbc5d1b32
Коммит efbeb07181
3 изменённых файлов: 40 добавлений и 0 удалений

Просмотреть файл

@ -92,6 +92,8 @@ struct oxygen_model {
void (*update_dac_volume)(struct oxygen *chip); void (*update_dac_volume)(struct oxygen *chip);
void (*update_dac_mute)(struct oxygen *chip); void (*update_dac_mute)(struct oxygen *chip);
void (*update_center_lfe_mix)(struct oxygen *chip, bool mixed); 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 (*gpio_changed)(struct oxygen *chip);
void (*uart_input)(struct oxygen *chip); void (*uart_input)(struct oxygen *chip);
void (*ac97_switch)(struct oxygen *chip, void (*ac97_switch)(struct oxygen *chip,

Просмотреть файл

@ -180,6 +180,8 @@ void oxygen_update_dac_routing(struct oxygen *chip)
(1 << OXYGEN_PLAY_DAC1_SOURCE_SHIFT) | (1 << OXYGEN_PLAY_DAC1_SOURCE_SHIFT) |
(2 << OXYGEN_PLAY_DAC2_SOURCE_SHIFT) | (2 << OXYGEN_PLAY_DAC2_SOURCE_SHIFT) |
(3 << OXYGEN_PLAY_DAC3_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_write16_masked(chip, OXYGEN_PLAY_ROUTING, reg_value,
OXYGEN_PLAY_DAC0_SOURCE_MASK | OXYGEN_PLAY_DAC0_SOURCE_MASK |
OXYGEN_PLAY_DAC1_SOURCE_MASK | OXYGEN_PLAY_DAC1_SOURCE_MASK |

Просмотреть файл

@ -24,6 +24,11 @@
* *
* SPI 0 -> CS4245 * 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 3 <- ?
* GPIO 4 <- headphone detect * GPIO 4 <- headphone detect
* GPIO 5 -> route input jack to line-in (0) or mic-in (1) * GPIO 5 -> route input jack to line-in (0) or mic-in (1)
@ -36,6 +41,7 @@
* input 1 <- aux * input 1 <- aux
* input 2 <- front mic * input 2 <- front mic
* input 4 <- line/mic * input 4 <- line/mic
* DAC out -> headphones
* aux out -> front panel 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); 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, static int output_switch_info(struct snd_kcontrol *ctl,
struct snd_ctl_elem_info *info) struct snd_ctl_elem_info *info)
{ {
@ -557,6 +592,7 @@ struct oxygen_model model_xonar_dg = {
.resume = dg_resume, .resume = dg_resume,
.set_dac_params = set_cs4245_dac_params, .set_dac_params = set_cs4245_dac_params,
.set_adc_params = set_cs4245_adc_params, .set_adc_params = set_cs4245_adc_params,
.adjust_dac_routing = adjust_dg_dac_routing,
.dump_registers = dump_cs4245_registers, .dump_registers = dump_cs4245_registers,
.model_data_size = sizeof(struct dg), .model_data_size = sizeof(struct dg),
.device_config = PLAYBACK_0_TO_I2S | .device_config = PLAYBACK_0_TO_I2S |