Unverified Commit f3806fe5 authored by Mark Brown's avatar Mark Brown
Browse files

ASoC: SOF: Intel: improve and extend HDaudio-based

Merge series from Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>:

For LunarLake, the SoundWire in-band wake detection is reported with
the HDAudio WAKE_EN/WAKE_STS registers. In the existing code, these
registers are only handled for HDaudio codecs. Now the same registers
have to be handled with care as shared resources.

The in-band wake detection mainly used for jack detection. Without
this patchset, the SoundWire headset codecs signal an event that would
be ignored and not reported.
parents 3018fdf7 35b5806e
Loading
Loading
Loading
Loading
+12 −3
Original line number Diff line number Diff line
@@ -79,18 +79,27 @@ void hda_codec_jack_wake_enable(struct snd_sof_dev *sdev, bool enable)
	struct hdac_bus *bus = sof_to_bus(sdev);
	struct hda_codec *codec;
	unsigned int mask = 0;
	unsigned int val = 0;

	if (IS_ENABLED(CONFIG_SND_SOC_SOF_NOCODEC_DEBUG_SUPPORT) &&
	    sof_debug_check_flag(SOF_DBG_FORCE_NOCODEC))
		return;

	if (enable) {
		list_for_each_codec(codec, hbus)
		list_for_each_codec(codec, hbus) {
			/* only set WAKEEN when needed for HDaudio codecs */
			mask |= BIT(codec->core.addr);
			if (codec->jacktbl.used)
				val |= BIT(codec->core.addr);
		}
	} else {
		list_for_each_codec(codec, hbus) {
			/* reset WAKEEN only HDaudio codecs */
			mask |= BIT(codec->core.addr);
		}
	}

	snd_hdac_chip_updatew(bus, WAKEEN, STATESTS_INT_MASK, mask);
	snd_hdac_chip_updatew(bus, WAKEEN, mask & STATESTS_INT_MASK, val);
}
EXPORT_SYMBOL_NS_GPL(hda_codec_jack_wake_enable, SND_SOC_SOF_HDA_AUDIO_CODEC);

+8 −1
Original line number Diff line number Diff line
@@ -184,6 +184,7 @@ int hda_dsp_ctrl_init_chip(struct snd_sof_dev *sdev)
	struct hdac_bus *bus = sof_to_bus(sdev);
	struct hdac_stream *stream;
	int sd_offset, ret = 0;
	u32 gctl;

	if (bus->chip_init)
		return 0;
@@ -192,6 +193,12 @@ int hda_dsp_ctrl_init_chip(struct snd_sof_dev *sdev)

	hda_dsp_ctrl_misc_clock_gating(sdev, false);

	/* clear WAKE_STS if not in reset */
	gctl = snd_sof_dsp_read(sdev, HDA_DSP_HDA_BAR, SOF_HDA_GCTL);
	if (gctl & SOF_HDA_GCTL_RESET)
		snd_sof_dsp_write(sdev, HDA_DSP_HDA_BAR,
				  SOF_HDA_WAKESTS, SOF_HDA_WAKESTS_INT_MASK);

	/* reset HDA controller */
	ret = hda_dsp_ctrl_link_reset(sdev, true);
	if (ret < 0) {
@@ -221,7 +228,7 @@ int hda_dsp_ctrl_init_chip(struct snd_sof_dev *sdev)

	/* clear WAKESTS */
	snd_sof_dsp_write(sdev, HDA_DSP_HDA_BAR, SOF_HDA_WAKESTS,
			  SOF_HDA_WAKESTS_INT_MASK);
			  bus->codec_mask);

	hda_codec_rirb_status_clear(sdev);

+18 −0
Original line number Diff line number Diff line
@@ -189,6 +189,23 @@ static int lnl_dsp_disable_interrupts(struct snd_sof_dev *sdev)
	return mtl_enable_interrupts(sdev, false);
}

static bool lnl_sdw_check_wakeen_irq(struct snd_sof_dev *sdev)
{
	struct hdac_bus *bus = sof_to_bus(sdev);
	u16 wake_sts;

	/*
	 * we need to use the global HDaudio WAKEEN/STS to be able to
	 * detect wakes in low-power modes. The link-specific information
	 * is handled in the process_wakeen() helper, this helper only
	 * detects a SoundWire wake without identifying the link.
	 */
	wake_sts = snd_hdac_chip_readw(bus, STATESTS);

	/* filter out the range of SDIs that can be set for SoundWire */
	return wake_sts & GENMASK(SDW_MAX_DEVICES, SDW_INTEL_DEV_NUM_IDA_MIN);
}

const struct sof_intel_dsp_desc lnl_chip_info = {
	.cores_num = 5,
	.init_core_mask = BIT(0),
@@ -205,6 +222,7 @@ const struct sof_intel_dsp_desc lnl_chip_info = {
	.read_sdw_lcount =  hda_sdw_check_lcount_ext,
	.enable_sdw_irq = lnl_enable_sdw_irq,
	.check_sdw_irq = lnl_dsp_check_sdw_irq,
	.check_sdw_wakeen_irq = lnl_sdw_check_wakeen_irq,
	.check_ipc_irq = mtl_dsp_check_ipc_irq,
	.cl_init = mtl_dsp_cl_init,
	.power_down_dsp = mtl_power_down_dsp,