ALSA: hda: Split Realtek HD-audio codec driver

The snd-hda-codec-realtek driver supports many different codec models
and accumulated lots of quirks.  Now let's split it to multiple
modules per probe function, i.e. for ALC260, ALC262, ALC269, etc.

The common code and quirks are provided by the common library module,
snd-hda-codec-realtek-lib now.  One drawback of this action is that
many symbols have to be exported.  But they are limited with
SND_HDA_CODEC_REALTEK namespace, at least.

This patch tries to be idiomatic and doesn't try to rewrite the
existing code.  We can move the codec model-specific code into each
codec driver later.

The HD-audio sub-codec component binding is currently specific to
ALC269, hence the management is moved into alc269.c.
After that, alc_free() became identical with snd_hda_gen_free(), and
it's replaced as a macro just to call snd_hda_gen_free().

Signed-off-by: Takashi Iwai <tiwai@suse.de>
Link: https://patch.msgid.link/20250709160434.1859-8-tiwai@suse.de
This commit is contained in:
Takashi Iwai 2025-07-09 18:04:10 +02:00
parent 6014e9021b
commit aeeb85f26c
16 changed files with 6191 additions and 5709 deletions

View file

@ -4,19 +4,6 @@ if SND_HDA
config SND_HDA_GENERIC_LEDS config SND_HDA_GENERIC_LEDS
bool bool
config SND_HDA_CODEC_REALTEK
tristate "Build Realtek HD-audio codec support"
depends on INPUT
select SND_HDA_GENERIC
select SND_HDA_GENERIC_LEDS
select SND_HDA_SCODEC_COMPONENT
help
Say Y or M here to include Realtek HD-audio codec support in
snd-hda-intel driver, such as ALC880.
comment "Set to Y if you want auto-loading the codec driver"
depends on SND_HDA=y && SND_HDA_CODEC_REALTEK=m
config SND_HDA_CODEC_ANALOG config SND_HDA_CODEC_ANALOG
tristate "Build Analog Devices HD-audio codec support" tristate "Build Analog Devices HD-audio codec support"
select SND_HDA_GENERIC select SND_HDA_GENERIC
@ -162,6 +149,7 @@ config SND_HDA_INTEL_HDMI_SILENT_STREAM
This feature can impact power consumption as resources This feature can impact power consumption as resources
are kept reserved both at transmitter and receiver. are kept reserved both at transmitter and receiver.
source "sound/hda/codecs/realtek/Kconfig"
source "sound/hda/codecs/cirrus/Kconfig" source "sound/hda/codecs/cirrus/Kconfig"
source "sound/hda/codecs/side-codecs/Kconfig" source "sound/hda/codecs/side-codecs/Kconfig"

View file

@ -2,30 +2,31 @@
subdir-ccflags-y += -I$(src)/../common subdir-ccflags-y += -I$(src)/../common
snd-hda-codec-generic-y := generic.o snd-hda-codec-generic-y := generic.o
snd-hda-codec-cmedia-y := cmedia.o
snd-hda-codec-analog-y := analog.o snd-hda-codec-analog-y := analog.o
snd-hda-codec-ca0110-y := ca0110.o snd-hda-codec-ca0110-y := ca0110.o
snd-hda-codec-ca0132-y := ca0132.o snd-hda-codec-ca0132-y := ca0132.o
snd-hda-codec-cmedia-y := cmedia.o snd-hda-codec-cmedia-y := cmedia.o
snd-hda-codec-conexant-y := conexant.o snd-hda-codec-conexant-y := conexant.o
snd-hda-codec-idt-y := sigmatel.o snd-hda-codec-idt-y := sigmatel.o
snd-hda-codec-realtek-y := realtek.o
snd-hda-codec-senarytech-y := senarytech.o snd-hda-codec-senarytech-y := senarytech.o
snd-hda-codec-si3054-y := si3054.o snd-hda-codec-si3054-y := si3054.o
snd-hda-codec-via-y := via.o snd-hda-codec-via-y := via.o
obj-y += cirrus/ obj-y += cirrus/
obj-y += hdmi/ obj-y += hdmi/
obj-y += realtek/
obj-y += side-codecs/ obj-y += side-codecs/
# codec drivers # codec drivers
obj-$(CONFIG_SND_HDA_GENERIC) += snd-hda-codec-generic.o obj-$(CONFIG_SND_HDA_GENERIC) += snd-hda-codec-generic.o
obj-$(CONFIG_SND_HDA_CODEC_CMEDIA) += snd-hda-codec-cmedia.o
obj-$(CONFIG_SND_HDA_CODEC_ANALOG) += snd-hda-codec-analog.o obj-$(CONFIG_SND_HDA_CODEC_ANALOG) += snd-hda-codec-analog.o
obj-$(CONFIG_SND_HDA_CODEC_CA0110) += snd-hda-codec-ca0110.o obj-$(CONFIG_SND_HDA_CODEC_CA0110) += snd-hda-codec-ca0110.o
obj-$(CONFIG_SND_HDA_CODEC_CA0132) += snd-hda-codec-ca0132.o obj-$(CONFIG_SND_HDA_CODEC_CA0132) += snd-hda-codec-ca0132.o
obj-$(CONFIG_SND_HDA_CODEC_CMEDIA) += snd-hda-codec-cmedia.o obj-$(CONFIG_SND_HDA_CODEC_CMEDIA) += snd-hda-codec-cmedia.o
obj-$(CONFIG_SND_HDA_CODEC_CONEXANT) += snd-hda-codec-conexant.o obj-$(CONFIG_SND_HDA_CODEC_CONEXANT) += snd-hda-codec-conexant.o
obj-$(CONFIG_SND_HDA_CODEC_SIGMATEL) += snd-hda-codec-idt.o obj-$(CONFIG_SND_HDA_CODEC_SIGMATEL) += snd-hda-codec-idt.o
obj-$(CONFIG_SND_HDA_CODEC_REALTEK) += snd-hda-codec-realtek.o
obj-$(CONFIG_SND_HDA_CODEC_SENARYTECH) += snd-hda-codec-senarytech.o obj-$(CONFIG_SND_HDA_CODEC_SENARYTECH) += snd-hda-codec-senarytech.o
obj-$(CONFIG_SND_HDA_CODEC_SI3054) += snd-hda-codec-si3054.o obj-$(CONFIG_SND_HDA_CODEC_SI3054) += snd-hda-codec-si3054.o
obj-$(CONFIG_SND_HDA_CODEC_VIA) += snd-hda-codec-via.o obj-$(CONFIG_SND_HDA_CODEC_VIA) += snd-hda-codec-via.o

View file

@ -0,0 +1,90 @@
# SPDX-License-Identifier: GPL-2.0-only
menuconfig SND_HDA_CODEC_REALTEK
bool "Realtek HD-audio codec support"
if SND_HDA_CODEC_REALTEK
config SND_HDA_CODEC_REALTEK_LIB
tristate
select SND_HDA_GENERIC
select SND_HDA_GENERIC_LEDS
select SND_HDA_SCODEC_COMPONENT
config SND_HDA_CODEC_ALC260
tristate "Build Realtek ALC260 HD-audio codec support"
depends on INPUT
select SND_HDA_CODEC_REALTEK_LIB
help
Say Y or M here to include Realtek ALC260 HD-audio codec support
config SND_HDA_CODEC_ALC262
tristate "Build Realtek ALC262 HD-audio codec support"
depends on INPUT
select SND_HDA_CODEC_REALTEK_LIB
help
Say Y or M here to include Realtek ALC262 HD-audio codec support
config SND_HDA_CODEC_ALC268
tristate "Build Realtek ALC268 HD-audio codec support"
depends on INPUT
select SND_HDA_CODEC_REALTEK_LIB
help
Say Y or M here to include Realtek ALC268 and compatible HD-audio
codec support
config SND_HDA_CODEC_ALC269
tristate "Build Realtek ALC269 HD-audio codecs support"
depends on INPUT
select SND_HDA_CODEC_REALTEK_LIB
help
Say Y or M here to include Realtek ALC269 and compatible HD-audio
codec support
config SND_HDA_CODEC_ALC662
tristate "Build Realtek ALC662 HD-audio codecs support"
depends on INPUT
select SND_HDA_CODEC_REALTEK_LIB
help
Say Y or M here to include Realtek ALC662 and compatible HD-audio
codec support
config SND_HDA_CODEC_ALC680
tristate "Build Realtek ALC680 HD-audio codecs support"
depends on INPUT
select SND_HDA_CODEC_REALTEK_LIB
help
Say Y or M here to include Realtek ALC680 HD-audio codec support
config SND_HDA_CODEC_ALC861
tristate "Build Realtek ALC861 HD-audio codecs support"
depends on INPUT
select SND_HDA_CODEC_REALTEK_LIB
help
Say Y or M here to include Realtek ALC861 HD-audio codec support
config SND_HDA_CODEC_ALC861VD
tristate "Build Realtek ALC861-VD HD-audio codecs support"
depends on INPUT
select SND_HDA_CODEC_REALTEK_LIB
help
Say Y or M here to include Realtek ALC861-VD HD-audio codec support
config SND_HDA_CODEC_ALC880
tristate "Build Realtek ALC880 HD-audio codecs support"
depends on INPUT
select SND_HDA_CODEC_REALTEK_LIB
help
Say Y or M here to include Realtek ALC880 HD-audio codec support
config SND_HDA_CODEC_ALC882
tristate "Build Realtek ALC882 HD-audio codecs support"
depends on INPUT
select SND_HDA_CODEC_REALTEK_LIB
help
Say Y or M here to include Realtek ALC882 and compatible HD-audio
codec support
endif

View file

@ -0,0 +1,26 @@
# SPDX-License-Identifier: GPL-2.0
subdir-ccflags-y += -I$(src)/../../common
snd-hda-codec-realtek-lib-y := realtek.o
snd-hda-codec-alc260-y := alc260.o
snd-hda-codec-alc262-y := alc262.o
snd-hda-codec-alc268-y := alc268.o
snd-hda-codec-alc269-y := alc269.o
snd-hda-codec-alc662-y := alc662.o
snd-hda-codec-alc680-y := alc680.o
snd-hda-codec-alc861-y := alc861.o
snd-hda-codec-alc861vd-y := alc861vd.o
snd-hda-codec-alc880-y := alc880.o
snd-hda-codec-alc882-y := alc882.o
obj-$(CONFIG_SND_HDA_CODEC_REALTEK_LIB) += snd-hda-codec-realtek-lib.o
obj-$(CONFIG_SND_HDA_CODEC_ALC260) += snd-hda-codec-alc260.o
obj-$(CONFIG_SND_HDA_CODEC_ALC262) += snd-hda-codec-alc262.o
obj-$(CONFIG_SND_HDA_CODEC_ALC268) += snd-hda-codec-alc268.o
obj-$(CONFIG_SND_HDA_CODEC_ALC269) += snd-hda-codec-alc269.o
obj-$(CONFIG_SND_HDA_CODEC_ALC662) += snd-hda-codec-alc662.o
obj-$(CONFIG_SND_HDA_CODEC_ALC680) += snd-hda-codec-alc680.o
obj-$(CONFIG_SND_HDA_CODEC_ALC861) += snd-hda-codec-alc861.o
obj-$(CONFIG_SND_HDA_CODEC_ALC861VD) += snd-hda-codec-alc861vd.o
obj-$(CONFIG_SND_HDA_CODEC_ALC880) += snd-hda-codec-alc880.o
obj-$(CONFIG_SND_HDA_CODEC_ALC882) += snd-hda-codec-alc882.o

View file

