14e01f54bSTakashi Iwai /* 24e01f54bSTakashi Iwai * HD audio interface patch for Creative X-Fi CA0110-IBG chip 34e01f54bSTakashi Iwai * 44e01f54bSTakashi Iwai * Copyright (c) 2008 Takashi Iwai <tiwai@suse.de> 54e01f54bSTakashi Iwai * 64e01f54bSTakashi Iwai * This driver is free software; you can redistribute it and/or modify 74e01f54bSTakashi Iwai * it under the terms of the GNU General Public License as published by 84e01f54bSTakashi Iwai * the Free Software Foundation; either version 2 of the License, or 94e01f54bSTakashi Iwai * (at your option) any later version. 104e01f54bSTakashi Iwai * 114e01f54bSTakashi Iwai * This driver is distributed in the hope that it will be useful, 124e01f54bSTakashi Iwai * but WITHOUT ANY WARRANTY; without even the implied warranty of 134e01f54bSTakashi Iwai * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 144e01f54bSTakashi Iwai * GNU General Public License for more details. 154e01f54bSTakashi Iwai * 164e01f54bSTakashi Iwai * You should have received a copy of the GNU General Public License 174e01f54bSTakashi Iwai * along with this program; if not, write to the Free Software 184e01f54bSTakashi Iwai * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 194e01f54bSTakashi Iwai */ 204e01f54bSTakashi Iwai 214e01f54bSTakashi Iwai #include <linux/init.h> 224e01f54bSTakashi Iwai #include <linux/delay.h> 234e01f54bSTakashi Iwai #include <linux/slab.h> 244e01f54bSTakashi Iwai #include <linux/pci.h> 25da155d5bSPaul Gortmaker #include <linux/module.h> 264e01f54bSTakashi Iwai #include <sound/core.h> 274e01f54bSTakashi Iwai #include "hda_codec.h" 284e01f54bSTakashi Iwai #include "hda_local.h" 29128bc4baSTakashi Iwai #include "hda_auto_parser.h" 308fadf1daSTakashi Iwai #include "hda_jack.h" 318fadf1daSTakashi Iwai #include "hda_generic.h" 324e01f54bSTakashi Iwai 334e01f54bSTakashi Iwai 34728850a7STakashi Iwai static const struct hda_codec_ops ca0110_patch_ops = { 358fadf1daSTakashi Iwai .build_controls = snd_hda_gen_build_controls, 368fadf1daSTakashi Iwai .build_pcms = snd_hda_gen_build_pcms, 378fadf1daSTakashi Iwai .init = snd_hda_gen_init, 388fadf1daSTakashi Iwai .free = snd_hda_gen_free, 39*8a6c21aeSTakashi Iwai .unsol_event = snd_hda_jack_unsol_event, 404e01f54bSTakashi Iwai }; 414e01f54bSTakashi Iwai 424e01f54bSTakashi Iwai static int ca0110_parse_auto_config(struct hda_codec *codec) 434e01f54bSTakashi Iwai { 448fadf1daSTakashi Iwai struct hda_gen_spec *spec = codec->spec; 454e01f54bSTakashi Iwai int err; 464e01f54bSTakashi Iwai 478fadf1daSTakashi Iwai err = snd_hda_parse_pin_defcfg(codec, &spec->autocfg, NULL, 0); 488fadf1daSTakashi Iwai if (err < 0) 498fadf1daSTakashi Iwai return err; 508fadf1daSTakashi Iwai err = snd_hda_gen_parse_auto_config(codec, &spec->autocfg); 514e01f54bSTakashi Iwai if (err < 0) 524e01f54bSTakashi Iwai return err; 534e01f54bSTakashi Iwai 544e01f54bSTakashi Iwai return 0; 554e01f54bSTakashi Iwai } 564e01f54bSTakashi Iwai 574e01f54bSTakashi Iwai 581e168953STakashi Iwai static int patch_ca0110(struct hda_codec *codec) 594e01f54bSTakashi Iwai { 608fadf1daSTakashi Iwai struct hda_gen_spec *spec; 614e01f54bSTakashi Iwai int err; 624e01f54bSTakashi Iwai 634e01f54bSTakashi Iwai spec = kzalloc(sizeof(*spec), GFP_KERNEL); 644e01f54bSTakashi Iwai if (!spec) 654e01f54bSTakashi Iwai return -ENOMEM; 668fadf1daSTakashi Iwai snd_hda_gen_spec_init(spec); 674e01f54bSTakashi Iwai codec->spec = spec; 684e01f54bSTakashi Iwai 698fadf1daSTakashi Iwai spec->multi_cap_vol = 1; 704e01f54bSTakashi Iwai codec->bus->needs_damn_long_delay = 1; 714e01f54bSTakashi Iwai 724e01f54bSTakashi Iwai err = ca0110_parse_auto_config(codec); 734e01f54bSTakashi Iwai if (err < 0) 744e01f54bSTakashi Iwai goto error; 754e01f54bSTakashi Iwai 764e01f54bSTakashi Iwai codec->patch_ops = ca0110_patch_ops; 774e01f54bSTakashi Iwai 784e01f54bSTakashi Iwai return 0; 794e01f54bSTakashi Iwai 804e01f54bSTakashi Iwai error: 818fadf1daSTakashi Iwai snd_hda_gen_free(codec); 824e01f54bSTakashi Iwai return err; 834e01f54bSTakashi Iwai } 844e01f54bSTakashi Iwai 854e01f54bSTakashi Iwai 864e01f54bSTakashi Iwai /* 874e01f54bSTakashi Iwai * patch entries 884e01f54bSTakashi Iwai */ 89728850a7STakashi Iwai static const struct hda_codec_preset snd_hda_preset_ca0110[] = { 904e01f54bSTakashi Iwai { .id = 0x1102000a, .name = "CA0110-IBG", .patch = patch_ca0110 }, 914e01f54bSTakashi Iwai { .id = 0x1102000b, .name = "CA0110-IBG", .patch = patch_ca0110 }, 924e01f54bSTakashi Iwai { .id = 0x1102000d, .name = "SB0880 X-Fi", .patch = patch_ca0110 }, 934e01f54bSTakashi Iwai {} /* terminator */ 944e01f54bSTakashi Iwai }; 954e01f54bSTakashi Iwai 964e01f54bSTakashi Iwai MODULE_ALIAS("snd-hda-codec-id:1102000a"); 974e01f54bSTakashi Iwai MODULE_ALIAS("snd-hda-codec-id:1102000b"); 984e01f54bSTakashi Iwai MODULE_ALIAS("snd-hda-codec-id:1102000d"); 994e01f54bSTakashi Iwai 1004e01f54bSTakashi Iwai MODULE_LICENSE("GPL"); 1014e01f54bSTakashi Iwai MODULE_DESCRIPTION("Creative CA0110-IBG HD-audio codec"); 1024e01f54bSTakashi Iwai 1034e01f54bSTakashi Iwai static struct hda_codec_preset_list ca0110_list = { 1044e01f54bSTakashi Iwai .preset = snd_hda_preset_ca0110, 1054e01f54bSTakashi Iwai .owner = THIS_MODULE, 1064e01f54bSTakashi Iwai }; 1074e01f54bSTakashi Iwai 1084e01f54bSTakashi Iwai static int __init patch_ca0110_init(void) 1094e01f54bSTakashi Iwai { 1104e01f54bSTakashi Iwai return snd_hda_add_codec_preset(&ca0110_list); 1114e01f54bSTakashi Iwai } 1124e01f54bSTakashi Iwai 1134e01f54bSTakashi Iwai static void __exit patch_ca0110_exit(void) 1144e01f54bSTakashi Iwai { 1154e01f54bSTakashi Iwai snd_hda_delete_codec_preset(&ca0110_list); 1164e01f54bSTakashi Iwai } 1174e01f54bSTakashi Iwai 1184e01f54bSTakashi Iwai module_init(patch_ca0110_init) 1194e01f54bSTakashi Iwai module_exit(patch_ca0110_exit) 120