diff options
Diffstat (limited to 'sound/soc/sof/intel')
-rw-r--r-- | sound/soc/sof/intel/Kconfig | 1 | ||||
-rw-r--r-- | sound/soc/sof/intel/hda-bus.c | 2 | ||||
-rw-r--r-- | sound/soc/sof/intel/hda-dsp.c | 8 | ||||
-rw-r--r-- | sound/soc/sof/intel/hda.c | 20 | ||||
-rw-r--r-- | sound/soc/sof/intel/hda.h | 9 | ||||
-rw-r--r-- | sound/soc/sof/intel/pci-ptl.c | 30 | ||||
-rw-r--r-- | sound/soc/sof/intel/ptl.c | 56 |
7 files changed, 120 insertions, 6 deletions
diff --git a/sound/soc/sof/intel/Kconfig b/sound/soc/sof/intel/Kconfig index fae3598fd601..dc1d21de4ab7 100644 --- a/sound/soc/sof/intel/Kconfig +++ b/sound/soc/sof/intel/Kconfig @@ -345,6 +345,7 @@ endif ## SND_SOC_SOF_HDA_GENERIC config SND_SOF_SOF_HDA_SDW_BPT tristate + select SND_HDA_EXT_CORE help This option is not user-selectable but automagically handled by 'select' statements at a higher level. diff --git a/sound/soc/sof/intel/hda-bus.c b/sound/soc/sof/intel/hda-bus.c index b1be03011d7e..6492e1cefbfb 100644 --- a/sound/soc/sof/intel/hda-bus.c +++ b/sound/soc/sof/intel/hda-bus.c @@ -76,7 +76,7 @@ void sof_hda_bus_init(struct snd_sof_dev *sdev, struct device *dev) snd_hdac_ext_bus_init(bus, dev, &bus_core_ops, sof_hda_ext_ops); - if (chip && chip->hw_ip_version == SOF_INTEL_ACE_2_0) + if (chip && chip->hw_ip_version >= SOF_INTEL_ACE_2_0) bus->use_pio_for_commands = true; #else snd_hdac_ext_bus_init(bus, dev, NULL, NULL); diff --git a/sound/soc/sof/intel/hda-dsp.c b/sound/soc/sof/intel/hda-dsp.c index ccf8eefdca70..f64e8a6a9a33 100644 --- a/sound/soc/sof/intel/hda-dsp.c +++ b/sound/soc/sof/intel/hda-dsp.c @@ -991,6 +991,10 @@ int hda_dsp_runtime_suspend(struct snd_sof_dev *sdev) if (!sdev->dspless_mode_selected) { /* cancel any attempt for DSP D0I3 */ cancel_delayed_work_sync(&hda->d0i3_work); + + /* Cancel the microphone privacy work if mic privacy is active */ + if (hda->mic_privacy.active) + cancel_work_sync(&hda->mic_privacy.work); } /* stop hda controller and power dsp off */ @@ -1017,6 +1021,10 @@ int hda_dsp_suspend(struct snd_sof_dev *sdev, u32 target_state) if (!sdev->dspless_mode_selected) { /* cancel any attempt for DSP D0I3 */ cancel_delayed_work_sync(&hda->d0i3_work); + + /* Cancel the microphone privacy work if mic privacy is active */ + if (hda->mic_privacy.active) + cancel_work_sync(&hda->mic_privacy.work); } if (target_state == SOF_DSP_PM_D0) { diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index 6b1ada566476..6a3932d90b43 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -968,6 +968,10 @@ void hda_dsp_remove(struct snd_sof_dev *sdev) if (sdev->dspless_mode_selected) goto skip_disable_dsp; + /* Cancel the microphone privacy work if mic privacy is active */ + if (hda->mic_privacy.active) + cancel_work_sync(&hda->mic_privacy.work); + /* no need to check for error as the DSP will be disabled anyway */ if (chip && chip->power_down_dsp) chip->power_down_dsp(sdev); @@ -1045,7 +1049,21 @@ static void hda_generic_machine_select(struct snd_sof_dev *sdev, if (!*mach && codec_num <= 2) { bool tplg_fixup = false; - hda_mach = snd_soc_acpi_intel_hda_machines; + /* + * make a local copy of the match array since we might + * be modifying it + */ + hda_mach = devm_kmemdup_array(sdev->dev, + snd_soc_acpi_intel_hda_machines, + 2, /* we have one entry + sentinel in the array */ + sizeof(snd_soc_acpi_intel_hda_machines[0]), + GFP_KERNEL); + if (!hda_mach) { + dev_err(bus->dev, + "%s: failed to duplicate the HDA match table\n", + __func__); + return; + } dev_info(bus->dev, "using HDA machine driver %s now\n", hda_mach->drv_name); diff --git a/sound/soc/sof/intel/hda.h b/sound/soc/sof/intel/hda.h index 76154627fc17..e14f82c0831f 100644 --- a/sound/soc/sof/intel/hda.h +++ b/sound/soc/sof/intel/hda.h @@ -487,6 +487,11 @@ enum sof_hda_D0_substate { SOF_HDA_DSP_PM_D0I3, /* low power D0 substate */ }; +struct sof_ace3_mic_privacy { + bool active; + struct work_struct work; +}; + /* represents DSP HDA controller frontend - i.e. host facing control */ struct sof_intel_hda_dev { bool imrboot_supported; @@ -542,6 +547,9 @@ struct sof_intel_hda_dev { /* Intel NHLT information */ struct nhlt_acpi_table *nhlt; + /* work queue for mic privacy state change notification sending */ + struct sof_ace3_mic_privacy mic_privacy; + /* * Pointing to the IPC message if immediate sending was not possible * because the downlink communication channel was BUSY at the time. @@ -927,6 +935,7 @@ extern const struct sof_intel_dsp_desc mtl_chip_info; extern const struct sof_intel_dsp_desc arl_s_chip_info; extern const struct sof_intel_dsp_desc lnl_chip_info; extern const struct sof_intel_dsp_desc ptl_chip_info; +extern const struct sof_intel_dsp_desc wcl_chip_info; /* Probes support */ #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_PROBES) diff --git a/sound/soc/sof/intel/pci-ptl.c b/sound/soc/sof/intel/pci-ptl.c index 7d4c46f56931..68f6a9841633 100644 --- a/sound/soc/sof/intel/pci-ptl.c +++ b/sound/soc/sof/intel/pci-ptl.c @@ -55,10 +55,40 @@ static const struct sof_dev_desc ptl_desc = { .ops_init = sof_ptl_ops_init, }; +static const struct sof_dev_desc wcl_desc = { + .use_acpi_target_states = true, + .machines = snd_soc_acpi_intel_ptl_machines, + .alt_machines = snd_soc_acpi_intel_ptl_sdw_machines, + .resindex_lpe_base = 0, + .resindex_pcicfg_base = -1, + .resindex_imr_base = -1, + .irqindex_host_ipc = -1, + .chip_info = &wcl_chip_info, + .ipc_supported_mask = BIT(SOF_IPC_TYPE_4), + .ipc_default = SOF_IPC_TYPE_4, + .dspless_mode_supported = true, + .default_fw_path = { + [SOF_IPC_TYPE_4] = "intel/sof-ipc4/wcl", + }, + .default_lib_path = { + [SOF_IPC_TYPE_4] = "intel/sof-ipc4-lib/wcl", + }, + .default_tplg_path = { + [SOF_IPC_TYPE_4] = "intel/sof-ipc4-tplg", + }, + .default_fw_filename = { + [SOF_IPC_TYPE_4] = "sof-wcl.ri", + }, + .nocodec_tplg_filename = "sof-ptl-nocodec.tplg", + .ops = &sof_ptl_ops, + .ops_init = sof_ptl_ops_init, +}; + /* PCI IDs */ static const struct pci_device_id sof_pci_ids[] = { { PCI_DEVICE_DATA(INTEL, HDA_PTL, &ptl_desc) }, /* PTL */ { PCI_DEVICE_DATA(INTEL, HDA_PTL_H, &ptl_desc) }, /* PTL-H */ + { PCI_DEVICE_DATA(INTEL, HDA_WCL, &wcl_desc) }, /* WCL */ { 0, } }; MODULE_DEVICE_TABLE(pci, sof_pci_ids); diff --git a/sound/soc/sof/intel/ptl.c b/sound/soc/sof/intel/ptl.c index 8fa4bdceedd9..875d18193b05 100644 --- a/sound/soc/sof/intel/ptl.c +++ b/sound/soc/sof/intel/ptl.c @@ -27,22 +27,44 @@ static bool sof_ptl_check_mic_privacy_irq(struct snd_sof_dev *sdev, bool alt, return hdac_bus_eml_is_mic_privacy_changed(sof_to_bus(sdev), alt, elid); } +static void sof_ptl_mic_privacy_work(struct work_struct *work) +{ + struct sof_intel_hda_dev *hdev = container_of(work, + struct sof_intel_hda_dev, + mic_privacy.work); + struct hdac_bus *bus = &hdev->hbus.core; + struct snd_sof_dev *sdev = dev_get_drvdata(bus->dev); + bool state; + + /* + * The microphone privacy state is only available via Soundwire shim + * in PTL + * The work is only scheduled on change. + */ + state = hdac_bus_eml_get_mic_privacy_state(bus, 1, + AZX_REG_ML_LEPTR_ID_SDW); + sof_ipc4_mic_privacy_state_change(sdev, state); +} + static void sof_ptl_process_mic_privacy(struct snd_sof_dev *sdev, bool alt, int elid) { - bool state; + struct sof_intel_hda_dev *hdev = sdev->pdata->hw_pdata; if (!alt || elid != AZX_REG_ML_LEPTR_ID_SDW) return; - state = hdac_bus_eml_get_mic_privacy_state(sof_to_bus(sdev), alt, elid); - - sof_ipc4_mic_privacy_state_change(sdev, state); + /* + * Schedule the work to read the microphone privacy state and send IPC + * message about the new state to the firmware + */ + schedule_work(&hdev->mic_privacy.work); } static void sof_ptl_set_mic_privacy(struct snd_sof_dev *sdev, struct sof_ipc4_intel_mic_privacy_cap *caps) { + struct sof_intel_hda_dev *hdev = sdev->pdata->hw_pdata; u32 micpvcp; if (!caps || !caps->capabilities_length) @@ -58,6 +80,9 @@ static void sof_ptl_set_mic_privacy(struct snd_sof_dev *sdev, hdac_bus_eml_set_mic_privacy_mask(sof_to_bus(sdev), true, AZX_REG_ML_LEPTR_ID_SDW, PTL_MICPVCP_GET_SDW_MASK(micpvcp)); + + INIT_WORK(&hdev->mic_privacy.work, sof_ptl_mic_privacy_work); + hdev->mic_privacy.active = true; } int sof_ptl_set_ops(struct snd_sof_dev *sdev, struct snd_sof_dsp_ops *dsp_ops) @@ -101,6 +126,29 @@ const struct sof_intel_dsp_desc ptl_chip_info = { .hw_ip_version = SOF_INTEL_ACE_3_0, }; +const struct sof_intel_dsp_desc wcl_chip_info = { + .cores_num = 3, + .init_core_mask = BIT(0), + .host_managed_cores_mask = BIT(0), + .ipc_req = MTL_DSP_REG_HFIPCXIDR, + .ipc_req_mask = MTL_DSP_REG_HFIPCXIDR_BUSY, + .ipc_ack = MTL_DSP_REG_HFIPCXIDA, + .ipc_ack_mask = MTL_DSP_REG_HFIPCXIDA_DONE, + .ipc_ctl = MTL_DSP_REG_HFIPCXCTL, + .rom_status_reg = LNL_DSP_REG_HFDSC, + .rom_init_timeout = 300, + .ssp_count = MTL_SSP_COUNT, + .d0i3_offset = MTL_HDA_VS_D0I3C, + .read_sdw_lcount = hda_sdw_check_lcount_ext, + .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, + .disable_interrupts = lnl_dsp_disable_interrupts, + .hw_ip_version = SOF_INTEL_ACE_3_0, +}; + MODULE_IMPORT_NS("SND_SOC_SOF_INTEL_MTL"); MODULE_IMPORT_NS("SND_SOC_SOF_INTEL_LNL"); MODULE_IMPORT_NS("SND_SOC_SOF_HDA_MLINK"); |