@ -0,0 +1,276 @@
// SPDX-License-Identifier: GPL-2.0-or-later
//
// Realtek ALC260 codec
//
#include <linux/init.h>
#include <linux/module.h>
#include "realtek.h"
static int alc260_parse_auto_config(struct hda_codec *codec)
{
static const hda_nid_t alc260_ignore[] = { 0x17, 0 };
static const hda_nid_t alc260_ssids[] = { 0x10, 0x15, 0x0f, 0 };
return alc_parse_auto_config(codec, alc260_ignore, alc260_ssids);
}
/*
* Pin config fixes
*/
enum {
ALC260_FIXUP_HP_DC5750,
ALC260_FIXUP_HP_PIN_0F,
ALC260_FIXUP_COEF,
ALC260_FIXUP_GPIO1,
ALC260_FIXUP_GPIO1_TOGGLE,
ALC260_FIXUP_REPLACER,
ALC260_FIXUP_HP_B1900,
ALC260_FIXUP_KN1,
ALC260_FIXUP_FSC_S7020,
ALC260_FIXUP_FSC_S7020_JWSE,
ALC260_FIXUP_VAIO_PINS,
};
static void alc260_gpio1_automute(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
alc_update_gpio_data(codec, 0x01, spec->gen.hp_jack_present);
}
static void alc260_fixup_gpio1_toggle(struct hda_codec *codec,
const struct hda_fixup *fix, int action)
{
struct alc_spec *spec = codec->spec;
if (action == HDA_FIXUP_ACT_PROBE) {
/* although the machine has only one output pin, we need to
* toggle GPIO1 according to the jack state
*/
spec->gen.automute_hook = alc260_gpio1_automute;
spec->gen.detect_hp = 1;
spec->gen.automute_speaker = 1;
spec->gen.autocfg.hp_pins[0] = 0x0f; /* copy it for automute */
snd_hda_jack_detect_enable_callback(codec, 0x0f,
snd_hda_gen_hp_automute);
alc_setup_gpio(codec, 0x01);
}
}
static void alc260_fixup_kn1(struct hda_codec *codec,
const struct hda_fixup *fix, int action)
{
struct alc_spec *spec = codec->spec;
static const struct hda_pintbl pincfgs[] = {
{ 0x0f, 0x02214000 }, /* HP/speaker */
{ 0x12, 0x90a60160 }, /* int mic */
{ 0x13, 0x02a19000 }, /* ext mic */
{ 0x18, 0x01446000 }, /* SPDIF out */
/* disable bogus I/O pins */
{ 0x10, 0x411111f0 },
{ 0x11, 0x411111f0 },
{ 0x14, 0x411111f0 },
{ 0x15, 0x411111f0 },
{ 0x16, 0x411111f0 },
{ 0x17, 0x411111f0 },
{ 0x19, 0x411111f0 },
{ }
};
switch (action) {
case HDA_FIXUP_ACT_PRE_PROBE:
snd_hda_apply_pincfgs(codec, pincfgs);
spec->init_amp = ALC_INIT_NONE;
break;
}
}
static void alc260_fixup_fsc_s7020(struct hda_codec *codec,
const struct hda_fixup *fix, int action)
{
struct alc_spec *spec = codec->spec;
if (action == HDA_FIXUP_ACT_PRE_PROBE)
spec->init_amp = ALC_INIT_NONE;
}
static void alc260_fixup_fsc_s7020_jwse(struct hda_codec *codec,
const struct hda_fixup *fix, int action)
{
struct alc_spec *spec = codec->spec;
if (action == HDA_FIXUP_ACT_PRE_PROBE) {
spec->gen.add_jack_modes = 1;
spec->gen.hp_mic = 1;
}
}
static const struct hda_fixup alc260_fixups[] = {
[ALC260_FIXUP_HP_DC5750] = {
.type = HDA_FIXUP_PINS,
.v.pins = (const struct hda_pintbl[]) {
{ 0x11, 0x90130110 }, /* speaker */
{ }
}
},
[ALC260_FIXUP_HP_PIN_0F] = {
.type = HDA_FIXUP_PINS,
.v.pins = (const struct hda_pintbl[]) {
{ 0x0f, 0x01214000 }, /* HP */
{ }
}
},
[ALC260_FIXUP_COEF] = {
.type = HDA_FIXUP_VERBS,
.v.verbs = (const struct hda_verb[]) {
{ 0x1a, AC_VERB_SET_COEF_INDEX, 0x07 },
{ 0x1a, AC_VERB_SET_PROC_COEF, 0x3040 },
{ }
},
},
[ALC260_FIXUP_GPIO1] = {
.type = HDA_FIXUP_FUNC,
.v.func = alc_fixup_gpio1,
},
[ALC260_FIXUP_GPIO1_TOGGLE] = {
.type = HDA_FIXUP_FUNC,
.v.func = alc260_fixup_gpio1_toggle,
.chained = true,
.chain_id = ALC260_FIXUP_HP_PIN_0F,
},
[ALC260_FIXUP_REPLACER] = {
.type = HDA_FIXUP_VERBS,
.v.verbs = (const struct hda_verb[]) {
{ 0x1a, AC_VERB_SET_COEF_INDEX, 0x07 },
{ 0x1a, AC_VERB_SET_PROC_COEF, 0x3050 },
{ }
},
.chained = true,
.chain_id = ALC260_FIXUP_GPIO1_TOGGLE,
},
[ALC260_FIXUP_HP_B1900] = {
.type = HDA_FIXUP_FUNC,
.v.func = alc260_fixup_gpio1_toggle,
.chained = true,
.chain_id = ALC260_FIXUP_COEF,
},
[ALC260_FIXUP_KN1] = {
.type = HDA_FIXUP_FUNC,
.v.func = alc260_fixup_kn1,
},
[ALC260_FIXUP_FSC_S7020] = {
.type = HDA_FIXUP_FUNC,
.v.func = alc260_fixup_fsc_s7020,
},
[ALC260_FIXUP_FSC_S7020_JWSE] = {
.type = HDA_FIXUP_FUNC,
.v.func = alc260_fixup_fsc_s7020_jwse,
.chained = true,
.chain_id = ALC260_FIXUP_FSC_S7020,
},
[ALC260_FIXUP_VAIO_PINS] = {
.type = HDA_FIXUP_PINS,
.v.pins = (const struct hda_pintbl[]) {
/* Pin configs are missing completely on some VAIOs */
{ 0x0f, 0x01211020 },
{ 0x10, 0x0001003f },
{ 0x11, 0x411111f0 },
{ 0x12, 0x01a15930 },
{ 0x13, 0x411111f0 },
{ 0x14, 0x411111f0 },
{ 0x15, 0x411111f0 },
{ 0x16, 0x411111f0 },
{ 0x17, 0x411111f0 },
{ 0x18, 0x411111f0 },
{ 0x19, 0x411111f0 },
{ }
}
},
};
static const struct hda_quirk alc260_fixup_tbl[] = {
SND_PCI_QUIRK(0x1025, 0x007b, "Acer C20x", ALC260_FIXUP_GPIO1),
SND_PCI_QUIRK(0x1025, 0x007f, "Acer Aspire 9500", ALC260_FIXUP_COEF),
SND_PCI_QUIRK(0x1025, 0x008f, "Acer", ALC260_FIXUP_GPIO1),
SND_PCI_QUIRK(0x103c, 0x280a, "HP dc5750", ALC260_FIXUP_HP_DC5750),
SND_PCI_QUIRK(0x103c, 0x30ba, "HP Presario B1900", ALC260_FIXUP_HP_B1900),
SND_PCI_QUIRK(0x104d, 0x81bb, "Sony VAIO", ALC260_FIXUP_VAIO_PINS),
SND_PCI_QUIRK(0x104d, 0x81e2, "Sony VAIO TX", ALC260_FIXUP_HP_PIN_0F),
SND_PCI_QUIRK(0x10cf, 0x1326, "FSC LifeBook S7020", ALC260_FIXUP_FSC_S7020),
SND_PCI_QUIRK(0x1509, 0x4540, "Favorit 100XS", ALC260_FIXUP_GPIO1),
SND_PCI_QUIRK(0x152d, 0x0729, "Quanta KN1", ALC260_FIXUP_KN1),
SND_PCI_QUIRK(0x161f, 0x2057, "Replacer 672V", ALC260_FIXUP_REPLACER),
SND_PCI_QUIRK(0x1631, 0xc017, "PB V7900", ALC260_FIXUP_COEF),
{}
};
static const struct hda_model_fixup alc260_fixup_models[] = {
{.id = ALC260_FIXUP_GPIO1, .name = "gpio1"},
{.id = ALC260_FIXUP_COEF, .name = "coef"},
{.id = ALC260_FIXUP_FSC_S7020, .name = "fujitsu"},
{.id = ALC260_FIXUP_FSC_S7020_JWSE, .name = "fujitsu-jwse"},
{}
};
/*
*/
static int patch_alc260(struct hda_codec *codec)
{
struct alc_spec *spec;
int err;
err = alc_alloc_spec(codec, 0x07);
if (err < 0)
return err;
spec = codec->spec;
/* as quite a few machines require HP amp for speaker outputs,
* it's easier to enable it unconditionally; even if it's unneeded,
* it's almost harmless.
*/
spec->gen.prefer_hp_amp = 1;
spec->gen.beep_nid = 0x01;
spec->shutup = alc_eapd_shutup;
alc_pre_init(codec);
snd_hda_pick_fixup(codec, alc260_fixup_models, alc260_fixup_tbl,
alc260_fixups);
snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
/* automatic parse from the BIOS config */
err = alc260_parse_auto_config(codec);
if (err < 0)
goto error;
if (!spec->gen.no_analog) {
err = set_beep_amp(spec, 0x07, 0x05, HDA_INPUT);
if (err < 0)
goto error;
}
snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
return 0;
error:
alc_free(codec);
return err;
}
/*
* driver entries
*/
static const struct hda_device_id snd_hda_id_alc260[] = {
HDA_CODEC_ENTRY(0x10ec0260, "ALC260", patch_alc260),
{} /* terminator */
};
MODULE_DEVICE_TABLE(hdaudio, snd_hda_id_alc260);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Realtek ALC260 HD-audio codec");
MODULE_IMPORT_NS("SND_HDA_CODEC_REALTEK");
static struct hda_codec_driver alc260_driver = {
.id = snd_hda_id_alc260,
};
module_hda_codec_driver(alc260_driver);

View file

@ -0,0 +1,199 @@
// SPDX-License-Identifier: GPL-2.0-or-later
//
// Realtek ALC262 codec
//
#include <linux/init.h>
#include <linux/module.h>
#include "realtek.h"
static int alc262_parse_auto_config(struct hda_codec *codec)
{
static const hda_nid_t alc262_ignore[] = { 0x1d, 0 };
static const hda_nid_t alc262_ssids[] = { 0x15, 0x1b, 0x14, 0 };
return alc_parse_auto_config(codec, alc262_ignore, alc262_ssids);
}
/*
* Pin config fixes
*/
enum {
ALC262_FIXUP_FSC_H270,
ALC262_FIXUP_FSC_S7110,
ALC262_FIXUP_HP_Z200,
ALC262_FIXUP_TYAN,
ALC262_FIXUP_LENOVO_3000,
ALC262_FIXUP_BENQ,
ALC262_FIXUP_BENQ_T31,
ALC262_FIXUP_INV_DMIC,
ALC262_FIXUP_INTEL_BAYLEYBAY,
};
static const struct hda_fixup alc262_fixups[] = {
[ALC262_FIXUP_FSC_H270] = {
.type = HDA_FIXUP_PINS,
.v.pins = (const struct hda_pintbl[]) {
{ 0x14, 0x99130110 }, /* speaker */
{ 0x15, 0x0221142f }, /* front HP */
{ 0x1b, 0x0121141f }, /* rear HP */
{ }
}
},
[ALC262_FIXUP_FSC_S7110] = {
.type = HDA_FIXUP_PINS,
.v.pins = (const struct hda_pintbl[]) {
{ 0x15, 0x90170110 }, /* speaker */
{ }
},
.chained = true,
.chain_id = ALC262_FIXUP_BENQ,
},
[ALC262_FIXUP_HP_Z200] = {
.type = HDA_FIXUP_PINS,
.v.pins = (const struct hda_pintbl[]) {
{ 0x16, 0x99130120 }, /* internal speaker */
{ }
}
},
[ALC262_FIXUP_TYAN] = {
.type = HDA_FIXUP_PINS,
.v.pins = (const struct hda_pintbl[]) {
{ 0x14, 0x1993e1f0 }, /* int AUX */
{ }
}
},
[ALC262_FIXUP_LENOVO_3000] = {
.type = HDA_FIXUP_PINCTLS,
.v.pins = (const struct hda_pintbl[]) {
{ 0x19, PIN_VREF50 },
{}
},
.chained = true,
.chain_id = ALC262_FIXUP_BENQ,
},
[ALC262_FIXUP_BENQ] = {
.type = HDA_FIXUP_VERBS,
.v.verbs = (const struct hda_verb[]) {
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x07 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x3070 },
{}
}
},
[ALC262_FIXUP_BENQ_T31] = {
.type = HDA_FIXUP_VERBS,
.v.verbs = (const struct hda_verb[]) {
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x07 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x3050 },
{}
}
},
[ALC262_FIXUP_INV_DMIC] = {
.type = HDA_FIXUP_FUNC,
.v.func = alc_fixup_inv_dmic,
},
[ALC262_FIXUP_INTEL_BAYLEYBAY] = {
.type = HDA_FIXUP_FUNC,
.v.func = alc_fixup_no_depop_delay,
},
};
static const struct hda_quirk alc262_fixup_tbl[] = {
SND_PCI_QUIRK(0x103c, 0x170b, "HP Z200", ALC262_FIXUP_HP_Z200),
SND_PCI_QUIRK(0x10cf, 0x1397, "Fujitsu Lifebook S7110", ALC262_FIXUP_FSC_S7110),
SND_PCI_QUIRK(0x10cf, 0x142d, "Fujitsu Lifebook E8410", ALC262_FIXUP_BENQ),
SND_PCI_QUIRK(0x10f1, 0x2915, "Tyan Thunder n6650W", ALC262_FIXUP_TYAN),
SND_PCI_QUIRK(0x1734, 0x1141, "FSC ESPRIMO U9210", ALC262_FIXUP_FSC_H270),
SND_PCI_QUIRK(0x1734, 0x1147, "FSC Celsius H270", ALC262_FIXUP_FSC_H270),
SND_PCI_QUIRK(0x17aa, 0x384e, "Lenovo 3000", ALC262_FIXUP_LENOVO_3000),
SND_PCI_QUIRK(0x17ff, 0x0560, "Benq ED8", ALC262_FIXUP_BENQ),
SND_PCI_QUIRK(0x17ff, 0x058d, "Benq T31-16", ALC262_FIXUP_BENQ_T31),
SND_PCI_QUIRK(0x8086, 0x7270, "BayleyBay", ALC262_FIXUP_INTEL_BAYLEYBAY),
{}
};
static const struct hda_model_fixup alc262_fixup_models[] = {
{.id = ALC262_FIXUP_INV_DMIC, .name = "inv-dmic"},
{.id = ALC262_FIXUP_FSC_H270, .name = "fsc-h270"},
{.id = ALC262_FIXUP_FSC_S7110, .name = "fsc-s7110"},
{.id = ALC262_FIXUP_HP_Z200, .name = "hp-z200"},
{.id = ALC262_FIXUP_TYAN, .name = "tyan"},
{.id = ALC262_FIXUP_LENOVO_3000, .name = "lenovo-3000"},
{.id = ALC262_FIXUP_BENQ, .name = "benq"},
{.id = ALC262_FIXUP_BENQ_T31, .name = "benq-t31"},
{.id = ALC262_FIXUP_INTEL_BAYLEYBAY, .name = "bayleybay"},
{}
};
/*
*/
static int patch_alc262(struct hda_codec *codec)
{
struct alc_spec *spec;
int err;
err = alc_alloc_spec(codec, 0x0b);
if (err < 0)
return err;
spec = codec->spec;
spec->gen.shared_mic_vref_pin = 0x18;
spec->shutup = alc_eapd_shutup;
#if 0
/* pshou 07/11/05 set a zero PCM sample to DAC when FIFO is
* under-run
*/
alc_update_coefex_idx(codec, 0x1a, 7, 0, 0x80);
#endif
alc_fix_pll_init(codec, 0x20, 0x0a, 10);
alc_pre_init(codec);
snd_hda_pick_fixup(codec, alc262_fixup_models, alc262_fixup_tbl,
alc262_fixups);
snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
alc_auto_parse_customize_define(codec);
if (has_cdefine_beep(codec))
spec->gen.beep_nid = 0x01;
/* automatic parse from the BIOS config */
err = alc262_parse_auto_config(codec);
if (err < 0)
goto error;
if (!spec->gen.no_analog && spec->gen.beep_nid) {
err = set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
if (err < 0)
goto error;
}
snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
return 0;
error:
alc_free(codec);
return err;
}
/*
* driver entries
*/
static const struct hda_device_id snd_hda_id_alc262[] = {
HDA_CODEC_ENTRY(0x10ec0262, "ALC262", patch_alc262),
{} /* terminator */
};
MODULE_DEVICE_TABLE(hdaudio, snd_hda_id_alc262);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Realtek ALC262 HD-audio codec");
MODULE_IMPORT_NS("SND_HDA_CODEC_REALTEK");
static struct hda_codec_driver alc262_driver = {
.id = snd_hda_id_alc262,
};
module_hda_codec_driver(alc262_driver);

View file

