Skip to content

Commit c445516

Browse files
ujfalusiranj063
authored andcommitted
ASoC: SOF: hda/ptl: Move mic privacy change notification sending to a work
IPC message cannot be sent from the irq thread directly as the message will not receive the reply (interrupts are disabled) and it will time out - the reply is going to be received right after the we leave the irq thread. This is a different case compared to the delayed IPC messages due to DSP busy state. Add support for sending the mic privacy change notification to the firmware from a work instead of the process callback. The work needs to be canceled if there is a chance that it might be running on module remove or before system/runtime suspend. Fixes: 4a43c32 ("ASoC: SOF: Intel: ptl: Add support for mic privacy") Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
1 parent f6593e8 commit c445516

4 files changed

Lines changed: 49 additions & 4 deletions

File tree

sound/soc/sof/intel/hda-dsp.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -998,6 +998,10 @@ int hda_dsp_runtime_suspend(struct snd_sof_dev *sdev)
998998
if (!sdev->dspless_mode_selected) {
999999
/* cancel any attempt for DSP D0I3 */
10001000
cancel_delayed_work_sync(&hda->d0i3_work);
1001+
1002+
/* Cancel the microphone privacy work if mic privacy is active */
1003+
if (hda->mic_privacy.active)
1004+
cancel_work_sync(&hda->mic_privacy.work);
10011005
}
10021006

10031007
/* stop hda controller and power dsp off */
@@ -1020,6 +1024,10 @@ int hda_dsp_suspend(struct snd_sof_dev *sdev, u32 target_state)
10201024
if (!sdev->dspless_mode_selected) {
10211025
/* cancel any attempt for DSP D0I3 */
10221026
cancel_delayed_work_sync(&hda->d0i3_work);
1027+
1028+
/* Cancel the microphone privacy work if mic privacy is active */
1029+
if (hda->mic_privacy.active)
1030+
cancel_work_sync(&hda->mic_privacy.work);
10231031
}
10241032

10251033
if (target_state == SOF_DSP_PM_D0) {

sound/soc/sof/intel/hda.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -976,6 +976,10 @@ void hda_dsp_remove(struct snd_sof_dev *sdev)
976976
if (sdev->dspless_mode_selected)
977977
goto skip_disable_dsp;
978978

979+
/* Cancel the microphone privacy work if mic privacy is active */
980+
if (hda->mic_privacy.active)
981+
cancel_work_sync(&hda->mic_privacy.work);
982+
979983
/* no need to check for error as the DSP will be disabled anyway */
980984
if (chip && chip->power_down_dsp)
981985
chip->power_down_dsp(sdev);

sound/soc/sof/intel/hda.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -487,6 +487,11 @@ enum sof_hda_D0_substate {
487487
SOF_HDA_DSP_PM_D0I3, /* low power D0 substate */
488488
};
489489

490+
struct sof_ace3_mic_privacy {
491+
bool active;
492+
struct work_struct work;
493+
};
494+
490495
/* represents DSP HDA controller frontend - i.e. host facing control */
491496
struct sof_intel_hda_dev {
492497
bool imrboot_supported;
@@ -542,6 +547,9 @@ struct sof_intel_hda_dev {
542547
/* Intel NHLT information */
543548
struct nhlt_acpi_table *nhlt;
544549

550+
/* work queue for mic privacy state change notification sending */
551+
struct sof_ace3_mic_privacy mic_privacy;
552+
545553
/*
546554
* Pointing to the IPC message if immediate sending was not possible
547555
* because the downlink communication channel was BUSY at the time.

sound/soc/sof/intel/ptl.c

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,22 +27,44 @@ static bool sof_ptl_check_mic_privacy_irq(struct snd_sof_dev *sdev, bool alt,
2727
return hdac_bus_eml_is_mic_privacy_changed(sof_to_bus(sdev), alt, elid);
2828
}
2929

30+
static void sof_ptl_mic_privacy_work(struct work_struct *work)
31+
{
32+
struct sof_intel_hda_dev *hdev = container_of(work,
33+
struct sof_intel_hda_dev,
34+
mic_privacy.work);
35+
struct hdac_bus *bus = &hdev->hbus.core;
36+
struct snd_sof_dev *sdev = dev_get_drvdata(bus->dev);
37+
bool state;
38+
39+
/*
40+
* The microphone privacy state is only available via Soundwire shim
41+
* in PTL
42+
* The work is only scheduled on change.
43+
*/
44+
state = hdac_bus_eml_get_mic_privacy_state(bus, 1,
45+
AZX_REG_ML_LEPTR_ID_SDW);
46+
sof_ipc4_mic_privacy_state_change(sdev, state);
47+
}
48+
3049
static void sof_ptl_process_mic_privacy(struct snd_sof_dev *sdev, bool alt,
3150
int elid)
3251
{
33-
bool state;
52+
struct sof_intel_hda_dev *hdev = sdev->pdata->hw_pdata;
3453

3554
if (!alt || elid != AZX_REG_ML_LEPTR_ID_SDW)
3655
return;
3756

38-
state = hdac_bus_eml_get_mic_privacy_state(sof_to_bus(sdev), alt, elid);
39-
40-
sof_ipc4_mic_privacy_state_change(sdev, state);
57+
/*
58+
* Schedule the work to read the microphone privacy state and send IPC
59+
* message about the new state to the firmware
60+
*/
61+
schedule_work(&hdev->mic_privacy.work);
4162
}
4263

4364
static void sof_ptl_set_mic_privacy(struct snd_sof_dev *sdev,
4465
struct sof_ipc4_intel_mic_privacy_cap *caps)
4566
{
67+
struct sof_intel_hda_dev *hdev = sdev->pdata->hw_pdata;
4668
u32 micpvcp;
4769

4870
if (!caps || !caps->capabilities_length)
@@ -58,6 +80,9 @@ static void sof_ptl_set_mic_privacy(struct snd_sof_dev *sdev,
5880
hdac_bus_eml_set_mic_privacy_mask(sof_to_bus(sdev), true,
5981
AZX_REG_ML_LEPTR_ID_SDW,
6082
PTL_MICPVCP_GET_SDW_MASK(micpvcp));
83+
84+
INIT_WORK(&hdev->mic_privacy.work, sof_ptl_mic_privacy_work);
85+
hdev->mic_privacy.active = true;
6186
}
6287

6388
int sof_ptl_set_ops(struct snd_sof_dev *sdev, struct snd_sof_dsp_ops *dsp_ops)

0 commit comments

Comments
 (0)