From ace9429bb58fd418f0c81d4c2835699bddf6bde6 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Thu, 11 Apr 2024 10:27:49 +0200 Subject: Adding upstream version 6.6.15. Signed-off-by: Daniel Baumann --- sound/pci/hda/patch_cmedia.c | 127 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 127 insertions(+) create mode 100644 sound/pci/hda/patch_cmedia.c (limited to 'sound/pci/hda/patch_cmedia.c') diff --git a/sound/pci/hda/patch_cmedia.c b/sound/pci/hda/patch_cmedia.c new file mode 100644 index 0000000000..2ddd33f8dd --- /dev/null +++ b/sound/pci/hda/patch_cmedia.c @@ -0,0 +1,127 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Universal Interface for Intel High Definition Audio Codec + * + * HD audio interface patch for C-Media CMI9880 + * + * Copyright (c) 2004 Takashi Iwai + */ + +#include +#include +#include +#include +#include +#include "hda_local.h" +#include "hda_auto_parser.h" +#include "hda_jack.h" +#include "hda_generic.h" + +struct cmi_spec { + struct hda_gen_spec gen; +}; + +/* + * stuff for auto-parser + */ +static const struct hda_codec_ops cmi_auto_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 patch_cmi9880(struct hda_codec *codec) +{ + struct cmi_spec *spec; + struct auto_pin_cfg *cfg; + int err; + + spec = kzalloc(sizeof(*spec), GFP_KERNEL); + if (spec == NULL) + return -ENOMEM; + + codec->spec = spec; + codec->patch_ops = cmi_auto_patch_ops; + cfg = &spec->gen.autocfg; + snd_hda_gen_spec_init(&spec->gen); + + err = snd_hda_parse_pin_defcfg(codec, cfg, NULL, 0); + if (err < 0) + goto error; + err = snd_hda_gen_parse_auto_config(codec, cfg); + if (err < 0) + goto error; + + return 0; + + error: + snd_hda_gen_free(codec); + return err; +} + +static int patch_cmi8888(struct hda_codec *codec) +{ + struct cmi_spec *spec; + struct auto_pin_cfg *cfg; + int err; + + spec = kzalloc(sizeof(*spec), GFP_KERNEL); + if (!spec) + return -ENOMEM; + + codec->spec = spec; + codec->patch_ops = cmi_auto_patch_ops; + cfg = &spec->gen.autocfg; + snd_hda_gen_spec_init(&spec->gen); + + /* mask NID 0x10 from the playback volume selection; + * it's a headphone boost volume handled manually below + */ + spec->gen.out_vol_mask = (1ULL << 0x10); + + err = snd_hda_parse_pin_defcfg(codec, cfg, NULL, 0); + if (err < 0) + goto error; + err = snd_hda_gen_parse_auto_config(codec, cfg); + if (err < 0) + goto error; + + if (get_defcfg_device(snd_hda_codec_get_pincfg(codec, 0x10)) == + AC_JACK_HP_OUT) { + static const struct snd_kcontrol_new amp_kctl = + HDA_CODEC_VOLUME("Headphone Amp Playback Volume", + 0x10, 0, HDA_OUTPUT); + if (!snd_hda_gen_add_kctl(&spec->gen, NULL, &_kctl)) { + err = -ENOMEM; + goto error; + } + } + + return 0; + + error: + snd_hda_gen_free(codec); + return err; +} + +/* + * patch entries + */ +static const struct hda_device_id snd_hda_id_cmedia[] = { + HDA_CODEC_ENTRY(0x13f68888, "CMI8888", patch_cmi8888), + HDA_CODEC_ENTRY(0x13f69880, "CMI9880", patch_cmi9880), + HDA_CODEC_ENTRY(0x434d4980, "CMI9880", patch_cmi9880), + {} /* terminator */ +}; +MODULE_DEVICE_TABLE(hdaudio, snd_hda_id_cmedia); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("C-Media HD-audio codec"); + +static struct hda_codec_driver cmedia_driver = { + .id = snd_hda_id_cmedia, +}; + +module_hda_codec_driver(cmedia_driver); -- cgit v1.2.3