From: Mark Brown Date: Fri, 23 Sep 2022 19:46:25 +0000 (+0100) Subject: ASoC: SOF: ipc4/Intel: Improve and enable IPC error dump X-Git-Url: http://git.maquefel.me/?a=commitdiff_plain;h=e9b0ff9336850863e608c2df0dde512adecb4a20;p=linux.git ASoC: SOF: ipc4/Intel: Improve and enable IPC error dump Merge series from Peter Ujfalusi : On Intel platforms the registers for DSP communications are used differently, the IPC dump information is not correct since important registers are not printed and existing ones are used a bit differently for IPC4. As a last step, enable the IPC timeout 'handling' and allow the printout of the now usefull IPC dump. --- e9b0ff9336850863e608c2df0dde512adecb4a20 diff --cc sound/soc/sof/intel/mtl.c index 27ec171cb586a,61bcaa1556f63..10298532816fe --- a/sound/soc/sof/intel/mtl.c +++ b/sound/soc/sof/intel/mtl.c @@@ -571,30 -552,167 +571,29 @@@ static int mtl_dsp_ipc_get_window_offse return MTL_SRAM_WINDOW_OFFSET(id); } -static int mtl_suspend(struct snd_sof_dev *sdev, bool runtime_suspend) -{ - struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata; - const struct sof_intel_dsp_desc *chip = hda->desc; -#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) - struct hdac_bus *bus = sof_to_bus(sdev); -#endif - u32 dsphfdsscs; - u32 cpa; - int ret; - int i; - - mtl_disable_ipc_interrupts(sdev); - ret = mtl_disable_interrupts(sdev); - if (ret) - return ret; - -#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) - hda_codec_jack_wake_enable(sdev, runtime_suspend); - /* power down all hda link */ - snd_hdac_ext_bus_link_power_down_all(bus); -#endif - snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, MTL_HFPWRCTL, - MTL_HFPWRCTL_WPDSPHPXPG, 0); - - /* Set the DSP subsystem power down */ - snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, MTL_HFDSSCS, - MTL_HFDSSCS_SPA_MASK, 0); - - /* Wait for unstable CPA read (1 then 0 then 1) just after setting SPA bit */ - usleep_range(1000, 1010); - - /* poll with timeout to check if operation successful */ - cpa = MTL_HFDSSCS_CPA_MASK; - dsphfdsscs = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_HFDSSCS); - ret = snd_sof_dsp_read_poll_timeout(sdev, HDA_DSP_BAR, MTL_HFDSSCS, dsphfdsscs, - (dsphfdsscs & cpa) == 0, HDA_DSP_REG_POLL_INTERVAL_US, - HDA_DSP_RESET_TIMEOUT_US); - if (ret < 0) - dev_err(sdev->dev, "failed to disable DSP subsystem\n"); - - /* reset ref counts for all cores */ - for (i = 0; i < chip->cores_num; i++) - sdev->dsp_core_ref_count[i] = 0; - - /* TODO: need to reset controller? */ - - /* display codec can be powered off after link reset */ - hda_codec_i915_display_power(sdev, false); - - return 0; -} - -static int mtl_dsp_suspend(struct snd_sof_dev *sdev, u32 target_state) -{ - const struct sof_dsp_power_state target_dsp_state = { - .state = target_state, - .substate = target_state == SOF_DSP_PM_D0 ? - SOF_HDA_DSP_PM_D0I3 : 0, - }; - int ret; - - ret = mtl_suspend(sdev, false); - if (ret < 0) - return ret; - - return snd_sof_dsp_set_power_state(sdev, &target_dsp_state); -} - -static int mtl_dsp_runtime_suspend(struct snd_sof_dev *sdev) -{ - const struct sof_dsp_power_state target_state = { - .state = SOF_DSP_PM_D3, - }; - int ret; - - ret = mtl_suspend(sdev, true); - if (ret < 0) - return ret; - - return snd_sof_dsp_set_power_state(sdev, &target_state); -} - -static int mtl_resume(struct snd_sof_dev *sdev, bool runtime_resume) -{ -#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) - struct hdac_bus *bus = sof_to_bus(sdev); - struct hdac_ext_link *hlink = NULL; -#endif - - /* display codec must be powered before link reset */ - hda_codec_i915_display_power(sdev, true); - -#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) - /* check jack status */ - if (runtime_resume) { - hda_codec_jack_wake_enable(sdev, false); - if (sdev->system_suspend_target == SOF_SUSPEND_NONE) - hda_codec_jack_check(sdev); - } - - /* turn off the links that were off before suspend */ - list_for_each_entry(hlink, &bus->hlink_list, list) { - if (!hlink->ref_count) - snd_hdac_ext_bus_link_power_down(hlink); - } - - /* check dma status and clean up CORB/RIRB buffers */ - if (!bus->cmd_dma_state) - snd_hdac_bus_stop_cmd_io(bus); -#endif - - return 0; -} - -static int mtl_dsp_resume(struct snd_sof_dev *sdev) -{ - const struct sof_dsp_power_state target_state = { - .state = SOF_DSP_PM_D0, - .substate = SOF_HDA_DSP_PM_D0I0, - }; - int ret; - - ret = mtl_resume(sdev, false); - if (ret < 0) - return ret; - - return snd_sof_dsp_set_power_state(sdev, &target_state); -} - -static int mtl_dsp_runtime_resume(struct snd_sof_dev *sdev) -{ - const struct sof_dsp_power_state target_state = { - .state = SOF_DSP_PM_D0, - }; - int ret; - - ret = mtl_resume(sdev, true); - if (ret < 0) - return ret; - - return snd_sof_dsp_set_power_state(sdev, &target_state); -} - static void mtl_ipc_dump(struct snd_sof_dev *sdev) { - u32 hipcctl; - u32 hipcida; - u32 hipctdr; + u32 hipcidr, hipcidd, hipcida, hipctdr, hipctdd, hipctda, hipcctl; - /* read IPC status */ + hipcidr = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_DSP_REG_HFIPCXIDR); + hipcidd = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_DSP_REG_HFIPCXIDDY); hipcida = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_DSP_REG_HFIPCXIDA); - hipcctl = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_DSP_REG_HFIPCXCTL); hipctdr = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_DSP_REG_HFIPCXTDR); + hipctdd = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_DSP_REG_HFIPCXTDDY); + hipctda = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_DSP_REG_HFIPCXTDA); + hipcctl = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_DSP_REG_HFIPCXCTL); - /* dump the IPC regs */ - /* TODO: parse the raw msg */ dev_err(sdev->dev, - "error: host status 0x%8.8x dsp status 0x%8.8x mask 0x%8.8x\n", - hipcida, hipctdr, hipcctl); + "Host IPC initiator: %#x|%#x|%#x, target: %#x|%#x|%#x, ctl: %#x\n", + hipcidr, hipcidd, hipcida, hipctdr, hipctdd, hipctda, hipcctl); } +static int mtl_dsp_disable_interrupts(struct snd_sof_dev *sdev) +{ + mtl_disable_ipc_interrupts(sdev); + return mtl_disable_interrupts(sdev); +} + /* Meteorlake ops */ struct snd_sof_dsp_ops sof_mtl_ops; EXPORT_SYMBOL_NS(sof_mtl_ops, SND_SOC_SOF_INTEL_HDA_COMMON);