Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f21d78e2 authored by Takashi Iwai's avatar Takashi Iwai
Browse files

ALSA: hda/realtek - Avoid conflict of unsol-events with static quirks



The recently added jack-kctl support sets the unsol event tags
dynamically, while static quirks usually set the fixed tags in the
init_verbs array.  Due to this conflict, the own unsol event handler
can't retrieve the tag and handle it properly any more.

For fixing this, avoid calling snd_hda_jack_add_kctls() for static
quirks, and always let them use own handlers instead of the standard
one for the auto-pareser.

Reported-by: default avatarDavid Henningsson <david.henningsson@canonical.com>
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent b90bf1de
Loading
Loading
Loading
Loading
+12 −5
Original line number Diff line number Diff line
@@ -762,16 +762,22 @@ static void alc880_uniwill_unsol_event(struct hda_codec *codec,
	/* Looks like the unsol event is incompatible with the standard
	 * definition.  4bit tag is placed at 28 bit!
	 */
	switch (res >> 28) {
	res >>= 28;
	switch (res) {
	case ALC_MIC_EVENT:
		alc88x_simple_mic_automute(codec);
		break;
	default:
		alc_sku_unsol_event(codec, res);
		alc_exec_unsol_event(codec, res);
		break;
	}
}

static void alc880_unsol_event(struct hda_codec *codec, unsigned int res)
{
	alc_exec_unsol_event(codec, res >> 28);
}

static void alc880_uniwill_p53_setup(struct hda_codec *codec)
{
	struct alc_spec *spec = codec->spec;
@@ -800,10 +806,11 @@ static void alc880_uniwill_p53_unsol_event(struct hda_codec *codec,
	/* Looks like the unsol event is incompatible with the standard
	 * definition.  4bit tag is placed at 28 bit!
	 */
	if ((res >> 28) == ALC_DCVOL_EVENT)
	res >>= 28;
	if (res == ALC_DCVOL_EVENT)
		alc880_uniwill_p53_dcvol_automute(codec);
	else
		alc_sku_unsol_event(codec, res);
		alc_exec_unsol_event(codec, res);
}

/*
@@ -1677,7 +1684,7 @@ static const struct alc_config_preset alc880_presets[] = {
		.channel_mode = alc880_lg_ch_modes,
		.need_dac_fix = 1,
		.input_mux = &alc880_lg_capture_source,
		.unsol_event = alc_sku_unsol_event,
		.unsol_event = alc880_unsol_event,
		.setup = alc880_lg_setup,
		.init_hook = alc_hp_automute,
#ifdef CONFIG_SND_HDA_POWER_SAVE
+10 −5
Original line number Diff line number Diff line
@@ -730,6 +730,11 @@ static void alc889A_mb31_unsol_event(struct hda_codec *codec, unsigned int res)
		alc889A_mb31_automute(codec);
}

static void alc882_unsol_event(struct hda_codec *codec, unsigned int res)
{
	alc_exec_unsol_event(codec, res >> 26);
}

/*
 * configuration and preset
 */
@@ -775,7 +780,7 @@ static const struct alc_config_preset alc882_presets[] = {
			.channel_mode = alc885_mba21_ch_modes,
			.num_channel_mode = ARRAY_SIZE(alc885_mba21_ch_modes),
			.input_mux = &alc882_capture_source,
			.unsol_event = alc_sku_unsol_event,
			.unsol_event = alc882_unsol_event,
			.setup = alc885_mba21_setup,
			.init_hook = alc_hp_automute,
       },
@@ -791,7 +796,7 @@ static const struct alc_config_preset alc882_presets[] = {
		.input_mux = &alc882_capture_source,
		.dig_out_nid = ALC882_DIGOUT_NID,
		.dig_in_nid = ALC882_DIGIN_NID,
		.unsol_event = alc_sku_unsol_event,
		.unsol_event = alc882_unsol_event,
		.setup = alc885_mbp3_setup,
		.init_hook = alc_hp_automute,
	},
@@ -806,7 +811,7 @@ static const struct alc_config_preset alc882_presets[] = {
		.input_mux = &mb5_capture_source,
		.dig_out_nid = ALC882_DIGOUT_NID,
		.dig_in_nid = ALC882_DIGIN_NID,
		.unsol_event = alc_sku_unsol_event,
		.unsol_event = alc882_unsol_event,
		.setup = alc885_mb5_setup,
		.init_hook = alc_hp_automute,
	},
@@ -821,7 +826,7 @@ static const struct alc_config_preset alc882_presets[] = {
		.input_mux = &macmini3_capture_source,
		.dig_out_nid = ALC882_DIGOUT_NID,
		.dig_in_nid = ALC882_DIGIN_NID,
		.unsol_event = alc_sku_unsol_event,
		.unsol_event = alc882_unsol_event,
		.setup = alc885_macmini3_setup,
		.init_hook = alc_hp_automute,
	},
@@ -836,7 +841,7 @@ static const struct alc_config_preset alc882_presets[] = {
		.input_mux = &alc889A_imac91_capture_source,
		.dig_out_nid = ALC882_DIGOUT_NID,
		.dig_in_nid = ALC882_DIGIN_NID,
		.unsol_event = alc_sku_unsol_event,
		.unsol_event = alc882_unsol_event,
		.setup = alc885_imac91_setup,
		.init_hook = alc_hp_automute,
	},
+31 −14
Original line number Diff line number Diff line
@@ -621,17 +621,10 @@ static void alc_mic_automute(struct hda_codec *codec)
		alc_mux_select(codec, 0, spec->int_mic_idx, false);
}

/* unsolicited event for HP jack sensing */
static void alc_sku_unsol_event(struct hda_codec *codec, unsigned int res)
/* handle the specified unsol action (ALC_XXX_EVENT) */
static void alc_exec_unsol_event(struct hda_codec *codec, int action)
{
	struct alc_spec *spec = codec->spec;
	if (codec->vendor_id == 0x10ec0880)
		res >>= 28;
	else
		res >>= 26;
	if (spec->use_jack_tbl)
		res = snd_hda_jack_get_action(codec, res);
	switch (res) {
	switch (action) {
	case ALC_HP_EVENT:
		alc_hp_automute(codec);
		break;
@@ -645,6 +638,19 @@ static void alc_sku_unsol_event(struct hda_codec *codec, unsigned int res)
	snd_hda_jack_report_sync(codec);
}

/* unsolicited event for HP jack sensing */
static void alc_sku_unsol_event(struct hda_codec *codec, unsigned int res)
{
	struct alc_spec *spec = codec->spec;
	if (codec->vendor_id == 0x10ec0880)
		res >>= 28;
	else
		res >>= 26;
	if (spec->use_jack_tbl)
		res = snd_hda_jack_get_action(codec, res);
	alc_exec_unsol_event(codec, res);
}

/* call init functions of standard auto-mute helpers */
static void alc_inithook(struct hda_codec *codec)
{
@@ -1883,7 +1889,7 @@ static const struct snd_kcontrol_new alc_beep_mixer[] = {
};
#endif

static int alc_build_controls(struct hda_codec *codec)
static int __alc_build_controls(struct hda_codec *codec)
{
	struct alc_spec *spec = codec->spec;
	struct snd_kcontrol *kctl = NULL;
@@ -2029,11 +2035,16 @@ static int alc_build_controls(struct hda_codec *codec)

	alc_free_kctls(codec); /* no longer needed */

	err = snd_hda_jack_add_kctls(codec, &spec->autocfg);
	return 0;
}

static int alc_build_controls(struct hda_codec *codec)
{
	struct alc_spec *spec = codec->spec;
	int err = __alc_build_controls(codec);
	if (err < 0)
		return err;

	return 0;
	return snd_hda_jack_add_kctls(codec, &spec->autocfg);
}


@@ -4168,6 +4179,8 @@ static int patch_alc880(struct hda_codec *codec)
	codec->patch_ops = alc_patch_ops;
	if (board_config == ALC_MODEL_AUTO)
		spec->init_hook = alc_auto_init_std;
	else
		codec->patch_ops.build_controls = __alc_build_controls;
#ifdef CONFIG_SND_HDA_POWER_SAVE
	if (!spec->loopback.amplist)
		spec->loopback.amplist = alc880_loopbacks;
@@ -4297,6 +4310,8 @@ static int patch_alc260(struct hda_codec *codec)
	codec->patch_ops = alc_patch_ops;
	if (board_config == ALC_MODEL_AUTO)
		spec->init_hook = alc_auto_init_std;
	else
		codec->patch_ops.build_controls = __alc_build_controls;
	spec->shutup = alc_eapd_shutup;
#ifdef CONFIG_SND_HDA_POWER_SAVE
	if (!spec->loopback.amplist)
@@ -4691,6 +4706,8 @@ static int patch_alc882(struct hda_codec *codec)
	codec->patch_ops = alc_patch_ops;
	if (board_config == ALC_MODEL_AUTO)
		spec->init_hook = alc_auto_init_std;
	else
		codec->patch_ops.build_controls = __alc_build_controls;

#ifdef CONFIG_SND_HDA_POWER_SAVE
	if (!spec->loopback.amplist)