2 * Universal Interface for Intel High Definition Audio Codec
4 * HD audio interface patch for SigmaTel STAC92xx
6 * Copyright (c) 2005 Embedded Alley Solutions, Inc.
7 * Matt Porter <mporter@embeddedalley.com>
9 * Based on patch_cmedia.c and patch_realtek.c
10 * Copyright (c) 2004 Takashi Iwai <tiwai@suse.de>
12 * This driver is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
17 * This driver is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 #include <sound/driver.h>
28 #include <linux/init.h>
29 #include <linux/delay.h>
30 #include <linux/slab.h>
31 #include <linux/pci.h>
32 #include <sound/core.h>
33 #include <sound/asoundef.h>
34 #include "hda_codec.h"
35 #include "hda_local.h"
37 #define NUM_CONTROL_ALLOC 32
38 #define STAC_HP_EVENT 0x37
39 #define STAC_UNSOL_ENABLE (AC_USRSP_EN | STAC_HP_EVENT)
42 #define STAC_D945GTP3 1
43 #define STAC_D945GTP5 2
45 struct sigmatel_spec
{
46 struct snd_kcontrol_new
*mixers
[4];
47 unsigned int num_mixers
;
50 unsigned int surr_switch
: 1;
51 unsigned int line_switch
: 1;
52 unsigned int mic_switch
: 1;
53 unsigned int alt_switch
: 1;
54 unsigned int hp_detect
: 1;
57 struct hda_multi_out multiout
;
58 hda_nid_t dac_nids
[5];
62 unsigned int num_adcs
;
64 unsigned int num_muxes
;
69 unsigned int num_pins
;
70 unsigned int *pin_configs
;
72 /* codec specific stuff */
73 struct hda_verb
*init
;
74 struct snd_kcontrol_new
*mixer
;
77 struct hda_input_mux
*input_mux
;
78 unsigned int cur_mux
[3];
81 unsigned int io_switch
[2];
83 struct hda_pcm pcm_rec
[2]; /* PCM information */
85 /* dynamic controls and input_mux */
86 struct auto_pin_cfg autocfg
;
87 unsigned int num_kctl_alloc
, num_kctl_used
;
88 struct snd_kcontrol_new
*kctl_alloc
;
89 struct hda_input_mux private_imux
;
92 static hda_nid_t stac9200_adc_nids
[1] = {
96 static hda_nid_t stac9200_mux_nids
[1] = {
100 static hda_nid_t stac9200_dac_nids
[1] = {
104 static hda_nid_t stac922x_adc_nids
[2] = {
108 static hda_nid_t stac922x_mux_nids
[2] = {
112 static hda_nid_t stac927x_adc_nids
[3] = {
116 static hda_nid_t stac927x_mux_nids
[3] = {
120 static hda_nid_t stac9200_pin_nids
[8] = {
121 0x08, 0x09, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12,
124 static hda_nid_t stac922x_pin_nids
[10] = {
125 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
126 0x0f, 0x10, 0x11, 0x15, 0x1b,
129 static hda_nid_t stac927x_pin_nids
[14] = {
130 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
131 0x0f, 0x10, 0x11, 0x12, 0x13,
132 0x14, 0x21, 0x22, 0x23,
135 static int stac92xx_mux_enum_info(struct snd_kcontrol
*kcontrol
, struct snd_ctl_elem_info
*uinfo
)
137 struct hda_codec
*codec
= snd_kcontrol_chip(kcontrol
);
138 struct sigmatel_spec
*spec
= codec
->spec
;
139 return snd_hda_input_mux_info(spec
->input_mux
, uinfo
);
142 static int stac92xx_mux_enum_get(struct snd_kcontrol
*kcontrol
, struct snd_ctl_elem_value
*ucontrol
)
144 struct hda_codec
*codec
= snd_kcontrol_chip(kcontrol
);
145 struct sigmatel_spec
*spec
= codec
->spec
;
146 unsigned int adc_idx
= snd_ctl_get_ioffidx(kcontrol
, &ucontrol
->id
);
148 ucontrol
->value
.enumerated
.item
[0] = spec
->cur_mux
[adc_idx
];
152 static int stac92xx_mux_enum_put(struct snd_kcontrol
*kcontrol
, struct snd_ctl_elem_value
*ucontrol
)
154 struct hda_codec
*codec
= snd_kcontrol_chip(kcontrol
);
155 struct sigmatel_spec
*spec
= codec
->spec
;
156 unsigned int adc_idx
= snd_ctl_get_ioffidx(kcontrol
, &ucontrol
->id
);
158 return snd_hda_input_mux_put(codec
, spec
->input_mux
, ucontrol
,
159 spec
->mux_nids
[adc_idx
], &spec
->cur_mux
[adc_idx
]);
162 static struct hda_verb stac9200_core_init
[] = {
163 /* set dac0mux for dac converter */
164 { 0x07, AC_VERB_SET_CONNECT_SEL
, 0x00},
168 static struct hda_verb stac922x_core_init
[] = {
169 /* set master volume and direct control */
170 { 0x16, AC_VERB_SET_VOLUME_KNOB_CONTROL
, 0xff},
174 static struct hda_verb stac927x_core_init
[] = {
175 /* set master volume and direct control */
176 { 0x24, AC_VERB_SET_VOLUME_KNOB_CONTROL
, 0xff},
180 static struct snd_kcontrol_new stac9200_mixer
[] = {
181 HDA_CODEC_VOLUME("Master Playback Volume", 0xb, 0, HDA_OUTPUT
),
182 HDA_CODEC_MUTE("Master Playback Switch", 0xb, 0, HDA_OUTPUT
),
184 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
185 .name
= "Input Source",
187 .info
= stac92xx_mux_enum_info
,
188 .get
= stac92xx_mux_enum_get
,
189 .put
= stac92xx_mux_enum_put
,
191 HDA_CODEC_VOLUME("Capture Volume", 0x0a, 0, HDA_OUTPUT
),
192 HDA_CODEC_MUTE("Capture Switch", 0x0a, 0, HDA_OUTPUT
),
193 HDA_CODEC_VOLUME("Capture Mux Volume", 0x0c, 0, HDA_OUTPUT
),
197 /* This needs to be generated dynamically based on sequence */
198 static struct snd_kcontrol_new stac922x_mixer
[] = {
200 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
201 .name
= "Input Source",
203 .info
= stac92xx_mux_enum_info
,
204 .get
= stac92xx_mux_enum_get
,
205 .put
= stac92xx_mux_enum_put
,
207 HDA_CODEC_VOLUME("Capture Volume", 0x17, 0x0, HDA_INPUT
),
208 HDA_CODEC_MUTE("Capture Switch", 0x17, 0x0, HDA_INPUT
),
209 HDA_CODEC_VOLUME("Mux Capture Volume", 0x12, 0x0, HDA_OUTPUT
),
213 static snd_kcontrol_new_t stac927x_mixer
[] = {
215 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
216 .name
= "Input Source",
218 .info
= stac92xx_mux_enum_info
,
219 .get
= stac92xx_mux_enum_get
,
220 .put
= stac92xx_mux_enum_put
,
222 HDA_CODEC_VOLUME("InMux Capture Volume", 0x15, 0x0, HDA_OUTPUT
),
223 HDA_CODEC_VOLUME("InVol Capture Volume", 0x18, 0x0, HDA_INPUT
),
224 HDA_CODEC_MUTE("ADCMux Capture Switch", 0x1b, 0x0, HDA_OUTPUT
),
228 static int stac92xx_build_controls(struct hda_codec
*codec
)
230 struct sigmatel_spec
*spec
= codec
->spec
;
234 err
= snd_hda_add_new_ctls(codec
, spec
->mixer
);
238 for (i
= 0; i
< spec
->num_mixers
; i
++) {
239 err
= snd_hda_add_new_ctls(codec
, spec
->mixers
[i
]);
244 if (spec
->multiout
.dig_out_nid
) {
245 err
= snd_hda_create_spdif_out_ctls(codec
, spec
->multiout
.dig_out_nid
);
249 if (spec
->dig_in_nid
) {
250 err
= snd_hda_create_spdif_in_ctls(codec
, spec
->dig_in_nid
);
257 static unsigned int ref9200_pin_configs
[8] = {
258 0x01c47010, 0x01447010, 0x0221401f, 0x01114010,
259 0x02a19020, 0x01a19021, 0x90100140, 0x01813122,
262 static unsigned int *stac9200_brd_tbl
[] = {
266 static struct hda_board_config stac9200_cfg_tbl
[] = {
267 { .modelname
= "ref",
268 .pci_subvendor
= PCI_VENDOR_ID_INTEL
,
269 .pci_subdevice
= 0x2668, /* DFI LanParty */
270 .config
= STAC_REF
},
274 static unsigned int ref922x_pin_configs
[10] = {
275 0x01014010, 0x01016011, 0x01012012, 0x0221401f,
276 0x01813122, 0x01011014, 0x01441030, 0x01c41030,
277 0x40000100, 0x40000100,
280 static unsigned int d945gtp3_pin_configs
[10] = {
281 0x0221401f, 0x01a19022, 0x01813021, 0x01014010,
282 0x40000100, 0x40000100, 0x40000100, 0x40000100,
283 0x02a19120, 0x40000100,
286 static unsigned int d945gtp5_pin_configs
[10] = {
287 0x0221401f, 0x01011012, 0x01813024, 0x01014010,
288 0x01a19021, 0x01016011, 0x01452130, 0x40000100,
289 0x02a19320, 0x40000100,
292 static unsigned int *stac922x_brd_tbl
[] = {
294 d945gtp3_pin_configs
,
295 d945gtp5_pin_configs
,
298 static struct hda_board_config stac922x_cfg_tbl
[] = {
299 { .modelname
= "ref",
300 .pci_subvendor
= PCI_VENDOR_ID_INTEL
,
301 .pci_subdevice
= 0x2668, /* DFI LanParty */
302 .config
= STAC_REF
}, /* SigmaTel reference board */
303 { .pci_subvendor
= PCI_VENDOR_ID_INTEL
,
304 .pci_subdevice
= 0x0101,
305 .config
= STAC_D945GTP3
}, /* Intel D945GTP - 3 Stack */
306 { .pci_subvendor
= PCI_VENDOR_ID_INTEL
,
307 .pci_subdevice
= 0x0202,
308 .config
= STAC_D945GTP3
}, /* Intel D945GNT - 3 Stack, 9221 A1 */
309 { .pci_subvendor
= PCI_VENDOR_ID_INTEL
,
310 .pci_subdevice
= 0x0b0b,
311 .config
= STAC_D945GTP3
}, /* Intel D945PSN - 3 Stack, 9221 A1 */
312 { .pci_subvendor
= PCI_VENDOR_ID_INTEL
,
313 .pci_subdevice
= 0x0404,
314 .config
= STAC_D945GTP5
}, /* Intel D945GTP - 5 Stack */
315 { .pci_subvendor
= PCI_VENDOR_ID_INTEL
,
316 .pci_subdevice
= 0x0303,
317 .config
= STAC_D945GTP5
}, /* Intel D945GNT - 5 Stack */
318 { .pci_subvendor
= PCI_VENDOR_ID_INTEL
,
319 .pci_subdevice
= 0x0013,
320 .config
= STAC_D945GTP5
}, /* Intel D955XBK - 5 Stack */
321 { .pci_subvendor
= PCI_VENDOR_ID_INTEL
,
322 .pci_subdevice
= 0x0417,
323 .config
= STAC_D945GTP5
}, /* Intel D975XBK - 5 Stack */
327 static unsigned int ref927x_pin_configs
[14] = {
328 0x01813122, 0x01a19021, 0x01014010, 0x01016011,
329 0x01012012, 0x01011014, 0x40000100, 0x40000100,
330 0x40000100, 0x40000100, 0x40000100, 0x01441030,
331 0x01c41030, 0x40000100,
334 static unsigned int *stac927x_brd_tbl
[] = {
338 static struct hda_board_config stac927x_cfg_tbl
[] = {
339 { .modelname
= "ref",
340 .pci_subvendor
= PCI_VENDOR_ID_INTEL
,
341 .pci_subdevice
= 0x2668, /* DFI LanParty */
342 .config
= STAC_REF
}, /* SigmaTel reference board */
346 static void stac92xx_set_config_regs(struct hda_codec
*codec
)
349 struct sigmatel_spec
*spec
= codec
->spec
;
350 unsigned int pin_cfg
;
352 for (i
=0; i
< spec
->num_pins
; i
++) {
353 snd_hda_codec_write(codec
, spec
->pin_nids
[i
], 0,
354 AC_VERB_SET_CONFIG_DEFAULT_BYTES_0
,
355 spec
->pin_configs
[i
] & 0x000000ff);
356 snd_hda_codec_write(codec
, spec
->pin_nids
[i
], 0,
357 AC_VERB_SET_CONFIG_DEFAULT_BYTES_1
,
358 (spec
->pin_configs
[i
] & 0x0000ff00) >> 8);
359 snd_hda_codec_write(codec
, spec
->pin_nids
[i
], 0,
360 AC_VERB_SET_CONFIG_DEFAULT_BYTES_2
,
361 (spec
->pin_configs
[i
] & 0x00ff0000) >> 16);
362 snd_hda_codec_write(codec
, spec
->pin_nids
[i
], 0,
363 AC_VERB_SET_CONFIG_DEFAULT_BYTES_3
,
364 spec
->pin_configs
[i
] >> 24);
365 pin_cfg
= snd_hda_codec_read(codec
, spec
->pin_nids
[i
], 0,
366 AC_VERB_GET_CONFIG_DEFAULT
,
368 snd_printdd(KERN_INFO
"hda_codec: pin nid %2.2x pin config %8.8x\n", spec
->pin_nids
[i
], pin_cfg
);
373 * Analog playback callbacks
375 static int stac92xx_playback_pcm_open(struct hda_pcm_stream
*hinfo
,
376 struct hda_codec
*codec
,
377 struct snd_pcm_substream
*substream
)
379 struct sigmatel_spec
*spec
= codec
->spec
;
380 return snd_hda_multi_out_analog_open(codec
, &spec
->multiout
, substream
);
383 static int stac92xx_playback_pcm_prepare(struct hda_pcm_stream
*hinfo
,
384 struct hda_codec
*codec
,
385 unsigned int stream_tag
,
387 struct snd_pcm_substream
*substream
)
389 struct sigmatel_spec
*spec
= codec
->spec
;
390 return snd_hda_multi_out_analog_prepare(codec
, &spec
->multiout
, stream_tag
, format
, substream
);
393 static int stac92xx_playback_pcm_cleanup(struct hda_pcm_stream
*hinfo
,
394 struct hda_codec
*codec
,
395 struct snd_pcm_substream
*substream
)
397 struct sigmatel_spec
*spec
= codec
->spec
;
398 return snd_hda_multi_out_analog_cleanup(codec
, &spec
->multiout
);
402 * Digital playback callbacks
404 static int stac92xx_dig_playback_pcm_open(struct hda_pcm_stream
*hinfo
,
405 struct hda_codec
*codec
,
406 struct snd_pcm_substream
*substream
)
408 struct sigmatel_spec
*spec
= codec
->spec
;
409 return snd_hda_multi_out_dig_open(codec
, &spec
->multiout
);
412 static int stac92xx_dig_playback_pcm_close(struct hda_pcm_stream
*hinfo
,
413 struct hda_codec
*codec
,
414 struct snd_pcm_substream
*substream
)
416 struct sigmatel_spec
*spec
= codec
->spec
;
417 return snd_hda_multi_out_dig_close(codec
, &spec
->multiout
);
422 * Analog capture callbacks
424 static int stac92xx_capture_pcm_prepare(struct hda_pcm_stream
*hinfo
,
425 struct hda_codec
*codec
,
426 unsigned int stream_tag
,
428 struct snd_pcm_substream
*substream
)
430 struct sigmatel_spec
*spec
= codec
->spec
;
432 snd_hda_codec_setup_stream(codec
, spec
->adc_nids
[substream
->number
],
433 stream_tag
, 0, format
);
437 static int stac92xx_capture_pcm_cleanup(struct hda_pcm_stream
*hinfo
,
438 struct hda_codec
*codec
,
439 struct snd_pcm_substream
*substream
)
441 struct sigmatel_spec
*spec
= codec
->spec
;
443 snd_hda_codec_setup_stream(codec
, spec
->adc_nids
[substream
->number
], 0, 0, 0);
447 static struct hda_pcm_stream stac92xx_pcm_digital_playback
= {
451 /* NID is set in stac92xx_build_pcms */
453 .open
= stac92xx_dig_playback_pcm_open
,
454 .close
= stac92xx_dig_playback_pcm_close
458 static struct hda_pcm_stream stac92xx_pcm_digital_capture
= {
462 /* NID is set in stac92xx_build_pcms */
465 static struct hda_pcm_stream stac92xx_pcm_analog_playback
= {
469 .nid
= 0x02, /* NID to query formats and rates */
471 .open
= stac92xx_playback_pcm_open
,
472 .prepare
= stac92xx_playback_pcm_prepare
,
473 .cleanup
= stac92xx_playback_pcm_cleanup
477 static struct hda_pcm_stream stac92xx_pcm_analog_alt_playback
= {
481 .nid
= 0x06, /* NID to query formats and rates */
483 .open
= stac92xx_playback_pcm_open
,
484 .prepare
= stac92xx_playback_pcm_prepare
,
485 .cleanup
= stac92xx_playback_pcm_cleanup
489 static struct hda_pcm_stream stac92xx_pcm_analog_capture
= {
493 /* NID is set in stac92xx_build_pcms */
495 .prepare
= stac92xx_capture_pcm_prepare
,
496 .cleanup
= stac92xx_capture_pcm_cleanup
500 static int stac92xx_build_pcms(struct hda_codec
*codec
)
502 struct sigmatel_spec
*spec
= codec
->spec
;
503 struct hda_pcm
*info
= spec
->pcm_rec
;
506 codec
->pcm_info
= info
;
508 info
->name
= "STAC92xx Analog";
509 info
->stream
[SNDRV_PCM_STREAM_PLAYBACK
] = stac92xx_pcm_analog_playback
;
510 info
->stream
[SNDRV_PCM_STREAM_CAPTURE
] = stac92xx_pcm_analog_capture
;
511 info
->stream
[SNDRV_PCM_STREAM_CAPTURE
].nid
= spec
->adc_nids
[0];
513 if (spec
->alt_switch
) {
516 info
->name
= "STAC92xx Analog Alt";
517 info
->stream
[SNDRV_PCM_STREAM_PLAYBACK
] = stac92xx_pcm_analog_alt_playback
;
520 if (spec
->multiout
.dig_out_nid
|| spec
->dig_in_nid
) {
523 info
->name
= "STAC92xx Digital";
524 if (spec
->multiout
.dig_out_nid
) {
525 info
->stream
[SNDRV_PCM_STREAM_PLAYBACK
] = stac92xx_pcm_digital_playback
;
526 info
->stream
[SNDRV_PCM_STREAM_PLAYBACK
].nid
= spec
->multiout
.dig_out_nid
;
528 if (spec
->dig_in_nid
) {
529 info
->stream
[SNDRV_PCM_STREAM_CAPTURE
] = stac92xx_pcm_digital_capture
;
530 info
->stream
[SNDRV_PCM_STREAM_CAPTURE
].nid
= spec
->dig_in_nid
;
537 static void stac92xx_auto_set_pinctl(struct hda_codec
*codec
, hda_nid_t nid
, int pin_type
)
540 snd_hda_codec_write(codec
, nid
, 0, AC_VERB_SET_PIN_WIDGET_CONTROL
, pin_type
);
543 static int stac92xx_io_switch_info(struct snd_kcontrol
*kcontrol
, struct snd_ctl_elem_info
*uinfo
)
545 uinfo
->type
= SNDRV_CTL_ELEM_TYPE_BOOLEAN
;
547 uinfo
->value
.integer
.min
= 0;
548 uinfo
->value
.integer
.max
= 1;
552 static int stac92xx_io_switch_get(struct snd_kcontrol
*kcontrol
, struct snd_ctl_elem_value
*ucontrol
)
554 struct hda_codec
*codec
= snd_kcontrol_chip(kcontrol
);
555 struct sigmatel_spec
*spec
= codec
->spec
;
556 int io_idx
= kcontrol
-> private_value
& 0xff;
558 ucontrol
->value
.integer
.value
[0] = spec
->io_switch
[io_idx
];
562 static int stac92xx_io_switch_put(struct snd_kcontrol
*kcontrol
, struct snd_ctl_elem_value
*ucontrol
)
564 struct hda_codec
*codec
= snd_kcontrol_chip(kcontrol
);
565 struct sigmatel_spec
*spec
= codec
->spec
;
566 hda_nid_t nid
= kcontrol
->private_value
>> 8;
567 int io_idx
= kcontrol
-> private_value
& 0xff;
568 unsigned short val
= ucontrol
->value
.integer
.value
[0];
570 spec
->io_switch
[io_idx
] = val
;
573 stac92xx_auto_set_pinctl(codec
, nid
, AC_PINCTL_OUT_EN
);
575 stac92xx_auto_set_pinctl(codec
, nid
, AC_PINCTL_IN_EN
);
580 #define STAC_CODEC_IO_SWITCH(xname, xpval) \
581 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
584 .info = stac92xx_io_switch_info, \
585 .get = stac92xx_io_switch_get, \
586 .put = stac92xx_io_switch_put, \
587 .private_value = xpval, \
593 STAC_CTL_WIDGET_MUTE
,
594 STAC_CTL_WIDGET_IO_SWITCH
,
597 static struct snd_kcontrol_new stac92xx_control_templates
[] = {
598 HDA_CODEC_VOLUME(NULL
, 0, 0, 0),
599 HDA_CODEC_MUTE(NULL
, 0, 0, 0),
600 STAC_CODEC_IO_SWITCH(NULL
, 0),
603 /* add dynamic controls */
604 static int stac92xx_add_control(struct sigmatel_spec
*spec
, int type
, const char *name
, unsigned long val
)
606 struct snd_kcontrol_new
*knew
;
608 if (spec
->num_kctl_used
>= spec
->num_kctl_alloc
) {
609 int num
= spec
->num_kctl_alloc
+ NUM_CONTROL_ALLOC
;
611 knew
= kcalloc(num
+ 1, sizeof(*knew
), GFP_KERNEL
); /* array + terminator */
614 if (spec
->kctl_alloc
) {
615 memcpy(knew
, spec
->kctl_alloc
, sizeof(*knew
) * spec
->num_kctl_alloc
);
616 kfree(spec
->kctl_alloc
);
618 spec
->kctl_alloc
= knew
;
619 spec
->num_kctl_alloc
= num
;
622 knew
= &spec
->kctl_alloc
[spec
->num_kctl_used
];
623 *knew
= stac92xx_control_templates
[type
];
624 knew
->name
= kstrdup(name
, GFP_KERNEL
);
627 knew
->private_value
= val
;
628 spec
->num_kctl_used
++;
632 /* flag inputs as additional dynamic lineouts */
633 static int stac92xx_add_dyn_out_pins(struct hda_codec
*codec
, struct auto_pin_cfg
*cfg
)
635 struct sigmatel_spec
*spec
= codec
->spec
;
637 switch (cfg
->line_outs
) {
639 /* add line-in as side */
640 if (cfg
->input_pins
[AUTO_PIN_LINE
]) {
641 cfg
->line_out_pins
[3] = cfg
->input_pins
[AUTO_PIN_LINE
];
642 spec
->line_switch
= 1;
647 /* add line-in as clfe and mic as side */
648 if (cfg
->input_pins
[AUTO_PIN_LINE
]) {
649 cfg
->line_out_pins
[2] = cfg
->input_pins
[AUTO_PIN_LINE
];
650 spec
->line_switch
= 1;
653 if (cfg
->input_pins
[AUTO_PIN_MIC
]) {
654 cfg
->line_out_pins
[3] = cfg
->input_pins
[AUTO_PIN_MIC
];
655 spec
->mic_switch
= 1;
660 /* add line-in as surr and mic as clfe */
661 if (cfg
->input_pins
[AUTO_PIN_LINE
]) {
662 cfg
->line_out_pins
[1] = cfg
->input_pins
[AUTO_PIN_LINE
];
663 spec
->line_switch
= 1;
666 if (cfg
->input_pins
[AUTO_PIN_MIC
]) {
667 cfg
->line_out_pins
[2] = cfg
->input_pins
[AUTO_PIN_MIC
];
668 spec
->mic_switch
= 1;
678 * XXX The line_out pin widget connection list may not be set to the
679 * desired DAC nid. This is the case on 927x where ports A and B can
680 * be routed to several DACs.
682 * This requires an analysis of the line-out/hp pin configuration
683 * to provide a best fit for pin/DAC configurations that are routable.
684 * For now, 927x DAC4 is not supported and 927x DAC1 output to ports
685 * A and B is not supported.
687 /* fill in the dac_nids table from the parsed pin configuration */
688 static int stac92xx_auto_fill_dac_nids(struct hda_codec
*codec
, const struct auto_pin_cfg
*cfg
)
690 struct sigmatel_spec
*spec
= codec
->spec
;
694 /* check the pins hardwired to audio widget */
695 for (i
= 0; i
< cfg
->line_outs
; i
++) {
696 nid
= cfg
->line_out_pins
[i
];
697 spec
->multiout
.dac_nids
[i
] = snd_hda_codec_read(codec
, nid
, 0,
698 AC_VERB_GET_CONNECT_LIST
, 0) & 0xff;
701 spec
->multiout
.num_dacs
= cfg
->line_outs
;
706 /* add playback controls from the parsed DAC table */
707 static int stac92xx_auto_create_multi_out_ctls(struct sigmatel_spec
*spec
, const struct auto_pin_cfg
*cfg
)
710 static const char *chname
[4] = { "Front", "Surround", NULL
/*CLFE*/, "Side" };
714 for (i
= 0; i
< cfg
->line_outs
; i
++) {
715 if (!spec
->multiout
.dac_nids
[i
])
718 nid
= spec
->multiout
.dac_nids
[i
];
722 if ((err
= stac92xx_add_control(spec
, STAC_CTL_WIDGET_VOL
, "Center Playback Volume",
723 HDA_COMPOSE_AMP_VAL(nid
, 1, 0, HDA_OUTPUT
))) < 0)
725 if ((err
= stac92xx_add_control(spec
, STAC_CTL_WIDGET_VOL
, "LFE Playback Volume",
726 HDA_COMPOSE_AMP_VAL(nid
, 2, 0, HDA_OUTPUT
))) < 0)
728 if ((err
= stac92xx_add_control(spec
, STAC_CTL_WIDGET_MUTE
, "Center Playback Switch",
729 HDA_COMPOSE_AMP_VAL(nid
, 1, 0, HDA_OUTPUT
))) < 0)
731 if ((err
= stac92xx_add_control(spec
, STAC_CTL_WIDGET_MUTE
, "LFE Playback Switch",
732 HDA_COMPOSE_AMP_VAL(nid
, 2, 0, HDA_OUTPUT
))) < 0)
735 sprintf(name
, "%s Playback Volume", chname
[i
]);
736 if ((err
= stac92xx_add_control(spec
, STAC_CTL_WIDGET_VOL
, name
,
737 HDA_COMPOSE_AMP_VAL(nid
, 3, 0, HDA_OUTPUT
))) < 0)
739 sprintf(name
, "%s Playback Switch", chname
[i
]);
740 if ((err
= stac92xx_add_control(spec
, STAC_CTL_WIDGET_MUTE
, name
,
741 HDA_COMPOSE_AMP_VAL(nid
, 3, 0, HDA_OUTPUT
))) < 0)
746 if (spec
->line_switch
)
747 if ((err
= stac92xx_add_control(spec
, STAC_CTL_WIDGET_IO_SWITCH
, "Line In as Output Switch", cfg
->input_pins
[AUTO_PIN_LINE
] << 8)) < 0)
750 if (spec
->mic_switch
)
751 if ((err
= stac92xx_add_control(spec
, STAC_CTL_WIDGET_IO_SWITCH
, "Mic as Output Switch", (cfg
->input_pins
[AUTO_PIN_MIC
] << 8) | 1)) < 0)
757 /* add playback controls for HP output */
758 static int stac92xx_auto_create_hp_ctls(struct hda_codec
*codec
, struct auto_pin_cfg
*cfg
)
760 struct sigmatel_spec
*spec
= codec
->spec
;
761 hda_nid_t pin
= cfg
->hp_pin
;
764 unsigned int wid_caps
;
769 wid_caps
= get_wcaps(codec
, pin
);
770 if (wid_caps
& AC_WCAP_UNSOL_CAP
) {
771 /* Enable unsolicited responses on the HP widget */
772 snd_hda_codec_write(codec
, pin
, 0,
773 AC_VERB_SET_UNSOLICITED_ENABLE
,
778 nid
= snd_hda_codec_read(codec
, pin
, 0, AC_VERB_GET_CONNECT_LIST
, 0) & 0xff;
779 for (i
= 0; i
< cfg
->line_outs
; i
++) {
780 if (! spec
->multiout
.dac_nids
[i
])
782 if (spec
->multiout
.dac_nids
[i
] == nid
)
786 spec
->multiout
.hp_nid
= nid
;
788 /* control HP volume/switch on the output mixer amp */
789 if ((err
= stac92xx_add_control(spec
, STAC_CTL_WIDGET_VOL
, "Headphone Playback Volume",
790 HDA_COMPOSE_AMP_VAL(nid
, 3, 0, HDA_OUTPUT
))) < 0)
792 if ((err
= stac92xx_add_control(spec
, STAC_CTL_WIDGET_MUTE
, "Headphone Playback Switch",
793 HDA_COMPOSE_AMP_VAL(nid
, 3, 0, HDA_OUTPUT
))) < 0)
799 /* create playback/capture controls for input pins */
800 static int stac92xx_auto_create_analog_input_ctls(struct hda_codec
*codec
, const struct auto_pin_cfg
*cfg
)
802 struct sigmatel_spec
*spec
= codec
->spec
;
803 struct hda_input_mux
*imux
= &spec
->private_imux
;
804 hda_nid_t con_lst
[HDA_MAX_NUM_INPUTS
];
807 for (i
= 0; i
< AUTO_PIN_LAST
; i
++) {
809 if (cfg
->input_pins
[i
]) {
810 imux
->items
[imux
->num_items
].label
= auto_pin_cfg_labels
[i
];
812 for (j
=0; j
<spec
->num_muxes
; j
++) {
813 int num_cons
= snd_hda_get_connections(codec
, spec
->mux_nids
[j
], con_lst
, HDA_MAX_NUM_INPUTS
);
814 for (k
=0; k
<num_cons
; k
++)
815 if (con_lst
[k
] == cfg
->input_pins
[i
]) {
822 imux
->items
[imux
->num_items
].index
= index
;
830 static void stac92xx_auto_init_multi_out(struct hda_codec
*codec
)
832 struct sigmatel_spec
*spec
= codec
->spec
;
835 for (i
= 0; i
< spec
->autocfg
.line_outs
; i
++) {
836 hda_nid_t nid
= spec
->autocfg
.line_out_pins
[i
];
837 stac92xx_auto_set_pinctl(codec
, nid
, AC_PINCTL_OUT_EN
);
841 static void stac92xx_auto_init_hp_out(struct hda_codec
*codec
)
843 struct sigmatel_spec
*spec
= codec
->spec
;
846 pin
= spec
->autocfg
.hp_pin
;
847 if (pin
) /* connect to front */
848 stac92xx_auto_set_pinctl(codec
, pin
, AC_PINCTL_OUT_EN
| AC_PINCTL_HP_EN
);
851 static int stac92xx_parse_auto_config(struct hda_codec
*codec
, hda_nid_t dig_out
, hda_nid_t dig_in
)
853 struct sigmatel_spec
*spec
= codec
->spec
;
856 if ((err
= snd_hda_parse_pin_def_config(codec
, &spec
->autocfg
, NULL
)) < 0)
858 if (! spec
->autocfg
.line_outs
)
859 return 0; /* can't find valid pin config */
860 if ((err
= stac92xx_add_dyn_out_pins(codec
, &spec
->autocfg
)) < 0)
862 if ((err
= stac92xx_auto_fill_dac_nids(codec
, &spec
->autocfg
)) < 0)
865 if ((err
= stac92xx_auto_create_multi_out_ctls(spec
, &spec
->autocfg
)) < 0 ||
866 (err
= stac92xx_auto_create_hp_ctls(codec
, &spec
->autocfg
)) < 0 ||
867 (err
= stac92xx_auto_create_analog_input_ctls(codec
, &spec
->autocfg
)) < 0)
870 spec
->multiout
.max_channels
= spec
->multiout
.num_dacs
* 2;
871 if (spec
->multiout
.max_channels
> 2)
872 spec
->surr_switch
= 1;
874 if (spec
->autocfg
.dig_out_pin
)
875 spec
->multiout
.dig_out_nid
= dig_out
;
876 if (spec
->autocfg
.dig_in_pin
)
877 spec
->dig_in_nid
= dig_in
;
879 if (spec
->kctl_alloc
)
880 spec
->mixers
[spec
->num_mixers
++] = spec
->kctl_alloc
;
882 spec
->input_mux
= &spec
->private_imux
;
887 /* add playback controls for HP output */
888 static int stac9200_auto_create_hp_ctls(struct hda_codec
*codec
,
889 struct auto_pin_cfg
*cfg
)
891 struct sigmatel_spec
*spec
= codec
->spec
;
892 hda_nid_t pin
= cfg
->hp_pin
;
893 unsigned int wid_caps
;
898 wid_caps
= get_wcaps(codec
, pin
);
899 if (wid_caps
& AC_WCAP_UNSOL_CAP
) {
900 /* Enable unsolicited responses on the HP widget */
901 snd_hda_codec_write(codec
, pin
, 0,
902 AC_VERB_SET_UNSOLICITED_ENABLE
,
910 static int stac9200_parse_auto_config(struct hda_codec
*codec
)
912 struct sigmatel_spec
*spec
= codec
->spec
;
915 if ((err
= snd_hda_parse_pin_def_config(codec
, &spec
->autocfg
, NULL
)) < 0)
918 if ((err
= stac92xx_auto_create_analog_input_ctls(codec
, &spec
->autocfg
)) < 0)
921 if ((err
= stac9200_auto_create_hp_ctls(codec
, &spec
->autocfg
)) < 0)
924 if (spec
->autocfg
.dig_out_pin
)
925 spec
->multiout
.dig_out_nid
= 0x05;
926 if (spec
->autocfg
.dig_in_pin
)
927 spec
->dig_in_nid
= 0x04;
929 if (spec
->kctl_alloc
)
930 spec
->mixers
[spec
->num_mixers
++] = spec
->kctl_alloc
;
932 spec
->input_mux
= &spec
->private_imux
;
937 static int stac92xx_init(struct hda_codec
*codec
)
939 struct sigmatel_spec
*spec
= codec
->spec
;
940 struct auto_pin_cfg
*cfg
= &spec
->autocfg
;
943 snd_hda_sequence_write(codec
, spec
->init
);
946 if (spec
->hp_detect
) {
947 /* fake event to set up pins */
948 codec
->patch_ops
.unsol_event(codec
, STAC_HP_EVENT
<< 26);
950 stac92xx_auto_init_multi_out(codec
);
951 stac92xx_auto_init_hp_out(codec
);
953 for (i
= 0; i
< AUTO_PIN_LAST
; i
++) {
954 if (cfg
->input_pins
[i
])
955 stac92xx_auto_set_pinctl(codec
, cfg
->input_pins
[i
],
958 if (cfg
->dig_out_pin
)
959 stac92xx_auto_set_pinctl(codec
, cfg
->dig_out_pin
,
962 stac92xx_auto_set_pinctl(codec
, cfg
->dig_in_pin
,
968 static void stac92xx_free(struct hda_codec
*codec
)
970 struct sigmatel_spec
*spec
= codec
->spec
;
976 if (spec
->kctl_alloc
) {
977 for (i
= 0; i
< spec
->num_kctl_used
; i
++)
978 kfree(spec
->kctl_alloc
[i
].name
);
979 kfree(spec
->kctl_alloc
);
985 static void stac92xx_set_pinctl(struct hda_codec
*codec
, hda_nid_t nid
,
988 unsigned int pin_ctl
= snd_hda_codec_read(codec
, nid
,
989 0, AC_VERB_GET_PIN_WIDGET_CONTROL
, 0x00);
990 snd_hda_codec_write(codec
, nid
, 0,
991 AC_VERB_SET_PIN_WIDGET_CONTROL
,
995 static void stac92xx_reset_pinctl(struct hda_codec
*codec
, hda_nid_t nid
,
998 unsigned int pin_ctl
= snd_hda_codec_read(codec
, nid
,
999 0, AC_VERB_GET_PIN_WIDGET_CONTROL
, 0x00);
1000 snd_hda_codec_write(codec
, nid
, 0,
1001 AC_VERB_SET_PIN_WIDGET_CONTROL
,
1005 static void stac92xx_unsol_event(struct hda_codec
*codec
, unsigned int res
)
1007 struct sigmatel_spec
*spec
= codec
->spec
;
1008 struct auto_pin_cfg
*cfg
= &spec
->autocfg
;
1011 if ((res
>> 26) != STAC_HP_EVENT
)
1014 presence
= snd_hda_codec_read(codec
, cfg
->hp_pin
, 0,
1015 AC_VERB_GET_PIN_SENSE
, 0x00) >> 31;
1018 /* disable lineouts, enable hp */
1019 for (i
= 0; i
< cfg
->line_outs
; i
++)
1020 stac92xx_reset_pinctl(codec
, cfg
->line_out_pins
[i
],
1022 stac92xx_set_pinctl(codec
, cfg
->hp_pin
, AC_PINCTL_OUT_EN
);
1024 /* enable lineouts, disable hp */
1025 for (i
= 0; i
< cfg
->line_outs
; i
++)
1026 stac92xx_set_pinctl(codec
, cfg
->line_out_pins
[i
],
1028 stac92xx_reset_pinctl(codec
, cfg
->hp_pin
, AC_PINCTL_OUT_EN
);
1033 static int stac92xx_resume(struct hda_codec
*codec
)
1035 struct sigmatel_spec
*spec
= codec
->spec
;
1038 stac92xx_init(codec
);
1039 for (i
= 0; i
< spec
->num_mixers
; i
++)
1040 snd_hda_resume_ctls(codec
, spec
->mixers
[i
]);
1041 if (spec
->multiout
.dig_out_nid
)
1042 snd_hda_resume_spdif_out(codec
);
1043 if (spec
->dig_in_nid
)
1044 snd_hda_resume_spdif_in(codec
);
1050 static struct hda_codec_ops stac92xx_patch_ops
= {
1051 .build_controls
= stac92xx_build_controls
,
1052 .build_pcms
= stac92xx_build_pcms
,
1053 .init
= stac92xx_init
,
1054 .free
= stac92xx_free
,
1055 .unsol_event
= stac92xx_unsol_event
,
1057 .resume
= stac92xx_resume
,
1061 static int patch_stac9200(struct hda_codec
*codec
)
1063 struct sigmatel_spec
*spec
;
1066 spec
= kzalloc(sizeof(*spec
), GFP_KERNEL
);
1071 spec
->board_config
= snd_hda_check_board_config(codec
, stac9200_cfg_tbl
);
1072 if (spec
->board_config
< 0)
1073 snd_printdd(KERN_INFO
"hda_codec: Unknown model for STAC9200, using BIOS defaults\n");
1076 spec
->pin_nids
= stac9200_pin_nids
;
1077 spec
->pin_configs
= stac9200_brd_tbl
[spec
->board_config
];
1078 stac92xx_set_config_regs(codec
);
1081 spec
->multiout
.max_channels
= 2;
1082 spec
->multiout
.num_dacs
= 1;
1083 spec
->multiout
.dac_nids
= stac9200_dac_nids
;
1084 spec
->adc_nids
= stac9200_adc_nids
;
1085 spec
->mux_nids
= stac9200_mux_nids
;
1086 spec
->num_muxes
= 1;
1088 spec
->init
= stac9200_core_init
;
1089 spec
->mixer
= stac9200_mixer
;
1091 err
= stac9200_parse_auto_config(codec
);
1093 stac92xx_free(codec
);
1097 codec
->patch_ops
= stac92xx_patch_ops
;
1102 static int patch_stac922x(struct hda_codec
*codec
)
1104 struct sigmatel_spec
*spec
;
1107 spec
= kzalloc(sizeof(*spec
), GFP_KERNEL
);
1112 spec
->board_config
= snd_hda_check_board_config(codec
, stac922x_cfg_tbl
);
1113 if (spec
->board_config
< 0)
1114 snd_printdd(KERN_INFO
"hda_codec: Unknown model for STAC922x, using BIOS defaults\n");
1116 spec
->num_pins
= 10;
1117 spec
->pin_nids
= stac922x_pin_nids
;
1118 spec
->pin_configs
= stac922x_brd_tbl
[spec
->board_config
];
1119 stac92xx_set_config_regs(codec
);
1122 spec
->adc_nids
= stac922x_adc_nids
;
1123 spec
->mux_nids
= stac922x_mux_nids
;
1124 spec
->num_muxes
= 2;
1126 spec
->init
= stac922x_core_init
;
1127 spec
->mixer
= stac922x_mixer
;
1129 spec
->multiout
.dac_nids
= spec
->dac_nids
;
1131 err
= stac92xx_parse_auto_config(codec
, 0x08, 0x09);
1133 stac92xx_free(codec
);
1137 codec
->patch_ops
= stac92xx_patch_ops
;
1142 static int patch_stac927x(struct hda_codec
*codec
)
1144 struct sigmatel_spec
*spec
;
1147 spec
= kzalloc(sizeof(*spec
), GFP_KERNEL
);
1152 spec
->board_config
= snd_hda_check_board_config(codec
, stac927x_cfg_tbl
);
1153 if (spec
->board_config
< 0)
1154 snd_printdd(KERN_INFO
"hda_codec: Unknown model for STAC927x, using BIOS defaults\n");
1156 spec
->num_pins
= 14;
1157 spec
->pin_nids
= stac927x_pin_nids
;
1158 spec
->pin_configs
= stac927x_brd_tbl
[spec
->board_config
];
1159 stac92xx_set_config_regs(codec
);
1162 spec
->adc_nids
= stac927x_adc_nids
;
1163 spec
->mux_nids
= stac927x_mux_nids
;
1164 spec
->num_muxes
= 3;
1166 spec
->init
= stac927x_core_init
;
1167 spec
->mixer
= stac927x_mixer
;
1169 spec
->multiout
.dac_nids
= spec
->dac_nids
;
1171 err
= stac92xx_parse_auto_config(codec
, 0x1e, 0x20);
1173 stac92xx_free(codec
);
1177 codec
->patch_ops
= stac92xx_patch_ops
;
1186 /* static config for Sony VAIO FE550G */
1187 static hda_nid_t vaio_dacs
[] = { 0x2 };
1188 #define VAIO_HP_DAC 0x5
1189 static hda_nid_t vaio_adcs
[] = { 0x8 /*,0x6*/ };
1190 static hda_nid_t vaio_mux_nids
[] = { 0x15 };
1192 static struct hda_input_mux vaio_mux
= {
1196 { "Unknown", 0x1 }, */
1202 static struct hda_verb vaio_init
[] = {
1203 {0x0a, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_HP
}, /* HP <- 0x2 */
1204 {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_OUT
}, /* Speaker <- 0x5 */
1205 {0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
}, /* Mic? (<- 0x2) */
1206 {0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_IN
}, /* CD */
1207 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
}, /* Mic? */
1208 {0x15, AC_VERB_SET_CONNECT_SEL
, 0x2}, /* mic-sel: 0a,0d,14,02 */
1209 {0x02, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
}, /* HP */
1210 {0x05, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_MUTE
}, /* Speaker */
1211 {0x09, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(0)}, /* capture sw/vol -> 0x8 */
1212 {0x07, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)}, /* CD-in -> 0x6 */
1213 {0x15, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_UNMUTE
}, /* Mic-in -> 0x9 */
1217 /* bind volumes of both NID 0x02 and 0x05 */
1218 static int vaio_master_vol_put(struct snd_kcontrol
*kcontrol
,
1219 struct snd_ctl_elem_value
*ucontrol
)
1221 struct hda_codec
*codec
= snd_kcontrol_chip(kcontrol
);
1222 long *valp
= ucontrol
->value
.integer
.value
;
1225 change
= snd_hda_codec_amp_update(codec
, 0x02, 0, HDA_OUTPUT
, 0,
1226 0x7f, valp
[0] & 0x7f);
1227 change
|= snd_hda_codec_amp_update(codec
, 0x02, 1, HDA_OUTPUT
, 0,
1228 0x7f, valp
[1] & 0x7f);
1229 snd_hda_codec_amp_update(codec
, 0x05, 0, HDA_OUTPUT
, 0,
1230 0x7f, valp
[0] & 0x7f);
1231 snd_hda_codec_amp_update(codec
, 0x05, 1, HDA_OUTPUT
, 0,
1232 0x7f, valp
[1] & 0x7f);
1236 /* bind volumes of both NID 0x02 and 0x05 */
1237 static int vaio_master_sw_put(struct snd_kcontrol
*kcontrol
,
1238 struct snd_ctl_elem_value
*ucontrol
)
1240 struct hda_codec
*codec
= snd_kcontrol_chip(kcontrol
);
1241 long *valp
= ucontrol
->value
.integer
.value
;
1244 change
= snd_hda_codec_amp_update(codec
, 0x02, 0, HDA_OUTPUT
, 0,
1245 0x80, valp
[0] & 0x80);
1246 change
|= snd_hda_codec_amp_update(codec
, 0x02, 1, HDA_OUTPUT
, 0,
1247 0x80, valp
[1] & 0x80);
1248 snd_hda_codec_amp_update(codec
, 0x05, 0, HDA_OUTPUT
, 0,
1249 0x80, valp
[0] & 0x80);
1250 snd_hda_codec_amp_update(codec
, 0x05, 1, HDA_OUTPUT
, 0,
1251 0x80, valp
[1] & 0x80);
1255 static struct snd_kcontrol_new vaio_mixer
[] = {
1257 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
1258 .name
= "Master Playback Volume",
1259 .info
= snd_hda_mixer_amp_volume_info
,
1260 .get
= snd_hda_mixer_amp_volume_get
,
1261 .put
= vaio_master_vol_put
,
1262 .private_value
= HDA_COMPOSE_AMP_VAL(0x02, 3, 0, HDA_OUTPUT
),
1265 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
1266 .name
= "Master Playback Switch",
1267 .info
= snd_hda_mixer_amp_switch_info
,
1268 .get
= snd_hda_mixer_amp_switch_get
,
1269 .put
= vaio_master_sw_put
,
1270 .private_value
= HDA_COMPOSE_AMP_VAL(0x02, 3, 0, HDA_OUTPUT
),
1272 /* HDA_CODEC_VOLUME("CD Capture Volume", 0x07, 0, HDA_INPUT), */
1273 HDA_CODEC_VOLUME("Capture Volume", 0x09, 0, HDA_INPUT
),
1274 HDA_CODEC_MUTE("Capture Switch", 0x09, 0, HDA_INPUT
),
1276 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
1277 .name
= "Capture Source",
1279 .info
= stac92xx_mux_enum_info
,
1280 .get
= stac92xx_mux_enum_get
,
1281 .put
= stac92xx_mux_enum_put
,
1286 static struct hda_codec_ops stac7661_patch_ops
= {
1287 .build_controls
= stac92xx_build_controls
,
1288 .build_pcms
= stac92xx_build_pcms
,
1289 .init
= stac92xx_init
,
1290 .free
= stac92xx_free
,
1292 .resume
= stac92xx_resume
,
1296 enum { STAC7661_VAIO
};
1298 static struct hda_board_config stac7661_cfg_tbl
[] = {
1299 { .modelname
= "vaio", .config
= STAC7661_VAIO
},
1300 { .pci_subvendor
= 0x104d, .pci_subdevice
= 0x81e6,
1301 .config
= STAC7661_VAIO
},
1302 { .pci_subvendor
= 0x104d, .pci_subdevice
= 0x81ef,
1303 .config
= STAC7661_VAIO
},
1307 static int patch_stac7661(struct hda_codec
*codec
)
1309 struct sigmatel_spec
*spec
;
1312 board_config
= snd_hda_check_board_config(codec
, stac7661_cfg_tbl
);
1313 if (board_config
< 0)
1314 /* unknown config, let generic-parser do its job... */
1315 return snd_hda_parse_generic_codec(codec
);
1317 spec
= kzalloc(sizeof(*spec
), GFP_KERNEL
);
1322 switch (board_config
) {
1324 spec
->mixer
= vaio_mixer
;
1325 spec
->init
= vaio_init
;
1326 spec
->multiout
.max_channels
= 2;
1327 spec
->multiout
.num_dacs
= ARRAY_SIZE(vaio_dacs
);
1328 spec
->multiout
.dac_nids
= vaio_dacs
;
1329 spec
->multiout
.hp_nid
= VAIO_HP_DAC
;
1330 spec
->num_adcs
= ARRAY_SIZE(vaio_adcs
);
1331 spec
->adc_nids
= vaio_adcs
;
1332 spec
->input_mux
= &vaio_mux
;
1333 spec
->mux_nids
= vaio_mux_nids
;
1337 codec
->patch_ops
= stac7661_patch_ops
;
1345 struct hda_codec_preset snd_hda_preset_sigmatel
[] = {
1346 { .id
= 0x83847690, .name
= "STAC9200", .patch
= patch_stac9200
},
1347 { .id
= 0x83847882, .name
= "STAC9220 A1", .patch
= patch_stac922x
},
1348 { .id
= 0x83847680, .name
= "STAC9221 A1", .patch
= patch_stac922x
},
1349 { .id
= 0x83847880, .name
= "STAC9220 A2", .patch
= patch_stac922x
},
1350 { .id
= 0x83847681, .name
= "STAC9220D/9223D A2", .patch
= patch_stac922x
},
1351 { .id
= 0x83847682, .name
= "STAC9221 A2", .patch
= patch_stac922x
},
1352 { .id
= 0x83847683, .name
= "STAC9221D A2", .patch
= patch_stac922x
},
1353 { .id
= 0x83847620, .name
= "STAC9274", .patch
= patch_stac927x
},
1354 { .id
= 0x83847621, .name
= "STAC9274D", .patch
= patch_stac927x
},
1355 { .id
= 0x83847622, .name
= "STAC9273X", .patch
= patch_stac927x
},
1356 { .id
= 0x83847623, .name
= "STAC9273D", .patch
= patch_stac927x
},
1357 { .id
= 0x83847624, .name
= "STAC9272X", .patch
= patch_stac927x
},
1358 { .id
= 0x83847625, .name
= "STAC9272D", .patch
= patch_stac927x
},
1359 { .id
= 0x83847626, .name
= "STAC9271X", .patch
= patch_stac927x
},
1360 { .id
= 0x83847627, .name
= "STAC9271D", .patch
= patch_stac927x
},
1361 { .id
= 0x83847628, .name
= "STAC9274X5NH", .patch
= patch_stac927x
},
1362 { .id
= 0x83847629, .name
= "STAC9274D5NH", .patch
= patch_stac927x
},
1363 { .id
= 0x83847661, .name
= "STAC7661", .patch
= patch_stac7661
},