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"
29 #include "hda_auto_parser.h"
35 struct auto_pin_cfg autocfg
;
36 struct hda_multi_out multiout
;
37 hda_nid_t out_pins
[AUTO_CFG_MAX_OUTS
];
38 hda_nid_t dacs
[AUTO_CFG_MAX_OUTS
];
40 hda_nid_t input_pins
[AUTO_PIN_LAST
];
41 hda_nid_t adcs
[AUTO_PIN_LAST
];
44 unsigned int num_inputs
;
45 char input_labels
[AUTO_PIN_LAST
][32];
46 struct hda_pcm pcm_rec
[2]; /* PCM information */
52 static int ca0110_playback_pcm_open(struct hda_pcm_stream
*hinfo
,
53 struct hda_codec
*codec
,
54 struct snd_pcm_substream
*substream
)
56 struct ca0110_spec
*spec
= codec
->spec
;
57 return snd_hda_multi_out_analog_open(codec
, &spec
->multiout
, substream
,
61 static int ca0110_playback_pcm_prepare(struct hda_pcm_stream
*hinfo
,
62 struct hda_codec
*codec
,
63 unsigned int stream_tag
,
65 struct snd_pcm_substream
*substream
)
67 struct ca0110_spec
*spec
= codec
->spec
;
68 return snd_hda_multi_out_analog_prepare(codec
, &spec
->multiout
,
69 stream_tag
, format
, substream
);
72 static int ca0110_playback_pcm_cleanup(struct hda_pcm_stream
*hinfo
,
73 struct hda_codec
*codec
,
74 struct snd_pcm_substream
*substream
)
76 struct ca0110_spec
*spec
= codec
->spec
;
77 return snd_hda_multi_out_analog_cleanup(codec
, &spec
->multiout
);
83 static int ca0110_dig_playback_pcm_open(struct hda_pcm_stream
*hinfo
,
84 struct hda_codec
*codec
,
85 struct snd_pcm_substream
*substream
)
87 struct ca0110_spec
*spec
= codec
->spec
;
88 return snd_hda_multi_out_dig_open(codec
, &spec
->multiout
);
91 static int ca0110_dig_playback_pcm_close(struct hda_pcm_stream
*hinfo
,
92 struct hda_codec
*codec
,
93 struct snd_pcm_substream
*substream
)
95 struct ca0110_spec
*spec
= codec
->spec
;
96 return snd_hda_multi_out_dig_close(codec
, &spec
->multiout
);
99 static int ca0110_dig_playback_pcm_prepare(struct hda_pcm_stream
*hinfo
,
100 struct hda_codec
*codec
,
101 unsigned int stream_tag
,
103 struct snd_pcm_substream
*substream
)
105 struct ca0110_spec
*spec
= codec
->spec
;
106 return snd_hda_multi_out_dig_prepare(codec
, &spec
->multiout
, stream_tag
,
113 static int ca0110_capture_pcm_prepare(struct hda_pcm_stream
*hinfo
,
114 struct hda_codec
*codec
,
115 unsigned int stream_tag
,
117 struct snd_pcm_substream
*substream
)
119 struct ca0110_spec
*spec
= codec
->spec
;
121 snd_hda_codec_setup_stream(codec
, spec
->adcs
[substream
->number
],
122 stream_tag
, 0, format
);
126 static int ca0110_capture_pcm_cleanup(struct hda_pcm_stream
*hinfo
,
127 struct hda_codec
*codec
,
128 struct snd_pcm_substream
*substream
)
130 struct ca0110_spec
*spec
= codec
->spec
;
132 snd_hda_codec_cleanup_stream(codec
, spec
->adcs
[substream
->number
]);
139 static const char * const dirstr
[2] = { "Playback", "Capture" };
141 static int _add_switch(struct hda_codec
*codec
, hda_nid_t nid
, const char *pfx
,
145 int type
= dir
? HDA_INPUT
: HDA_OUTPUT
;
146 struct snd_kcontrol_new knew
=
147 HDA_CODEC_MUTE_MONO(namestr
, nid
, chan
, 0, type
);
148 sprintf(namestr
, "%s %s Switch", pfx
, dirstr
[dir
]);
149 return snd_hda_ctl_add(codec
, nid
, snd_ctl_new1(&knew
, codec
));
152 static int _add_volume(struct hda_codec
*codec
, hda_nid_t nid
, const char *pfx
,
156 int type
= dir
? HDA_INPUT
: HDA_OUTPUT
;
157 struct snd_kcontrol_new knew
=
158 HDA_CODEC_VOLUME_MONO(namestr
, nid
, chan
, 0, type
);
159 sprintf(namestr
, "%s %s Volume", pfx
, dirstr
[dir
]);
160 return snd_hda_ctl_add(codec
, nid
, snd_ctl_new1(&knew
, codec
));
163 #define add_out_switch(codec, nid, pfx) _add_switch(codec, nid, pfx, 3, 0)
164 #define add_out_volume(codec, nid, pfx) _add_volume(codec, nid, pfx, 3, 0)
165 #define add_in_switch(codec, nid, pfx) _add_switch(codec, nid, pfx, 3, 1)
166 #define add_in_volume(codec, nid, pfx) _add_volume(codec, nid, pfx, 3, 1)
167 #define add_mono_switch(codec, nid, pfx, chan) \
168 _add_switch(codec, nid, pfx, chan, 0)
169 #define add_mono_volume(codec, nid, pfx, chan) \
170 _add_volume(codec, nid, pfx, chan, 0)
172 static int ca0110_build_controls(struct hda_codec
*codec
)
174 struct ca0110_spec
*spec
= codec
->spec
;
175 struct auto_pin_cfg
*cfg
= &spec
->autocfg
;
176 static const char * const prefix
[AUTO_CFG_MAX_OUTS
] = {
177 "Front", "Surround", NULL
, "Side", "Multi"
182 for (i
= 0; i
< spec
->multiout
.num_dacs
; i
++) {
183 if (get_wcaps(codec
, spec
->out_pins
[i
]) & AC_WCAP_OUT_AMP
)
184 mutenid
= spec
->out_pins
[i
];
186 mutenid
= spec
->multiout
.dac_nids
[i
];
188 err
= add_mono_switch(codec
, mutenid
,
192 err
= add_mono_switch(codec
, mutenid
,
196 err
= add_mono_volume(codec
, spec
->multiout
.dac_nids
[i
],
200 err
= add_mono_volume(codec
, spec
->multiout
.dac_nids
[i
],
205 err
= add_out_switch(codec
, mutenid
,
209 err
= add_out_volume(codec
, spec
->multiout
.dac_nids
[i
],
216 if (get_wcaps(codec
, cfg
->hp_pins
[0]) & AC_WCAP_OUT_AMP
)
217 mutenid
= cfg
->hp_pins
[0];
219 mutenid
= spec
->multiout
.dac_nids
[i
];
221 err
= add_out_switch(codec
, mutenid
, "Headphone");
225 err
= add_out_volume(codec
, spec
->hp_dac
, "Headphone");
230 for (i
= 0; i
< spec
->num_inputs
; i
++) {
231 const char *label
= spec
->input_labels
[i
];
232 if (get_wcaps(codec
, spec
->input_pins
[i
]) & AC_WCAP_IN_AMP
)
233 mutenid
= spec
->input_pins
[i
];
235 mutenid
= spec
->adcs
[i
];
236 err
= add_in_switch(codec
, mutenid
, label
);
239 err
= add_in_volume(codec
, spec
->adcs
[i
], label
);
245 err
= snd_hda_create_spdif_out_ctls(codec
, spec
->dig_out
,
249 err
= snd_hda_create_spdif_share_sw(codec
, &spec
->multiout
);
252 spec
->multiout
.share_spdif
= 1;
255 err
= snd_hda_create_spdif_in_ctls(codec
, spec
->dig_in
);
258 err
= add_in_volume(codec
, spec
->dig_in
, "IEC958");
265 static const struct hda_pcm_stream ca0110_pcm_analog_playback
= {
270 .open
= ca0110_playback_pcm_open
,
271 .prepare
= ca0110_playback_pcm_prepare
,
272 .cleanup
= ca0110_playback_pcm_cleanup
276 static const struct hda_pcm_stream ca0110_pcm_analog_capture
= {
281 .prepare
= ca0110_capture_pcm_prepare
,
282 .cleanup
= ca0110_capture_pcm_cleanup
286 static const struct hda_pcm_stream ca0110_pcm_digital_playback
= {
291 .open
= ca0110_dig_playback_pcm_open
,
292 .close
= ca0110_dig_playback_pcm_close
,
293 .prepare
= ca0110_dig_playback_pcm_prepare
297 static const struct hda_pcm_stream ca0110_pcm_digital_capture
= {
303 static int ca0110_build_pcms(struct hda_codec
*codec
)
305 struct ca0110_spec
*spec
= codec
->spec
;
306 struct hda_pcm
*info
= spec
->pcm_rec
;
308 codec
->pcm_info
= info
;
311 info
->name
= "CA0110 Analog";
312 info
->stream
[SNDRV_PCM_STREAM_PLAYBACK
] = ca0110_pcm_analog_playback
;
313 info
->stream
[SNDRV_PCM_STREAM_PLAYBACK
].nid
= spec
->dacs
[0];
314 info
->stream
[SNDRV_PCM_STREAM_PLAYBACK
].channels_max
=
315 spec
->multiout
.max_channels
;
316 info
->stream
[SNDRV_PCM_STREAM_CAPTURE
] = ca0110_pcm_analog_capture
;
317 info
->stream
[SNDRV_PCM_STREAM_CAPTURE
].substreams
= spec
->num_inputs
;
318 info
->stream
[SNDRV_PCM_STREAM_CAPTURE
].nid
= spec
->adcs
[0];
321 if (!spec
->dig_out
&& !spec
->dig_in
)
325 info
->name
= "CA0110 Digital";
326 info
->pcm_type
= HDA_PCM_TYPE_SPDIF
;
328 info
->stream
[SNDRV_PCM_STREAM_PLAYBACK
] =
329 ca0110_pcm_digital_playback
;
330 info
->stream
[SNDRV_PCM_STREAM_PLAYBACK
].nid
= spec
->dig_out
;
333 info
->stream
[SNDRV_PCM_STREAM_CAPTURE
] =
334 ca0110_pcm_digital_capture
;
335 info
->stream
[SNDRV_PCM_STREAM_CAPTURE
].nid
= spec
->dig_in
;
342 static void init_output(struct hda_codec
*codec
, hda_nid_t pin
, hda_nid_t dac
)
345 snd_hda_set_pin_ctl(codec
, pin
, 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_set_pin_ctl(codec
, pin
, PIN_IN
|
360 snd_hda_get_default_vref(codec
, pin
));
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
)