diff options
Diffstat (limited to 'sound/soc/sof/intel/mtl.c')
-rw-r--r-- | sound/soc/sof/intel/mtl.c | 87 |
1 files changed, 64 insertions, 23 deletions
diff --git a/sound/soc/sof/intel/mtl.c b/sound/soc/sof/intel/mtl.c index 060c34988e90..1bf274509ee6 100644 --- a/sound/soc/sof/intel/mtl.c +++ b/sound/soc/sof/intel/mtl.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) // -// Copyright(c) 2022 Intel Corporation. All rights reserved. +// Copyright(c) 2022 Intel Corporation // // Authors: Ranjani Sridharan <ranjani.sridharan@linux.intel.com> // @@ -9,6 +9,7 @@ * Hardware interface for audio DSP on Meteorlake. */ +#include <linux/debugfs.h> #include <linux/firmware.h> #include <sound/sof/ipc4/header.h> #include <trace/events/sof_intel.h> @@ -24,6 +25,7 @@ static const struct snd_sof_debugfs_map mtl_dsp_debugfs[] = { {"hda", HDA_DSP_HDA_BAR, 0, 0x4000, SOF_DEBUGFS_ACCESS_ALWAYS}, {"pp", HDA_DSP_PP_BAR, 0, 0x1000, SOF_DEBUGFS_ACCESS_ALWAYS}, {"dsp", HDA_DSP_BAR, 0, 0x10000, SOF_DEBUGFS_ACCESS_ALWAYS}, + {"fw_regs", HDA_DSP_BAR, MTL_SRAM_WINDOW_OFFSET(0), 0x1000, SOF_DEBUGFS_ACCESS_D0_ONLY}, }; static void mtl_ipc_host_done(struct snd_sof_dev *sdev) @@ -75,6 +77,7 @@ bool mtl_dsp_check_ipc_irq(struct snd_sof_dev *sdev) return false; } +EXPORT_SYMBOL_NS(mtl_dsp_check_ipc_irq, SND_SOC_SOF_INTEL_MTL); /* Check if an SDW IRQ occurred */ static bool mtl_dsp_check_sdw_irq(struct snd_sof_dev *sdev) @@ -118,6 +121,7 @@ int mtl_ipc_send_msg(struct snd_sof_dev *sdev, struct snd_sof_ipc_msg *msg) return 0; } +EXPORT_SYMBOL_NS(mtl_ipc_send_msg, SND_SOC_SOF_INTEL_MTL); void mtl_enable_ipc_interrupts(struct snd_sof_dev *sdev) { @@ -145,6 +149,7 @@ void mtl_disable_ipc_interrupts(struct snd_sof_dev *sdev) snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, chip->ipc_ctl, MTL_DSP_REG_HFIPCXCTL_BUSY | MTL_DSP_REG_HFIPCXCTL_DONE, 0); } +EXPORT_SYMBOL_NS(mtl_disable_ipc_interrupts, SND_SOC_SOF_INTEL_MTL); static void mtl_enable_sdw_irq(struct snd_sof_dev *sdev, bool enable) { @@ -229,6 +234,7 @@ int mtl_enable_interrupts(struct snd_sof_dev *sdev, bool enable) return ret; } +EXPORT_SYMBOL_NS(mtl_enable_interrupts, SND_SOC_SOF_INTEL_MTL); /* pre fw run operations */ int mtl_dsp_pre_fw_run(struct snd_sof_dev *sdev) @@ -279,6 +285,7 @@ int mtl_dsp_pre_fw_run(struct snd_sof_dev *sdev) return ret; } +EXPORT_SYMBOL_NS(mtl_dsp_pre_fw_run, SND_SOC_SOF_INTEL_MTL); int mtl_dsp_post_fw_run(struct snd_sof_dev *sdev) { @@ -294,36 +301,36 @@ int mtl_dsp_post_fw_run(struct snd_sof_dev *sdev) } /* Check if IMR boot is usable */ - if (!sof_debug_check_flag(SOF_DBG_IGNORE_D3_PERSISTENT)) + if (!sof_debug_check_flag(SOF_DBG_IGNORE_D3_PERSISTENT)) { hdev->imrboot_supported = true; + debugfs_create_bool("skip_imr_boot", + 0644, sdev->debugfs_root, + &hdev->skip_imr_boot); + } } hda_sdw_int_enable(sdev, true); return 0; } +EXPORT_SYMBOL_NS(mtl_dsp_post_fw_run, SND_SOC_SOF_INTEL_MTL); void mtl_dsp_dump(struct snd_sof_dev *sdev, u32 flags) { char *level = (flags & SOF_DBG_DUMP_OPTIONAL) ? KERN_DEBUG : KERN_ERR; - u32 romdbgsts; - u32 romdbgerr; u32 fwsts; u32 fwlec; + hda_dsp_get_state(sdev, level); fwsts = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_DSP_ROM_STS); fwlec = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_DSP_ROM_ERROR); - romdbgsts = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_DSP_REG_HFFLGPXQWY); - romdbgerr = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_DSP_REG_HFFLGPXQWY_ERROR); - dev_err(sdev->dev, "ROM status: %#x, ROM error: %#x\n", fwsts, fwlec); - dev_err(sdev->dev, "ROM debug status: %#x, ROM debug error: %#x\n", romdbgsts, - romdbgerr); - romdbgsts = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_DSP_REG_HFFLGPXQWY + 0x8 * 3); - dev_printk(level, sdev->dev, "ROM feature bit%s enabled\n", - romdbgsts & BIT(24) ? "" : " not"); + if (fwsts != 0xffffffff) + dev_err(sdev->dev, "Firmware state: %#x, status/error code: %#x\n", + fwsts, fwlec); sof_ipc4_intel_dump_telemetry_state(sdev, flags); } +EXPORT_SYMBOL_NS(mtl_dsp_dump, SND_SOC_SOF_INTEL_MTL); static bool mtl_dsp_primary_core_is_enabled(struct snd_sof_dev *sdev) { @@ -434,12 +441,13 @@ int mtl_power_down_dsp(struct snd_sof_dev *sdev) (dsphfdsscs & cpa) == 0, HDA_DSP_REG_POLL_INTERVAL_US, HDA_DSP_RESET_TIMEOUT_US); } +EXPORT_SYMBOL_NS(mtl_power_down_dsp, SND_SOC_SOF_INTEL_MTL); int mtl_dsp_cl_init(struct snd_sof_dev *sdev, int stream_tag, bool imr_boot) { struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata; const struct sof_intel_dsp_desc *chip = hda->desc; - unsigned int status; + unsigned int status, target_status; u32 ipc_hdr, flags; char *dump_msg; int ret; @@ -485,13 +493,40 @@ int mtl_dsp_cl_init(struct snd_sof_dev *sdev, int stream_tag, bool imr_boot) mtl_enable_ipc_interrupts(sdev); + if (chip->rom_status_reg == MTL_DSP_ROM_STS) { + /* + * Workaround: when the ROM status register is pointing to + * the SRAM window (MTL_DSP_ROM_STS) the platform cannot catch + * ROM_INIT_DONE because of a very short timing window. + * Follow the recommendations and skip target state waiting. + */ + return 0; + } + /* - * ACE workaround: don't wait for ROM INIT. - * The platform cannot catch ROM_INIT_DONE because of a very short - * timing window. Follow the recommendations and skip this part. + * step 7: + * - Cold/Full boot: wait for ROM init to proceed to download the firmware + * - IMR boot: wait for ROM firmware entered (firmware booted up from IMR) */ + if (imr_boot) + target_status = FSR_STATE_FW_ENTERED; + else + target_status = FSR_STATE_INIT_DONE; - return 0; + ret = snd_sof_dsp_read_poll_timeout(sdev, HDA_DSP_BAR, + chip->rom_status_reg, status, + (FSR_TO_STATE_CODE(status) == target_status), + HDA_DSP_REG_POLL_INTERVAL_US, + chip->rom_init_timeout * + USEC_PER_MSEC); + + if (!ret) + return 0; + + if (hda->boot_iteration == HDA_FW_BOOT_ATTEMPTS) + dev_err(sdev->dev, + "%s: timeout with rom_status_reg (%#x) read\n", + __func__, chip->rom_status_reg); err: flags = SOF_DBG_DUMP_PCI | SOF_DBG_DUMP_MBOX | SOF_DBG_DUMP_OPTIONAL; @@ -503,11 +538,13 @@ err: dump_msg = kasprintf(GFP_KERNEL, "Boot iteration failed: %d/%d", hda->boot_iteration, HDA_FW_BOOT_ATTEMPTS); snd_sof_dsp_dbg_dump(sdev, dump_msg, flags); + mtl_enable_interrupts(sdev, false); mtl_dsp_core_power_down(sdev, SOF_DSP_PRIMARY_CORE); kfree(dump_msg); return ret; } +EXPORT_SYMBOL_NS(mtl_dsp_cl_init, SND_SOC_SOF_INTEL_MTL); irqreturn_t mtl_ipc_irq_thread(int irq, void *context) { @@ -591,16 +628,19 @@ irqreturn_t mtl_ipc_irq_thread(int irq, void *context) return IRQ_HANDLED; } +EXPORT_SYMBOL_NS(mtl_ipc_irq_thread, SND_SOC_SOF_INTEL_MTL); int mtl_dsp_ipc_get_mailbox_offset(struct snd_sof_dev *sdev) { return MTL_DSP_MBOX_UPLINK_OFFSET; } +EXPORT_SYMBOL_NS(mtl_dsp_ipc_get_mailbox_offset, SND_SOC_SOF_INTEL_MTL); int mtl_dsp_ipc_get_window_offset(struct snd_sof_dev *sdev, u32 id) { return MTL_SRAM_WINDOW_OFFSET(id); } +EXPORT_SYMBOL_NS(mtl_dsp_ipc_get_window_offset, SND_SOC_SOF_INTEL_MTL); void mtl_ipc_dump(struct snd_sof_dev *sdev) { @@ -618,6 +658,7 @@ void mtl_ipc_dump(struct snd_sof_dev *sdev) "Host IPC initiator: %#x|%#x|%#x, target: %#x|%#x|%#x, ctl: %#x\n", hipcidr, hipcidd, hipcida, hipctdr, hipctdd, hipctda, hipcctl); } +EXPORT_SYMBOL_NS(mtl_ipc_dump, SND_SOC_SOF_INTEL_MTL); static int mtl_dsp_disable_interrupts(struct snd_sof_dev *sdev) { @@ -638,6 +679,7 @@ int mtl_dsp_core_get(struct snd_sof_dev *sdev, int core) return 0; } +EXPORT_SYMBOL_NS(mtl_dsp_core_get, SND_SOC_SOF_INTEL_MTL); int mtl_dsp_core_put(struct snd_sof_dev *sdev, int core) { @@ -655,10 +697,10 @@ int mtl_dsp_core_put(struct snd_sof_dev *sdev, int core) return 0; } +EXPORT_SYMBOL_NS(mtl_dsp_core_put, SND_SOC_SOF_INTEL_MTL); /* Meteorlake ops */ struct snd_sof_dsp_ops sof_mtl_ops; -EXPORT_SYMBOL_NS(sof_mtl_ops, SND_SOC_SOF_INTEL_HDA_COMMON); int sof_mtl_ops_init(struct snd_sof_dev *sdev) { @@ -716,7 +758,6 @@ int sof_mtl_ops_init(struct snd_sof_dev *sdev) return 0; }; -EXPORT_SYMBOL_NS(sof_mtl_ops_init, SND_SOC_SOF_INTEL_HDA_COMMON); const struct sof_intel_dsp_desc mtl_chip_info = { .cores_num = 3, @@ -727,7 +768,7 @@ const struct sof_intel_dsp_desc mtl_chip_info = { .ipc_ack = MTL_DSP_REG_HFIPCXIDA, .ipc_ack_mask = MTL_DSP_REG_HFIPCXIDA_DONE, .ipc_ctl = MTL_DSP_REG_HFIPCXCTL, - .rom_status_reg = MTL_DSP_ROM_STS, + .rom_status_reg = MTL_DSP_REG_HFFLGPXQWY, .rom_init_timeout = 300, .ssp_count = MTL_SSP_COUNT, .ssp_base_offset = CNL_SSP_BASE_OFFSET, @@ -738,13 +779,13 @@ const struct sof_intel_dsp_desc mtl_chip_info = { .enable_sdw_irq = mtl_enable_sdw_irq, .check_sdw_irq = mtl_dsp_check_sdw_irq, .check_sdw_wakeen_irq = hda_sdw_check_wakeen_irq_common, + .sdw_process_wakeen = hda_sdw_process_wakeen_common, .check_ipc_irq = mtl_dsp_check_ipc_irq, .cl_init = mtl_dsp_cl_init, .power_down_dsp = mtl_power_down_dsp, .disable_interrupts = mtl_dsp_disable_interrupts, .hw_ip_version = SOF_INTEL_ACE_1_0, }; -EXPORT_SYMBOL_NS(mtl_chip_info, SND_SOC_SOF_INTEL_HDA_COMMON); const struct sof_intel_dsp_desc arl_s_chip_info = { .cores_num = 2, @@ -755,7 +796,7 @@ const struct sof_intel_dsp_desc arl_s_chip_info = { .ipc_ack = MTL_DSP_REG_HFIPCXIDA, .ipc_ack_mask = MTL_DSP_REG_HFIPCXIDA_DONE, .ipc_ctl = MTL_DSP_REG_HFIPCXCTL, - .rom_status_reg = MTL_DSP_ROM_STS, + .rom_status_reg = MTL_DSP_REG_HFFLGPXQWY, .rom_init_timeout = 300, .ssp_count = MTL_SSP_COUNT, .ssp_base_offset = CNL_SSP_BASE_OFFSET, @@ -766,10 +807,10 @@ const struct sof_intel_dsp_desc arl_s_chip_info = { .enable_sdw_irq = mtl_enable_sdw_irq, .check_sdw_irq = mtl_dsp_check_sdw_irq, .check_sdw_wakeen_irq = hda_sdw_check_wakeen_irq_common, + .sdw_process_wakeen = hda_sdw_process_wakeen_common, .check_ipc_irq = mtl_dsp_check_ipc_irq, .cl_init = mtl_dsp_cl_init, .power_down_dsp = mtl_power_down_dsp, .disable_interrupts = mtl_dsp_disable_interrupts, .hw_ip_version = SOF_INTEL_ACE_1_0, }; -EXPORT_SYMBOL_NS(arl_s_chip_info, SND_SOC_SOF_INTEL_HDA_COMMON); |