Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2809cb84 authored by Roman Volkov's avatar Roman Volkov Committed by Clemens Ladisch
Browse files

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: default avatarRoman Volkov <v1ron@mail.ru>
Signed-off-by: default avatarClemens Ladisch <clemens@ladisch.de>
parent 3dd77654
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -268,7 +268,7 @@ unsigned int adjust_dg_dac_routing(struct oxygen *chip,
	struct dg *data = chip->model_data;
	unsigned int routing = 0;

	switch (data->pcm_output) {
	switch (data->output_sel) {
	case PLAYBACK_DST_HP:
	case PLAYBACK_DST_HP_FP:
		oxygen_write8_masked(chip, OXYGEN_PLAY_ROUTING,
+1 −2
Original line number Diff line number Diff line
@@ -27,8 +27,7 @@ struct dg {
	/* shadow copy of the CS4245 register space */
	unsigned char cs4245_shadow[17];
	/* output select: headphone/speakers */
	unsigned char pcm_output;
	unsigned int output_sel;
	unsigned char output_sel;
	s8 input_vol[4][2];
	unsigned int input_sel;
	u8 hp_vol_att;
+45 −30
Original line number Diff line number Diff line
@@ -27,17 +27,46 @@
#include "xonar_dg.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)
{
	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);
}

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 oxygen *chip = ctl->private_data;
@@ -49,38 +78,24 @@ static int output_switch_get(struct snd_kcontrol *ctl,
	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 oxygen *chip = ctl->private_data;
	struct dg *data = chip->model_data;
	u8 reg;
	int changed;

	if (value->value.enumerated.item[0] > 2)
		return -EINVAL;
	unsigned int new = value->value.enumerated.item[0];
	int changed = 0;
	int ret;

	mutex_lock(&chip->mutex);
	changed = value->value.enumerated.item[0] != data->output_sel;
	if (changed) {
		data->output_sel = value->value.enumerated.item[0];

		reg = data->cs4245_shadow[CS4245_SIGNAL_SEL] &
						~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);
	if (data->output_sel != new) {
		data->output_sel = new;
		ret = output_select_apply(chip);
		changed = ret >= 0 ? 1 : ret;
		oxygen_update_dac_routing(chip);
	}
	mutex_unlock(&chip->mutex);

	return changed;
}

@@ -301,9 +316,9 @@ static const struct snd_kcontrol_new dg_controls[] = {
	{
		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
		.name = "Analog Output Playback Enum",
		.info = output_switch_info,
		.get = output_switch_get,
		.put = output_switch_put,
		.info = output_select_info,
		.get = output_select_get,
		.put = output_select_put,
	},
	{
		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,