Commit 84cf83a2 authored by Clemens Ladisch's avatar Clemens Ladisch Committed by Takashi Iwai

ALSA: virtuoso: automatically handle Xonar DS headphone routing

Automatically mute the speaker outputs as long as a headphone is plugged.
Signed-off-by: default avatarClemens Ladisch <clemens@ladisch.de>
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent 435feac6
...@@ -27,8 +27,8 @@ ...@@ -27,8 +27,8 @@
* *
* GPIO 4 <- headphone detect, 0 = plugged * GPIO 4 <- headphone detect, 0 = plugged
* GPIO 6 -> route input jack to mic-in (0) or line-in (1) * GPIO 6 -> route input jack to mic-in (0) or line-in (1)
* GPIO 7 -> enable output to speakers * GPIO 7 -> enable output to front L/R speaker channels
* GPIO 8 -> enable output to speakers * GPIO 8 -> enable output to other speaker channels and front panel headphone
* *
* WM8766: * WM8766:
* *
...@@ -52,7 +52,8 @@ ...@@ -52,7 +52,8 @@
#define GPIO_DS_HP_DETECT 0x0010 #define GPIO_DS_HP_DETECT 0x0010
#define GPIO_DS_INPUT_ROUTE 0x0040 #define GPIO_DS_INPUT_ROUTE 0x0040
#define GPIO_DS_OUTPUT_ENABLE 0x0180 #define GPIO_DS_OUTPUT_FRONTLR 0x0080
#define GPIO_DS_OUTPUT_ENABLE 0x0100
#define LC_CONTROL_LIMITER 0x40000000 #define LC_CONTROL_LIMITER 0x40000000
#define LC_CONTROL_ALC 0x20000000 #define LC_CONTROL_ALC 0x20000000
...@@ -150,7 +151,10 @@ static void wm8776_registers_init(struct oxygen *chip) ...@@ -150,7 +151,10 @@ static void wm8776_registers_init(struct oxygen *chip)
static void wm8766_registers_init(struct oxygen *chip) static void wm8766_registers_init(struct oxygen *chip)
{ {
struct xonar_wm87x6 *data = chip->model_data;
wm8766_write(chip, WM8766_RESET, 0); wm8766_write(chip, WM8766_RESET, 0);
wm8766_write(chip, WM8766_DAC_CTRL, data->wm8766_regs[WM8766_DAC_CTRL]);
wm8766_write(chip, WM8766_INT_CTRL, WM8766_FMT_LJUST | WM8766_IWL_24); wm8766_write(chip, WM8766_INT_CTRL, WM8766_FMT_LJUST | WM8766_IWL_24);
wm8766_write(chip, WM8766_DAC_CTRL2, wm8766_write(chip, WM8766_DAC_CTRL2,
WM8766_ZCD | (chip->dac_mute ? WM8766_DMUTE_MASK : 0)); WM8766_ZCD | (chip->dac_mute ? WM8766_DMUTE_MASK : 0));
...@@ -179,14 +183,38 @@ static void wm8776_init(struct oxygen *chip) ...@@ -179,14 +183,38 @@ static void wm8776_init(struct oxygen *chip)
wm8776_registers_init(chip); wm8776_registers_init(chip);
} }
static void xonar_ds_report_hp_jack(struct oxygen *chip) static void wm8766_init(struct oxygen *chip)
{ {
struct xonar_wm87x6 *data = chip->model_data; struct xonar_wm87x6 *data = chip->model_data;
u16 bits;
bits = oxygen_read16(chip, OXYGEN_GPIO_DATA); data->wm8766_regs[WM8766_DAC_CTRL] =
snd_jack_report(data->hp_jack, WM8766_PL_LEFT_LEFT | WM8766_PL_RIGHT_RIGHT;
bits & GPIO_DS_HP_DETECT ? 0 : SND_JACK_HEADPHONE); wm8766_registers_init(chip);
}
static void xonar_ds_handle_hp_jack(struct oxygen *chip)
{
struct xonar_wm87x6 *data = chip->model_data;
bool hp_plugged;
unsigned int reg;
mutex_lock(&chip->mutex);
hp_plugged = !(oxygen_read16(chip, OXYGEN_GPIO_DATA) &
GPIO_DS_HP_DETECT);
oxygen_write16_masked(chip, OXYGEN_GPIO_DATA,
hp_plugged ? 0 : GPIO_DS_OUTPUT_FRONTLR,
GPIO_DS_OUTPUT_FRONTLR);
reg = data->wm8766_regs[WM8766_DAC_CTRL] & ~WM8766_MUTEALL;
if (hp_plugged)
reg |= WM8766_MUTEALL;
wm8766_write_cached(chip, WM8766_DAC_CTRL, reg);
snd_jack_report(data->hp_jack, hp_plugged ? SND_JACK_HEADPHONE : 0);
mutex_unlock(&chip->mutex);
} }
static void xonar_ds_init(struct oxygen *chip) static void xonar_ds_init(struct oxygen *chip)
...@@ -197,10 +225,12 @@ static void xonar_ds_init(struct oxygen *chip) ...@@ -197,10 +225,12 @@ static void xonar_ds_init(struct oxygen *chip)
data->generic.output_enable_bit = GPIO_DS_OUTPUT_ENABLE; data->generic.output_enable_bit = GPIO_DS_OUTPUT_ENABLE;
wm8776_init(chip); wm8776_init(chip);
wm8766_registers_init(chip); wm8766_init(chip);
oxygen_write16_masked(chip, OXYGEN_GPIO_CONTROL, GPIO_DS_INPUT_ROUTE, oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL,
GPIO_DS_HP_DETECT | GPIO_DS_INPUT_ROUTE); GPIO_DS_INPUT_ROUTE | GPIO_DS_OUTPUT_FRONTLR);
oxygen_clear_bits16(chip, OXYGEN_GPIO_CONTROL,
GPIO_DS_HP_DETECT);
oxygen_set_bits16(chip, OXYGEN_GPIO_DATA, GPIO_DS_INPUT_ROUTE); oxygen_set_bits16(chip, OXYGEN_GPIO_DATA, GPIO_DS_INPUT_ROUTE);
oxygen_set_bits16(chip, OXYGEN_GPIO_INTERRUPT_MASK, GPIO_DS_HP_DETECT); oxygen_set_bits16(chip, OXYGEN_GPIO_INTERRUPT_MASK, GPIO_DS_HP_DETECT);
chip->interrupt_mask |= OXYGEN_INT_GPIO; chip->interrupt_mask |= OXYGEN_INT_GPIO;
...@@ -209,7 +239,7 @@ static void xonar_ds_init(struct oxygen *chip) ...@@ -209,7 +239,7 @@ static void xonar_ds_init(struct oxygen *chip)
snd_jack_new(chip->card, "Headphone", snd_jack_new(chip->card, "Headphone",
SND_JACK_HEADPHONE, &data->hp_jack); SND_JACK_HEADPHONE, &data->hp_jack);
xonar_ds_report_hp_jack(chip); xonar_ds_handle_hp_jack(chip);
snd_component_add(chip->card, "WM8776"); snd_component_add(chip->card, "WM8776");
snd_component_add(chip->card, "WM8766"); snd_component_add(chip->card, "WM8766");
...@@ -231,6 +261,7 @@ static void xonar_ds_resume(struct oxygen *chip) ...@@ -231,6 +261,7 @@ static void xonar_ds_resume(struct oxygen *chip)
wm8776_registers_init(chip); wm8776_registers_init(chip);
wm8766_registers_init(chip); wm8766_registers_init(chip);
xonar_enable_output(chip); xonar_enable_output(chip);
xonar_ds_handle_hp_jack(chip);
} }
static void wm8776_adc_hardware_filter(unsigned int channel, static void wm8776_adc_hardware_filter(unsigned int channel,
...@@ -348,7 +379,7 @@ static void update_wm87x6_mute(struct oxygen *chip) ...@@ -348,7 +379,7 @@ static void update_wm87x6_mute(struct oxygen *chip)
static void xonar_ds_gpio_changed(struct oxygen *chip) static void xonar_ds_gpio_changed(struct oxygen *chip)
{ {
xonar_ds_report_hp_jack(chip); xonar_ds_handle_hp_jack(chip);
} }
static int wm8776_bit_switch_get(struct snd_kcontrol *ctl, static int wm8776_bit_switch_get(struct snd_kcontrol *ctl,
......
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