diff options
author | Takashi Iwai <tiwai@suse.de> | 2012-04-20 06:34:50 -0400 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2012-04-20 06:38:48 -0400 |
commit | cdd03cedc5b55da017fcdeff7d47cac2639cded8 (patch) | |
tree | b0b8b8360eb22f79b81ded6ef9981639be15010d /sound/pci/hda/patch_conexant.c | |
parent | d39801105722c9aef9eae180656190c399c576a9 (diff) |
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: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci/hda/patch_conexant.c')
-rw-r--r-- | sound/pci/hda/patch_conexant.c | 44 |
1 files changed, 15 insertions, 29 deletions
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index 6e04c2bf06de..afa510f0b993 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c | |||
@@ -1602,17 +1602,13 @@ static void cxt5051_update_speaker(struct hda_codec *codec) | |||
1602 | unsigned int pinctl; | 1602 | unsigned int pinctl; |
1603 | /* headphone pin */ | 1603 | /* headphone pin */ |
1604 | pinctl = (spec->hp_present && spec->cur_eapd) ? PIN_HP : 0; | 1604 | pinctl = (spec->hp_present && spec->cur_eapd) ? PIN_HP : 0; |
1605 | snd_hda_codec_write(codec, 0x16, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, | 1605 | snd_hda_set_pin_ctl(codec, 0x16, pinctl); |
1606 | pinctl); | ||
1607 | /* speaker pin */ | 1606 | /* speaker pin */ |
1608 | pinctl = (!spec->hp_present && spec->cur_eapd) ? PIN_OUT : 0; | 1607 | pinctl = (!spec->hp_present && spec->cur_eapd) ? PIN_OUT : 0; |
1609 | snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, | 1608 | snd_hda_set_pin_ctl(codec, 0x1a, pinctl); |
1610 | pinctl); | ||
1611 | /* on ideapad there is an additional speaker (subwoofer) to mute */ | 1609 | /* on ideapad there is an additional speaker (subwoofer) to mute */ |
1612 | if (spec->ideapad) | 1610 | if (spec->ideapad) |
1613 | snd_hda_codec_write(codec, 0x1b, 0, | 1611 | snd_hda_set_pin_ctl(codec, 0x1b, pinctl); |
1614 | AC_VERB_SET_PIN_WIDGET_CONTROL, | ||
1615 | pinctl); | ||
1616 | } | 1612 | } |
1617 | 1613 | ||
1618 | /* turn on/off EAPD (+ mute HP) as a master switch */ | 1614 | /* turn on/off EAPD (+ mute HP) as a master switch */ |
@@ -1997,8 +1993,7 @@ static void cxt5066_update_speaker(struct hda_codec *codec) | |||
1997 | 1993 | ||
1998 | /* Port A (HP) */ | 1994 | /* Port A (HP) */ |
1999 | pinctl = (hp_port_a_present(spec) && spec->cur_eapd) ? PIN_HP : 0; | 1995 | pinctl = (hp_port_a_present(spec) && spec->cur_eapd) ? PIN_HP : 0; |
2000 | snd_hda_codec_write(codec, 0x19, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, | 1996 | snd_hda_set_pin_ctl(codec, 0x19, pinctl); |
2001 | pinctl); | ||
2002 | 1997 | ||
2003 | /* Port D (HP/LO) */ | 1998 | /* Port D (HP/LO) */ |
2004 | pinctl = spec->cur_eapd ? spec->port_d_mode : 0; | 1999 | pinctl = spec->cur_eapd ? spec->port_d_mode : 0; |
@@ -2011,13 +2006,11 @@ static void cxt5066_update_speaker(struct hda_codec *codec) | |||
2011 | if (!hp_port_d_present(spec)) | 2006 | if (!hp_port_d_present(spec)) |
2012 | pinctl = 0; | 2007 | pinctl = 0; |
2013 | } | 2008 | } |
2014 | snd_hda_codec_write(codec, 0x1c, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, | 2009 | snd_hda_set_pin_ctl(codec, 0x1c, pinctl); |
2015 | pinctl); | ||
2016 | 2010 | ||
2017 | /* CLASS_D AMP */ | 2011 | /* CLASS_D AMP */ |
2018 | pinctl = (!spec->hp_present && spec->cur_eapd) ? PIN_OUT : 0; | 2012 | pinctl = (!spec->hp_present && spec->cur_eapd) ? PIN_OUT : 0; |
2019 | snd_hda_codec_write(codec, 0x1f, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, | 2013 | snd_hda_set_pin_ctl(codec, 0x1f, pinctl); |
2020 | pinctl); | ||
2021 | } | 2014 | } |
2022 | 2015 | ||
2023 | /* turn on/off EAPD (+ mute HP) as a master switch */ | 2016 | /* 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 | /* Even though port F is the DC input, the bias is controlled on port B. | 2041 | /* Even though port F is the DC input, the bias is controlled on port B. |
2049 | * we also leave that port as an active input (but unselected) in DC mode | 2042 | * we also leave that port as an active input (but unselected) in DC mode |
2050 | * just in case that is necessary to make the bias setting take effect. */ | 2043 | * just in case that is necessary to make the bias setting take effect. */ |
2051 | return snd_hda_codec_write_cache(codec, 0x1a, 0, | 2044 | return snd_hda_set_pin_ctl_cache(codec, 0x1a, |
2052 | AC_VERB_SET_PIN_WIDGET_CONTROL, | ||
2053 | cxt5066_olpc_dc_bias.items[spec->dc_input_bias].index); | 2045 | cxt5066_olpc_dc_bias.items[spec->dc_input_bias].index); |
2054 | } | 2046 | } |
2055 | 2047 | ||
@@ -2082,14 +2074,14 @@ static void cxt5066_olpc_select_mic(struct hda_codec *codec) | |||
2082 | } | 2074 | } |
2083 | 2075 | ||
2084 | /* disable DC (port F) */ | 2076 | /* disable DC (port F) */ |
2085 | snd_hda_codec_write(codec, 0x1e, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, 0); | 2077 | snd_hda_set_pin_ctl(codec, 0x1e, 0); |
2086 | 2078 | ||
2087 | /* external mic, port B */ | 2079 | /* external mic, port B */ |
2088 | snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, | 2080 | snd_hda_set_pin_ctl(codec, 0x1a, |
2089 | spec->ext_mic_present ? CXT5066_OLPC_EXT_MIC_BIAS : 0); | 2081 | spec->ext_mic_present ? CXT5066_OLPC_EXT_MIC_BIAS : 0); |
2090 | 2082 | ||
2091 | /* internal mic, port C */ | 2083 | /* internal mic, port C */ |
2092 | snd_hda_codec_write(codec, 0x1b, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, | 2084 | snd_hda_set_pin_ctl(codec, 0x1b, |
2093 | spec->ext_mic_present ? 0 : PIN_VREF80); | 2085 | spec->ext_mic_present ? 0 : PIN_VREF80); |
2094 | } | 2086 | } |
2095 | 2087 | ||
@@ -3358,9 +3350,7 @@ static void do_automute(struct hda_codec *codec, int num_pins, | |||
3358 | struct conexant_spec *spec = codec->spec; | 3350 | struct conexant_spec *spec = codec->spec; |
3359 | int i; | 3351 | int i; |
3360 | for (i = 0; i < num_pins; i++) | 3352 | for (i = 0; i < num_pins; i++) |
3361 | snd_hda_codec_write(codec, pins[i], 0, | 3353 | snd_hda_set_pin_ctl(codec, pins[i], on ? PIN_OUT : 0); |
3362 | AC_VERB_SET_PIN_WIDGET_CONTROL, | ||
3363 | on ? PIN_OUT : 0); | ||
3364 | if (spec->pin_eapd_ctrls) | 3354 | if (spec->pin_eapd_ctrls) |
3365 | cx_auto_turn_eapd(codec, num_pins, pins, on); | 3355 | cx_auto_turn_eapd(codec, num_pins, pins, on); |
3366 | } | 3356 | } |
@@ -3977,8 +3967,7 @@ static void cx_auto_init_output(struct hda_codec *codec) | |||
3977 | if (snd_hda_query_pin_caps(codec, cfg->hp_pins[i]) & | 3967 | if (snd_hda_query_pin_caps(codec, cfg->hp_pins[i]) & |
3978 | AC_PINCAP_HP_DRV) | 3968 | AC_PINCAP_HP_DRV) |
3979 | val |= AC_PINCTL_HP_EN; | 3969 | val |= AC_PINCTL_HP_EN; |
3980 | snd_hda_codec_write(codec, cfg->hp_pins[i], 0, | 3970 | snd_hda_set_pin_ctl(codec, cfg->hp_pins[i], val); |
3981 | AC_VERB_SET_PIN_WIDGET_CONTROL, val); | ||
3982 | } | 3971 | } |
3983 | mute_outputs(codec, cfg->hp_outs, cfg->hp_pins); | 3972 | mute_outputs(codec, cfg->hp_outs, cfg->hp_pins); |
3984 | mute_outputs(codec, cfg->line_outs, cfg->line_out_pins); | 3973 | 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 | type = PIN_VREF80; | 4025 | type = PIN_VREF80; |
4037 | else | 4026 | else |
4038 | type = PIN_IN; | 4027 | type = PIN_IN; |
4039 | snd_hda_codec_write(codec, cfg->inputs[i].pin, 0, | 4028 | snd_hda_set_pin_ctl(codec, cfg->inputs[i].pin, type); |
4040 | AC_VERB_SET_PIN_WIDGET_CONTROL, type); | ||
4041 | } | 4029 | } |
4042 | 4030 | ||
4043 | if (spec->auto_mic) { | 4031 | if (spec->auto_mic) { |
@@ -4064,11 +4052,9 @@ static void cx_auto_init_digital(struct hda_codec *codec) | |||
4064 | struct auto_pin_cfg *cfg = &spec->autocfg; | 4052 | struct auto_pin_cfg *cfg = &spec->autocfg; |
4065 | 4053 | ||
4066 | if (spec->multiout.dig_out_nid) | 4054 | if (spec->multiout.dig_out_nid) |
4067 | snd_hda_codec_write(codec, cfg->dig_out_pins[0], 0, | 4055 | snd_hda_set_pin_ctl(codec, cfg->dig_out_pins[0], PIN_OUT); |
4068 | AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT); | ||
4069 | if (spec->dig_in_nid) | 4056 | if (spec->dig_in_nid) |
4070 | snd_hda_codec_write(codec, cfg->dig_in_pin, 0, | 4057 | snd_hda_set_pin_ctl(codec, cfg->dig_in_pin, PIN_IN); |
4071 | AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN); | ||
4072 | } | 4058 | } |
4073 | 4059 | ||
4074 | static int cx_auto_init(struct hda_codec *codec) | 4060 | static int cx_auto_init(struct hda_codec *codec) |