[ALSA] fix multi-channel for model==full
[linux-2.6.git] / sound / pci / hda / patch_cmedia.c
1 /*
2  * Universal Interface for Intel High Definition Audio Codec
3  *
4  * HD audio interface patch for C-Media CMI9880
5  *
6  * Copyright (c) 2004 Takashi Iwai <tiwai@suse.de>
7  *
8  *
9  *  This driver is free software; you can redistribute it and/or modify
10  *  it under the terms of the GNU General Public License as published by
11  *  the Free Software Foundation; either version 2 of the License, or
12  *  (at your option) any later version.
13  *
14  *  This driver is distributed in the hope that it will be useful,
15  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  *  GNU General Public License for more details.
18  *
19  *  You should have received a copy of the GNU General Public License
20  *  along with this program; if not, write to the Free Software
21  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
22  */
23
24 #include <sound/driver.h>
25 #include <linux/init.h>
26 #include <linux/delay.h>
27 #include <linux/slab.h>
28 #include <linux/pci.h>
29 #include <sound/core.h>
30 #include "hda_codec.h"
31 #include "hda_local.h"
32
33
34 /* board config type */
35 enum {
36         CMI_MINIMAL,    /* back 3-jack */
37         CMI_MIN_FP,     /* back 3-jack + front-panel 2-jack */
38         CMI_FULL,       /* back 6-jack + front-panel 2-jack */
39         CMI_FULL_DIG,   /* back 6-jack + front-panel 2-jack + digital I/O */
40         CMI_ALLOUT,     /* back 5-jack + front-panel 2-jack + digital out */
41 };
42
43 struct cmi_spec {
44         int board_config;
45         unsigned int surr_switch: 1;    /* switchable line,mic */
46         unsigned int no_line_in: 1;     /* no line-in (5-jack) */
47         unsigned int front_panel: 1;    /* has front-panel 2-jack */
48
49         /* playback */
50         struct hda_multi_out multiout;
51
52         /* capture */
53         hda_nid_t *adc_nids;
54         hda_nid_t dig_in_nid;
55
56         /* capture source */
57         const struct hda_input_mux *input_mux;
58         unsigned int cur_mux[2];
59
60         /* channel mode */
61         unsigned int num_ch_modes;
62         unsigned int cur_ch_mode;
63         const struct cmi_channel_mode *channel_modes;
64
65         struct hda_pcm pcm_rec[2];      /* PCM information */
66 };
67
68 /*
69  * input MUX
70  */
71 static int cmi_mux_enum_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
72 {
73         struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
74         struct cmi_spec *spec = codec->spec;
75         return snd_hda_input_mux_info(spec->input_mux, uinfo);
76 }
77
78 static int cmi_mux_enum_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
79 {
80         struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
81         struct cmi_spec *spec = codec->spec;
82         unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
83
84         ucontrol->value.enumerated.item[0] = spec->cur_mux[adc_idx];
85         return 0;
86 }
87
88 static int cmi_mux_enum_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
89 {
90         struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
91         struct cmi_spec *spec = codec->spec;
92         unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
93
94         return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol,
95                                      spec->adc_nids[adc_idx], &spec->cur_mux[adc_idx]);
96 }
97
98 /*
99  * shared line-in, mic for surrounds
100  */
101
102 /* 3-stack / 2 channel */
103 static struct hda_verb cmi9880_ch2_init[] = {
104         /* set line-in PIN for input */
105         { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
106         /* set mic PIN for input, also enable vref */
107         { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
108         /* route front PCM (DAC1) to HP */
109         { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 },
110         {}
111 };
112
113 /* 3-stack / 6 channel */
114 static struct hda_verb cmi9880_ch6_init[] = {
115         /* set line-in PIN for output */
116         { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
117         /* set mic PIN for output */
118         { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
119         /* route front PCM (DAC1) to HP */
120         { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 },
121         {}
122 };
123
124 /* 3-stack+front / 8 channel */
125 static struct hda_verb cmi9880_ch8_init[] = {
126         /* set line-in PIN for output */
127         { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
128         /* set mic PIN for output */
129         { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
130         /* route rear-surround PCM (DAC4) to HP */
131         { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x03 },
132         {}
133 };
134
135 struct cmi_channel_mode {
136         unsigned int channels;
137         const struct hda_verb *sequence;
138 };
139
140 static struct cmi_channel_mode cmi9880_channel_modes[3] = {
141         { 2, cmi9880_ch2_init },
142         { 6, cmi9880_ch6_init },
143         { 8, cmi9880_ch8_init },
144 };
145
146 static int cmi_ch_mode_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
147 {
148         struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
149         struct cmi_spec *spec = codec->spec;
150
151         snd_assert(spec->channel_modes, return -EINVAL);
152         uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
153         uinfo->count = 1;
154         uinfo->value.enumerated.items = spec->num_ch_modes;
155         if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
156                 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
157         sprintf(uinfo->value.enumerated.name, "%dch",
158                 spec->channel_modes[uinfo->value.enumerated.item].channels);
159         return 0;
160 }
161
162 static int cmi_ch_mode_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
163 {
164         struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
165         struct cmi_spec *spec = codec->spec;
166
167         ucontrol->value.enumerated.item[0] = spec->cur_ch_mode;
168         return 0;
169 }
170
171 static int cmi_ch_mode_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
172 {
173         struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
174         struct cmi_spec *spec = codec->spec;
175
176         snd_assert(spec->channel_modes, return -EINVAL);
177         if (ucontrol->value.enumerated.item[0] >= spec->num_ch_modes)
178                 ucontrol->value.enumerated.item[0] = spec->num_ch_modes;
179         if (ucontrol->value.enumerated.item[0] == spec->cur_ch_mode &&
180             ! codec->in_resume)
181                 return 0;
182
183         spec->cur_ch_mode = ucontrol->value.enumerated.item[0];
184         snd_hda_sequence_write(codec, spec->channel_modes[spec->cur_ch_mode].sequence);
185         spec->multiout.max_channels = spec->channel_modes[spec->cur_ch_mode].channels;
186         return 1;
187 }
188
189 /*
190  */
191 static snd_kcontrol_new_t cmi9880_basic_mixer[] = {
192         /* CMI9880 has no playback volumes! */
193         HDA_CODEC_MUTE("PCM Playback Switch", 0x03, 0x0, HDA_OUTPUT), /* front */
194         HDA_CODEC_MUTE("Surround Playback Switch", 0x04, 0x0, HDA_OUTPUT),
195         HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x05, 1, 0x0, HDA_OUTPUT),
196         HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x05, 2, 0x0, HDA_OUTPUT),
197         HDA_CODEC_MUTE("Side Playback Switch", 0x06, 0x0, HDA_OUTPUT),
198         {
199                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
200                 /* The multiple "Capture Source" controls confuse alsamixer
201                  * So call somewhat different..
202                  * FIXME: the controls appear in the "playback" view!
203                  */
204                 /* .name = "Capture Source", */
205                 .name = "Input Source",
206                 .count = 2,
207                 .info = cmi_mux_enum_info,
208                 .get = cmi_mux_enum_get,
209                 .put = cmi_mux_enum_put,
210         },
211         HDA_CODEC_VOLUME("Capture Volume", 0x08, 0, HDA_INPUT),
212         HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0, HDA_INPUT),
213         HDA_CODEC_MUTE("Capture Switch", 0x08, 0, HDA_INPUT),
214         HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0, HDA_INPUT),
215         HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x23, 0, HDA_OUTPUT),
216         HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x23, 0, HDA_OUTPUT),
217         { } /* end */
218 };
219
220 /*
221  * shared I/O pins
222  */
223 static snd_kcontrol_new_t cmi9880_ch_mode_mixer[] = {
224         {
225                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
226                 .name = "Channel Mode",
227                 .info = cmi_ch_mode_info,
228                 .get = cmi_ch_mode_get,
229                 .put = cmi_ch_mode_put,
230         },
231         { } /* end */
232 };
233
234 /* AUD-in selections:
235  * 0x0b 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x1f 0x20
236  */
237 static struct hda_input_mux cmi9880_basic_mux = {
238         .num_items = 4,
239         .items = {
240                 { "Front Mic", 0x5 },
241                 { "Rear Mic", 0x2 },
242                 { "Line", 0x1 },
243                 { "CD", 0x7 },
244         }
245 };
246
247 static struct hda_input_mux cmi9880_no_line_mux = {
248         .num_items = 3,
249         .items = {
250                 { "Front Mic", 0x5 },
251                 { "Rear Mic", 0x2 },
252                 { "CD", 0x7 },
253         }
254 };
255
256 /* front, rear, clfe, rear_surr */
257 static hda_nid_t cmi9880_dac_nids[4] = {
258         0x03, 0x04, 0x05, 0x06
259 };
260 /* ADC0, ADC1 */
261 static hda_nid_t cmi9880_adc_nids[2] = {
262         0x08, 0x09
263 };
264
265 #define CMI_DIG_OUT_NID 0x07
266 #define CMI_DIG_IN_NID  0x0a
267
268 /*
269  */
270 static struct hda_verb cmi9880_basic_init[] = {
271         /* port-D for line out (rear panel) */
272         { 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
273         /* port-E for HP out (front panel) */
274         { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
275         /* route front PCM to HP */
276         { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 },
277         /* port-A for surround (rear panel) */
278         { 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
279         /* port-G for CLFE (rear panel) */
280         { 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
281         { 0x1f, AC_VERB_SET_CONNECT_SEL, 0x02 },
282         /* port-H for side (rear panel) */
283         { 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
284         { 0x20, AC_VERB_SET_CONNECT_SEL, 0x01 },
285         /* port-C for line-in (rear panel) */
286         { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
287         /* port-B for mic-in (rear panel) with vref */
288         { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
289         /* port-F for mic-in (front panel) with vref */
290         { 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
291         /* CD-in */
292         { 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
293         /* route front mic to ADC1/2 */
294         { 0x08, AC_VERB_SET_CONNECT_SEL, 0x05 },
295         { 0x09, AC_VERB_SET_CONNECT_SEL, 0x05 },
296         {} /* terminator */
297 };
298
299 static struct hda_verb cmi9880_allout_init[] = {
300         /* port-D for line out (rear panel) */
301         { 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
302         /* port-E for HP out (front panel) */
303         { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
304         /* route front PCM to HP */
305         { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 },
306         /* port-A for side (rear panel) */
307         { 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
308         /* port-G for CLFE (rear panel) */
309         { 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
310         { 0x1f, AC_VERB_SET_CONNECT_SEL, 0x02 },
311         /* port-H for side (rear panel) */
312         { 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
313         { 0x20, AC_VERB_SET_CONNECT_SEL, 0x01 },
314         /* port-C for surround (rear panel) */
315         { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
316         /* port-B for mic-in (rear panel) with vref */
317         { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
318         /* port-F for mic-in (front panel) with vref */
319         { 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
320         /* CD-in */
321         { 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
322         /* route front mic to ADC1/2 */
323         { 0x08, AC_VERB_SET_CONNECT_SEL, 0x05 },
324         { 0x09, AC_VERB_SET_CONNECT_SEL, 0x05 },
325         {} /* terminator */
326 };
327
328 /*
329  */
330 static int cmi9880_build_controls(struct hda_codec *codec)
331 {
332         struct cmi_spec *spec = codec->spec;
333         int err;
334
335         err = snd_hda_add_new_ctls(codec, cmi9880_basic_mixer);
336         if (err < 0)
337                 return err;
338         if (spec->surr_switch) {
339                 err = snd_hda_add_new_ctls(codec, cmi9880_ch_mode_mixer);
340                 if (err < 0)
341                         return err;
342         }
343         if (spec->multiout.dig_out_nid) {
344                 err = snd_hda_create_spdif_out_ctls(codec, spec->multiout.dig_out_nid);
345                 if (err < 0)
346                         return err;
347         }
348         if (spec->dig_in_nid) {
349                 err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
350                 if (err < 0)
351                         return err;
352         }
353         return 0;
354 }
355
356 static int cmi9880_init(struct hda_codec *codec)
357 {
358         struct cmi_spec *spec = codec->spec;
359         if (spec->board_config == CMI_ALLOUT)
360                 snd_hda_sequence_write(codec, cmi9880_allout_init);
361         else
362                 snd_hda_sequence_write(codec, cmi9880_basic_init);
363         return 0;
364 }
365
366 #ifdef CONFIG_PM
367 /*
368  * resume
369  */
370 static int cmi9880_resume(struct hda_codec *codec)
371 {
372         struct cmi_spec *spec = codec->spec;
373
374         cmi9880_init(codec);
375         snd_hda_resume_ctls(codec, cmi9880_basic_mixer);
376         if (spec->surr_switch)
377                 snd_hda_resume_ctls(codec, cmi9880_ch_mode_mixer);
378         if (spec->multiout.dig_out_nid)
379                 snd_hda_resume_spdif_out(codec);
380         if (spec->dig_in_nid)
381                 snd_hda_resume_spdif_in(codec);
382
383         return 0;
384 }
385 #endif
386
387 /*
388  * Analog playback callbacks
389  */
390 static int cmi9880_playback_pcm_open(struct hda_pcm_stream *hinfo,
391                                      struct hda_codec *codec,
392                                      snd_pcm_substream_t *substream)
393 {
394         struct cmi_spec *spec = codec->spec;
395         return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream);
396 }
397
398 static int cmi9880_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
399                                         struct hda_codec *codec,
400                                         unsigned int stream_tag,
401                                         unsigned int format,
402                                         snd_pcm_substream_t *substream)
403 {
404         struct cmi_spec *spec = codec->spec;
405         return snd_hda_multi_out_analog_prepare(codec, &spec->multiout, stream_tag,
406                                                 format, substream);
407 }
408
409 static int cmi9880_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
410                                        struct hda_codec *codec,
411                                        snd_pcm_substream_t *substream)
412 {
413         struct cmi_spec *spec = codec->spec;
414         return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
415 }
416
417 /*
418  * Digital out
419  */
420 static int cmi9880_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
421                                          struct hda_codec *codec,
422                                          snd_pcm_substream_t *substream)
423 {
424         struct cmi_spec *spec = codec->spec;
425         return snd_hda_multi_out_dig_open(codec, &spec->multiout);
426 }
427
428 static int cmi9880_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
429                                           struct hda_codec *codec,
430                                           snd_pcm_substream_t *substream)
431 {
432         struct cmi_spec *spec = codec->spec;
433         return snd_hda_multi_out_dig_close(codec, &spec->multiout);
434 }
435
436 /*
437  * Analog capture
438  */
439 static int cmi9880_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
440                                       struct hda_codec *codec,
441                                       unsigned int stream_tag,
442                                       unsigned int format,
443                                       snd_pcm_substream_t *substream)
444 {
445         struct cmi_spec *spec = codec->spec;
446
447         snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number],
448                                    stream_tag, 0, format);
449         return 0;
450 }
451
452 static int cmi9880_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
453                                       struct hda_codec *codec,
454                                       snd_pcm_substream_t *substream)
455 {
456         struct cmi_spec *spec = codec->spec;
457
458         snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number], 0, 0, 0);
459         return 0;
460 }
461
462
463 /*
464  */
465 static struct hda_pcm_stream cmi9880_pcm_analog_playback = {
466         .substreams = 1,
467         .channels_min = 2,
468         .channels_max = 8,
469         .nid = 0x03, /* NID to query formats and rates */
470         .ops = {
471                 .open = cmi9880_playback_pcm_open,
472                 .prepare = cmi9880_playback_pcm_prepare,
473                 .cleanup = cmi9880_playback_pcm_cleanup
474         },
475 };
476
477 static struct hda_pcm_stream cmi9880_pcm_analog_capture = {
478         .substreams = 2,
479         .channels_min = 2,
480         .channels_max = 2,
481         .nid = 0x08, /* NID to query formats and rates */
482         .ops = {
483                 .prepare = cmi9880_capture_pcm_prepare,
484                 .cleanup = cmi9880_capture_pcm_cleanup
485         },
486 };
487
488 static struct hda_pcm_stream cmi9880_pcm_digital_playback = {
489         .substreams = 1,
490         .channels_min = 2,
491         .channels_max = 2,
492         /* NID is set in cmi9880_build_pcms */
493         .ops = {
494                 .open = cmi9880_dig_playback_pcm_open,
495                 .close = cmi9880_dig_playback_pcm_close
496         },
497 };
498
499 static struct hda_pcm_stream cmi9880_pcm_digital_capture = {
500         .substreams = 1,
501         .channels_min = 2,
502         .channels_max = 2,
503         /* NID is set in cmi9880_build_pcms */
504 };
505
506 static int cmi9880_build_pcms(struct hda_codec *codec)
507 {
508         struct cmi_spec *spec = codec->spec;
509         struct hda_pcm *info = spec->pcm_rec;
510
511         codec->num_pcms = 1;
512         codec->pcm_info = info;
513
514         info->name = "CMI9880";
515         info->stream[SNDRV_PCM_STREAM_PLAYBACK] = cmi9880_pcm_analog_playback;
516         info->stream[SNDRV_PCM_STREAM_CAPTURE] = cmi9880_pcm_analog_capture;
517
518         if (spec->multiout.dig_out_nid || spec->dig_in_nid) {
519                 codec->num_pcms++;
520                 info++;
521                 info->name = "CMI9880 Digital";
522                 if (spec->multiout.dig_out_nid) {
523                         info->stream[SNDRV_PCM_STREAM_PLAYBACK] = cmi9880_pcm_digital_playback;
524                         info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid;
525                 }
526                 if (spec->dig_in_nid) {
527                         info->stream[SNDRV_PCM_STREAM_CAPTURE] = cmi9880_pcm_digital_capture;
528                         info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->dig_in_nid;
529                 }
530         }
531
532         return 0;
533 }
534
535 static void cmi9880_free(struct hda_codec *codec)
536 {
537         kfree(codec->spec);
538 }
539
540 /*
541  */
542
543 static struct hda_board_config cmi9880_cfg_tbl[] = {
544         { .modelname = "minimal", .config = CMI_MINIMAL },
545         { .modelname = "min_fp", .config = CMI_MIN_FP },
546         { .modelname = "full", .config = CMI_FULL },
547         { .modelname = "full_dig", .config = CMI_FULL_DIG },
548         { .modelname = "allout", .config = CMI_ALLOUT },
549         {} /* terminator */
550 };
551
552 static struct hda_codec_ops cmi9880_patch_ops = {
553         .build_controls = cmi9880_build_controls,
554         .build_pcms = cmi9880_build_pcms,
555         .init = cmi9880_init,
556         .free = cmi9880_free,
557 #ifdef CONFIG_PM
558         .resume = cmi9880_resume,
559 #endif
560 };
561
562 static int patch_cmi9880(struct hda_codec *codec)
563 {
564         struct cmi_spec *spec;
565
566         spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
567         if (spec == NULL)
568                 return -ENOMEM;
569
570         codec->spec = spec;
571         spec->board_config = snd_hda_check_board_config(codec, cmi9880_cfg_tbl);
572         if (spec->board_config < 0) {
573                 snd_printd(KERN_INFO "hda_codec: Unknown model for CMI9880\n");
574                 spec->board_config = CMI_FULL_DIG; /* try everything */
575         }
576
577         switch (spec->board_config) {
578         case CMI_MINIMAL:
579         case CMI_MIN_FP:
580                 spec->surr_switch = 1;
581                 if (spec->board_config == CMI_MINIMAL)
582                         spec->num_ch_modes = 2;
583                 else {
584                         spec->front_panel = 1;
585                         spec->num_ch_modes = 3;
586                 }
587                 spec->channel_modes = cmi9880_channel_modes;
588                 spec->multiout.max_channels = cmi9880_channel_modes[0].channels;
589                 spec->input_mux = &cmi9880_basic_mux;
590                 break;
591         case CMI_FULL:
592         case CMI_FULL_DIG:
593                 spec->front_panel = 1;
594                 spec->multiout.max_channels = 8;
595                 spec->input_mux = &cmi9880_basic_mux;
596                 if (spec->board_config == CMI_FULL_DIG) {
597                         spec->multiout.dig_out_nid = CMI_DIG_OUT_NID;
598                         spec->dig_in_nid = CMI_DIG_IN_NID;
599                 }
600                 break;
601         case CMI_ALLOUT:
602                 spec->front_panel = 1;
603                 spec->multiout.max_channels = 8;
604                 spec->no_line_in = 1;
605                 spec->input_mux = &cmi9880_no_line_mux;
606                 spec->multiout.dig_out_nid = CMI_DIG_OUT_NID;
607                 break;
608         }
609
610         spec->multiout.num_dacs = 4;
611         spec->multiout.dac_nids = cmi9880_dac_nids;
612
613         spec->adc_nids = cmi9880_adc_nids;
614
615         codec->patch_ops = cmi9880_patch_ops;
616
617         return 0;
618 }
619
620 /*
621  * patch entries
622  */
623 struct hda_codec_preset snd_hda_preset_cmedia[] = {
624         { .id = 0x13f69880, .name = "CMI9880", .patch = patch_cmi9880 },
625         { .id = 0x434d4980, .name = "CMI9880", .patch = patch_cmi9880 },
626         {} /* terminator */
627 };