diff options
Diffstat (limited to 'sound/soc/sof/intel/hda-codec.c')
| -rw-r--r-- | sound/soc/sof/intel/hda-codec.c | 50 | 
1 files changed, 44 insertions, 6 deletions
diff --git a/sound/soc/sof/intel/hda-codec.c b/sound/soc/sof/intel/hda-codec.c index b8b37f082309..3ca6795a89ba 100644 --- a/sound/soc/sof/intel/hda-codec.c +++ b/sound/soc/sof/intel/hda-codec.c @@ -10,6 +10,7 @@  #include <linux/module.h>  #include <sound/hdaudio_ext.h> +#include <sound/hda_register.h>  #include <sound/hda_codec.h>  #include <sound/hda_i915.h>  #include <sound/sof.h> @@ -37,16 +38,55 @@ static void hda_codec_load_module(struct hda_codec *codec)  static void hda_codec_load_module(struct hda_codec *codec) {}  #endif +/* enable controller wake up event for all codecs with jack connectors */ +void hda_codec_jack_wake_enable(struct snd_sof_dev *sdev) +{ +	struct hda_bus *hbus = sof_to_hbus(sdev); +	struct hdac_bus *bus = sof_to_bus(sdev); +	struct hda_codec *codec; +	unsigned int mask = 0; + +	list_for_each_codec(codec, hbus) +		if (codec->jacktbl.used) +			mask |= BIT(codec->core.addr); + +	snd_hdac_chip_updatew(bus, WAKEEN, STATESTS_INT_MASK, mask); +} + +/* check jack status after resuming from suspend mode */ +void hda_codec_jack_check(struct snd_sof_dev *sdev) +{ +	struct hda_bus *hbus = sof_to_hbus(sdev); +	struct hdac_bus *bus = sof_to_bus(sdev); +	struct hda_codec *codec; + +	/* disable controller Wake Up event*/ +	snd_hdac_chip_updatew(bus, WAKEEN, STATESTS_INT_MASK, 0); + +	list_for_each_codec(codec, hbus) +		/* +		 * Wake up all jack-detecting codecs regardless whether an event +		 * has been recorded in STATESTS +		 */ +		if (codec->jacktbl.used) +			schedule_delayed_work(&codec->jackpoll_work, +					      codec->jackpoll_interval); +} +#else +void hda_codec_jack_wake_enable(struct snd_sof_dev *sdev) {} +void hda_codec_jack_check(struct snd_sof_dev *sdev) {}  #endif /* CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC */ +EXPORT_SYMBOL(hda_codec_jack_wake_enable); +EXPORT_SYMBOL(hda_codec_jack_check);  /* probe individual codec */  static int hda_codec_probe(struct snd_sof_dev *sdev, int address)  { -	struct hda_bus *hbus = sof_to_hbus(sdev); -	struct hdac_device *hdev;  #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC)  	struct hdac_hda_priv *hda_priv;  #endif +	struct hda_bus *hbus = sof_to_hbus(sdev); +	struct hdac_device *hdev;  	u32 hda_cmd = (address << 28) | (AC_NODE_ROOT << 20) |  		(AC_VERB_PARAMETERS << 8) | AC_PAR_VENDOR_ID;  	u32 resp = -1; @@ -62,8 +102,7 @@ static int hda_codec_probe(struct snd_sof_dev *sdev, int address)  		address, resp);  #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC) -	/* snd_hdac_ext_bus_device_exit will use kfree to free hdev */ -	hda_priv = kzalloc(sizeof(*hda_priv), GFP_KERNEL); +	hda_priv = devm_kzalloc(sdev->dev, sizeof(*hda_priv), GFP_KERNEL);  	if (!hda_priv)  		return -ENOMEM; @@ -82,8 +121,7 @@ static int hda_codec_probe(struct snd_sof_dev *sdev, int address)  	return 0;  #else -	/* snd_hdac_ext_bus_device_exit will use kfree to free hdev */ -	hdev = kzalloc(sizeof(*hdev), GFP_KERNEL); +	hdev = devm_kzalloc(sdev->dev, sizeof(*hdev), GFP_KERNEL);  	if (!hdev)  		return -ENOMEM;  |