ALSA: oxygen: Xonar DG(X): modify playback output select
Change the order of elements in the output select control. This will reduce the number of relay switches. Change 'put' function to call the oxygen_update_dac_routing() function. Otherwise multichannel playback does not work. Also there is a new function to apply settings, this prevents from duplicating the code. Signed-off-by: Roman Volkov <v1ron@mail.ru> Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
This commit is contained in:
parent
3dd77654fb
commit
2809cb84d1
|
@ -268,7 +268,7 @@ unsigned int adjust_dg_dac_routing(struct oxygen *chip,
|
||||||
struct dg *data = chip->model_data;
|
struct dg *data = chip->model_data;
|
||||||
unsigned int routing = 0;
|
unsigned int routing = 0;
|
||||||
|
|
||||||
switch (data->pcm_output) {
|
switch (data->output_sel) {
|
||||||
case PLAYBACK_DST_HP:
|
case PLAYBACK_DST_HP:
|
||||||
case PLAYBACK_DST_HP_FP:
|
case PLAYBACK_DST_HP_FP:
|
||||||
oxygen_write8_masked(chip, OXYGEN_PLAY_ROUTING,
|
oxygen_write8_masked(chip, OXYGEN_PLAY_ROUTING,
|
||||||
|
|
|
@ -27,8 +27,7 @@ struct dg {
|
||||||
/* shadow copy of the CS4245 register space */
|
/* shadow copy of the CS4245 register space */
|
||||||
unsigned char cs4245_shadow[17];
|
unsigned char cs4245_shadow[17];
|
||||||
/* output select: headphone/speakers */
|
/* output select: headphone/speakers */
|
||||||
unsigned char pcm_output;
|
unsigned char output_sel;
|
||||||
unsigned int output_sel;
|
|
||||||
s8 input_vol[4][2];
|
s8 input_vol[4][2];
|
||||||
unsigned int input_sel;
|
unsigned int input_sel;
|
||||||
u8 hp_vol_att;
|
u8 hp_vol_att;
|
||||||
|
|
|
@ -27,17 +27,46 @@
|
||||||
#include "xonar_dg.h"
|
#include "xonar_dg.h"
|
||||||
#include "cs4245.h"
|
#include "cs4245.h"
|
||||||
|
|
||||||
static int output_switch_info(struct snd_kcontrol *ctl,
|
/* analog output select */
|
||||||
|
|
||||||
|
static int output_select_apply(struct oxygen *chip)
|
||||||
|
{
|
||||||
|
struct dg *data = chip->model_data;
|
||||||
|
|
||||||
|
data->cs4245_shadow[CS4245_SIGNAL_SEL] &= ~CS4245_A_OUT_SEL_MASK;
|
||||||
|
if (data->output_sel == PLAYBACK_DST_HP) {
|
||||||
|
/* mute FP (aux output) amplifier, switch rear jack to CS4245 */
|
||||||
|
oxygen_set_bits8(chip, OXYGEN_GPIO_DATA, GPIO_HP_REAR);
|
||||||
|
} else if (data->output_sel == PLAYBACK_DST_HP_FP) {
|
||||||
|
/*
|
||||||
|
* Unmute FP amplifier, switch rear jack to CS4361;
|
||||||
|
* I2S channels 2,3,4 should be inactive.
|
||||||
|
*/
|
||||||
|
oxygen_clear_bits8(chip, OXYGEN_GPIO_DATA, GPIO_HP_REAR);
|
||||||
|
data->cs4245_shadow[CS4245_SIGNAL_SEL] |= CS4245_A_OUT_SEL_DAC;
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* 2.0, 4.0, 5.1: switch to CS4361, mute FP amp.,
|
||||||
|
* and change playback routing.
|
||||||
|
*/
|
||||||
|
oxygen_clear_bits8(chip, OXYGEN_GPIO_DATA, GPIO_HP_REAR);
|
||||||
|
}
|
||||||
|
return cs4245_write_spi(chip, CS4245_SIGNAL_SEL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int output_select_info(struct snd_kcontrol *ctl,
|
||||||
struct snd_ctl_elem_info *info)
|
struct snd_ctl_elem_info *info)
|
||||||
{
|
{
|
||||||
static const char *const names[3] = {
|
static const char *const names[3] = {
|
||||||
"Speakers", "Headphones", "FP Headphones"
|
"Stereo Headphones",
|
||||||
|
"Stereo Headphones FP",
|
||||||
|
"Multichannel",
|
||||||
};
|
};
|
||||||
|
|
||||||
return snd_ctl_enum_info(info, 1, 3, names);
|
return snd_ctl_enum_info(info, 1, 3, names);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int output_switch_get(struct snd_kcontrol *ctl,
|
static int output_select_get(struct snd_kcontrol *ctl,
|
||||||
struct snd_ctl_elem_value *value)
|
struct snd_ctl_elem_value *value)
|
||||||
{
|
{
|
||||||
struct oxygen *chip = ctl->private_data;
|
struct oxygen *chip = ctl->private_data;
|
||||||
|
@ -49,38 +78,24 @@ static int output_switch_get(struct snd_kcontrol *ctl,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int output_switch_put(struct snd_kcontrol *ctl,
|
static int output_select_put(struct snd_kcontrol *ctl,
|
||||||
struct snd_ctl_elem_value *value)
|
struct snd_ctl_elem_value *value)
|
||||||
{
|
{
|
||||||
struct oxygen *chip = ctl->private_data;
|
struct oxygen *chip = ctl->private_data;
|
||||||
struct dg *data = chip->model_data;
|
struct dg *data = chip->model_data;
|
||||||
u8 reg;
|
unsigned int new = value->value.enumerated.item[0];
|
||||||
int changed;
|
int changed = 0;
|
||||||
|
int ret;
|
||||||
if (value->value.enumerated.item[0] > 2)
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
mutex_lock(&chip->mutex);
|
mutex_lock(&chip->mutex);
|
||||||
changed = value->value.enumerated.item[0] != data->output_sel;
|
if (data->output_sel != new) {
|
||||||
if (changed) {
|
data->output_sel = new;
|
||||||
data->output_sel = value->value.enumerated.item[0];
|
ret = output_select_apply(chip);
|
||||||
|
changed = ret >= 0 ? 1 : ret;
|
||||||
reg = data->cs4245_shadow[CS4245_SIGNAL_SEL] &
|
oxygen_update_dac_routing(chip);
|
||||||
~CS4245_A_OUT_SEL_MASK;
|
|
||||||
reg |= data->output_sel == 2 ?
|
|
||||||
CS4245_A_OUT_SEL_DAC : CS4245_A_OUT_SEL_HIZ;
|
|
||||||
cs4245_write_cached(chip, CS4245_SIGNAL_SEL, reg);
|
|
||||||
|
|
||||||
cs4245_write_cached(chip, CS4245_DAC_A_CTRL,
|
|
||||||
data->output_sel ? data->hp_vol_att : 0);
|
|
||||||
cs4245_write_cached(chip, CS4245_DAC_B_CTRL,
|
|
||||||
data->output_sel ? data->hp_vol_att : 0);
|
|
||||||
|
|
||||||
oxygen_write16_masked(chip, OXYGEN_GPIO_DATA,
|
|
||||||
data->output_sel == 1 ? GPIO_HP_REAR : 0,
|
|
||||||
GPIO_HP_REAR);
|
|
||||||
}
|
}
|
||||||
mutex_unlock(&chip->mutex);
|
mutex_unlock(&chip->mutex);
|
||||||
|
|
||||||
return changed;
|
return changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -301,9 +316,9 @@ static const struct snd_kcontrol_new dg_controls[] = {
|
||||||
{
|
{
|
||||||
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
|
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
|
||||||
.name = "Analog Output Playback Enum",
|
.name = "Analog Output Playback Enum",
|
||||||
.info = output_switch_info,
|
.info = output_select_info,
|
||||||
.get = output_switch_get,
|
.get = output_select_get,
|
||||||
.put = output_switch_put,
|
.put = output_select_put,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
|
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
|
||||||
|
|
Loading…
Reference in New Issue