2 * card driver for the Xonar DG/DGX
4 * Copyright (c) Clemens Ladisch <clemens@ladisch.de>
5 * Copyright (c) Roman Volkov <v1ron@mail.ru>
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.
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.
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/>.
23 * CS4245 and CS4361 both will mute all outputs if any clock ratio
32 * I²S 2 -> CS4361 (center/LFE)
33 * I²S 3 -> CS4361 (surround)
34 * I²S 4 -> CS4361 (front)
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
50 * input 2 <- front mic
52 * DAC out -> headphones
53 * aux out -> front panel headphones
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>
67 int cs4245_write_spi(struct oxygen
*chip
, u8 reg
)
69 struct dg
*data
= chip
->model_data
;
73 packet
|= (CS4245_SPI_ADDRESS
| CS4245_SPI_WRITE
) << 16;
74 packet
|= data
->cs4245_shadow
[reg
];
76 return oxygen_write_spi(chip
, OXYGEN_SPI_TRIGGER
|
77 OXYGEN_SPI_DATA_LENGTH_3
|
78 OXYGEN_SPI_CLOCK_1280
|
79 (0 << OXYGEN_SPI_CODEC_SHIFT
) |
80 OXYGEN_SPI_CEN_LATCH_CLOCK_HI
,
84 int cs4245_read_spi(struct oxygen
*chip
, u8 addr
)
86 struct dg
*data
= chip
->model_data
;
89 ret
= oxygen_write_spi(chip
, OXYGEN_SPI_TRIGGER
|
90 OXYGEN_SPI_DATA_LENGTH_2
|
91 OXYGEN_SPI_CEN_LATCH_CLOCK_HI
|
92 OXYGEN_SPI_CLOCK_1280
| (0 << OXYGEN_SPI_CODEC_SHIFT
),
93 ((CS4245_SPI_ADDRESS
| CS4245_SPI_WRITE
) << 8) | addr
);
97 ret
= oxygen_write_spi(chip
, OXYGEN_SPI_TRIGGER
|
98 OXYGEN_SPI_DATA_LENGTH_2
|
99 OXYGEN_SPI_CEN_LATCH_CLOCK_HI
|
100 OXYGEN_SPI_CLOCK_1280
| (0 << OXYGEN_SPI_CODEC_SHIFT
),
101 (CS4245_SPI_ADDRESS
| CS4245_SPI_READ
) << 8);
105 data
->cs4245_shadow
[addr
] = oxygen_read8(chip
, OXYGEN_SPI_DATA1
);
110 int cs4245_shadow_control(struct oxygen
*chip
, enum cs4245_shadow_operation op
)
112 struct dg
*data
= chip
->model_data
;
116 for (addr
= 1; addr
< ARRAY_SIZE(data
->cs4245_shadow
); addr
++) {
117 ret
= (op
== CS4245_SAVE_TO_SHADOW
?
118 cs4245_read_spi(chip
, addr
) :
119 cs4245_write_spi(chip
, addr
));
126 static void cs4245_write(struct oxygen
*chip
, unsigned int reg
, u8 value
)
128 struct dg
*data
= chip
->model_data
;
130 oxygen_write_spi(chip
, OXYGEN_SPI_TRIGGER
|
131 OXYGEN_SPI_DATA_LENGTH_3
|
132 OXYGEN_SPI_CLOCK_1280
|
133 (0 << OXYGEN_SPI_CODEC_SHIFT
) |
134 OXYGEN_SPI_CEN_LATCH_CLOCK_HI
,
135 CS4245_SPI_ADDRESS_S
|
138 data
->cs4245_shadow
[reg
] = value
;
141 static void cs4245_write_cached(struct oxygen
*chip
, unsigned int reg
, u8 value
)
143 struct dg
*data
= chip
->model_data
;
145 if (value
!= data
->cs4245_shadow
[reg
])
146 cs4245_write(chip
, reg
, value
);
149 static void cs4245_init(struct oxygen
*chip
)
151 struct dg
*data
= chip
->model_data
;
153 /* save the initial state: codec version, registers */
154 cs4245_shadow_control(chip
, CS4245_SAVE_TO_SHADOW
);
157 * Power up the CODEC internals, enable soft ramp & zero cross, work in
158 * async. mode, enable aux output from DAC. Invert DAC output as in the
161 data
->cs4245_shadow
[CS4245_POWER_CTRL
] = 0;
162 data
->cs4245_shadow
[CS4245_SIGNAL_SEL
] =
163 CS4245_A_OUT_SEL_DAC
| CS4245_ASYNCH
;
164 data
->cs4245_shadow
[CS4245_DAC_CTRL_1
] =
165 CS4245_DAC_FM_SINGLE
| CS4245_DAC_DIF_LJUST
;
166 data
->cs4245_shadow
[CS4245_DAC_CTRL_2
] =
167 CS4245_DAC_SOFT
| CS4245_DAC_ZERO
| CS4245_INVERT_DAC
;
168 data
->cs4245_shadow
[CS4245_ADC_CTRL
] =
169 CS4245_ADC_FM_SINGLE
| CS4245_ADC_DIF_LJUST
;
170 data
->cs4245_shadow
[CS4245_ANALOG_IN
] =
171 CS4245_PGA_SOFT
| CS4245_PGA_ZERO
;
172 data
->cs4245_shadow
[CS4245_PGA_B_CTRL
] = 0;
173 data
->cs4245_shadow
[CS4245_PGA_A_CTRL
] = 0;
174 data
->cs4245_shadow
[CS4245_DAC_A_CTRL
] = 4;
175 data
->cs4245_shadow
[CS4245_DAC_B_CTRL
] = 4;
177 cs4245_shadow_control(chip
, CS4245_LOAD_FROM_SHADOW
);
178 snd_component_add(chip
->card
, "CS4245");
181 static void dg_init(struct oxygen
*chip
)
183 struct dg
*data
= chip
->model_data
;
185 data
->output_sel
= 0;
187 data
->hp_vol_att
= 2 * 16;
190 oxygen_write16(chip
, OXYGEN_GPIO_CONTROL
,
191 GPIO_OUTPUT_ENABLE
| GPIO_HP_REAR
| GPIO_INPUT_ROUTE
);
192 oxygen_write16(chip
, OXYGEN_GPIO_DATA
, GPIO_INPUT_ROUTE
);
193 msleep(2500); /* anti-pop delay */
194 oxygen_write16(chip
, OXYGEN_GPIO_DATA
,
195 GPIO_OUTPUT_ENABLE
| GPIO_INPUT_ROUTE
);
198 static void dg_cleanup(struct oxygen
*chip
)
200 oxygen_clear_bits16(chip
, OXYGEN_GPIO_DATA
, GPIO_OUTPUT_ENABLE
);
203 static void dg_suspend(struct oxygen
*chip
)
208 static void dg_resume(struct oxygen
*chip
)
210 cs4245_shadow_control(chip
, CS4245_LOAD_FROM_SHADOW
);
212 oxygen_set_bits16(chip
, OXYGEN_GPIO_DATA
, GPIO_OUTPUT_ENABLE
);
215 static void set_cs4245_dac_params(struct oxygen
*chip
,
216 struct snd_pcm_hw_params
*params
)
218 struct dg
*data
= chip
->model_data
;
219 unsigned char dac_ctrl
;
220 unsigned char mclk_freq
;
222 dac_ctrl
= data
->cs4245_shadow
[CS4245_DAC_CTRL_1
] & ~CS4245_DAC_FM_MASK
;
223 mclk_freq
= data
->cs4245_shadow
[CS4245_MCLK_FREQ
] & ~CS4245_MCLK1_MASK
;
224 if (params_rate(params
) <= 50000) {
225 dac_ctrl
|= CS4245_DAC_FM_SINGLE
;
226 mclk_freq
|= CS4245_MCLK_1
<< CS4245_MCLK1_SHIFT
;
227 } else if (params_rate(params
) <= 100000) {
228 dac_ctrl
|= CS4245_DAC_FM_DOUBLE
;
229 mclk_freq
|= CS4245_MCLK_1
<< CS4245_MCLK1_SHIFT
;
231 dac_ctrl
|= CS4245_DAC_FM_QUAD
;
232 mclk_freq
|= CS4245_MCLK_2
<< CS4245_MCLK1_SHIFT
;
234 data
->cs4245_shadow
[CS4245_DAC_CTRL_1
] = dac_ctrl
;
235 data
->cs4245_shadow
[CS4245_MCLK_FREQ
] = mclk_freq
;
236 cs4245_write_spi(chip
, CS4245_DAC_CTRL_1
);
237 cs4245_write_spi(chip
, CS4245_MCLK_FREQ
);
240 static void set_cs4245_adc_params(struct oxygen
*chip
,
241 struct snd_pcm_hw_params
*params
)
243 struct dg
*data
= chip
->model_data
;
244 unsigned char adc_ctrl
;
245 unsigned char mclk_freq
;
247 adc_ctrl
= data
->cs4245_shadow
[CS4245_ADC_CTRL
] & ~CS4245_ADC_FM_MASK
;
248 mclk_freq
= data
->cs4245_shadow
[CS4245_MCLK_FREQ
] & ~CS4245_MCLK2_MASK
;
249 if (params_rate(params
) <= 50000) {
250 adc_ctrl
|= CS4245_ADC_FM_SINGLE
;
251 mclk_freq
|= CS4245_MCLK_1
<< CS4245_MCLK2_SHIFT
;
252 } else if (params_rate(params
) <= 100000) {
253 adc_ctrl
|= CS4245_ADC_FM_DOUBLE
;
254 mclk_freq
|= CS4245_MCLK_1
<< CS4245_MCLK2_SHIFT
;
256 adc_ctrl
|= CS4245_ADC_FM_QUAD
;
257 mclk_freq
|= CS4245_MCLK_2
<< CS4245_MCLK2_SHIFT
;
259 data
->cs4245_shadow
[CS4245_ADC_CTRL
] = adc_ctrl
;
260 data
->cs4245_shadow
[CS4245_MCLK_FREQ
] = mclk_freq
;
261 cs4245_write_spi(chip
, CS4245_ADC_CTRL
);
262 cs4245_write_spi(chip
, CS4245_MCLK_FREQ
);
265 static unsigned int adjust_dg_dac_routing(struct oxygen
*chip
,
266 unsigned int play_routing
)
268 struct dg
*data
= chip
->model_data
;
269 unsigned int routing
= 0;
271 switch (data
->pcm_output
) {
272 case PLAYBACK_DST_HP
:
273 case PLAYBACK_DST_HP_FP
:
274 oxygen_write8_masked(chip
, OXYGEN_PLAY_ROUTING
,
275 OXYGEN_PLAY_MUTE23
| OXYGEN_PLAY_MUTE45
|
276 OXYGEN_PLAY_MUTE67
, OXYGEN_PLAY_MUTE_MASK
);
278 case PLAYBACK_DST_MULTICH
:
279 routing
= (0 << OXYGEN_PLAY_DAC0_SOURCE_SHIFT
) |
280 (2 << OXYGEN_PLAY_DAC1_SOURCE_SHIFT
) |
281 (1 << OXYGEN_PLAY_DAC2_SOURCE_SHIFT
) |
282 (0 << OXYGEN_PLAY_DAC3_SOURCE_SHIFT
);
283 oxygen_write8_masked(chip
, OXYGEN_PLAY_ROUTING
,
284 OXYGEN_PLAY_MUTE01
, OXYGEN_PLAY_MUTE_MASK
);
290 static int output_switch_info(struct snd_kcontrol
*ctl
,
291 struct snd_ctl_elem_info
*info
)
293 static const char *const names
[3] = {
294 "Speakers", "Headphones", "FP Headphones"
297 return snd_ctl_enum_info(info
, 1, 3, names
);
300 static int output_switch_get(struct snd_kcontrol
*ctl
,
301 struct snd_ctl_elem_value
*value
)
303 struct oxygen
*chip
= ctl
->private_data
;
304 struct dg
*data
= chip
->model_data
;
306 mutex_lock(&chip
->mutex
);
307 value
->value
.enumerated
.item
[0] = data
->output_sel
;
308 mutex_unlock(&chip
->mutex
);
312 static int output_switch_put(struct snd_kcontrol
*ctl
,
313 struct snd_ctl_elem_value
*value
)
315 struct oxygen
*chip
= ctl
->private_data
;
316 struct dg
*data
= chip
->model_data
;
320 if (value
->value
.enumerated
.item
[0] > 2)
323 mutex_lock(&chip
->mutex
);
324 changed
= value
->value
.enumerated
.item
[0] != data
->output_sel
;
326 data
->output_sel
= value
->value
.enumerated
.item
[0];
328 reg
= data
->cs4245_shadow
[CS4245_SIGNAL_SEL
] &
329 ~CS4245_A_OUT_SEL_MASK
;
330 reg
|= data
->output_sel
== 2 ?
331 CS4245_A_OUT_SEL_DAC
: CS4245_A_OUT_SEL_HIZ
;
332 cs4245_write_cached(chip
, CS4245_SIGNAL_SEL
, reg
);
334 cs4245_write_cached(chip
, CS4245_DAC_A_CTRL
,
335 data
->output_sel
? data
->hp_vol_att
: 0);
336 cs4245_write_cached(chip
, CS4245_DAC_B_CTRL
,
337 data
->output_sel
? data
->hp_vol_att
: 0);
339 oxygen_write16_masked(chip
, OXYGEN_GPIO_DATA
,
340 data
->output_sel
== 1 ? GPIO_HP_REAR
: 0,
343 mutex_unlock(&chip
->mutex
);
347 static int hp_volume_offset_info(struct snd_kcontrol
*ctl
,
348 struct snd_ctl_elem_info
*info
)
350 static const char *const names
[3] = {
351 "< 64 ohms", "64-150 ohms", "150-300 ohms"
354 return snd_ctl_enum_info(info
, 1, 3, names
);
357 static int hp_volume_offset_get(struct snd_kcontrol
*ctl
,
358 struct snd_ctl_elem_value
*value
)
360 struct oxygen
*chip
= ctl
->private_data
;
361 struct dg
*data
= chip
->model_data
;
363 mutex_lock(&chip
->mutex
);
364 if (data
->hp_vol_att
> 2 * 7)
365 value
->value
.enumerated
.item
[0] = 0;
366 else if (data
->hp_vol_att
> 0)
367 value
->value
.enumerated
.item
[0] = 1;
369 value
->value
.enumerated
.item
[0] = 2;
370 mutex_unlock(&chip
->mutex
);
374 static int hp_volume_offset_put(struct snd_kcontrol
*ctl
,
375 struct snd_ctl_elem_value
*value
)
377 static const s8 atts
[3] = { 2 * 16, 2 * 7, 0 };
378 struct oxygen
*chip
= ctl
->private_data
;
379 struct dg
*data
= chip
->model_data
;
383 if (value
->value
.enumerated
.item
[0] > 2)
385 att
= atts
[value
->value
.enumerated
.item
[0]];
386 mutex_lock(&chip
->mutex
);
387 changed
= att
!= data
->hp_vol_att
;
389 data
->hp_vol_att
= att
;
390 if (data
->output_sel
) {
391 cs4245_write_cached(chip
, CS4245_DAC_A_CTRL
, att
);
392 cs4245_write_cached(chip
, CS4245_DAC_B_CTRL
, att
);
395 mutex_unlock(&chip
->mutex
);
399 static int input_vol_info(struct snd_kcontrol
*ctl
,
400 struct snd_ctl_elem_info
*info
)
402 info
->type
= SNDRV_CTL_ELEM_TYPE_INTEGER
;
404 info
->value
.integer
.min
= 2 * -12;
405 info
->value
.integer
.max
= 2 * 12;
409 static int input_vol_get(struct snd_kcontrol
*ctl
,
410 struct snd_ctl_elem_value
*value
)
412 struct oxygen
*chip
= ctl
->private_data
;
413 struct dg
*data
= chip
->model_data
;
414 unsigned int idx
= ctl
->private_value
;
416 mutex_lock(&chip
->mutex
);
417 value
->value
.integer
.value
[0] = data
->input_vol
[idx
][0];
418 value
->value
.integer
.value
[1] = data
->input_vol
[idx
][1];
419 mutex_unlock(&chip
->mutex
);
423 static int input_vol_put(struct snd_kcontrol
*ctl
,
424 struct snd_ctl_elem_value
*value
)
426 struct oxygen
*chip
= ctl
->private_data
;
427 struct dg
*data
= chip
->model_data
;
428 unsigned int idx
= ctl
->private_value
;
431 if (value
->value
.integer
.value
[0] < 2 * -12 ||
432 value
->value
.integer
.value
[0] > 2 * 12 ||
433 value
->value
.integer
.value
[1] < 2 * -12 ||
434 value
->value
.integer
.value
[1] > 2 * 12)
436 mutex_lock(&chip
->mutex
);
437 changed
= data
->input_vol
[idx
][0] != value
->value
.integer
.value
[0] ||
438 data
->input_vol
[idx
][1] != value
->value
.integer
.value
[1];
440 data
->input_vol
[idx
][0] = value
->value
.integer
.value
[0];
441 data
->input_vol
[idx
][1] = value
->value
.integer
.value
[1];
442 if (idx
== data
->input_sel
) {
443 cs4245_write_cached(chip
, CS4245_PGA_A_CTRL
,
444 data
->input_vol
[idx
][0]);
445 cs4245_write_cached(chip
, CS4245_PGA_B_CTRL
,
446 data
->input_vol
[idx
][1]);
449 mutex_unlock(&chip
->mutex
);
453 static DECLARE_TLV_DB_SCALE(cs4245_pga_db_scale
, -1200, 50, 0);
455 static int input_sel_info(struct snd_kcontrol
*ctl
,
456 struct snd_ctl_elem_info
*info
)
458 static const char *const names
[4] = {
459 "Mic", "Aux", "Front Mic", "Line"
462 return snd_ctl_enum_info(info
, 1, 4, names
);
465 static int input_sel_get(struct snd_kcontrol
*ctl
,
466 struct snd_ctl_elem_value
*value
)
468 struct oxygen
*chip
= ctl
->private_data
;
469 struct dg
*data
= chip
->model_data
;
471 mutex_lock(&chip
->mutex
);
472 value
->value
.enumerated
.item
[0] = data
->input_sel
;
473 mutex_unlock(&chip
->mutex
);
477 static int input_sel_put(struct snd_kcontrol
*ctl
,
478 struct snd_ctl_elem_value
*value
)
480 static const u8 sel_values
[4] = {
486 struct oxygen
*chip
= ctl
->private_data
;
487 struct dg
*data
= chip
->model_data
;
490 if (value
->value
.enumerated
.item
[0] > 3)
493 mutex_lock(&chip
->mutex
);
494 changed
= value
->value
.enumerated
.item
[0] != data
->input_sel
;
496 data
->input_sel
= value
->value
.enumerated
.item
[0];
498 cs4245_write(chip
, CS4245_ANALOG_IN
,
499 (data
->cs4245_shadow
[CS4245_ANALOG_IN
] &
501 sel_values
[data
->input_sel
]);
503 cs4245_write_cached(chip
, CS4245_PGA_A_CTRL
,
504 data
->input_vol
[data
->input_sel
][0]);
505 cs4245_write_cached(chip
, CS4245_PGA_B_CTRL
,
506 data
->input_vol
[data
->input_sel
][1]);
508 oxygen_write16_masked(chip
, OXYGEN_GPIO_DATA
,
509 data
->input_sel
? 0 : GPIO_INPUT_ROUTE
,
512 mutex_unlock(&chip
->mutex
);
516 static int hpf_info(struct snd_kcontrol
*ctl
, struct snd_ctl_elem_info
*info
)
518 static const char *const names
[2] = { "Active", "Frozen" };
520 return snd_ctl_enum_info(info
, 1, 2, names
);
523 static int hpf_get(struct snd_kcontrol
*ctl
, struct snd_ctl_elem_value
*value
)
525 struct oxygen
*chip
= ctl
->private_data
;
526 struct dg
*data
= chip
->model_data
;
528 value
->value
.enumerated
.item
[0] =
529 !!(data
->cs4245_shadow
[CS4245_ADC_CTRL
] & CS4245_HPF_FREEZE
);
533 static int hpf_put(struct snd_kcontrol
*ctl
, struct snd_ctl_elem_value
*value
)
535 struct oxygen
*chip
= ctl
->private_data
;
536 struct dg
*data
= chip
->model_data
;
540 mutex_lock(&chip
->mutex
);
541 reg
= data
->cs4245_shadow
[CS4245_ADC_CTRL
] & ~CS4245_HPF_FREEZE
;
542 if (value
->value
.enumerated
.item
[0])
543 reg
|= CS4245_HPF_FREEZE
;
544 changed
= reg
!= data
->cs4245_shadow
[CS4245_ADC_CTRL
];
546 cs4245_write(chip
, CS4245_ADC_CTRL
, reg
);
547 mutex_unlock(&chip
->mutex
);
551 #define INPUT_VOLUME(xname, index) { \
552 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
554 .info = input_vol_info, \
555 .get = input_vol_get, \
556 .put = input_vol_put, \
557 .tlv = { .p = cs4245_pga_db_scale }, \
558 .private_value = index, \
560 static const struct snd_kcontrol_new dg_controls
[] = {
562 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
563 .name
= "Analog Output Playback Enum",
564 .info
= output_switch_info
,
565 .get
= output_switch_get
,
566 .put
= output_switch_put
,
569 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
570 .name
= "Headphones Impedance Playback Enum",
571 .info
= hp_volume_offset_info
,
572 .get
= hp_volume_offset_get
,
573 .put
= hp_volume_offset_put
,
575 INPUT_VOLUME("Mic Capture Volume", 0),
576 INPUT_VOLUME("Aux Capture Volume", 1),
577 INPUT_VOLUME("Front Mic Capture Volume", 2),
578 INPUT_VOLUME("Line Capture Volume", 3),
580 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
581 .name
= "Capture Source",
582 .info
= input_sel_info
,
583 .get
= input_sel_get
,
584 .put
= input_sel_put
,
587 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
588 .name
= "ADC High-pass Filter Capture Enum",
595 static int dg_control_filter(struct snd_kcontrol_new
*template)
597 if (!strncmp(template->name
, "Master Playback ", 16))
602 static int dg_mixer_init(struct oxygen
*chip
)
607 for (i
= 0; i
< ARRAY_SIZE(dg_controls
); ++i
) {
608 err
= snd_ctl_add(chip
->card
,
609 snd_ctl_new1(&dg_controls
[i
], chip
));
616 static void dump_cs4245_registers(struct oxygen
*chip
,
617 struct snd_info_buffer
*buffer
)
619 struct dg
*data
= chip
->model_data
;
622 snd_iprintf(buffer
, "\nCS4245:");
623 for (i
= 1; i
<= 0x10; ++i
)
624 snd_iprintf(buffer
, " %02x", data
->cs4245_shadow
[i
]);
625 snd_iprintf(buffer
, "\n");
628 struct oxygen_model model_xonar_dg
= {
629 .longname
= "C-Media Oxygen HD Audio",
632 .control_filter
= dg_control_filter
,
633 .mixer_init
= dg_mixer_init
,
634 .cleanup
= dg_cleanup
,
635 .suspend
= dg_suspend
,
637 .set_dac_params
= set_cs4245_dac_params
,
638 .set_adc_params
= set_cs4245_adc_params
,
639 .adjust_dac_routing
= adjust_dg_dac_routing
,
640 .dump_registers
= dump_cs4245_registers
,
641 .model_data_size
= sizeof(struct dg
),
642 .device_config
= PLAYBACK_0_TO_I2S
|
643 PLAYBACK_1_TO_SPDIF
|
644 CAPTURE_0_FROM_I2S_2
|
645 CAPTURE_1_FROM_SPDIF
,
646 .dac_channels_pcm
= 6,
647 .dac_channels_mixer
= 0,
648 .function_flags
= OXYGEN_FUNCTION_SPI
,
649 .dac_mclks
= OXYGEN_MCLKS(256, 128, 128),
650 .adc_mclks
= OXYGEN_MCLKS(256, 128, 128),
651 .dac_i2s_format
= OXYGEN_I2S_FORMAT_LJUST
,
652 .adc_i2s_format
= OXYGEN_I2S_FORMAT_LJUST
,