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

Commit 4740860b authored by Takashi Iwai's avatar Takashi Iwai
Browse files

ALSA: hda - Add snd_hda_get_default_vref() helper function



Add a new helper function to guess the default VREF pin control bits
for mic in.  This can be used to set the pin control value safely
matching with the actual pin capabilities.

Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent cdd03ced
Loading
Loading
Loading
Loading
+27 −0
Original line number Original line Diff line number Diff line
@@ -4795,6 +4795,33 @@ int snd_hda_multi_out_analog_cleanup(struct hda_codec *codec,
}
}
EXPORT_SYMBOL_HDA(snd_hda_multi_out_analog_cleanup);
EXPORT_SYMBOL_HDA(snd_hda_multi_out_analog_cleanup);


/**
 * snd_hda_get_default_vref - Get the default (mic) VREF pin bits
 *
 * Guess the suitable VREF pin bits to be set as the pin-control value.
 * Note: the function doesn't set the AC_PINCTL_IN_EN bit.
 */
unsigned int snd_hda_get_default_vref(struct hda_codec *codec, hda_nid_t pin)
{
	unsigned int pincap;
	unsigned int oldval;
	oldval = snd_hda_codec_read(codec, pin, 0,
				    AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
	pincap = snd_hda_query_pin_caps(codec, pin);
	pincap = (pincap & AC_PINCAP_VREF) >> AC_PINCAP_VREF_SHIFT;
	/* Exception: if the default pin setup is vref50, we give it priority */
	if ((pincap & AC_PINCAP_VREF_80) && oldval != PIN_VREF50)
		return AC_PINCTL_VREF_80;
	else if (pincap & AC_PINCAP_VREF_50)
		return AC_PINCTL_VREF_50;
	else if (pincap & AC_PINCAP_VREF_100)
		return AC_PINCTL_VREF_100;
	else if (pincap & AC_PINCAP_VREF_GRD)
		return AC_PINCTL_VREF_GRD;
	return AC_PINCTL_VREF_HIZ;
}
EXPORT_SYMBOL_HDA(snd_hda_get_default_vref);

int _snd_hda_set_pin_ctl(struct hda_codec *codec, hda_nid_t pin,
int _snd_hda_set_pin_ctl(struct hda_codec *codec, hda_nid_t pin,
			 unsigned int val, bool cached)
			 unsigned int val, bool cached)
{
{
+2 −0
Original line number Original line Diff line number Diff line
@@ -502,6 +502,7 @@ int snd_hda_parse_pin_defcfg(struct hda_codec *codec,
#define PIN_HP			(AC_PINCTL_OUT_EN | AC_PINCTL_HP_EN)
#define PIN_HP			(AC_PINCTL_OUT_EN | AC_PINCTL_HP_EN)
#define PIN_HP_AMP		(AC_PINCTL_HP_EN)
#define PIN_HP_AMP		(AC_PINCTL_HP_EN)


unsigned int snd_hda_get_default_vref(struct hda_codec *codec, hda_nid_t pin);
int _snd_hda_set_pin_ctl(struct hda_codec *codec, hda_nid_t pin,
int _snd_hda_set_pin_ctl(struct hda_codec *codec, hda_nid_t pin,
			 unsigned int val, bool cached);
			 unsigned int val, bool cached);


@@ -517,6 +518,7 @@ int _snd_hda_set_pin_ctl(struct hda_codec *codec, hda_nid_t pin,
 * HP-drive capability, the HP bit is omitted.
 * HP-drive capability, the HP bit is omitted.
 *
 *
 * The function doesn't check the input VREF capability bits, though.
 * The function doesn't check the input VREF capability bits, though.
 * Use snd_hda_get_default_vref() to guess the right value.
 * Also, this function is only for analog pins, not for HDMI pins.
 * Also, this function is only for analog pins, not for HDMI pins.
 */
 */
static inline int
static inline int
+5 −2
Original line number Original line Diff line number Diff line
@@ -3155,6 +3155,7 @@ static void ad1988_auto_init_analog_input(struct hda_codec *codec)
	for (i = 0; i < cfg->num_inputs; i++) {
	for (i = 0; i < cfg->num_inputs; i++) {
		hda_nid_t nid = cfg->inputs[i].pin;
		hda_nid_t nid = cfg->inputs[i].pin;
		int type = cfg->inputs[i].type;
		int type = cfg->inputs[i].type;
		int val;
		switch (nid) {
		switch (nid) {
		case 0x15: /* port-C */
		case 0x15: /* port-C */
			snd_hda_codec_write(codec, 0x33, 0, AC_VERB_SET_CONNECT_SEL, 0x0);
			snd_hda_codec_write(codec, 0x33, 0, AC_VERB_SET_CONNECT_SEL, 0x0);
@@ -3163,8 +3164,10 @@ static void ad1988_auto_init_analog_input(struct hda_codec *codec)
			snd_hda_codec_write(codec, 0x34, 0, AC_VERB_SET_CONNECT_SEL, 0x0);
			snd_hda_codec_write(codec, 0x34, 0, AC_VERB_SET_CONNECT_SEL, 0x0);
			break;
			break;
		}
		}
		snd_hda_set_pin_ctl(codec, nid,
		val = PIN_IN;
				    type == AUTO_PIN_MIC ? PIN_VREF80 : PIN_IN);
		if (type == AUTO_PIN_MIC)
			val |= snd_hda_get_default_vref(codec, nid);
		snd_hda_set_pin_ctl(codec, nid, val);
		if (nid != AD1988_PIN_CD_NID)
		if (nid != AD1988_PIN_CD_NID)
			snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
			snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
					    AMP_OUT_MUTE);
					    AMP_OUT_MUTE);
+2 −1
Original line number Original line Diff line number Diff line
@@ -355,7 +355,8 @@ static void init_output(struct hda_codec *codec, hda_nid_t pin, hda_nid_t dac)
static void init_input(struct hda_codec *codec, hda_nid_t pin, hda_nid_t adc)
static void init_input(struct hda_codec *codec, hda_nid_t pin, hda_nid_t adc)
{
{
	if (pin) {
	if (pin) {
		snd_hda_set_pin_ctl(codec, pin, PIN_VREF80);
		snd_hda_set_pin_ctl(codec, pin, PIN_IN |
				    snd_hda_get_default_vref(codec, pin));
		if (get_wcaps(codec, pin) & AC_WCAP_IN_AMP)
		if (get_wcaps(codec, pin) & AC_WCAP_IN_AMP)
			snd_hda_codec_write(codec, pin, 0,
			snd_hda_codec_write(codec, pin, 0,
					    AC_VERB_SET_AMP_GAIN_MUTE,
					    AC_VERB_SET_AMP_GAIN_MUTE,
+2 −1
Original line number Original line Diff line number Diff line
@@ -253,7 +253,8 @@ static void init_output(struct hda_codec *codec, hda_nid_t pin, hda_nid_t dac)
static void init_input(struct hda_codec *codec, hda_nid_t pin, hda_nid_t adc)
static void init_input(struct hda_codec *codec, hda_nid_t pin, hda_nid_t adc)
{
{
	if (pin) {
	if (pin) {
		snd_hda_set_pin_ctl(codec, pin, PIN_VREF80);
		snd_hda_set_pin_ctl(codec, pin, PIN_IN |
				    snd_hda_get_default_vref(codec, pin));
		if (get_wcaps(codec, pin) & AC_WCAP_IN_AMP)
		if (get_wcaps(codec, pin) & AC_WCAP_IN_AMP)
			snd_hda_codec_write(codec, pin, 0,
			snd_hda_codec_write(codec, pin, 0,
					    AC_VERB_SET_AMP_GAIN_MUTE,
					    AC_VERB_SET_AMP_GAIN_MUTE,
Loading