static int patch_cs4210(struct hda_codec *codec) { struct cs_spec *spec; int err; spec = cs_alloc_spec(codec, CS4210_VENDOR_NID); if (!spec) return -ENOMEM; codec->patch_ops = cs421x_patch_ops; spec->gen.automute_hook = cs_automute; snd_hda_pick_fixup(codec, cs421x_models, cs421x_fixup_tbl, cs421x_fixups); snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); /* Update the GPIO/DMIC/SENSE_B pinmux before the configuration is auto-parsed. If GPIO or SENSE_B is forced, DMIC input is disabled. */ cs4210_pinmux_init(codec); err = cs421x_parse_auto_config(codec); if (err < 0) goto error; snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE); return 0; error: cs_free(codec); return err; }
static int patch_cs420x(struct hda_codec *codec) { struct cs_spec *spec; int err; spec = cs_alloc_spec(codec, CS420X_VENDOR_NID); if (!spec) return -ENOMEM; codec->patch_ops = cs_patch_ops; spec->gen.automute_hook = cs_automute; codec->single_adc_amp = 1; snd_hda_pick_fixup(codec, cs420x_models, cs420x_fixup_tbl, cs420x_fixups); snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); err = cs_parse_auto_config(codec); if (err < 0) goto error; snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE); return 0; error: cs_free(codec); return err; }
static int patch_ad1981(struct hda_codec *codec) { struct ad198x_spec *spec; int err; err = alloc_ad_spec(codec); if (err < 0) return -ENOMEM; spec = codec->spec; spec->gen.mixer_nid = 0x0e; spec->gen.beep_nid = 0x10; set_beep_amp(spec, 0x0d, 0, HDA_OUTPUT); snd_hda_pick_fixup(codec, NULL, ad1981_fixup_tbl, ad1981_fixups); snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); err = ad198x_parse_auto_config(codec, false); if (err < 0) goto error; err = ad1983_add_spdif_mux_ctl(codec); if (err < 0) goto error; snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE); return 0; error: snd_hda_gen_free(codec); return err; }
static int patch_ad1986a(struct hda_codec *codec) { int err; struct ad198x_spec *spec; static hda_nid_t preferred_pairs[] = { 0x1a, 0x03, 0x1b, 0x03, 0x1c, 0x04, 0x1d, 0x05, 0x1e, 0x03, 0 }; err = alloc_ad_spec(codec); if (err < 0) return err; spec = codec->spec; /* AD1986A has the inverted EAPD implementation */ codec->inv_eapd = 1; spec->gen.mixer_nid = 0x07; spec->gen.beep_nid = 0x19; set_beep_amp(spec, 0x18, 0, HDA_OUTPUT); /* AD1986A has a hardware problem that it can't share a stream * with multiple output pins. The copy of front to surrounds * causes noisy or silent outputs at a certain timing, e.g. * changing the volume. * So, let's disable the shared stream. */ spec->gen.multiout.no_share_stream = 1; /* give fixed DAC/pin pairs */ spec->gen.preferred_dacs = preferred_pairs; /* AD1986A can't manage the dynamic pin on/off smoothly */ spec->gen.auto_mute_via_amp = 1; snd_hda_pick_fixup(codec, ad1986a_fixup_models, ad1986a_fixup_tbl, ad1986a_fixups); snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); err = ad198x_parse_auto_config(codec, false); if (err < 0) { snd_hda_gen_free(codec); return err; } snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE); return 0; }
static int cs_build_controls(struct hda_codec *codec) { int err; err = snd_hda_gen_build_controls(codec); if (err < 0) return err; snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_BUILD); return 0; }
/* remap the fixup from codec SSID and apply it */ static void cs4208_fixup_mac(struct hda_codec *codec, const struct hda_fixup *fix, int action) { if (action != HDA_FIXUP_ACT_PRE_PROBE) return; snd_hda_pick_fixup(codec, NULL, cs4208_mac_fixup_tbl, cs4208_fixups); if (codec->fixup_id < 0 || codec->fixup_id == CS4208_MAC_AUTO) codec->fixup_id = CS4208_GPIO0; /* default fixup */ snd_hda_apply_fixup(codec, action); }
static int cx_auto_init(struct hda_codec *codec) { struct conexant_spec *spec = codec->spec; snd_hda_gen_init(codec); if (!spec->dynamic_eapd) cx_auto_turn_eapd(codec, spec->num_eapds, spec->eapds, true); snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_INIT); return 0; }
static int patch_cs4208(struct hda_codec *codec) { struct cs_spec *spec; int err; spec = cs_alloc_spec(codec, CS4208_VENDOR_NID); if (!spec) return -ENOMEM; spec->gen.automute_hook = cs_automute; /* exclude NID 0x10 (HP) from output volumes due to different steps */ spec->gen.out_vol_mask = 1ULL << 0x10; snd_hda_pick_fixup(codec, cs4208_models, cs4208_fixup_tbl, cs4208_fixups); snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); snd_hda_override_wcaps(codec, 0x18, get_wcaps(codec, 0x18) | AC_WCAP_STEREO); cs4208_fix_amp_caps(codec, 0x18); cs4208_fix_amp_caps(codec, 0x1b); cs4208_fix_amp_caps(codec, 0x1c); err = cs_parse_auto_config(codec); if (err < 0) goto error; codec->patch_ops = cs_patch_ops; snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE); return 0; error: cs_free(codec); return err; }
static int patch_conexant_auto(struct hda_codec *codec) { struct conexant_spec *spec; int err; codec_info(codec, "%s: BIOS auto-probing.\n", codec->core.chip_name); spec = kzalloc(sizeof(*spec), GFP_KERNEL); if (!spec) return -ENOMEM; snd_hda_gen_spec_init(&spec->gen); codec->spec = spec; codec->patch_ops = cx_auto_patch_ops; cx_auto_parse_beep(codec); cx_auto_parse_eapd(codec); spec->gen.own_eapd_ctl = 1; if (spec->dynamic_eapd) spec->gen.vmaster_mute.hook = cx_auto_vmaster_hook; switch (codec->core.vendor_id) { case 0x14f15045: codec->single_adc_amp = 1; spec->gen.mixer_nid = 0x17; spec->gen.add_stereo_mix_input = HDA_HINT_STEREO_MIX_AUTO; snd_hda_pick_fixup(codec, cxt5045_fixup_models, cxt5045_fixups, cxt_fixups); break; case 0x14f15047: codec->pin_amp_workaround = 1; spec->gen.mixer_nid = 0x19; spec->gen.add_stereo_mix_input = HDA_HINT_STEREO_MIX_AUTO; snd_hda_pick_fixup(codec, cxt5047_fixup_models, cxt5047_fixups, cxt_fixups); break; case 0x14f15051: add_cx5051_fake_mutes(codec); codec->pin_amp_workaround = 1; snd_hda_pick_fixup(codec, cxt5051_fixup_models, cxt5051_fixups, cxt_fixups); break; default: codec->pin_amp_workaround = 1; snd_hda_pick_fixup(codec, cxt5066_fixup_models, cxt5066_fixups, cxt_fixups); break; } /* Show mute-led control only on HP laptops * This is a sort of white-list: on HP laptops, EAPD corresponds * only to the mute-LED without actualy amp function. Meanwhile, * others may use EAPD really as an amp switch, so it might be * not good to expose it blindly. */ switch (codec->core.subsystem_id >> 16) { case 0x103c: spec->gen.vmaster_mute_enum = 1; break; } snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); err = snd_hda_parse_pin_defcfg(codec, &spec->gen.autocfg, NULL, spec->parse_flags); if (err < 0) goto error; err = snd_hda_gen_parse_auto_config(codec, &spec->gen.autocfg); if (err < 0) goto error; /* Some laptops with Conexant chips show stalls in S3 resume, * which falls into the single-cmd mode. * Better to make reset, then. */ if (!codec->bus->core.sync_write) { codec_info(codec, "Enable sync_write for stable communication\n"); codec->bus->core.sync_write = 1; codec->bus->allow_bus_reset = 1; } snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE); return 0; error: cx_auto_free(codec); return err; }