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

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
...@@ -35,6 +35,7 @@ ...@@ -35,6 +35,7 @@
#define MIDI_OUTPUT 0x0800 #define MIDI_OUTPUT 0x0800
#define MIDI_INPUT 0x1000 #define MIDI_INPUT 0x1000
#define AC97_CD_INPUT 0x2000 #define AC97_CD_INPUT 0x2000
#define AC97_FMIC_SWITCH 0x4000
enum { enum {
CONTROL_SPDIF_PCM, CONTROL_SPDIF_PCM,
......
...@@ -644,6 +644,51 @@ static int ac97_volume_put(struct snd_kcontrol *ctl, ...@@ -644,6 +644,51 @@ static int ac97_volume_put(struct snd_kcontrol *ctl,
return change; 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, static int ac97_fp_rec_volume_info(struct snd_kcontrol *ctl,
struct snd_ctl_elem_info *info) struct snd_ctl_elem_info *info)
{ {
...@@ -908,6 +953,13 @@ static const struct snd_kcontrol_new ac97_controls[] = { ...@@ -908,6 +953,13 @@ static const struct snd_kcontrol_new ac97_controls[] = {
AC97_VOLUME("Mic Capture Volume", 0, AC97_MIC, 0), AC97_VOLUME("Mic Capture Volume", 0, AC97_MIC, 0),
AC97_SWITCH("Mic Capture Switch", 0, AC97_MIC, 15, 1), AC97_SWITCH("Mic Capture Switch", 0, AC97_MIC, 15, 1),
AC97_SWITCH("Mic Boost (+20dB)", 0, AC97_MIC, 6, 0), 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_SWITCH("Line Capture Switch", 0, AC97_LINE, 15, 1),
AC97_VOLUME("CD Capture Volume", 0, AC97_CD, 1), AC97_VOLUME("CD Capture Volume", 0, AC97_CD, 1),
AC97_SWITCH("CD Capture Switch", 0, AC97_CD, 15, 1), AC97_SWITCH("CD Capture Switch", 0, AC97_CD, 15, 1),
...@@ -972,6 +1024,9 @@ static int add_controls(struct oxygen *chip, ...@@ -972,6 +1024,9 @@ static int add_controls(struct oxygen *chip,
if (!strcmp(template.name, "Stereo Upmixing") && if (!strcmp(template.name, "Stereo Upmixing") &&
chip->model.dac_channels == 2) chip->model.dac_channels == 2)
continue; continue;
if (!strcmp(template.name, "Mic Source Capture Enum") &&
!(chip->model.device_config & AC97_FMIC_SWITCH))
continue;
if (!strncmp(template.name, "CD Capture ", 11) && if (!strncmp(template.name, "CD Capture ", 11) &&
!(chip->model.device_config & AC97_CD_INPUT)) !(chip->model.device_config & AC97_CD_INPUT))
continue; continue;
......
...@@ -28,7 +28,7 @@ ...@@ -28,7 +28,7 @@
* GPI 0 <- external power present (DX only) * GPI 0 <- external power present (DX only)
* *
* GPIO 0 -> enable output to speakers * 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 2 -> M0 of CS5361
* GPIO 3 -> M1 of CS5361 * GPIO 3 -> M1 of CS5361
* GPIO 8 -> route input jack to line-in (0) or mic-in (1) * 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) ...@@ -176,8 +176,6 @@ static void xonar_d1_init(struct oxygen *chip)
oxygen_clear_bits16(chip, OXYGEN_GPIO_DATA, oxygen_clear_bits16(chip, OXYGEN_GPIO_DATA,
GPIO_D1_FRONT_PANEL | GPIO_D1_INPUT_ROUTE); GPIO_D1_FRONT_PANEL | GPIO_D1_INPUT_ROUTE);
oxygen_ac97_set_bits(chip, 0, CM9780_JACK, CM9780_FMIC2MIC);
xonar_init_cs53x1(chip); xonar_init_cs53x1(chip);
xonar_enable_output(chip); xonar_enable_output(chip);
...@@ -287,7 +285,7 @@ static void update_cs43xx_center_lfe_mix(struct oxygen *chip, bool mixed) ...@@ -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 = { static const struct snd_kcontrol_new front_panel_switch = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Front Panel Switch", .name = "Front Panel Playback Switch",
.info = snd_ctl_boolean_mono_info, .info = snd_ctl_boolean_mono_info,
.get = xonar_gpio_bit_switch_get, .get = xonar_gpio_bit_switch_get,
.put = xonar_gpio_bit_switch_put, .put = xonar_gpio_bit_switch_put,
...@@ -402,7 +400,8 @@ static const struct oxygen_model model_xonar_d1 = { ...@@ -402,7 +400,8 @@ static const struct oxygen_model model_xonar_d1 = {
.model_data_size = sizeof(struct xonar_cs43xx), .model_data_size = sizeof(struct xonar_cs43xx),
.device_config = PLAYBACK_0_TO_I2S | .device_config = PLAYBACK_0_TO_I2S |
PLAYBACK_1_TO_SPDIF | PLAYBACK_1_TO_SPDIF |
CAPTURE_0_FROM_I2S_2, CAPTURE_0_FROM_I2S_2 |
AC97_FMIC_SWITCH,
.dac_channels = 8, .dac_channels = 8,
.dac_volume_min = 127 - 60, .dac_volume_min = 127 - 60,
.dac_volume_max = 127, .dac_volume_max = 127,
......
...@@ -1079,7 +1079,8 @@ static const struct oxygen_model model_xonar_st = { ...@@ -1079,7 +1079,8 @@ static const struct oxygen_model model_xonar_st = {
.model_data_size = sizeof(struct xonar_pcm179x), .model_data_size = sizeof(struct xonar_pcm179x),
.device_config = PLAYBACK_0_TO_I2S | .device_config = PLAYBACK_0_TO_I2S |
PLAYBACK_1_TO_SPDIF | PLAYBACK_1_TO_SPDIF |
CAPTURE_0_FROM_I2S_2, CAPTURE_0_FROM_I2S_2 |
AC97_FMIC_SWITCH,
.dac_channels = 2, .dac_channels = 2,
.dac_volume_min = 255 - 2*60, .dac_volume_min = 255 - 2*60,
.dac_volume_max = 255, .dac_volume_max = 255,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment