summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorClemens Ladisch <clemens@ladisch.de>2010-12-02 11:39:34 +0100
committerTakashi Iwai <tiwai@suse.de>2010-12-06 14:48:08 +0100
commite96f38f732d24515792296b3738842934c985539 (patch)
tree627b4c03b4f1b12e903a265f97ba98767af0c0aa
parentALSA: virtuoso: add HDMI enable switch for HDAV1.3 (diff)
downloadlinux-e96f38f732d24515792296b3738842934c985539.tar.xz
linux-e96f38f732d24515792296b3738842934c985539.zip
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: Clemens Ladisch <clemens@ladisch.de> Signed-off-by: Takashi Iwai <tiwai@suse.de>
-rw-r--r--sound/pci/oxygen/oxygen.h1
-rw-r--r--sound/pci/oxygen/oxygen_mixer.c55
-rw-r--r--sound/pci/oxygen/xonar_cs43xx.c9
-rw-r--r--sound/pci/oxygen/xonar_pcm179x.c3
4 files changed, 62 insertions, 6 deletions
diff --git a/sound/pci/oxygen/oxygen.h b/sound/pci/oxygen/oxygen.h
index 7d5222caa0a9..cf9054ecb97b 100644
--- a/sound/pci/oxygen/oxygen.h
+++ b/sound/pci/oxygen/oxygen.h
@@ -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,
diff --git a/sound/pci/oxygen/oxygen_mixer.c b/sound/pci/oxygen/oxygen_mixer.c
index 2849b36f5f7e..605e84b9e1ec 100644
--- a/sound/pci/oxygen/oxygen_mixer.c
+++ b/sound/pci/oxygen/oxygen_mixer.c
@@ -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;
diff --git a/sound/pci/oxygen/xonar_cs43xx.c b/sound/pci/oxygen/xonar_cs43xx.c
index ae4e5b512483..501fe45bbdce 100644
--- a/sound/pci/oxygen/xonar_cs43xx.c
+++ b/sound/pci/oxygen/xonar_cs43xx.c
@@ -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,
diff --git a/sound/pci/oxygen/xonar_pcm179x.c b/sound/pci/oxygen/xonar_pcm179x.c
index 3850834f989c..5193d73a916d 100644
--- a/sound/pci/oxygen/xonar_pcm179x.c
+++ b/sound/pci/oxygen/xonar_pcm179x.c
@@ -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,