--- patch_ca0132.c +++ patch_ca0132.c @@ -32,6 +32,7 @@ #include "hda_local.h" #include "hda_auto_parser.h" #include "hda_jack.h" +#include "hda_generic.h" #include "ca0132_regs.h" @@ -697,13 +698,14 @@ */ struct ca0132_spec { + struct hda_gen_spec gen; /* must be at head */ + struct snd_kcontrol_new *mixers[5]; unsigned int num_mixers; const struct hda_verb *base_init_verbs; const struct hda_verb *base_exit_verbs; const struct hda_verb *chip_init_verbs; struct hda_verb *spec_init_verbs; - struct auto_pin_cfg autocfg; /* Nodes configurations */ struct hda_multi_out multiout; @@ -761,6 +763,7 @@ enum { QUIRK_NONE, QUIRK_ALIENWARE, + QUIRK_GENERIC_PARSER, }; static const struct hda_pintbl alienware_pincfgs[] = { @@ -781,6 +784,13 @@ SND_PCI_QUIRK(0x1028, 0x0685, "Alienware 15 2015", QUIRK_ALIENWARE), SND_PCI_QUIRK(0x1028, 0x0688, "Alienware 17 2015", QUIRK_ALIENWARE), SND_PCI_QUIRK(0x1028, 0x0708, "Alienware 15 R2 2016", QUIRK_ALIENWARE), + SND_PCI_QUIRK(0x1102, 0x0010, "Sound Blaster Z", QUIRK_GENERIC_PARSER), + SND_PCI_QUIRK(0x1102, 0x0012, "Sound Blaster Z", QUIRK_GENERIC_PARSER), + SND_PCI_QUIRK(0x1102, 0x0023, "Sound Blaster Z", QUIRK_GENERIC_PARSER), + SND_PCI_QUIRK(0x1102, 0x0024, "Sound Blaster Z", QUIRK_GENERIC_PARSER), + SND_PCI_QUIRK(0x1102, 0x0027, "Sound Blaster Z", QUIRK_GENERIC_PARSER), + SND_PCI_QUIRK(0x1102, 0x0025, "Sound Blaster Zx", QUIRK_GENERIC_PARSER), + SND_PCI_QUIRK(0x1102, 0x0033, "Sound Blaster ZxR", QUIRK_GENERIC_PARSER), {} }; @@ -3996,7 +4006,7 @@ add_tuning_ctls(codec); #endif - err = snd_hda_jack_add_kctls(codec, &spec->autocfg); + err = snd_hda_jack_add_kctls(codec, &spec->gen.autocfg); if (err < 0) return err; @@ -4562,7 +4572,7 @@ static int ca0132_init(struct hda_codec *codec) { struct ca0132_spec *spec = codec->spec; - struct auto_pin_cfg *cfg = &spec->autocfg; + struct auto_pin_cfg *cfg = &spec->gen.autocfg; int i; if (spec->dsp_state != DSP_DOWNLOAD_FAILED) @@ -4629,7 +4639,7 @@ static void ca0132_config(struct hda_codec *codec) { struct ca0132_spec *spec = codec->spec; - struct auto_pin_cfg *cfg = &spec->autocfg; + struct auto_pin_cfg *cfg = &spec->gen.autocfg; spec->dacs[0] = 0x2; spec->dacs[1] = 0x3; @@ -4734,6 +4744,82 @@ return 0; } +/* + * CA0132 codec support using generic parser; + * This mode is a kind of fallback mode as the provided DSP has some + * hard-coding mapping and we can't fix it. That is, the board works + * just like a normal HD-audio, and of course, without any effects. + */ +enum { + CA0132_GEN_FIXUP_SBZ, +}; + +static const struct hda_fixup ca0132_gen_fixups[] = { + [CA0132_GEN_FIXUP_SBZ] = { + .type = HDA_FIXUP_PINS, + .v.pins = (const struct hda_pintbl[]) { + { 0x0b, 0x411111f0 }, + { 0x0c, 0x411111f0 }, + { 0x0d, 0x01017010 }, /* lineout */ + { 0x0e, 0x411111f0 }, + { 0x0f, 0x411111f0 }, + { 0x10, 0x411111f0 }, + { 0x11, 0x411111f0 }, + { 0x12, 0x01a170f0 }, /* mic */ + { 0x13, 0x50d000f0 }, + { 0x18, 0x500000f0 }, + {} + }, + }, +}; + +static const struct snd_pci_quirk ca0132_gen_fixup_tbl[] = { + SND_PCI_QUIRK(0x1102, 0x0010, "Sound Blaster Z", CA0132_GEN_FIXUP_SBZ), + SND_PCI_QUIRK(0x1102, 0x0012, "Sound Blaster Z", CA0132_GEN_FIXUP_SBZ), + SND_PCI_QUIRK(0x1102, 0x0023, "Sound Blaster Z", CA0132_GEN_FIXUP_SBZ), + SND_PCI_QUIRK(0x1102, 0x0024, "Sound Blaster Z", CA0132_GEN_FIXUP_SBZ), + SND_PCI_QUIRK(0x1102, 0x0027, "Sound Blaster Z", CA0132_GEN_FIXUP_SBZ), + SND_PCI_QUIRK(0x1102, 0x0025, "Sound Blaster Zx", CA0132_GEN_FIXUP_SBZ), + SND_PCI_QUIRK(0x1102, 0x0033, "Sound Blaster ZxR", CA0132_GEN_FIXUP_SBZ), +}; + +static const struct hda_codec_ops ca0132_gen_patch_ops = { + .build_controls = snd_hda_gen_build_controls, + .build_pcms = snd_hda_gen_build_pcms, + .init = snd_hda_gen_init, + .free = snd_hda_gen_free, + .unsol_event = snd_hda_jack_unsol_event, +}; + +static int parse_ca0132_generic(struct hda_codec *codec) +{ + struct ca0132_spec *spec = codec->spec; + struct auto_pin_cfg *cfg = &spec->gen.autocfg; + int err; + + codec_dbg(codec, "Using generic parser for CA0132\n"); + snd_hda_gen_spec_init(&spec->gen); + codec->patch_ops = ca0132_gen_patch_ops; + snd_hda_pick_fixup(codec, NULL, ca0132_gen_fixup_tbl, + ca0132_gen_fixups); + snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); + + err = snd_hda_parse_pin_def_config(codec, cfg, NULL); + if (err < 0) + goto error; + err = snd_hda_gen_parse_auto_config(codec, cfg); + if (err < 0) + goto error; + + snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE); + return 0; + + error: + snd_hda_gen_free(codec); + return err; +} + +/* common probe entry */ static int patch_ca0132(struct hda_codec *codec) { struct ca0132_spec *spec; @@ -4748,7 +4834,6 @@ codec->spec = spec; spec->codec = codec; - codec->patch_ops = ca0132_patch_ops; codec->pcm_format_first = 1; codec->no_sticky_stream = 1; @@ -4759,6 +4844,11 @@ else spec->quirk = QUIRK_NONE; + if (spec->quirk == QUIRK_GENERIC_PARSER) + return parse_ca0132_generic(codec); + + codec->patch_ops = ca0132_patch_ops; + spec->dsp_state = DSP_DOWNLOAD_INIT; spec->num_mixers = 1; spec->mixers[0] = ca0132_mixer; @@ -4776,7 +4866,7 @@ if (err < 0) return err; - err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL); + err = snd_hda_parse_pin_def_config(codec, &spec->gen.autocfg, NULL); if (err < 0) return err;