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 char *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 char *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
);
246 err
= snd_hda_create_spdif_share_sw(codec
, &spec
->multiout
);
249 spec
->multiout
.share_spdif
= 1;
252 err
= snd_hda_create_spdif_in_ctls(codec
, spec
->dig_in
);
255 err
= add_in_volume(codec
, spec
->dig_in
, "IEC958");
262 static struct hda_pcm_stream ca0110_pcm_analog_playback
= {
267 .open
= ca0110_playback_pcm_open
,
268 .prepare
= ca0110_playback_pcm_prepare
,
269 .cleanup
= ca0110_playback_pcm_cleanup
273 static struct hda_pcm_stream ca0110_pcm_analog_capture
= {
278 .prepare
= ca0110_capture_pcm_prepare
,
279 .cleanup
= ca0110_capture_pcm_cleanup
283 static struct hda_pcm_stream ca0110_pcm_digital_playback
= {
288 .open
= ca0110_dig_playback_pcm_open
,
289 .close
= ca0110_dig_playback_pcm_close
,
290 .prepare
= ca0110_dig_playback_pcm_prepare
294 static struct hda_pcm_stream ca0110_pcm_digital_capture
= {
300 static int ca0110_build_pcms(struct hda_codec
*codec
)
302 struct ca0110_spec
*spec
= codec
->spec
;
303 struct hda_pcm
*info
= spec
->pcm_rec
;
305 codec
->pcm_info
= info
;
308 info
->name
= "CA0110 Analog";
309 info
->stream
[SNDRV_PCM_STREAM_PLAYBACK
] = ca0110_pcm_analog_playback
;
310 info
->stream
[SNDRV_PCM_STREAM_PLAYBACK
].nid
= spec
->dacs
[0];
311 info
->stream
[SNDRV_PCM_STREAM_PLAYBACK
].channels_max
=
312 spec
->multiout
.max_channels
;
313 info
->stream
[SNDRV_PCM_STREAM_CAPTURE
] = ca0110_pcm_analog_capture
;
314 info
->stream
[SNDRV_PCM_STREAM_CAPTURE
].substreams
= spec
->num_inputs
;
315 info
->stream
[SNDRV_PCM_STREAM_CAPTURE
].nid
= spec
->adcs
[0];
318 if (!spec
->dig_out
&& !spec
->dig_in
)
322 info
->name
= "CA0110 Digital";
323 info
->pcm_type
= HDA_PCM_TYPE_SPDIF
;
325 info
->stream
[SNDRV_PCM_STREAM_PLAYBACK
] =
326 ca0110_pcm_digital_playback
;
327 info
->stream
[SNDRV_PCM_STREAM_PLAYBACK
].nid
= spec
->dig_out
;
330 info
->stream
[SNDRV_PCM_STREAM_CAPTURE
] =
331 ca0110_pcm_digital_capture
;
332 info
->stream
[SNDRV_PCM_STREAM_CAPTURE
].nid
= spec
->dig_in
;
339 static void init_output(struct hda_codec
*codec
, hda_nid_t pin
, hda_nid_t dac
)
342 snd_hda_codec_write(codec
, pin
, 0,
343 AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_HP
);
344 if (get_wcaps(codec
, pin
) & AC_WCAP_OUT_AMP
)
345 snd_hda_codec_write(codec
, pin
, 0,
346 AC_VERB_SET_AMP_GAIN_MUTE
,
350 snd_hda_codec_write(codec
, dac
, 0,
351 AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
);
354 static void init_input(struct hda_codec
*codec
, hda_nid_t pin
, hda_nid_t adc
)
357 snd_hda_codec_write(codec
, pin
, 0,
358 AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_VREF80
);
359 if (get_wcaps(codec
, pin
) & AC_WCAP_IN_AMP
)
360 snd_hda_codec_write(codec
, pin
, 0,
361 AC_VERB_SET_AMP_GAIN_MUTE
,
365 snd_hda_codec_write(codec
, adc
, 0, AC_VERB_SET_AMP_GAIN_MUTE
,
369 static int ca0110_init(struct hda_codec
*codec
)
371 struct ca0110_spec
*spec
= codec
->spec
;
372 struct auto_pin_cfg
*cfg
= &spec
->autocfg
;
375 for (i
= 0; i
< spec
->multiout
.num_dacs
; i
++)
376 init_output(codec
, spec
->out_pins
[i
],
377 spec
->multiout
.dac_nids
[i
]);
378 init_output(codec
, cfg
->hp_pins
[0], spec
->hp_dac
);
379 init_output(codec
, cfg
->dig_out_pins
[0], spec
->dig_out
);
381 for (i
= 0; i
< spec
->num_inputs
; i
++)
382 init_input(codec
, spec
->input_pins
[i
], spec
->adcs
[i
]);
383 init_input(codec
, cfg
->dig_in_pin
, spec
->dig_in
);
387 static void ca0110_free(struct hda_codec
*codec
)
392 static struct hda_codec_ops ca0110_patch_ops
= {
393 .build_controls
= ca0110_build_controls
,
394 .build_pcms
= ca0110_build_pcms
,
400 static void parse_line_outs(struct hda_codec
*codec
)
402 struct ca0110_spec
*spec
= codec
->spec
;
403 struct auto_pin_cfg
*cfg
= &spec
->autocfg
;
405 unsigned int def_conf
;
409 for (i
= 0; i
< cfg
->line_outs
; i
++) {
410 nid
= cfg
->line_out_pins
[i
];
411 def_conf
= snd_hda_codec_get_pincfg(codec
, nid
);
413 continue; /* invalid pin */
414 if (snd_hda_get_connections(codec
, nid
, &spec
->dacs
[i
], 1) != 1)
416 spec
->out_pins
[n
++] = nid
;
418 spec
->multiout
.dac_nids
= spec
->dacs
;
419 spec
->multiout
.num_dacs
= n
;
420 spec
->multiout
.max_channels
= n
* 2;
423 static void parse_hp_out(struct hda_codec
*codec
)
425 struct ca0110_spec
*spec
= codec
->spec
;
426 struct auto_pin_cfg
*cfg
= &spec
->autocfg
;
428 unsigned int def_conf
;
433 nid
= cfg
->hp_pins
[0];
434 def_conf
= snd_hda_codec_get_pincfg(codec
, nid
);
439 if (snd_hda_get_connections(codec
, nid
, &dac
, 1) != 1)
442 for (i
= 0; i
< cfg
->line_outs
; i
++)
443 if (dac
== spec
->dacs
[i
])
445 if (i
>= cfg
->line_outs
) {
447 spec
->multiout
.hp_nid
= dac
;
451 static void parse_input(struct hda_codec
*codec
)
453 struct ca0110_spec
*spec
= codec
->spec
;
454 struct auto_pin_cfg
*cfg
= &spec
->autocfg
;
459 nid
= codec
->start_nid
;
460 for (i
= 0; i
< codec
->num_nodes
; i
++, nid
++) {
461 unsigned int wcaps
= get_wcaps(codec
, nid
);
462 unsigned int type
= get_wcaps_type(wcaps
);
463 if (type
!= AC_WID_AUD_IN
)
465 if (snd_hda_get_connections(codec
, nid
, &pin
, 1) != 1)
467 if (pin
== cfg
->dig_in_pin
) {
471 for (j
= 0; j
< cfg
->num_inputs
; j
++)
472 if (cfg
->inputs
[j
].pin
== pin
)
474 if (j
>= cfg
->num_inputs
)
476 spec
->input_pins
[n
] = pin
;
477 spec
->input_labels
[n
] = hda_get_input_pin_label(codec
, pin
, 1);
481 spec
->num_inputs
= n
;
484 static void parse_digital(struct hda_codec
*codec
)
486 struct ca0110_spec
*spec
= codec
->spec
;
487 struct auto_pin_cfg
*cfg
= &spec
->autocfg
;
490 snd_hda_get_connections(codec
, cfg
->dig_out_pins
[0],
491 &spec
->dig_out
, 1) == 1)
492 spec
->multiout
.dig_out_nid
= spec
->dig_out
;
495 static int ca0110_parse_auto_config(struct hda_codec
*codec
)
497 struct ca0110_spec
*spec
= codec
->spec
;
500 err
= snd_hda_parse_pin_def_config(codec
, &spec
->autocfg
, NULL
);
504 parse_line_outs(codec
);
506 parse_digital(codec
);
512 static int patch_ca0110(struct hda_codec
*codec
)
514 struct ca0110_spec
*spec
;
517 spec
= kzalloc(sizeof(*spec
), GFP_KERNEL
);
522 codec
->bus
->needs_damn_long_delay
= 1;
524 err
= ca0110_parse_auto_config(codec
);
528 codec
->patch_ops
= ca0110_patch_ops
;
542 static struct hda_codec_preset snd_hda_preset_ca0110
[] = {
543 { .id
= 0x1102000a, .name
= "CA0110-IBG", .patch
= patch_ca0110
},
544 { .id
= 0x1102000b, .name
= "CA0110-IBG", .patch
= patch_ca0110
},
545 { .id
= 0x1102000d, .name
= "SB0880 X-Fi", .patch
= patch_ca0110
},
549 MODULE_ALIAS("snd-hda-codec-id:1102000a");
550 MODULE_ALIAS("snd-hda-codec-id:1102000b");
551 MODULE_ALIAS("snd-hda-codec-id:1102000d");
553 MODULE_LICENSE("GPL");
554 MODULE_DESCRIPTION("Creative CA0110-IBG HD-audio codec");
556 static struct hda_codec_preset_list ca0110_list
= {
557 .preset
= snd_hda_preset_ca0110
,
558 .owner
= THIS_MODULE
,
561 static int __init
patch_ca0110_init(void)
563 return snd_hda_add_codec_preset(&ca0110_list
);
566 static void __exit
patch_ca0110_exit(void)
568 snd_hda_delete_codec_preset(&ca0110_list
);
571 module_init(patch_ca0110_init
)
572 module_exit(patch_ca0110_exit
)