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

Commit 47fd830a authored by Takashi Iwai's avatar Takashi Iwai Committed by Jaroslav Kysela
Browse files

[ALSA] hda-codec - add snd_hda_codec_stereo() function



Added snd_hda_codec_amp_stereo() function that changes both of stereo
channels with the same mask and value bits.  It simplifies most of
amp-handling codes.

Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
Signed-off-by: default avatarJaroslav Kysela <perex@suse.cz>
parent 82beb8fd
Loading
Loading
Loading
Loading
+26 −12
Original line number Diff line number Diff line
@@ -842,6 +842,19 @@ int snd_hda_codec_amp_update(struct hda_codec *codec, hda_nid_t nid, int ch,
	return 1;
}

/*
 * update the AMP stereo with the same mask and value
 */
int snd_hda_codec_amp_stereo(struct hda_codec *codec, hda_nid_t nid,
			     int direction, int idx, int mask, int val)
{
	int ch, ret = 0;
	for (ch = 0; ch < 2; ch++)
		ret |= snd_hda_codec_amp_update(codec, nid, ch, direction,
						idx, mask, val);
	return ret;
}

#ifdef CONFIG_PM
/* resume the all amp commands from the cache */
void snd_hda_codec_resume_amp(struct hda_codec *codec)
@@ -913,9 +926,11 @@ int snd_hda_mixer_amp_volume_get(struct snd_kcontrol *kcontrol,
	long *valp = ucontrol->value.integer.value;

	if (chs & 1)
		*valp++ = snd_hda_codec_amp_read(codec, nid, 0, dir, idx) & 0x7f;
		*valp++ = snd_hda_codec_amp_read(codec, nid, 0, dir, idx)
			& HDA_AMP_VOLMASK;
	if (chs & 2)
		*valp = snd_hda_codec_amp_read(codec, nid, 1, dir, idx) & 0x7f;
		*valp = snd_hda_codec_amp_read(codec, nid, 1, dir, idx)
			& HDA_AMP_VOLMASK;
	return 0;
}

@@ -992,10 +1007,10 @@ int snd_hda_mixer_amp_switch_get(struct snd_kcontrol *kcontrol,

	if (chs & 1)
		*valp++ = (snd_hda_codec_amp_read(codec, nid, 0, dir, idx) &
			   0x80) ? 0 : 1;
			   HDA_AMP_MUTE) ? 0 : 1;
	if (chs & 2)
		*valp = (snd_hda_codec_amp_read(codec, nid, 1, dir, idx) &
			 0x80) ? 0 : 1;
			 HDA_AMP_MUTE) ? 0 : 1;
	return 0;
}

@@ -1012,12 +1027,14 @@ int snd_hda_mixer_amp_switch_put(struct snd_kcontrol *kcontrol,

	if (chs & 1) {
		change = snd_hda_codec_amp_update(codec, nid, 0, dir, idx,
						  0x80, *valp ? 0 : 0x80);
						  HDA_AMP_MUTE,
						  *valp ? 0 : HDA_AMP_MUTE);
		valp++;
	}
	if (chs & 2)
		change |= snd_hda_codec_amp_update(codec, nid, 1, dir, idx,
						   0x80, *valp ? 0 : 0x80);
						   HDA_AMP_MUTE,
						   *valp ? 0 : HDA_AMP_MUTE);
	
	return change;
}
@@ -1318,12 +1335,9 @@ static int snd_hda_spdif_out_switch_put(struct snd_kcontrol *kcontrol,
					  val & 0xff);
		/* unmute amp switch (if any) */
		if ((get_wcaps(codec, nid) & AC_WCAP_OUT_AMP) &&
		    (val & AC_DIG1_ENABLE)) {
			snd_hda_codec_amp_update(codec, nid, 0, HDA_OUTPUT, 0,
						 0x80, 0x00);
			snd_hda_codec_amp_update(codec, nid, 1, HDA_OUTPUT, 0,
						 0x80, 0x00);
		}
		    (val & AC_DIG1_ENABLE))
			snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
						 HDA_AMP_MUTE, 0);
	}
	mutex_unlock(&codec->spdif_mutex);
	return change;
