File Index
Files and directories
Sign in
FILE

alc861.c

File preview with syntax highlighting.

linux-6.19.14/sound/hda/codecs/realtek/alc861.c C
  1// SPDX-License-Identifier: GPL-2.0-or-later
  2//
  3// Realtek ALC861 codec
  4//
  5
  6#include <linux/init.h>
  7#include <linux/module.h>
  8#include "realtek.h"
  9
 10static int alc861_parse_auto_config(struct hda_codec *codec)
 11{
 12	static const hda_nid_t alc861_ignore[] = { 0x1d, 0 };
 13	static const hda_nid_t alc861_ssids[] = { 0x0e, 0x0f, 0x0b, 0 };
 14	return alc_parse_auto_config(codec, alc861_ignore, alc861_ssids);
 15}
 16
 17/* Pin config fixes */
 18enum {
 19	ALC861_FIXUP_FSC_AMILO_PI1505,
 20	ALC861_FIXUP_AMP_VREF_0F,
 21	ALC861_FIXUP_NO_JACK_DETECT,
 22	ALC861_FIXUP_ASUS_A6RP,
 23	ALC660_FIXUP_ASUS_W7J,
 24};
 25
 26/* On some laptops, VREF of pin 0x0f is abused for controlling the main amp */
 27static void alc861_fixup_asus_amp_vref_0f(struct hda_codec *codec,
 28			const struct hda_fixup *fix, int action)
 29{
 30	struct alc_spec *spec = codec->spec;
 31	unsigned int val;
 32
 33	if (action != HDA_FIXUP_ACT_INIT)
 34		return;
 35	val = snd_hda_codec_get_pin_target(codec, 0x0f);
 36	if (!(val & (AC_PINCTL_IN_EN | AC_PINCTL_OUT_EN)))
 37		val |= AC_PINCTL_IN_EN;
 38	val |= AC_PINCTL_VREF_50;
 39	snd_hda_set_pin_ctl(codec, 0x0f, val);
 40	spec->gen.keep_vref_in_automute = 1;
 41}
 42
 43static const struct hda_fixup alc861_fixups[] = {
 44	[ALC861_FIXUP_FSC_AMILO_PI1505] = {
 45		.type = HDA_FIXUP_PINS,
 46		.v.pins = (const struct hda_pintbl[]) {
 47			{ 0x0b, 0x0221101f }, /* HP */
 48			{ 0x0f, 0x90170310 }, /* speaker */
 49			{ }
 50		}
 51	},
 52	[ALC861_FIXUP_AMP_VREF_0F] = {
 53		.type = HDA_FIXUP_FUNC,
 54		.v.func = alc861_fixup_asus_amp_vref_0f,
 55	},
 56	[ALC861_FIXUP_NO_JACK_DETECT] = {
 57		.type = HDA_FIXUP_FUNC,
 58		.v.func = alc_fixup_no_jack_detect,
 59	},
 60	[ALC861_FIXUP_ASUS_A6RP] = {
 61		.type = HDA_FIXUP_FUNC,
 62		.v.func = alc861_fixup_asus_amp_vref_0f,
 63		.chained = true,
 64		.chain_id = ALC861_FIXUP_NO_JACK_DETECT,
 65	},
 66	[ALC660_FIXUP_ASUS_W7J] = {
 67		.type = HDA_FIXUP_VERBS,
 68		.v.verbs = (const struct hda_verb[]) {
 69			/* ASUS W7J needs a magic pin setup on unused NID 0x10
 70			 * for enabling outputs
 71			 */
 72			{0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
 73			{ }
 74		},
 75	}
 76};
 77
 78static const struct hda_quirk alc861_fixup_tbl[] = {
 79	SND_PCI_QUIRK(0x1043, 0x1253, "ASUS W7J", ALC660_FIXUP_ASUS_W7J),
 80	SND_PCI_QUIRK(0x1043, 0x1263, "ASUS Z35HL", ALC660_FIXUP_ASUS_W7J),
 81	SND_PCI_QUIRK(0x1043, 0x1393, "ASUS A6Rp", ALC861_FIXUP_ASUS_A6RP),
 82	SND_PCI_QUIRK_VENDOR(0x1043, "ASUS laptop", ALC861_FIXUP_AMP_VREF_0F),
 83	SND_PCI_QUIRK(0x1462, 0x7254, "HP DX2200", ALC861_FIXUP_NO_JACK_DETECT),
 84	SND_PCI_QUIRK_VENDOR(0x1584, "Haier/Uniwill", ALC861_FIXUP_AMP_VREF_0F),
 85	SND_PCI_QUIRK(0x1734, 0x10c7, "FSC Amilo Pi1505", ALC861_FIXUP_FSC_AMILO_PI1505),
 86	{}
 87};
 88
 89/*
 90 */
 91static int alc861_probe(struct hda_codec *codec, const struct hda_device_id *id)
 92{
 93	struct alc_spec *spec;
 94	int err;
 95
 96	err = alc_alloc_spec(codec, 0x15);
 97	if (err < 0)
 98		return err;
 99
100	spec = codec->spec;
101	if (has_cdefine_beep(codec))
102		spec->gen.beep_nid = 0x23;
103
104	spec->power_hook = alc_power_eapd;
105
106	alc_pre_init(codec);
107
108	snd_hda_pick_fixup(codec, NULL, alc861_fixup_tbl, alc861_fixups);
109	snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
110
111	/* automatic parse from the BIOS config */
112	err = alc861_parse_auto_config(codec);
113	if (err < 0)
114		goto error;
115
116	if (!spec->gen.no_analog) {
117		err = set_beep_amp(spec, 0x23, 0, HDA_OUTPUT);
118		if (err < 0)
119			goto error;
120	}
121
122	snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
123
124	return 0;
125
126 error:
127	snd_hda_gen_remove(codec);
128	return err;
129}
130
131static const struct hda_codec_ops alc861_codec_ops = {
132	.probe = alc861_probe,
133	.remove = snd_hda_gen_remove,
134	.build_controls = alc_build_controls,
135	.build_pcms = snd_hda_gen_build_pcms,
136	.init = alc_init,
137	.unsol_event = snd_hda_jack_unsol_event,
138	.resume = alc_resume,
139	.suspend = alc_suspend,
140	.check_power_status = snd_hda_gen_check_power_status,
141	.stream_pm = snd_hda_gen_stream_pm,
142};
143
144/*
145 * driver entries
146 */
147static const struct hda_device_id snd_hda_id_alc861[] = {
148	HDA_CODEC_ID_REV(0x10ec0861, 0x100340, "ALC660"),
149	HDA_CODEC_ID(0x10ec0861, "ALC861"),
150	{} /* terminator */
151};
152MODULE_DEVICE_TABLE(hdaudio, snd_hda_id_alc861);
153
154MODULE_LICENSE("GPL");
155MODULE_DESCRIPTION("Realtek ALC861 HD-audio codec");
156MODULE_IMPORT_NS("SND_HDA_CODEC_REALTEK");
157
158static struct hda_codec_driver alc861_driver = {
159	.id = snd_hda_id_alc861,
160	.ops = &alc861_codec_ops,
161};
162
163module_hda_codec_driver(alc861_driver);
~/ Read-only file preview.