~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/sound/pci/oxygen/xonar_wm87x6.c

Version: ~ [ linux-5.5-rc7 ] ~ [ linux-5.4.13 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.97 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.166 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.210 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.210 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.140 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.81 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-3.9.11 ] ~ [ linux-3.8.13 ] ~ [ linux-3.7.10 ] ~ [ linux-3.6.11 ] ~ [ linux-3.5.7 ] ~ [ linux-3.4.113 ] ~ [ linux-3.3.8 ] ~ [ linux-3.2.102 ] ~ [ linux-3.1.10 ] ~ [ linux-3.0.101 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2  * card driver for models with WM8776/WM8766 DACs (Xonar DS/HDAV1.3 Slim)
  3  *
  4  * Copyright (c) Clemens Ladisch <clemens@ladisch.de>
  5  *
  6  *
  7  *  This driver is free software; you can redistribute it and/or modify
  8  *  it under the terms of the GNU General Public License, version 2.
  9  *
 10  *  This driver is distributed in the hope that it will be useful,
 11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 13  *  GNU General Public License for more details.
 14  *
 15  *  You should have received a copy of the GNU General Public License
 16  *  along with this driver; if not, see <http://www.gnu.org/licenses/>.
 17  */
 18 
 19 /*
 20  * Xonar DS
 21  * --------
 22  *
 23  * CMI8788:
 24  *
 25  *   SPI 0 -> WM8766 (surround, center/LFE, back)
 26  *   SPI 1 -> WM8776 (front, input)
 27  *
 28  *   GPIO 4 <- headphone detect, 0 = plugged
 29  *   GPIO 6 -> route input jack to mic-in (0) or line-in (1)
 30  *   GPIO 7 -> enable output to front L/R speaker channels
 31  *   GPIO 8 -> enable output to other speaker channels and front panel headphone
 32  *
 33  * WM8776:
 34  *
 35  *   input 1 <- line
 36  *   input 2 <- mic
 37  *   input 3 <- front mic
 38  *   input 4 <- aux
 39  */
 40 
 41 /*
 42  * Xonar HDAV1.3 Slim
 43  * ------------------
 44  *
 45  * CMI8788:
 46  *
 47  *   I²C <-> WM8776 (addr 0011010)
 48  *
 49  *   GPIO 0  -> disable HDMI output
 50  *   GPIO 1  -> enable HP output
 51  *   GPIO 6  -> firmware EEPROM I²C clock
 52  *   GPIO 7 <-> firmware EEPROM I²C data
 53  *
 54  *   UART <-> HDMI controller
 55  *
 56  * WM8776:
 57  *
 58  *   input 1 <- mic
 59  *   input 2 <- aux
 60  */
 61 
 62 #include <linux/pci.h>
 63 #include <linux/delay.h>
 64 #include <sound/control.h>
 65 #include <sound/core.h>
 66 #include <sound/info.h>
 67 #include <sound/jack.h>
 68 #include <sound/pcm.h>
 69 #include <sound/pcm_params.h>
 70 #include <sound/tlv.h>
 71 #include "xonar.h"
 72 #include "wm8776.h"
 73 #include "wm8766.h"
 74 
 75 #define GPIO_DS_HP_DETECT       0x0010
 76 #define GPIO_DS_INPUT_ROUTE     0x0040
 77 #define GPIO_DS_OUTPUT_FRONTLR  0x0080
 78 #define GPIO_DS_OUTPUT_ENABLE   0x0100
 79 
 80 #define GPIO_SLIM_HDMI_DISABLE  0x0001
 81 #define GPIO_SLIM_OUTPUT_ENABLE 0x0002
 82 #define GPIO_SLIM_FIRMWARE_CLK  0x0040
 83 #define GPIO_SLIM_FIRMWARE_DATA 0x0080
 84 
 85 #define I2C_DEVICE_WM8776       0x34    /* 001101, 0, /W=0 */
 86 
 87 #define LC_CONTROL_LIMITER      0x40000000
 88 #define LC_CONTROL_ALC          0x20000000
 89 
 90 struct xonar_wm87x6 {
 91         struct xonar_generic generic;
 92         u16 wm8776_regs[0x17];
 93         u16 wm8766_regs[0x10];
 94         struct snd_kcontrol *line_adcmux_control;
 95         struct snd_kcontrol *mic_adcmux_control;
 96         struct snd_kcontrol *lc_controls[13];
 97         struct snd_jack *hp_jack;
 98         struct xonar_hdmi hdmi;
 99 };
100 
101 static void wm8776_write_spi(struct oxygen *chip,
102                              unsigned int reg, unsigned int value)
103 {
104         oxygen_write_spi(chip, OXYGEN_SPI_TRIGGER |
105                          OXYGEN_SPI_DATA_LENGTH_2 |
106                          OXYGEN_SPI_CLOCK_160 |
107                          (1 << OXYGEN_SPI_CODEC_SHIFT) |
108                          OXYGEN_SPI_CEN_LATCH_CLOCK_LO,
109                          (reg << 9) | value);
110 }
111 
112 static void wm8776_write_i2c(struct oxygen *chip,
113                              unsigned int reg, unsigned int value)
114 {
115         oxygen_write_i2c(chip, I2C_DEVICE_WM8776,
116                          (reg << 1) | (value >> 8), value);
117 }
118 
119 static void wm8776_write(struct oxygen *chip,
120                          unsigned int reg, unsigned int value)
121 {
122         struct xonar_wm87x6 *data = chip->model_data;
123 
124         if ((chip->model.function_flags & OXYGEN_FUNCTION_2WIRE_SPI_MASK) ==
125             OXYGEN_FUNCTION_SPI)
126                 wm8776_write_spi(chip, reg, value);
127         else
128                 wm8776_write_i2c(chip, reg, value);
129         if (reg < ARRAY_SIZE(data->wm8776_regs)) {
130                 if (reg >= WM8776_HPLVOL && reg <= WM8776_DACMASTER)
131                         value &= ~WM8776_UPDATE;
132                 data->wm8776_regs[reg] = value;
133         }
134 }
135 
136 static void wm8776_write_cached(struct oxygen *chip,
137                                 unsigned int reg, unsigned int value)
138 {
139         struct xonar_wm87x6 *data = chip->model_data;
140 
141         if (reg >= ARRAY_SIZE(data->wm8776_regs) ||
142             value != data->wm8776_regs[reg])
143                 wm8776_write(chip, reg, value);
144 }
145 
146 static void wm8766_write(struct oxygen *chip,
147                          unsigned int reg, unsigned int value)
148 {
149         struct xonar_wm87x6 *data = chip->model_data;
150 
151         oxygen_write_spi(chip, OXYGEN_SPI_TRIGGER |
152                          OXYGEN_SPI_DATA_LENGTH_2 |
153                          OXYGEN_SPI_CLOCK_160 |
154                          (0 << OXYGEN_SPI_CODEC_SHIFT) |
155                          OXYGEN_SPI_CEN_LATCH_CLOCK_LO,
156                          (reg << 9) | value);
157         if (reg < ARRAY_SIZE(data->wm8766_regs)) {
158                 if ((reg >= WM8766_LDA1 && reg <= WM8766_RDA1) ||
159                     (reg >= WM8766_LDA2 && reg <= WM8766_MASTDA))
160                         value &= ~WM8766_UPDATE;
161                 data->wm8766_regs[reg] = value;
162         }
163 }
164 
165 static void wm8766_write_cached(struct oxygen *chip,
166                                 unsigned int reg, unsigned int value)
167 {
168         struct xonar_wm87x6 *data = chip->model_data;
169 
170         if (reg >= ARRAY_SIZE(data->wm8766_regs) ||
171             value != data->wm8766_regs[reg])
172                 wm8766_write(chip, reg, value);
173 }
174 
175 static void wm8776_registers_init(struct oxygen *chip)
176 {
177         struct xonar_wm87x6 *data = chip->model_data;
178 
179         wm8776_write(chip, WM8776_RESET, 0);
180         wm8776_write(chip, WM8776_PHASESWAP, WM8776_PH_MASK);
181         wm8776_write(chip, WM8776_DACCTRL1, WM8776_DZCEN |
182                      WM8776_PL_LEFT_LEFT | WM8776_PL_RIGHT_RIGHT);
183         wm8776_write(chip, WM8776_DACMUTE, chip->dac_mute ? WM8776_DMUTE : 0);
184         wm8776_write(chip, WM8776_DACIFCTRL,
185                      WM8776_DACFMT_LJUST | WM8776_DACWL_24);
186         wm8776_write(chip, WM8776_ADCIFCTRL,
187                      data->wm8776_regs[WM8776_ADCIFCTRL]);
188         wm8776_write(chip, WM8776_MSTRCTRL, data->wm8776_regs[WM8776_MSTRCTRL]);
189         wm8776_write(chip, WM8776_PWRDOWN, data->wm8776_regs[WM8776_PWRDOWN]);
190         wm8776_write(chip, WM8776_HPLVOL, data->wm8776_regs[WM8776_HPLVOL]);
191         wm8776_write(chip, WM8776_HPRVOL, data->wm8776_regs[WM8776_HPRVOL] |
192                      WM8776_UPDATE);
193         wm8776_write(chip, WM8776_ADCLVOL, data->wm8776_regs[WM8776_ADCLVOL]);
194         wm8776_write(chip, WM8776_ADCRVOL, data->wm8776_regs[WM8776_ADCRVOL]);
195         wm8776_write(chip, WM8776_ADCMUX, data->wm8776_regs[WM8776_ADCMUX]);
196         wm8776_write(chip, WM8776_DACLVOL, chip->dac_volume[0]);
197         wm8776_write(chip, WM8776_DACRVOL, chip->dac_volume[1] | WM8776_UPDATE);
198 }
199 
200 static void wm8766_registers_init(struct oxygen *chip)
201 {
202         struct xonar_wm87x6 *data = chip->model_data;
203 
204         wm8766_write(chip, WM8766_RESET, 0);
205         wm8766_write(chip, WM8766_DAC_CTRL, data->wm8766_regs[WM8766_DAC_CTRL]);
206         wm8766_write(chip, WM8766_INT_CTRL, WM8766_FMT_LJUST | WM8766_IWL_24);
207         wm8766_write(chip, WM8766_DAC_CTRL2,
208                      WM8766_ZCD | (chip->dac_mute ? WM8766_DMUTE_MASK : 0));
209         wm8766_write(chip, WM8766_LDA1, chip->dac_volume[2]);
210         wm8766_write(chip, WM8766_RDA1, chip->dac_volume[3]);
211         wm8766_write(chip, WM8766_LDA2, chip->dac_volume[4]);
212         wm8766_write(chip, WM8766_RDA2, chip->dac_volume[5]);
213         wm8766_write(chip, WM8766_LDA3, chip->dac_volume[6]);
214         wm8766_write(chip, WM8766_RDA3, chip->dac_volume[7] | WM8766_UPDATE);
215 }
216 
217 static void wm8776_init(struct oxygen *chip)
218 {
219         struct xonar_wm87x6 *data = chip->model_data;
220 
221         data->wm8776_regs[WM8776_HPLVOL] = (0x79 - 60) | WM8776_HPZCEN;
222         data->wm8776_regs[WM8776_HPRVOL] = (0x79 - 60) | WM8776_HPZCEN;
223         data->wm8776_regs[WM8776_ADCIFCTRL] =
224                 WM8776_ADCFMT_LJUST | WM8776_ADCWL_24 | WM8776_ADCMCLK;
225         data->wm8776_regs[WM8776_MSTRCTRL] =
226                 WM8776_ADCRATE_256 | WM8776_DACRATE_256;
227         data->wm8776_regs[WM8776_PWRDOWN] = WM8776_HPPD;
228         data->wm8776_regs[WM8776_ADCLVOL] = 0xa5 | WM8776_ZCA;
229         data->wm8776_regs[WM8776_ADCRVOL] = 0xa5 | WM8776_ZCA;
230         data->wm8776_regs[WM8776_ADCMUX] = 0x001;
231         wm8776_registers_init(chip);
232 }
233 
234 static void wm8766_init(struct oxygen *chip)
235 {
236         struct xonar_wm87x6 *data = chip->model_data;
237 
238         data->wm8766_regs[WM8766_DAC_CTRL] =
239                 WM8766_PL_LEFT_LEFT | WM8766_PL_RIGHT_RIGHT;
240         wm8766_registers_init(chip);
241 }
242 
243 static void xonar_ds_handle_hp_jack(struct oxygen *chip)
244 {
245         struct xonar_wm87x6 *data = chip->model_data;
246         bool hp_plugged;
247         unsigned int reg;
248 
249         mutex_lock(&chip->mutex);
250 
251         hp_plugged = !(oxygen_read16(chip, OXYGEN_GPIO_DATA) &
252                        GPIO_DS_HP_DETECT);
253 
254         oxygen_write16_masked(chip, OXYGEN_GPIO_DATA,
255                               hp_plugged ? 0 : GPIO_DS_OUTPUT_FRONTLR,
256                               GPIO_DS_OUTPUT_FRONTLR);
257 
258         reg = data->wm8766_regs[WM8766_DAC_CTRL] & ~WM8766_MUTEALL;
259         if (hp_plugged)
260                 reg |= WM8766_MUTEALL;
261         wm8766_write_cached(chip, WM8766_DAC_CTRL, reg);
262 
263         snd_jack_report(data->hp_jack, hp_plugged ? SND_JACK_HEADPHONE : 0);
264 
265         mutex_unlock(&chip->mutex);
266 }
267 
268 static void xonar_ds_init(struct oxygen *chip)
269 {
270         struct xonar_wm87x6 *data = chip->model_data;
271 
272         data->generic.anti_pop_delay = 300;
273         data->generic.output_enable_bit = GPIO_DS_OUTPUT_ENABLE;
274 
275         wm8776_init(chip);
276         wm8766_init(chip);
277 
278         oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL,
279                           GPIO_DS_INPUT_ROUTE | GPIO_DS_OUTPUT_FRONTLR);
280         oxygen_clear_bits16(chip, OXYGEN_GPIO_CONTROL,
281                             GPIO_DS_HP_DETECT);
282         oxygen_set_bits16(chip, OXYGEN_GPIO_DATA, GPIO_DS_INPUT_ROUTE);
283         oxygen_set_bits16(chip, OXYGEN_GPIO_INTERRUPT_MASK, GPIO_DS_HP_DETECT);
284         chip->interrupt_mask |= OXYGEN_INT_GPIO;
285 
286         xonar_enable_output(chip);
287 
288         snd_jack_new(chip->card, "Headphone",
289                      SND_JACK_HEADPHONE, &data->hp_jack, false, false);
290         xonar_ds_handle_hp_jack(chip);
291 
292         snd_component_add(chip->card, "WM8776");
293         snd_component_add(chip->card, "WM8766");
294 }
295 
296 static void xonar_hdav_slim_init(struct oxygen *chip)
297 {
298         struct xonar_wm87x6 *data = chip->model_data;
299 
300         data->generic.anti_pop_delay = 300;
301         data->generic.output_enable_bit = GPIO_SLIM_OUTPUT_ENABLE;
302 
303         wm8776_init(chip);
304 
305         oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL,
306                           GPIO_SLIM_HDMI_DISABLE |
307                           GPIO_SLIM_FIRMWARE_CLK |
308                           GPIO_SLIM_FIRMWARE_DATA);
309 
310         xonar_hdmi_init(chip, &data->hdmi);
311         xonar_enable_output(chip);
312 
313         snd_component_add(chip->card, "WM8776");
314 }
315 
316 static void xonar_ds_cleanup(struct oxygen *chip)
317 {
318         xonar_disable_output(chip);
319         wm8776_write(chip, WM8776_RESET, 0);
320 }
321 
322 static void xonar_hdav_slim_cleanup(struct oxygen *chip)
323 {
324         xonar_hdmi_cleanup(chip);
325         xonar_disable_output(chip);
326         wm8776_write(chip, WM8776_RESET, 0);
327         msleep(2);
328 }
329 
330 static void xonar_ds_suspend(struct oxygen *chip)
331 {
332         xonar_ds_cleanup(chip);
333 }
334 
335 static void xonar_hdav_slim_suspend(struct oxygen *chip)
336 {
337         xonar_hdav_slim_cleanup(chip);
338 }
339 
340 static void xonar_ds_resume(struct oxygen *chip)
341 {
342         wm8776_registers_init(chip);
343         wm8766_registers_init(chip);
344         xonar_enable_output(chip);
345         xonar_ds_handle_hp_jack(chip);
346 }
347 
348 static void xonar_hdav_slim_resume(struct oxygen *chip)
349 {
350         struct xonar_wm87x6 *data = chip->model_data;
351 
352         wm8776_registers_init(chip);
353         xonar_hdmi_resume(chip, &data->hdmi);
354         xonar_enable_output(chip);
355 }
356 
357 static void wm8776_adc_hardware_filter(unsigned int channel,
358                                        struct snd_pcm_hardware *hardware)
359 {
360         if (channel == PCM_A) {
361                 hardware->rates = SNDRV_PCM_RATE_32000 |
362                                   SNDRV_PCM_RATE_44100 |
363                                   SNDRV_PCM_RATE_48000 |
364                                   SNDRV_PCM_RATE_64000 |
365                                   SNDRV_PCM_RATE_88200 |
366                                   SNDRV_PCM_RATE_96000;
367                 hardware->rate_max = 96000;
368         }
369 }
370 
371 static void xonar_hdav_slim_hardware_filter(unsigned int channel,
372                                             struct snd_pcm_hardware *hardware)
373 {
374         wm8776_adc_hardware_filter(channel, hardware);
375         xonar_hdmi_pcm_hardware_filter(channel, hardware);
376 }
377 
378 static void set_wm87x6_dac_params(struct oxygen *chip,
379                                   struct snd_pcm_hw_params *params)
380 {
381 }
382 
383 static void set_wm8776_adc_params(struct oxygen *chip,
384                                   struct snd_pcm_hw_params *params)
385 {
386         u16 reg;
387 
388         reg = WM8776_ADCRATE_256 | WM8776_DACRATE_256;
389         if (params_rate(params) > 48000)
390                 reg |= WM8776_ADCOSR;
391         wm8776_write_cached(chip, WM8776_MSTRCTRL, reg);
392 }
393 
394 static void set_hdav_slim_dac_params(struct oxygen *chip,
395                                      struct snd_pcm_hw_params *params)
396 {
397         struct xonar_wm87x6 *data = chip->model_data;
398 
399         xonar_set_hdmi_params(chip, &data->hdmi, params);
400 }
401 
402 static void update_wm8776_volume(struct oxygen *chip)
403 {
404         struct xonar_wm87x6 *data = chip->model_data;
405         u8 to_change;
406 
407         if (chip->dac_volume[0] == chip->dac_volume[1]) {
408                 if (chip->dac_volume[0] != data->wm8776_regs[WM8776_DACLVOL] ||
409                     chip->dac_volume[1] != data->wm8776_regs[WM8776_DACRVOL]) {
410                         wm8776_write(chip, WM8776_DACMASTER,
411                                      chip->dac_volume[0] | WM8776_UPDATE);
412                         data->wm8776_regs[WM8776_DACLVOL] = chip->dac_volume[0];
413                         data->wm8776_regs[WM8776_DACRVOL] = chip->dac_volume[0];
414                 }
415         } else {
416                 to_change = (chip->dac_volume[0] !=
417                              data->wm8776_regs[WM8776_DACLVOL]) << 0;
418                 to_change |= (chip->dac_volume[1] !=
419                               data->wm8776_regs[WM8776_DACLVOL]) << 1;
420                 if (to_change & 1)
421                         wm8776_write(chip, WM8776_DACLVOL, chip->dac_volume[0] |
422                                      ((to_change & 2) ? 0 : WM8776_UPDATE));
423                 if (to_change & 2)
424                         wm8776_write(chip, WM8776_DACRVOL,
425                                      chip->dac_volume[1] | WM8776_UPDATE);
426         }
427 }
428 
429 static void update_wm87x6_volume(struct oxygen *chip)
430 {
431         static const u8 wm8766_regs[6] = {
432                 WM8766_LDA1, WM8766_RDA1,
433                 WM8766_LDA2, WM8766_RDA2,
434                 WM8766_LDA3, WM8766_RDA3,
435         };
436         struct xonar_wm87x6 *data = chip->model_data;
437         unsigned int i;
438         u8 to_change;
439 
440         update_wm8776_volume(chip);
441         if (chip->dac_volume[2] == chip->dac_volume[3] &&
442             chip->dac_volume[2] == chip->dac_volume[4] &&
443             chip->dac_volume[2] == chip->dac_volume[5] &&
444             chip->dac_volume[2] == chip->dac_volume[6] &&
445             chip->dac_volume[2] == chip->dac_volume[7]) {
446                 to_change = 0;
447                 for (i = 0; i < 6; ++i)
448                         if (chip->dac_volume[2] !=
449                             data->wm8766_regs[wm8766_regs[i]])
450                                 to_change = 1;
451                 if (to_change) {
452                         wm8766_write(chip, WM8766_MASTDA,
453                                      chip->dac_volume[2] | WM8766_UPDATE);
454                         for (i = 0; i < 6; ++i)
455                                 data->wm8766_regs[wm8766_regs[i]] =
456                                         chip->dac_volume[2];
457                 }
458         } else {
459                 to_change = 0;
460                 for (i = 0; i < 6; ++i)
461                         to_change |= (chip->dac_volume[2 + i] !=
462                                       data->wm8766_regs[wm8766_regs[i]]) << i;
463                 for (i = 0; i < 6; ++i)
464                         if (to_change & (1 << i))
465                                 wm8766_write(chip, wm8766_regs[i],
466                                              chip->dac_volume[2 + i] |
467                                              ((to_change & (0x3e << i))
468                                               ? 0 : WM8766_UPDATE));
469         }
470 }
471 
472 static void update_wm8776_mute(struct oxygen *chip)
473 {
474         wm8776_write_cached(chip, WM8776_DACMUTE,
475                             chip->dac_mute ? WM8776_DMUTE : 0);
476 }
477 
478 static void update_wm87x6_mute(struct oxygen *chip)
479 {
480         update_wm8776_mute(chip);
481         wm8766_write_cached(chip, WM8766_DAC_CTRL2, WM8766_ZCD |
482                             (chip->dac_mute ? WM8766_DMUTE_MASK : 0));
483 }
484 
485 static void update_wm8766_center_lfe_mix(struct oxygen *chip, bool mixed)
486 {
487         struct xonar_wm87x6 *data = chip->model_data;
488         unsigned int reg;
489 
490         /*
491          * The WM8766 can mix left and right channels, but this setting
492          * applies to all three stereo pairs.
493          */
494         reg = data->wm8766_regs[WM8766_DAC_CTRL] &
495                 ~(WM8766_PL_LEFT_MASK | WM8766_PL_RIGHT_MASK);
496         if (mixed)
497                 reg |= WM8766_PL_LEFT_LRMIX | WM8766_PL_RIGHT_LRMIX;
498         else
499                 reg |= WM8766_PL_LEFT_LEFT | WM8766_PL_RIGHT_RIGHT;
500         wm8766_write_cached(chip, WM8766_DAC_CTRL, reg);
501 }
502 
503 static void xonar_ds_gpio_changed(struct oxygen *chip)
504 {
505         xonar_ds_handle_hp_jack(chip);
506 }
507 
508 static int wm8776_bit_switch_get(struct snd_kcontrol *ctl,
509                                  struct snd_ctl_elem_value *value)
510 {
511         struct oxygen *chip = ctl->private_data;
512         struct xonar_wm87x6 *data = chip->model_data;
513         u16 bit = ctl->private_value & 0xffff;
514         unsigned int reg_index = (ctl->private_value >> 16) & 0xff;
515         bool invert = (ctl->private_value >> 24) & 1;
516 
517         value->value.integer.value[0] =
518                 ((data->wm8776_regs[reg_index] & bit) != 0) ^ invert;
519         return 0;
520 }
521 
522 static int wm8776_bit_switch_put(struct snd_kcontrol *ctl,
523                                  struct snd_ctl_elem_value *value)
524 {
525         struct oxygen *chip = ctl->private_data;
526         struct xonar_wm87x6 *data = chip->model_data;
527         u16 bit = ctl->private_value & 0xffff;
528         u16 reg_value;
529         unsigned int reg_index = (ctl->private_value >> 16) & 0xff;
530         bool invert = (ctl->private_value >> 24) & 1;
531         int changed;
532 
533         mutex_lock(&chip->mutex);
534         reg_value = data->wm8776_regs[reg_index] & ~bit;
535         if (value->value.integer.value[0] ^ invert)
536                 reg_value |= bit;
537         changed = reg_value != data->wm8776_regs[reg_index];
538         if (changed)
539                 wm8776_write(chip, reg_index, reg_value);
540         mutex_unlock(&chip->mutex);
541         return changed;
542 }
543 
544 static int wm8776_field_enum_info(struct snd_kcontrol *ctl,
545                                   struct snd_ctl_elem_info *info)
546 {
547         static const char *const hld[16] = {
548                 "0 ms", "2.67 ms", "5.33 ms", "10.6 ms",
549                 "21.3 ms", "42.7 ms", "85.3 ms", "171 ms",
550                 "341 ms", "683 ms", "1.37 s", "2.73 s",
551                 "5.46 s", "10.9 s", "21.8 s", "43.7 s",
552         };
553         static const char *const atk_lim[11] = {
554                 "0.25 ms", "0.5 ms", "1 ms", "2 ms",
555                 "4 ms", "8 ms", "16 ms", "32 ms",
556                 "64 ms", "128 ms", "256 ms",
557         };
558         static const char *const atk_alc[11] = {
559                 "8.40 ms", "16.8 ms", "33.6 ms", "67.2 ms",
560                 "134 ms", "269 ms", "538 ms", "1.08 s",
561                 "2.15 s", "4.3 s", "8.6 s",
562         };
563         static const char *const dcy_lim[11] = {
564                 "1.2 ms", "2.4 ms", "4.8 ms", "9.6 ms",
565                 "19.2 ms", "38.4 ms", "76.8 ms", "154 ms",
566                 "307 ms", "614 ms", "1.23 s",
567         };
568         static const char *const dcy_alc[11] = {
569                 "33.5 ms", "67.0 ms", "134 ms", "268 ms",
570                 "536 ms", "1.07 s", "2.14 s", "4.29 s",
571                 "8.58 s", "17.2 s", "34.3 s",
572         };
573         static const char *const tranwin[8] = {
574                 "0 us", "62.5 us", "125 us", "250 us",
575                 "500 us", "1 ms", "2 ms", "4 ms",
576         };
577         u8 max;
578         const char *const *names;
579 
580         max = (ctl->private_value >> 12) & 0xf;
581         switch ((ctl->private_value >> 24) & 0x1f) {
582         case WM8776_ALCCTRL2:
583                 names = hld;
584                 break;
585         case WM8776_ALCCTRL3:
586                 if (((ctl->private_value >> 20) & 0xf) == 0) {
587                         if (ctl->private_value & LC_CONTROL_LIMITER)
588                                 names = atk_lim;
589                         else
590                                 names = atk_alc;
591                 } else {
592                         if (ctl->private_value & LC_CONTROL_LIMITER)
593                                 names = dcy_lim;
594                         else
595                                 names = dcy_alc;
596                 }
597                 break;
598         case WM8776_LIMITER:
599                 names = tranwin;
600                 break;
601         default:
602                 return -ENXIO;
603         }
604         return snd_ctl_enum_info(info, 1, max + 1, names);
605 }
606 
607 static int wm8776_field_volume_info(struct snd_kcontrol *ctl,
608                                     struct snd_ctl_elem_info *info)
609 {
610         info->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
611         info->count = 1;
612         info->value.integer.min = (ctl->private_value >> 8) & 0xf;
613         info->value.integer.max = (ctl->private_value >> 12) & 0xf;
614         return 0;
615 }
616 
617 static void wm8776_field_set_from_ctl(struct snd_kcontrol *ctl)
618 {
619         struct oxygen *chip = ctl->private_data;
620         struct xonar_wm87x6 *data = chip->model_data;
621         unsigned int value, reg_index, mode;
622         u8 min, max, shift;
623         u16 mask, reg_value;
624         bool invert;
625 
626         if ((data->wm8776_regs[WM8776_ALCCTRL1] & WM8776_LCSEL_MASK) ==
627             WM8776_LCSEL_LIMITER)
628                 mode = LC_CONTROL_LIMITER;
629         else
630                 mode = LC_CONTROL_ALC;
631         if (!(ctl->private_value & mode))
632                 return;
633 
634         value = ctl->private_value & 0xf;
635         min = (ctl->private_value >> 8) & 0xf;
636         max = (ctl->private_value >> 12) & 0xf;
637         mask = (ctl->private_value >> 16) & 0xf;
638         shift = (ctl->private_value >> 20) & 0xf;
639         reg_index = (ctl->private_value >> 24) & 0x1f;
640         invert = (ctl->private_value >> 29) & 0x1;
641 
642         if (invert)
643                 value = max - (value - min);
644         reg_value = data->wm8776_regs[reg_index];
645         reg_value &= ~(mask << shift);
646         reg_value |= value << shift;
647         wm8776_write_cached(chip, reg_index, reg_value);
648 }
649 
650 static int wm8776_field_set(struct snd_kcontrol *ctl, unsigned int value)
651 {
652         struct oxygen *chip = ctl->private_data;
653         u8 min, max;
654         int changed;
655 
656         min = (ctl->private_value >> 8) & 0xf;
657         max = (ctl->private_value >> 12) & 0xf;
658         if (value < min || value > max)
659                 return -EINVAL;
660         mutex_lock(&chip->mutex);
661         changed = value != (ctl->private_value & 0xf);
662         if (changed) {
663                 ctl->private_value = (ctl->private_value & ~0xf) | value;
664                 wm8776_field_set_from_ctl(ctl);
665         }
666         mutex_unlock(&chip->mutex);
667         return changed;
668 }
669 
670 static int wm8776_field_enum_get(struct snd_kcontrol *ctl,
671                                  struct snd_ctl_elem_value *value)
672 {
673         value->value.enumerated.item[0] = ctl->private_value & 0xf;
674         return 0;
675 }
676 
677 static int wm8776_field_volume_get(struct snd_kcontrol *ctl,
678                                    struct snd_ctl_elem_value *value)
679 {
680         value->value.integer.value[0] = ctl->private_value & 0xf;
681         return 0;
682 }
683 
684 static int wm8776_field_enum_put(struct snd_kcontrol *ctl,
685                                  struct snd_ctl_elem_value *value)
686 {
687         return wm8776_field_set(ctl, value->value.enumerated.item[0]);
688 }
689 
690 static int wm8776_field_volume_put(struct snd_kcontrol *ctl,
691                                    struct snd_ctl_elem_value *value)
692 {
693         return wm8776_field_set(ctl, value->value.integer.value[0]);
694 }
695 
696 static int wm8776_hp_vol_info(struct snd_kcontrol *ctl,
697                               struct snd_ctl_elem_info *info)
698 {
699         info->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
700         info->count = 2;
701         info->value.integer.min = 0x79 - 60;
702         info->value.integer.max = 0x7f;
703         return 0;
704 }
705 
706 static int wm8776_hp_vol_get(struct snd_kcontrol *ctl,
707                              struct snd_ctl_elem_value *value)
708 {
709         struct oxygen *chip = ctl->private_data;
710         struct xonar_wm87x6 *data = chip->model_data;
711 
712         mutex_lock(&chip->mutex);
713         value->value.integer.value[0] =
714                 data->wm8776_regs[WM8776_HPLVOL] & WM8776_HPATT_MASK;
715         value->value.integer.value[1] =
716                 data->wm8776_regs[WM8776_HPRVOL] & WM8776_HPATT_MASK;
717         mutex_unlock(&chip->mutex);
718         return 0;
719 }
720 
721 static int wm8776_hp_vol_put(struct snd_kcontrol *ctl,
722                              struct snd_ctl_elem_value *value)
723 {
724         struct oxygen *chip = ctl->private_data;
725         struct xonar_wm87x6 *data = chip->model_data;
726         u8 to_update;
727 
728         mutex_lock(&chip->mutex);
729         to_update = (value->value.integer.value[0] !=
730                      (data->wm8776_regs[WM8776_HPLVOL] & WM8776_HPATT_MASK))
731                 << 0;
732         to_update |= (value->value.integer.value[1] !=
733                       (data->wm8776_regs[WM8776_HPRVOL] & WM8776_HPATT_MASK))
734                 << 1;
735         if (value->value.integer.value[0] == value->value.integer.value[1]) {
736                 if (to_update) {
737                         wm8776_write(chip, WM8776_HPMASTER,
738                                      value->value.integer.value[0] |
739                                      WM8776_HPZCEN | WM8776_UPDATE);
740                         data->wm8776_regs[WM8776_HPLVOL] =
741                                 value->value.integer.value[0] | WM8776_HPZCEN;
742                         data->wm8776_regs[WM8776_HPRVOL] =
743                                 value->value.integer.value[0] | WM8776_HPZCEN;
744                 }
745         } else {
746                 if (to_update & 1)
747                         wm8776_write(chip, WM8776_HPLVOL,
748                                      value->value.integer.value[0] |
749                                      WM8776_HPZCEN |
750                                      ((to_update & 2) ? 0 : WM8776_UPDATE));
751                 if (to_update & 2)
752                         wm8776_write(chip, WM8776_HPRVOL,
753                                      value->value.integer.value[1] |
754                                      WM8776_HPZCEN | WM8776_UPDATE);
755         }
756         mutex_unlock(&chip->mutex);
757         return to_update != 0;
758 }
759 
760 static int wm8776_input_mux_get(struct snd_kcontrol *ctl,
761                                 struct snd_ctl_elem_value *value)
762 {
763         struct oxygen *chip = ctl->private_data;
764         struct xonar_wm87x6 *data = chip->model_data;
765         unsigned int mux_bit = ctl->private_value;
766 
767         value->value.integer.value[0] =
768                 !!(data->wm8776_regs[WM8776_ADCMUX] & mux_bit);
769         return 0;
770 }
771 
772 static int wm8776_input_mux_put(struct snd_kcontrol *ctl,
773                                 struct snd_ctl_elem_value *value)
774 {
775         struct oxygen *chip = ctl->private_data;
776         struct xonar_wm87x6 *data = chip->model_data;
777         struct snd_kcontrol *other_ctl;
778         unsigned int mux_bit = ctl->private_value;
779         u16 reg;
780         int changed;
781 
782         mutex_lock(&chip->mutex);
783         reg = data->wm8776_regs[WM8776_ADCMUX];
784         if (value->value.integer.value[0]) {
785                 reg |= mux_bit;
786                 /* line-in and mic-in are exclusive */
787                 mux_bit ^= 3;
788                 if (reg & mux_bit) {
789                         reg &= ~mux_bit;
790                         if (mux_bit == 1)
791                                 other_ctl = data->line_adcmux_control;
792                         else
793                                 other_ctl = data->mic_adcmux_control;
794                         snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
795                                        &other_ctl->id);
796                 }
797         } else
798                 reg &= ~mux_bit;
799         changed = reg != data->wm8776_regs[WM8776_ADCMUX];
800         if (changed) {
801                 oxygen_write16_masked(chip, OXYGEN_GPIO_DATA,
802                                       reg & 1 ? GPIO_DS_INPUT_ROUTE : 0,
803                                       GPIO_DS_INPUT_ROUTE);
804                 wm8776_write(chip, WM8776_ADCMUX, reg);
805         }
806         mutex_unlock(&chip->mutex);
807         return changed;
808 }
809 
810 static int wm8776_input_vol_info(struct snd_kcontrol *ctl,
811                                  struct snd_ctl_elem_info *info)
812 {
813         info->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
814         info->count = 2;
815         info->value.integer.min = 0xa5;
816         info->value.integer.max = 0xff;
817         return 0;
818 }
819 
820 static int wm8776_input_vol_get(struct snd_kcontrol *ctl,
821                                 struct snd_ctl_elem_value *value)
822 {
823         struct oxygen *chip = ctl->private_data;
824         struct xonar_wm87x6 *data = chip->model_data;
825 
826         mutex_lock(&chip->mutex);
827         value->value.integer.value[0] =
828                 data->wm8776_regs[WM8776_ADCLVOL] & WM8776_AGMASK;
829         value->value.integer.value[1] =
830                 data->wm8776_regs[WM8776_ADCRVOL] & WM8776_AGMASK;
831         mutex_unlock(&chip->mutex);
832         return 0;
833 }
834 
835 static int wm8776_input_vol_put(struct snd_kcontrol *ctl,
836                                 struct snd_ctl_elem_value *value)
837 {
838         struct oxygen *chip = ctl->private_data;
839         struct xonar_wm87x6 *data = chip->model_data;
840         int changed = 0;
841 
842         mutex_lock(&chip->mutex);
843         changed = (value->value.integer.value[0] !=
844                    (data->wm8776_regs[WM8776_ADCLVOL] & WM8776_AGMASK)) ||
845                   (value->value.integer.value[1] !=
846                    (data->wm8776_regs[WM8776_ADCRVOL] & WM8776_AGMASK));
847         wm8776_write_cached(chip, WM8776_ADCLVOL,
848                             value->value.integer.value[0] | WM8776_ZCA);
849         wm8776_write_cached(chip, WM8776_ADCRVOL,
850                             value->value.integer.value[1] | WM8776_ZCA);
851         mutex_unlock(&chip->mutex);
852         return changed;
853 }
854 
855 static int wm8776_level_control_info(struct snd_kcontrol *ctl,
856                                      struct snd_ctl_elem_info *info)
857 {
858         static const char *const names[3] = {
859                 "None", "Peak Limiter", "Automatic Level Control"
860         };
861 
862         return snd_ctl_enum_info(info, 1, 3, names);
863 }
864 
865 static int wm8776_level_control_get(struct snd_kcontrol *ctl,
866                                     struct snd_ctl_elem_value *value)
867 {
868         struct oxygen *chip = ctl->private_data;
869         struct xonar_wm87x6 *data = chip->model_data;
870 
871         if (!(data->wm8776_regs[WM8776_ALCCTRL2] & WM8776_LCEN))
872                 value->value.enumerated.item[0] = 0;
873         else if ((data->wm8776_regs[WM8776_ALCCTRL1] & WM8776_LCSEL_MASK) ==
874                  WM8776_LCSEL_LIMITER)
875                 value->value.enumerated.item[0] = 1;
876         else
877                 value->value.enumerated.item[0] = 2;
878         return 0;
879 }
880 
881 static void activate_control(struct oxygen *chip,
882                              struct snd_kcontrol *ctl, unsigned int mode)
883 {
884         unsigned int access;
885 
886         if (ctl->private_value & mode)
887                 access = 0;
888         else
889                 access = SNDRV_CTL_ELEM_ACCESS_INACTIVE;
890         if ((ctl->vd[0].access & SNDRV_CTL_ELEM_ACCESS_INACTIVE) != access) {
891                 ctl->vd[0].access ^= SNDRV_CTL_ELEM_ACCESS_INACTIVE;
892                 snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_INFO, &ctl->id);
893         }
894 }
895 
896 static int wm8776_level_control_put(struct snd_kcontrol *ctl,
897                                     struct snd_ctl_elem_value *value)
898 {
899         struct oxygen *chip = ctl->private_data;
900         struct xonar_wm87x6 *data = chip->model_data;
901         unsigned int mode = 0, i;
902         u16 ctrl1, ctrl2;
903         int changed;
904 
905         if (value->value.enumerated.item[0] >= 3)
906                 return -EINVAL;
907         mutex_lock(&chip->mutex);
908         changed = value->value.enumerated.item[0] != ctl->private_value;
909         if (changed) {
910                 ctl->private_value = value->value.enumerated.item[0];
911                 ctrl1 = data->wm8776_regs[WM8776_ALCCTRL1];
912                 ctrl2 = data->wm8776_regs[WM8776_ALCCTRL2];
913                 switch (value->value.enumerated.item[0]) {
914                 default:
915                         wm8776_write_cached(chip, WM8776_ALCCTRL2,
916                                             ctrl2 & ~WM8776_LCEN);
917                         break;
918                 case 1:
919                         wm8776_write_cached(chip, WM8776_ALCCTRL1,
920                                             (ctrl1 & ~WM8776_LCSEL_MASK) |
921                                             WM8776_LCSEL_LIMITER);
922                         wm8776_write_cached(chip, WM8776_ALCCTRL2,
923                                             ctrl2 | WM8776_LCEN);
924                         mode = LC_CONTROL_LIMITER;
925                         break;
926                 case 2:
927                         wm8776_write_cached(chip, WM8776_ALCCTRL1,
928                                             (ctrl1 & ~WM8776_LCSEL_MASK) |
929                                             WM8776_LCSEL_ALC_STEREO);
930                         wm8776_write_cached(chip, WM8776_ALCCTRL2,
931                                             ctrl2 | WM8776_LCEN);
932                         mode = LC_CONTROL_ALC;
933                         break;
934                 }
935                 for (i = 0; i < ARRAY_SIZE(data->lc_controls); ++i)
936                         activate_control(chip, data->lc_controls[i], mode);
937         }
938         mutex_unlock(&chip->mutex);
939         return changed;
940 }
941 
942 static int hpf_info(struct snd_kcontrol *ctl, struct snd_ctl_elem_info *info)
943 {
944         static const char *const names[2] = {
945                 "None", "High-pass Filter"
946         };
947 
948         return snd_ctl_enum_info(info, 1, 2, names);
949 }
950 
951 static int hpf_get(struct snd_kcontrol *ctl, struct snd_ctl_elem_value *value)
952 {
953         struct oxygen *chip = ctl->private_data;
954         struct xonar_wm87x6 *data = chip->model_data;
955 
956         value->value.enumerated.item[0] =
957                 !(data->wm8776_regs[WM8776_ADCIFCTRL] & WM8776_ADCHPD);
958         return 0;
959 }
960 
961 static int hpf_put(struct snd_kcontrol *ctl, struct snd_ctl_elem_value *value)
962 {
963         struct oxygen *chip = ctl->private_data;
964         struct xonar_wm87x6 *data = chip->model_data;
965         unsigned int reg;
966         int changed;
967 
968         mutex_lock(&chip->mutex);
969         reg = data->wm8776_regs[WM8776_ADCIFCTRL] & ~WM8776_ADCHPD;
970         if (!value->value.enumerated.item[0])
971                 reg |= WM8776_ADCHPD;
972         changed = reg != data->wm8776_regs[WM8776_ADCIFCTRL];
973         if (changed)
974                 wm8776_write(chip, WM8776_ADCIFCTRL, reg);
975         mutex_unlock(&chip->mutex);
976         return changed;
977 }
978 
979 #define WM8776_BIT_SWITCH(xname, reg, bit, invert, flags) { \
980         .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
981         .name = xname, \
982         .info = snd_ctl_boolean_mono_info, \
983         .get = wm8776_bit_switch_get, \
984         .put = wm8776_bit_switch_put, \
985         .private_value = ((reg) << 16) | (bit) | ((invert) << 24) | (flags), \
986 }
987 #define _WM8776_FIELD_CTL(xname, reg, shift, initval, min, max, mask, flags) \
988         .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
989         .name = xname, \
990         .private_value = (initval) | ((min) << 8) | ((max) << 12) | \
991         ((mask) << 16) | ((shift) << 20) | ((reg) << 24) | (flags)
992 #define WM8776_FIELD_CTL_ENUM(xname, reg, shift, init, min, max, mask, flags) {\
993         _WM8776_FIELD_CTL(xname " Capture Enum", \
994                           reg, shift, init, min, max, mask, flags), \
995         .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \
996                   SNDRV_CTL_ELEM_ACCESS_INACTIVE, \
997         .info = wm8776_field_enum_info, \
998         .get = wm8776_field_enum_get, \
999         .put = wm8776_field_enum_put, \
1000 }
1001 #define WM8776_FIELD_CTL_VOLUME(a, b, c, d, e, f, g, h, tlv_p) { \
1002         _WM8776_FIELD_CTL(a " Capture Volume", b, c, d, e, f, g, h), \
1003         .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \
1004                   SNDRV_CTL_ELEM_ACCESS_INACTIVE | \
1005                   SNDRV_CTL_ELEM_ACCESS_TLV_READ, \
1006         .info = wm8776_field_volume_info, \
1007         .get = wm8776_field_volume_get, \
1008         .put = wm8776_field_volume_put, \
1009         .tlv = { .p = tlv_p }, \
1010 }
1011 
1012 static const DECLARE_TLV_DB_SCALE(wm87x6_dac_db_scale, -6000, 50, 0);
1013 static const DECLARE_TLV_DB_SCALE(wm8776_adc_db_scale, -2100, 50, 0);
1014 static const DECLARE_TLV_DB_SCALE(wm8776_hp_db_scale, -6000, 100, 0);
1015 static const DECLARE_TLV_DB_SCALE(wm8776_lct_db_scale, -1600, 100, 0);
1016 static const DECLARE_TLV_DB_SCALE(wm8776_maxgain_db_scale, 0, 400, 0);
1017 static const DECLARE_TLV_DB_SCALE(wm8776_ngth_db_scale, -7800, 600, 0);
1018 static const DECLARE_TLV_DB_SCALE(wm8776_maxatten_lim_db_scale, -1200, 100, 0);
1019 static const DECLARE_TLV_DB_SCALE(wm8776_maxatten_alc_db_scale, -2100, 400, 0);
1020 
1021 static const struct snd_kcontrol_new ds_controls[] = {
1022         {
1023                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1024                 .name = "Headphone Playback Volume",
1025                 .info = wm8776_hp_vol_info,
1026                 .get = wm8776_hp_vol_get,
1027                 .put = wm8776_hp_vol_put,
1028                 .tlv = { .p = wm8776_hp_db_scale },
1029         },
1030         WM8776_BIT_SWITCH("Headphone Playback Switch",
1031                           WM8776_PWRDOWN, WM8776_HPPD, 1, 0),
1032         {
1033                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1034                 .name = "Input Capture Volume",
1035                 .info = wm8776_input_vol_info,
1036                 .get = wm8776_input_vol_get,
1037                 .put = wm8776_input_vol_put,
1038                 .tlv = { .p = wm8776_adc_db_scale },
1039         },
1040         {
1041                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1042                 .name = "Line Capture Switch",
1043                 .info = snd_ctl_boolean_mono_info,
1044                 .get = wm8776_input_mux_get,
1045                 .put = wm8776_input_mux_put,
1046                 .private_value = 1 << 0,
1047         },
1048         {
1049                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1050                 .name = "Mic Capture Switch",
1051                 .info = snd_ctl_boolean_mono_info,
1052                 .get = wm8776_input_mux_get,
1053                 .put = wm8776_input_mux_put,
1054                 .private_value = 1 << 1,
1055         },
1056         WM8776_BIT_SWITCH("Front Mic Capture Switch",
1057                           WM8776_ADCMUX, 1 << 2, 0, 0),
1058         WM8776_BIT_SWITCH("Aux Capture Switch",
1059                           WM8776_ADCMUX, 1 << 3, 0, 0),
1060         {
1061                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1062                 .name = "ADC Filter Capture Enum",
1063                 .info = hpf_info,
1064                 .get = hpf_get,
1065                 .put = hpf_put,
1066         },
1067         {
1068                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1069                 .name = "Level Control Capture Enum",
1070                 .info = wm8776_level_control_info,
1071                 .get = wm8776_level_control_get,
1072                 .put = wm8776_level_control_put,
1073                 .private_value = 0,
1074         },
1075 };
1076 static const struct snd_kcontrol_new hdav_slim_controls[] = {
1077         {
1078                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1079                 .name = "HDMI Playback Switch",
1080                 .info = snd_ctl_boolean_mono_info,
1081                 .get = xonar_gpio_bit_switch_get,
1082                 .put = xonar_gpio_bit_switch_put,
1083                 .private_value = GPIO_SLIM_HDMI_DISABLE | XONAR_GPIO_BIT_INVERT,
1084         },
1085         {
1086                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1087                 .name = "Headphone Playback Volume",
1088                 .info = wm8776_hp_vol_info,
1089                 .get = wm8776_hp_vol_get,
1090                 .put = wm8776_hp_vol_put,
1091                 .tlv = { .p = wm8776_hp_db_scale },
1092         },
1093         WM8776_BIT_SWITCH("Headphone Playback Switch",
1094                           WM8776_PWRDOWN, WM8776_HPPD, 1, 0),
1095         {
1096                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1097                 .name = "Input Capture Volume",
1098                 .info = wm8776_input_vol_info,
1099                 .get = wm8776_input_vol_get,
1100                 .put = wm8776_input_vol_put,
1101                 .tlv = { .p = wm8776_adc_db_scale },
1102         },
1103         WM8776_BIT_SWITCH("Mic Capture Switch",
1104                           WM8776_ADCMUX, 1 << 0, 0, 0),
1105         WM8776_BIT_SWITCH("Aux Capture Switch",
1106                           WM8776_ADCMUX, 1 << 1, 0, 0),
1107         {
1108                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1109                 .name = "ADC Filter Capture Enum",
1110                 .info = hpf_info,
1111                 .get = hpf_get,
1112                 .put = hpf_put,
1113         },
1114         {
1115                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1116                 .name = "Level Control Capture Enum",
1117                 .info = wm8776_level_control_info,
1118                 .get = wm8776_level_control_get,
1119                 .put = wm8776_level_control_put,
1120                 .private_value = 0,
1121         },
1122 };
1123 static const struct snd_kcontrol_new lc_controls[] = {
1124         WM8776_FIELD_CTL_VOLUME("Limiter Threshold",
1125                                 WM8776_ALCCTRL1, 0, 11, 0, 15, 0xf,
1126                                 LC_CONTROL_LIMITER, wm8776_lct_db_scale),
1127         WM8776_FIELD_CTL_ENUM("Limiter Attack Time",
1128                               WM8776_ALCCTRL3, 0, 2, 0, 10, 0xf,
1129                               LC_CONTROL_LIMITER),
1130         WM8776_FIELD_CTL_ENUM("Limiter Decay Time",
1131                               WM8776_ALCCTRL3, 4, 3, 0, 10, 0xf,
1132                               LC_CONTROL_LIMITER),
1133         WM8776_FIELD_CTL_ENUM("Limiter Transient Window",
1134                               WM8776_LIMITER, 4, 2, 0, 7, 0x7,
1135                               LC_CONTROL_LIMITER),
1136         WM8776_FIELD_CTL_VOLUME("Limiter Maximum Attenuation",
1137                                 WM8776_LIMITER, 0, 6, 3, 12, 0xf,
1138                                 LC_CONTROL_LIMITER,
1139                                 wm8776_maxatten_lim_db_scale),
1140         WM8776_FIELD_CTL_VOLUME("ALC Target Level",
1141                                 WM8776_ALCCTRL1, 0, 11, 0, 15, 0xf,
1142                                 LC_CONTROL_ALC, wm8776_lct_db_scale),
1143         WM8776_FIELD_CTL_ENUM("ALC Attack Time",
1144                               WM8776_ALCCTRL3, 0, 2, 0, 10, 0xf,
1145                               LC_CONTROL_ALC),
1146         WM8776_FIELD_CTL_ENUM("ALC Decay Time",
1147                               WM8776_ALCCTRL3, 4, 3, 0, 10, 0xf,
1148                               LC_CONTROL_ALC),
1149         WM8776_FIELD_CTL_VOLUME("ALC Maximum Gain",
1150                                 WM8776_ALCCTRL1, 4, 7, 1, 7, 0x7,
1151                                 LC_CONTROL_ALC, wm8776_maxgain_db_scale),
1152         WM8776_FIELD_CTL_VOLUME("ALC Maximum Attenuation",
1153                                 WM8776_LIMITER, 0, 10, 10, 15, 0xf,
1154                                 LC_CONTROL_ALC, wm8776_maxatten_alc_db_scale),
1155         WM8776_FIELD_CTL_ENUM("ALC Hold Time",
1156                               WM8776_ALCCTRL2, 0, 0, 0, 15, 0xf,
1157                               LC_CONTROL_ALC),
1158         WM8776_BIT_SWITCH("Noise Gate Capture Switch",
1159                           WM8776_NOISEGATE, WM8776_NGAT, 0,
1160                           LC_CONTROL_ALC),
1161         WM8776_FIELD_CTL_VOLUME("Noise Gate Threshold",
1162                                 WM8776_NOISEGATE, 2, 0, 0, 7, 0x7,
1163                                 LC_CONTROL_ALC, wm8776_ngth_db_scale),
1164 };
1165 
1166 static int add_lc_controls(struct oxygen *chip)
1167 {
1168         struct xonar_wm87x6 *data = chip->model_data;
1169         unsigned int i;
1170         struct snd_kcontrol *ctl;
1171         int err;
1172 
1173         BUILD_BUG_ON(ARRAY_SIZE(lc_controls) != ARRAY_SIZE(data->lc_controls));
1174         for (i = 0; i < ARRAY_SIZE(lc_controls); ++i) {
1175                 ctl = snd_ctl_new1(&lc_controls[i], chip);
1176                 if (!ctl)
1177                         return -ENOMEM;
1178                 err = snd_ctl_add(chip->card, ctl);
1179                 if (err < 0)
1180                         return err;
1181                 data->lc_controls[i] = ctl;
1182         }
1183         return 0;
1184 }
1185 
1186 static int xonar_ds_mixer_init(struct oxygen *chip)
1187 {
1188         struct xonar_wm87x6 *data = chip->model_data;
1189         unsigned int i;
1190         struct snd_kcontrol *ctl;
1191         int err;
1192 
1193         for (i = 0; i < ARRAY_SIZE(ds_controls); ++i) {
1194                 ctl = snd_ctl_new1(&ds_controls[i], chip);
1195                 if (!ctl)
1196                         return -ENOMEM;
1197                 err = snd_ctl_add(chip->card, ctl);
1198                 if (err < 0)
1199                         return err;
1200                 if (!strcmp(ctl->id.name, "Line Capture Switch"))
1201                         data->line_adcmux_control = ctl;
1202                 else if (!strcmp(ctl->id.name, "Mic Capture Switch"))
1203                         data->mic_adcmux_control = ctl;
1204         }
1205         if (!data->line_adcmux_control || !data->mic_adcmux_control)
1206                 return -ENXIO;
1207 
1208         return add_lc_controls(chip);
1209 }
1210 
1211 static int xonar_hdav_slim_mixer_init(struct oxygen *chip)
1212 {
1213         unsigned int i;
1214         struct snd_kcontrol *ctl;
1215         int err;
1216 
1217         for (i = 0; i < ARRAY_SIZE(hdav_slim_controls); ++i) {
1218                 ctl = snd_ctl_new1(&hdav_slim_controls[i], chip);
1219                 if (!ctl)
1220                         return -ENOMEM;
1221                 err = snd_ctl_add(chip->card, ctl);
1222                 if (err < 0)
1223                         return err;
1224         }
1225 
1226         return add_lc_controls(chip);
1227 }
1228 
1229 static void dump_wm8776_registers(struct oxygen *chip,
1230                                   struct snd_info_buffer *buffer)
1231 {
1232         struct xonar_wm87x6 *data = chip->model_data;
1233         unsigned int i;
1234 
1235         snd_iprintf(buffer, "\nWM8776:\n00:");
1236         for (i = 0; i < 0x10; ++i)
1237                 snd_iprintf(buffer, " %03x", data->wm8776_regs[i]);
1238         snd_iprintf(buffer, "\n10:");
1239         for (i = 0x10; i < 0x17; ++i)
1240                 snd_iprintf(buffer, " %03x", data->wm8776_regs[i]);
1241         snd_iprintf(buffer, "\n");
1242 }
1243 
1244 static void dump_wm87x6_registers(struct oxygen *chip,
1245                                   struct snd_info_buffer *buffer)
1246 {
1247         struct xonar_wm87x6 *data = chip->model_data;
1248         unsigned int i;
1249 
1250         dump_wm8776_registers(chip, buffer);
1251         snd_iprintf(buffer, "\nWM8766:\n00:");
1252         for (i = 0; i < 0x10; ++i)
1253                 snd_iprintf(buffer, " %03x", data->wm8766_regs[i]);
1254         snd_iprintf(buffer, "\n");
1255 }
1256 
1257 static const struct oxygen_model model_xonar_ds = {
1258         .longname = "Asus Virtuoso 66",
1259         .chip = "AV200",
1260         .init = xonar_ds_init,
1261         .mixer_init = xonar_ds_mixer_init,
1262         .cleanup = xonar_ds_cleanup,
1263         .suspend = xonar_ds_suspend,
1264         .resume = xonar_ds_resume,
1265         .pcm_hardware_filter = wm8776_adc_hardware_filter,
1266         .set_dac_params = set_wm87x6_dac_params,
1267         .set_adc_params = set_wm8776_adc_params,
1268         .update_dac_volume = update_wm87x6_volume,
1269         .update_dac_mute = update_wm87x6_mute,
1270         .update_center_lfe_mix = update_wm8766_center_lfe_mix,
1271         .gpio_changed = xonar_ds_gpio_changed,
1272         .dump_registers = dump_wm87x6_registers,
1273         .dac_tlv = wm87x6_dac_db_scale,
1274         .model_data_size = sizeof(struct xonar_wm87x6),
1275         .device_config = PLAYBACK_0_TO_I2S |
1276                          PLAYBACK_1_TO_SPDIF |
1277                          CAPTURE_0_FROM_I2S_1 |
1278                          CAPTURE_1_FROM_SPDIF,
1279         .dac_channels_pcm = 8,
1280         .dac_channels_mixer = 8,
1281         .dac_volume_min = 255 - 2*60,
1282         .dac_volume_max = 255,
1283         .function_flags = OXYGEN_FUNCTION_SPI,
1284         .dac_mclks = OXYGEN_MCLKS(256, 256, 128),
1285         .adc_mclks = OXYGEN_MCLKS(256, 256, 128),
1286         .dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
1287         .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
1288 };
1289 
1290 static const struct oxygen_model model_xonar_hdav_slim = {
1291         .shortname = "Xonar HDAV1.3 Slim",
1292         .longname = "Asus Virtuoso 200",
1293         .chip = "AV200",
1294         .init = xonar_hdav_slim_init,
1295         .mixer_init = xonar_hdav_slim_mixer_init,
1296         .cleanup = xonar_hdav_slim_cleanup,
1297         .suspend = xonar_hdav_slim_suspend,
1298         .resume = xonar_hdav_slim_resume,
1299         .pcm_hardware_filter = xonar_hdav_slim_hardware_filter,
1300         .set_dac_params = set_hdav_slim_dac_params,
1301         .set_adc_params = set_wm8776_adc_params,
1302         .update_dac_volume = update_wm8776_volume,
1303         .update_dac_mute = update_wm8776_mute,
1304         .uart_input = xonar_hdmi_uart_input,
1305         .dump_registers = dump_wm8776_registers,
1306         .dac_tlv = wm87x6_dac_db_scale,
1307         .model_data_size = sizeof(struct xonar_wm87x6),
1308         .device_config = PLAYBACK_0_TO_I2S |
1309                          PLAYBACK_1_TO_SPDIF |
1310                          CAPTURE_0_FROM_I2S_1 |
1311                          CAPTURE_1_FROM_SPDIF,
1312         .dac_channels_pcm = 8,
1313         .dac_channels_mixer = 2,
1314         .dac_volume_min = 255 - 2*60,
1315         .dac_volume_max = 255,
1316         .function_flags = OXYGEN_FUNCTION_2WIRE,
1317         .dac_mclks = OXYGEN_MCLKS(256, 256, 128),
1318         .adc_mclks = OXYGEN_MCLKS(256, 256, 128),
1319         .dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
1320         .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
1321 };
1322 
1323 int get_xonar_wm87x6_model(struct oxygen *chip,
1324                            const struct pci_device_id *id)
1325 {
1326         switch (id->subdevice) {
1327         case 0x838e:
1328                 chip->model = model_xonar_ds;
1329                 chip->model.shortname = "Xonar DS";
1330                 break;
1331         case 0x8522:
1332                 chip->model = model_xonar_ds;
1333                 chip->model.shortname = "Xonar DSX";
1334                 break;
1335         case 0x835e:
1336                 chip->model = model_xonar_hdav_slim;
1337                 break;
1338         default:
1339                 return -EINVAL;
1340         }
1341         return 0;
1342 }
1343 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp