summaryrefslogtreecommitdiffstats
path: root/sound/pci/hda/patch_via.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/pci/hda/patch_via.c')
-rw-r--r--sound/pci/hda/patch_via.c135
1 files changed, 59 insertions, 76 deletions
diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c
index 430771776915..72a2f60b087c 100644
--- a/sound/pci/hda/patch_via.c
+++ b/sound/pci/hda/patch_via.c
@@ -118,6 +118,8 @@ enum {
};
struct via_spec {
+ struct hda_gen_spec gen;
+
/* codec parameterization */
const struct snd_kcontrol_new *mixers[6];
unsigned int num_mixers;
@@ -246,6 +248,7 @@ static struct via_spec * via_new_spec(struct hda_codec *codec)
/* VT1708BCE & VT1708S are almost same */
if (spec->codec_type == VT1708BCE)
spec->codec_type = VT1708S;
+ snd_hda_gen_init(&spec->gen);
return spec;
}
@@ -299,7 +302,6 @@ static enum VIA_HDA_CODEC get_codec_type(struct hda_codec *codec)
#define VIA_JACK_EVENT 0x20
#define VIA_HP_EVENT 0x01
-#define VIA_GPIO_EVENT 0x02
#define VIA_LINE_EVENT 0x03
enum {
@@ -1628,6 +1630,7 @@ static void via_free(struct hda_codec *codec)
vt1708_stop_hp_work(spec);
kfree(spec->bind_cap_vol);
kfree(spec->bind_cap_sw);
+ snd_hda_gen_free(&spec->gen);
kfree(spec);
}
@@ -1672,7 +1675,8 @@ static void via_hp_automute(struct hda_codec *codec)
struct via_spec *spec = codec->spec;
if (!spec->hp_independent_mode && spec->autocfg.hp_pins[0] &&
- (spec->codec_type != VT1708 || spec->vt1708_jack_detect))
+ (spec->codec_type != VT1708 || spec->vt1708_jack_detect) &&
+ is_jack_detectable(codec, spec->autocfg.hp_pins[0]))
present = snd_hda_jack_detect(codec, spec->autocfg.hp_pins[0]);
if (spec->smart51_enabled)
@@ -1684,69 +1688,6 @@ static void via_hp_automute(struct hda_codec *codec)
via_line_automute(codec, present);
}
-static void via_gpio_control(struct hda_codec *codec)
-{
- unsigned int gpio_data;
- unsigned int vol_counter;
- unsigned int vol;
- unsigned int master_vol;
-
- struct via_spec *spec = codec->spec;
-
- gpio_data = snd_hda_codec_read(codec, codec->afg, 0,
- AC_VERB_GET_GPIO_DATA, 0) & 0x03;
-
- vol_counter = (snd_hda_codec_read(codec, codec->afg, 0,
- 0xF84, 0) & 0x3F0000) >> 16;
-
- vol = vol_counter & 0x1F;
- master_vol = snd_hda_codec_read(codec, 0x1A, 0,
- AC_VERB_GET_AMP_GAIN_MUTE,
- AC_AMP_GET_INPUT);
-
- if (gpio_data == 0x02) {
- /* unmute line out */
- snd_hda_set_pin_ctl(codec, spec->autocfg.line_out_pins[0],
- PIN_OUT);
- if (vol_counter & 0x20) {
- /* decrease volume */
- if (vol > master_vol)
- vol = master_vol;
- snd_hda_codec_amp_stereo(codec, 0x1A, HDA_INPUT,
- 0, HDA_AMP_VOLMASK,
- master_vol-vol);
- } else {
- /* increase volume */
- snd_hda_codec_amp_stereo(codec, 0x1A, HDA_INPUT, 0,
- HDA_AMP_VOLMASK,
- ((master_vol+vol) > 0x2A) ? 0x2A :
- (master_vol+vol));
- }
- } else if (!(gpio_data & 0x02)) {
- /* mute line out */
- snd_hda_set_pin_ctl(codec, spec->autocfg.line_out_pins[0], 0);
- }
-}
-
-/* unsolicited event for jack sensing */
-static void via_unsol_event(struct hda_codec *codec,
- unsigned int res)
-{
- res >>= 26;
- res = snd_hda_jack_get_action(codec, res);
-
- if (res & VIA_JACK_EVENT)
- set_widgets_power_state(codec);
-
- res &= ~VIA_JACK_EVENT;
-
- if (res == VIA_HP_EVENT || res == VIA_LINE_EVENT)
- via_hp_automute(codec);
- else if (res == VIA_GPIO_EVENT)
- via_gpio_control(codec);
- snd_hda_jack_report_sync(codec);
-}
-
#ifdef CONFIG_PM
static int via_suspend(struct hda_codec *codec)
{
@@ -1764,7 +1705,7 @@ static int via_suspend(struct hda_codec *codec)
}
#endif
-#ifdef CONFIG_SND_HDA_POWER_SAVE
+#ifdef CONFIG_PM
static int via_check_power_status(struct hda_codec *codec, hda_nid_t nid)
{
struct via_spec *spec = codec->spec;
@@ -1782,11 +1723,9 @@ static const struct hda_codec_ops via_patch_ops = {
.build_pcms = via_build_pcms,
.init = via_init,
.free = via_free,
- .unsol_event = via_unsol_event,
+ .unsol_event = snd_hda_jack_unsol_event,
#ifdef CONFIG_PM
.suspend = via_suspend,
-#endif
-#ifdef CONFIG_SND_HDA_POWER_SAVE
.check_power_status = via_check_power_status,
#endif
};
@@ -2762,6 +2701,17 @@ static void via_auto_init_dig_in(struct hda_codec *codec)
snd_hda_set_pin_ctl(codec, spec->autocfg.dig_in_pin, PIN_IN);
}
+static void via_jack_output_event(struct hda_codec *codec, struct hda_jack_tbl *tbl)
+{
+ set_widgets_power_state(codec);
+ via_hp_automute(codec);
+}
+
+static void via_jack_powerstate_event(struct hda_codec *codec, struct hda_jack_tbl *tbl)
+{
+ set_widgets_power_state(codec);
+}
+
/* initialize the unsolicited events */
static void via_auto_init_unsol_event(struct hda_codec *codec)
{
@@ -2769,26 +2719,31 @@ static void via_auto_init_unsol_event(struct hda_codec *codec)
struct auto_pin_cfg *cfg = &spec->autocfg;
unsigned int ev;
int i;
+ hda_jack_callback cb;
if (cfg->hp_pins[0] && is_jack_detectable(codec, cfg->hp_pins[0]))
- snd_hda_jack_detect_enable(codec, cfg->hp_pins[0],
- VIA_HP_EVENT | VIA_JACK_EVENT);
+ snd_hda_jack_detect_enable_callback(codec, cfg->hp_pins[0],
+ VIA_HP_EVENT | VIA_JACK_EVENT,
+ via_jack_output_event);
if (cfg->speaker_pins[0])
ev = VIA_LINE_EVENT;
else
ev = 0;
+ cb = ev ? via_jack_output_event : via_jack_powerstate_event;
+
for (i = 0; i < cfg->line_outs; i++) {
if (cfg->line_out_pins[i] &&
is_jack_detectable(codec, cfg->line_out_pins[i]))
- snd_hda_jack_detect_enable(codec, cfg->line_out_pins[i],
- ev | VIA_JACK_EVENT);
+ snd_hda_jack_detect_enable_callback(codec, cfg->line_out_pins[i],
+ ev | VIA_JACK_EVENT, cb);
}
for (i = 0; i < cfg->num_inputs; i++) {
if (is_jack_detectable(codec, cfg->inputs[i].pin))
- snd_hda_jack_detect_enable(codec, cfg->inputs[i].pin,
- VIA_JACK_EVENT);
+ snd_hda_jack_detect_enable_callback(codec, cfg->inputs[i].pin,
+ VIA_JACK_EVENT,
+ via_jack_powerstate_event);
}
}
@@ -2815,7 +2770,6 @@ static int via_init(struct hda_codec *codec)
via_hp_automute(codec);
vt1708_update_hp_work(spec);
- snd_hda_jack_report_sync(codec);
return 0;
}
@@ -3669,6 +3623,32 @@ static void set_widgets_power_state_vt2002P(struct hda_codec *codec)
update_power_state(codec, 0x21, AC_PWRST_D3);
}
+/*
+ * pin fix-up
+ */
+enum {
+ VIA_FIXUP_INTMIC_BOOST,
+};
+
+static void via_fixup_intmic_boost(struct hda_codec *codec,
+ const struct hda_fixup *fix, int action)
+{
+ if (action == HDA_FIXUP_ACT_PRE_PROBE)
+ override_mic_boost(codec, 0x30, 0, 2, 40);
+}
+
+static const struct hda_fixup via_fixups[] = {
+ [VIA_FIXUP_INTMIC_BOOST] = {
+ .type = HDA_FIXUP_FUNC,
+ .v.func = via_fixup_intmic_boost,
+ },
+};
+
+static const struct snd_pci_quirk vt2002p_fixups[] = {
+ SND_PCI_QUIRK(0x1043, 0x8532, "Asus X202E", VIA_FIXUP_INTMIC_BOOST),
+ {}
+};
+
/* patch for vt2002P */
static int patch_vt2002P(struct hda_codec *codec)
{
@@ -3685,6 +3665,9 @@ static int patch_vt2002P(struct hda_codec *codec)
override_mic_boost(codec, 0x29, 0, 3, 40);
add_secret_dac_path(codec);
+ snd_hda_pick_fixup(codec, NULL, vt2002p_fixups, via_fixups);
+ snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
+
/* automatic parse from the BIOS config */
err = via_parse_auto_config(codec);
if (err < 0) {