summaryrefslogtreecommitdiffstats
path: root/sound/pci/hda/patch_analog.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/pci/hda/patch_analog.c')
-rw-r--r--sound/pci/hda/patch_analog.c79
1 files changed, 77 insertions, 2 deletions
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c
index e75b5e5..cecd3c1 100644
--- a/sound/pci/hda/patch_analog.c
+++ b/sound/pci/hda/patch_analog.c
@@ -244,8 +244,7 @@ static int ad198x_build_controls(struct hda_codec *codec)
if (!kctl)
kctl = snd_hda_find_mixer_ctl(codec, "Input Source");
for (i = 0; kctl && i < kctl->count; i++) {
- err = snd_hda_add_nids(codec, kctl, i, spec->capsrc_nids,
- spec->input_mux->num_items);
+ err = snd_hda_add_nid(codec, kctl, i, spec->capsrc_nids[i]);
if (err < 0)
return err;
}
@@ -442,6 +441,11 @@ static int ad198x_build_pcms(struct hda_codec *codec)
return 0;
}
+static inline void ad198x_shutup(struct hda_codec *codec)
+{
+ snd_hda_shutup_pins(codec);
+}
+
static void ad198x_free_kctls(struct hda_codec *codec)
{
struct ad198x_spec *spec = codec->spec;
@@ -455,6 +459,46 @@ static void ad198x_free_kctls(struct hda_codec *codec)
snd_array_free(&spec->kctls);
}
+static void ad198x_power_eapd_write(struct hda_codec *codec, hda_nid_t front,
+ hda_nid_t hp)
+{
+ struct ad198x_spec *spec = codec->spec;
+ snd_hda_codec_write(codec, front, 0, AC_VERB_SET_EAPD_BTLENABLE,
+ !spec->inv_eapd ? 0x00 : 0x02);
+ snd_hda_codec_write(codec, hp, 0, AC_VERB_SET_EAPD_BTLENABLE,
+ !spec->inv_eapd ? 0x00 : 0x02);
+}
+
+static void ad198x_power_eapd(struct hda_codec *codec)
+{
+ /* We currently only handle front, HP */
+ switch (codec->vendor_id) {
+ case 0x11d41882:
+ case 0x11d4882a:
+ case 0x11d41884:
+ case 0x11d41984:
+ case 0x11d41883:
+ case 0x11d4184a:
+ case 0x11d4194a:
+ case 0x11d4194b:
+ ad198x_power_eapd_write(codec, 0x12, 0x11);
+ break;
+ case 0x11d41981:
+ case 0x11d41983:
+ ad198x_power_eapd_write(codec, 0x05, 0x06);
+ break;
+ case 0x11d41986:
+ ad198x_power_eapd_write(codec, 0x1b, 0x1a);
+ break;
+ case 0x11d41988:
+ case 0x11d4198b:
+ case 0x11d4989a:
+ case 0x11d4989b:
+ ad198x_power_eapd_write(codec, 0x29, 0x22);
+ break;
+ }
+}
+
static void ad198x_free(struct hda_codec *codec)
{
struct ad198x_spec *spec = codec->spec;
@@ -462,11 +506,29 @@ static void ad198x_free(struct hda_codec *codec)
if (!spec)
return;
+ ad198x_shutup(codec);
ad198x_free_kctls(codec);
kfree(spec);
snd_hda_detach_beep_device(codec);
}
+#ifdef SND_HDA_NEEDS_RESUME
+static int ad198x_suspend(struct hda_codec *codec, pm_message_t state)
+{
+ ad198x_shutup(codec);
+ ad198x_power_eapd(codec);
+ return 0;
+}
+
+static int ad198x_resume(struct hda_codec *codec)
+{
+ ad198x_init(codec);
+ snd_hda_codec_resume_amp(codec);
+ snd_hda_codec_resume_cache(codec);
+ return 0;
+}
+#endif
+
static struct hda_codec_ops ad198x_patch_ops = {
.build_controls = ad198x_build_controls,
.build_pcms = ad198x_build_pcms,
@@ -475,6 +537,11 @@ static struct hda_codec_ops ad198x_patch_ops = {
#ifdef CONFIG_SND_HDA_POWER_SAVE
.check_power_status = ad198x_check_power_status,
#endif
+#ifdef SND_HDA_NEEDS_RESUME
+ .suspend = ad198x_suspend,
+ .resume = ad198x_resume,
+#endif
+ .reboot_notify = ad198x_shutup,
};
@@ -1813,6 +1880,14 @@ static int patch_ad1981(struct hda_codec *codec)
codec->patch_ops.init = ad1981_hp_init;
codec->patch_ops.unsol_event = ad1981_hp_unsol_event;
+ /* set the upper-limit for mixer amp to 0dB for avoiding the
+ * possible damage by overloading
+ */
+ snd_hda_override_amp_caps(codec, 0x11, HDA_INPUT,
+ (0x17 << AC_AMPCAP_OFFSET_SHIFT) |
+ (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) |
+ (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) |
+ (1 << AC_AMPCAP_MUTE_SHIFT));
break;
case AD1981_THINKPAD:
spec->mixers[0] = ad1981_thinkpad_mixers;
OpenPOWER on IntegriCloud