Linux Sound subsystem development
 help / color / mirror / Atom feed
From: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
To: lgirdwood@gmail.com, broonie@kernel.org
Cc: linux-sound@vger.kernel.org, kai.vehmanen@linux.intel.com,
	ranjani.sridharan@linux.intel.com,
	yung-chuan.liao@linux.intel.com, pierre-louis.bossart@linux.dev,
	liam.r.girdwood@intel.com
Subject: [PATCH 6/8] ASoC: SOF: Intel: hda-mlink: Add support for mic privacy in VS SHIM registers
Date: Thu,  6 Mar 2025 15:35:25 +0200	[thread overview]
Message-ID: <20250306133527.16722-7-peter.ujfalusi@linux.intel.com> (raw)
In-Reply-To: <20250306133527.16722-1-peter.ujfalusi@linux.intel.com>

New register has been introduced with PTL in the vendor specific SHIM
registers, outside of the IPs itself for microphone privacy status handling.

Via the PVCCS register the current microphone privacy status can be checked
and the interrupt generation on status change can be enabled/disabled.
The status change interrupt is routed to the owner of the interface
(DSP/host).

The PVCCS is provided for each sublink under the IP to make it possible to
control the interrupt generation per sublink.
On status change the MDSTSCHG bit needs to be cleared for all sublink of
the interface to be able to detect future changes in privacy.

The status bit (MDSTS) is volatile in all PVCCS register, it reflects the
current state of the GPIO signal.

Microphone privacy is a hardware feature (if enabled and configured that
way), the host has only passive, monitoring role.

The added functions are generic to be future proof if the mic privacy
support is extended beyond Soundwire and DMIC links.

Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
Reviewed-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
Reviewed-by: Liam Girdwood <liam.r.girdwood@intel.com>
Reviewed-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
---
 include/sound/hda-mlink.h       |  25 +++++++
 sound/soc/sof/intel/hda-mlink.c | 127 ++++++++++++++++++++++++++++++++
 2 files changed, 152 insertions(+)

diff --git a/include/sound/hda-mlink.h b/include/sound/hda-mlink.h
index 6774f4b9e5fc..4327317be6af 100644
--- a/include/sound/hda-mlink.h
+++ b/include/sound/hda-mlink.h
@@ -62,6 +62,12 @@ struct mutex *hdac_bus_eml_get_mutex(struct hdac_bus *bus, bool alt, int elid);
 
 int hdac_bus_eml_enable_offload(struct hdac_bus *bus, bool alt, int elid, bool enable);
 
+/* microphone privacy specific function supported by ACE3+ architecture */
+void hdac_bus_eml_set_mic_privacy_mask(struct hdac_bus *bus, bool alt, int elid,
+				       unsigned long mask);
+bool hdac_bus_eml_is_mic_privacy_changed(struct hdac_bus *bus, bool alt, int elid);
+bool hdac_bus_eml_get_mic_privacy_state(struct hdac_bus *bus, bool alt, int elid);
+
 #else
 
 static inline int
