Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ASoC: SOF: Intel: Add support for hardware mic privacy change reproting #5312

Open
wants to merge 8 commits into
base: topic/sof-dev
Choose a base branch
from
24 changes: 24 additions & 0 deletions include/sound/hda-mlink.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,11 @@ 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);

void hdac_bus_eml_set_mic_privacy_mask(struct hdac_bus *bus, bool alt, int elid,
unsigned long mask);
bool hdac_bus_eml_check_mic_privacy(struct hdac_bus *bus, bool alt, int elid);
bool hdac_bus_eml_get_mic_privacy(struct hdac_bus *bus, bool alt, int elid);

#else

static inline int
Expand Down Expand Up @@ -185,4 +190,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_check_mic_privacy(struct hdac_bus *bus, bool alt, int elid)
{
return false
}

static inline bool
hdac_bus_eml_get_mic_privacy(struct hdac_bus *bus, bool alt, int elid)
{
return false;
}

#endif /* CONFIG_SND_SOC_SOF_HDA_MLINK */
13 changes: 13 additions & 0 deletions include/sound/sof/ipc4/header.h
Original file line number Diff line number Diff line change
Expand Up @@ -396,6 +396,7 @@ enum sof_ipc4_base_fw_params {
SOF_IPC4_FW_PARAM_MODULES_INFO_GET,
SOF_IPC4_FW_PARAM_LIBRARIES_INFO_GET = 16,
SOF_IPC4_FW_PARAM_SYSTEM_TIME = 20,
SOF_IPC4_FW_PARAM_MIC_PRIVACY_STATE_CHANGE = 35,
};

