[ALSA] virtuoso: correctly switch input jack on Xonar DX
Clemens Ladisch [Wed, 9 Apr 2008 07:16:14 +0000 (09:16 +0200)]
When selecting the capture source on the Xonar DX, the input jack must
be routed to either the line input or the microphone input by setting a
GPIO pin.  This requires an additional callback so that the model driver
can hook into the toggling of AC97 switches.

Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
Signed-off-by: Takashi Iwai <tiwai@suse.de>

sound/pci/oxygen/oxygen.h
sound/pci/oxygen/oxygen_mixer.c
sound/pci/oxygen/virtuoso.c

index d53c18c..7efbf54 100644 (file)
@@ -98,6 +98,8 @@ struct oxygen_model {
        void (*update_dac_volume)(struct oxygen *chip);
        void (*update_dac_mute)(struct oxygen *chip);
        void (*gpio_changed)(struct oxygen *chip);
+       void (*ac97_switch)(struct oxygen *chip,
+                           unsigned int reg, unsigned int mute);
        size_t model_data_size;
        unsigned int pcm_dev_cfg;
        u8 dac_channels;
index 9a7c880..d0bef09 100644 (file)
@@ -518,6 +518,8 @@ static void mute_ac97_ctl(struct oxygen *chip, unsigned int control)
        value = oxygen_read_ac97(chip, 0, priv_idx);
        if (!(value & 0x8000)) {
                oxygen_write_ac97(chip, 0, priv_idx, value | 0x8000);
+               if (chip->model->ac97_switch)
+                       chip->model->ac97_switch(chip, priv_idx, 0x8000);
                snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
                               &chip->controls[control]->id);
        }
@@ -544,6 +546,8 @@ static int ac97_switch_put(struct snd_kcontrol *ctl,
        change = newreg != oldreg;
        if (change) {
                oxygen_write_ac97(chip, codec, index, newreg);
+               if (codec == 0 && chip->model->ac97_switch)
+                       chip->model->ac97_switch(chip, index, newreg & 0x8000);
                if (index == AC97_LINE) {
                        oxygen_write_ac97_masked(chip, 0, CM9780_GPIO_STATUS,
                                                 newreg & 0x8000 ?
index 1db4aa5..b678e2d 100644 (file)
  * GPI 0 <- external power present
  *
  * GPIO 0 -> enable output to speakers
- * GPIO 1 -> ALT?
+ * GPIO 1 -> ?
  * GPIO 2 -> M0 of CS5361
  * GPIO 3 -> M1 of CS5361
- * GPIO 8 -> line-in/mic-in/digital-out switch?
+ * GPIO 8 -> route input jack to line-in (0) or mic-in (1)
  *
  * CS4398:
  *
@@ -120,7 +120,7 @@ MODULE_DEVICE_TABLE(pci, xonar_ids);
 #define GPI_DX_EXT_POWER       0x01
 #define GPIO_DX_OUTPUT_ENABLE  0x0001
 #define GPIO_DX_UNKNOWN1       0x0002
-#define GPIO_DX_UNKNOWN2       0x0100
+#define GPIO_DX_INPUT_ROUTE    0x0100
 
 #define I2C_DEVICE_CS4398      0x9e    /* 10011, AD1=1, AD0=1, /W=0 */
 #define I2C_DEVICE_CS4362A     0x30    /* 001100, AD0=0, /W=0 */
@@ -267,7 +267,8 @@ static void xonar_dx_init(struct oxygen *chip)
        cs4362a_write(chip, 0x01, CS4362A_CPEN);
 
        oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL,
-                         GPIO_DX_UNKNOWN1 | GPIO_DX_UNKNOWN2);
+                         GPIO_DX_UNKNOWN1 | GPIO_DX_INPUT_ROUTE);
+       oxygen_clear_bits16(chip, OXYGEN_GPIO_DATA, GPIO_DX_INPUT_ROUTE);
 
        xonar_common_init(chip);
 
@@ -469,6 +470,18 @@ static const struct snd_kcontrol_new alt_switch = {
        .put = alt_switch_put,
 };
 
+static void xonar_dx_ac97_switch(struct oxygen *chip,
+                                unsigned int reg, unsigned int mute)
+{
+       if (reg == AC97_LINE) {
+               spin_lock_irq(&chip->reg_lock);
+               oxygen_write16_masked(chip, OXYGEN_GPIO_DATA,
+                                     mute ? GPIO_DX_INPUT_ROUTE : 0,
+                                     GPIO_DX_INPUT_ROUTE);
+               spin_unlock_irq(&chip->reg_lock);
+       }
+}
+
 static const DECLARE_TLV_DB_SCALE(pcm1796_db_scale, -12000, 50, 0);
 static const DECLARE_TLV_DB_SCALE(cs4362a_db_scale, -12700, 100, 0);
 
@@ -572,6 +585,7 @@ static const struct oxygen_model xonar_models[] = {
                .update_dac_volume = update_cs43xx_volume,
                .update_dac_mute = update_cs43xx_mute,
                .gpio_changed = xonar_gpio_changed,
+               .ac97_switch = xonar_dx_ac97_switch,
                .model_data_size = sizeof(struct xonar_data),
                .pcm_dev_cfg = PLAYBACK_0_TO_I2S |
                               PLAYBACK_1_TO_SPDIF |