+2 −6
Original line number Diff line number Diff line
@@ -218,8 +218,7 @@ static int unmute_output(struct hda_codec *codec, struct hda_gnode *node)
	ofs = (node->amp_out_caps & AC_AMPCAP_OFFSET) >> AC_AMPCAP_OFFSET_SHIFT;
	if (val >= ofs)
		val -= ofs;
	snd_hda_codec_amp_update(codec, node->nid, 0, HDA_OUTPUT, 0, 0xff, val);
	snd_hda_codec_amp_update(codec, node->nid, 0, HDA_OUTPUT, 1, 0xff, val);
	snd_hda_codec_amp_stereo(codec, node->nid, HDA_OUTPUT, 0, 0xff, val);
	return 0;
}

@@ -234,10 +233,7 @@ static int unmute_input(struct hda_codec *codec, struct hda_gnode *node, unsigne
	ofs = (node->amp_in_caps & AC_AMPCAP_OFFSET) >> AC_AMPCAP_OFFSET_SHIFT;
	if (val >= ofs)
		val -= ofs;
	snd_hda_codec_amp_update(codec, node->nid, 0, HDA_INPUT, index,
				 0xff, val);
	snd_hda_codec_amp_update(codec, node->nid, 1, HDA_INPUT, index,
				 0xff, val);
	snd_hda_codec_amp_stereo(codec, node->nid, HDA_INPUT, index, 0xff, val);
	return 0;
}

+7 −0
Original line number Diff line number Diff line
@@ -84,10 +84,17 @@ int snd_hda_codec_amp_read(struct hda_codec *codec, hda_nid_t nid, int ch,
			   int direction, int index);
int snd_hda_codec_amp_update(struct hda_codec *codec, hda_nid_t nid, int ch,
			     int direction, int idx, int mask, int val);
int snd_hda_codec_amp_stereo(struct hda_codec *codec, hda_nid_t nid,
			     int dir, int idx, int mask, int val);
#ifdef CONFIG_PM
void snd_hda_codec_resume_amp(struct hda_codec *codec);
#endif

/* amp value bits */
#define HDA_AMP_MUTE	0x80
#define HDA_AMP_UNMUTE	0x00
#define HDA_AMP_VOLMASK	0x7f

/* mono switch binding multiple inputs */
#define HDA_BIND_MUTE_MONO(xname, nid, channel, indices, direction) \
	{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0,  \
+9 −12
Original line number Diff line number Diff line
@@ -1120,10 +1120,9 @@ static int ad1981_hp_master_sw_put(struct snd_kcontrol *kcontrol,
		return 0;

	/* toggle HP mute appropriately */
	snd_hda_codec_amp_update(codec, 0x06, 0, HDA_OUTPUT, 0,
				 0x80, spec->cur_eapd ? 0 : 0x80);
	snd_hda_codec_amp_update(codec, 0x06, 1, HDA_OUTPUT, 0,
				 0x80, spec->cur_eapd ? 0 : 0x80);
	snd_hda_codec_amp_stereo(codec, 0x06, HDA_OUTPUT, 0,
				 HDA_AMP_MUTE,
				 spec->cur_eapd ? 0 : HDA_AMP_MUTE);
	return 1;
}

@@ -1136,13 +1135,13 @@ static int ad1981_hp_master_vol_put(struct snd_kcontrol *kcontrol,
	int change;

	change = snd_hda_codec_amp_update(codec, 0x05, 0, HDA_OUTPUT, 0,
					  0x7f, valp[0] & 0x7f);
					  HDA_AMP_VOLMASK, valp[0]);
	change |= snd_hda_codec_amp_update(codec, 0x05, 1, HDA_OUTPUT, 0,
					   0x7f, valp[1] & 0x7f);
					   HDA_AMP_VOLMASK, valp[1]);
	snd_hda_codec_amp_update(codec, 0x06, 0, HDA_OUTPUT, 0,
				 0x7f, valp[0] & 0x7f);
				 HDA_AMP_VOLMASK, valp[0]);
	snd_hda_codec_amp_update(codec, 0x06, 1, HDA_OUTPUT, 0,
				 0x7f, valp[1] & 0x7f);
				 HDA_AMP_VOLMASK, valp[1]);
	return change;
}

