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" 30*8fadf1daSTakashi Iwai #include "hda_jack.h" 31*8fadf1daSTakashi Iwai #include "hda_generic.h" 324e01f54bSTakashi Iwai 334e01f54bSTakashi Iwai 34728850a7STakashi Iwai static const struct hda_codec_ops ca0110_patch_ops = { 35*8fadf1daSTakashi Iwai .build_controls = snd_hda_gen_build_controls, 36*8fadf1daSTakashi Iwai .build_pcms = snd_hda_gen_build_pcms, 37*8fadf1daSTakashi Iwai .init = snd_hda_gen_init, 38*8fadf1daSTakashi Iwai .free = snd_hda_gen_free, 394e01f54bSTakashi Iwai }; 404e01f54bSTakashi Iwai 414e01f54bSTakashi Iwai static int ca0110_parse_auto_config(struct hda_codec *codec) 424e01f54bSTakashi Iwai { 43*8fadf1daSTakashi Iwai struct hda_gen_spec *spec = codec->spec; 444e01f54bSTakashi Iwai int err; 454e01f54bSTakashi Iwai 46*8fadf1daSTakashi Iwai err = snd_hda_parse_pin_defcfg(codec, &spec->autocfg, NULL, 0); 47*8fadf1daSTakashi Iwai if (err < 0) 48*8fadf1daSTakashi Iwai return err; 49*8fadf1daSTakashi Iwai err = snd_hda_gen_parse_auto_config(codec, &spec->autocfg); 504e01f54bSTakashi Iwai if (err < 0) 514e01f54bSTakashi Iwai return err; 524e01f54bSTakashi Iwai 534e01f54bSTakashi Iwai return 0; 544e01f54bSTakashi Iwai } 554e01f54bSTakashi Iwai 564e01f54bSTakashi Iwai 571e168953STakashi Iwai static int patch_ca0110(struct hda_codec *codec) 584e01f54bSTakashi Iwai { 59*8fadf1daSTakashi Iwai struct hda_gen_spec *spec; 604e01f54bSTakashi Iwai int err; 614e01f54bSTakashi Iwai 624e01f54bSTakashi Iwai spec = kzalloc(sizeof(*spec), GFP_KERNEL); 634e01f54bSTakashi Iwai if (!spec) 644e01f54bSTakashi Iwai return -ENOMEM; 65*8fadf1daSTakashi Iwai snd_hda_gen_spec_init(spec); 664e01f54bSTakashi Iwai codec->spec = spec; 674e01f54bSTakashi Iwai 68*8fadf1daSTakashi Iwai spec->multi_cap_vol = 1; 694e01f54bSTakashi Iwai codec->bus->needs_damn_long_delay = 1; 704e01f54bSTakashi Iwai 714e01f54bSTakashi Iwai err = ca0110_parse_auto_config(codec); 724e01f54bSTakashi Iwai if (err < 0) 734e01f54bSTakashi Iwai goto error; 744e01f54bSTakashi Iwai 754e01f54bSTakashi Iwai codec->patch_ops = ca0110_patch_ops; 764e01f54bSTakashi Iwai 774e01f54bSTakashi Iwai return 0; 784e01f54bSTakashi Iwai 794e01f54bSTakashi Iwai error: 80*8fadf1daSTakashi Iwai snd_hda_gen_free(codec); 814e01f54bSTakashi Iwai return err; 824e01f54bSTakashi Iwai } 834e01f54bSTakashi Iwai 844e01f54bSTakashi Iwai 854e01f54bSTakashi Iwai /* 864e01f54bSTakashi Iwai * patch entries 874e01f54bSTakashi Iwai */ 88728850a7STakashi Iwai static const struct hda_codec_preset snd_hda_preset_ca0110[] = { 894e01f54bSTakashi Iwai { .id = 0x1102000a, .name = "CA0110-IBG", .patch = patch_ca0110 }, 904e01f54bSTakashi Iwai { .id = 0x1102000b, .name = "CA0110-IBG", .patch = patch_ca0110 }, 914e01f54bSTakashi Iwai { .id = 0x1102000d, .name = "SB0880 X-Fi", .patch = patch_ca0110 }, 924e01f54bSTakashi Iwai {} /* terminator */ 934e01f54bSTakashi Iwai }; 944e01f54bSTakashi Iwai 954e01f54bSTakashi Iwai MODULE_ALIAS("snd-hda-codec-id:1102000a"); 964e01f54bSTakashi Iwai MODULE_ALIAS("snd-hda-codec-id:1102000b"); 974e01f54bSTakashi Iwai MODULE_ALIAS("snd-hda-codec-id:1102000d"); 984e01f54bSTakashi Iwai 994e01f54bSTakashi Iwai MODULE_LICENSE("GPL"); 1004e01f54bSTakashi Iwai MODULE_DESCRIPTION("Creative CA0110-IBG HD-audio codec"); 1014e01f54bSTakashi Iwai 1024e01f54bSTakashi Iwai static struct hda_codec_preset_list ca0110_list = { 1034e01f54bSTakashi Iwai .preset = snd_hda_preset_ca0110, 1044e01f54bSTakashi Iwai .owner = THIS_MODULE, 1054e01f54bSTakashi Iwai }; 1064e01f54bSTakashi Iwai 1074e01f54bSTakashi Iwai static int __init patch_ca0110_init(void) 1084e01f54bSTakashi Iwai { 1094e01f54bSTakashi Iwai return snd_hda_add_codec_preset(&ca0110_list); 1104e01f54bSTakashi Iwai } 1114e01f54bSTakashi Iwai 1124e01f54bSTakashi Iwai static void __exit patch_ca0110_exit(void) 1134e01f54bSTakashi Iwai { 1144e01f54bSTakashi Iwai snd_hda_delete_codec_preset(&ca0110_list); 1154e01f54bSTakashi Iwai } 1164e01f54bSTakashi Iwai 1174e01f54bSTakashi Iwai module_init(patch_ca0110_init) 1184e01f54bSTakashi Iwai module_exit(patch_ca0110_exit) 119