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 <sound/core.h>
26 #include "hda_codec.h"
27 #include "hda_local.h"
33 struct auto_pin_cfg autocfg
;
34 struct hda_multi_out multiout
;
35 hda_nid_t out_pins
[AUTO_CFG_MAX_OUTS
];
36 hda_nid_t dacs
[AUTO_CFG_MAX_OUTS
];
38 hda_nid_t input_pins
[AUTO_PIN_LAST
];
39 hda_nid_t adcs
[AUTO_PIN_LAST
];
42 unsigned int num_inputs
;
43 const char *input_labels
[AUTO_PIN_LAST
];
44 struct hda_pcm pcm_rec
[2]; /* PCM information */
50 static int ca0110_playback_pcm_open(struct hda_pcm_stream
*hinfo
,
51 struct hda_codec
*codec
,
52 struct snd_pcm_substream
*substream
)
54 struct ca0110_spec
*spec
= codec
->spec
;
55 return snd_hda_multi_out_analog_open(codec
, &spec
->multiout
, substream
,
59 static int ca0110_playback_pcm_prepare(struct hda_pcm_stream
*hinfo
,
60 struct hda_codec
*codec
,
61 unsigned int stream_tag
,
63 struct snd_pcm_substream
*substream
)
65 struct ca0110_spec
*spec
= codec
->spec
;
66 return snd_hda_multi_out_analog_prepare(codec
, &spec
->multiout
,
67 stream_tag
, format
, substream
);
70 static int ca0110_playback_pcm_cleanup(struct hda_pcm_stream
*hinfo
,
71 struct hda_codec
*codec
,
72 struct snd_pcm_substream
*substream
)
74 struct ca0110_spec
*spec
= codec
->spec
;
75 return snd_hda_multi_out_analog_cleanup(codec
, &spec
->multiout
);
81 static int ca0110_dig_playback_pcm_open(struct hda_pcm_stream
*hinfo
,
82 struct hda_codec
*codec
,
83 struct snd_pcm_substream
*substream
)
85 struct ca0110_spec
*spec
= codec
->spec
;
86 return snd_hda_multi_out_dig_open(codec
, &spec
->multiout
);
89 static int ca0110_dig_playback_pcm_close(struct hda_pcm_stream
*hinfo
,
90 struct hda_codec
*codec
,
91 struct snd_pcm_substream
*substream
)
93 struct ca0110_spec
*spec
= codec
->spec
;
94 return snd_hda_multi_out_dig_close(codec
, &spec
->multiout
);
97 static int ca0110_dig_playback_pcm_prepare(struct hda_pcm_stream
*hinfo
,
98 struct hda_codec
*codec
,
99 unsigned int stream_tag
,
101 struct snd_pcm_substream
*substream
)
103 struct ca0110_spec
*spec
= codec
->spec
;
104 return snd_hda_multi_out_dig_prepare(codec
, &spec
->multiout
, stream_tag
,
111 static int ca0110_capture_pcm_prepare(struct hda_pcm_stream
*hinfo
,
112 struct hda_codec
*codec
,
113 unsigned int stream_tag
,
115 struct snd_pcm_substream
*substream
)
117 struct ca0110_spec
*spec
= codec
->spec
;
119 snd_hda_codec_setup_stream(codec
, spec
->adcs
[substream
->number
],
120 stream_tag
, 0, format
);
124 static int ca0110_capture_pcm_cleanup(struct hda_pcm_stream
*hinfo
,
125 struct hda_codec
*codec
,
126 struct snd_pcm_substream
*substream
)
128 struct ca0110_spec
*spec
= codec
->spec
;
130 snd_hda_codec_cleanup_stream(codec
, spec
->adcs
[substream
->number
]);
137 static const char * const dirstr
[2] = { "Playback", "Capture" };
139 static int _add_switch(struct hda_codec
*codec
, hda_nid_t nid
, const char *pfx
,
143 int type
= dir
? HDA_INPUT
: HDA_OUTPUT
;
144 struct snd_kcontrol_new knew
=
145 HDA_CODEC_MUTE_MONO(namestr
, nid
, chan
, 0, type
);
146 sprintf(namestr
, "%s %s Switch", pfx
, dirstr
[dir
]);
147 return snd_hda_ctl_add(codec
, nid
, snd_ctl_new1(&knew
, codec
));
150 static int _add_volume(struct hda_codec
*codec
, hda_nid_t nid
, const char *pfx
,
154 int type
= dir
? HDA_INPUT
: HDA_OUTPUT
;
155 struct snd_kcontrol_new knew
=
156 HDA_CODEC_VOLUME_MONO(namestr
, nid
, chan
, 0, type
);
157 sprintf(namestr
, "%s %s Volume", pfx
, dirstr
[dir
]);
158 return snd_hda_ctl_add(codec
, nid
, snd_ctl_new1(&knew
, codec
));
161 #define add_out_switch(codec, nid, pfx) _add_switch(codec, nid, pfx, 3, 0)
162 #define add_out_volume(codec, nid, pfx) _add_volume(codec, nid, pfx, 3, 0)
163 #define add_in_switch(codec, nid, pfx) _add_switch(codec, nid, pfx, 3, 1)
164 #define add_in_volume(codec, nid, pfx) _add_volume(codec, nid, pfx, 3, 1)
165 #define add_mono_switch(codec, nid, pfx, chan) \
166 _add_switch(codec, nid, pfx, chan, 0)
167 #define add_mono_volume(codec, nid, pfx, chan) \
168 _add_volume(codec, nid, pfx, chan, 0)
170 static int ca0110_build_controls(struct hda_codec
*codec
)
172 struct ca0110_spec
*spec
= codec
->spec
;
173 struct auto_pin_cfg
*cfg
= &spec
->autocfg
;
174 static const char * const prefix
[AUTO_CFG_MAX_OUTS
] = {
175 "Front", "Surround", NULL
, "Side", "Multi"
180 for (i
= 0; i
< spec
->multiout
.num_dacs
; i
++) {
181 if (get_wcaps(codec
, spec
->out_pins
[i
]) & AC_WCAP_OUT_AMP
)
182 mutenid
= spec
->out_pins
[i
];
184 mutenid
= spec
->multiout
.dac_nids
[i
];
186 err
= add_mono_switch(codec
, mutenid
,
190 err
= add_mono_switch(codec
, mutenid
,
194 err
= add_mono_volume(codec
, spec
->multiout
.dac_nids
[i
],
198 err
= add_mono_volume(codec
, spec
->multiout
.dac_nids
[i
],
203 err
= add_out_switch(codec
, mutenid
,
207 err
= add_out_volume(codec
, spec
->multiout
.dac_nids
[i
],
214 if (get_wcaps(codec
, cfg
->hp_pins
[0]) & AC_WCAP_OUT_AMP
)
215 mutenid
= cfg
->hp_pins
[0];
217 mutenid
= spec
->multiout
.dac_nids
[i
];
219 err
= add_out_switch(codec
, mutenid
, "Headphone");
223 err
= add_out_volume(codec
, spec
->hp_dac
, "Headphone");
228 for (i
= 0; i
< spec
->num_inputs
; i
++) {
229 const char *label
= spec
->input_labels
[i
];
230 if (get_wcaps(codec
, spec
->input_pins
[i
]) & AC_WCAP_IN_AMP
)
231 mutenid
= spec
->input_pins
[i
];
233 mutenid
= spec
->adcs
[i
];
234 err
= add_in_switch(codec
, mutenid
, label
);
237 err
= add_in_volume(codec
, spec
->adcs
[i
], label
);
243 err
= snd_hda_create_spdif_out_ctls(codec
, spec
->dig_out
,
247 err
= snd_hda_create_spdif_share_sw(codec
, &spec
->multiout
);
250 spec
->multiout
.share_spdif
= 1;
253 err
= snd_hda_create_spdif_in_ctls(codec
, spec
->dig_in
);
256 err
= add_in_volume(codec
, spec
->dig_in
, "IEC958");
263 static const struct hda_pcm_stream ca0110_pcm_analog_playback
= {
268 .open
= ca0110_playback_pcm_open
,
269 .prepare
= ca0110_playback_pcm_prepare
,
270 .cleanup
= ca0110_playback_pcm_cleanup
274 static const struct hda_pcm_stream ca0110_pcm_analog_capture
= {
279 .prepare
= ca0110_capture_pcm_prepare
,
280 .cleanup
= ca0110_capture_pcm_cleanup
284 static const struct hda_pcm_stream ca0110_pcm_digital_playback
= {
289 .open
= ca0110_dig_playback_pcm_open
,
290 .close
= ca0110_dig_playback_pcm_close
,
291 .prepare
= ca0110_dig_playback_pcm_prepare
295 static const struct hda_pcm_stream ca0110_pcm_digital_capture
= {
301 static int ca0110_build_pcms(struct hda_codec
*codec
)
303 struct ca0110_spec
*spec
= codec
->spec
;
304 struct hda_pcm
*info
= spec
->pcm_rec
;
306 codec
->pcm_info
= info
;
309 info
->name
= "CA0110 Analog";
310 info
->stream
[SNDRV_PCM_STREAM_PLAYBACK
] = ca0110_pcm_analog_playback
;
311 info
->stream
[SNDRV_PCM_STREAM_PLAYBACK
].nid
= spec
->dacs
[0];
312 info
->stream
[SNDRV_PCM_STREAM_PLAYBACK
].channels_max
=
313 spec
->multiout
.max_channels
;
314 info
->stream
[SNDRV_PCM_STREAM_CAPTURE
] = ca0110_pcm_analog_capture
;
315 info
->stream
[SNDRV_PCM_STREAM_CAPTURE
].substreams
= spec
->num_inputs
;
316 info
->stream
[SNDRV_PCM_STREAM_CAPTURE
].nid
= spec
->adcs
[0];
319 if (!spec
->dig_out
&& !spec
->dig_in
)
323 info
->name
= "CA0110 Digital";
324 info
->pcm_type
= HDA_PCM_TYPE_SPDIF
;
326 info
->stream
[SNDRV_PCM_STREAM_PLAYBACK
] =
327 ca0110_pcm_digital_playback
;
328 info
->stream
[SNDRV_PCM_STREAM_PLAYBACK
].nid
= spec
->dig_out
;
331 info
->stream
[SNDRV_PCM_STREAM_CAPTURE
] =
332 ca0110_pcm_digital_capture
;
333 info
->stream
[SNDRV_PCM_STREAM_CAPTURE
].nid
= spec
->dig_in
;
340 static void init_output(struct hda_codec
*codec
, hda_nid_t pin
, hda_nid_t dac
)
343 snd_hda_codec_write(codec
, pin
, 0,
344 AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_HP
);
345 if (get_wcaps(codec
, pin
) & AC_WCAP_OUT_AMP
)
346 snd_hda_codec_write(codec
, pin
, 0,
347 AC_VERB_SET_AMP_GAIN_MUTE
,
351 snd_hda_codec_write(codec
, dac
, 0,
352 AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
);
355 static void init_input(struct hda_codec
*codec
, hda_nid_t pin
, hda_nid_t adc
)
358 snd_hda_codec_write(codec
, pin
, 0,
359 AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
);
360 if (get_wcaps(codec
, pin
) & AC_WCAP_IN_AMP
)
361 snd_hda_codec_write(codec
, pin
, 0,
362 AC_VERB_SET_AMP_GAIN_MUTE
,
366 snd_hda_codec_write(codec
, adc
, 0, AC_VERB_SET_AMP_GAIN_MUTE
,
370 static int ca0110_init(struct hda_codec
*codec
)
372 struct ca0110_spec
*spec
= codec
->spec
;
373 struct auto_pin_cfg
*cfg
= &spec
->autocfg
;
376 for (i
= 0; i
< spec
->multiout
.num_dacs
; i
++)
377 init_output(codec
, spec
->out_pins
[i
],
378 spec
->multiout
.dac_nids
[i
]);
379 init_output(codec
, cfg
->hp_pins
[0], spec
->hp_dac
);
380 init_output(codec
, cfg
->dig_out_pins
[0], spec
->dig_out
);
382 for (i
= 0; i
< spec
->num_inputs
; i
++)
383 init_input(codec
, spec
->input_pins
[i
], spec
->adcs
[i
]);
384 init_input(codec
, cfg
->dig_in_pin
, spec
->dig_in
);
388 static void ca0110_free(struct hda_codec
*codec
)
393 static const struct hda_codec_ops ca0110_patch_ops
= {
394 .build_controls
= ca0110_build_controls
,
395 .build_pcms
= ca0110_build_pcms
,
401 static void parse_line_outs(struct hda_codec
*codec
)
403 struct ca0110_spec
*spec
= codec
->spec
;
404 struct auto_pin_cfg
*cfg
= &spec
->autocfg
;
406 unsigned int def_conf
;
410 for (i
= 0; i
< cfg
->line_outs
; i
++) {
411 nid
= cfg
->line_out_pins
[i
];
412 def_conf
= snd_hda_codec_get_pincfg(codec
, nid
);
414 continue; /* invalid pin */
415 if (snd_hda_get_connections(codec
, nid
, &spec
->dacs
[i
], 1) != 1)
417 spec
->out_pins
[n
++] = nid
;
419 spec
->multiout
.dac_nids
= spec
->dacs
;
420 spec
->multiout
.num_dacs
= n
;
421 spec
->multiout
.max_channels
= n
* 2;
424 static void parse_hp_out(struct hda_codec
*codec
)
426 struct ca0110_spec
*spec
= codec
->spec
;
427 struct auto_pin_cfg
*cfg
= &spec
->autocfg
;
429 unsigned int def_conf
;
434 nid
= cfg
->hp_pins
[0];
435 def_conf
= snd_hda_codec_get_pincfg(codec
, nid
);
440 if (snd_hda_get_connections(codec
, nid
, &dac
, 1) != 1)
443 for (i
= 0; i
< cfg
->line_outs
; i
++)
444 if (dac
== spec
->dacs
[i
])
446 if (i
>= cfg
->line_outs
) {
448 spec
->multiout
.hp_nid
= dac
;
452 static void parse_input(struct hda_codec
*codec
)
454 struct ca0110_spec
*spec
= codec
->spec
;
455 struct auto_pin_cfg
*cfg
= &spec
->autocfg
;
460 nid
= codec
->start_nid
;
461 for (i
= 0; i
< codec
->num_nodes
; i
++, nid
++) {
462 unsigned int wcaps
= get_wcaps(codec
, nid
);
463 unsigned int type
= get_wcaps_type(wcaps
);
464 if (type
!= AC_WID_AUD_IN
)
466 if (snd_hda_get_connections(codec
, nid
, &pin
, 1) != 1)
468 if (pin
== cfg
->dig_in_pin
) {
472 for (j
= 0; j
< cfg
->num_inputs
; j
++)
473 if (cfg
->inputs
[j
].pin
== pin
)
475 if (j
>= cfg
->num_inputs
)
477 spec
->input_pins
[n
] = pin
;
478 spec
->input_labels
[n
] = hda_get_input_pin_label(codec
, pin
, 1);
482 spec
->num_inputs
= n
;
485 static void parse_digital(struct hda_codec
*codec
)
487 struct ca0110_spec
*spec
= codec
->spec
;
488 struct auto_pin_cfg
*cfg
= &spec
->autocfg
;
491 snd_hda_get_connections(codec
, cfg
->dig_out_pins
[0],
492 &spec
->dig_out
, 1) == 1)
493 spec
->multiout
.dig_out_nid
= spec
->dig_out
;
496 static int ca0110_parse_auto_config(struct hda_codec
*codec
)
498 struct ca0110_spec
*spec
= codec
->spec
;
501 err
= snd_hda_parse_pin_def_config(codec
, &spec
->autocfg
, NULL
);
505 parse_line_outs(codec
);
507 parse_digital(codec
);
513 static int patch_ca0110(struct hda_codec
*codec
)
515 struct ca0110_spec
*spec
;
518 spec
= kzalloc(sizeof(*spec
), GFP_KERNEL
);
523 codec
->bus
->needs_damn_long_delay
= 1;
525 err
= ca0110_parse_auto_config(codec
);
529 codec
->patch_ops
= ca0110_patch_ops
;
543 static const struct hda_codec_preset snd_hda_preset_ca0110
[] = {
544 { .id
= 0x1102000a, .name
= "CA0110-IBG", .patch
= patch_ca0110
},
545 { .id
= 0x1102000b, .name
= "CA0110-IBG", .patch
= patch_ca0110
},
546 { .id
= 0x1102000d, .name
= "SB0880 X-Fi", .patch
= patch_ca0110
},
550 MODULE_ALIAS("snd-hda-codec-id:1102000a");
551 MODULE_ALIAS("snd-hda-codec-id:1102000b");
552 MODULE_ALIAS("snd-hda-codec-id:1102000d");
554 MODULE_LICENSE("GPL");
555 MODULE_DESCRIPTION("Creative CA0110-IBG HD-audio codec");
557 static struct hda_codec_preset_list ca0110_list
= {
558 .preset
= snd_hda_preset_ca0110
,
559 .owner
= THIS_MODULE
,
562 static int __init
patch_ca0110_init(void)
564 return snd_hda_add_codec_preset(&ca0110_list
);
567 static void __exit
patch_ca0110_exit(void)
569 snd_hda_delete_codec_preset(&ca0110_list
);
572 module_init(patch_ca0110_init
)
573 module_exit(patch_ca0110_exit
)