@@ -1153,10 +1152,8 @@ static void ad1981_hp_automute(struct hda_codec *codec)

	present = snd_hda_codec_read(codec, 0x06, 0,
				     AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
	snd_hda_codec_amp_update(codec, 0x05, 0, HDA_OUTPUT, 0,
				 0x80, present ? 0x80 : 0);
	snd_hda_codec_amp_update(codec, 0x05, 1, HDA_OUTPUT, 0,
				 0x80, present ? 0x80 : 0);
	snd_hda_codec_amp_stereo(codec, 0x05, HDA_OUTPUT, 0,
				 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
}

/* toggle input of built-in and mic jack appropriately */
+33 −33
Original line number Diff line number Diff line
@@ -472,13 +472,13 @@ static int cxt5045_hp_master_sw_put(struct snd_kcontrol *kcontrol,
	/* toggle internal speakers mute depending of presence of
	 * the headphone jack
	 */
	bits = (!spec->hp_present && spec->cur_eapd) ? 0 : 0x80;
	snd_hda_codec_amp_update(codec, 0x10, 0, HDA_OUTPUT, 0, 0x80, bits);
	snd_hda_codec_amp_update(codec, 0x10, 1, HDA_OUTPUT, 0, 0x80, bits);
	bits = (!spec->hp_present && spec->cur_eapd) ? 0 : HDA_AMP_MUTE;
	snd_hda_codec_amp_stereo(codec, 0x10, HDA_OUTPUT, 0,
				 HDA_AMP_MUTE, bits);

	bits = spec->cur_eapd ? 0 : 0x80;
	snd_hda_codec_amp_update(codec, 0x11, 0, HDA_OUTPUT, 0, 0x80, bits);
	snd_hda_codec_amp_update(codec, 0x11, 1, HDA_OUTPUT, 0, 0x80, bits);
	bits = spec->cur_eapd ? 0 : HDA_AMP_MUTE;
	snd_hda_codec_amp_stereo(codec, 0x11, HDA_OUTPUT, 0,
				 HDA_AMP_MUTE, bits);
	return 1;
}

@@ -491,13 +491,13 @@ static int cxt5045_hp_master_vol_put(struct snd_kcontrol *kcontrol,
	int change;

	change = snd_hda_codec_amp_update(codec, 0x10, 0, HDA_OUTPUT, 0,
					  0x7f, valp[0] & 0x7f);
					  HDA_AMP_VOLMASK, valp[0]);
	change |= snd_hda_codec_amp_update(codec, 0x10, 1, HDA_OUTPUT, 0,
					   0x7f, valp[1] & 0x7f);
					   HDA_AMP_VOLMASK, valp[1]);
	snd_hda_codec_amp_update(codec, 0x11, 0, HDA_OUTPUT, 0,
				 0x7f, valp[0] & 0x7f);
				 HDA_AMP_VOLMASK, valp[0]);
	snd_hda_codec_amp_update(codec, 0x11, 1, HDA_OUTPUT, 0,
				 0x7f, valp[1] & 0x7f);
				 HDA_AMP_VOLMASK, valp[1]);
	return change;
}

@@ -534,9 +534,9 @@ static void cxt5045_hp_automute(struct hda_codec *codec)
	spec->hp_present = snd_hda_codec_read(codec, 0x11, 0,
				     AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;

	bits = (spec->hp_present || !spec->cur_eapd) ? 0x80 : 0; 
	snd_hda_codec_amp_update(codec, 0x10, 0, HDA_OUTPUT, 0, 0x80, bits);
	snd_hda_codec_amp_update(codec, 0x10, 1, HDA_OUTPUT, 0, 0x80, bits);
	bits = (spec->hp_present || !spec->cur_eapd) ? HDA_AMP_MUTE : 0; 
	snd_hda_codec_amp_stereo(codec, 0x10, HDA_OUTPUT, 0,
				 HDA_AMP_MUTE, bits);
}

/* unsolicited event for HP jack sensing */
@@ -887,12 +887,12 @@ static int cxt5047_hp_master_sw_put(struct snd_kcontrol *kcontrol,
	/* toggle internal speakers mute depending of presence of
	 * the headphone jack
	 */
	bits = (!spec->hp_present && spec->cur_eapd) ? 0 : 0x80;
	snd_hda_codec_amp_update(codec, 0x1d, 0, HDA_OUTPUT, 0, 0x80, bits);
	snd_hda_codec_amp_update(codec, 0x1d, 1, HDA_OUTPUT, 0, 0x80, bits);
	bits = spec->cur_eapd ? 0 : 0x80;
	snd_hda_codec_amp_update(codec, 0x13, 0, HDA_OUTPUT, 0, 0x80, bits);
	snd_hda_codec_amp_update(codec, 0x13, 1, HDA_OUTPUT, 0, 0x80, bits);
	bits = (!spec->hp_present && spec->cur_eapd) ? 0 : HDA_AMP_MUTE;
	snd_hda_codec_amp_stereo(codec, 0x1d, HDA_OUTPUT, 0,
				 HDA_AMP_MUTE, bits);
	bits = spec->cur_eapd ? 0 : HDA_AMP_MUTE;
	snd_hda_codec_amp_stereo(codec, 0x13, HDA_OUTPUT, 0,
				 HDA_AMP_MUTE, bits);
	return 1;
}

