2 * HD audio interface patch for Creative X-Fi CA0110-IBG chip
4 * Copyright (c) 2008 Takashi Iwai <tiwai@suse.de>
6 * This driver is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This driver is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #include <linux/init.h>
22 #include <linux/delay.h>
23 #include <linux/slab.h>
24 #include <linux/pci.h>
25 #include <linux/module.h>
26 #include <sound/core.h>
27 #include "hda_codec.h"
28 #include "hda_local.h"
34 struct auto_pin_cfg autocfg
;
35 struct hda_multi_out multiout
;
36 hda_nid_t out_pins
[AUTO_CFG_MAX_OUTS
];
37 hda_nid_t dacs
[AUTO_CFG_MAX_OUTS
];
39 hda_nid_t input_pins
[AUTO_PIN_LAST
];
40 hda_nid_t adcs
[AUTO_PIN_LAST
];
43 unsigned int num_inputs
;
44 char input_labels
[AUTO_PIN_LAST
][32];
45 struct hda_pcm pcm_rec
[2]; /* PCM information */
51 static int ca0110_playback_pcm_open(struct hda_pcm_stream
*hinfo
,
52 struct hda_codec
*codec
,
53 struct snd_pcm_substream
*substream
)
55 struct ca0110_spec
*spec
= codec
->spec
;
56 return snd_hda_multi_out_analog_open(codec
, &spec
->multiout
, substream
,
60 static int ca0110_playback_pcm_prepare(struct hda_pcm_stream
*hinfo
,
61 struct hda_codec
*codec
,
62 unsigned int stream_tag
,
64 struct snd_pcm_substream
*substream
)
66 struct ca0110_spec
*spec
= codec
->spec
;
67 return snd_hda_multi_out_analog_prepare(codec
, &spec
->multiout
,
68 stream_tag
, format
, substream
);
71 static int ca0110_playback_pcm_cleanup(struct hda_pcm_stream
*hinfo
,
72 struct hda_codec
*codec
,
73 struct snd_pcm_substream
*substream
)
75 struct ca0110_spec
*spec
= codec
->spec
;
76 return snd_hda_multi_out_analog_cleanup(codec
, &spec
->multiout
);
82 static int ca0110_dig_playback_pcm_open(struct hda_pcm_stream
*hinfo
,
83 struct hda_codec
*codec
,
84 struct snd_pcm_substream
*substream
)
86 struct ca0110_spec
*spec
= codec
->spec
;
87 return snd_hda_multi_out_dig_open(codec
, &spec
->multiout
);
90 static int ca0110_dig_playback_pcm_close(struct hda_pcm_stream
*hinfo
,
91 struct hda_codec
*codec
,
92 struct snd_pcm_substream
*substream
)
94 struct ca0110_spec
*spec
= codec
->spec
;
95 return snd_hda_multi_out_dig_close(codec
, &spec
->multiout
);
98 static int ca0110_dig_playback_pcm_prepare(struct hda_pcm_stream
*hinfo
,
99 struct hda_codec
*codec
,
100 unsigned int stream_tag
,
102 struct snd_pcm_substream
*substream
)
104 struct ca0110_spec
*spec
= codec
->spec
;
105 return snd_hda_multi_out_dig_prepare(codec
, &spec
->multiout
, stream_tag
,
112 static int ca0110_capture_pcm_prepare(struct hda_pcm_stream
*hinfo
,
113 struct hda_codec
*codec
,
114 unsigned int stream_tag
,
116 struct snd_pcm_substream
*substream
)
118 struct ca0110_spec
*spec
= codec
->spec
;
120 snd_hda_codec_setup_stream(codec
, spec
->adcs
[substream
->number
],
121 stream_tag
, 0, format
);
125 static int ca0110_capture_pcm_cleanup(struct hda_pcm_stream
*hinfo
,
126 struct hda_codec
*codec
,
127 struct snd_pcm_substream
*substream
)
129 struct ca0110_spec
*spec
= codec
->spec
;
131 snd_hda_codec_cleanup_stream(codec
, spec
->adcs
[substream
->number
]);
138 static const char * const dirstr
[2] = { "Playback", "Capture" };
140 static int _add_switch(struct hda_codec
*codec
, hda_nid_t nid
, const char *pfx
,
144 int type
= dir
? HDA_INPUT
: HDA_OUTPUT
;
145 struct snd_kcontrol_new knew
=
146 HDA_CODEC_MUTE_MONO(namestr
, nid
, chan
, 0, type
);
147 sprintf(namestr
, "%s %s Switch", pfx
, dirstr
[dir
]);
148 return snd_hda_ctl_add(codec
, nid
, snd_ctl_new1(&knew
, codec
));
151 static int _add_volume(struct hda_codec
*codec
, hda_nid_t nid
, const char *pfx
,
155 int type
= dir
? HDA_INPUT
: HDA_OUTPUT
;
156 struct snd_kcontrol_new knew
=
157 HDA_CODEC_VOLUME_MONO(namestr
, nid
, chan
, 0, type
);
158 sprintf(namestr
, "%s %s Volume", pfx
, dirstr
[dir
]);
159 return snd_hda_ctl_add(codec
, nid
, snd_ctl_new1(&knew
, codec
));
162 #define add_out_switch(codec, nid, pfx) _add_switch(codec, nid, pfx, 3, 0)
163 #define add_out_volume(codec, nid, pfx) _add_volume(codec, nid, pfx, 3, 0)
164 #define add_in_switch(codec, nid, pfx) _add_switch(codec, nid, pfx, 3, 1)
165 #define add_in_volume(codec, nid, pfx) _add_volume(codec, nid, pfx, 3, 1)
166 #define add_mono_switch(codec, nid, pfx, chan) \
167 _add_switch(codec, nid, pfx, chan, 0)
168 #define add_mono_volume(codec, nid, pfx, chan) \
169 _add_volume(codec, nid, pfx, chan, 0)
171 static int ca0110_build_controls(struct hda_codec
*codec
)
173 struct ca0110_spec
*spec
= codec
->spec
;
174 struct auto_pin_cfg
*cfg
= &spec
->autocfg
;
175 static const char * const prefix
[AUTO_CFG_MAX_OUTS
] = {
176 "Front", "Surround", NULL
, "Side", "Multi"
181 for (i
= 0; i
< spec
->multiout
.num_dacs
; i
++) {
182 if (get_wcaps(codec
, spec
->out_pins
[i
]) & AC_WCAP_OUT_AMP
)
183 mutenid
= spec
->out_pins
[i
];
185 mutenid
= spec
->multiout
.dac_nids
[i
];
187 err
= add_mono_switch(codec
, mutenid
,
191 err
= add_mono_switch(codec
, mutenid
,
195 err
= add_mono_volume(codec
, spec
->multiout
.dac_nids
[i
],
199 err
= add_mono_volume(codec
, spec
->multiout
.dac_nids
[i
],
204 err
= add_out_switch(codec
, mutenid
,
208 err
= add_out_volume(codec
, spec
->multiout
.dac_nids
[i
],
215 if (get_wcaps(codec
, cfg
->hp_pins
[0]) & AC_WCAP_OUT_AMP
)
216 mutenid
= cfg
->hp_pins
[0];
218 mutenid
= spec
->multiout
.dac_nids
[i
];
220 err
= add_out_switch(codec
, mutenid
, "Headphone");
224 err
= add_out_volume(codec
, spec
->hp_dac
, "Headphone");
229 for (i
= 0; i
< spec
->num_inputs
; i
++) {
230 const char *label
= spec
->input_labels
[i
];
231 if (get_wcaps(codec
, spec
->input_pins
[i
]) & AC_WCAP_IN_AMP
)
232 mutenid
= spec
->input_pins
[i
];
234 mutenid
= spec
->adcs
[i
];
235 err
= add_in_switch(codec
, mutenid
, label
);
238 err
= add_in_volume(codec
, spec
->adcs
[i
], label
);
244 err
= snd_hda_create_spdif_out_ctls(codec
, spec
->dig_out
,
248 err
= snd_hda_create_spdif_share_sw(codec
, &spec
->multiout
);
251 spec
->multiout
.share_spdif
= 1;
254 err
= snd_hda_create_spdif_in_ctls(codec
, spec
->dig_in
);
257 err
= add_in_volume(codec
, spec
->dig_in
, "IEC958");
264 static const struct hda_pcm_stream ca0110_pcm_analog_playback
= {
269 .open
= ca0110_playback_pcm_open
,
270 .prepare
= ca0110_playback_pcm_prepare
,
271 .cleanup
= ca0110_playback_pcm_cleanup
275 static const struct hda_pcm_stream ca0110_pcm_analog_capture
= {
280 .prepare
= ca0110_capture_pcm_prepare
,
281 .cleanup
= ca0110_capture_pcm_cleanup
285 static const struct hda_pcm_stream ca0110_pcm_digital_playback
= {
290 .open
= ca0110_dig_playback_pcm_open
,
291 .close
= ca0110_dig_playback_pcm_close
,
292 .prepare
= ca0110_dig_playback_pcm_prepare
296 static const struct hda_pcm_stream ca0110_pcm_digital_capture
= {
302 static int ca0110_build_pcms(struct hda_codec
*codec
)
304 struct ca0110_spec
*spec
= codec
->spec
;
305 struct hda_pcm
*info
= spec
->pcm_rec
;
307 codec
->pcm_info
= info
;
310 info
->name
= "CA0110 Analog";
311 info
->stream
[SNDRV_PCM_STREAM_PLAYBACK
] = ca0110_pcm_analog_playback
;
312 info
->stream
[SNDRV_PCM_STREAM_PLAYBACK
].nid
= spec
->dacs
[0];
313 info
->stream
[SNDRV_PCM_STREAM_PLAYBACK
].channels_max
=
314 spec
->multiout
.max_channels
;
315 info
->stream
[SNDRV_PCM_STREAM_CAPTURE
] = ca0110_pcm_analog_capture
;
316 info
->stream
[SNDRV_PCM_STREAM_CAPTURE
].substreams
= spec
->num_inputs
;
317 info
->stream
[SNDRV_PCM_STREAM_CAPTURE
].nid
= spec
->adcs
[0];
320 if (!spec
->dig_out
&& !spec
->dig_in
)
324 info
->name
= "CA0110 Digital";
325 info
->pcm_type
= HDA_PCM_TYPE_SPDIF
;
327 info
->stream
[SNDRV_PCM_STREAM_PLAYBACK
] =
328 ca0110_pcm_digital_playback
;
329 info
->stream
[SNDRV_PCM_STREAM_PLAYBACK
].nid
= spec
->dig_out
;
332 info
->stream
[SNDRV_PCM_STREAM_CAPTURE
] =
333 ca0110_pcm_digital_capture
;
334 info
->stream
[SNDRV_PCM_STREAM_CAPTURE
].nid
= spec
->dig_in
;
341 static void init_output(struct hda_codec
*codec
, hda_nid_t pin
, hda_nid_t dac
)
344 snd_hda_codec_write(codec
, pin
, 0,
345 AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_HP
);
346 if (get_wcaps(codec
, pin
) & AC_WCAP_OUT_AMP
)
347 snd_hda_codec_write(codec
, pin
, 0,
348 AC_VERB_SET_AMP_GAIN_MUTE
,
352 snd_hda_codec_write(codec
, dac
, 0,
353 AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
);
356 static void init_input(struct hda_codec
*codec
, hda_nid_t pin
, hda_nid_t adc
)
359 snd_hda_codec_write(codec
, pin
, 0,
360 AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
);
361 if (get_wcaps(codec
, pin
) & AC_WCAP_IN_AMP
)
362 snd_hda_codec_write(codec
, pin
, 0,
363 AC_VERB_SET_AMP_GAIN_MUTE
,
367 snd_hda_codec_write(codec
, adc
, 0, AC_VERB_SET_AMP_GAIN_MUTE
,
371 static int ca0110_init(struct hda_codec
*codec
)
373 struct ca0110_spec
*spec
= codec
->spec
;
374 struct auto_pin_cfg
*cfg
= &spec
->autocfg
;
377 for (i
= 0; i
< spec
->multiout
.num_dacs
; i
++)
378 init_output(codec
, spec
->out_pins
[i
],
379 spec
->multiout
.dac_nids
[i
]);
380 init_output(codec
, cfg
->hp_pins
[0], spec
->hp_dac
);
381 init_output(codec
, cfg
->dig_out_pins
[0], spec
->dig_out
);
383 for (i
= 0; i
< spec
->num_inputs
; i
++)
384 init_input(codec
, spec
->input_pins
[i
], spec
->adcs
[i
]);
385 init_input(codec
, cfg
->dig_in_pin
, spec
->dig_in
);
389 static void ca0110_free(struct hda_codec
*codec
)
394 static const struct hda_codec_ops ca0110_patch_ops
= {
395 .build_controls
= ca0110_build_controls
,
396 .build_pcms
= ca0110_build_pcms
,
402 static void parse_line_outs(struct hda_codec
*codec
)
404 struct ca0110_spec
*spec
= codec
->spec
;
405 struct auto_pin_cfg
*cfg
= &spec
->autocfg
;
407 unsigned int def_conf
;
411 for (i
= 0; i
< cfg
->line_outs
; i
++) {
412 nid
= cfg
->line_out_pins
[i
];
413 def_conf
= snd_hda_codec_get_pincfg(codec
, nid
);
415 continue; /* invalid pin */
416 if (snd_hda_get_connections(codec
, nid
, &spec
->dacs
[i
], 1) != 1)
418 spec
->out_pins
[n
++] = nid
;
420 spec
->multiout
.dac_nids
= spec
->dacs
;
421 spec
->multiout
.num_dacs
= n
;
422 spec
->multiout
.max_channels
= n
* 2;
425 static void parse_hp_out(struct hda_codec
*codec
)
427 struct ca0110_spec
*spec
= codec
->spec
;
428 struct auto_pin_cfg
*cfg
= &spec
->autocfg
;
430 unsigned int def_conf
;
435 nid
= cfg
->hp_pins
[0];
436 def_conf
= snd_hda_codec_get_pincfg(codec
, nid
);
441 if (snd_hda_get_connections(codec
, nid
, &dac
, 1) != 1)
444 for (i
= 0; i
< cfg
->line_outs
; i
++)
445 if (dac
== spec
->dacs
[i
])
447 if (i
>= cfg
->line_outs
) {
449 spec
->multiout
.hp_nid
= dac
;
453 static void parse_input(struct hda_codec
*codec
)
455 struct ca0110_spec
*spec
= codec
->spec
;
456 struct auto_pin_cfg
*cfg
= &spec
->autocfg
;
461 nid
= codec
->start_nid
;
462 for (i
= 0; i
< codec
->num_nodes
; i
++, nid
++) {
463 unsigned int wcaps
= get_wcaps(codec
, nid
);
464 unsigned int type
= get_wcaps_type(wcaps
);
465 if (type
!= AC_WID_AUD_IN
)
467 if (snd_hda_get_connections(codec
, nid
, &pin
, 1) != 1)
469 if (pin
== cfg
->dig_in_pin
) {
473 for (j
= 0; j
< cfg
->num_inputs
; j
++)
474 if (cfg
->inputs
[j
].pin
== pin
)
476 if (j
>= cfg
->num_inputs
)
478 spec
->input_pins
[n
] = pin
;
479 snd_hda_get_pin_label(codec
, pin
, cfg
,
480 spec
->input_labels
[n
],
481 sizeof(spec
->input_labels
[n
]), NULL
);
485 spec
->num_inputs
= n
;
488 static void parse_digital(struct hda_codec
*codec
)
490 struct ca0110_spec
*spec
= codec
->spec
;
491 struct auto_pin_cfg
*cfg
= &spec
->autocfg
;
494 snd_hda_get_connections(codec
, cfg
->dig_out_pins
[0],
495 &spec
->dig_out
, 1) == 1)
496 spec
->multiout
.dig_out_nid
= spec
->dig_out
;
499 static int ca0110_parse_auto_config(struct hda_codec
*codec
)
501 struct ca0110_spec
*spec
= codec
->spec
;
504 err
= snd_hda_parse_pin_def_config(codec
, &spec
->autocfg
, NULL
);
508 parse_line_outs(codec
);
510 parse_digital(codec
);
516 static int patch_ca0110(struct hda_codec
*codec
)
518 struct ca0110_spec
*spec
;
521 spec
= kzalloc(sizeof(*spec
), GFP_KERNEL
);
526 codec
->bus
->needs_damn_long_delay
= 1;
528 err
= ca0110_parse_auto_config(codec
);
532 codec
->patch_ops
= ca0110_patch_ops
;
546 static const struct hda_codec_preset snd_hda_preset_ca0110
[] = {
547 { .id
= 0x1102000a, .name
= "CA0110-IBG", .patch
= patch_ca0110
},
548 { .id
= 0x1102000b, .name
= "CA0110-IBG", .patch
= patch_ca0110
},
549 { .id
= 0x1102000d, .name
= "SB0880 X-Fi", .patch
= patch_ca0110
},
553 MODULE_ALIAS("snd-hda-codec-id:1102000a");
554 MODULE_ALIAS("snd-hda-codec-id:1102000b");
555 MODULE_ALIAS("snd-hda-codec-id:1102000d");
557 MODULE_LICENSE("GPL");
558 MODULE_DESCRIPTION("Creative CA0110-IBG HD-audio codec");
560 static struct hda_codec_preset_list ca0110_list
= {
561 .preset
= snd_hda_preset_ca0110
,
562 .owner
= THIS_MODULE
,
565 static int __init
patch_ca0110_init(void)
567 return snd_hda_add_codec_preset(&ca0110_list
);
570 static void __exit
patch_ca0110_exit(void)
572 snd_hda_delete_codec_preset(&ca0110_list
);
575 module_init(patch_ca0110_init
)
576 module_exit(patch_ca0110_exit
)