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

Commit e96f38f7 authored by Clemens Ladisch's avatar Clemens Ladisch Committed by Takashi Iwai
Browse files

ALSA: virtuoso: fix front panel routing for D1/DX/ST(X)



The "Front Panel" switch on the Xonar D1/DX actually switches only the
output direction, so mark it appropriately.

The front panel microphone is controlled by the FMIC2MIC bit of the
CM9780.  It was unconditionally enabled on the D1/DX and never set on
the ST(X); add a control for it.  Selecting the front panel microphone
as source does not actually disable the microphone jack, but this is
bug-compatible with the Windows driver, and users rely on it.

Signed-off-by: default avatarClemens Ladisch <clemens@ladisch.de>
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent 2509ec62
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -35,6 +35,7 @@
#define MIDI_OUTPUT		0x0800
#define MIDI_INPUT		0x1000
#define AC97_CD_INPUT		0x2000
#define AC97_FMIC_SWITCH	0x4000

enum {
	CONTROL_SPDIF_PCM,
+55 −0
Original line number Diff line number Diff line
@@ -644,6 +644,51 @@ static int ac97_volume_put(struct snd_kcontrol *ctl,
	return change;
}

static int mic_fmic_source_info(struct snd_kcontrol *ctl,
			   struct snd_ctl_elem_info *info)
{
	static const char *const names[] = { "Mic Jack", "Front Panel" };

	info->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
	info->count = 1;
	info->value.enumerated.items = 2;
	info->value.enumerated.item &= 1;
	strcpy(info->value.enumerated.name, names[info->value.enumerated.item]);
	return 0;
}

static int mic_fmic_source_get(struct snd_kcontrol *ctl,
			       struct snd_ctl_elem_value *value)
{
	struct oxygen *chip = ctl->private_data;

	mutex_lock(&chip->mutex);
	value->value.enumerated.item[0] =
		!!(oxygen_read_ac97(chip, 0, CM9780_JACK) & CM9780_FMIC2MIC);
	mutex_unlock(&chip->mutex);
	return 0;
}

static int mic_fmic_source_put(struct snd_kcontrol *ctl,
			       struct snd_ctl_elem_value *value)
{
	struct oxygen *chip = ctl->private_data;
	u16 oldreg, newreg;
	int change;

	mutex_lock(&chip->mutex);
	oldreg = oxygen_read_ac97(chip, 0, CM9780_JACK);
	if (value->value.enumerated.item[0])
		newreg = oldreg | CM9780_FMIC2MIC;
	else
		newreg = oldreg & ~CM9780_FMIC2MIC;
	change = newreg != oldreg;
	if (change)
		oxygen_write_ac97(chip, 0, CM9780_JACK, newreg);
	mutex_unlock(&chip->mutex);
	return change;
}

static int ac97_fp_rec_volume_info(struct snd_kcontrol *ctl,
				   struct snd_ctl_elem_info *info)
{
@@ -908,6 +953,13 @@ static const struct snd_kcontrol_new ac97_controls[] = {
	AC97_VOLUME("Mic Capture Volume", 0, AC97_MIC, 0),
	AC97_SWITCH("Mic Capture Switch", 0, AC97_MIC, 15, 1),
	AC97_SWITCH("Mic Boost (+20dB)", 0, AC97_MIC, 6, 0),
	{
		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
		.name = "Mic Source Capture Enum",
		.info = mic_fmic_source_info,
		.get = mic_fmic_source_get,
		.put = mic_fmic_source_put,
	},
	AC97_SWITCH("Line Capture Switch", 0, AC97_LINE, 15, 1),
	AC97_VOLUME("CD Capture Volume", 0, AC97_CD, 1),
	AC97_SWITCH("CD Capture Switch", 0, AC97_CD, 15, 1),
@@ -972,6 +1024,9 @@ static int add_controls(struct oxygen *chip,
		if (!strcmp(template.name, "Stereo Upmixing") &&
		    chip->model.dac_channels == 2)
			continue;
		if (!strcmp(template.name, "Mic Source Capture Enum") &&
		    !(chip->model.device_config & AC97_FMIC_SWITCH))
			continue;
		if (!strncmp(template.name, "CD Capture ", 11) &&
		    !(chip->model.device_config & AC97_CD_INPUT))
			continue;
+4 −5
Original line number Diff line number Diff line
@@ -28,7 +28,7 @@
 * GPI 0 <- external power present (DX only)
 *
 * GPIO 0 -> enable output to speakers
 * GPIO 1 -> enable front panel I/O
 * GPIO 1 -> route output to front panel
 * GPIO 2 -> M0 of CS5361
 * GPIO 3 -> M1 of CS5361
 * GPIO 8 -> route input jack to line-in (0) or mic-in (1)
@@ -176,8 +176,6 @@ static void xonar_d1_init(struct oxygen *chip)
	oxygen_clear_bits16(chip, OXYGEN_GPIO_DATA,
			    GPIO_D1_FRONT_PANEL | GPIO_D1_INPUT_ROUTE);

	oxygen_ac97_set_bits(chip, 0, CM9780_JACK, CM9780_FMIC2MIC);

	xonar_init_cs53x1(chip);
	xonar_enable_output(chip);

@@ -287,7 +285,7 @@ static void update_cs43xx_center_lfe_mix(struct oxygen *chip, bool mixed)

static const struct snd_kcontrol_new front_panel_switch = {
	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
	.name = "Front Panel Switch",
	.name = "Front Panel Playback Switch",
	.info = snd_ctl_boolean_mono_info,
	.get = xonar_gpio_bit_switch_get,
	.put = xonar_gpio_bit_switch_put,
@@ -402,7 +400,8 @@ static const struct oxygen_model model_xonar_d1 = {
	.model_data_size = sizeof(struct xonar_cs43xx),
	.device_config = PLAYBACK_0_TO_I2S |
			 PLAYBACK_1_TO_SPDIF |
			 CAPTURE_0_FROM_I2S_2,
			 CAPTURE_0_FROM_I2S_2 |
			 AC97_FMIC_SWITCH,
	.dac_channels = 8,
	.dac_volume_min = 127 - 60,
	.dac_volume_max = 127,
+2 −1
Original line number Diff line number Diff line
@@ -1079,7 +1079,8 @@ static const struct oxygen_model model_xonar_st = {
	.model_data_size = sizeof(struct xonar_pcm179x),
	.device_config = PLAYBACK_0_TO_I2S |
			 PLAYBACK_1_TO_SPDIF |
			 CAPTURE_0_FROM_I2S_2,
			 CAPTURE_0_FROM_I2S_2 |
			 AC97_FMIC_SWITCH,
	.dac_channels = 2,
	.dac_volume_min = 255 - 2*60,
	.dac_volume_max = 255,