1d0fa1179SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
24e01f54bSTakashi Iwai /*
34e01f54bSTakashi Iwai * HD audio interface patch for Creative X-Fi CA0110-IBG chip
44e01f54bSTakashi Iwai *
54e01f54bSTakashi Iwai * Copyright (c) 2008 Takashi Iwai <tiwai@suse.de>
64e01f54bSTakashi Iwai */
74e01f54bSTakashi Iwai
84e01f54bSTakashi Iwai #include <linux/init.h>
94e01f54bSTakashi Iwai #include <linux/slab.h>
10da155d5bSPaul Gortmaker #include <linux/module.h>
114e01f54bSTakashi Iwai #include <sound/core.h>
12be57bfffSPierre-Louis Bossart #include <sound/hda_codec.h>
134e01f54bSTakashi Iwai #include "hda_local.h"
14128bc4baSTakashi Iwai #include "hda_auto_parser.h"
158fadf1daSTakashi Iwai #include "hda_jack.h"
168fadf1daSTakashi Iwai #include "hda_generic.h"
174e01f54bSTakashi Iwai
184e01f54bSTakashi Iwai
19728850a7STakashi Iwai static const struct hda_codec_ops ca0110_patch_ops = {
208fadf1daSTakashi Iwai .build_controls = snd_hda_gen_build_controls,
218fadf1daSTakashi Iwai .build_pcms = snd_hda_gen_build_pcms,
228fadf1daSTakashi Iwai .init = snd_hda_gen_init,
238fadf1daSTakashi Iwai .free = snd_hda_gen_free,
248a6c21aeSTakashi Iwai .unsol_event = snd_hda_jack_unsol_event,
254e01f54bSTakashi Iwai };
264e01f54bSTakashi Iwai
ca0110_parse_auto_config(struct hda_codec * codec)274e01f54bSTakashi Iwai static int ca0110_parse_auto_config(struct hda_codec *codec)
284e01f54bSTakashi Iwai {
298fadf1daSTakashi Iwai struct hda_gen_spec *spec = codec->spec;
304e01f54bSTakashi Iwai int err;
314e01f54bSTakashi Iwai
328fadf1daSTakashi Iwai err = snd_hda_parse_pin_defcfg(codec, &spec->autocfg, NULL, 0);
338fadf1daSTakashi Iwai if (err < 0)
348fadf1daSTakashi Iwai return err;
358fadf1daSTakashi Iwai err = snd_hda_gen_parse_auto_config(codec, &spec->autocfg);
364e01f54bSTakashi Iwai if (err < 0)
374e01f54bSTakashi Iwai return err;
384e01f54bSTakashi Iwai
394e01f54bSTakashi Iwai return 0;
404e01f54bSTakashi Iwai }
414e01f54bSTakashi Iwai
424e01f54bSTakashi Iwai
patch_ca0110(struct hda_codec * codec)431e168953STakashi Iwai static int patch_ca0110(struct hda_codec *codec)
444e01f54bSTakashi Iwai {
458fadf1daSTakashi Iwai struct hda_gen_spec *spec;
464e01f54bSTakashi Iwai int err;
474e01f54bSTakashi Iwai
484e01f54bSTakashi Iwai spec = kzalloc(sizeof(*spec), GFP_KERNEL);
494e01f54bSTakashi Iwai if (!spec)
504e01f54bSTakashi Iwai return -ENOMEM;
518fadf1daSTakashi Iwai snd_hda_gen_spec_init(spec);
524e01f54bSTakashi Iwai codec->spec = spec;
53225068abSTakashi Iwai codec->patch_ops = ca0110_patch_ops;
544e01f54bSTakashi Iwai
558fadf1daSTakashi Iwai spec->multi_cap_vol = 1;
56*5f2cb361STakashi Iwai codec->bus->core.needs_damn_long_delay = 1;
574e01f54bSTakashi Iwai
584e01f54bSTakashi Iwai err = ca0110_parse_auto_config(codec);
594e01f54bSTakashi Iwai if (err < 0)
604e01f54bSTakashi Iwai goto error;
614e01f54bSTakashi Iwai
624e01f54bSTakashi Iwai return 0;
634e01f54bSTakashi Iwai
644e01f54bSTakashi Iwai error:
658fadf1daSTakashi Iwai snd_hda_gen_free(codec);
664e01f54bSTakashi Iwai return err;
674e01f54bSTakashi Iwai }
684e01f54bSTakashi Iwai
694e01f54bSTakashi Iwai
704e01f54bSTakashi Iwai /*
714e01f54bSTakashi Iwai * patch entries
724e01f54bSTakashi Iwai */
73b9a94a9cSTakashi Iwai static const struct hda_device_id snd_hda_id_ca0110[] = {
74b9a94a9cSTakashi Iwai HDA_CODEC_ENTRY(0x1102000a, "CA0110-IBG", patch_ca0110),
75b9a94a9cSTakashi Iwai HDA_CODEC_ENTRY(0x1102000b, "CA0110-IBG", patch_ca0110),
76b9a94a9cSTakashi Iwai HDA_CODEC_ENTRY(0x1102000d, "SB0880 X-Fi", patch_ca0110),
774e01f54bSTakashi Iwai {} /* terminator */
784e01f54bSTakashi Iwai };
79b9a94a9cSTakashi Iwai MODULE_DEVICE_TABLE(hdaudio, snd_hda_id_ca0110);
804e01f54bSTakashi Iwai
814e01f54bSTakashi Iwai MODULE_LICENSE("GPL");
824e01f54bSTakashi Iwai MODULE_DESCRIPTION("Creative CA0110-IBG HD-audio codec");
834e01f54bSTakashi Iwai
84d8a766a1STakashi Iwai static struct hda_codec_driver ca0110_driver = {
85b9a94a9cSTakashi Iwai .id = snd_hda_id_ca0110,
864e01f54bSTakashi Iwai };
874e01f54bSTakashi Iwai
88d8a766a1STakashi Iwai module_hda_codec_driver(ca0110_driver);
89