enum sof_ipc4_fw_config_params {
Expand Down Expand Up @@ -446,6 +447,18 @@ struct sof_ipc4_dx_state_info {
uint32_t dx_mask;
} __packed __aligned(4);

enum sof_ipc4_hw_config_params {
SOF_IPC4_HW_CFG_INTEL_MIC_PRIVACY_CAPS = 11,
};

#define SOF_IPC_INTEL_MIC_PRIVACY_VERSION_PTL 1

struct sof_ipc4_intel_mic_privacy_cap {
uint32_t version;
uint32_t capabilities_length;
uint32_t capabilities[];
} __packed;

/* Reply messages */

/*
Expand Down
2 changes: 1 addition & 1 deletion sound/soc/sof/intel/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ snd-sof-pci-intel-icl-y := pci-icl.o icl.o
snd-sof-pci-intel-tgl-y := pci-tgl.o tgl.o
snd-sof-pci-intel-mtl-y := pci-mtl.o mtl.o
snd-sof-pci-intel-lnl-y := pci-lnl.o lnl.o
snd-sof-pci-intel-ptl-y := pci-ptl.o
snd-sof-pci-intel-ptl-y := pci-ptl.o ptl.o

obj-$(CONFIG_SND_SOC_SOF_MERRIFIELD) += snd-sof-pci-intel-tng.o
obj-$(CONFIG_SND_SOC_SOF_INTEL_SKL) += snd-sof-pci-intel-skl.o
Expand Down
110 changes: 110 additions & 0 deletions sound/soc/sof/intel/hda-mlink.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,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;
Expand All @@ -65,6 +66,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)
Expand All @@ -90,6 +93,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
Expand Down Expand Up @@ -696,6 +706,14 @@ 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;

writew(readw(pvccs) | AZX_REG_INTEL_VS_SHIM_PVCCS_MDSTSCHGIE, pvccs);
}

skip_init:
if (eml_lock)
Expand Down Expand Up @@ -742,6 +760,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:
Expand Down Expand Up @@ -987,6 +1015,88 @@ 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;

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_check_mic_privacy(struct hdac_bus *bus, bool alt, int elid)
{
struct hdac_ext2_link *h2link;
bool triggered = false;
u16 __iomem *pvccs;
int i;

h2link = find_ext2_link(bus, alt, elid);
if (!h2link)
return false;

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);
triggered = true;
}
}

return triggered;
}
EXPORT_SYMBOL_NS(hdac_bus_eml_check_mic_privacy, "SND_SOC_SOF_HDA_MLINK");

bool hdac_bus_eml_get_mic_privacy(struct hdac_bus *bus, bool alt, int elid)
{
struct hdac_ext2_link *h2link;
u16 __iomem *pvccs;
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;

pvccs = h2link->base_ptr +
h2link->shim_vs_offset +
i * h2link->instance_offset +
AZX_REG_INTEL_VS_SHIM_PVCCS;

return readw(pvccs) & AZX_REG_INTEL_VS_SHIM_PVCCS_MDSTS;
}

return false;
}
EXPORT_SYMBOL_NS(hdac_bus_eml_get_mic_privacy, "SND_SOC_SOF_HDA_MLINK");

#endif

MODULE_LICENSE("Dual BSD/GPL");
Expand Down
34 changes: 34 additions & 0 deletions sound/soc/sof/intel/hda.c
Original file line number Diff line number Diff line change
Expand Up @@ -358,6 +358,27 @@ void hda_sdw_process_wakeen_common(struct snd_sof_dev *sdev)
}
EXPORT_SYMBOL_NS(hda_sdw_process_wakeen_common, "SND_SOC_SOF_INTEL_HDA_GENERIC");

static bool hda_dsp_sdw_check_mic_privacy_irq(struct snd_sof_dev *sdev)
{
const struct sof_intel_dsp_desc *chip;

chip = get_chip_info(sdev->pdata);
if (chip && chip->check_mic_privacy_irq)
return chip->check_mic_privacy_irq(sdev, true,
AZX_REG_ML_LEPTR_ID_SDW);

return false;
}

static void hda_dsp_sdw_process_mic_privacy(struct snd_sof_dev *sdev)
{
const struct sof_intel_dsp_desc *chip;

chip = get_chip_info(sdev->pdata);
if (chip && chip->process_mic_privacy)
chip->process_mic_privacy(sdev, true, AZX_REG_ML_LEPTR_ID_SDW);
}

#else /* IS_ENABLED(CONFIG_SND_SOC_SOF_INTEL_SOUNDWIRE) */
static inline int hda_sdw_acpi_scan(struct snd_sof_dev *sdev)
{
Expand Down Expand Up @@ -389,6 +410,13 @@ static inline bool hda_sdw_check_wakeen_irq(struct snd_sof_dev *sdev)
return false;
}

static inline bool hda_dsp_sdw_check_mic_privacy_irq(struct snd_sof_dev *sdev)
{
return false;
}

static inline void hda_dsp_sdw_process_mic_privacy(struct snd_sof_dev *sdev) { }

#endif /* IS_ENABLED(CONFIG_SND_SOC_SOF_INTEL_SOUNDWIRE) */

/* pre fw run operations */
Expand Down Expand Up @@ -684,7 +712,13 @@ static irqreturn_t hda_dsp_interrupt_thread(int irq, void *context)

if (hda_dsp_check_sdw_irq(sdev)) {
trace_sof_intel_hda_irq(sdev, "sdw");

hda_dsp_sdw_thread(irq, hdev->sdw);

if (hda_dsp_sdw_check_mic_privacy_irq(sdev)) {
trace_sof_intel_hda_irq(sdev, "mic privacy");
hda_dsp_sdw_process_mic_privacy(sdev);
}
}

if (hda_sdw_check_wakeen_irq(sdev)) {
Expand Down
4 changes: 0 additions & 4 deletions sound/soc/sof/intel/hda.h
Original file line number Diff line number Diff line change
Expand Up @@ -913,10 +913,6 @@ extern struct snd_sof_dsp_ops sof_tgl_ops;
int sof_tgl_ops_init(struct snd_sof_dev *sdev);
extern struct snd_sof_dsp_ops sof_icl_ops;
int sof_icl_ops_init(struct snd_sof_dev *sdev);
extern struct snd_sof_dsp_ops sof_mtl_ops;
int sof_mtl_ops_init(struct snd_sof_dev *sdev);
extern struct snd_sof_dsp_ops sof_lnl_ops;
int sof_lnl_ops_init(struct snd_sof_dev *sdev);

extern const struct sof_intel_dsp_desc skl_chip_info;
extern const struct sof_intel_dsp_desc apl_chip_info;
Expand Down
Loading
Loading