@@ -905,13 +905,13 @@ static int cxt5047_hp_master_vol_put(struct snd_kcontrol *kcontrol,
	int change;

	change = snd_hda_codec_amp_update(codec, 0x1d, 0, HDA_OUTPUT, 0,
					  0x7f, valp[0] & 0x7f);
					  HDA_AMP_VOLMASK, valp[0]);
	change |= snd_hda_codec_amp_update(codec, 0x1d, 1, HDA_OUTPUT, 0,
					   0x7f, valp[1] & 0x7f);
					   HDA_AMP_VOLMASK, valp[1]);
	snd_hda_codec_amp_update(codec, 0x13, 0, HDA_OUTPUT, 0,
				 0x7f, valp[0] & 0x7f);
				 HDA_AMP_VOLMASK, valp[0]);
	snd_hda_codec_amp_update(codec, 0x13, 1, HDA_OUTPUT, 0,
				 0x7f, valp[1] & 0x7f);
				 HDA_AMP_VOLMASK, valp[1]);
	return change;
}

@@ -924,12 +924,12 @@ static void cxt5047_hp_automute(struct hda_codec *codec)
	spec->hp_present = snd_hda_codec_read(codec, 0x13, 0,
				     AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;

	bits = (spec->hp_present || !spec->cur_eapd) ? 0x80 : 0;
	snd_hda_codec_amp_update(codec, 0x1d, 0, HDA_OUTPUT, 0, 0x80, bits);
	snd_hda_codec_amp_update(codec, 0x1d, 1, HDA_OUTPUT, 0, 0x80, bits);
	bits = (spec->hp_present || !spec->cur_eapd) ? HDA_AMP_MUTE : 0;
	snd_hda_codec_amp_stereo(codec, 0x1d, HDA_OUTPUT, 0,
				 HDA_AMP_MUTE, bits);
	/* Mute/Unmute PCM 2 for good measure - some systems need this */
	snd_hda_codec_amp_update(codec, 0x1c, 0, HDA_OUTPUT, 0, 0x80, bits);
	snd_hda_codec_amp_update(codec, 0x1c, 1, HDA_OUTPUT, 0, 0x80, bits);
	snd_hda_codec_amp_stereo(codec, 0x1c, HDA_OUTPUT, 0,
				 HDA_AMP_MUTE, bits);
}

/* mute internal speaker if HP is plugged */
@@ -941,12 +941,12 @@ static void cxt5047_hp2_automute(struct hda_codec *codec)
	spec->hp_present = snd_hda_codec_read(codec, 0x13, 0,
				     AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;

	bits = spec->hp_present ? 0x80 : 0;
	snd_hda_codec_amp_update(codec, 0x1d, 0, HDA_OUTPUT, 0, 0x80, bits);
	snd_hda_codec_amp_update(codec, 0x1d, 1, HDA_OUTPUT, 0, 0x80, bits);
	bits = spec->hp_present ? HDA_AMP_MUTE : 0;
	snd_hda_codec_amp_stereo(codec, 0x1d, HDA_OUTPUT, 0,
				 HDA_AMP_MUTE, bits);
	/* Mute/Unmute PCM 2 for good measure - some systems need this */
	snd_hda_codec_amp_update(codec, 0x1c, 0, HDA_OUTPUT, 0, 0x80, bits);
	snd_hda_codec_amp_update(codec, 0x1c, 1, HDA_OUTPUT, 0, 0x80, bits);
	snd_hda_codec_amp_stereo(codec, 0x1c, HDA_OUTPUT, 0,
				 HDA_AMP_MUTE, bits);
}

/* toggle input of built-in and mic jack appropriately */
Loading