diff options
Diffstat (limited to 'sound/pci/oxygen/xonar_wm87x6.c')
-rw-r--r-- | sound/pci/oxygen/xonar_wm87x6.c | 57 |
1 files changed, 44 insertions, 13 deletions
diff --git a/sound/pci/oxygen/xonar_wm87x6.c b/sound/pci/oxygen/xonar_wm87x6.c index 9d57b5eee3f5..cee07fe3aa36 100644 --- a/sound/pci/oxygen/xonar_wm87x6.c +++ b/sound/pci/oxygen/xonar_wm87x6.c | |||
@@ -27,8 +27,8 @@ | |||
27 | * | 27 | * |
28 | * GPIO 4 <- headphone detect, 0 = plugged | 28 | * GPIO 4 <- headphone detect, 0 = plugged |
29 | * GPIO 6 -> route input jack to mic-in (0) or line-in (1) | 29 | * GPIO 6 -> route input jack to mic-in (0) or line-in (1) |
30 | * GPIO 7 -> enable output to speakers | 30 | * GPIO 7 -> enable output to front L/R speaker channels |
31 | * GPIO 8 -> enable output to speakers | 31 | * GPIO 8 -> enable output to other speaker channels and front panel headphone |
32 | * | 32 | * |
33 | * WM8766: | 33 | * WM8766: |
34 | * | 34 | * |
@@ -52,7 +52,8 @@ | |||
52 | 52 | ||
53 | #define GPIO_DS_HP_DETECT 0x0010 | 53 | #define GPIO_DS_HP_DETECT 0x0010 |
54 | #define GPIO_DS_INPUT_ROUTE 0x0040 | 54 | #define GPIO_DS_INPUT_ROUTE 0x0040 |
55 | #define GPIO_DS_OUTPUT_ENABLE 0x0180 | 55 | #define GPIO_DS_OUTPUT_FRONTLR 0x0080 |
56 | #define GPIO_DS_OUTPUT_ENABLE 0x0100 | ||
56 | 57 | ||
57 | #define LC_CONTROL_LIMITER 0x40000000 | 58 | #define LC_CONTROL_LIMITER 0x40000000 |
58 | #define LC_CONTROL_ALC 0x20000000 | 59 | #define LC_CONTROL_ALC 0x20000000 |
@@ -150,7 +151,10 @@ static void wm8776_registers_init(struct oxygen *chip) | |||
150 | 151 | ||
151 | static void wm8766_registers_init(struct oxygen *chip) | 152 | static void wm8766_registers_init(struct oxygen *chip) |
152 | { | 153 | { |
154 | struct xonar_wm87x6 *data = chip->model_data; | ||
155 | |||
153 | wm8766_write(chip, WM8766_RESET, 0); | 156 | wm8766_write(chip, WM8766_RESET, 0); |
157 | wm8766_write(chip, WM8766_DAC_CTRL, data->wm8766_regs[WM8766_DAC_CTRL]); | ||
154 | wm8766_write(chip, WM8766_INT_CTRL, WM8766_FMT_LJUST | WM8766_IWL_24); | 158 | wm8766_write(chip, WM8766_INT_CTRL, WM8766_FMT_LJUST | WM8766_IWL_24); |
155 | wm8766_write(chip, WM8766_DAC_CTRL2, | 159 | wm8766_write(chip, WM8766_DAC_CTRL2, |
156 | WM8766_ZCD | (chip->dac_mute ? WM8766_DMUTE_MASK : 0)); | 160 | WM8766_ZCD | (chip->dac_mute ? WM8766_DMUTE_MASK : 0)); |
@@ -179,14 +183,38 @@ static void wm8776_init(struct oxygen *chip) | |||
179 | wm8776_registers_init(chip); | 183 | wm8776_registers_init(chip); |
180 | } | 184 | } |
181 | 185 | ||
182 | static void xonar_ds_report_hp_jack(struct oxygen *chip) | 186 | static void wm8766_init(struct oxygen *chip) |
183 | { | 187 | { |
184 | struct xonar_wm87x6 *data = chip->model_data; | 188 | struct xonar_wm87x6 *data = chip->model_data; |
185 | u16 bits; | ||
186 | 189 | ||
187 | bits = oxygen_read16(chip, OXYGEN_GPIO_DATA); | 190 | data->wm8766_regs[WM8766_DAC_CTRL] = |
188 | snd_jack_report(data->hp_jack, | 191 | WM8766_PL_LEFT_LEFT | WM8766_PL_RIGHT_RIGHT; |
189 | bits & GPIO_DS_HP_DETECT ? 0 : SND_JACK_HEADPHONE); | 192 | wm8766_registers_init(chip); |
193 | } | ||
194 | |||
195 | static void xonar_ds_handle_hp_jack(struct oxygen *chip) | ||
196 | { | ||
197 | struct xonar_wm87x6 *data = chip->model_data; | ||
198 | bool hp_plugged; | ||
199 | unsigned int reg; | ||
200 | |||
201 | mutex_lock(&chip->mutex); | ||
202 | |||
203 | hp_plugged = !(oxygen_read16(chip, OXYGEN_GPIO_DATA) & | ||
204 | GPIO_DS_HP_DETECT); | ||
205 | |||
206 | oxygen_write16_masked(chip, OXYGEN_GPIO_DATA, | ||
207 | hp_plugged ? 0 : GPIO_DS_OUTPUT_FRONTLR, | ||
208 | GPIO_DS_OUTPUT_FRONTLR); | ||
209 | |||
210 | reg = data->wm8766_regs[WM8766_DAC_CTRL] & ~WM8766_MUTEALL; | ||
211 | if (hp_plugged) | ||
212 | reg |= WM8766_MUTEALL; | ||
213 | wm8766_write_cached(chip, WM8766_DAC_CTRL, reg); | ||
214 | |||
215 | snd_jack_report(data->hp_jack, hp_plugged ? SND_JACK_HEADPHONE : 0); | ||
216 | |||
217 | mutex_unlock(&chip->mutex); | ||
190 | } | 218 | } |
191 | 219 | ||
192 | static void xonar_ds_init(struct oxygen *chip) | 220 | static void xonar_ds_init(struct oxygen *chip) |
@@ -197,10 +225,12 @@ static void xonar_ds_init(struct oxygen *chip) | |||
197 | data->generic.output_enable_bit = GPIO_DS_OUTPUT_ENABLE; | 225 | data->generic.output_enable_bit = GPIO_DS_OUTPUT_ENABLE; |
198 | 226 | ||
199 | wm8776_init(chip); | 227 | wm8776_init(chip); |
200 | wm8766_registers_init(chip); | 228 | wm8766_init(chip); |
201 | 229 | ||
202 | oxygen_write16_masked(chip, OXYGEN_GPIO_CONTROL, GPIO_DS_INPUT_ROUTE, | 230 | oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL, |
203 | GPIO_DS_HP_DETECT | GPIO_DS_INPUT_ROUTE); | 231 | GPIO_DS_INPUT_ROUTE | GPIO_DS_OUTPUT_FRONTLR); |
232 | oxygen_clear_bits16(chip, OXYGEN_GPIO_CONTROL, | ||
233 | GPIO_DS_HP_DETECT); | ||
204 | oxygen_set_bits16(chip, OXYGEN_GPIO_DATA, GPIO_DS_INPUT_ROUTE); | 234 | oxygen_set_bits16(chip, OXYGEN_GPIO_DATA, GPIO_DS_INPUT_ROUTE); |
205 | oxygen_set_bits16(chip, OXYGEN_GPIO_INTERRUPT_MASK, GPIO_DS_HP_DETECT); | 235 | oxygen_set_bits16(chip, OXYGEN_GPIO_INTERRUPT_MASK, GPIO_DS_HP_DETECT); |
206 | chip->interrupt_mask |= OXYGEN_INT_GPIO; | 236 | chip->interrupt_mask |= OXYGEN_INT_GPIO; |
@@ -209,7 +239,7 @@ static void xonar_ds_init(struct oxygen *chip) | |||
209 | 239 | ||
210 | snd_jack_new(chip->card, "Headphone", | 240 | snd_jack_new(chip->card, "Headphone", |
211 | SND_JACK_HEADPHONE, &data->hp_jack); | 241 | SND_JACK_HEADPHONE, &data->hp_jack); |
212 | xonar_ds_report_hp_jack(chip); | 242 | xonar_ds_handle_hp_jack(chip); |
213 | 243 | ||
214 | snd_component_add(chip->card, "WM8776"); | 244 | snd_component_add(chip->card, "WM8776"); |
215 | snd_component_add(chip->card, "WM8766"); | 245 | snd_component_add(chip->card, "WM8766"); |
@@ -231,6 +261,7 @@ static void xonar_ds_resume(struct oxygen *chip) | |||
231 | wm8776_registers_init(chip); | 261 | wm8776_registers_init(chip); |
232 | wm8766_registers_init(chip); | 262 | wm8766_registers_init(chip); |
233 | xonar_enable_output(chip); | 263 | xonar_enable_output(chip); |
264 | xonar_ds_handle_hp_jack(chip); | ||
234 | } | 265 | } |
235 | 266 | ||
236 | static void wm8776_adc_hardware_filter(unsigned int channel, | 267 | static void wm8776_adc_hardware_filter(unsigned int channel, |
@@ -348,7 +379,7 @@ static void update_wm87x6_mute(struct oxygen *chip) | |||
348 | 379 | ||
349 | static void xonar_ds_gpio_changed(struct oxygen *chip) | 380 | static void xonar_ds_gpio_changed(struct oxygen *chip) |
350 | { | 381 | { |
351 | xonar_ds_report_hp_jack(chip); | 382 | xonar_ds_handle_hp_jack(chip); |
352 | } | 383 | } |
353 | 384 | ||
354 | static int wm8776_bit_switch_get(struct snd_kcontrol *ctl, | 385 | static int wm8776_bit_switch_get(struct snd_kcontrol *ctl, |