@ -0,0 +1,176 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#include <linux/init.h>
#include <linux/module.h>
#include "realtek.h"
/* bind Beep switches of both NID 0x0f and 0x10 */
static int alc268_beep_switch_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
unsigned long pval;
int err;
mutex_lock(&codec->control_mutex);
pval = kcontrol->private_value;
kcontrol->private_value = (pval & ~0xff) | 0x0f;
err = snd_hda_mixer_amp_switch_put(kcontrol, ucontrol);
if (err >= 0) {
kcontrol->private_value = (pval & ~0xff) | 0x10;
err = snd_hda_mixer_amp_switch_put(kcontrol, ucontrol);
}
kcontrol->private_value = pval;
mutex_unlock(&codec->control_mutex);
return err;
}
static const struct snd_kcontrol_new alc268_beep_mixer[] = {
HDA_CODEC_VOLUME("Beep Playback Volume", 0x1d, 0x0, HDA_INPUT),
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Beep Playback Switch",
.subdevice = HDA_SUBDEV_AMP_FLAG,
.info = snd_hda_mixer_amp_switch_info,
.get = snd_hda_mixer_amp_switch_get,
.put = alc268_beep_switch_put,
.private_value = HDA_COMPOSE_AMP_VAL(0x0f, 3, 1, HDA_INPUT)
},
};
/* set PCBEEP vol = 0, mute connections */
static const struct hda_verb alc268_beep_init_verbs[] = {
{0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
{0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
{ }
};
enum {
ALC268_FIXUP_INV_DMIC,
ALC268_FIXUP_HP_EAPD,
ALC268_FIXUP_SPDIF,
};
static const struct hda_fixup alc268_fixups[] = {
[ALC268_FIXUP_INV_DMIC] = {
.type = HDA_FIXUP_FUNC,
.v.func = alc_fixup_inv_dmic,
},
[ALC268_FIXUP_HP_EAPD] = {
.type = HDA_FIXUP_VERBS,
.v.verbs = (const struct hda_verb[]) {
{0x15, AC_VERB_SET_EAPD_BTLENABLE, 0},
{}
}
},
[ALC268_FIXUP_SPDIF] = {
.type = HDA_FIXUP_PINS,
.v.pins = (const struct hda_pintbl[]) {
{ 0x1e, 0x014b1180 }, /* enable SPDIF out */
{}
}
},
};
static const struct hda_model_fixup alc268_fixup_models[] = {
{.id = ALC268_FIXUP_INV_DMIC, .name = "inv-dmic"},
{.id = ALC268_FIXUP_HP_EAPD, .name = "hp-eapd"},
{.id = ALC268_FIXUP_SPDIF, .name = "spdif"},
{}
};
static const struct hda_quirk alc268_fixup_tbl[] = {
SND_PCI_QUIRK(0x1025, 0x0139, "Acer TravelMate 6293", ALC268_FIXUP_SPDIF),
SND_PCI_QUIRK(0x1025, 0x015b, "Acer AOA 150 (ZG5)", ALC268_FIXUP_INV_DMIC),
/* below is codec SSID since multiple Toshiba laptops have the
* same PCI SSID 1179:ff00
*/
SND_PCI_QUIRK(0x1179, 0xff06, "Toshiba P200", ALC268_FIXUP_HP_EAPD),
{}
};
/*
* BIOS auto configuration
*/
static int alc268_parse_auto_config(struct hda_codec *codec)
{
static const hda_nid_t alc268_ssids[] = { 0x15, 0x1b, 0x14, 0 };
return alc_parse_auto_config(codec, NULL, alc268_ssids);
}
/*
*/
static int patch_alc268(struct hda_codec *codec)
{
struct alc_spec *spec;
int i, err;
/* ALC268 has no aa-loopback mixer */
err = alc_alloc_spec(codec, 0);
if (err < 0)
return err;
spec = codec->spec;
if (has_cdefine_beep(codec))
spec->gen.beep_nid = 0x01;
spec->shutup = alc_eapd_shutup;
alc_pre_init(codec);
snd_hda_pick_fixup(codec, alc268_fixup_models, alc268_fixup_tbl, alc268_fixups);
snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
/* automatic parse from the BIOS config */
err = alc268_parse_auto_config(codec);
if (err < 0)
goto error;
if (err > 0 && !spec->gen.no_analog &&
spec->gen.autocfg.speaker_pins[0] != 0x1d) {
for (i = 0; i < ARRAY_SIZE(alc268_beep_mixer); i++) {
if (!snd_hda_gen_add_kctl(&spec->gen, NULL,
&alc268_beep_mixer[i])) {
err = -ENOMEM;
goto error;
}
}
snd_hda_add_verbs(codec, alc268_beep_init_verbs);
if (!query_amp_caps(codec, 0x1d, HDA_INPUT))
/* override the amp caps for beep generator */
snd_hda_override_amp_caps(codec, 0x1d, HDA_INPUT,
(0x0c << AC_AMPCAP_OFFSET_SHIFT) |
(0x0c << AC_AMPCAP_NUM_STEPS_SHIFT) |
(0x07 << AC_AMPCAP_STEP_SIZE_SHIFT) |
(0 << AC_AMPCAP_MUTE_SHIFT));
}
snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
return 0;
error:
alc_free(codec);
return err;
}
/*
* driver entries
*/
static const struct hda_device_id snd_hda_id_alc268[] = {
HDA_CODEC_ENTRY(0x10ec0267, "ALC267", patch_alc268),
HDA_CODEC_ENTRY(0x10ec0268, "ALC268", patch_alc268),
{} /* terminator */
};
MODULE_DEVICE_TABLE(hdaudio, snd_hda_id_alc268);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Realtek ALC267/268 HD-audio codec");
MODULE_IMPORT_NS("SND_HDA_CODEC_REALTEK");
static struct hda_codec_driver alc268_driver = {
.id = snd_hda_id_alc268,
};
module_hda_codec_driver(alc268_driver);

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,53 @@
// SPDX-License-Identifier: GPL-2.0-or-later
//
// Realtek ALC680 codec
//
#include <linux/init.h>
#include <linux/module.h>
#include "realtek.h"
static int alc680_parse_auto_config(struct hda_codec *codec)
{
return alc_parse_auto_config(codec, NULL, NULL);
}
/*
*/
static int patch_alc680(struct hda_codec *codec)
{
int err;
/* ALC680 has no aa-loopback mixer */
err = alc_alloc_spec(codec, 0);
if (err < 0)
return err;
/* automatic parse from the BIOS config */
err = alc680_parse_auto_config(codec);
if (err < 0) {
alc_free(codec);
return err;
}
return 0;
}
/*
* driver entries
*/
static const struct hda_device_id snd_hda_id_alc680[] = {
HDA_CODEC_ENTRY(0x10ec0680, "ALC680", patch_alc680),
{} /* terminator */
};
MODULE_DEVICE_TABLE(hdaudio, snd_hda_id_alc680);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Realtek ALC680 HD-audio codec");
MODULE_IMPORT_NS("SND_HDA_CODEC_REALTEK");
static struct hda_codec_driver alc680_driver = {
.id = snd_hda_id_alc680,
};
module_hda_codec_driver(alc680_driver);

View file

@ -0,0 +1,149 @@
// SPDX-License-Identifier: GPL-2.0-or-later
//
// Realtek ALC861 codec
//
#include <linux/init.h>
#include <linux/module.h>
#include "realtek.h"
static int alc861_parse_auto_config(struct hda_codec *codec)
{
static const hda_nid_t alc861_ignore[] = { 0x1d, 0 };
static const hda_nid_t alc861_ssids[] = { 0x0e, 0x0f, 0x0b, 0 };
return alc_parse_auto_config(codec, alc861_ignore, alc861_ssids);
}
/* Pin config fixes */
enum {
ALC861_FIXUP_FSC_AMILO_PI1505,
ALC861_FIXUP_AMP_VREF_0F,
ALC861_FIXUP_NO_JACK_DETECT,
ALC861_FIXUP_ASUS_A6RP,
ALC660_FIXUP_ASUS_W7J,
};
/* On some laptops, VREF of pin 0x0f is abused for controlling the main amp */
static void alc861_fixup_asus_amp_vref_0f(struct hda_codec *codec,
const struct hda_fixup *fix, int action)
{
struct alc_spec *spec = codec->spec;
unsigned int val;
if (action != HDA_FIXUP_ACT_INIT)
return;
val = snd_hda_codec_get_pin_target(codec, 0x0f);
if (!(val & (AC_PINCTL_IN_EN | AC_PINCTL_OUT_EN)))
val |= AC_PINCTL_IN_EN;
val |= AC_PINCTL_VREF_50;
snd_hda_set_pin_ctl(codec, 0x0f, val);
spec->gen.keep_vref_in_automute = 1;
}
static const struct hda_fixup alc861_fixups[] = {
[ALC861_FIXUP_FSC_AMILO_PI1505] = {
.type = HDA_FIXUP_PINS,
.v.pins = (const struct hda_pintbl[]) {
{ 0x0b, 0x0221101f }, /* HP */
{ 0x0f, 0x90170310 }, /* speaker */
{ }
}
},
[ALC861_FIXUP_AMP_VREF_0F] = {
.type = HDA_FIXUP_FUNC,
.v.func = alc861_fixup_asus_amp_vref_0f,
},
[ALC861_FIXUP_NO_JACK_DETECT] = {
.type = HDA_FIXUP_FUNC,
.v.func = alc_fixup_no_jack_detect,
},
[ALC861_FIXUP_ASUS_A6RP] = {
.type = HDA_FIXUP_FUNC,
.v.func = alc861_fixup_asus_amp_vref_0f,
.chained = true,
.chain_id = ALC861_FIXUP_NO_JACK_DETECT,
},
[ALC660_FIXUP_ASUS_W7J] = {
.type = HDA_FIXUP_VERBS,
.v.verbs = (const struct hda_verb[]) {
/* ASUS W7J needs a magic pin setup on unused NID 0x10
* for enabling outputs
*/
{0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
{ }
},
}
};
static const struct hda_quirk alc861_fixup_tbl[] = {
SND_PCI_QUIRK(0x1043, 0x1253, "ASUS W7J", ALC660_FIXUP_ASUS_W7J),
SND_PCI_QUIRK(0x1043, 0x1263, "ASUS Z35HL", ALC660_FIXUP_ASUS_W7J),
SND_PCI_QUIRK(0x1043, 0x1393, "ASUS A6Rp", ALC861_FIXUP_ASUS_A6RP),
SND_PCI_QUIRK_VENDOR(0x1043, "ASUS laptop", ALC861_FIXUP_AMP_VREF_0F),
SND_PCI_QUIRK(0x1462, 0x7254, "HP DX2200", ALC861_FIXUP_NO_JACK_DETECT),
SND_PCI_QUIRK_VENDOR(0x1584, "Haier/Uniwill", ALC861_FIXUP_AMP_VREF_0F),
SND_PCI_QUIRK(0x1734, 0x10c7, "FSC Amilo Pi1505", ALC861_FIXUP_FSC_AMILO_PI1505),
{}
};
/*
*/
static int patch_alc861(struct hda_codec *codec)
{
struct alc_spec *spec;
int err;
err = alc_alloc_spec(codec, 0x15);
if (err < 0)
return err;
spec = codec->spec;
if (has_cdefine_beep(codec))
spec->gen.beep_nid = 0x23;
spec->power_hook = alc_power_eapd;
alc_pre_init(codec);
snd_hda_pick_fixup(codec, NULL, alc861_fixup_tbl, alc861_fixups);
snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
/* automatic parse from the BIOS config */
err = alc861_parse_auto_config(codec);
if (err < 0)
goto error;
if (!spec->gen.no_analog) {
err = set_beep_amp(spec, 0x23, 0, HDA_OUTPUT);
if (err < 0)
goto error;
}
snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
return 0;
error:
alc_free(codec);
return err;
}
/*
* driver entries
*/
static const struct hda_device_id snd_hda_id_alc861[] = {
HDA_CODEC_REV_ENTRY(0x10ec0861, 0x100340, "ALC660", patch_alc861),
HDA_CODEC_ENTRY(0x10ec0861, "ALC861", patch_alc861),
{} /* terminator */
};
MODULE_DEVICE_TABLE(hdaudio, snd_hda_id_alc861);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Realtek ALC861 HD-audio codec");
MODULE_IMPORT_NS("SND_HDA_CODEC_REALTEK");
static struct hda_codec_driver alc861_driver = {
.id = snd_hda_id_alc861,
};
module_hda_codec_driver(alc861_driver);

View file

@ -0,0 +1,123 @@
// SPDX-License-Identifier: GPL-2.0-or-later
//
// Realtek ALC861-VD codec
// Based on ALC882
// In addition, an independent DAC
//
#include <linux/init.h>
#include <linux/module.h>
#include "realtek.h"
static int alc861vd_parse_auto_config(struct hda_codec *codec)
{
static const hda_nid_t alc861vd_ignore[] = { 0x1d, 0 };
static const hda_nid_t alc861vd_ssids[] = { 0x15, 0x1b, 0x14, 0 };
return alc_parse_auto_config(codec, alc861vd_ignore, alc861vd_ssids);
}
enum {
ALC660VD_FIX_ASUS_GPIO1,
ALC861VD_FIX_DALLAS,
};
/* exclude VREF80 */
static void alc861vd_fixup_dallas(struct hda_codec *codec,
const struct hda_fixup *fix, int action)
{
if (action == HDA_FIXUP_ACT_PRE_PROBE) {
snd_hda_override_pin_caps(codec, 0x18, 0x00000734);
snd_hda_override_pin_caps(codec, 0x19, 0x0000073c);
}
}
/* reset GPIO1 */
static void alc660vd_fixup_asus_gpio1(struct hda_codec *codec,
const struct hda_fixup *fix, int action)
{
struct alc_spec *spec = codec->spec;
if (action == HDA_FIXUP_ACT_PRE_PROBE)
spec->gpio_mask |= 0x02;
alc_fixup_gpio(codec, action, 0x01);
}
static const struct hda_fixup alc861vd_fixups[] = {
[ALC660VD_FIX_ASUS_GPIO1] = {
.type = HDA_FIXUP_FUNC,
.v.func = alc660vd_fixup_asus_gpio1,
},
[ALC861VD_FIX_DALLAS] = {
.type = HDA_FIXUP_FUNC,
.v.func = alc861vd_fixup_dallas,
},
};
static const struct hda_quirk alc861vd_fixup_tbl[] = {
SND_PCI_QUIRK(0x103c, 0x30bf, "HP TX1000", ALC861VD_FIX_DALLAS),
SND_PCI_QUIRK(0x1043, 0x1339, "ASUS A7-K", ALC660VD_FIX_ASUS_GPIO1),
SND_PCI_QUIRK(0x1179, 0xff31, "Toshiba L30-149", ALC861VD_FIX_DALLAS),
{}
};
/*
*/
static int patch_alc861vd(struct hda_codec *codec)
{
struct alc_spec *spec;
int err;
err = alc_alloc_spec(codec, 0x0b);
if (err < 0)
return err;
spec = codec->spec;
if (has_cdefine_beep(codec))
spec->gen.beep_nid = 0x23;
spec->shutup = alc_eapd_shutup;
alc_pre_init(codec);
snd_hda_pick_fixup(codec, NULL, alc861vd_fixup_tbl, alc861vd_fixups);
snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
/* automatic parse from the BIOS config */
err = alc861vd_parse_auto_config(codec);
if (err < 0)
goto error;
if (!spec->gen.no_analog) {
err = set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
if (err < 0)
goto error;
}
snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
return 0;
error:
alc_free(codec);
return err;
}
/*
* driver entries
*/
static const struct hda_device_id snd_hda_id_alc861vd[] = {
HDA_CODEC_ENTRY(0x10ec0660, "ALC660-VD", patch_alc861vd),
HDA_CODEC_ENTRY(0x10ec0862, "ALC861-VD", patch_alc861vd),
{} /* terminator */
};
MODULE_DEVICE_TABLE(hdaudio, snd_hda_id_alc861vd);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Realtek ALC861-VD HD-audio codec");
MODULE_IMPORT_NS("SND_HDA_CODEC_REALTEK");
static struct hda_codec_driver alc861vd_driver = {
.id = snd_hda_id_alc861vd,
};
module_hda_codec_driver(alc861vd_driver);

View file

@ -0,0 +1,497 @@
// SPDX-License-Identifier: GPL-2.0-or-later
//
// Realtek ALC880 codec
//
#include <linux/init.h>
#include <linux/module.h>
#include "realtek.h"
static void alc880_unsol_event(struct hda_codec *codec, unsigned int res)
{
/* For some reason, the res given from ALC880 is broken.
Here we adjust it properly. */
snd_hda_jack_unsol_event(codec, res >> 2);
}
static int alc880_parse_auto_config(struct hda_codec *codec)
{
static const hda_nid_t alc880_ignore[] = { 0x1d, 0 };
static const hda_nid_t alc880_ssids[] = { 0x15, 0x1b, 0x14, 0 };
return alc_parse_auto_config(codec, alc880_ignore, alc880_ssids);
}
/*
* ALC880 fix-ups
*/
enum {
ALC880_FIXUP_GPIO1,
ALC880_FIXUP_GPIO2,
ALC880_FIXUP_MEDION_RIM,
ALC880_FIXUP_LG,
ALC880_FIXUP_LG_LW25,
ALC880_FIXUP_W810,
ALC880_FIXUP_EAPD_COEF,
ALC880_FIXUP_TCL_S700,
ALC880_FIXUP_VOL_KNOB,
ALC880_FIXUP_FUJITSU,
ALC880_FIXUP_F1734,
ALC880_FIXUP_UNIWILL,
ALC880_FIXUP_UNIWILL_DIG,
ALC880_FIXUP_Z71V,
ALC880_FIXUP_ASUS_W5A,
ALC880_FIXUP_3ST_BASE,
ALC880_FIXUP_3ST,
ALC880_FIXUP_3ST_DIG,
ALC880_FIXUP_5ST_BASE,
ALC880_FIXUP_5ST,
ALC880_FIXUP_5ST_DIG,
ALC880_FIXUP_6ST_BASE,
ALC880_FIXUP_6ST,
ALC880_FIXUP_6ST_DIG,
ALC880_FIXUP_6ST_AUTOMUTE,
};
/* enable the volume-knob widget support on NID 0x21 */
static void alc880_fixup_vol_knob(struct hda_codec *codec,
const struct hda_fixup *fix, int action)
{
if (action == HDA_FIXUP_ACT_PROBE)
snd_hda_jack_detect_enable_callback(codec, 0x21,
alc_update_knob_master);
}
static const struct hda_fixup alc880_fixups[] = {
[ALC880_FIXUP_GPIO1] = {
.type = HDA_FIXUP_FUNC,
.v.func = alc_fixup_gpio1,
},
[ALC880_FIXUP_GPIO2] = {
.type = HDA_FIXUP_FUNC,
.v.func = alc_fixup_gpio2,
},
[ALC880_FIXUP_MEDION_RIM] = {
.type = HDA_FIXUP_VERBS,
.v.verbs = (const struct hda_verb[]) {
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x07 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x3060 },
{ }
},
.chained = true,
.chain_id = ALC880_FIXUP_GPIO2,
},
[ALC880_FIXUP_LG] = {
.type = HDA_FIXUP_PINS,
.v.pins = (const struct hda_pintbl[]) {
/* disable bogus unused pins */
{ 0x16, 0x411111f0 },
{ 0x18, 0x411111f0 },
{ 0x1a, 0x411111f0 },
{ }
}
},
[ALC880_FIXUP_LG_LW25] = {
.type = HDA_FIXUP_PINS,
.v.pins = (const struct hda_pintbl[]) {
{ 0x1a, 0x0181344f }, /* line-in */
{ 0x1b, 0x0321403f }, /* headphone */
{ }
}
},
[ALC880_FIXUP_W810] = {
.type = HDA_FIXUP_PINS,
.v.pins = (const struct hda_pintbl[]) {
/* disable bogus unused pins */
{ 0x17, 0x411111f0 },
{ }
},
.chained = true,
.chain_id = ALC880_FIXUP_GPIO2,
},
[ALC880_FIXUP_EAPD_COEF] = {
.type = HDA_FIXUP_VERBS,
.v.verbs = (const struct hda_verb[]) {
/* change to EAPD mode */
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x07 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x3060 },
{}
},
},
[ALC880_FIXUP_TCL_S700] = {
.type = HDA_FIXUP_VERBS,
.v.verbs = (const struct hda_verb[]) {
/* change to EAPD mode */
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x07 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x3070 },
{}
},
.chained = true,
.chain_id = ALC880_FIXUP_GPIO2,
},
[ALC880_FIXUP_VOL_KNOB] = {
.type = HDA_FIXUP_FUNC,
.v.func = alc880_fixup_vol_knob,
},
[ALC880_FIXUP_FUJITSU] = {
/* override all pins as BIOS on old Amilo is broken */
.type = HDA_FIXUP_PINS,
.v.pins = (const struct hda_pintbl[]) {
{ 0x14, 0x0121401f }, /* HP */
{ 0x15, 0x99030120 }, /* speaker */
{ 0x16, 0x99030130 }, /* bass speaker */
{ 0x17, 0x411111f0 }, /* N/A */
{ 0x18, 0x411111f0 }, /* N/A */
{ 0x19, 0x01a19950 }, /* mic-in */
{ 0x1a, 0x411111f0 }, /* N/A */
{ 0x1b, 0x411111f0 }, /* N/A */
{ 0x1c, 0x411111f0 }, /* N/A */
{ 0x1d, 0x411111f0 }, /* N/A */
{ 0x1e, 0x01454140 }, /* SPDIF out */
{ }
},
.chained = true,
.chain_id = ALC880_FIXUP_VOL_KNOB,
},
[ALC880_FIXUP_F1734] = {
/* almost compatible with FUJITSU, but no bass and SPDIF */
.type = HDA_FIXUP_PINS,
.v.pins = (const struct hda_pintbl[]) {
{ 0x14, 0x0121401f }, /* HP */
{ 0x15, 0x99030120 }, /* speaker */
{ 0x16, 0x411111f0 }, /* N/A */
{ 0x17, 0x411111f0 }, /* N/A */
{ 0x18, 0x411111f0 }, /* N/A */
{ 0x19, 0x01a19950 }, /* mic-in */
{ 0x1a, 0x411111f0 }, /* N/A */
{ 0x1b, 0x411111f0 }, /* N/A */
{ 0x1c, 0x411111f0 }, /* N/A */
{ 0x1d, 0x411111f0 }, /* N/A */
{ 0x1e, 0x411111f0 }, /* N/A */
{ }
},
.chained = true,
.chain_id = ALC880_FIXUP_VOL_KNOB,
},
[ALC880_FIXUP_UNIWILL] = {
/* need to fix HP and speaker pins to be parsed correctly */
.type = HDA_FIXUP_PINS,
.v.pins = (const struct hda_pintbl[]) {
{ 0x14, 0x0121411f }, /* HP */
{ 0x15, 0x99030120 }, /* speaker */
{ 0x16, 0x99030130 }, /* bass speaker */
{ }
},
},
[ALC880_FIXUP_UNIWILL_DIG] = {
.type = HDA_FIXUP_PINS,
.v.pins = (const struct hda_pintbl[]) {
/* disable bogus unused pins */
{ 0x17, 0x411111f0 },
{ 0x19, 0x411111f0 },
{ 0x1b, 0x411111f0 },
{ 0x1f, 0x411111f0 },
{ }
}
},
[ALC880_FIXUP_Z71V] = {
.type = HDA_FIXUP_PINS,
.v.pins = (const struct hda_pintbl[]) {
/* set up the whole pins as BIOS is utterly broken */
{ 0x14, 0x99030120 }, /* speaker */
{ 0x15, 0x0121411f }, /* HP */
{ 0x16, 0x411111f0 }, /* N/A */
{ 0x17, 0x411111f0 }, /* N/A */
{ 0x18, 0x01a19950 }, /* mic-in */
{ 0x19, 0x411111f0 }, /* N/A */
{ 0x1a, 0x01813031 }, /* line-in */
{ 0x1b, 0x411111f0 }, /* N/A */
{ 0x1c, 0x411111f0 }, /* N/A */
{ 0x1d, 0x411111f0 }, /* N/A */
{ 0x1e, 0x0144111e }, /* SPDIF */
{ }
}
},
[ALC880_FIXUP_ASUS_W5A] = {
.type = HDA_FIXUP_PINS,
.v.pins = (const struct hda_pintbl[]) {
/* set up the whole pins as BIOS is utterly broken */
{ 0x14, 0x0121411f }, /* HP */
{ 0x15, 0x411111f0 }, /* N/A */
{ 0x16, 0x411111f0 }, /* N/A */
{ 0x17, 0x411111f0 }, /* N/A */
{ 0x18, 0x90a60160 }, /* mic */
{ 0x19, 0x411111f0 }, /* N/A */
{ 0x1a, 0x411111f0 }, /* N/A */
{ 0x1b, 0x411111f0 }, /* N/A */
{ 0x1c, 0x411111f0 }, /* N/A */
{ 0x1d, 0x411111f0 }, /* N/A */
{ 0x1e, 0xb743111e }, /* SPDIF out */
{ }
},
.chained = true,
.chain_id = ALC880_FIXUP_GPIO1,
},
[ALC880_FIXUP_3ST_BASE] = {
.type = HDA_FIXUP_PINS,
.v.pins = (const struct hda_pintbl[]) {
{ 0x14, 0x01014010 }, /* line-out */
{ 0x15, 0x411111f0 }, /* N/A */
{ 0x16, 0x411111f0 }, /* N/A */
{ 0x17, 0x411111f0 }, /* N/A */
{ 0x18, 0x01a19c30 }, /* mic-in */
{ 0x19, 0x0121411f }, /* HP */
{ 0x1a, 0x01813031 }, /* line-in */
{ 0x1b, 0x02a19c40 }, /* front-mic */
{ 0x1c, 0x411111f0 }, /* N/A */
{ 0x1d, 0x411111f0 }, /* N/A */
/* 0x1e is filled in below */
{ 0x1f, 0x411111f0 }, /* N/A */
{ }
}
},
[ALC880_FIXUP_3ST] = {
.type = HDA_FIXUP_PINS,
.v.pins = (const struct hda_pintbl[]) {
{ 0x1e, 0x411111f0 }, /* N/A */
{ }
},
.chained = true,
.chain_id = ALC880_FIXUP_3ST_BASE,
},
[ALC880_FIXUP_3ST_DIG] = {
.type = HDA_FIXUP_PINS,
.v.pins = (const struct hda_pintbl[]) {
{ 0x1e, 0x0144111e }, /* SPDIF */
{ }
},
.chained = true,
.chain_id = ALC880_FIXUP_3ST_BASE,
},
[ALC880_FIXUP_5ST_BASE] = {
.type = HDA_FIXUP_PINS,
.v.pins = (const struct hda_pintbl[]) {
{ 0x14, 0x01014010 }, /* front */
{ 0x15, 0x411111f0 }, /* N/A */
{ 0x16, 0x01011411 }, /* CLFE */
{ 0x17, 0x01016412 }, /* surr */
{ 0x18, 0x01a19c30 }, /* mic-in */
{ 0x19, 0x0121411f }, /* HP */
{ 0x1a, 0x01813031 }, /* line-in */
{ 0x1b, 0x02a19c40 }, /* front-mic */
{ 0x1c, 0x411111f0 }, /* N/A */
{ 0x1d, 0x411111f0 }, /* N/A */
/* 0x1e is filled in below */
{ 0x1f, 0x411111f0 }, /* N/A */
{ }
}
},
[ALC880_FIXUP_5ST] = {
.type = HDA_FIXUP_PINS,
.v.pins = (const struct hda_pintbl[]) {
{ 0x1e, 0x411111f0 }, /* N/A */
{ }
},
.chained = true,
.chain_id = ALC880_FIXUP_5ST_BASE,
},
[ALC880_FIXUP_5ST_DIG] = {
.type = HDA_FIXUP_PINS,
.v.pins = (const struct hda_pintbl[]) {
{ 0x1e, 0x0144111e }, /* SPDIF */
{ }
},
.chained = true,
.chain_id = ALC880_FIXUP_5ST_BASE,
},
[ALC880_FIXUP_6ST_BASE] = {
.type = HDA_FIXUP_PINS,
.v.pins = (const struct hda_pintbl[]) {
{ 0x14, 0x01014010 }, /* front */
{ 0x15, 0x01016412 }, /* surr */
{ 0x16, 0x01011411 }, /* CLFE */
{ 0x17, 0x01012414 }, /* side */
{ 0x18, 0x01a19c30 }, /* mic-in */
{ 0x19, 0x02a19c40 }, /* front-mic */
{ 0x1a, 0x01813031 }, /* line-in */
{ 0x1b, 0x0121411f }, /* HP */
{ 0x1c, 0x411111f0 }, /* N/A */
{ 0x1d, 0x411111f0 }, /* N/A */
/* 0x1e is filled in below */
{ 0x1f, 0x411111f0 }, /* N/A */
{ }
}
},
[ALC880_FIXUP_6ST] = {
.type = HDA_FIXUP_PINS,
.v.pins = (const struct hda_pintbl[]) {
{ 0x1e, 0x411111f0 }, /* N/A */
{ }
},
.chained = true,
.chain_id = ALC880_FIXUP_6ST_BASE,
},
[ALC880_FIXUP_6ST_DIG] = {
.type = HDA_FIXUP_PINS,
.v.pins = (const struct hda_pintbl[]) {
{ 0x1e, 0x0144111e }, /* SPDIF */
{ }
},
.chained = true,
.chain_id = ALC880_FIXUP_6ST_BASE,
},
[ALC880_FIXUP_6ST_AUTOMUTE] = {
.type = HDA_FIXUP_PINS,
.v.pins = (const struct hda_pintbl[]) {
{ 0x1b, 0x0121401f }, /* HP with jack detect */
{ }
},
.chained_before = true,
.chain_id = ALC880_FIXUP_6ST_BASE,
},
};
static const struct hda_quirk alc880_fixup_tbl[] = {
SND_PCI_QUIRK(0x1019, 0x0f69, "Coeus G610P", ALC880_FIXUP_W810),
SND_PCI_QUIRK(0x1043, 0x10c3, "ASUS W5A", ALC880_FIXUP_ASUS_W5A),
SND_PCI_QUIRK(0x1043, 0x1964, "ASUS Z71V", ALC880_FIXUP_Z71V),
SND_PCI_QUIRK_VENDOR(0x1043, "ASUS", ALC880_FIXUP_GPIO1),
SND_PCI_QUIRK(0x147b, 0x1045, "ABit AA8XE", ALC880_FIXUP_6ST_AUTOMUTE),
SND_PCI_QUIRK(0x1558, 0x5401, "Clevo GPIO2", ALC880_FIXUP_GPIO2),
SND_PCI_QUIRK_VENDOR(0x1558, "Clevo", ALC880_FIXUP_EAPD_COEF),
SND_PCI_QUIRK(0x1584, 0x9050, "Uniwill", ALC880_FIXUP_UNIWILL_DIG),
SND_PCI_QUIRK(0x1584, 0x9054, "Uniwill", ALC880_FIXUP_F1734),
SND_PCI_QUIRK(0x1584, 0x9070, "Uniwill", ALC880_FIXUP_UNIWILL),
SND_PCI_QUIRK(0x1584, 0x9077, "Uniwill P53", ALC880_FIXUP_VOL_KNOB),
SND_PCI_QUIRK(0x161f, 0x203d, "W810", ALC880_FIXUP_W810),
SND_PCI_QUIRK(0x161f, 0x205d, "Medion Rim 2150", ALC880_FIXUP_MEDION_RIM),
SND_PCI_QUIRK(0x1631, 0xe011, "PB 13201056", ALC880_FIXUP_6ST_AUTOMUTE),
SND_PCI_QUIRK(0x1734, 0x107c, "FSC Amilo M1437", ALC880_FIXUP_FUJITSU),
SND_PCI_QUIRK(0x1734, 0x1094, "FSC Amilo M1451G", ALC880_FIXUP_FUJITSU),
SND_PCI_QUIRK(0x1734, 0x10ac, "FSC AMILO Xi 1526", ALC880_FIXUP_F1734),
SND_PCI_QUIRK(0x1734, 0x10b0, "FSC Amilo Pi1556", ALC880_FIXUP_FUJITSU),
SND_PCI_QUIRK(0x1854, 0x003b, "LG", ALC880_FIXUP_LG),
SND_PCI_QUIRK(0x1854, 0x005f, "LG P1 Express", ALC880_FIXUP_LG),
SND_PCI_QUIRK(0x1854, 0x0068, "LG w1", ALC880_FIXUP_LG),
SND_PCI_QUIRK(0x1854, 0x0077, "LG LW25", ALC880_FIXUP_LG_LW25),
SND_PCI_QUIRK(0x19db, 0x4188, "TCL S700", ALC880_FIXUP_TCL_S700),
/* Below is the copied entries from alc880_quirks.c.
* It's not quite sure whether BIOS sets the correct pin-config table
* on these machines, thus they are kept to be compatible with
* the old static quirks. Once when it's confirmed to work without
* these overrides, it'd be better to remove.
*/
SND_PCI_QUIRK(0x1019, 0xa880, "ECS", ALC880_FIXUP_5ST_DIG),
SND_PCI_QUIRK(0x1019, 0xa884, "Acer APFV", ALC880_FIXUP_6ST),
SND_PCI_QUIRK(0x1025, 0x0070, "ULI", ALC880_FIXUP_3ST_DIG),
SND_PCI_QUIRK(0x1025, 0x0077, "ULI", ALC880_FIXUP_6ST_DIG),
SND_PCI_QUIRK(0x1025, 0x0078, "ULI", ALC880_FIXUP_6ST_DIG),
SND_PCI_QUIRK(0x1025, 0x0087, "ULI", ALC880_FIXUP_6ST_DIG),
SND_PCI_QUIRK(0x1025, 0xe309, "ULI", ALC880_FIXUP_3ST_DIG),
SND_PCI_QUIRK(0x1025, 0xe310, "ULI", ALC880_FIXUP_3ST),
SND_PCI_QUIRK(0x1039, 0x1234, NULL, ALC880_FIXUP_6ST_DIG),
SND_PCI_QUIRK(0x104d, 0x81a0, "Sony", ALC880_FIXUP_3ST),
SND_PCI_QUIRK(0x104d, 0x81d6, "Sony", ALC880_FIXUP_3ST),
SND_PCI_QUIRK(0x107b, 0x3032, "Gateway", ALC880_FIXUP_5ST),
SND_PCI_QUIRK(0x107b, 0x3033, "Gateway", ALC880_FIXUP_5ST),
SND_PCI_QUIRK(0x107b, 0x4039, "Gateway", ALC880_FIXUP_5ST),
SND_PCI_QUIRK(0x1297, 0xc790, "Shuttle ST20G5", ALC880_FIXUP_6ST_DIG),
SND_PCI_QUIRK(0x1458, 0xa102, "Gigabyte K8", ALC880_FIXUP_6ST_DIG),
SND_PCI_QUIRK(0x1462, 0x1150, "MSI", ALC880_FIXUP_6ST_DIG),
SND_PCI_QUIRK(0x1509, 0x925d, "FIC P4M", ALC880_FIXUP_6ST_DIG),
SND_PCI_QUIRK(0x1565, 0x8202, "Biostar", ALC880_FIXUP_5ST_DIG),
SND_PCI_QUIRK(0x1695, 0x400d, "EPoX", ALC880_FIXUP_5ST_DIG),
SND_PCI_QUIRK(0x1695, 0x4012, "EPox EP-5LDA", ALC880_FIXUP_5ST_DIG),
SND_PCI_QUIRK(0x2668, 0x8086, NULL, ALC880_FIXUP_6ST_DIG), /* broken BIOS */
SND_PCI_QUIRK(0x8086, 0x2668, NULL, ALC880_FIXUP_6ST_DIG),
SND_PCI_QUIRK(0x8086, 0xa100, "Intel mobo", ALC880_FIXUP_5ST_DIG),
SND_PCI_QUIRK(0x8086, 0xd400, "Intel mobo", ALC880_FIXUP_5ST_DIG),
SND_PCI_QUIRK(0x8086, 0xd401, "Intel mobo", ALC880_FIXUP_5ST_DIG),
SND_PCI_QUIRK(0x8086, 0xd402, "Intel mobo", ALC880_FIXUP_3ST_DIG),
SND_PCI_QUIRK(0x8086, 0xe224, "Intel mobo", ALC880_FIXUP_5ST_DIG),
SND_PCI_QUIRK(0x8086, 0xe305, "Intel mobo", ALC880_FIXUP_3ST_DIG),
SND_PCI_QUIRK(0x8086, 0xe308, "Intel mobo", ALC880_FIXUP_3ST_DIG),
SND_PCI_QUIRK(0x8086, 0xe400, "Intel mobo", ALC880_FIXUP_5ST_DIG),
SND_PCI_QUIRK(0x8086, 0xe401, "Intel mobo", ALC880_FIXUP_5ST_DIG),
SND_PCI_QUIRK(0x8086, 0xe402, "Intel mobo", ALC880_FIXUP_5ST_DIG),
/* default Intel */
SND_PCI_QUIRK_VENDOR(0x8086, "Intel mobo", ALC880_FIXUP_3ST),
SND_PCI_QUIRK(0xa0a0, 0x0560, "AOpen i915GMm-HFS", ALC880_FIXUP_5ST_DIG),
SND_PCI_QUIRK(0xe803, 0x1019, NULL, ALC880_FIXUP_6ST_DIG),
{}
};
static const struct hda_model_fixup alc880_fixup_models[] = {
{.id = ALC880_FIXUP_3ST, .name = "3stack"},
{.id = ALC880_FIXUP_3ST_DIG, .name = "3stack-digout"},
{.id = ALC880_FIXUP_5ST, .name = "5stack"},
{.id = ALC880_FIXUP_5ST_DIG, .name = "5stack-digout"},
{.id = ALC880_FIXUP_6ST, .name = "6stack"},
{.id = ALC880_FIXUP_6ST_DIG, .name = "6stack-digout"},
{.id = ALC880_FIXUP_6ST_AUTOMUTE, .name = "6stack-automute"},
{}
};
/*
* OK, here we have finally the patch for ALC880
*/
static int patch_alc880(struct hda_codec *codec)
{
struct alc_spec *spec;
int err;
err = alc_alloc_spec(codec, 0x0b);
if (err < 0)
return err;
spec = codec->spec;
spec->gen.need_dac_fix = 1;
spec->gen.beep_nid = 0x01;
codec->patch_ops.unsol_event = alc880_unsol_event;
alc_pre_init(codec);
snd_hda_pick_fixup(codec, alc880_fixup_models, alc880_fixup_tbl,
alc880_fixups);
snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
/* automatic parse from the BIOS config */
err = alc880_parse_auto_config(codec);
if (err < 0)
goto error;
if (!spec->gen.no_analog) {
err = set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
if (err < 0)
goto error;
}
snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
return 0;
error:
alc_free(codec);
return err;
}
/*
* driver entries
*/
static const struct hda_device_id snd_hda_id_alc880[] = {
HDA_CODEC_ENTRY(0x10ec0880, "ALC880", patch_alc880),
{} /* terminator */
};
MODULE_DEVICE_TABLE(hdaudio, snd_hda_id_alc880);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Realtek ALC880 HD-audio codec");
MODULE_IMPORT_NS("SND_HDA_CODEC_REALTEK");
static struct hda_codec_driver alc880_driver = {
.id = snd_hda_id_alc880,
};
module_hda_codec_driver(alc880_driver);

