File Index
Files and directories
Sign in
FILE

alc260.c

File preview with syntax highlighting.

linux-6.19.14/sound/hda/codecs/realtek/alc260.c C
  1// SPDX-License-Identifier: GPL-2.0-or-later
  2//
  3// Realtek ALC260 codec
  4//
  5
  6#include <linux/init.h>
  7#include <linux/module.h>
  8#include "realtek.h"
  9
 10static int alc260_parse_auto_config(struct hda_codec *codec)
 11{
 12	static const hda_nid_t alc260_ignore[] = { 0x17, 0 };
 13	static const hda_nid_t alc260_ssids[] = { 0x10, 0x15, 0x0f, 0 };
 14	return alc_parse_auto_config(codec, alc260_ignore, alc260_ssids);
 15}
 16
 17/*
 18 * Pin config fixes
 19 */
 20enum {
 21	ALC260_FIXUP_HP_DC5750,
 22	ALC260_FIXUP_HP_PIN_0F,
 23	ALC260_FIXUP_COEF,
 24	ALC260_FIXUP_GPIO1,
 25	ALC260_FIXUP_GPIO1_TOGGLE,
 26	ALC260_FIXUP_REPLACER,
 27	ALC260_FIXUP_HP_B1900,
 28	ALC260_FIXUP_KN1,
 29	ALC260_FIXUP_FSC_S7020,
 30	ALC260_FIXUP_FSC_S7020_JWSE,
 31	ALC260_FIXUP_VAIO_PINS,
 32};
 33
 34static void alc260_gpio1_automute(struct hda_codec *codec)
 35{
 36	struct alc_spec *spec = codec->spec;
 37
 38	alc_update_gpio_data(codec, 0x01, spec->gen.hp_jack_present);
 39}
 40
 41static void alc260_fixup_gpio1_toggle(struct hda_codec *codec,
 42				      const struct hda_fixup *fix, int action)
 43{
 44	struct alc_spec *spec = codec->spec;
 45	if (action == HDA_FIXUP_ACT_PROBE) {
 46		/* although the machine has only one output pin, we need to
 47		 * toggle GPIO1 according to the jack state
 48		 */
 49		spec->gen.automute_hook = alc260_gpio1_automute;
 50		spec->gen.detect_hp = 1;
 51		spec->gen.automute_speaker = 1;
 52		spec->gen.autocfg.hp_pins[0] = 0x0f; /* copy it for automute */
 53		snd_hda_jack_detect_enable_callback(codec, 0x0f,
 54						    snd_hda_gen_hp_automute);
 55		alc_setup_gpio(codec, 0x01);
 56	}
 57}
 58
 59static void alc260_fixup_kn1(struct hda_codec *codec,
 60			     const struct hda_fixup *fix, int action)
 61{
 62	struct alc_spec *spec = codec->spec;
 63	static const struct hda_pintbl pincfgs[] = {
 64		{ 0x0f, 0x02214000 }, /* HP/speaker */
 65		{ 0x12, 0x90a60160 }, /* int mic */
 66		{ 0x13, 0x02a19000 }, /* ext mic */
 67		{ 0x18, 0x01446000 }, /* SPDIF out */
 68		/* disable bogus I/O pins */
 69		{ 0x10, 0x411111f0 },
 70		{ 0x11, 0x411111f0 },
 71		{ 0x14, 0x411111f0 },
 72		{ 0x15, 0x411111f0 },
 73		{ 0x16, 0x411111f0 },
 74		{ 0x17, 0x411111f0 },
 75		{ 0x19, 0x411111f0 },
 76		{ }
 77	};
 78
 79	switch (action) {
 80	case HDA_FIXUP_ACT_PRE_PROBE:
 81		snd_hda_apply_pincfgs(codec, pincfgs);
 82		spec->init_amp = ALC_INIT_NONE;
 83		break;
 84	}
 85}
 86
 87static void alc260_fixup_fsc_s7020(struct hda_codec *codec,
 88				   const struct hda_fixup *fix, int action)
 89{
 90	struct alc_spec *spec = codec->spec;
 91	if (action == HDA_FIXUP_ACT_PRE_PROBE)
 92		spec->init_amp = ALC_INIT_NONE;
 93}
 94
 95static void alc260_fixup_fsc_s7020_jwse(struct hda_codec *codec,
 96				   const struct hda_fixup *fix, int action)
 97{
 98	struct alc_spec *spec = codec->spec;
 99	if (action == HDA_FIXUP_ACT_PRE_PROBE) {
100		spec->gen.add_jack_modes = 1;
101		spec->gen.hp_mic = 1;
102	}
103}
104
105static const struct hda_fixup alc260_fixups[] = {
106	[ALC260_FIXUP_HP_DC5750] = {
107		.type = HDA_FIXUP_PINS,
108		.v.pins = (const struct hda_pintbl[]) {
109			{ 0x11, 0x90130110 }, /* speaker */
110			{ }
111		}
112	},
113	[ALC260_FIXUP_HP_PIN_0F] = {
114		.type = HDA_FIXUP_PINS,
115		.v.pins = (const struct hda_pintbl[]) {
116			{ 0x0f, 0x01214000 }, /* HP */
117			{ }
118		}
119	},
120	[ALC260_FIXUP_COEF] = {
121		.type = HDA_FIXUP_VERBS,
122		.v.verbs = (const struct hda_verb[]) {
123			{ 0x1a, AC_VERB_SET_COEF_INDEX, 0x07 },
124			{ 0x1a, AC_VERB_SET_PROC_COEF,  0x3040 },
125			{ }
126		},
127	},
128	[ALC260_FIXUP_GPIO1] = {
129		.type = HDA_FIXUP_FUNC,
130		.v.func = alc_fixup_gpio1,
131	},
132	[ALC260_FIXUP_GPIO1_TOGGLE] = {
133		.type = HDA_FIXUP_FUNC,
134		.v.func = alc260_fixup_gpio1_toggle,
135		.chained = true,
136		.chain_id = ALC260_FIXUP_HP_PIN_0F,
137	},
138	[ALC260_FIXUP_REPLACER] = {
139		.type = HDA_FIXUP_VERBS,
140		.v.verbs = (const struct hda_verb[]) {
141			{ 0x1a, AC_VERB_SET_COEF_INDEX, 0x07 },
142			{ 0x1a, AC_VERB_SET_PROC_COEF,  0x3050 },
143			{ }
144		},
145		.chained = true,
146		.chain_id = ALC260_FIXUP_GPIO1_TOGGLE,
147	},
148	[ALC260_FIXUP_HP_B1900] = {
149		.type = HDA_FIXUP_FUNC,
150		.v.func = alc260_fixup_gpio1_toggle,
151		.chained = true,
152		.chain_id = ALC260_FIXUP_COEF,
153	},
154	[ALC260_FIXUP_KN1] = {
155		.type = HDA_FIXUP_FUNC,
156		.v.func = alc260_fixup_kn1,
157	},
158	[ALC260_FIXUP_FSC_S7020] = {
159		.type = HDA_FIXUP_FUNC,
160		.v.func = alc260_fixup_fsc_s7020,
161	},
162	[ALC260_FIXUP_FSC_S7020_JWSE] = {
163		.type = HDA_FIXUP_FUNC,
164		.v.func = alc260_fixup_fsc_s7020_jwse,
165		.chained = true,
166		.chain_id = ALC260_FIXUP_FSC_S7020,
167	},
168	[ALC260_FIXUP_VAIO_PINS] = {
169		.type = HDA_FIXUP_PINS,
170		.v.pins = (const struct hda_pintbl[]) {
171			/* Pin configs are missing completely on some VAIOs */
172			{ 0x0f, 0x01211020 },
173			{ 0x10, 0x0001003f },
174			{ 0x11, 0x411111f0 },
175			{ 0x12, 0x01a15930 },
176			{ 0x13, 0x411111f0 },
177			{ 0x14, 0x411111f0 },
178			{ 0x15, 0x411111f0 },
179			{ 0x16, 0x411111f0 },
180			{ 0x17, 0x411111f0 },
181			{ 0x18, 0x411111f0 },
182			{ 0x19, 0x411111f0 },
183			{ }
184		}
185	},
186};
187
188static const struct hda_quirk alc260_fixup_tbl[] = {
189	SND_PCI_QUIRK(0x1025, 0x007b, "Acer C20x", ALC260_FIXUP_GPIO1),
190	SND_PCI_QUIRK(0x1025, 0x007f, "Acer Aspire 9500", ALC260_FIXUP_COEF),
191	SND_PCI_QUIRK(0x1025, 0x008f, "Acer", ALC260_FIXUP_GPIO1),
192	SND_PCI_QUIRK(0x103c, 0x280a, "HP dc5750", ALC260_FIXUP_HP_DC5750),
193	SND_PCI_QUIRK(0x103c, 0x30ba, "HP Presario B1900", ALC260_FIXUP_HP_B1900),
194	SND_PCI_QUIRK(0x104d, 0x81bb, "Sony VAIO", ALC260_FIXUP_VAIO_PINS),
195	SND_PCI_QUIRK(0x104d, 0x81e2, "Sony VAIO TX", ALC260_FIXUP_HP_PIN_0F),
196	SND_PCI_QUIRK(0x10cf, 0x1326, "FSC LifeBook S7020", ALC260_FIXUP_FSC_S7020),
197	SND_PCI_QUIRK(0x1509, 0x4540, "Favorit 100XS", ALC260_FIXUP_GPIO1),
198	SND_PCI_QUIRK(0x152d, 0x0729, "Quanta KN1", ALC260_FIXUP_KN1),
199	SND_PCI_QUIRK(0x161f, 0x2057, "Replacer 672V", ALC260_FIXUP_REPLACER),
200	SND_PCI_QUIRK(0x1631, 0xc017, "PB V7900", ALC260_FIXUP_COEF),
201	{}
202};
203
204static const struct hda_model_fixup alc260_fixup_models[] = {
205	{.id = ALC260_FIXUP_GPIO1, .name = "gpio1"},
206	{.id = ALC260_FIXUP_COEF, .name = "coef"},
207	{.id = ALC260_FIXUP_FSC_S7020, .name = "fujitsu"},
208	{.id = ALC260_FIXUP_FSC_S7020_JWSE, .name = "fujitsu-jwse"},
209	{}
210};
211
212/*
213 */
214static int alc260_probe(struct hda_codec *codec, const struct hda_device_id *id)
215{
216	struct alc_spec *spec;
217	int err;
218
219	err = alc_alloc_spec(codec, 0x07);
220	if (err < 0)
221		return err;
222
223	spec = codec->spec;
224	/* as quite a few machines require HP amp for speaker outputs,
225	 * it's easier to enable it unconditionally; even if it's unneeded,
226	 * it's almost harmless.
227	 */
228	spec->gen.prefer_hp_amp = 1;
229	spec->gen.beep_nid = 0x01;
230
231	spec->shutup = alc_eapd_shutup;
232
233	alc_pre_init(codec);
234
235	snd_hda_pick_fixup(codec, alc260_fixup_models, alc260_fixup_tbl,
236			   alc260_fixups);
237	snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
238
239	/* automatic parse from the BIOS config */
240	err = alc260_parse_auto_config(codec);
241	if (err < 0)
242		goto error;
243
244	if (!spec->gen.no_analog) {
245		err = set_beep_amp(spec, 0x07, 0x05, HDA_INPUT);
246		if (err < 0)
247			goto error;
248	}
249
250	snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
251
252	return 0;
253
254 error:
255	snd_hda_gen_remove(codec);
256	return err;
257}
258
259static const struct hda_codec_ops alc260_codec_ops = {
260	.probe = alc260_probe,
261	.remove = snd_hda_gen_remove,
262	.build_controls = alc_build_controls,
263	.build_pcms = snd_hda_gen_build_pcms,
264	.init = alc_init,
265	.unsol_event = snd_hda_jack_unsol_event,
266	.resume = alc_resume,
267	.suspend = alc_suspend,
268	.check_power_status = snd_hda_gen_check_power_status,
269	.stream_pm = snd_hda_gen_stream_pm,
270};
271
272/*
273 * driver entries
274 */
275static const struct hda_device_id snd_hda_id_alc260[] = {
276	HDA_CODEC_ID(0x10ec0260, "ALC260"),
277	{} /* terminator */
278};
279MODULE_DEVICE_TABLE(hdaudio, snd_hda_id_alc260);
280
281MODULE_LICENSE("GPL");
282MODULE_DESCRIPTION("Realtek ALC260 HD-audio codec");
283MODULE_IMPORT_NS("SND_HDA_CODEC_REALTEK");
284
285static struct hda_codec_driver alc260_driver = {
286	.id = snd_hda_id_alc260,
287	.ops = &alc260_codec_ops,
288};
289
290module_hda_codec_driver(alc260_driver);
~/ Read-only file preview.