@@ -185,4 +191,23 @@ hdac_bus_eml_enable_offload(struct hdac_bus *bus, bool alt, int elid, bool enabl
 {
 	return 0;
 }
+
+static inline void
+hdac_bus_eml_set_mic_privacy_mask(struct hdac_bus *bus, bool alt, int elid,
+				  unsigned long mask)
+{
+}
+
+static inline bool
+hdac_bus_eml_is_mic_privacy_changed(struct hdac_bus *bus, bool alt, int elid)
+{
+	return false;
+}
+
+static inline bool
+hdac_bus_eml_get_mic_privacy_state(struct hdac_bus *bus, bool alt, int elid)
+{
+	return false;
+}
+
 #endif /* CONFIG_SND_SOC_SOF_HDA_MLINK */
diff --git a/sound/soc/sof/intel/hda-mlink.c b/sound/soc/sof/intel/hda-mlink.c
index fe627bcb0531..ce561fe52bd5 100644
--- a/sound/soc/sof/intel/hda-mlink.c
+++ b/sound/soc/sof/intel/hda-mlink.c
@@ -16,6 +16,7 @@
 
 #include <linux/bitfield.h>
 #include <linux/module.h>
+#include <linux/string_choices.h>
 
 #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_MLINK)
 
@@ -42,6 +43,7 @@
  * @shim_offset:	offset to SHIM register base
  * @ip_offset:		offset to IP register base
  * @shim_vs_offset:	offset to vendor-specific (VS) SHIM base
+ * @mic_privacy_mask:	bitmask of sublinks where mic privacy is applied
  */
 struct hdac_ext2_link {
 	struct hdac_ext_link hext_link;
@@ -65,6 +67,8 @@ struct hdac_ext2_link {
 	u32 shim_offset;
 	u32 ip_offset;
 	u32 shim_vs_offset;
+
+	unsigned long mic_privacy_mask;
 };
 
 #define hdac_ext_link_to_ext2(h) container_of(h, struct hdac_ext2_link, hext_link)
@@ -90,6 +94,13 @@ struct hdac_ext2_link {
 #define AZX_REG_INTEL_UAOL_IP_OFFSET			0x100
 #define AZX_REG_INTEL_UAOL_VS_SHIM_OFFSET		0xC00
 
+/* Microphone privacy */
+#define AZX_REG_INTEL_VS_SHIM_PVCCS			0x10
+#define AZX_REG_INTEL_VS_SHIM_PVCCS_MDSTSCHGIE		BIT(0)
+#define AZX_REG_INTEL_VS_SHIM_PVCCS_MDSTSCHG		BIT(8)
+#define AZX_REG_INTEL_VS_SHIM_PVCCS_MDSTS		BIT(9)
+#define AZX_REG_INTEL_VS_SHIM_PVCCS_FMDIS		BIT(10)
+
 /* HDAML section - this part follows sequences in the hardware specification,
  * including naming conventions and the use of the hdaml_ prefix.
  * The code is intentionally minimal with limited dependencies on frameworks or
@@ -696,6 +707,20 @@ static int hdac_bus_eml_power_up_base(struct hdac_bus *bus, bool alt, int elid,
 	}
 
 	ret = hdaml_link_init(hlink->ml_addr + AZX_REG_ML_LCTL, sublink);
+	if ((h2link->mic_privacy_mask & BIT(sublink)) && !ret) {
+		u16 __iomem *pvccs = h2link->base_ptr +
+				     h2link->shim_vs_offset +
+				     sublink * h2link->instance_offset +
+				     AZX_REG_INTEL_VS_SHIM_PVCCS;
+		u16 val = readw(pvccs);
+
+		writew(val | AZX_REG_INTEL_VS_SHIM_PVCCS_MDSTSCHGIE, pvccs);
+
+		if (val & AZX_REG_INTEL_VS_SHIM_PVCCS_MDSTS)
+			dev_dbg(bus->dev,
+				"sublink %d (%d:%d): Mic privacy is enabled\n",
+				sublink, alt, elid);
+	}
 
 skip_init:
 	if (eml_lock)
@@ -742,6 +767,16 @@ static int hdac_bus_eml_power_down_base(struct hdac_bus *bus, bool alt, int elid
 		if (--h2link->sublink_ref_count[sublink] > 0)
 			goto skip_shutdown;
 	}
+
+	if (h2link->mic_privacy_mask & BIT(sublink)) {
+		u16 __iomem *pvccs = h2link->base_ptr +
+				     h2link->shim_vs_offset +
+				     sublink * h2link->instance_offset +
+				     AZX_REG_INTEL_VS_SHIM_PVCCS;
+
+		writew(readw(pvccs) & ~AZX_REG_INTEL_VS_SHIM_PVCCS_MDSTSCHGIE, pvccs);
+	}
+
 	ret = hdaml_link_shutdown(hlink->ml_addr + AZX_REG_ML_LCTL, sublink);
 
 skip_shutdown:
@@ -987,6 +1022,98 @@ int hdac_bus_eml_enable_offload(struct hdac_bus *bus, bool alt, int elid, bool e
 }
 EXPORT_SYMBOL_NS(hdac_bus_eml_enable_offload, "SND_SOC_SOF_HDA_MLINK");
 
+void hdac_bus_eml_set_mic_privacy_mask(struct hdac_bus *bus, bool alt, int elid,
+				       unsigned long mask)
+{
+	struct hdac_ext2_link *h2link;
+
+	if (!mask)
+		return;
+
+	h2link = find_ext2_link(bus, alt, elid);
+	if (!h2link)
+		return;
+
+	if (__fls(mask) > h2link->slcount) {
+		dev_warn(bus->dev,
+			 "%s: invalid sublink mask for %d:%d, slcount %d: %#lx\n",
+			 __func__, alt, elid, h2link->slcount, mask);
+		return;
+	}
+
+	dev_dbg(bus->dev, "sublink mask for %d:%d, slcount %d: %#lx\n", alt,
+		elid, h2link->slcount, mask);
+
+	h2link->mic_privacy_mask = mask;
+}
+EXPORT_SYMBOL_NS(hdac_bus_eml_set_mic_privacy_mask, "SND_SOC_SOF_HDA_MLINK");
+
+bool hdac_bus_eml_is_mic_privacy_changed(struct hdac_bus *bus, bool alt, int elid)
+{
+	struct hdac_ext2_link *h2link;
+	bool changed = false;
+	u16 __iomem *pvccs;
+	int i;
+
+	h2link = find_ext2_link(bus, alt, elid);
+	if (!h2link)
+		return false;
+
+	/* The change in privacy state needs to be acked for each link */
+	for_each_set_bit(i, &h2link->mic_privacy_mask, h2link->slcount) {
+		u16 val;
+
+		if (h2link->sublink_ref_count[i] == 0)
+			continue;
+
+		pvccs = h2link->base_ptr +
+			h2link->shim_vs_offset +
+			i * h2link->instance_offset +
+			AZX_REG_INTEL_VS_SHIM_PVCCS;
+
+		val = readw(pvccs);
+		if (val & AZX_REG_INTEL_VS_SHIM_PVCCS_MDSTSCHG) {
+			writew(val, pvccs);
+			changed = true;
+		}
+	}
+
+	return changed;
+}
+EXPORT_SYMBOL_NS(hdac_bus_eml_is_mic_privacy_changed, "SND_SOC_SOF_HDA_MLINK");
+
+bool hdac_bus_eml_get_mic_privacy_state(struct hdac_bus *bus, bool alt, int elid)
+{
+	struct hdac_ext2_link *h2link;
+	u16 __iomem *pvccs;
+	bool state;
+	int i;
+
+	h2link = find_ext2_link(bus, alt, elid);
+	if (!h2link)
+		return false;
+
+	for_each_set_bit(i, &h2link->mic_privacy_mask, h2link->slcount) {
+		if (h2link->sublink_ref_count[i] == 0)
+			continue;
+
+		/* Return the privacy state from the first active link */
+		pvccs = h2link->base_ptr +
+			h2link->shim_vs_offset +
+			i * h2link->instance_offset +
+			AZX_REG_INTEL_VS_SHIM_PVCCS;
+
+		state = readw(pvccs) & AZX_REG_INTEL_VS_SHIM_PVCCS_MDSTS;
+		dev_dbg(bus->dev, "alt: %d, elid: %d: Mic privacy is %s\n", alt,
+			elid, str_enabled_disabled(state));
+
+		return state;
+	}
+
+	return false;
+}
+EXPORT_SYMBOL_NS(hdac_bus_eml_get_mic_privacy_state, "SND_SOC_SOF_HDA_MLINK");
+
 #endif
 
 MODULE_LICENSE("Dual BSD/GPL");
-- 
2.48.1


  parent reply	other threads:[~2025-03-06 13:35 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-03-06 13:35 [PATCH 0/8] ASoC: SOF: Intel: Add support for ACE3+ mic privacy Peter Ujfalusi
2025-03-06 13:35 ` [PATCH 1/8] ASoC: SOF: Intel: mtl: Split up dsp_ops setup code Peter Ujfalusi
2025-03-06 13:35 ` [PATCH 2/8] ASoC: SOF: Intel: lnl/ptl: Only set dsp_ops which differs from MTL Peter Ujfalusi
2025-03-06 13:35 ` [PATCH 3/8] ASoC: SOF: Intel: mtl: Stop exporting dsp_ops callback functions Peter Ujfalusi
2025-03-06 13:35 ` [PATCH 4/8] ASoC: SOF: Intel: Create ptl.c as placeholder for Panther Lake features Peter Ujfalusi
2025-03-06 13:35 ` [PATCH 5/8] ASoC: SOF: ipc4: Add support for Intel HW managed mic privacy messaging Peter Ujfalusi
2025-03-06 13:42   ` Mark Brown
2025-03-06 15:37     ` Péter Ujfalusi
2025-03-06 13:35 ` Peter Ujfalusi [this message]
2025-03-06 13:35 ` [PATCH 7/8] ASoC: SOF: hda/shim: Add callbacks to handle mic privacy change for sdw Peter Ujfalusi
2025-03-06 13:35 ` [PATCH 8/8] ASoC: SOF: Intel: ptl: Add support for mic privacy Peter Ujfalusi
2025-03-06 14:05   ` Amadeusz Sławiński
2025-03-06 15:40     ` Péter Ujfalusi

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20250306133527.16722-7-peter.ujfalusi@linux.intel.com \
    --to=peter.ujfalusi@linux.intel.com \
    --cc=broonie@kernel.org \
    --cc=kai.vehmanen@linux.intel.com \
    --cc=lgirdwood@gmail.com \
    --cc=liam.r.girdwood@intel.com \
    --cc=linux-sound@vger.kernel.org \
    --cc=pierre-louis.bossart@linux.dev \
    --cc=ranjani.sridharan@linux.intel.com \
    --cc=yung-chuan.liao@linux.intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox