]> asedeno.scripts.mit.edu Git - linux.git/blob - sound/pci/oxygen/xonar_dg.c
ALSA: oxygen: change description of the xonar_dg.c file
[linux.git] / sound / pci / oxygen / xonar_dg.c
1 /*
2  * card driver for the Xonar DG/DGX
3  *
4  * Copyright (c) Clemens Ladisch <clemens@ladisch.de>
5  * Copyright (c) Roman Volkov <v1ron@mail.ru>
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 DG/DGX
21  * ------------
22  *
23  * CS4245 and CS4361 both will mute all outputs if any clock ratio
24  * is invalid.
25  *
26  * CMI8788:
27  *
28  *   SPI 0 -> CS4245
29  *
30  *   Playback:
31  *   I²S 1 -> CS4245
32  *   I²S 2 -> CS4361 (center/LFE)
33  *   I²S 3 -> CS4361 (surround)
34  *   I²S 4 -> CS4361 (front)
35  *   Capture:
36  *   I²S ADC 1 <- CS4245
37  *
38  *   GPIO 3 <- ?
39  *   GPIO 4 <- headphone detect
40  *   GPIO 5 -> enable ADC analog circuit for the left channel
41  *   GPIO 6 -> enable ADC analog circuit for the right channel
42  *   GPIO 7 -> switch green rear output jack between CS4245 and and the first
43  *             channel of CS4361 (mechanical relay)
44  *   GPIO 8 -> enable output to speakers
45  *
46  * CS4245:
47  *
48  *   input 0 <- mic
49  *   input 1 <- aux
50  *   input 2 <- front mic
51  *   input 4 <- line
52  *   DAC out -> headphones
53  *   aux out -> front panel headphones
54  */
55
56 #include <linux/pci.h>
57 #include <linux/delay.h>
58 #include <sound/control.h>
59 #include <sound/core.h>
60 #include <sound/info.h>
61 #include <sound/pcm.h>
62 #include <sound/tlv.h>
63 #include "oxygen.h"
64 #include "xonar_dg.h"
65 #include "cs4245.h"
66
67 #define GPIO_MAGIC              0x0008
68 #define GPIO_HP_DETECT          0x0010
69 #define GPIO_INPUT_ROUTE        0x0060
70 #define GPIO_HP_REAR            0x0080
71 #define GPIO_OUTPUT_ENABLE      0x0100
72
73 struct dg {
74         unsigned int output_sel;
75         s8 input_vol[4][2];
76         unsigned int input_sel;
77         u8 hp_vol_att;
78         u8 cs4245_regs[0x11];
79 };
80
81 static void cs4245_write(struct oxygen *chip, unsigned int reg, u8 value)
82 {
83         struct dg *data = chip->model_data;
84
85         oxygen_write_spi(chip, OXYGEN_SPI_TRIGGER |
86                          OXYGEN_SPI_DATA_LENGTH_3 |
87                          OXYGEN_SPI_CLOCK_1280 |
88                          (0 << OXYGEN_SPI_CODEC_SHIFT) |
89                          OXYGEN_SPI_CEN_LATCH_CLOCK_HI,
90                          CS4245_SPI_ADDRESS |
91                          CS4245_SPI_WRITE |
92                          (reg << 8) | value);
93         data->cs4245_regs[reg] = value;
94 }
95
96 static void cs4245_write_cached(struct oxygen *chip, unsigned int reg, u8 value)
97 {
98         struct dg *data = chip->model_data;
99
100         if (value != data->cs4245_regs[reg])
101                 cs4245_write(chip, reg, value);
102 }
103
104 static void cs4245_registers_init(struct oxygen *chip)
105 {
106         struct dg *data = chip->model_data;
107
108         cs4245_write(chip, CS4245_POWER_CTRL, CS4245_PDN);
109         cs4245_write(chip, CS4245_DAC_CTRL_1,
110                      data->cs4245_regs[CS4245_DAC_CTRL_1]);
111         cs4245_write(chip, CS4245_ADC_CTRL,
112                      data->cs4245_regs[CS4245_ADC_CTRL]);
113         cs4245_write(chip, CS4245_SIGNAL_SEL,
114                      data->cs4245_regs[CS4245_SIGNAL_SEL]);
115         cs4245_write(chip, CS4245_PGA_B_CTRL,
116                      data->cs4245_regs[CS4245_PGA_B_CTRL]);
117         cs4245_write(chip, CS4245_PGA_A_CTRL,
118                      data->cs4245_regs[CS4245_PGA_A_CTRL]);
119         cs4245_write(chip, CS4245_ANALOG_IN,
120                      data->cs4245_regs[CS4245_ANALOG_IN]);
121         cs4245_write(chip, CS4245_DAC_A_CTRL,
122                      data->cs4245_regs[CS4245_DAC_A_CTRL]);
123         cs4245_write(chip, CS4245_DAC_B_CTRL,
124                      data->cs4245_regs[CS4245_DAC_B_CTRL]);
125         cs4245_write(chip, CS4245_DAC_CTRL_2,
126                      CS4245_DAC_SOFT | CS4245_DAC_ZERO | CS4245_INVERT_DAC);
127         cs4245_write(chip, CS4245_INT_MASK, 0);
128         cs4245_write(chip, CS4245_POWER_CTRL, 0);
129 }
130
131 static void cs4245_init(struct oxygen *chip)
132 {
133         struct dg *data = chip->model_data;
134
135         data->cs4245_regs[CS4245_DAC_CTRL_1] =
136                 CS4245_DAC_FM_SINGLE | CS4245_DAC_DIF_LJUST;
137         data->cs4245_regs[CS4245_ADC_CTRL] =
138                 CS4245_ADC_FM_SINGLE | CS4245_ADC_DIF_LJUST;
139         data->cs4245_regs[CS4245_SIGNAL_SEL] =
140                 CS4245_A_OUT_SEL_HIZ | CS4245_ASYNCH;
141         data->cs4245_regs[CS4245_PGA_B_CTRL] = 0;
142         data->cs4245_regs[CS4245_PGA_A_CTRL] = 0;
143         data->cs4245_regs[CS4245_ANALOG_IN] =
144                 CS4245_PGA_SOFT | CS4245_PGA_ZERO | CS4245_SEL_INPUT_4;
145         data->cs4245_regs[CS4245_DAC_A_CTRL] = 0;
146         data->cs4245_regs[CS4245_DAC_B_CTRL] = 0;
147         cs4245_registers_init(chip);
148         snd_component_add(chip->card, "CS4245");
149 }
150
151 static void dg_output_enable(struct oxygen *chip)
152 {
153         msleep(2500);
154         oxygen_set_bits16(chip, OXYGEN_GPIO_DATA, GPIO_OUTPUT_ENABLE);
155 }
156
157 static void dg_init(struct oxygen *chip)
158 {
159         struct dg *data = chip->model_data;
160
161         data->output_sel = 0;
162         data->input_sel = 3;
163         data->hp_vol_att = 2 * 16;
164
165         cs4245_init(chip);
166
167         oxygen_clear_bits16(chip, OXYGEN_GPIO_CONTROL,
168                             GPIO_MAGIC | GPIO_HP_DETECT);
169         oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL,
170                           GPIO_INPUT_ROUTE | GPIO_HP_REAR | GPIO_OUTPUT_ENABLE);
171         oxygen_clear_bits16(chip, OXYGEN_GPIO_DATA,
172                             GPIO_INPUT_ROUTE | GPIO_HP_REAR);
173         dg_output_enable(chip);
174 }
175
176 static void dg_cleanup(struct oxygen *chip)
177 {
178         oxygen_clear_bits16(chip, OXYGEN_GPIO_DATA, GPIO_OUTPUT_ENABLE);
179 }
180
181 static void dg_suspend(struct oxygen *chip)
182 {
183         dg_cleanup(chip);
184 }
185
186 static void dg_resume(struct oxygen *chip)
187 {
188         cs4245_registers_init(chip);
189         dg_output_enable(chip);
190 }
191
192 static void set_cs4245_dac_params(struct oxygen *chip,
193                                   struct snd_pcm_hw_params *params)
194 {
195         struct dg *data = chip->model_data;
196         u8 value;
197
198         value = data->cs4245_regs[CS4245_DAC_CTRL_1] & ~CS4245_DAC_FM_MASK;
199         if (params_rate(params) <= 50000)
200                 value |= CS4245_DAC_FM_SINGLE;
201         else if (params_rate(params) <= 100000)
202                 value |= CS4245_DAC_FM_DOUBLE;
203         else
204                 value |= CS4245_DAC_FM_QUAD;
205         cs4245_write_cached(chip, CS4245_DAC_CTRL_1, value);
206 }
207
208 static void set_cs4245_adc_params(struct oxygen *chip,
209                                   struct snd_pcm_hw_params *params)
210 {
211         struct dg *data = chip->model_data;
212         u8 value;
213
214         value = data->cs4245_regs[CS4245_ADC_CTRL] & ~CS4245_ADC_FM_MASK;
215         if (params_rate(params) <= 50000)
216                 value |= CS4245_ADC_FM_SINGLE;
217         else if (params_rate(params) <= 100000)
218                 value |= CS4245_ADC_FM_DOUBLE;
219         else
220                 value |= CS4245_ADC_FM_QUAD;
221         cs4245_write_cached(chip, CS4245_ADC_CTRL, value);
222 }
223
224 static inline unsigned int shift_bits(unsigned int value,
225                                       unsigned int shift_from,
226                                       unsigned int shift_to,
227                                       unsigned int mask)
228 {
229         if (shift_from < shift_to)
230                 return (value << (shift_to - shift_from)) & mask;
231         else
232                 return (value >> (shift_from - shift_to)) & mask;
233 }
234
235 static unsigned int adjust_dg_dac_routing(struct oxygen *chip,
236                                           unsigned int play_routing)
237 {
238         return (play_routing & OXYGEN_PLAY_DAC0_SOURCE_MASK) |
239                shift_bits(play_routing,
240                           OXYGEN_PLAY_DAC2_SOURCE_SHIFT,
241                           OXYGEN_PLAY_DAC1_SOURCE_SHIFT,
242                           OXYGEN_PLAY_DAC1_SOURCE_MASK) |
243                shift_bits(play_routing,
244                           OXYGEN_PLAY_DAC1_SOURCE_SHIFT,
245                           OXYGEN_PLAY_DAC2_SOURCE_SHIFT,
246                           OXYGEN_PLAY_DAC2_SOURCE_MASK) |
247                shift_bits(play_routing,
248                           OXYGEN_PLAY_DAC0_SOURCE_SHIFT,
249                           OXYGEN_PLAY_DAC3_SOURCE_SHIFT,
250                           OXYGEN_PLAY_DAC3_SOURCE_MASK);
251 }
252
253 static int output_switch_info(struct snd_kcontrol *ctl,
254                               struct snd_ctl_elem_info *info)
255 {
256         static const char *const names[3] = {
257                 "Speakers", "Headphones", "FP Headphones"
258         };
259
260         return snd_ctl_enum_info(info, 1, 3, names);
261 }
262
263 static int output_switch_get(struct snd_kcontrol *ctl,
264                              struct snd_ctl_elem_value *value)
265 {
266         struct oxygen *chip = ctl->private_data;
267         struct dg *data = chip->model_data;
268
269         mutex_lock(&chip->mutex);
270         value->value.enumerated.item[0] = data->output_sel;
271         mutex_unlock(&chip->mutex);
272         return 0;
273 }
274
275 static int output_switch_put(struct snd_kcontrol *ctl,
276                              struct snd_ctl_elem_value *value)
277 {
278         struct oxygen *chip = ctl->private_data;
279         struct dg *data = chip->model_data;
280         u8 reg;
281         int changed;
282
283         if (value->value.enumerated.item[0] > 2)
284                 return -EINVAL;
285
286         mutex_lock(&chip->mutex);
287         changed = value->value.enumerated.item[0] != data->output_sel;
288         if (changed) {
289                 data->output_sel = value->value.enumerated.item[0];
290
291                 reg = data->cs4245_regs[CS4245_SIGNAL_SEL] &
292                                                 ~CS4245_A_OUT_SEL_MASK;
293                 reg |= data->output_sel == 2 ?
294                                 CS4245_A_OUT_SEL_DAC : CS4245_A_OUT_SEL_HIZ;
295                 cs4245_write_cached(chip, CS4245_SIGNAL_SEL, reg);
296
297                 cs4245_write_cached(chip, CS4245_DAC_A_CTRL,
298                                     data->output_sel ? data->hp_vol_att : 0);
299                 cs4245_write_cached(chip, CS4245_DAC_B_CTRL,
300                                     data->output_sel ? data->hp_vol_att : 0);
301
302                 oxygen_write16_masked(chip, OXYGEN_GPIO_DATA,
303                                       data->output_sel == 1 ? GPIO_HP_REAR : 0,
304                                       GPIO_HP_REAR);
305         }
306         mutex_unlock(&chip->mutex);
307         return changed;
308 }
309
310 static int hp_volume_offset_info(struct snd_kcontrol *ctl,
311                                  struct snd_ctl_elem_info *info)
312 {
313         static const char *const names[3] = {
314                 "< 64 ohms", "64-150 ohms", "150-300 ohms"
315         };
316
317         return snd_ctl_enum_info(info, 1, 3, names);
318 }
319
320 static int hp_volume_offset_get(struct snd_kcontrol *ctl,
321                                 struct snd_ctl_elem_value *value)
322 {
323         struct oxygen *chip = ctl->private_data;
324         struct dg *data = chip->model_data;
325
326         mutex_lock(&chip->mutex);
327         if (data->hp_vol_att > 2 * 7)
328                 value->value.enumerated.item[0] = 0;
329         else if (data->hp_vol_att > 0)
330                 value->value.enumerated.item[0] = 1;
331         else
332                 value->value.enumerated.item[0] = 2;
333         mutex_unlock(&chip->mutex);
334         return 0;
335 }
336
337 static int hp_volume_offset_put(struct snd_kcontrol *ctl,
338                                 struct snd_ctl_elem_value *value)
339 {
340         static const s8 atts[3] = { 2 * 16, 2 * 7, 0 };
341         struct oxygen *chip = ctl->private_data;
342         struct dg *data = chip->model_data;
343         s8 att;
344         int changed;
345
346         if (value->value.enumerated.item[0] > 2)
347                 return -EINVAL;
348         att = atts[value->value.enumerated.item[0]];
349         mutex_lock(&chip->mutex);
350         changed = att != data->hp_vol_att;
351         if (changed) {
352                 data->hp_vol_att = att;
353                 if (data->output_sel) {
354                         cs4245_write_cached(chip, CS4245_DAC_A_CTRL, att);
355                         cs4245_write_cached(chip, CS4245_DAC_B_CTRL, att);
356                 }
357         }
358         mutex_unlock(&chip->mutex);
359         return changed;
360 }
361
362 static int input_vol_info(struct snd_kcontrol *ctl,
363                           struct snd_ctl_elem_info *info)
364 {
365         info->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
366         info->count = 2;
367         info->value.integer.min = 2 * -12;
368         info->value.integer.max = 2 * 12;
369         return 0;
370 }
371
372 static int input_vol_get(struct snd_kcontrol *ctl,
373                          struct snd_ctl_elem_value *value)
374 {
375         struct oxygen *chip = ctl->private_data;
376         struct dg *data = chip->model_data;
377         unsigned int idx = ctl->private_value;
378
379         mutex_lock(&chip->mutex);
380         value->value.integer.value[0] = data->input_vol[idx][0];
381         value->value.integer.value[1] = data->input_vol[idx][1];
382         mutex_unlock(&chip->mutex);
383         return 0;
384 }
385
386 static int input_vol_put(struct snd_kcontrol *ctl,
387                          struct snd_ctl_elem_value *value)
388 {
389         struct oxygen *chip = ctl->private_data;
390         struct dg *data = chip->model_data;
391         unsigned int idx = ctl->private_value;
392         int changed = 0;
393
394         if (value->value.integer.value[0] < 2 * -12 ||
395             value->value.integer.value[0] > 2 * 12 ||
396             value->value.integer.value[1] < 2 * -12 ||
397             value->value.integer.value[1] > 2 * 12)
398                 return -EINVAL;
399         mutex_lock(&chip->mutex);
400         changed = data->input_vol[idx][0] != value->value.integer.value[0] ||
401                   data->input_vol[idx][1] != value->value.integer.value[1];
402         if (changed) {
403                 data->input_vol[idx][0] = value->value.integer.value[0];
404                 data->input_vol[idx][1] = value->value.integer.value[1];
405                 if (idx == data->input_sel) {
406                         cs4245_write_cached(chip, CS4245_PGA_A_CTRL,
407                                             data->input_vol[idx][0]);
408                         cs4245_write_cached(chip, CS4245_PGA_B_CTRL,
409                                             data->input_vol[idx][1]);
410                 }
411         }
412         mutex_unlock(&chip->mutex);
413         return changed;
414 }
415
416 static DECLARE_TLV_DB_SCALE(cs4245_pga_db_scale, -1200, 50, 0);
417
418 static int input_sel_info(struct snd_kcontrol *ctl,
419                           struct snd_ctl_elem_info *info)
420 {
421         static const char *const names[4] = {
422                 "Mic", "Aux", "Front Mic", "Line"
423         };
424
425         return snd_ctl_enum_info(info, 1, 4, names);
426 }
427
428 static int input_sel_get(struct snd_kcontrol *ctl,
429                          struct snd_ctl_elem_value *value)
430 {
431         struct oxygen *chip = ctl->private_data;
432         struct dg *data = chip->model_data;
433
434         mutex_lock(&chip->mutex);
435         value->value.enumerated.item[0] = data->input_sel;
436         mutex_unlock(&chip->mutex);
437         return 0;
438 }
439
440 static int input_sel_put(struct snd_kcontrol *ctl,
441                          struct snd_ctl_elem_value *value)
442 {
443         static const u8 sel_values[4] = {
444                 CS4245_SEL_MIC,
445                 CS4245_SEL_INPUT_1,
446                 CS4245_SEL_INPUT_2,
447                 CS4245_SEL_INPUT_4
448         };
449         struct oxygen *chip = ctl->private_data;
450         struct dg *data = chip->model_data;
451         int changed;
452
453         if (value->value.enumerated.item[0] > 3)
454                 return -EINVAL;
455
456         mutex_lock(&chip->mutex);
457         changed = value->value.enumerated.item[0] != data->input_sel;
458         if (changed) {
459                 data->input_sel = value->value.enumerated.item[0];
460
461                 cs4245_write(chip, CS4245_ANALOG_IN,
462                              (data->cs4245_regs[CS4245_ANALOG_IN] &
463                                                         ~CS4245_SEL_MASK) |
464                              sel_values[data->input_sel]);
465
466                 cs4245_write_cached(chip, CS4245_PGA_A_CTRL,
467                                     data->input_vol[data->input_sel][0]);
468                 cs4245_write_cached(chip, CS4245_PGA_B_CTRL,
469                                     data->input_vol[data->input_sel][1]);
470
471                 oxygen_write16_masked(chip, OXYGEN_GPIO_DATA,
472                                       data->input_sel ? 0 : GPIO_INPUT_ROUTE,
473                                       GPIO_INPUT_ROUTE);
474         }
475         mutex_unlock(&chip->mutex);
476         return changed;
477 }
478
479 static int hpf_info(struct snd_kcontrol *ctl, struct snd_ctl_elem_info *info)
480 {
481         static const char *const names[2] = { "Active", "Frozen" };
482
483         return snd_ctl_enum_info(info, 1, 2, names);
484 }
485
486 static int hpf_get(struct snd_kcontrol *ctl, struct snd_ctl_elem_value *value)
487 {
488         struct oxygen *chip = ctl->private_data;
489         struct dg *data = chip->model_data;
490
491         value->value.enumerated.item[0] =
492                 !!(data->cs4245_regs[CS4245_ADC_CTRL] & CS4245_HPF_FREEZE);
493         return 0;
494 }
495
496 static int hpf_put(struct snd_kcontrol *ctl, struct snd_ctl_elem_value *value)
497 {
498         struct oxygen *chip = ctl->private_data;
499         struct dg *data = chip->model_data;
500         u8 reg;
501         int changed;
502
503         mutex_lock(&chip->mutex);
504         reg = data->cs4245_regs[CS4245_ADC_CTRL] & ~CS4245_HPF_FREEZE;
505         if (value->value.enumerated.item[0])
506                 reg |= CS4245_HPF_FREEZE;
507         changed = reg != data->cs4245_regs[CS4245_ADC_CTRL];
508         if (changed)
509                 cs4245_write(chip, CS4245_ADC_CTRL, reg);
510         mutex_unlock(&chip->mutex);
511         return changed;
512 }
513
514 #define INPUT_VOLUME(xname, index) { \
515         .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
516         .name = xname, \
517         .info = input_vol_info, \
518         .get = input_vol_get, \
519         .put = input_vol_put, \
520         .tlv = { .p = cs4245_pga_db_scale }, \
521         .private_value = index, \
522 }
523 static const struct snd_kcontrol_new dg_controls[] = {
524         {
525                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
526                 .name = "Analog Output Playback Enum",
527                 .info = output_switch_info,
528                 .get = output_switch_get,
529                 .put = output_switch_put,
530         },
531         {
532                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
533                 .name = "Headphones Impedance Playback Enum",
534                 .info = hp_volume_offset_info,
535                 .get = hp_volume_offset_get,
536                 .put = hp_volume_offset_put,
537         },
538         INPUT_VOLUME("Mic Capture Volume", 0),
539         INPUT_VOLUME("Aux Capture Volume", 1),
540         INPUT_VOLUME("Front Mic Capture Volume", 2),
541         INPUT_VOLUME("Line Capture Volume", 3),
542         {
543                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
544                 .name = "Capture Source",
545                 .info = input_sel_info,
546                 .get = input_sel_get,
547                 .put = input_sel_put,
548         },
549         {
550                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
551                 .name = "ADC High-pass Filter Capture Enum",
552                 .info = hpf_info,
553                 .get = hpf_get,
554                 .put = hpf_put,
555         },
556 };
557
558 static int dg_control_filter(struct snd_kcontrol_new *template)
559 {
560         if (!strncmp(template->name, "Master Playback ", 16))
561                 return 1;
562         return 0;
563 }
564
565 static int dg_mixer_init(struct oxygen *chip)
566 {
567         unsigned int i;
568         int err;
569
570         for (i = 0; i < ARRAY_SIZE(dg_controls); ++i) {
571                 err = snd_ctl_add(chip->card,
572                                   snd_ctl_new1(&dg_controls[i], chip));
573                 if (err < 0)
574                         return err;
575         }
576         return 0;
577 }
578
579 static void dump_cs4245_registers(struct oxygen *chip,
580                                   struct snd_info_buffer *buffer)
581 {
582         struct dg *data = chip->model_data;
583         unsigned int i;
584
585         snd_iprintf(buffer, "\nCS4245:");
586         for (i = 1; i <= 0x10; ++i)
587                 snd_iprintf(buffer, " %02x", data->cs4245_regs[i]);
588         snd_iprintf(buffer, "\n");
589 }
590
591 struct oxygen_model model_xonar_dg = {
592         .longname = "C-Media Oxygen HD Audio",
593         .chip = "CMI8786",
594         .init = dg_init,
595         .control_filter = dg_control_filter,
596         .mixer_init = dg_mixer_init,
597         .cleanup = dg_cleanup,
598         .suspend = dg_suspend,
599         .resume = dg_resume,
600         .set_dac_params = set_cs4245_dac_params,
601         .set_adc_params = set_cs4245_adc_params,
602         .adjust_dac_routing = adjust_dg_dac_routing,
603         .dump_registers = dump_cs4245_registers,
604         .model_data_size = sizeof(struct dg),
605         .device_config = PLAYBACK_0_TO_I2S |
606                          PLAYBACK_1_TO_SPDIF |
607                          CAPTURE_0_FROM_I2S_2 |
608                          CAPTURE_1_FROM_SPDIF,
609         .dac_channels_pcm = 6,
610         .dac_channels_mixer = 0,
611         .function_flags = OXYGEN_FUNCTION_SPI,
612         .dac_mclks = OXYGEN_MCLKS(256, 128, 128),
613         .adc_mclks = OXYGEN_MCLKS(256, 128, 128),
614         .dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
615         .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
616 };