16014e902STakashi Iwai // SPDX-License-Identifier: GPL-2.0-or-later 26014e902STakashi Iwai /* 3*dbe3e4abSTakashi Iwai * HD audio codec driver for Creative X-Fi CA0110-IBG chip 46014e902STakashi Iwai * 56014e902STakashi Iwai * Copyright (c) 2008 Takashi Iwai <tiwai@suse.de> 66014e902STakashi Iwai */ 76014e902STakashi Iwai 86014e902STakashi Iwai #include <linux/init.h> 96014e902STakashi Iwai #include <linux/slab.h> 106014e902STakashi Iwai #include <linux/module.h> 116014e902STakashi Iwai #include <sound/core.h> 126014e902STakashi Iwai #include <sound/hda_codec.h> 136014e902STakashi Iwai #include "hda_local.h" 146014e902STakashi Iwai #include "hda_auto_parser.h" 156014e902STakashi Iwai #include "hda_jack.h" 166014e902STakashi Iwai #include "generic.h" 176014e902STakashi Iwai 186014e902STakashi Iwai static int ca0110_parse_auto_config(struct hda_codec *codec) 196014e902STakashi Iwai { 206014e902STakashi Iwai struct hda_gen_spec *spec = codec->spec; 216014e902STakashi Iwai int err; 226014e902STakashi Iwai 236014e902STakashi Iwai err = snd_hda_parse_pin_defcfg(codec, &spec->autocfg, NULL, 0); 246014e902STakashi Iwai if (err < 0) 256014e902STakashi Iwai return err; 266014e902STakashi Iwai err = snd_hda_gen_parse_auto_config(codec, &spec->autocfg); 276014e902STakashi Iwai if (err < 0) 286014e902STakashi Iwai return err; 296014e902STakashi Iwai 306014e902STakashi Iwai return 0; 316014e902STakashi Iwai } 326014e902STakashi Iwai 33*dbe3e4abSTakashi Iwai static int ca0110_probe(struct hda_codec *codec, const struct hda_device_id *id) 346014e902STakashi Iwai { 356014e902STakashi Iwai struct hda_gen_spec *spec; 366014e902STakashi Iwai int err; 376014e902STakashi Iwai 386014e902STakashi Iwai spec = kzalloc(sizeof(*spec), GFP_KERNEL); 396014e902STakashi Iwai if (!spec) 406014e902STakashi Iwai return -ENOMEM; 416014e902STakashi Iwai snd_hda_gen_spec_init(spec); 426014e902STakashi Iwai codec->spec = spec; 436014e902STakashi Iwai 446014e902STakashi Iwai spec->multi_cap_vol = 1; 456014e902STakashi Iwai codec->bus->core.needs_damn_long_delay = 1; 466014e902STakashi Iwai 476014e902STakashi Iwai err = ca0110_parse_auto_config(codec); 486014e902STakashi Iwai if (err < 0) 496014e902STakashi Iwai goto error; 506014e902STakashi Iwai 516014e902STakashi Iwai return 0; 526014e902STakashi Iwai 536014e902STakashi Iwai error: 54*dbe3e4abSTakashi Iwai snd_hda_gen_remove(codec); 556014e902STakashi Iwai return err; 566014e902STakashi Iwai } 576014e902STakashi Iwai 586014e902STakashi Iwai 59*dbe3e4abSTakashi Iwai static const struct hda_codec_ops ca0110_codec_ops = { 60*dbe3e4abSTakashi Iwai .probe = ca0110_probe, 61*dbe3e4abSTakashi Iwai .remove = snd_hda_gen_remove, 62*dbe3e4abSTakashi Iwai .build_controls = snd_hda_gen_build_controls, 63*dbe3e4abSTakashi Iwai .build_pcms = snd_hda_gen_build_pcms, 64*dbe3e4abSTakashi Iwai .init = snd_hda_gen_init, 65*dbe3e4abSTakashi Iwai .unsol_event = snd_hda_jack_unsol_event, 66*dbe3e4abSTakashi Iwai }; 67*dbe3e4abSTakashi Iwai 686014e902STakashi Iwai /* 69*dbe3e4abSTakashi Iwai * driver entries 706014e902STakashi Iwai */ 716014e902STakashi Iwai static const struct hda_device_id snd_hda_id_ca0110[] = { 72*dbe3e4abSTakashi Iwai HDA_CODEC_ID(0x1102000a, "CA0110-IBG"), 73*dbe3e4abSTakashi Iwai HDA_CODEC_ID(0x1102000b, "CA0110-IBG"), 74*dbe3e4abSTakashi Iwai HDA_CODEC_ID(0x1102000d, "SB0880 X-Fi"), 756014e902STakashi Iwai {} /* terminator */ 766014e902STakashi Iwai }; 776014e902STakashi Iwai MODULE_DEVICE_TABLE(hdaudio, snd_hda_id_ca0110); 786014e902STakashi Iwai 796014e902STakashi Iwai MODULE_LICENSE("GPL"); 806014e902STakashi Iwai MODULE_DESCRIPTION("Creative CA0110-IBG HD-audio codec"); 816014e902STakashi Iwai 826014e902STakashi Iwai static struct hda_codec_driver ca0110_driver = { 836014e902STakashi Iwai .id = snd_hda_id_ca0110, 84*dbe3e4abSTakashi Iwai .ops = &ca0110_codec_ops, 856014e902STakashi Iwai }; 866014e902STakashi Iwai 876014e902STakashi Iwai module_hda_codec_driver(ca0110_driver); 88