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

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

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

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

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

kernel.org | git.kernel.org | LWN.net | Project Home | 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.

sflogo.php