summaryrefslogtreecommitdiff
path: root/sound/pci/hda/patch_realtek.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/pci/hda/patch_realtek.c')
-rw-r--r--sound/pci/hda/patch_realtek.c119
1 files changed, 47 insertions, 72 deletions
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 4f81dd44c83..8568aee56e2 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -174,7 +174,7 @@ struct alc_spec {
/* hooks */
void (*init_hook)(struct hda_codec *codec);
-#ifdef CONFIG_SND_HDA_POWER_SAVE
+#ifdef CONFIG_PM
void (*power_hook)(struct hda_codec *codec);
#endif
void (*shutup)(struct hda_codec *codec);
@@ -215,7 +215,7 @@ struct alc_spec {
/* for virtual master */
hda_nid_t vmaster_nid;
struct hda_vmaster_mute_hook vmaster_mute;
-#ifdef CONFIG_SND_HDA_POWER_SAVE
+#ifdef CONFIG_PM
struct hda_loopback_check loopback;
int num_loopbacks;
struct hda_amp_list loopback_list[8];
@@ -594,7 +594,7 @@ static void call_update_outputs(struct hda_codec *codec)
}
/* standard HP-automute helper */
-static void alc_hp_automute(struct hda_codec *codec)
+static void alc_hp_automute(struct hda_codec *codec, struct hda_jack_tbl *jack)
{
struct alc_spec *spec = codec->spec;
@@ -607,7 +607,7 @@ static void alc_hp_automute(struct hda_codec *codec)
}
/* standard line-out-automute helper */
-static void alc_line_automute(struct hda_codec *codec)
+static void alc_line_automute(struct hda_codec *codec, struct hda_jack_tbl *jack)
{
struct alc_spec *spec = codec->spec;
@@ -627,7 +627,7 @@ static void alc_line_automute(struct hda_codec *codec)
snd_hda_get_conn_index(codec, mux, nid, 0)
/* standard mic auto-switch helper */
-static void alc_mic_automute(struct hda_codec *codec)
+static void alc_mic_automute(struct hda_codec *codec, struct hda_jack_tbl *jack)
{
struct alc_spec *spec = codec->spec;
hda_nid_t *pins = spec->imux_pins;
@@ -648,25 +648,8 @@ static void alc_mic_automute(struct hda_codec *codec)
alc_mux_select(codec, 0, spec->int_mic_idx, false);
}
-/* handle the specified unsol action (ALC_XXX_EVENT) */
-static void alc_exec_unsol_event(struct hda_codec *codec, int action)
-{
- switch (action) {
- case ALC_HP_EVENT:
- alc_hp_automute(codec);
- break;
- case ALC_FRONT_EVENT:
- alc_line_automute(codec);
- break;
- case ALC_MIC_EVENT:
- alc_mic_automute(codec);
- break;
- }
- snd_hda_jack_report_sync(codec);
-}
-
/* update the master volume per volume-knob's unsol event */
-static void alc_update_knob_master(struct hda_codec *codec, hda_nid_t nid)
+static void alc_update_knob_master(struct hda_codec *codec, struct hda_jack_tbl *jack)
{
unsigned int val;
struct snd_kcontrol *kctl;
@@ -678,7 +661,7 @@ static void alc_update_knob_master(struct hda_codec *codec, hda_nid_t nid)
uctl = kzalloc(sizeof(*uctl), GFP_KERNEL);
if (!uctl)
return;
- val = snd_hda_codec_read(codec, nid, 0,
+ val = snd_hda_codec_read(codec, jack->nid, 0,
AC_VERB_GET_VOLUME_KNOB_CONTROL, 0);
val &= HDA_AMP_VOLMASK;
uctl->value.integer.value[0] = val;
@@ -687,37 +670,19 @@ static void alc_update_knob_master(struct hda_codec *codec, hda_nid_t nid)
kfree(uctl);
}
-/* unsolicited event for HP jack sensing */
-static void alc_unsol_event(struct hda_codec *codec, unsigned int res)
+static void alc880_unsol_event(struct hda_codec *codec, unsigned int res)
{
- int action;
-
- if (codec->vendor_id == 0x10ec0880)
- res >>= 28;
- else
- res >>= 26;
- action = snd_hda_jack_get_action(codec, res);
- if (action == ALC_DCVOL_EVENT) {
- /* Execute the dc-vol event here as it requires the NID
- * but we don't pass NID to alc_exec_unsol_event().
- * Once when we convert all static quirks to the auto-parser,
- * this can be integerated into there.
- */
- struct hda_jack_tbl *jack;
- jack = snd_hda_jack_tbl_get_from_tag(codec, res);
- if (jack)
- alc_update_knob_master(codec, jack->nid);
- return;
- }
- alc_exec_unsol_event(codec, action);
+ /* For some reason, the res given from ALC880 is broken.
+ Here we adjust it properly. */
+ snd_hda_jack_unsol_event(codec, res >> 2);
}
/* call init functions of standard auto-mute helpers */
static void alc_inithook(struct hda_codec *codec)
{
- alc_hp_automute(codec);
- alc_line_automute(codec);
- alc_mic_automute(codec);
+ alc_hp_automute(codec, NULL);
+ alc_line_automute(codec, NULL);
+ alc_mic_automute(codec, NULL);
}
/* additional initialization for ALC888 variants */
@@ -999,7 +964,8 @@ static void alc_init_automute(struct hda_codec *codec)
continue;
snd_printdd("realtek: Enable HP auto-muting on NID 0x%x\n",
nid);
- snd_hda_jack_detect_enable(codec, nid, ALC_HP_EVENT);
+ snd_hda_jack_detect_enable_callback(codec, nid, ALC_HP_EVENT,
+ alc_hp_automute);
spec->detect_hp = 1;
}
@@ -1011,10 +977,10 @@ static void alc_init_automute(struct hda_codec *codec)
continue;
snd_printdd("realtek: Enable Line-Out "
"auto-muting on NID 0x%x\n", nid);
- snd_hda_jack_detect_enable(codec, nid,
- ALC_FRONT_EVENT);
+ snd_hda_jack_detect_enable_callback(codec, nid, ALC_FRONT_EVENT,
+ alc_line_automute);
spec->detect_lo = 1;
- }
+ }
spec->automute_lo_possible = spec->detect_hp;
}
@@ -1110,10 +1076,12 @@ static bool alc_auto_mic_check_imux(struct hda_codec *codec)
return false; /* no corresponding imux */
}
- snd_hda_jack_detect_enable(codec, spec->ext_mic_pin, ALC_MIC_EVENT);
+ snd_hda_jack_detect_enable_callback(codec, spec->ext_mic_pin,
+ ALC_MIC_EVENT, alc_mic_automute);
if (spec->dock_mic_pin)
- snd_hda_jack_detect_enable(codec, spec->dock_mic_pin,
- ALC_MIC_EVENT);
+ snd_hda_jack_detect_enable_callback(codec, spec->dock_mic_pin,
+ ALC_MIC_EVENT,
+ alc_mic_automute);
spec->auto_mic_valid_imux = 1;
spec->auto_mic = 1;
@@ -2053,13 +2021,11 @@ static int alc_init(struct hda_codec *codec)
alc_apply_fixup(codec, ALC_FIXUP_ACT_INIT);
- snd_hda_jack_report_sync(codec);
-
hda_call_check_power_status(codec, 0x01);
return 0;
}
-#ifdef CONFIG_SND_HDA_POWER_SAVE
+#ifdef CONFIG_PM
static int alc_check_power_status(struct hda_codec *codec, hda_nid_t nid)
{
struct alc_spec *spec = codec->spec;
@@ -2289,6 +2255,8 @@ static int alc_build_pcms(struct hda_codec *codec)
p = &alc_pcm_analog_playback;
info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *p;
info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dac_nids[0];
+ info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max =
+ spec->multiout.max_channels;
}
if (spec->adc_nids) {
p = spec->stream_analog_capture;
@@ -2437,7 +2405,7 @@ static void alc_free(struct hda_codec *codec)
snd_hda_detach_beep_device(codec);
}
-#ifdef CONFIG_SND_HDA_POWER_SAVE
+#ifdef CONFIG_PM
static void alc_power_eapd(struct hda_codec *codec)
{
alc_auto_setup_eapd(codec, false);
@@ -2473,17 +2441,18 @@ static const struct hda_codec_ops alc_patch_ops = {
.build_pcms = alc_build_pcms,
.init = alc_init,
.free = alc_free,
- .unsol_event = alc_unsol_event,
+ .unsol_event = snd_hda_jack_unsol_event,
#ifdef CONFIG_PM
.resume = alc_resume,
#endif
-#ifdef CONFIG_SND_HDA_POWER_SAVE
+#ifdef CONFIG_PM
.suspend = alc_suspend,
.check_power_status = alc_check_power_status,
#endif
.reboot_notify = alc_shutup,
};
+
/* replace the codec chip_name with the given string */
static int alc_codec_rename(struct hda_codec *codec, const char *name)
{
@@ -2633,7 +2602,7 @@ static const char *alc_get_line_out_pfx(struct alc_spec *spec, int ch,
return channel_name[ch];
}
-#ifdef CONFIG_SND_HDA_POWER_SAVE
+#ifdef CONFIG_PM
/* add the powersave loopback-list entry */
static void add_loopback_list(struct alc_spec *spec, hda_nid_t mix, int idx)
{
@@ -4447,7 +4416,7 @@ static void alc880_fixup_vol_knob(struct hda_codec *codec,
const struct alc_fixup *fix, int action)
{
if (action == ALC_FIXUP_ACT_PROBE)
- snd_hda_jack_detect_enable(codec, 0x21, ALC_DCVOL_EVENT);
+ snd_hda_jack_detect_enable_callback(codec, 0x21, ALC_DCVOL_EVENT, alc_update_knob_master);
}
static const struct alc_fixup alc880_fixups[] = {
@@ -4812,6 +4781,8 @@ static int patch_alc880(struct hda_codec *codec)
}
codec->patch_ops = alc_patch_ops;
+ codec->patch_ops.unsol_event = alc880_unsol_event;
+
alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
@@ -4866,7 +4837,8 @@ static void alc260_fixup_gpio1_toggle(struct hda_codec *codec,
spec->detect_hp = 1;
spec->automute_speaker = 1;
spec->autocfg.hp_pins[0] = 0x0f; /* copy it for automute */
- snd_hda_jack_detect_enable(codec, 0x0f, ALC_HP_EVENT);
+ snd_hda_jack_detect_enable_callback(codec, 0x0f, ALC_HP_EVENT,
+ alc_hp_automute);
snd_hda_gen_add_verbs(&spec->gen, alc_gpio1_init_verbs);
}
}
@@ -6189,6 +6161,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x1025, 0x0349, "Acer AOD260", ALC269_FIXUP_INV_DMIC),
SND_PCI_QUIRK(0x103c, 0x1586, "HP", ALC269_FIXUP_MIC2_MUTE_LED),
SND_PCI_QUIRK(0x1043, 0x1427, "Asus Zenbook UX31E", ALC269VB_FIXUP_DMIC),
+ SND_PCI_QUIRK(0x1043, 0x1517, "Asus Zenbook UX31A", ALC269VB_FIXUP_DMIC),
SND_PCI_QUIRK(0x1043, 0x1a13, "Asus G73Jw", ALC269_FIXUP_ASUS_G73JW),
SND_PCI_QUIRK(0x1043, 0x1b13, "Asus U41SV", ALC269_FIXUP_INV_DMIC),
SND_PCI_QUIRK(0x1043, 0x16e3, "ASUS UX50", ALC269_FIXUP_STEREO_DMIC),
@@ -6334,6 +6307,12 @@ static int patch_alc269(struct hda_codec *codec)
spec = codec->spec;
+ alc_pick_fixup(codec, alc269_fixup_models,
+ alc269_fixup_tbl, alc269_fixups);
+ alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
+
+ alc_auto_parse_customize_define(codec);
+
if (codec->vendor_id == 0x10ec0269) {
spec->codec_variant = ALC269_TYPE_ALC269VA;
switch (alc_get_coef0(codec) & 0x00f0) {
@@ -6361,12 +6340,6 @@ static int patch_alc269(struct hda_codec *codec)
alc269_fill_coef(codec);
}
- alc_pick_fixup(codec, alc269_fixup_models,
- alc269_fixup_tbl, alc269_fixups);
- alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
-
- alc_auto_parse_customize_define(codec);
-
/* automatic parse from the BIOS config */
err = alc269_parse_auto_config(codec);
if (err < 0)
@@ -6503,7 +6476,7 @@ static int patch_alc861(struct hda_codec *codec)
}
codec->patch_ops = alc_patch_ops;
-#ifdef CONFIG_SND_HDA_POWER_SAVE
+#ifdef CONFIG_PM
spec->power_hook = alc_power_eapd;
#endif
@@ -7068,6 +7041,8 @@ static const struct hda_codec_preset snd_hda_preset_realtek[] = {
{ .id = 0x10ec0276, .name = "ALC276", .patch = patch_alc269 },
{ .id = 0x10ec0280, .name = "ALC280", .patch = patch_alc269 },
{ .id = 0x10ec0282, .name = "ALC282", .patch = patch_alc269 },
+ { .id = 0x10ec0283, .name = "ALC283", .patch = patch_alc269 },
+ { .id = 0x10ec0290, .name = "ALC290", .patch = patch_alc269 },
{ .id = 0x10ec0861, .rev = 0x100340, .name = "ALC660",
.patch = patch_alc861 },
{ .id = 0x10ec0660, .name = "ALC660-VD", .patch = patch_alc861vd },