提交 cdd03ced 编写于 作者: T Takashi Iwai

ALSA: hda - Introduce snd_hda_set_pin_ctl*() helper functions

For setting the pin-control values more safely to match with the
actual pin capability bits, a copule of new helper functions,
snd_hda_set_pin_ctl() and snd_hda_set_pin_ctl_cache(), are
introduced.  These are simple replacement of the codec verb write with
AC_VERB_SET_PIN_WIDGET but do more sanity checks and filter out
superfluous pin-control bits if they don't fit with the corresponding
pin capabilities.

Some codecs are screwed up or ignore the command when such a wrong bit
is set.  These helpers will avoid such secret errors.
Signed-off-by: NTakashi Iwai <tiwai@suse.de>
上级 d3980110
...@@ -4795,6 +4795,32 @@ int snd_hda_multi_out_analog_cleanup(struct hda_codec *codec, ...@@ -4795,6 +4795,32 @@ 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);
int _snd_hda_set_pin_ctl(struct hda_codec *codec, hda_nid_t pin,
unsigned int val, bool cached)
{
if (val) {
unsigned int cap = snd_hda_query_pin_caps(codec, pin);
if (val & AC_PINCTL_OUT_EN) {
if (!(cap & AC_PINCAP_OUT))
val &= ~(AC_PINCTL_OUT_EN | AC_PINCTL_HP_EN);
else if ((val & AC_PINCTL_HP_EN) &&
!(cap & AC_PINCAP_HP_DRV))
val &= ~AC_PINCTL_HP_EN;
}
if (val & AC_PINCTL_IN_EN) {
if (!(cap & AC_PINCAP_IN))
val &= ~(AC_PINCTL_IN_EN | AC_PINCTL_VREFEN);
}
}
if (cached)
return snd_hda_codec_update_cache(codec, pin, 0,
AC_VERB_SET_PIN_WIDGET_CONTROL, val);
else
return snd_hda_codec_write(codec, pin, 0,
AC_VERB_SET_PIN_WIDGET_CONTROL, val);
}
EXPORT_SYMBOL_HDA(_snd_hda_set_pin_ctl);
/* /*
* Helper for automatic pin configuration * Helper for automatic pin configuration
*/ */
......
...@@ -502,6 +502,44 @@ int snd_hda_parse_pin_defcfg(struct hda_codec *codec, ...@@ -502,6 +502,44 @@ 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)
int _snd_hda_set_pin_ctl(struct hda_codec *codec, hda_nid_t pin,
unsigned int val, bool cached);
/**
* _snd_hda_set_pin_ctl - Set a pin-control value safely
* @codec: the codec instance
* @pin: the pin NID to set the control
* @val: the pin-control value (AC_PINCTL_* bits)
*
* This function sets the pin-control value to the given pin, but
* filters out the invalid pin-control bits when the pin has no such
* capabilities. For example, when PIN_HP is passed but the pin has no
* HP-drive capability, the HP bit is omitted.
*
* The function doesn't check the input VREF capability bits, though.
* Also, this function is only for analog pins, not for HDMI pins.
*/
static inline int
snd_hda_set_pin_ctl(struct hda_codec *codec, hda_nid_t pin, unsigned int val)
{
return _snd_hda_set_pin_ctl(codec, pin, val, false);
}
/**
* snd_hda_set_pin_ctl_cache - Set a pin-control value safely
* @codec: the codec instance
* @pin: the pin NID to set the control
* @val: the pin-control value (AC_PINCTL_* bits)
*
* Just like snd_hda_set_pin_ctl() but write to cache as well.
*/
static inline int
snd_hda_set_pin_ctl_cache(struct hda_codec *codec, hda_nid_t pin,
unsigned int val)
{
return _snd_hda_set_pin_ctl(codec, pin, val, true);
}
/* /*
* get widget capabilities * get widget capabilities
*/ */
......
...@@ -1742,9 +1742,7 @@ static int ad1981_hp_master_sw_put(struct snd_kcontrol *kcontrol, ...@@ -1742,9 +1742,7 @@ static int ad1981_hp_master_sw_put(struct snd_kcontrol *kcontrol,
if (! ad198x_eapd_put(kcontrol, ucontrol)) if (! ad198x_eapd_put(kcontrol, ucontrol))
return 0; return 0;
/* change speaker pin appropriately */ /* change speaker pin appropriately */
snd_hda_codec_write(codec, 0x05, 0, snd_hda_set_pin_ctl(codec, 0x05, spec->cur_eapd ? PIN_OUT : 0);
AC_VERB_SET_PIN_WIDGET_CONTROL,
spec->cur_eapd ? PIN_OUT : 0);
/* toggle HP mute appropriately */ /* toggle HP mute appropriately */
snd_hda_codec_amp_stereo(codec, 0x06, HDA_OUTPUT, 0, snd_hda_codec_amp_stereo(codec, 0x06, HDA_OUTPUT, 0,
HDA_AMP_MUTE, HDA_AMP_MUTE,
...@@ -3103,7 +3101,7 @@ static void ad1988_auto_set_output_and_unmute(struct hda_codec *codec, ...@@ -3103,7 +3101,7 @@ static void ad1988_auto_set_output_and_unmute(struct hda_codec *codec,
int dac_idx) int dac_idx)
{ {
/* set as output */ /* set as output */
snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, pin_type); snd_hda_set_pin_ctl(codec, nid, pin_type);
snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE); snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
switch (nid) { switch (nid) {
case 0x11: /* port-A - DAC 03 */ case 0x11: /* port-A - DAC 03 */
...@@ -3165,7 +3163,7 @@ static void ad1988_auto_init_analog_input(struct hda_codec *codec) ...@@ -3165,7 +3163,7 @@ 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_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, snd_hda_set_pin_ctl(codec, nid,
type == AUTO_PIN_MIC ? PIN_VREF80 : PIN_IN); type == AUTO_PIN_MIC ? PIN_VREF80 : PIN_IN);
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,
......
...@@ -341,8 +341,7 @@ static int ca0110_build_pcms(struct hda_codec *codec) ...@@ -341,8 +341,7 @@ static int ca0110_build_pcms(struct hda_codec *codec)
static void init_output(struct hda_codec *codec, hda_nid_t pin, hda_nid_t dac) static void init_output(struct hda_codec *codec, hda_nid_t pin, hda_nid_t dac)
{ {
if (pin) { if (pin) {
snd_hda_codec_write(codec, pin, 0, snd_hda_set_pin_ctl(codec, pin, PIN_HP);
AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP);
if (get_wcaps(codec, pin) & AC_WCAP_OUT_AMP) if (get_wcaps(codec, pin) & AC_WCAP_OUT_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,
...@@ -356,8 +355,7 @@ static void init_output(struct hda_codec *codec, hda_nid_t pin, hda_nid_t dac) ...@@ -356,8 +355,7 @@ 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_codec_write(codec, pin, 0, snd_hda_set_pin_ctl(codec, pin, PIN_VREF80);
AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80);
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,
......
...@@ -239,8 +239,7 @@ enum get_set { ...@@ -239,8 +239,7 @@ enum get_set {
static void init_output(struct hda_codec *codec, hda_nid_t pin, hda_nid_t dac) static void init_output(struct hda_codec *codec, hda_nid_t pin, hda_nid_t dac)
{ {
if (pin) { if (pin) {
snd_hda_codec_write(codec, pin, 0, snd_hda_set_pin_ctl(codec, pin, PIN_HP);
AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP);
if (get_wcaps(codec, pin) & AC_WCAP_OUT_AMP) if (get_wcaps(codec, pin) & AC_WCAP_OUT_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,
...@@ -254,9 +253,7 @@ static void init_output(struct hda_codec *codec, hda_nid_t pin, hda_nid_t dac) ...@@ -254,9 +253,7 @@ 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_codec_write(codec, pin, 0, snd_hda_set_pin_ctl(codec, pin, PIN_VREF80);
AC_VERB_SET_PIN_WIDGET_CONTROL,
PIN_VREF80);
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,
......
...@@ -933,8 +933,7 @@ static void cs_automute(struct hda_codec *codec) ...@@ -933,8 +933,7 @@ static void cs_automute(struct hda_codec *codec)
pin_ctl = 0; pin_ctl = 0;
nid = cfg->speaker_pins[i]; nid = cfg->speaker_pins[i];
snd_hda_codec_write(codec, nid, 0, snd_hda_set_pin_ctl(codec, nid, pin_ctl);
AC_VERB_SET_PIN_WIDGET_CONTROL, pin_ctl);
} }
if (spec->gpio_eapd_hp) { if (spec->gpio_eapd_hp) {
unsigned int gpio = hp_present ? unsigned int gpio = hp_present ?
...@@ -948,16 +947,14 @@ static void cs_automute(struct hda_codec *codec) ...@@ -948,16 +947,14 @@ static void cs_automute(struct hda_codec *codec)
/* mute HPs if spdif jack (SENSE_B) is present */ /* mute HPs if spdif jack (SENSE_B) is present */
for (i = 0; i < cfg->hp_outs; i++) { for (i = 0; i < cfg->hp_outs; i++) {
nid = cfg->hp_pins[i]; nid = cfg->hp_pins[i];
snd_hda_codec_write(codec, nid, 0, snd_hda_set_pin_ctl(codec, nid,
AC_VERB_SET_PIN_WIDGET_CONTROL,
(spdif_present && spec->sense_b) ? 0 : PIN_HP); (spdif_present && spec->sense_b) ? 0 : PIN_HP);
} }
/* SPDIF TX on/off */ /* SPDIF TX on/off */
if (cfg->dig_outs) { if (cfg->dig_outs) {
nid = cfg->dig_out_pins[0]; nid = cfg->dig_out_pins[0];
snd_hda_codec_write(codec, nid, 0, snd_hda_set_pin_ctl(codec, nid,
AC_VERB_SET_PIN_WIDGET_CONTROL,
spdif_present ? PIN_OUT : 0); spdif_present ? PIN_OUT : 0);
} }
...@@ -1024,13 +1021,11 @@ static void init_output(struct hda_codec *codec) ...@@ -1024,13 +1021,11 @@ static void init_output(struct hda_codec *codec)
/* set appropriate pin controls */ /* set appropriate pin controls */
for (i = 0; i < cfg->line_outs; i++) for (i = 0; i < cfg->line_outs; i++)
snd_hda_codec_write(codec, cfg->line_out_pins[i], 0, snd_hda_set_pin_ctl(codec, cfg->line_out_pins[i], PIN_OUT);
AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
/* HP */ /* HP */
for (i = 0; i < cfg->hp_outs; i++) { for (i = 0; i < cfg->hp_outs; i++) {
hda_nid_t nid = cfg->hp_pins[i]; hda_nid_t nid = cfg->hp_pins[i];
snd_hda_codec_write(codec, nid, 0, snd_hda_set_pin_ctl(codec, nid, PIN_HP);
AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP);
if (!cfg->speaker_outs) if (!cfg->speaker_outs)
continue; continue;
if (get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP) { if (get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP) {
...@@ -1041,8 +1036,7 @@ static void init_output(struct hda_codec *codec) ...@@ -1041,8 +1036,7 @@ static void init_output(struct hda_codec *codec)
/* Speaker */ /* Speaker */
for (i = 0; i < cfg->speaker_outs; i++) for (i = 0; i < cfg->speaker_outs; i++)
snd_hda_codec_write(codec, cfg->speaker_pins[i], 0, snd_hda_set_pin_ctl(codec, cfg->speaker_pins[i], PIN_OUT);
AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
/* SPDIF is enabled on presence detect for CS421x */ /* SPDIF is enabled on presence detect for CS421x */
if (spec->hp_detect || spec->spdif_detect) if (spec->hp_detect || spec->spdif_detect)
...@@ -1069,8 +1063,7 @@ static void init_input(struct hda_codec *codec) ...@@ -1069,8 +1063,7 @@ static void init_input(struct hda_codec *codec)
if (caps & AC_PINCAP_VREF_80) if (caps & AC_PINCAP_VREF_80)
ctl = PIN_VREF80; ctl = PIN_VREF80;
} }
snd_hda_codec_write(codec, pin, 0, snd_hda_set_pin_ctl(codec, pin, ctl);
AC_VERB_SET_PIN_WIDGET_CONTROL, ctl);
snd_hda_codec_write(codec, spec->adc_nid[i], 0, snd_hda_codec_write(codec, spec->adc_nid[i], 0,
AC_VERB_SET_AMP_GAIN_MUTE, AC_VERB_SET_AMP_GAIN_MUTE,
AMP_IN_MUTE(spec->adc_idx[i])); AMP_IN_MUTE(spec->adc_idx[i]));
......
...@@ -1602,17 +1602,13 @@ static void cxt5051_update_speaker(struct hda_codec *codec) ...@@ -1602,17 +1602,13 @@ static void cxt5051_update_speaker(struct hda_codec *codec)
unsigned int pinctl; unsigned int pinctl;
/* headphone pin */ /* headphone pin */
pinctl = (spec->hp_present && spec->cur_eapd) ? PIN_HP : 0; pinctl = (spec->hp_present && spec->cur_eapd) ? PIN_HP : 0;
snd_hda_codec_write(codec, 0x16, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, snd_hda_set_pin_ctl(codec, 0x16, pinctl);
pinctl);
/* speaker pin */ /* speaker pin */
pinctl = (!spec->hp_present && spec->cur_eapd) ? PIN_OUT : 0; pinctl = (!spec->hp_present && spec->cur_eapd) ? PIN_OUT : 0;
snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, snd_hda_set_pin_ctl(codec, 0x1a, pinctl);
pinctl);
/* on ideapad there is an additional speaker (subwoofer) to mute */ /* on ideapad there is an additional speaker (subwoofer) to mute */
if (spec->ideapad) if (spec->ideapad)
snd_hda_codec_write(codec, 0x1b, 0, snd_hda_set_pin_ctl(codec, 0x1b, pinctl);
AC_VERB_SET_PIN_WIDGET_CONTROL,
pinctl);
} }
/* turn on/off EAPD (+ mute HP) as a master switch */ /* turn on/off EAPD (+ mute HP) as a master switch */
...@@ -1997,8 +1993,7 @@ static void cxt5066_update_speaker(struct hda_codec *codec) ...@@ -1997,8 +1993,7 @@ static void cxt5066_update_speaker(struct hda_codec *codec)
/* Port A (HP) */ /* Port A (HP) */
pinctl = (hp_port_a_present(spec) && spec->cur_eapd) ? PIN_HP : 0; pinctl = (hp_port_a_present(spec) && spec->cur_eapd) ? PIN_HP : 0;
snd_hda_codec_write(codec, 0x19, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, snd_hda_set_pin_ctl(codec, 0x19, pinctl);
pinctl);
/* Port D (HP/LO) */ /* Port D (HP/LO) */
pinctl = spec->cur_eapd ? spec->port_d_mode : 0; pinctl = spec->cur_eapd ? spec->port_d_mode : 0;
...@@ -2011,13 +2006,11 @@ static void cxt5066_update_speaker(struct hda_codec *codec) ...@@ -2011,13 +2006,11 @@ static void cxt5066_update_speaker(struct hda_codec *codec)
if (!hp_port_d_present(spec)) if (!hp_port_d_present(spec))
pinctl = 0; pinctl = 0;
} }
snd_hda_codec_write(codec, 0x1c, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, snd_hda_set_pin_ctl(codec, 0x1c, pinctl);
pinctl);
/* CLASS_D AMP */ /* CLASS_D AMP */
pinctl = (!spec->hp_present && spec->cur_eapd) ? PIN_OUT : 0; pinctl = (!spec->hp_present && spec->cur_eapd) ? PIN_OUT : 0;
snd_hda_codec_write(codec, 0x1f, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, snd_hda_set_pin_ctl(codec, 0x1f, pinctl);
pinctl);
} }
/* turn on/off EAPD (+ mute HP) as a master switch */ /* turn on/off EAPD (+ mute HP) as a master switch */
...@@ -2048,8 +2041,7 @@ static int cxt5066_set_olpc_dc_bias(struct hda_codec *codec) ...@@ -2048,8 +2041,7 @@ static int cxt5066_set_olpc_dc_bias(struct hda_codec *codec)
/* Even though port F is the DC input, the bias is controlled on port B. /* Even though port F is the DC input, the bias is controlled on port B.
* we also leave that port as an active input (but unselected) in DC mode * we also leave that port as an active input (but unselected) in DC mode
* just in case that is necessary to make the bias setting take effect. */ * just in case that is necessary to make the bias setting take effect. */
return snd_hda_codec_write_cache(codec, 0x1a, 0, return snd_hda_set_pin_ctl_cache(codec, 0x1a,
AC_VERB_SET_PIN_WIDGET_CONTROL,
cxt5066_olpc_dc_bias.items[spec->dc_input_bias].index); cxt5066_olpc_dc_bias.items[spec->dc_input_bias].index);
} }
...@@ -2082,14 +2074,14 @@ static void cxt5066_olpc_select_mic(struct hda_codec *codec) ...@@ -2082,14 +2074,14 @@ static void cxt5066_olpc_select_mic(struct hda_codec *codec)
} }
/* disable DC (port F) */ /* disable DC (port F) */
snd_hda_codec_write(codec, 0x1e, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, 0); snd_hda_set_pin_ctl(codec, 0x1e, 0);
/* external mic, port B */ /* external mic, port B */
snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, snd_hda_set_pin_ctl(codec, 0x1a,
spec->ext_mic_present ? CXT5066_OLPC_EXT_MIC_BIAS : 0); spec->ext_mic_present ? CXT5066_OLPC_EXT_MIC_BIAS : 0);
/* internal mic, port C */ /* internal mic, port C */
snd_hda_codec_write(codec, 0x1b, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, snd_hda_set_pin_ctl(codec, 0x1b,
spec->ext_mic_present ? 0 : PIN_VREF80); spec->ext_mic_present ? 0 : PIN_VREF80);
} }
...@@ -3358,9 +3350,7 @@ static void do_automute(struct hda_codec *codec, int num_pins, ...@@ -3358,9 +3350,7 @@ static void do_automute(struct hda_codec *codec, int num_pins,
struct conexant_spec *spec = codec->spec; struct conexant_spec *spec = codec->spec;
int i; int i;
for (i = 0; i < num_pins; i++) for (i = 0; i < num_pins; i++)
snd_hda_codec_write(codec, pins[i], 0, snd_hda_set_pin_ctl(codec, pins[i], on ? PIN_OUT : 0);
AC_VERB_SET_PIN_WIDGET_CONTROL,
on ? PIN_OUT : 0);
if (spec->pin_eapd_ctrls) if (spec->pin_eapd_ctrls)
cx_auto_turn_eapd(codec, num_pins, pins, on); cx_auto_turn_eapd(codec, num_pins, pins, on);
} }
...@@ -3977,8 +3967,7 @@ static void cx_auto_init_output(struct hda_codec *codec) ...@@ -3977,8 +3967,7 @@ static void cx_auto_init_output(struct hda_codec *codec)
if (snd_hda_query_pin_caps(codec, cfg->hp_pins[i]) & if (snd_hda_query_pin_caps(codec, cfg->hp_pins[i]) &
AC_PINCAP_HP_DRV) AC_PINCAP_HP_DRV)
val |= AC_PINCTL_HP_EN; val |= AC_PINCTL_HP_EN;
snd_hda_codec_write(codec, cfg->hp_pins[i], 0, snd_hda_set_pin_ctl(codec, cfg->hp_pins[i], val);
AC_VERB_SET_PIN_WIDGET_CONTROL, val);
} }
mute_outputs(codec, cfg->hp_outs, cfg->hp_pins); mute_outputs(codec, cfg->hp_outs, cfg->hp_pins);
mute_outputs(codec, cfg->line_outs, cfg->line_out_pins); mute_outputs(codec, cfg->line_outs, cfg->line_out_pins);
...@@ -4036,8 +4025,7 @@ static void cx_auto_init_input(struct hda_codec *codec) ...@@ -4036,8 +4025,7 @@ static void cx_auto_init_input(struct hda_codec *codec)
type = PIN_VREF80; type = PIN_VREF80;
else else
type = PIN_IN; type = PIN_IN;
snd_hda_codec_write(codec, cfg->inputs[i].pin, 0, snd_hda_set_pin_ctl(codec, cfg->inputs[i].pin, type);
AC_VERB_SET_PIN_WIDGET_CONTROL, type);
} }
if (spec->auto_mic) { if (spec->auto_mic) {
...@@ -4064,11 +4052,9 @@ static void cx_auto_init_digital(struct hda_codec *codec) ...@@ -4064,11 +4052,9 @@ static void cx_auto_init_digital(struct hda_codec *codec)
struct auto_pin_cfg *cfg = &spec->autocfg; struct auto_pin_cfg *cfg = &spec->autocfg;
if (spec->multiout.dig_out_nid) if (spec->multiout.dig_out_nid)
snd_hda_codec_write(codec, cfg->dig_out_pins[0], 0, snd_hda_set_pin_ctl(codec, cfg->dig_out_pins[0], PIN_OUT);
AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
if (spec->dig_in_nid) if (spec->dig_in_nid)
snd_hda_codec_write(codec, cfg->dig_in_pin, 0, snd_hda_set_pin_ctl(codec, cfg->dig_in_pin, PIN_IN);
AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN);
} }
static int cx_auto_init(struct hda_codec *codec) static int cx_auto_init(struct hda_codec *codec)
......
...@@ -319,13 +319,16 @@ static int alc_mux_select(struct hda_codec *codec, unsigned int adc_idx, ...@@ -319,13 +319,16 @@ static int alc_mux_select(struct hda_codec *codec, unsigned int adc_idx,
/* for shared I/O, change the pin-control accordingly */ /* for shared I/O, change the pin-control accordingly */
if (spec->shared_mic_hp) { if (spec->shared_mic_hp) {
unsigned int val;
hda_nid_t pin = spec->autocfg.inputs[1].pin;
/* NOTE: this assumes that there are only two inputs, the /* NOTE: this assumes that there are only two inputs, the
* first is the real internal mic and the second is HP jack. * first is the real internal mic and the second is HP jack.
*/ */
snd_hda_codec_write(codec, spec->autocfg.inputs[1].pin, 0, if (spec->cur_mux[adc_idx])
AC_VERB_SET_PIN_WIDGET_CONTROL, val = PIN_VREF80;
spec->cur_mux[adc_idx] ? else
PIN_VREF80 : PIN_HP); val = PIN_HP;
snd_hda_set_pin_ctl(codec, pin, val);
spec->automute_speaker = !spec->cur_mux[adc_idx]; spec->automute_speaker = !spec->cur_mux[adc_idx];
call_update_outputs(codec); call_update_outputs(codec);
} }
...@@ -394,7 +397,7 @@ static void alc_set_input_pin(struct hda_codec *codec, hda_nid_t nid, ...@@ -394,7 +397,7 @@ static void alc_set_input_pin(struct hda_codec *codec, hda_nid_t nid,
else if (pincap & AC_PINCAP_VREF_GRD) else if (pincap & AC_PINCAP_VREF_GRD)
val = PIN_VREFGRD; val = PIN_VREFGRD;
} }
snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, val); snd_hda_set_pin_ctl(codec, nid, val);
} }
/* /*
...@@ -517,9 +520,7 @@ static void do_automute(struct hda_codec *codec, int num_pins, hda_nid_t *pins, ...@@ -517,9 +520,7 @@ static void do_automute(struct hda_codec *codec, int num_pins, hda_nid_t *pins,
} else } else
val = 0; val = 0;
val |= pin_bits; val |= pin_bits;
snd_hda_codec_write(codec, nid, 0, snd_hda_set_pin_ctl(codec, nid, val);
AC_VERB_SET_PIN_WIDGET_CONTROL,
val);
break; break;
case ALC_AUTOMUTE_AMP: case ALC_AUTOMUTE_AMP:
snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0, snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
...@@ -1621,8 +1622,7 @@ static void alc_auto_init_digital(struct hda_codec *codec) ...@@ -1621,8 +1622,7 @@ static void alc_auto_init_digital(struct hda_codec *codec)
pin = spec->autocfg.dig_out_pins[i]; pin = spec->autocfg.dig_out_pins[i];
if (!pin) if (!pin)
continue; continue;
snd_hda_codec_write(codec, pin, 0, snd_hda_set_pin_ctl(codec, pin, PIN_OUT);
AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
if (!i) if (!i)
dac = spec->multiout.dig_out_nid; dac = spec->multiout.dig_out_nid;
else else
...@@ -1635,9 +1635,7 @@ static void alc_auto_init_digital(struct hda_codec *codec) ...@@ -1635,9 +1635,7 @@ static void alc_auto_init_digital(struct hda_codec *codec)
} }
pin = spec->autocfg.dig_in_pin; pin = spec->autocfg.dig_in_pin;
if (pin) if (pin)
snd_hda_codec_write(codec, pin, 0, snd_hda_set_pin_ctl(codec, pin, PIN_IN);
AC_VERB_SET_PIN_WIDGET_CONTROL,
PIN_IN);
} }
/* parse digital I/Os and set up NIDs in BIOS auto-parse mode */ /* parse digital I/Os and set up NIDs in BIOS auto-parse mode */
...@@ -2856,8 +2854,7 @@ static int alc_auto_create_shared_input(struct hda_codec *codec) ...@@ -2856,8 +2854,7 @@ static int alc_auto_create_shared_input(struct hda_codec *codec)
static void alc_set_pin_output(struct hda_codec *codec, hda_nid_t nid, static void alc_set_pin_output(struct hda_codec *codec, hda_nid_t nid,
unsigned int pin_type) unsigned int pin_type)
{ {
snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, snd_hda_set_pin_ctl(codec, nid, pin_type);
pin_type);
/* unmute pin */ /* unmute pin */
if (nid_has_mute(codec, nid, HDA_OUTPUT)) if (nid_has_mute(codec, nid, HDA_OUTPUT))
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,
...@@ -3998,9 +3995,7 @@ static int alc_set_multi_io(struct hda_codec *codec, int idx, bool output) ...@@ -3998,9 +3995,7 @@ static int alc_set_multi_io(struct hda_codec *codec, int idx, bool output)
snd_hda_codec_read(codec, nid, 0, snd_hda_codec_read(codec, nid, 0,
AC_VERB_GET_PIN_WIDGET_CONTROL, 0); AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
if (output) { if (output) {
snd_hda_codec_update_cache(codec, nid, 0, snd_hda_set_pin_ctl_cache(codec, nid, PIN_OUT);
AC_VERB_SET_PIN_WIDGET_CONTROL,
PIN_OUT);
if (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP) if (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP)
snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0, snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
HDA_AMP_MUTE, 0); HDA_AMP_MUTE, 0);
...@@ -4009,9 +4004,8 @@ static int alc_set_multi_io(struct hda_codec *codec, int idx, bool output) ...@@ -4009,9 +4004,8 @@ static int alc_set_multi_io(struct hda_codec *codec, int idx, bool output)
if (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP) if (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP)
snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0, snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
HDA_AMP_MUTE, HDA_AMP_MUTE); HDA_AMP_MUTE, HDA_AMP_MUTE);
snd_hda_codec_update_cache(codec, nid, 0, snd_hda_set_pin_ctl_cache(codec, nid,
AC_VERB_SET_PIN_WIDGET_CONTROL, spec->multi_io[idx].ctl_in);
spec->multi_io[idx].ctl_in);
} }
return 0; return 0;
} }
...@@ -5171,8 +5165,7 @@ static void alc889_fixup_mbp_vref(struct hda_codec *codec, ...@@ -5171,8 +5165,7 @@ static void alc889_fixup_mbp_vref(struct hda_codec *codec,
val = snd_hda_codec_read(codec, nids[i], 0, val = snd_hda_codec_read(codec, nids[i], 0,
AC_VERB_GET_PIN_WIDGET_CONTROL, 0); AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
val |= AC_PINCTL_VREF_80; val |= AC_PINCTL_VREF_80;
snd_hda_codec_write(codec, nids[i], 0, snd_hda_set_pin_ctl(codec, nids[i], val);
AC_VERB_SET_PIN_WIDGET_CONTROL, val);
spec->keep_vref_in_automute = 1; spec->keep_vref_in_automute = 1;
break; break;
} }
...@@ -5193,8 +5186,7 @@ static void alc889_fixup_imac91_vref(struct hda_codec *codec, ...@@ -5193,8 +5186,7 @@ static void alc889_fixup_imac91_vref(struct hda_codec *codec,
val = snd_hda_codec_read(codec, nids[i], 0, val = snd_hda_codec_read(codec, nids[i], 0,
AC_VERB_GET_PIN_WIDGET_CONTROL, 0); AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
val |= AC_PINCTL_VREF_50; val |= AC_PINCTL_VREF_50;
snd_hda_codec_write(codec, nids[i], 0, snd_hda_set_pin_ctl(codec, nids[i], val);
AC_VERB_SET_PIN_WIDGET_CONTROL, val);
} }
spec->keep_vref_in_automute = 1; spec->keep_vref_in_automute = 1;
} }
...@@ -5943,9 +5935,7 @@ static void alc269_fixup_mic2_mute_hook(void *private_data, int enabled) ...@@ -5943,9 +5935,7 @@ static void alc269_fixup_mic2_mute_hook(void *private_data, int enabled)
{ {
struct hda_codec *codec = private_data; struct hda_codec *codec = private_data;
unsigned int pinval = enabled ? 0x20 : 0x24; unsigned int pinval = enabled ? 0x20 : 0x24;
snd_hda_codec_update_cache(codec, 0x19, 0, snd_hda_set_pin_ctl_cache(codec, 0x19, pinval);
AC_VERB_SET_PIN_WIDGET_CONTROL,
pinval);
} }
static void alc269_fixup_mic2_mute(struct hda_codec *codec, static void alc269_fixup_mic2_mute(struct hda_codec *codec,
...@@ -6342,8 +6332,7 @@ static void alc861_fixup_asus_amp_vref_0f(struct hda_codec *codec, ...@@ -6342,8 +6332,7 @@ static void alc861_fixup_asus_amp_vref_0f(struct hda_codec *codec,
if (!(val & (AC_PINCTL_IN_EN | AC_PINCTL_OUT_EN))) if (!(val & (AC_PINCTL_IN_EN | AC_PINCTL_OUT_EN)))
val |= AC_PINCTL_IN_EN; val |= AC_PINCTL_IN_EN;
val |= AC_PINCTL_VREF_50; val |= AC_PINCTL_VREF_50;
snd_hda_codec_write(codec, 0x0f, 0, snd_hda_set_pin_ctl(codec, 0x0f, val);
AC_VERB_SET_PIN_WIDGET_CONTROL, val);
spec->keep_vref_in_automute = 1; spec->keep_vref_in_automute = 1;
} }
......
...@@ -681,8 +681,7 @@ static int stac_vrefout_set(struct hda_codec *codec, ...@@ -681,8 +681,7 @@ static int stac_vrefout_set(struct hda_codec *codec,
pinctl &= ~AC_PINCTL_VREFEN; pinctl &= ~AC_PINCTL_VREFEN;
pinctl |= (new_vref & AC_PINCTL_VREFEN); pinctl |= (new_vref & AC_PINCTL_VREFEN);
error = snd_hda_codec_write_cache(codec, nid, 0, error = snd_hda_set_pin_ctl_cache(codec, nid, pinctl);
AC_VERB_SET_PIN_WIDGET_CONTROL, pinctl);
if (error < 0) if (error < 0)
return error; return error;
...@@ -706,8 +705,7 @@ static unsigned int stac92xx_vref_set(struct hda_codec *codec, ...@@ -706,8 +705,7 @@ static unsigned int stac92xx_vref_set(struct hda_codec *codec,
else else
pincfg |= AC_PINCTL_IN_EN; pincfg |= AC_PINCTL_IN_EN;
error = snd_hda_codec_write_cache(codec, nid, 0, error = snd_hda_set_pin_ctl_cache(codec, nid, pincfg);
AC_VERB_SET_PIN_WIDGET_CONTROL, pincfg);
if (error < 0) if (error < 0)
return error; return error;
else else
...@@ -2524,8 +2522,7 @@ static unsigned int stac92xx_get_default_vref(struct hda_codec *codec, ...@@ -2524,8 +2522,7 @@ static unsigned int stac92xx_get_default_vref(struct hda_codec *codec,
static void stac92xx_auto_set_pinctl(struct hda_codec *codec, hda_nid_t nid, int pin_type) static void stac92xx_auto_set_pinctl(struct hda_codec *codec, hda_nid_t nid, int pin_type)
{ {
snd_hda_codec_write_cache(codec, nid, 0, snd_hda_set_pin_ctl_cache(codec, nid, pin_type);
AC_VERB_SET_PIN_WIDGET_CONTROL, pin_type);
} }
#define stac92xx_hp_switch_info snd_ctl_boolean_mono_info #define stac92xx_hp_switch_info snd_ctl_boolean_mono_info
...@@ -4460,8 +4457,7 @@ static void stac92xx_shutup_pins(struct hda_codec *codec) ...@@ -4460,8 +4457,7 @@ static void stac92xx_shutup_pins(struct hda_codec *codec)
struct hda_pincfg *pin = snd_array_elem(&codec->init_pins, i); struct hda_pincfg *pin = snd_array_elem(&codec->init_pins, i);
def_conf = snd_hda_codec_get_pincfg(codec, pin->nid); def_conf = snd_hda_codec_get_pincfg(codec, pin->nid);
if (get_defcfg_connect(def_conf) != AC_JACK_PORT_NONE) if (get_defcfg_connect(def_conf) != AC_JACK_PORT_NONE)
snd_hda_codec_write(codec, pin->nid, 0, snd_hda_set_pin_ctl(codec, pin->nid, 0);
AC_VERB_SET_PIN_WIDGET_CONTROL, 0);
} }
} }
...@@ -4517,9 +4513,7 @@ static void stac92xx_set_pinctl(struct hda_codec *codec, hda_nid_t nid, ...@@ -4517,9 +4513,7 @@ static void stac92xx_set_pinctl(struct hda_codec *codec, hda_nid_t nid,
pin_ctl |= flag; pin_ctl |= flag;
if (old_ctl != pin_ctl) if (old_ctl != pin_ctl)
snd_hda_codec_write_cache(codec, nid, 0, snd_hda_set_pin_ctl_cache(codec, nid, pin_ctl);
AC_VERB_SET_PIN_WIDGET_CONTROL,
pin_ctl);
} }
static void stac92xx_reset_pinctl(struct hda_codec *codec, hda_nid_t nid, static void stac92xx_reset_pinctl(struct hda_codec *codec, hda_nid_t nid,
...@@ -4528,9 +4522,7 @@ static void stac92xx_reset_pinctl(struct hda_codec *codec, hda_nid_t nid, ...@@ -4528,9 +4522,7 @@ static void stac92xx_reset_pinctl(struct hda_codec *codec, hda_nid_t nid,
unsigned int pin_ctl = snd_hda_codec_read(codec, nid, unsigned int pin_ctl = snd_hda_codec_read(codec, nid,
0, AC_VERB_GET_PIN_WIDGET_CONTROL, 0x00); 0, AC_VERB_GET_PIN_WIDGET_CONTROL, 0x00);
if (pin_ctl & flag) if (pin_ctl & flag)
snd_hda_codec_write_cache(codec, nid, 0, snd_hda_set_pin_ctl_cache(codec, nid, pin_ctl & ~flag);
AC_VERB_SET_PIN_WIDGET_CONTROL,
pin_ctl & ~flag);
} }
static inline int get_pin_presence(struct hda_codec *codec, hda_nid_t nid) static inline int get_pin_presence(struct hda_codec *codec, hda_nid_t nid)
......
...@@ -532,8 +532,7 @@ static void init_output_pin(struct hda_codec *codec, hda_nid_t pin, ...@@ -532,8 +532,7 @@ static void init_output_pin(struct hda_codec *codec, hda_nid_t pin,
{ {
if (!pin) if (!pin)
return; return;
snd_hda_codec_write(codec, pin, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, snd_hda_set_pin_ctl(codec, pin, pin_type);
pin_type);
if (snd_hda_query_pin_caps(codec, pin) & AC_PINCAP_EAPD) if (snd_hda_query_pin_caps(codec, pin) & AC_PINCAP_EAPD)
snd_hda_codec_write(codec, pin, 0, snd_hda_codec_write(codec, pin, 0,
AC_VERB_SET_EAPD_BTLENABLE, 0x02); AC_VERB_SET_EAPD_BTLENABLE, 0x02);
...@@ -666,8 +665,7 @@ static void via_auto_init_analog_input(struct hda_codec *codec) ...@@ -666,8 +665,7 @@ static void via_auto_init_analog_input(struct hda_codec *codec)
ctl = PIN_VREF50; ctl = PIN_VREF50;
else else
ctl = PIN_IN; ctl = PIN_IN;
snd_hda_codec_write(codec, nid, 0, snd_hda_set_pin_ctl(codec, nid, ctl);
AC_VERB_SET_PIN_WIDGET_CONTROL, ctl);
} }
/* init input-src */ /* init input-src */
...@@ -1006,9 +1004,7 @@ static int via_smart51_put(struct snd_kcontrol *kcontrol, ...@@ -1006,9 +1004,7 @@ static int via_smart51_put(struct snd_kcontrol *kcontrol,
AC_VERB_GET_PIN_WIDGET_CONTROL, 0); AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
parm &= ~(AC_PINCTL_IN_EN | AC_PINCTL_OUT_EN); parm &= ~(AC_PINCTL_IN_EN | AC_PINCTL_OUT_EN);
parm |= out_in; parm |= out_in;
snd_hda_codec_write(codec, nid, 0, snd_hda_set_pin_ctl(codec, nid, parm);
AC_VERB_SET_PIN_WIDGET_CONTROL,
parm);
if (out_in == AC_PINCTL_OUT_EN) { if (out_in == AC_PINCTL_OUT_EN) {
mute_aa_path(codec, 1); mute_aa_path(codec, 1);
notify_aa_path_ctls(codec); notify_aa_path_ctls(codec);
...@@ -1647,8 +1643,7 @@ static void toggle_output_mutes(struct hda_codec *codec, int num_pins, ...@@ -1647,8 +1643,7 @@ static void toggle_output_mutes(struct hda_codec *codec, int num_pins,
parm &= ~AC_PINCTL_OUT_EN; parm &= ~AC_PINCTL_OUT_EN;
else else
parm |= AC_PINCTL_OUT_EN; parm |= AC_PINCTL_OUT_EN;
snd_hda_codec_write(codec, pins[i], 0, snd_hda_set_pin_ctl(codec, pins[i], parm);
AC_VERB_SET_PIN_WIDGET_CONTROL, parm);
} }
} }
...@@ -1709,8 +1704,7 @@ static void via_gpio_control(struct hda_codec *codec) ...@@ -1709,8 +1704,7 @@ static void via_gpio_control(struct hda_codec *codec)
if (gpio_data == 0x02) { if (gpio_data == 0x02) {
/* unmute line out */ /* unmute line out */
snd_hda_codec_write(codec, spec->autocfg.line_out_pins[0], 0, snd_hda_set_pin_ctl(codec, spec->autocfg.line_out_pins[0],
AC_VERB_SET_PIN_WIDGET_CONTROL,
PIN_OUT); PIN_OUT);
if (vol_counter & 0x20) { if (vol_counter & 0x20) {
/* decrease volume */ /* decrease volume */
...@@ -1728,9 +1722,7 @@ static void via_gpio_control(struct hda_codec *codec) ...@@ -1728,9 +1722,7 @@ static void via_gpio_control(struct hda_codec *codec)
} }
} else if (!(gpio_data & 0x02)) { } else if (!(gpio_data & 0x02)) {
/* mute line out */ /* mute line out */
snd_hda_codec_write(codec, spec->autocfg.line_out_pins[0], 0, snd_hda_set_pin_ctl(codec, spec->autocfg.line_out_pins[0], 0);
AC_VERB_SET_PIN_WIDGET_CONTROL,
0);
} }
} }
...@@ -2757,8 +2749,7 @@ static void via_auto_init_dig_in(struct hda_codec *codec) ...@@ -2757,8 +2749,7 @@ static void via_auto_init_dig_in(struct hda_codec *codec)
struct via_spec *spec = codec->spec; struct via_spec *spec = codec->spec;
if (!spec->dig_in_nid) if (!spec->dig_in_nid)
return; return;
snd_hda_codec_write(codec, spec->autocfg.dig_in_pin, 0, snd_hda_set_pin_ctl(codec, spec->autocfg.dig_in_pin, PIN_IN);
AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN);
} }
/* initialize the unsolicited events */ /* initialize the unsolicited events */
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册