Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

ALSA: hda/generic: Add a helper to mute speakers at suspend/shutdown

Some devices indicate click noises at suspend or shutdown when the
speakers are unmuted. This patch adds a helper,
snd_hda_gen_shutup_speakers(), to work around it. The new function is
supposed to be called at suspend or shutdown by the codec driver, and
it mutes the speakers.

The mute status isn't cached, hence the original mute state will be
restored at resume again.

Link: https://patch.msgid.link/20240726142625.2460-1-tiwai@suse.de
Signed-off-by: Takashi Iwai <tiwai@suse.de>

+64
+63
sound/pci/hda/hda_generic.c
··· 4955 4955 } 4956 4956 EXPORT_SYMBOL_GPL(snd_hda_gen_stream_pm); 4957 4957 4958 + /* forcibly mute the speaker output without caching; return true if updated */ 4959 + static bool force_mute_output_path(struct hda_codec *codec, hda_nid_t nid) 4960 + { 4961 + if (!nid) 4962 + return false; 4963 + if (!nid_has_mute(codec, nid, HDA_OUTPUT)) 4964 + return false; /* no mute, skip */ 4965 + if (snd_hda_codec_amp_read(codec, nid, 0, HDA_OUTPUT, 0) & 4966 + snd_hda_codec_amp_read(codec, nid, 1, HDA_OUTPUT, 0) & 4967 + HDA_AMP_MUTE) 4968 + return false; /* both channels already muted, skip */ 4969 + 4970 + /* direct amp update without caching */ 4971 + snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, 4972 + AC_AMP_SET_OUTPUT | AC_AMP_SET_LEFT | 4973 + AC_AMP_SET_RIGHT | HDA_AMP_MUTE); 4974 + return true; 4975 + } 4976 + 4977 + /** 4978 + * snd_hda_gen_shutup_speakers - Forcibly mute the speaker outputs 4979 + * @codec: the HDA codec 4980 + * 4981 + * Forcibly mute the speaker outputs, to be called at suspend or shutdown. 4982 + * 4983 + * The mute state done by this function isn't cached, hence the original state 4984 + * will be restored at resume. 4985 + * 4986 + * Return true if the mute state has been changed. 4987 + */ 4988 + bool snd_hda_gen_shutup_speakers(struct hda_codec *codec) 4989 + { 4990 + struct hda_gen_spec *spec = codec->spec; 4991 + const int *paths; 4992 + const struct nid_path *path; 4993 + int i, p, num_paths; 4994 + bool updated = false; 4995 + 4996 + /* if already powered off, do nothing */ 4997 + if (!snd_hdac_is_power_on(&codec->core)) 4998 + return false; 4999 + 5000 + if (spec->autocfg.line_out_type == AUTO_PIN_SPEAKER_OUT) { 5001 + paths = spec->out_paths; 5002 + num_paths = spec->autocfg.line_outs; 5003 + } else { 5004 + paths = spec->speaker_paths; 5005 + num_paths = spec->autocfg.speaker_outs; 5006 + } 5007 + 5008 + for (i = 0; i < num_paths; i++) { 5009 + path = snd_hda_get_path_from_idx(codec, paths[i]); 5010 + if (!path) 5011 + continue; 5012 + for (p = 0; p < path->depth; p++) 5013 + if (force_mute_output_path(codec, path->path[p])) 5014 + updated = true; 5015 + } 5016 + 5017 + return updated; 5018 + } 5019 + EXPORT_SYMBOL_GPL(snd_hda_gen_shutup_speakers); 5020 + 4958 5021 /** 4959 5022 * snd_hda_gen_parse_auto_config - Parse the given BIOS configuration and 4960 5023 * set up the hda_gen_spec
+1
sound/pci/hda/hda_generic.h
··· 353 353 int snd_hda_gen_add_micmute_led_cdev(struct hda_codec *codec, 354 354 int (*callback)(struct led_classdev *, 355 355 enum led_brightness)); 356 + bool snd_hda_gen_shutup_speakers(struct hda_codec *codec); 356 357 357 358 #endif /* __SOUND_HDA_GENERIC_H */