View file

@ -0,0 +1,847 @@
// SPDX-License-Identifier: GPL-2.0-or-later
//
// Realtek ALC882/883/885/888/889 codec support
//
// ALC882 is almost identical with ALC880 but has cleaner and more flexible
// configuration. Each pin widget can choose any input DACs and a mixer.
// Each ADC is connected from a mixer of all inputs. This makes possible
// 6-channel independent captures.
//
// In addition, an independent DAC for the multi-playback (not used in this
// driver yet).
//
#include <linux/init.h>
#include <linux/module.h>
#include "realtek.h"
/*
* Pin config fixes
*/
enum {
ALC882_FIXUP_ABIT_AW9D_MAX,
ALC882_FIXUP_LENOVO_Y530,
ALC882_FIXUP_PB_M5210,
ALC882_FIXUP_ACER_ASPIRE_7736,
ALC882_FIXUP_ASUS_W90V,
ALC889_FIXUP_CD,
ALC889_FIXUP_FRONT_HP_NO_PRESENCE,
ALC889_FIXUP_VAIO_TT,
ALC888_FIXUP_EEE1601,
ALC886_FIXUP_EAPD,
ALC882_FIXUP_EAPD,
ALC883_FIXUP_EAPD,
ALC883_FIXUP_ACER_EAPD,
ALC882_FIXUP_GPIO1,
ALC882_FIXUP_GPIO2,
ALC882_FIXUP_GPIO3,
ALC889_FIXUP_COEF,
ALC882_FIXUP_ASUS_W2JC,
ALC882_FIXUP_ACER_ASPIRE_4930G,
ALC882_FIXUP_ACER_ASPIRE_8930G,
ALC882_FIXUP_ASPIRE_8930G_VERBS,
ALC885_FIXUP_MACPRO_GPIO,
ALC889_FIXUP_DAC_ROUTE,
ALC889_FIXUP_MBP_VREF,
ALC889_FIXUP_IMAC91_VREF,
ALC889_FIXUP_MBA11_VREF,
ALC889_FIXUP_MBA21_VREF,
ALC889_FIXUP_MP11_VREF,
ALC889_FIXUP_MP41_VREF,
ALC882_FIXUP_INV_DMIC,
ALC882_FIXUP_NO_PRIMARY_HP,
ALC887_FIXUP_ASUS_BASS,
ALC887_FIXUP_BASS_CHMAP,
ALC1220_FIXUP_GB_DUAL_CODECS,
ALC1220_FIXUP_GB_X570,
ALC1220_FIXUP_CLEVO_P950,
ALC1220_FIXUP_CLEVO_PB51ED,
ALC1220_FIXUP_CLEVO_PB51ED_PINS,
ALC887_FIXUP_ASUS_AUDIO,
ALC887_FIXUP_ASUS_HMIC,
ALCS1200A_FIXUP_MIC_VREF,
ALC888VD_FIXUP_MIC_100VREF,
};
static void alc889_fixup_coef(struct hda_codec *codec,
const struct hda_fixup *fix, int action)
{
if (action != HDA_FIXUP_ACT_INIT)
return;
alc_update_coef_idx(codec, 7, 0, 0x2030);
}
/* set up GPIO at initialization */
static void alc885_fixup_macpro_gpio(struct hda_codec *codec,
const struct hda_fixup *fix, int action)
{
struct alc_spec *spec = codec->spec;
spec->gpio_write_delay = true;
alc_fixup_gpio3(codec, fix, action);
}
/* Fix the connection of some pins for ALC889:
* At least, Acer Aspire 5935 shows the connections to DAC3/4 don't
* work correctly (bko#42740)
*/
static void alc889_fixup_dac_route(struct hda_codec *codec,
const struct hda_fixup *fix, int action)
{
if (action == HDA_FIXUP_ACT_PRE_PROBE) {
/* fake the connections during parsing the tree */
static const hda_nid_t conn1[] = { 0x0c, 0x0d };
static const hda_nid_t conn2[] = { 0x0e, 0x0f };
snd_hda_override_conn_list(codec, 0x14, ARRAY_SIZE(conn1), conn1);
snd_hda_override_conn_list(codec, 0x15, ARRAY_SIZE(conn1), conn1);
snd_hda_override_conn_list(codec, 0x18, ARRAY_SIZE(conn2), conn2);
snd_hda_override_conn_list(codec, 0x1a, ARRAY_SIZE(conn2), conn2);
} else if (action == HDA_FIXUP_ACT_PROBE) {
/* restore the connections */
static const hda_nid_t conn[] = { 0x0c, 0x0d, 0x0e, 0x0f, 0x26 };
snd_hda_override_conn_list(codec, 0x14, ARRAY_SIZE(conn), conn);
snd_hda_override_conn_list(codec, 0x15, ARRAY_SIZE(conn), conn);
snd_hda_override_conn_list(codec, 0x18, ARRAY_SIZE(conn), conn);
snd_hda_override_conn_list(codec, 0x1a, ARRAY_SIZE(conn), conn);
}
}
/* Set VREF on HP pin */
static void alc889_fixup_mbp_vref(struct hda_codec *codec,
const struct hda_fixup *fix, int action)
{
static const hda_nid_t nids[] = { 0x14, 0x15, 0x19 };
struct alc_spec *spec = codec->spec;
int i;
if (action != HDA_FIXUP_ACT_INIT)
return;
for (i = 0; i < ARRAY_SIZE(nids); i++) {
unsigned int val = snd_hda_codec_get_pincfg(codec, nids[i]);
if (get_defcfg_device(val) != AC_JACK_HP_OUT)
continue;
val = snd_hda_codec_get_pin_target(codec, nids[i]);
val |= AC_PINCTL_VREF_80;
snd_hda_set_pin_ctl(codec, nids[i], val);
spec->gen.keep_vref_in_automute = 1;
break;
}
}
static void alc889_fixup_mac_pins(struct hda_codec *codec,
const hda_nid_t *nids, int num_nids)
{
struct alc_spec *spec = codec->spec;
int i;
for (i = 0; i < num_nids; i++) {
unsigned int val;
val = snd_hda_codec_get_pin_target(codec, nids[i]);
val |= AC_PINCTL_VREF_50;
snd_hda_set_pin_ctl(codec, nids[i], val);
}
spec->gen.keep_vref_in_automute = 1;
}
/* Set VREF on speaker pins on imac91 */
static void alc889_fixup_imac91_vref(struct hda_codec *codec,
const struct hda_fixup *fix, int action)
{
static const hda_nid_t nids[] = { 0x18, 0x1a };
if (action == HDA_FIXUP_ACT_INIT)
alc889_fixup_mac_pins(codec, nids, ARRAY_SIZE(nids));
}
/* Set VREF on speaker pins on mba11 */
static void alc889_fixup_mba11_vref(struct hda_codec *codec,
const struct hda_fixup *fix, int action)
{
static const hda_nid_t nids[] = { 0x18 };
if (action == HDA_FIXUP_ACT_INIT)
alc889_fixup_mac_pins(codec, nids, ARRAY_SIZE(nids));
}
/* Set VREF on speaker pins on mba21 */
static void alc889_fixup_mba21_vref(struct hda_codec *codec,
const struct hda_fixup *fix, int action)
{
static const hda_nid_t nids[] = { 0x18, 0x19 };
if (action == HDA_FIXUP_ACT_INIT)
alc889_fixup_mac_pins(codec, nids, ARRAY_SIZE(nids));
}
/* Don't take HP output as primary
* Strangely, the speaker output doesn't work on Vaio Z and some Vaio
* all-in-one desktop PCs (for example VGC-LN51JGB) through DAC 0x05
*/
static void alc882_fixup_no_primary_hp(struct hda_codec *codec,
const struct hda_fixup *fix, int action)
{
struct alc_spec *spec = codec->spec;
if (action == HDA_FIXUP_ACT_PRE_PROBE) {
spec->gen.no_primary_hp = 1;
spec->gen.no_multi_io = 1;
}
}
static void alc1220_fixup_gb_x570(struct hda_codec *codec,
const struct hda_fixup *fix,
int action)
{
static const hda_nid_t conn1[] = { 0x0c };
static const struct coef_fw gb_x570_coefs[] = {
WRITE_COEF(0x07, 0x03c0),
WRITE_COEF(0x1a, 0x01c1),
WRITE_COEF(0x1b, 0x0202),
WRITE_COEF(0x43, 0x3005),
{}
};
switch (action) {
case HDA_FIXUP_ACT_PRE_PROBE:
snd_hda_override_conn_list(codec, 0x14, ARRAY_SIZE(conn1), conn1);
snd_hda_override_conn_list(codec, 0x1b, ARRAY_SIZE(conn1), conn1);
break;
case HDA_FIXUP_ACT_INIT:
alc_process_coef_fw(codec, gb_x570_coefs);
break;
}
}
static void alc1220_fixup_clevo_p950(struct hda_codec *codec,
const struct hda_fixup *fix,
int action)
{
static const hda_nid_t conn1[] = { 0x0c };
if (action != HDA_FIXUP_ACT_PRE_PROBE)
return;
alc_update_coef_idx(codec, 0x7, 0, 0x3c3);
/* We therefore want to make sure 0x14 (front headphone) and
* 0x1b (speakers) use the stereo DAC 0x02
*/
snd_hda_override_conn_list(codec, 0x14, ARRAY_SIZE(conn1), conn1);
snd_hda_override_conn_list(codec, 0x1b, ARRAY_SIZE(conn1), conn1);
}
static void alc1220_fixup_clevo_pb51ed(struct hda_codec *codec,
const struct hda_fixup *fix,
int action)
{
alc1220_fixup_clevo_p950(codec, fix, action);
alc_fixup_headset_mode_no_hp_mic(codec, fix, action);
}
static void alc887_asus_hp_automute_hook(struct hda_codec *codec,
struct hda_jack_callback *jack)
{
struct alc_spec *spec = codec->spec;
unsigned int vref;
snd_hda_gen_hp_automute(codec, jack);
if (spec->gen.hp_jack_present)
vref = AC_PINCTL_VREF_80;
else
vref = AC_PINCTL_VREF_HIZ;
snd_hda_set_pin_ctl(codec, 0x19, PIN_HP | vref);
}
static void alc887_fixup_asus_jack(struct hda_codec *codec,
const struct hda_fixup *fix, int action)
{
struct alc_spec *spec = codec->spec;
if (action != HDA_FIXUP_ACT_PROBE)
return;
snd_hda_set_pin_ctl_cache(codec, 0x1b, PIN_HP);
spec->gen.hp_automute_hook = alc887_asus_hp_automute_hook;
}
static const struct hda_fixup alc882_fixups[] = {
[ALC882_FIXUP_ABIT_AW9D_MAX] = {
.type = HDA_FIXUP_PINS,
.v.pins = (const struct hda_pintbl[]) {
{ 0x15, 0x01080104 }, /* side */
{ 0x16, 0x01011012 }, /* rear */
{ 0x17, 0x01016011 }, /* clfe */
{ }
}
},
[ALC882_FIXUP_LENOVO_Y530] = {
.type = HDA_FIXUP_PINS,
.v.pins = (const struct hda_pintbl[]) {
{ 0x15, 0x99130112 }, /* rear int speakers */
{ 0x16, 0x99130111 }, /* subwoofer */
{ }
}
},
[ALC882_FIXUP_PB_M5210] = {
.type = HDA_FIXUP_PINCTLS,
.v.pins = (const struct hda_pintbl[]) {
{ 0x19, PIN_VREF50 },
{}
}
},
[ALC882_FIXUP_ACER_ASPIRE_7736] = {
.type = HDA_FIXUP_FUNC,
.v.func = alc_fixup_sku_ignore,
},
[ALC882_FIXUP_ASUS_W90V] = {
.type = HDA_FIXUP_PINS,
.v.pins = (const struct hda_pintbl[]) {
{ 0x16, 0x99130110 }, /* fix sequence for CLFE */
{ }
}
},
[ALC889_FIXUP_CD] = {
.type = HDA_FIXUP_PINS,
.v.pins = (const struct hda_pintbl[]) {
{ 0x1c, 0x993301f0 }, /* CD */
{ }
}
},
[ALC889_FIXUP_FRONT_HP_NO_PRESENCE] = {
.type = HDA_FIXUP_PINS,
.v.pins = (const struct hda_pintbl[]) {
{ 0x1b, 0x02214120 }, /* Front HP jack is flaky, disable jack detect */
{ }
},
.chained = true,
.chain_id = ALC889_FIXUP_CD,
},
[ALC889_FIXUP_VAIO_TT] = {
.type = HDA_FIXUP_PINS,
.v.pins = (const struct hda_pintbl[]) {
{ 0x17, 0x90170111 }, /* hidden surround speaker */
{ }
}
},
[ALC888_FIXUP_EEE1601] = {
.type = HDA_FIXUP_VERBS,
.v.verbs = (const struct hda_verb[]) {
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x0b },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0838 },
{ }
}
},
[ALC886_FIXUP_EAPD] = {
.type = HDA_FIXUP_VERBS,
.v.verbs = (const struct hda_verb[]) {
/* change to EAPD mode */
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x07 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0068 },
{ }
}
},
[ALC882_FIXUP_EAPD] = {
.type = HDA_FIXUP_VERBS,
.v.verbs = (const struct hda_verb[]) {
/* change to EAPD mode */
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x07 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x3060 },
{ }
}
},
[ALC883_FIXUP_EAPD] = {
.type = HDA_FIXUP_VERBS,
.v.verbs = (const struct hda_verb[]) {
/* change to EAPD mode */
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x07 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x3070 },
{ }
}
},
[ALC883_FIXUP_ACER_EAPD] = {
.type = HDA_FIXUP_VERBS,
.v.verbs = (const struct hda_verb[]) {
/* eanable EAPD on Acer laptops */
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x07 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x3050 },
{ }
}
},
[ALC882_FIXUP_GPIO1] = {
.type = HDA_FIXUP_FUNC,
.v.func = alc_fixup_gpio1,
},
[ALC882_FIXUP_GPIO2] = {
.type = HDA_FIXUP_FUNC,
.v.func = alc_fixup_gpio2,
},
[ALC882_FIXUP_GPIO3] = {
.type = HDA_FIXUP_FUNC,
.v.func = alc_fixup_gpio3,
},
[ALC882_FIXUP_ASUS_W2JC] = {
.type = HDA_FIXUP_FUNC,
.v.func = alc_fixup_gpio1,
.chained = true,
.chain_id = ALC882_FIXUP_EAPD,
},
[ALC889_FIXUP_COEF] = {
.type = HDA_FIXUP_FUNC,
.v.func = alc889_fixup_coef,
},
[ALC882_FIXUP_ACER_ASPIRE_4930G] = {
.type = HDA_FIXUP_PINS,
.v.pins = (const struct hda_pintbl[]) {
{ 0x16, 0x99130111 }, /* CLFE speaker */
{ 0x17, 0x99130112 }, /* surround speaker */
{ }
},
.chained = true,
.chain_id = ALC882_FIXUP_GPIO1,
},
[ALC882_FIXUP_ACER_ASPIRE_8930G] = {
.type = HDA_FIXUP_PINS,
.v.pins = (const struct hda_pintbl[]) {
{ 0x16, 0x99130111 }, /* CLFE speaker */
{ 0x1b, 0x99130112 }, /* surround speaker */
{ }
},
.chained = true,
.chain_id = ALC882_FIXUP_ASPIRE_8930G_VERBS,
},
[ALC882_FIXUP_ASPIRE_8930G_VERBS] = {
/* additional init verbs for Acer Aspire 8930G */
.type = HDA_FIXUP_VERBS,
.v.verbs = (const struct hda_verb[]) {
/* Enable all DACs */
/* DAC DISABLE/MUTE 1? */
/* setting bits 1-5 disables DAC nids 0x02-0x06
* apparently. Init=0x38 */
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x03 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
/* DAC DISABLE/MUTE 2? */
/* some bit here disables the other DACs.
* Init=0x4900 */
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x08 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
/* DMIC fix
* This laptop has a stereo digital microphone.
* The mics are only 1cm apart which makes the stereo
* useless. However, either the mic or the ALC889
* makes the signal become a difference/sum signal
* instead of standard stereo, which is annoying.
* So instead we flip this bit which makes the
* codec replicate the sum signal to both channels,
* turning it into a normal mono mic.
*/
/* DMIC_CONTROL? Init value = 0x0001 */
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x0b },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0003 },
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x07 },
{ 0x20, AC_VERB_SET_PROC_COEF, 0x3050 },
{ }
},
.chained = true,
.chain_id = ALC882_FIXUP_GPIO1,
},
[ALC885_FIXUP_MACPRO_GPIO] = {
.type = HDA_FIXUP_FUNC,
.v.func = alc885_fixup_macpro_gpio,
},
[ALC889_FIXUP_DAC_ROUTE] = {
.type = HDA_FIXUP_FUNC,
.v.func = alc889_fixup_dac_route,
},
[ALC889_FIXUP_MBP_VREF] = {
.type = HDA_FIXUP_FUNC,
.v.func = alc889_fixup_mbp_vref,
.chained = true,
.chain_id = ALC882_FIXUP_GPIO1,
},
[ALC889_FIXUP_IMAC91_VREF] = {
.type = HDA_FIXUP_FUNC,
.v.func = alc889_fixup_imac91_vref,
.chained = true,
.chain_id = ALC882_FIXUP_GPIO1,
},
[ALC889_FIXUP_MBA11_VREF] = {
.type = HDA_FIXUP_FUNC,
.v.func = alc889_fixup_mba11_vref,
.chained = true,
.chain_id = ALC889_FIXUP_MBP_VREF,
},
[ALC889_FIXUP_MBA21_VREF] = {
.type = HDA_FIXUP_FUNC,
.v.func = alc889_fixup_mba21_vref,
.chained = true,
.chain_id = ALC889_FIXUP_MBP_VREF,
},
[ALC889_FIXUP_MP11_VREF] = {
.type = HDA_FIXUP_FUNC,
.v.func = alc889_fixup_mba11_vref,
.chained = true,
.chain_id = ALC885_FIXUP_MACPRO_GPIO,
},
[ALC889_FIXUP_MP41_VREF] = {
.type = HDA_FIXUP_FUNC,
.v.func = alc889_fixup_mbp_vref,
.chained = true,
.chain_id = ALC885_FIXUP_MACPRO_GPIO,
},
[ALC882_FIXUP_INV_DMIC] = {
.type = HDA_FIXUP_FUNC,
.v.func = alc_fixup_inv_dmic,
},
[ALC882_FIXUP_NO_PRIMARY_HP] = {
.type = HDA_FIXUP_FUNC,
.v.func = alc882_fixup_no_primary_hp,
},
[ALC887_FIXUP_ASUS_BASS] = {
.type = HDA_FIXUP_PINS,
.v.pins = (const struct hda_pintbl[]) {
{0x16, 0x99130130}, /* bass speaker */
{}
},
.chained = true,
.chain_id = ALC887_FIXUP_BASS_CHMAP,
},
[ALC887_FIXUP_BASS_CHMAP] = {
.type = HDA_FIXUP_FUNC,
.v.func = alc_fixup_bass_chmap,
},
[ALC1220_FIXUP_GB_DUAL_CODECS] = {
.type = HDA_FIXUP_FUNC,
.v.func = alc1220_fixup_gb_dual_codecs,
},
[ALC1220_FIXUP_GB_X570] = {
.type = HDA_FIXUP_FUNC,
.v.func = alc1220_fixup_gb_x570,
},
[ALC1220_FIXUP_CLEVO_P950] = {
.type = HDA_FIXUP_FUNC,
.v.func = alc1220_fixup_clevo_p950,
},
[ALC1220_FIXUP_CLEVO_PB51ED] = {
.type = HDA_FIXUP_FUNC,
.v.func = alc1220_fixup_clevo_pb51ed,
},
[ALC1220_FIXUP_CLEVO_PB51ED_PINS] = {
.type = HDA_FIXUP_PINS,
.v.pins = (const struct hda_pintbl[]) {
{ 0x19, 0x01a1913c }, /* use as headset mic, without its own jack detect */
{}
},
.chained = true,
.chain_id = ALC1220_FIXUP_CLEVO_PB51ED,
},
[ALC887_FIXUP_ASUS_AUDIO] = {
.type = HDA_FIXUP_PINS,
.v.pins = (const struct hda_pintbl[]) {
{ 0x15, 0x02a14150 }, /* use as headset mic, without its own jack detect */
{ 0x19, 0x22219420 },
{}
},
},
[ALC887_FIXUP_ASUS_HMIC] = {
.type = HDA_FIXUP_FUNC,
.v.func = alc887_fixup_asus_jack,
.chained = true,
.chain_id = ALC887_FIXUP_ASUS_AUDIO,
},
[ALCS1200A_FIXUP_MIC_VREF] = {
.type = HDA_FIXUP_PINCTLS,
.v.pins = (const struct hda_pintbl[]) {
{ 0x18, PIN_VREF50 }, /* rear mic */
{ 0x19, PIN_VREF50 }, /* front mic */
{}
}
},
[ALC888VD_FIXUP_MIC_100VREF] = {
.type = HDA_FIXUP_PINCTLS,
.v.pins = (const struct hda_pintbl[]) {
{ 0x18, PIN_VREF100 }, /* headset mic */
{}
}
},
};
static const struct hda_quirk alc882_fixup_tbl[] = {
SND_PCI_QUIRK(0x1025, 0x006c, "Acer Aspire 9810", ALC883_FIXUP_ACER_EAPD),
SND_PCI_QUIRK(0x1025, 0x0090, "Acer Aspire", ALC883_FIXUP_ACER_EAPD),
SND_PCI_QUIRK(0x1025, 0x0107, "Acer Aspire", ALC883_FIXUP_ACER_EAPD),
SND_PCI_QUIRK(0x1025, 0x010a, "Acer Ferrari 5000", ALC883_FIXUP_ACER_EAPD),
SND_PCI_QUIRK(0x1025, 0x0110, "Acer Aspire", ALC883_FIXUP_ACER_EAPD),
SND_PCI_QUIRK(0x1025, 0x0112, "Acer Aspire 9303", ALC883_FIXUP_ACER_EAPD),
SND_PCI_QUIRK(0x1025, 0x0121, "Acer Aspire 5920G", ALC883_FIXUP_ACER_EAPD),
SND_PCI_QUIRK(0x1025, 0x013e, "Acer Aspire 4930G",
ALC882_FIXUP_ACER_ASPIRE_4930G),
SND_PCI_QUIRK(0x1025, 0x013f, "Acer Aspire 5930G",
ALC882_FIXUP_ACER_ASPIRE_4930G),
SND_PCI_QUIRK(0x1025, 0x0145, "Acer Aspire 8930G",
ALC882_FIXUP_ACER_ASPIRE_8930G),
SND_PCI_QUIRK(0x1025, 0x0146, "Acer Aspire 6935G",
ALC882_FIXUP_ACER_ASPIRE_8930G),
SND_PCI_QUIRK(0x1025, 0x0142, "Acer Aspire 7730G",
ALC882_FIXUP_ACER_ASPIRE_4930G),
SND_PCI_QUIRK(0x1025, 0x0155, "Packard-Bell M5120", ALC882_FIXUP_PB_M5210),
SND_PCI_QUIRK(0x1025, 0x015e, "Acer Aspire 6930G",
ALC882_FIXUP_ACER_ASPIRE_4930G),
SND_PCI_QUIRK(0x1025, 0x0166, "Acer Aspire 6530G",
ALC882_FIXUP_ACER_ASPIRE_4930G),
SND_PCI_QUIRK(0x1025, 0x021e, "Acer Aspire 5739G",
ALC882_FIXUP_ACER_ASPIRE_4930G),
SND_PCI_QUIRK(0x1025, 0x0259, "Acer Aspire 5935", ALC889_FIXUP_DAC_ROUTE),
SND_PCI_QUIRK(0x1025, 0x026b, "Acer Aspire 8940G", ALC882_FIXUP_ACER_ASPIRE_8930G),
SND_PCI_QUIRK(0x1025, 0x0296, "Acer Aspire 7736z", ALC882_FIXUP_ACER_ASPIRE_7736),
SND_PCI_QUIRK(0x1043, 0x13c2, "Asus A7M", ALC882_FIXUP_EAPD),
SND_PCI_QUIRK(0x1043, 0x1873, "ASUS W90V", ALC882_FIXUP_ASUS_W90V),
SND_PCI_QUIRK(0x1043, 0x1971, "Asus W2JC", ALC882_FIXUP_ASUS_W2JC),
SND_PCI_QUIRK(0x1043, 0x2390, "Asus D700SA", ALC887_FIXUP_ASUS_HMIC),
SND_PCI_QUIRK(0x1043, 0x835f, "Asus Eee 1601", ALC888_FIXUP_EEE1601),
SND_PCI_QUIRK(0x1043, 0x84bc, "ASUS ET2700", ALC887_FIXUP_ASUS_BASS),
SND_PCI_QUIRK(0x1043, 0x8691, "ASUS ROG Ranger VIII", ALC882_FIXUP_GPIO3),
SND_PCI_QUIRK(0x1043, 0x8797, "ASUS TUF B550M-PLUS", ALCS1200A_FIXUP_MIC_VREF),
SND_PCI_QUIRK(0x104d, 0x9043, "Sony Vaio VGC-LN51JGB", ALC882_FIXUP_NO_PRIMARY_HP),
SND_PCI_QUIRK(0x104d, 0x9044, "Sony VAIO AiO", ALC882_FIXUP_NO_PRIMARY_HP),
SND_PCI_QUIRK(0x104d, 0x9047, "Sony Vaio TT", ALC889_FIXUP_VAIO_TT),
SND_PCI_QUIRK(0x104d, 0x905a, "Sony Vaio Z", ALC882_FIXUP_NO_PRIMARY_HP),
SND_PCI_QUIRK(0x104d, 0x9060, "Sony Vaio VPCL14M1R", ALC882_FIXUP_NO_PRIMARY_HP),
/* All Apple entries are in codec SSIDs */
SND_PCI_QUIRK(0x106b, 0x00a0, "MacBookPro 3,1", ALC889_FIXUP_MBP_VREF),
SND_PCI_QUIRK(0x106b, 0x00a1, "Macbook", ALC889_FIXUP_MBP_VREF),
SND_PCI_QUIRK(0x106b, 0x00a4, "MacbookPro 4,1", ALC889_FIXUP_MBP_VREF),
SND_PCI_QUIRK(0x106b, 0x0c00, "Mac Pro", ALC889_FIXUP_MP11_VREF),
SND_PCI_QUIRK(0x106b, 0x1000, "iMac 24", ALC885_FIXUP_MACPRO_GPIO),
SND_PCI_QUIRK(0x106b, 0x2800, "AppleTV", ALC885_FIXUP_MACPRO_GPIO),
SND_PCI_QUIRK(0x106b, 0x2c00, "MacbookPro rev3", ALC889_FIXUP_MBP_VREF),
SND_PCI_QUIRK(0x106b, 0x3000, "iMac", ALC889_FIXUP_MBP_VREF),
SND_PCI_QUIRK(0x106b, 0x3200, "iMac 7,1 Aluminum", ALC882_FIXUP_EAPD),
SND_PCI_QUIRK(0x106b, 0x3400, "MacBookAir 1,1", ALC889_FIXUP_MBA11_VREF),
SND_PCI_QUIRK(0x106b, 0x3500, "MacBookAir 2,1", ALC889_FIXUP_MBA21_VREF),
SND_PCI_QUIRK(0x106b, 0x3600, "Macbook 3,1", ALC889_FIXUP_MBP_VREF),
SND_PCI_QUIRK(0x106b, 0x3800, "MacbookPro 4,1", ALC889_FIXUP_MBP_VREF),
SND_PCI_QUIRK(0x106b, 0x3e00, "iMac 24 Aluminum", ALC885_FIXUP_MACPRO_GPIO),
SND_PCI_QUIRK(0x106b, 0x3f00, "Macbook 5,1", ALC889_FIXUP_IMAC91_VREF),
SND_PCI_QUIRK(0x106b, 0x4000, "MacbookPro 5,1", ALC889_FIXUP_IMAC91_VREF),
SND_PCI_QUIRK(0x106b, 0x4100, "Macmini 3,1", ALC889_FIXUP_IMAC91_VREF),
SND_PCI_QUIRK(0x106b, 0x4200, "Mac Pro 4,1/5,1", ALC889_FIXUP_MP41_VREF),
SND_PCI_QUIRK(0x106b, 0x4300, "iMac 9,1", ALC889_FIXUP_IMAC91_VREF),
SND_PCI_QUIRK(0x106b, 0x4600, "MacbookPro 5,2", ALC889_FIXUP_IMAC91_VREF),
SND_PCI_QUIRK(0x106b, 0x4900, "iMac 9,1 Aluminum", ALC889_FIXUP_IMAC91_VREF),
SND_PCI_QUIRK(0x106b, 0x4a00, "Macbook 5,2", ALC889_FIXUP_MBA11_VREF),
SND_PCI_QUIRK(0x1071, 0x8258, "Evesham Voyaeger", ALC882_FIXUP_EAPD),
SND_PCI_QUIRK(0x10ec, 0x12d8, "iBase Elo Touch", ALC888VD_FIXUP_MIC_100VREF),
SND_PCI_QUIRK(0x13fe, 0x1009, "Advantech MIT-W101", ALC886_FIXUP_EAPD),
SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte EP45-DS3/Z87X-UD3H", ALC889_FIXUP_FRONT_HP_NO_PRESENCE),
SND_PCI_QUIRK(0x1458, 0xa0b8, "Gigabyte AZ370-Gaming", ALC1220_FIXUP_GB_DUAL_CODECS),
SND_PCI_QUIRK(0x1458, 0xa0cd, "Gigabyte X570 Aorus Master", ALC1220_FIXUP_GB_X570),
SND_PCI_QUIRK(0x1458, 0xa0ce, "Gigabyte X570 Aorus Xtreme", ALC1220_FIXUP_GB_X570),
SND_PCI_QUIRK(0x1458, 0xa0d5, "Gigabyte X570S Aorus Master", ALC1220_FIXUP_GB_X570),
SND_PCI_QUIRK(0x1462, 0x11f7, "MSI-GE63", ALC1220_FIXUP_CLEVO_P950),
SND_PCI_QUIRK(0x1462, 0x1228, "MSI-GP63", ALC1220_FIXUP_CLEVO_P950),
SND_PCI_QUIRK(0x1462, 0x1229, "MSI-GP73", ALC1220_FIXUP_CLEVO_P950),
SND_PCI_QUIRK(0x1462, 0x1275, "MSI-GL63", ALC1220_FIXUP_CLEVO_P950),
SND_PCI_QUIRK(0x1462, 0x1276, "MSI-GL73", ALC1220_FIXUP_CLEVO_P950),
SND_PCI_QUIRK(0x1462, 0x1293, "MSI-GP65", ALC1220_FIXUP_CLEVO_P950),
SND_PCI_QUIRK(0x1462, 0x7350, "MSI-7350", ALC889_FIXUP_CD),
SND_PCI_QUIRK(0x1462, 0xcc34, "MSI Godlike X570", ALC1220_FIXUP_GB_DUAL_CODECS),
SND_PCI_QUIRK(0x1462, 0xda57, "MSI Z270-Gaming", ALC1220_FIXUP_GB_DUAL_CODECS),
SND_PCI_QUIRK_VENDOR(0x1462, "MSI", ALC882_FIXUP_GPIO3),
SND_PCI_QUIRK(0x147b, 0x107a, "Abit AW9D-MAX", ALC882_FIXUP_ABIT_AW9D_MAX),
SND_PCI_QUIRK(0x1558, 0x3702, "Clevo X370SN[VW]", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
SND_PCI_QUIRK(0x1558, 0x50d3, "Clevo PC50[ER][CDF]", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
SND_PCI_QUIRK(0x1558, 0x5802, "Clevo X58[05]WN[RST]", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
SND_PCI_QUIRK(0x1558, 0x65d1, "Clevo PB51[ER][CDF]", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
SND_PCI_QUIRK(0x1558, 0x65d2, "Clevo PB51R[CDF]", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
SND_PCI_QUIRK(0x1558, 0x65e1, "Clevo PB51[ED][DF]", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
SND_PCI_QUIRK(0x1558, 0x65e5, "Clevo PC50D[PRS](?:-D|-G)?", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
SND_PCI_QUIRK(0x1558, 0x65f1, "Clevo PC50HS", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
SND_PCI_QUIRK(0x1558, 0x65f5, "Clevo PD50PN[NRT]", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
SND_PCI_QUIRK(0x1558, 0x66a2, "Clevo PE60RNE", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
SND_PCI_QUIRK(0x1558, 0x66a6, "Clevo PE60SN[CDE]-[GS]", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
SND_PCI_QUIRK(0x1558, 0x67d1, "Clevo PB71[ER][CDF]", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
SND_PCI_QUIRK(0x1558, 0x67e1, "Clevo PB71[DE][CDF]", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
SND_PCI_QUIRK(0x1558, 0x67e5, "Clevo PC70D[PRS](?:-D|-G)?", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
SND_PCI_QUIRK(0x1558, 0x67f1, "Clevo PC70H[PRS]", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
SND_PCI_QUIRK(0x1558, 0x67f5, "Clevo PD70PN[NRT]", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
SND_PCI_QUIRK(0x1558, 0x70d1, "Clevo PC70[ER][CDF]", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
SND_PCI_QUIRK(0x1558, 0x7714, "Clevo X170SM", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
SND_PCI_QUIRK(0x1558, 0x7715, "Clevo X170KM-G", ALC1220_FIXUP_CLEVO_PB51ED),
SND_PCI_QUIRK(0x1558, 0x9501, "Clevo P950HR", ALC1220_FIXUP_CLEVO_P950),
SND_PCI_QUIRK(0x1558, 0x9506, "Clevo P955HQ", ALC1220_FIXUP_CLEVO_P950),
SND_PCI_QUIRK(0x1558, 0x950a, "Clevo P955H[PR]", ALC1220_FIXUP_CLEVO_P950),
SND_PCI_QUIRK(0x1558, 0x95e1, "Clevo P95xER", ALC1220_FIXUP_CLEVO_P950),
SND_PCI_QUIRK(0x1558, 0x95e2, "Clevo P950ER", ALC1220_FIXUP_CLEVO_P950),
SND_PCI_QUIRK(0x1558, 0x95e3, "Clevo P955[ER]T", ALC1220_FIXUP_CLEVO_P950),
SND_PCI_QUIRK(0x1558, 0x95e4, "Clevo P955ER", ALC1220_FIXUP_CLEVO_P950),
SND_PCI_QUIRK(0x1558, 0x95e5, "Clevo P955EE6", ALC1220_FIXUP_CLEVO_P950),
SND_PCI_QUIRK(0x1558, 0x95e6, "Clevo P950R[CDF]", ALC1220_FIXUP_CLEVO_P950),
SND_PCI_QUIRK(0x1558, 0x96e1, "Clevo P960[ER][CDFN]-K", ALC1220_FIXUP_CLEVO_P950),
SND_PCI_QUIRK(0x1558, 0x97e1, "Clevo P970[ER][CDFN]", ALC1220_FIXUP_CLEVO_P950),
SND_PCI_QUIRK(0x1558, 0x97e2, "Clevo P970RC-M", ALC1220_FIXUP_CLEVO_P950),
SND_PCI_QUIRK(0x1558, 0xd502, "Clevo PD50SNE", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
SND_PCI_QUIRK_VENDOR(0x1558, "Clevo laptop", ALC882_FIXUP_EAPD),
SND_PCI_QUIRK(0x161f, 0x2054, "Medion laptop", ALC883_FIXUP_EAPD),
SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo Y530", ALC882_FIXUP_LENOVO_Y530),
SND_PCI_QUIRK(0x8086, 0x0022, "DX58SO", ALC889_FIXUP_COEF),
{}
};
static const struct hda_model_fixup alc882_fixup_models[] = {
{.id = ALC882_FIXUP_ABIT_AW9D_MAX, .name = "abit-aw9d"},
{.id = ALC882_FIXUP_LENOVO_Y530, .name = "lenovo-y530"},
{.id = ALC882_FIXUP_ACER_ASPIRE_7736, .name = "acer-aspire-7736"},
{.id = ALC882_FIXUP_ASUS_W90V, .name = "asus-w90v"},
{.id = ALC889_FIXUP_CD, .name = "cd"},
{.id = ALC889_FIXUP_FRONT_HP_NO_PRESENCE, .name = "no-front-hp"},
{.id = ALC889_FIXUP_VAIO_TT, .name = "vaio-tt"},
{.id = ALC888_FIXUP_EEE1601, .name = "eee1601"},
{.id = ALC882_FIXUP_EAPD, .name = "alc882-eapd"},
{.id = ALC883_FIXUP_EAPD, .name = "alc883-eapd"},
{.id = ALC882_FIXUP_GPIO1, .name = "gpio1"},
{.id = ALC882_FIXUP_GPIO2, .name = "gpio2"},
{.id = ALC882_FIXUP_GPIO3, .name = "gpio3"},
{.id = ALC889_FIXUP_COEF, .name = "alc889-coef"},
{.id = ALC882_FIXUP_ASUS_W2JC, .name = "asus-w2jc"},
{.id = ALC882_FIXUP_ACER_ASPIRE_4930G, .name = "acer-aspire-4930g"},
{.id = ALC882_FIXUP_ACER_ASPIRE_8930G, .name = "acer-aspire-8930g"},
{.id = ALC883_FIXUP_ACER_EAPD, .name = "acer-aspire"},
{.id = ALC885_FIXUP_MACPRO_GPIO, .name = "macpro-gpio"},
{.id = ALC889_FIXUP_DAC_ROUTE, .name = "dac-route"},
{.id = ALC889_FIXUP_MBP_VREF, .name = "mbp-vref"},
{.id = ALC889_FIXUP_IMAC91_VREF, .name = "imac91-vref"},
{.id = ALC889_FIXUP_MBA11_VREF, .name = "mba11-vref"},
{.id = ALC889_FIXUP_MBA21_VREF, .name = "mba21-vref"},
{.id = ALC889_FIXUP_MP11_VREF, .name = "mp11-vref"},
{.id = ALC889_FIXUP_MP41_VREF, .name = "mp41-vref"},
{.id = ALC882_FIXUP_INV_DMIC, .name = "inv-dmic"},
{.id = ALC882_FIXUP_NO_PRIMARY_HP, .name = "no-primary-hp"},
{.id = ALC887_FIXUP_ASUS_BASS, .name = "asus-bass"},
{.id = ALC1220_FIXUP_GB_DUAL_CODECS, .name = "dual-codecs"},
{.id = ALC1220_FIXUP_GB_X570, .name = "gb-x570"},
{.id = ALC1220_FIXUP_CLEVO_P950, .name = "clevo-p950"},
{}
};
static const struct snd_hda_pin_quirk alc882_pin_fixup_tbl[] = {
SND_HDA_PIN_QUIRK(0x10ec1220, 0x1043, "ASUS", ALC1220_FIXUP_CLEVO_P950,
{0x14, 0x01014010},
{0x15, 0x01011012},
{0x16, 0x01016011},
{0x18, 0x01a19040},
{0x19, 0x02a19050},
{0x1a, 0x0181304f},
{0x1b, 0x0221401f},
{0x1e, 0x01456130}),
SND_HDA_PIN_QUIRK(0x10ec1220, 0x1462, "MS-7C35", ALC1220_FIXUP_CLEVO_P950,
{0x14, 0x01015010},
{0x15, 0x01011012},
{0x16, 0x01011011},
{0x18, 0x01a11040},
{0x19, 0x02a19050},
{0x1a, 0x0181104f},
{0x1b, 0x0221401f},
{0x1e, 0x01451130}),
{}
};
/*
* BIOS auto configuration
*/
/* almost identical with ALC880 parser... */
static int alc882_parse_auto_config(struct hda_codec *codec)
{
static const hda_nid_t alc882_ignore[] = { 0x1d, 0 };
static const hda_nid_t alc882_ssids[] = { 0x15, 0x1b, 0x14, 0 };
return alc_parse_auto_config(codec, alc882_ignore, alc882_ssids);
}
/*
*/
static int patch_alc882(struct hda_codec *codec)
{
struct alc_spec *spec;
int err;
err = alc_alloc_spec(codec, 0x0b);
if (err < 0)
return err;
spec = codec->spec;
switch (codec->core.vendor_id) {
case 0x10ec0882:
case 0x10ec0885:
case 0x10ec0900:
case 0x10ec0b00:
case 0x10ec1220:
break;
default:
/* ALC883 and variants */
alc_fix_pll_init(codec, 0x20, 0x0a, 10);
break;
}
alc_pre_init(codec);
snd_hda_pick_fixup(codec, alc882_fixup_models, alc882_fixup_tbl,
alc882_fixups);
snd_hda_pick_pin_fixup(codec, alc882_pin_fixup_tbl, alc882_fixups, true);
snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
alc_auto_parse_customize_define(codec);
if (has_cdefine_beep(codec))
spec->gen.beep_nid = 0x01;
/* automatic parse from the BIOS config */
err = alc882_parse_auto_config(codec);
if (err < 0)
goto error;
if (!spec->gen.no_analog && spec->gen.beep_nid) {
err = set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
if (err < 0)
goto error;
}
snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
return 0;
error:
alc_free(codec);
return err;
}
/*
* driver entries
*/
static const struct hda_device_id snd_hda_id_alc882[] = {
HDA_CODEC_REV_ENTRY(0x10ec0662, 0x100002, "ALC662 rev2", patch_alc882),
HDA_CODEC_ENTRY(0x10ec0882, "ALC882", patch_alc882),
HDA_CODEC_ENTRY(0x10ec0883, "ALC883", patch_alc882),
HDA_CODEC_REV_ENTRY(0x10ec0885, 0x100101, "ALC889A", patch_alc882),
HDA_CODEC_REV_ENTRY(0x10ec0885, 0x100103, "ALC889A", patch_alc882),
HDA_CODEC_ENTRY(0x10ec0885, "ALC885", patch_alc882),
HDA_CODEC_ENTRY(0x10ec0887, "ALC887", patch_alc882),
HDA_CODEC_REV_ENTRY(0x10ec0888, 0x100101, "ALC1200", patch_alc882),
HDA_CODEC_ENTRY(0x10ec0888, "ALC888", patch_alc882),
HDA_CODEC_ENTRY(0x10ec0889, "ALC889", patch_alc882),
HDA_CODEC_ENTRY(0x10ec0899, "ALC898", patch_alc882),
HDA_CODEC_ENTRY(0x10ec0900, "ALC1150", patch_alc882),
HDA_CODEC_ENTRY(0x10ec0b00, "ALCS1200A", patch_alc882),
HDA_CODEC_ENTRY(0x10ec1168, "ALC1220", patch_alc882),
HDA_CODEC_ENTRY(0x10ec1220, "ALC1220", patch_alc882),
{} /* terminator */
};
MODULE_DEVICE_TABLE(hdaudio, snd_hda_id_alc882);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Realtek ALC882 and compatible HD-audio codecs");
MODULE_IMPORT_NS("SND_HDA_CODEC_REALTEK");
static struct hda_codec_driver alc882_driver = {
.id = snd_hda_id_alc882,
};
module_hda_codec_driver(alc882_driver);

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,302 @@
// SPDX-License-Identifier: GPL-2.0-or-later
//
// Realtek HD-audio codec support code
//
#ifndef __HDA_REALTEK_H
#define __HDA_REALTEK_H
#include <linux/acpi.h>
#include <linux/cleanup.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/pci.h>
#include <linux/dmi.h>
#include <linux/module.h>
#include <linux/i2c.h>
#include <linux/input.h>
#include <linux/leds.h>
#include <linux/ctype.h>
#include <linux/spi/spi.h>
#include <sound/core.h>
#include <sound/jack.h>
#include <sound/hda_codec.h>
#include "hda_local.h"
#include "hda_auto_parser.h"
#include "hda_beep.h"
#include "hda_jack.h"
#include "../generic.h"
#include "../side-codecs/hda_component.h"
/* extra amp-initialization sequence types */
enum {
ALC_INIT_UNDEFINED,
ALC_INIT_NONE,
ALC_INIT_DEFAULT,
};
enum {
ALC_HEADSET_MODE_UNKNOWN,
ALC_HEADSET_MODE_UNPLUGGED,
ALC_HEADSET_MODE_HEADSET,
ALC_HEADSET_MODE_MIC,
ALC_HEADSET_MODE_HEADPHONE,
};
enum {
ALC_HEADSET_TYPE_UNKNOWN,
ALC_HEADSET_TYPE_CTIA,
ALC_HEADSET_TYPE_OMTP,
};
enum {
ALC_KEY_MICMUTE_INDEX,
};
struct alc_customize_define {
unsigned int sku_cfg;
unsigned char port_connectivity;
unsigned char check_sum;
unsigned char customization;
unsigned char external_amp;
unsigned int enable_pcbeep:1;
unsigned int platform_type:1;
unsigned int swap:1;
unsigned int override:1;
unsigned int fixup:1; /* Means that this sku is set by driver, not read from hw */
};
struct alc_coef_led {
unsigned int idx;
unsigned int mask;
unsigned int on;
unsigned int off;
};
struct alc_spec {
struct hda_gen_spec gen; /* must be at head */
/* codec parameterization */
struct alc_customize_define cdefine;
unsigned int parse_flags; /* flag for snd_hda_parse_pin_defcfg() */
/* GPIO bits */
unsigned int gpio_mask;
unsigned int gpio_dir;
unsigned int gpio_data;
bool gpio_write_delay; /* add a delay before writing gpio_data */
/* mute LED for HP laptops, see vref_mute_led_set() */
int mute_led_polarity;
int micmute_led_polarity;
hda_nid_t mute_led_nid;
hda_nid_t cap_mute_led_nid;
unsigned int gpio_mute_led_mask;
unsigned int gpio_mic_led_mask;
struct alc_coef_led mute_led_coef;
struct alc_coef_led mic_led_coef;
struct mutex coef_mutex;
hda_nid_t headset_mic_pin;
hda_nid_t headphone_mic_pin;
int current_headset_mode;
int current_headset_type;
/* hooks */
void (*init_hook)(struct hda_codec *codec);
void (*power_hook)(struct hda_codec *codec);
void (*shutup)(struct hda_codec *codec);
int init_amp;
int codec_variant; /* flag for other variants */
unsigned int has_alc5505_dsp:1;
unsigned int no_depop_delay:1;
unsigned int done_hp_init:1;
unsigned int no_shutup_pins:1;
unsigned int ultra_low_power:1;
unsigned int has_hs_key:1;
unsigned int no_internal_mic_pin:1;
unsigned int en_3kpull_low:1;
int num_speaker_amps;
/* for PLL fix */
hda_nid_t pll_nid;
unsigned int pll_coef_idx, pll_coef_bit;
unsigned int coef0;
struct input_dev *kb_dev;
u8 alc_mute_keycode_map[1];
/* component binding */
struct hda_component_parent comps;
};
int alc_read_coefex_idx(struct hda_codec *codec, hda_nid_t nid,
unsigned int coef_idx);
void alc_write_coefex_idx(struct hda_codec *codec, hda_nid_t nid,
unsigned int coef_idx, unsigned int coef_val);
void alc_update_coefex_idx(struct hda_codec *codec, hda_nid_t nid,
unsigned int coef_idx, unsigned int mask,
unsigned int bits_set);
#define alc_read_coef_idx(codec, coef_idx) \
alc_read_coefex_idx(codec, 0x20, coef_idx)
#define alc_write_coef_idx(codec, coef_idx, coef_val) \
alc_write_coefex_idx(codec, 0x20, coef_idx, coef_val)
#define alc_update_coef_idx(codec, coef_idx, mask, bits_set) \
alc_update_coefex_idx(codec, 0x20, coef_idx, mask, bits_set)
unsigned int alc_get_coef0(struct hda_codec *codec);
/* coef writes/updates batch */
struct coef_fw {
unsigned char nid;
unsigned char idx;
unsigned short mask;
unsigned short val;
};
#define UPDATE_COEFEX(_nid, _idx, _mask, _val) \
{ .nid = (_nid), .idx = (_idx), .mask = (_mask), .val = (_val) }
#define WRITE_COEFEX(_nid, _idx, _val) UPDATE_COEFEX(_nid, _idx, -1, _val)
#define WRITE_COEF(_idx, _val) WRITE_COEFEX(0x20, _idx, _val)
#define UPDATE_COEF(_idx, _mask, _val) UPDATE_COEFEX(0x20, _idx, _mask, _val)
void alc_process_coef_fw(struct hda_codec *codec, const struct coef_fw *fw);
/*
* GPIO helpers
*/
void alc_setup_gpio(struct hda_codec *codec, unsigned int mask);
void alc_write_gpio_data(struct hda_codec *codec);
void alc_update_gpio_data(struct hda_codec *codec, unsigned int mask,
bool on);
void alc_write_gpio(struct hda_codec *codec);
/* common GPIO fixups */
void alc_fixup_gpio(struct hda_codec *codec, int action, unsigned int mask);
void alc_fixup_gpio1(struct hda_codec *codec,
const struct hda_fixup *fix, int action);
void alc_fixup_gpio2(struct hda_codec *codec,
const struct hda_fixup *fix, int action);
void alc_fixup_gpio3(struct hda_codec *codec,
const struct hda_fixup *fix, int action);
void alc_fixup_gpio4(struct hda_codec *codec,
const struct hda_fixup *fix, int action);
void alc_fixup_micmute_led(struct hda_codec *codec,
const struct hda_fixup *fix, int action);
/*
* Common init code, callbacks and helpers
*/
void alc_fix_pll(struct hda_codec *codec);
void alc_fix_pll_init(struct hda_codec *codec, hda_nid_t nid,
unsigned int coef_idx, unsigned int coef_bit);
void alc_fill_eapd_coef(struct hda_codec *codec);
void alc_auto_setup_eapd(struct hda_codec *codec, bool on);
int alc_find_ext_mic_pin(struct hda_codec *codec);
void alc_headset_mic_no_shutup(struct hda_codec *codec);
void alc_shutup_pins(struct hda_codec *codec);
void alc_eapd_shutup(struct hda_codec *codec);
void alc_auto_init_amp(struct hda_codec *codec, int type);
hda_nid_t alc_get_hp_pin(struct alc_spec *spec);
int alc_auto_parse_customize_define(struct hda_codec *codec);
int alc_subsystem_id(struct hda_codec *codec, const hda_nid_t *ports);
void alc_ssid_check(struct hda_codec *codec, const hda_nid_t *ports);
int alc_build_controls(struct hda_codec *codec);
void alc_update_knob_master(struct hda_codec *codec,
struct hda_jack_callback *jack);
static inline void alc_pre_init(struct hda_codec *codec)
{
alc_fill_eapd_coef(codec);
}
#define is_s3_resume(codec) \
((codec)->core.dev.power.power_state.event == PM_EVENT_RESUME)
#define is_s4_resume(codec) \
((codec)->core.dev.power.power_state.event == PM_EVENT_RESTORE)
#define is_s4_suspend(codec) \
((codec)->core.dev.power.power_state.event == PM_EVENT_FREEZE)
int alc_init(struct hda_codec *codec);
void alc_shutup(struct hda_codec *codec);
void alc_power_eapd(struct hda_codec *codec);
int alc_suspend(struct hda_codec *codec);
int alc_resume(struct hda_codec *codec);
#define alc_free snd_hda_gen_free
int alc_parse_auto_config(struct hda_codec *codec,
const hda_nid_t *ignore_nids,
const hda_nid_t *ssid_nids);
int alc_alloc_spec(struct hda_codec *codec, hda_nid_t mixer_nid);
extern const struct hda_codec_ops alc_patch_ops;
#define alc_codec_rename(codec, name) snd_hda_codec_set_name(codec, name)
#ifdef CONFIG_SND_HDA_INPUT_BEEP
int alc_set_beep_amp(struct alc_spec *spec, hda_nid_t nid, int idx, int dir);
int alc_has_cdefine_beep(struct hda_codec *codec);
#define set_beep_amp alc_set_beep_amp
#define has_cdefine_beep alc_has_cdefine_beep
#else
#define set_beep_amp(spec, nid, idx, dir) 0
#define has_cdefine_beep(codec) 0
#endif
static inline void rename_ctl(struct hda_codec *codec, const char *oldname,
const char *newname)
{
struct snd_kcontrol *kctl;
kctl = snd_hda_find_mixer_ctl(codec, oldname);
if (kctl)
snd_ctl_rename(codec->card, kctl, newname);
}
/* Common fixups */
void alc_fixup_sku_ignore(struct hda_codec *codec,
const struct hda_fixup *fix, int action);
void alc_fixup_no_depop_delay(struct hda_codec *codec,
const struct hda_fixup *fix, int action);
void alc_fixup_inv_dmic(struct hda_codec *codec,
const struct hda_fixup *fix, int action);
void alc_fixup_dual_codecs(struct hda_codec *codec,
const struct hda_fixup *fix, int action);
void alc_fixup_bass_chmap(struct hda_codec *codec,
const struct hda_fixup *fix, int action);
void alc_fixup_headset_mode(struct hda_codec *codec,
const struct hda_fixup *fix, int action);
void alc_fixup_headset_mode_no_hp_mic(struct hda_codec *codec,
const struct hda_fixup *fix, int action);
void alc_fixup_headset_mic(struct hda_codec *codec,
const struct hda_fixup *fix, int action);
void alc_update_headset_jack_cb(struct hda_codec *codec,
struct hda_jack_callback *jack);
void alc_update_gpio_led(struct hda_codec *codec, unsigned int mask,
int polarity, bool enabled);
void alc_fixup_hp_gpio_led(struct hda_codec *codec,
int action,
unsigned int mute_mask,
unsigned int micmute_mask);
void alc_fixup_no_jack_detect(struct hda_codec *codec,
const struct hda_fixup *fix, int action);
void alc_fixup_disable_aamix(struct hda_codec *codec,
const struct hda_fixup *fix, int action);
void alc_fixup_auto_mute_via_amp(struct hda_codec *codec,
const struct hda_fixup *fix, int action);
/* device-specific, but used by multiple codec drivers */
void alc1220_fixup_gb_dual_codecs(struct hda_codec *codec,
const struct hda_fixup *fix,
int action);
void alc233_alc662_fixup_lenovo_dual_codecs(struct hda_codec *codec,
const struct hda_fixup *fix,
int action);
void alc_fixup_dell_xps13(struct hda_codec *codec,
const struct hda_fixup *fix, int action);
#endif /* __HDA_REALTEK_H */