1064520e8SBard Liao // SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) 2064520e8SBard Liao // 3064520e8SBard Liao // Copyright(c) 2022 Intel Corporation. All rights reserved. 4064520e8SBard Liao // 5064520e8SBard Liao // Authors: Ranjani Sridharan <ranjani.sridharan@linux.intel.com> 6064520e8SBard Liao // 7064520e8SBard Liao 8064520e8SBard Liao /* 9064520e8SBard Liao * Hardware interface for audio DSP on Meteorlake. 10064520e8SBard Liao */ 11064520e8SBard Liao 12064520e8SBard Liao #include <linux/firmware.h> 13064520e8SBard Liao #include <sound/sof/ipc4/header.h> 14d272b657SBard Liao #include <trace/events/sof_intel.h> 15064520e8SBard Liao #include "../ipc4-priv.h" 16064520e8SBard Liao #include "../ops.h" 17064520e8SBard Liao #include "hda.h" 18064520e8SBard Liao #include "hda-ipc.h" 19064520e8SBard Liao #include "../sof-audio.h" 20064520e8SBard Liao #include "mtl.h" 21064520e8SBard Liao 22064520e8SBard Liao static const struct snd_sof_debugfs_map mtl_dsp_debugfs[] = { 23064520e8SBard Liao {"hda", HDA_DSP_HDA_BAR, 0, 0x4000, SOF_DEBUGFS_ACCESS_ALWAYS}, 24064520e8SBard Liao {"pp", HDA_DSP_PP_BAR, 0, 0x1000, SOF_DEBUGFS_ACCESS_ALWAYS}, 25064520e8SBard Liao {"dsp", HDA_DSP_BAR, 0, 0x10000, SOF_DEBUGFS_ACCESS_ALWAYS}, 26064520e8SBard Liao }; 27064520e8SBard Liao 28064520e8SBard Liao static void mtl_ipc_host_done(struct snd_sof_dev *sdev) 29064520e8SBard Liao { 30064520e8SBard Liao /* 31064520e8SBard Liao * clear busy interrupt to tell dsp controller this interrupt has been accepted, 32064520e8SBard Liao * not trigger it again 33064520e8SBard Liao */ 34064520e8SBard Liao snd_sof_dsp_update_bits_forced(sdev, HDA_DSP_BAR, MTL_DSP_REG_HFIPCXTDR, 35064520e8SBard Liao MTL_DSP_REG_HFIPCXTDR_BUSY, MTL_DSP_REG_HFIPCXTDR_BUSY); 36064520e8SBard Liao /* 37064520e8SBard Liao * clear busy bit to ack dsp the msg has been processed and send reply msg to dsp 38064520e8SBard Liao */ 39064520e8SBard Liao snd_sof_dsp_update_bits_forced(sdev, HDA_DSP_BAR, MTL_DSP_REG_HFIPCXTDA, 40064520e8SBard Liao MTL_DSP_REG_HFIPCXTDA_BUSY, 0); 41064520e8SBard Liao } 42064520e8SBard Liao 43064520e8SBard Liao static void mtl_ipc_dsp_done(struct snd_sof_dev *sdev) 44064520e8SBard Liao { 45064520e8SBard Liao /* 46064520e8SBard Liao * set DONE bit - tell DSP we have received the reply msg from DSP, and processed it, 47064520e8SBard Liao * don't send more reply to host 48064520e8SBard Liao */ 49064520e8SBard Liao snd_sof_dsp_update_bits_forced(sdev, HDA_DSP_BAR, MTL_DSP_REG_HFIPCXIDA, 50064520e8SBard Liao MTL_DSP_REG_HFIPCXIDA_DONE, MTL_DSP_REG_HFIPCXIDA_DONE); 51064520e8SBard Liao 52064520e8SBard Liao /* unmask Done interrupt */ 53064520e8SBard Liao snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, MTL_DSP_REG_HFIPCXCTL, 54064520e8SBard Liao MTL_DSP_REG_HFIPCXCTL_DONE, MTL_DSP_REG_HFIPCXCTL_DONE); 55064520e8SBard Liao } 56064520e8SBard Liao 57064520e8SBard Liao /* Check if an IPC IRQ occurred */ 58064520e8SBard Liao static bool mtl_dsp_check_ipc_irq(struct snd_sof_dev *sdev) 59064520e8SBard Liao { 60064520e8SBard Liao u32 irq_status; 61064520e8SBard Liao u32 hfintipptr; 62064520e8SBard Liao 63064520e8SBard Liao /* read Interrupt IP Pointer */ 64064520e8SBard Liao hfintipptr = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_HFINTIPPTR) & MTL_HFINTIPPTR_PTR_MASK; 65064520e8SBard Liao irq_status = snd_sof_dsp_read(sdev, HDA_DSP_BAR, hfintipptr + MTL_DSP_IRQSTS); 66064520e8SBard Liao 67d272b657SBard Liao trace_sof_intel_hda_irq_ipc_check(sdev, irq_status); 68064520e8SBard Liao 69064520e8SBard Liao if (irq_status != U32_MAX && (irq_status & MTL_DSP_IRQSTS_IPC)) 70064520e8SBard Liao return true; 71064520e8SBard Liao 72064520e8SBard Liao return false; 73064520e8SBard Liao } 74064520e8SBard Liao 75064520e8SBard Liao /* Check if an SDW IRQ occurred */ 76064520e8SBard Liao static bool mtl_dsp_check_sdw_irq(struct snd_sof_dev *sdev) 77064520e8SBard Liao { 78064520e8SBard Liao u32 irq_status; 79064520e8SBard Liao u32 hfintipptr; 80064520e8SBard Liao 81064520e8SBard Liao /* read Interrupt IP Pointer */ 82064520e8SBard Liao hfintipptr = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_HFINTIPPTR) & MTL_HFINTIPPTR_PTR_MASK; 83064520e8SBard Liao irq_status = snd_sof_dsp_read(sdev, HDA_DSP_BAR, hfintipptr + MTL_DSP_IRQSTS); 84064520e8SBard Liao 85064520e8SBard Liao if (irq_status != U32_MAX && (irq_status & MTL_DSP_IRQSTS_SDW)) 86064520e8SBard Liao return true; 87064520e8SBard Liao 88064520e8SBard Liao return false; 89064520e8SBard Liao } 90064520e8SBard Liao 91064520e8SBard Liao static int mtl_ipc_send_msg(struct snd_sof_dev *sdev, struct snd_sof_ipc_msg *msg) 92064520e8SBard Liao { 93064520e8SBard Liao struct sof_ipc4_msg *msg_data = msg->msg_data; 94064520e8SBard Liao 95064520e8SBard Liao /* send the message via mailbox */ 96064520e8SBard Liao if (msg_data->data_size) 97064520e8SBard Liao sof_mailbox_write(sdev, sdev->host_box.offset, msg_data->data_ptr, 98064520e8SBard Liao msg_data->data_size); 99064520e8SBard Liao 100064520e8SBard Liao snd_sof_dsp_write(sdev, HDA_DSP_BAR, MTL_DSP_REG_HFIPCXIDDY, 101064520e8SBard Liao msg_data->extension); 102064520e8SBard Liao snd_sof_dsp_write(sdev, HDA_DSP_BAR, MTL_DSP_REG_HFIPCXIDR, 103064520e8SBard Liao msg_data->primary | MTL_DSP_REG_HFIPCXIDR_BUSY); 104064520e8SBard Liao 105064520e8SBard Liao return 0; 106064520e8SBard Liao } 107064520e8SBard Liao 108064520e8SBard Liao static void mtl_enable_ipc_interrupts(struct snd_sof_dev *sdev) 109064520e8SBard Liao { 110064520e8SBard Liao struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata; 111064520e8SBard Liao const struct sof_intel_dsp_desc *chip = hda->desc; 112064520e8SBard Liao 113064520e8SBard Liao /* enable IPC DONE and BUSY interrupts */ 114064520e8SBard Liao snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, chip->ipc_ctl, 115064520e8SBard Liao MTL_DSP_REG_HFIPCXCTL_BUSY | MTL_DSP_REG_HFIPCXCTL_DONE, 116064520e8SBard Liao MTL_DSP_REG_HFIPCXCTL_BUSY | MTL_DSP_REG_HFIPCXCTL_DONE); 117064520e8SBard Liao } 118064520e8SBard Liao 119064520e8SBard Liao static void mtl_disable_ipc_interrupts(struct snd_sof_dev *sdev) 120064520e8SBard Liao { 121064520e8SBard Liao struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata; 122064520e8SBard Liao const struct sof_intel_dsp_desc *chip = hda->desc; 123064520e8SBard Liao 124064520e8SBard Liao /* disable IPC DONE and BUSY interrupts */ 125064520e8SBard Liao snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, chip->ipc_ctl, 126064520e8SBard Liao MTL_DSP_REG_HFIPCXCTL_BUSY | MTL_DSP_REG_HFIPCXCTL_DONE, 0); 127064520e8SBard Liao } 128064520e8SBard Liao 129064520e8SBard Liao static int mtl_enable_interrupts(struct snd_sof_dev *sdev) 130064520e8SBard Liao { 131064520e8SBard Liao u32 hfintipptr; 132064520e8SBard Liao u32 irqinten; 133064520e8SBard Liao u32 host_ipc; 134064520e8SBard Liao u32 hipcie; 135064520e8SBard Liao int ret; 136064520e8SBard Liao 137064520e8SBard Liao /* read Interrupt IP Pointer */ 138064520e8SBard Liao hfintipptr = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_HFINTIPPTR) & MTL_HFINTIPPTR_PTR_MASK; 139064520e8SBard Liao 140064520e8SBard Liao /* Enable Host IPC and SOUNDWIRE */ 141064520e8SBard Liao snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, hfintipptr, 142064520e8SBard Liao MTL_IRQ_INTEN_L_HOST_IPC_MASK | MTL_IRQ_INTEN_L_SOUNDWIRE_MASK, 143064520e8SBard Liao MTL_IRQ_INTEN_L_HOST_IPC_MASK | MTL_IRQ_INTEN_L_SOUNDWIRE_MASK); 144064520e8SBard Liao 145064520e8SBard Liao /* check if operation was successful */ 146064520e8SBard Liao host_ipc = MTL_IRQ_INTEN_L_HOST_IPC_MASK | MTL_IRQ_INTEN_L_SOUNDWIRE_MASK; 147064520e8SBard Liao ret = snd_sof_dsp_read_poll_timeout(sdev, HDA_DSP_BAR, hfintipptr, irqinten, 148064520e8SBard Liao (irqinten & host_ipc) == host_ipc, 149064520e8SBard Liao HDA_DSP_REG_POLL_INTERVAL_US, HDA_DSP_RESET_TIMEOUT_US); 150064520e8SBard Liao if (ret < 0) { 151064520e8SBard Liao dev_err(sdev->dev, "failed to enable Host IPC and/or SOUNDWIRE\n"); 152064520e8SBard Liao return ret; 153064520e8SBard Liao } 154064520e8SBard Liao 155064520e8SBard Liao /* Set Host IPC interrupt enable */ 156064520e8SBard Liao snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, MTL_DSP_REG_HfHIPCIE, 157064520e8SBard Liao MTL_DSP_REG_HfHIPCIE_IE_MASK, MTL_DSP_REG_HfHIPCIE_IE_MASK); 158064520e8SBard Liao 159064520e8SBard Liao /* check if operation was successful */ 160064520e8SBard Liao host_ipc = MTL_DSP_REG_HfHIPCIE_IE_MASK; 161064520e8SBard Liao ret = snd_sof_dsp_read_poll_timeout(sdev, HDA_DSP_BAR, MTL_DSP_REG_HfHIPCIE, hipcie, 162064520e8SBard Liao (hipcie & host_ipc) == host_ipc, 163064520e8SBard Liao HDA_DSP_REG_POLL_INTERVAL_US, HDA_DSP_RESET_TIMEOUT_US); 164064520e8SBard Liao if (ret < 0) { 165064520e8SBard Liao dev_err(sdev->dev, "failed to set Host IPC interrupt enable\n"); 166064520e8SBard Liao return ret; 167064520e8SBard Liao } 168064520e8SBard Liao 169064520e8SBard Liao snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, MTL_DSP_REG_HfSNDWIE, 170064520e8SBard Liao MTL_DSP_REG_HfSNDWIE_IE_MASK, MTL_DSP_REG_HfSNDWIE_IE_MASK); 171064520e8SBard Liao host_ipc = MTL_DSP_REG_HfSNDWIE_IE_MASK; 172064520e8SBard Liao ret = snd_sof_dsp_read_poll_timeout(sdev, HDA_DSP_BAR, MTL_DSP_REG_HfSNDWIE, hipcie, 173064520e8SBard Liao (hipcie & host_ipc) == host_ipc, 174064520e8SBard Liao HDA_DSP_REG_POLL_INTERVAL_US, HDA_DSP_RESET_TIMEOUT_US); 175064520e8SBard Liao if (ret < 0) 176064520e8SBard Liao dev_err(sdev->dev, "failed to set SoundWire IPC interrupt enable\n"); 177064520e8SBard Liao 178064520e8SBard Liao return ret; 179064520e8SBard Liao } 180064520e8SBard Liao 181064520e8SBard Liao static int mtl_disable_interrupts(struct snd_sof_dev *sdev) 182064520e8SBard Liao { 183064520e8SBard Liao u32 hfintipptr; 184064520e8SBard Liao u32 irqinten; 185064520e8SBard Liao u32 host_ipc; 186064520e8SBard Liao u32 hipcie; 187064520e8SBard Liao int ret1; 188064520e8SBard Liao int ret; 189064520e8SBard Liao 190064520e8SBard Liao /* read Interrupt IP Pointer */ 191064520e8SBard Liao hfintipptr = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_HFINTIPPTR) & MTL_HFINTIPPTR_PTR_MASK; 192064520e8SBard Liao 193064520e8SBard Liao /* Disable Host IPC and SOUNDWIRE */ 194064520e8SBard Liao snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, hfintipptr, 195064520e8SBard Liao MTL_IRQ_INTEN_L_HOST_IPC_MASK | MTL_IRQ_INTEN_L_SOUNDWIRE_MASK, 0); 196064520e8SBard Liao 197064520e8SBard Liao /* check if operation was successful */ 198064520e8SBard Liao host_ipc = MTL_IRQ_INTEN_L_HOST_IPC_MASK | MTL_IRQ_INTEN_L_SOUNDWIRE_MASK; 199064520e8SBard Liao ret = snd_sof_dsp_read_poll_timeout(sdev, HDA_DSP_BAR, hfintipptr, irqinten, 200064520e8SBard Liao (irqinten & host_ipc) == 0, 201064520e8SBard Liao HDA_DSP_REG_POLL_INTERVAL_US, HDA_DSP_RESET_TIMEOUT_US); 202064520e8SBard Liao /* Continue to disable other interrupts when error happens */ 203064520e8SBard Liao if (ret < 0) 204064520e8SBard Liao dev_err(sdev->dev, "failed to disable Host IPC and SoundWire\n"); 205064520e8SBard Liao 206064520e8SBard Liao /* Set Host IPC interrupt disable */ 207064520e8SBard Liao snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, MTL_DSP_REG_HfHIPCIE, 208064520e8SBard Liao MTL_DSP_REG_HfHIPCIE_IE_MASK, 0); 209064520e8SBard Liao 210064520e8SBard Liao /* check if operation was successful */ 211064520e8SBard Liao host_ipc = MTL_DSP_REG_HfHIPCIE_IE_MASK; 212064520e8SBard Liao ret1 = snd_sof_dsp_read_poll_timeout(sdev, HDA_DSP_BAR, MTL_DSP_REG_HfHIPCIE, hipcie, 213064520e8SBard Liao (hipcie & host_ipc) == 0, 214064520e8SBard Liao HDA_DSP_REG_POLL_INTERVAL_US, 215064520e8SBard Liao HDA_DSP_RESET_TIMEOUT_US); 216064520e8SBard Liao if (ret1 < 0) { 217064520e8SBard Liao dev_err(sdev->dev, "failed to set Host IPC interrupt disable\n"); 218064520e8SBard Liao if (!ret) 219064520e8SBard Liao ret = ret1; 220064520e8SBard Liao } 221064520e8SBard Liao 222064520e8SBard Liao /* Set SoundWire IPC interrupt disable */ 223064520e8SBard Liao snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, MTL_DSP_REG_HfSNDWIE, 224064520e8SBard Liao MTL_DSP_REG_HfSNDWIE_IE_MASK, 0); 225064520e8SBard Liao host_ipc = MTL_DSP_REG_HfSNDWIE_IE_MASK; 226064520e8SBard Liao ret1 = snd_sof_dsp_read_poll_timeout(sdev, HDA_DSP_BAR, MTL_DSP_REG_HfSNDWIE, hipcie, 227064520e8SBard Liao (hipcie & host_ipc) == 0, 228064520e8SBard Liao HDA_DSP_REG_POLL_INTERVAL_US, 229064520e8SBard Liao HDA_DSP_RESET_TIMEOUT_US); 230064520e8SBard Liao if (ret1 < 0) { 231064520e8SBard Liao dev_err(sdev->dev, "failed to set SoundWire IPC interrupt disable\n"); 232064520e8SBard Liao if (!ret) 233064520e8SBard Liao ret = ret1; 234064520e8SBard Liao } 235064520e8SBard Liao 236064520e8SBard Liao return ret; 237064520e8SBard Liao } 238064520e8SBard Liao 239064520e8SBard Liao /* pre fw run operations */ 240064520e8SBard Liao static int mtl_dsp_pre_fw_run(struct snd_sof_dev *sdev) 241064520e8SBard Liao { 242064520e8SBard Liao u32 dsphfpwrsts; 243064520e8SBard Liao u32 dsphfdsscs; 244064520e8SBard Liao u32 cpa; 245064520e8SBard Liao u32 pgs; 246064520e8SBard Liao int ret; 247064520e8SBard Liao 248064520e8SBard Liao /* Set the DSP subsystem power on */ 249064520e8SBard Liao snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, MTL_HFDSSCS, 250064520e8SBard Liao MTL_HFDSSCS_SPA_MASK, MTL_HFDSSCS_SPA_MASK); 251064520e8SBard Liao 252064520e8SBard Liao /* Wait for unstable CPA read (1 then 0 then 1) just after setting SPA bit */ 253064520e8SBard Liao usleep_range(1000, 1010); 254064520e8SBard Liao 255064520e8SBard Liao /* poll with timeout to check if operation successful */ 256064520e8SBard Liao cpa = MTL_HFDSSCS_CPA_MASK; 257064520e8SBard Liao ret = snd_sof_dsp_read_poll_timeout(sdev, HDA_DSP_BAR, MTL_HFDSSCS, dsphfdsscs, 258064520e8SBard Liao (dsphfdsscs & cpa) == cpa, HDA_DSP_REG_POLL_INTERVAL_US, 259064520e8SBard Liao HDA_DSP_RESET_TIMEOUT_US); 260064520e8SBard Liao if (ret < 0) { 261064520e8SBard Liao dev_err(sdev->dev, "failed to enable DSP subsystem\n"); 262064520e8SBard Liao return ret; 263064520e8SBard Liao } 264064520e8SBard Liao 265064520e8SBard Liao /* Power up gated-DSP-0 domain in order to access the DSP shim register block. */ 266064520e8SBard Liao snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, MTL_HFPWRCTL, 267064520e8SBard Liao MTL_HFPWRCTL_WPDSPHPXPG, MTL_HFPWRCTL_WPDSPHPXPG); 268064520e8SBard Liao 269064520e8SBard Liao usleep_range(1000, 1010); 270064520e8SBard Liao 271064520e8SBard Liao /* poll with timeout to check if operation successful */ 272064520e8SBard Liao pgs = MTL_HFPWRSTS_DSPHPXPGS_MASK; 273064520e8SBard Liao ret = snd_sof_dsp_read_poll_timeout(sdev, HDA_DSP_BAR, MTL_HFPWRSTS, dsphfpwrsts, 274064520e8SBard Liao (dsphfpwrsts & pgs) == pgs, 275064520e8SBard Liao HDA_DSP_REG_POLL_INTERVAL_US, 276064520e8SBard Liao HDA_DSP_RESET_TIMEOUT_US); 277064520e8SBard Liao if (ret < 0) 278064520e8SBard Liao dev_err(sdev->dev, "failed to power up gated DSP domain\n"); 279064520e8SBard Liao 280064520e8SBard Liao /* make sure SoundWire is not power-gated */ 281064520e8SBard Liao snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, MTL_HFPWRCTL, 282064520e8SBard Liao MTL_HfPWRCTL_WPIOXPG(1), MTL_HfPWRCTL_WPIOXPG(1)); 283064520e8SBard Liao return ret; 284064520e8SBard Liao } 285064520e8SBard Liao 286064520e8SBard Liao static int mtl_dsp_post_fw_run(struct snd_sof_dev *sdev) 287064520e8SBard Liao { 288064520e8SBard Liao int ret; 289064520e8SBard Liao 290064520e8SBard Liao if (sdev->first_boot) { 291064520e8SBard Liao struct sof_intel_hda_dev *hdev = sdev->pdata->hw_pdata; 292064520e8SBard Liao 293064520e8SBard Liao ret = hda_sdw_startup(sdev); 294064520e8SBard Liao if (ret < 0) { 295064520e8SBard Liao dev_err(sdev->dev, "could not startup SoundWire links\n"); 296064520e8SBard Liao return ret; 297064520e8SBard Liao } 298064520e8SBard Liao 299064520e8SBard Liao /* Check if IMR boot is usable */ 300064520e8SBard Liao if (!sof_debug_check_flag(SOF_DBG_IGNORE_D3_PERSISTENT)) 301064520e8SBard Liao hdev->imrboot_supported = true; 302064520e8SBard Liao } 303064520e8SBard Liao 304064520e8SBard Liao hda_sdw_int_enable(sdev, true); 305064520e8SBard Liao return 0; 306064520e8SBard Liao } 307064520e8SBard Liao 308064520e8SBard Liao static void mtl_dsp_dump(struct snd_sof_dev *sdev, u32 flags) 309064520e8SBard Liao { 310064520e8SBard Liao char *level = (flags & SOF_DBG_DUMP_OPTIONAL) ? KERN_DEBUG : KERN_ERR; 311064520e8SBard Liao u32 romdbgsts; 312064520e8SBard Liao u32 romdbgerr; 313064520e8SBard Liao u32 fwsts; 314064520e8SBard Liao u32 fwlec; 315064520e8SBard Liao 316064520e8SBard Liao fwsts = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_DSP_ROM_STS); 317064520e8SBard Liao fwlec = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_DSP_ROM_ERROR); 318064520e8SBard Liao romdbgsts = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_DSP_REG_HFFLGPXQWY); 319064520e8SBard Liao romdbgerr = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_DSP_REG_HFFLGPXQWY_ERROR); 320064520e8SBard Liao 321064520e8SBard Liao dev_err(sdev->dev, "ROM status: %#x, ROM error: %#x\n", fwsts, fwlec); 322064520e8SBard Liao dev_err(sdev->dev, "ROM debug status: %#x, ROM debug error: %#x\n", romdbgsts, 323064520e8SBard Liao romdbgerr); 324064520e8SBard Liao romdbgsts = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_DSP_REG_HFFLGPXQWY + 0x8 * 3); 325064520e8SBard Liao dev_printk(level, sdev->dev, "ROM feature bit%s enabled\n", 326064520e8SBard Liao romdbgsts & BIT(24) ? "" : " not"); 327064520e8SBard Liao } 328064520e8SBard Liao 329064520e8SBard Liao static bool mtl_dsp_primary_core_is_enabled(struct snd_sof_dev *sdev) 330064520e8SBard Liao { 331064520e8SBard Liao int val; 332064520e8SBard Liao 333064520e8SBard Liao val = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_DSP2CXCTL_PRIMARY_CORE); 334064520e8SBard Liao if (val != U32_MAX && val & MTL_DSP2CXCTL_PRIMARY_CORE_CPA_MASK) 335064520e8SBard Liao return true; 336064520e8SBard Liao 337064520e8SBard Liao return false; 338064520e8SBard Liao } 339064520e8SBard Liao 340064520e8SBard Liao static int mtl_dsp_core_power_up(struct snd_sof_dev *sdev, int core) 341064520e8SBard Liao { 342064520e8SBard Liao unsigned int cpa; 343064520e8SBard Liao u32 dspcxctl; 344064520e8SBard Liao int ret; 345064520e8SBard Liao 346064520e8SBard Liao /* Only the primary core can be powered up by the host */ 347064520e8SBard Liao if (core != SOF_DSP_PRIMARY_CORE || mtl_dsp_primary_core_is_enabled(sdev)) 348064520e8SBard Liao return 0; 349064520e8SBard Liao 350064520e8SBard Liao /* Program the owner of the IP & shim registers (10: Host CPU) */ 351064520e8SBard Liao snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, MTL_DSP2CXCTL_PRIMARY_CORE, 352064520e8SBard Liao MTL_DSP2CXCTL_PRIMARY_CORE_OSEL, 353064520e8SBard Liao 0x2 << MTL_DSP2CXCTL_PRIMARY_CORE_OSEL_SHIFT); 354064520e8SBard Liao 355064520e8SBard Liao /* enable SPA bit */ 356064520e8SBard Liao snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, MTL_DSP2CXCTL_PRIMARY_CORE, 357064520e8SBard Liao MTL_DSP2CXCTL_PRIMARY_CORE_SPA_MASK, 358064520e8SBard Liao MTL_DSP2CXCTL_PRIMARY_CORE_SPA_MASK); 359064520e8SBard Liao 360064520e8SBard Liao /* Wait for unstable CPA read (1 then 0 then 1) just after setting SPA bit */ 361064520e8SBard Liao usleep_range(1000, 1010); 362064520e8SBard Liao 363064520e8SBard Liao /* poll with timeout to check if operation successful */ 364064520e8SBard Liao cpa = MTL_DSP2CXCTL_PRIMARY_CORE_CPA_MASK; 365064520e8SBard Liao ret = snd_sof_dsp_read_poll_timeout(sdev, HDA_DSP_BAR, MTL_DSP2CXCTL_PRIMARY_CORE, dspcxctl, 366064520e8SBard Liao (dspcxctl & cpa) == cpa, HDA_DSP_REG_POLL_INTERVAL_US, 367064520e8SBard Liao HDA_DSP_RESET_TIMEOUT_US); 368740e5d87SYong Zhi if (ret < 0) 369064520e8SBard Liao dev_err(sdev->dev, "%s: timeout on MTL_DSP2CXCTL_PRIMARY_CORE read\n", 370064520e8SBard Liao __func__); 371064520e8SBard Liao 372064520e8SBard Liao return ret; 373064520e8SBard Liao } 374064520e8SBard Liao 375064520e8SBard Liao static int mtl_dsp_core_power_down(struct snd_sof_dev *sdev, int core) 376064520e8SBard Liao { 377064520e8SBard Liao u32 dspcxctl; 378064520e8SBard Liao int ret; 379064520e8SBard Liao 380064520e8SBard Liao /* Only the primary core can be powered down by the host */ 381064520e8SBard Liao if (core != SOF_DSP_PRIMARY_CORE || !mtl_dsp_primary_core_is_enabled(sdev)) 382064520e8SBard Liao return 0; 383064520e8SBard Liao 384064520e8SBard Liao /* disable SPA bit */ 385064520e8SBard Liao snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, MTL_DSP2CXCTL_PRIMARY_CORE, 386064520e8SBard Liao MTL_DSP2CXCTL_PRIMARY_CORE_SPA_MASK, 0); 387064520e8SBard Liao 388064520e8SBard Liao /* Wait for unstable CPA read (1 then 0 then 1) just after setting SPA bit */ 389064520e8SBard Liao usleep_range(1000, 1010); 390064520e8SBard Liao 391064520e8SBard Liao ret = snd_sof_dsp_read_poll_timeout(sdev, HDA_DSP_BAR, MTL_DSP2CXCTL_PRIMARY_CORE, dspcxctl, 392064520e8SBard Liao !(dspcxctl & MTL_DSP2CXCTL_PRIMARY_CORE_CPA_MASK), 393064520e8SBard Liao HDA_DSP_REG_POLL_INTERVAL_US, 394064520e8SBard Liao HDA_DSP_PD_TIMEOUT * USEC_PER_MSEC); 395064520e8SBard Liao if (ret < 0) 396064520e8SBard Liao dev_err(sdev->dev, "failed to power down primary core\n"); 397064520e8SBard Liao 398064520e8SBard Liao return ret; 399064520e8SBard Liao } 400064520e8SBard Liao 4012090cb9bSFred Oh static int mtl_power_down_dsp(struct snd_sof_dev *sdev) 4022090cb9bSFred Oh { 4032090cb9bSFred Oh u32 dsphfdsscs, cpa; 4042090cb9bSFred Oh int ret; 4052090cb9bSFred Oh 4062090cb9bSFred Oh /* first power down core */ 4072090cb9bSFred Oh ret = mtl_dsp_core_power_down(sdev, SOF_DSP_PRIMARY_CORE); 4082090cb9bSFred Oh if (ret) { 4092090cb9bSFred Oh dev_err(sdev->dev, "mtl dsp power down error, %d\n", ret); 4102090cb9bSFred Oh return ret; 4112090cb9bSFred Oh } 4122090cb9bSFred Oh 4132090cb9bSFred Oh /* Set the DSP subsystem power down */ 4142090cb9bSFred Oh snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, MTL_HFDSSCS, 4152090cb9bSFred Oh MTL_HFDSSCS_SPA_MASK, 0); 4162090cb9bSFred Oh 4172090cb9bSFred Oh /* Wait for unstable CPA read (1 then 0 then 1) just after setting SPA bit */ 4182090cb9bSFred Oh usleep_range(1000, 1010); 4192090cb9bSFred Oh 4202090cb9bSFred Oh /* poll with timeout to check if operation successful */ 4212090cb9bSFred Oh cpa = MTL_HFDSSCS_CPA_MASK; 4222090cb9bSFred Oh dsphfdsscs = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_HFDSSCS); 4232090cb9bSFred Oh return snd_sof_dsp_read_poll_timeout(sdev, HDA_DSP_BAR, MTL_HFDSSCS, dsphfdsscs, 4242090cb9bSFred Oh (dsphfdsscs & cpa) == 0, HDA_DSP_REG_POLL_INTERVAL_US, 4252090cb9bSFred Oh HDA_DSP_RESET_TIMEOUT_US); 4262090cb9bSFred Oh } 4272090cb9bSFred Oh 428064520e8SBard Liao static int mtl_dsp_cl_init(struct snd_sof_dev *sdev, int stream_tag, bool imr_boot) 429064520e8SBard Liao { 430064520e8SBard Liao struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata; 431064520e8SBard Liao const struct sof_intel_dsp_desc *chip = hda->desc; 432064520e8SBard Liao unsigned int status; 433064520e8SBard Liao u32 ipc_hdr; 434064520e8SBard Liao int ret; 435064520e8SBard Liao 436064520e8SBard Liao /* step 1: purge FW request */ 437064520e8SBard Liao ipc_hdr = chip->ipc_req_mask | HDA_DSP_ROM_IPC_CONTROL; 438064520e8SBard Liao if (!imr_boot) 439064520e8SBard Liao ipc_hdr |= HDA_DSP_ROM_IPC_PURGE_FW | ((stream_tag - 1) << 9); 440064520e8SBard Liao 441064520e8SBard Liao snd_sof_dsp_write(sdev, HDA_DSP_BAR, chip->ipc_req, ipc_hdr); 442064520e8SBard Liao 443064520e8SBard Liao /* step 2: power up primary core */ 444064520e8SBard Liao ret = mtl_dsp_core_power_up(sdev, SOF_DSP_PRIMARY_CORE); 445064520e8SBard Liao if (ret < 0) { 446064520e8SBard Liao if (hda->boot_iteration == HDA_FW_BOOT_ATTEMPTS) 447064520e8SBard Liao dev_err(sdev->dev, "dsp core 0/1 power up failed\n"); 448064520e8SBard Liao goto err; 449064520e8SBard Liao } 450064520e8SBard Liao 451064520e8SBard Liao dev_dbg(sdev->dev, "Primary core power up successful\n"); 452064520e8SBard Liao 453064520e8SBard Liao /* step 3: wait for IPC DONE bit from ROM */ 454064520e8SBard Liao ret = snd_sof_dsp_read_poll_timeout(sdev, HDA_DSP_BAR, chip->ipc_ack, status, 455064520e8SBard Liao ((status & chip->ipc_ack_mask) == chip->ipc_ack_mask), 456064520e8SBard Liao HDA_DSP_REG_POLL_INTERVAL_US, MTL_DSP_PURGE_TIMEOUT_US); 457064520e8SBard Liao if (ret < 0) { 458064520e8SBard Liao if (hda->boot_iteration == HDA_FW_BOOT_ATTEMPTS) 459064520e8SBard Liao dev_err(sdev->dev, "timeout waiting for purge IPC done\n"); 460064520e8SBard Liao goto err; 461064520e8SBard Liao } 462064520e8SBard Liao 463064520e8SBard Liao /* set DONE bit to clear the reply IPC message */ 464064520e8SBard Liao snd_sof_dsp_update_bits_forced(sdev, HDA_DSP_BAR, chip->ipc_ack, chip->ipc_ack_mask, 465064520e8SBard Liao chip->ipc_ack_mask); 466064520e8SBard Liao 467064520e8SBard Liao /* step 4: enable interrupts */ 468064520e8SBard Liao ret = mtl_enable_interrupts(sdev); 469064520e8SBard Liao if (ret < 0) { 470064520e8SBard Liao if (hda->boot_iteration == HDA_FW_BOOT_ATTEMPTS) 471064520e8SBard Liao dev_err(sdev->dev, "%s: failed to enable interrupts\n", __func__); 472064520e8SBard Liao goto err; 473064520e8SBard Liao } 474064520e8SBard Liao 475064520e8SBard Liao mtl_enable_ipc_interrupts(sdev); 476064520e8SBard Liao 477064520e8SBard Liao /* 478064520e8SBard Liao * ACE workaround: don't wait for ROM INIT. 479064520e8SBard Liao * The platform cannot catch ROM_INIT_DONE because of a very short 480064520e8SBard Liao * timing window. Follow the recommendations and skip this part. 481064520e8SBard Liao */ 482064520e8SBard Liao 483064520e8SBard Liao return 0; 484064520e8SBard Liao 485064520e8SBard Liao err: 486064520e8SBard Liao snd_sof_dsp_dbg_dump(sdev, "MTL DSP init fail", 0); 487064520e8SBard Liao mtl_dsp_core_power_down(sdev, SOF_DSP_PRIMARY_CORE); 488064520e8SBard Liao return ret; 489064520e8SBard Liao } 490064520e8SBard Liao 491064520e8SBard Liao static irqreturn_t mtl_ipc_irq_thread(int irq, void *context) 492064520e8SBard Liao { 493064520e8SBard Liao struct sof_ipc4_msg notification_data = {{ 0 }}; 494064520e8SBard Liao struct snd_sof_dev *sdev = context; 495064520e8SBard Liao bool ipc_irq = false; 496064520e8SBard Liao u32 hipcida; 497064520e8SBard Liao u32 hipctdr; 498064520e8SBard Liao 499064520e8SBard Liao hipcida = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_DSP_REG_HFIPCXIDA); 500064520e8SBard Liao 501064520e8SBard Liao /* reply message from DSP */ 502064520e8SBard Liao if (hipcida & MTL_DSP_REG_HFIPCXIDA_DONE) { 503064520e8SBard Liao /* DSP received the message */ 504064520e8SBard Liao snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, MTL_DSP_REG_HFIPCXCTL, 505064520e8SBard Liao MTL_DSP_REG_HFIPCXCTL_DONE, 0); 506064520e8SBard Liao 507064520e8SBard Liao mtl_ipc_dsp_done(sdev); 508064520e8SBard Liao 509064520e8SBard Liao ipc_irq = true; 510064520e8SBard Liao } 511064520e8SBard Liao 512064520e8SBard Liao hipctdr = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_DSP_REG_HFIPCXTDR); 513064520e8SBard Liao if (hipctdr & MTL_DSP_REG_HFIPCXTDR_BUSY) { 514064520e8SBard Liao /* Message from DSP (reply or notification) */ 515064520e8SBard Liao u32 extension = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_DSP_REG_HFIPCXTDDY); 516064520e8SBard Liao u32 primary = hipctdr & MTL_DSP_REG_HFIPCXTDR_MSG_MASK; 517064520e8SBard Liao 518064520e8SBard Liao /* 519064520e8SBard Liao * ACE fw sends a new fw ipc message to host to 520064520e8SBard Liao * notify the status of the last host ipc message 521064520e8SBard Liao */ 522064520e8SBard Liao if (primary & SOF_IPC4_MSG_DIR_MASK) { 523064520e8SBard Liao /* Reply received */ 5241549a69bSPeter Ujfalusi if (likely(sdev->fw_state == SOF_FW_BOOT_COMPLETE)) { 525064520e8SBard Liao struct sof_ipc4_msg *data = sdev->ipc->msg.reply_data; 526064520e8SBard Liao 527064520e8SBard Liao data->primary = primary; 528064520e8SBard Liao data->extension = extension; 529064520e8SBard Liao 530064520e8SBard Liao spin_lock_irq(&sdev->ipc_lock); 531064520e8SBard Liao 532064520e8SBard Liao snd_sof_ipc_get_reply(sdev); 533064520e8SBard Liao snd_sof_ipc_reply(sdev, data->primary); 534064520e8SBard Liao 535064520e8SBard Liao spin_unlock_irq(&sdev->ipc_lock); 536064520e8SBard Liao } else { 5371549a69bSPeter Ujfalusi dev_dbg_ratelimited(sdev->dev, 5381549a69bSPeter Ujfalusi "IPC reply before FW_READY: %#x|%#x\n", 5391549a69bSPeter Ujfalusi primary, extension); 5401549a69bSPeter Ujfalusi } 5411549a69bSPeter Ujfalusi } else { 542064520e8SBard Liao /* Notification received */ 543064520e8SBard Liao notification_data.primary = primary; 544064520e8SBard Liao notification_data.extension = extension; 545064520e8SBard Liao 546064520e8SBard Liao sdev->ipc->msg.rx_data = ¬ification_data; 547064520e8SBard Liao snd_sof_ipc_msgs_rx(sdev); 548064520e8SBard Liao sdev->ipc->msg.rx_data = NULL; 549064520e8SBard Liao } 550064520e8SBard Liao 551064520e8SBard Liao mtl_ipc_host_done(sdev); 552064520e8SBard Liao 553064520e8SBard Liao ipc_irq = true; 554064520e8SBard Liao } 555064520e8SBard Liao 556064520e8SBard Liao if (!ipc_irq) { 557064520e8SBard Liao /* This interrupt is not shared so no need to return IRQ_NONE. */ 558b837870fSPierre-Louis Bossart dev_dbg_ratelimited(sdev->dev, "nothing to do in IPC IRQ thread\n"); 559064520e8SBard Liao } 560064520e8SBard Liao 561064520e8SBard Liao return IRQ_HANDLED; 562064520e8SBard Liao } 563064520e8SBard Liao 564064520e8SBard Liao static int mtl_dsp_ipc_get_mailbox_offset(struct snd_sof_dev *sdev) 565064520e8SBard Liao { 566064520e8SBard Liao return MTL_DSP_MBOX_UPLINK_OFFSET; 567064520e8SBard Liao } 568064520e8SBard Liao 569064520e8SBard Liao static int mtl_dsp_ipc_get_window_offset(struct snd_sof_dev *sdev, u32 id) 570064520e8SBard Liao { 571064520e8SBard Liao return MTL_SRAM_WINDOW_OFFSET(id); 572064520e8SBard Liao } 573064520e8SBard Liao 574064520e8SBard Liao static void mtl_ipc_dump(struct snd_sof_dev *sdev) 575064520e8SBard Liao { 576d01784eeSPeter Ujfalusi u32 hipcidr, hipcidd, hipcida, hipctdr, hipctdd, hipctda, hipcctl; 577064520e8SBard Liao 578d01784eeSPeter Ujfalusi hipcidr = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_DSP_REG_HFIPCXIDR); 579d01784eeSPeter Ujfalusi hipcidd = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_DSP_REG_HFIPCXIDDY); 580064520e8SBard Liao hipcida = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_DSP_REG_HFIPCXIDA); 581064520e8SBard Liao hipctdr = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_DSP_REG_HFIPCXTDR); 582d01784eeSPeter Ujfalusi hipctdd = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_DSP_REG_HFIPCXTDDY); 583d01784eeSPeter Ujfalusi hipctda = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_DSP_REG_HFIPCXTDA); 584d01784eeSPeter Ujfalusi hipcctl = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_DSP_REG_HFIPCXCTL); 585064520e8SBard Liao 586064520e8SBard Liao dev_err(sdev->dev, 587d01784eeSPeter Ujfalusi "Host IPC initiator: %#x|%#x|%#x, target: %#x|%#x|%#x, ctl: %#x\n", 588d01784eeSPeter Ujfalusi hipcidr, hipcidd, hipcida, hipctdr, hipctdd, hipctda, hipcctl); 589064520e8SBard Liao } 590064520e8SBard Liao 59139df087fSRanjani Sridharan static int mtl_dsp_disable_interrupts(struct snd_sof_dev *sdev) 59239df087fSRanjani Sridharan { 59339df087fSRanjani Sridharan mtl_disable_ipc_interrupts(sdev); 59439df087fSRanjani Sridharan return mtl_disable_interrupts(sdev); 59539df087fSRanjani Sridharan } 59639df087fSRanjani Sridharan 597064520e8SBard Liao /* Meteorlake ops */ 598064520e8SBard Liao struct snd_sof_dsp_ops sof_mtl_ops; 599064520e8SBard Liao EXPORT_SYMBOL_NS(sof_mtl_ops, SND_SOC_SOF_INTEL_HDA_COMMON); 600064520e8SBard Liao 601064520e8SBard Liao int sof_mtl_ops_init(struct snd_sof_dev *sdev) 602064520e8SBard Liao { 603064520e8SBard Liao struct sof_ipc4_fw_data *ipc4_data; 604064520e8SBard Liao 605064520e8SBard Liao /* common defaults */ 606064520e8SBard Liao memcpy(&sof_mtl_ops, &sof_hda_common_ops, sizeof(struct snd_sof_dsp_ops)); 607064520e8SBard Liao 608064520e8SBard Liao /* shutdown */ 609064520e8SBard Liao sof_mtl_ops.shutdown = hda_dsp_shutdown; 610064520e8SBard Liao 611064520e8SBard Liao /* doorbell */ 612064520e8SBard Liao sof_mtl_ops.irq_thread = mtl_ipc_irq_thread; 613064520e8SBard Liao 614064520e8SBard Liao /* ipc */ 615064520e8SBard Liao sof_mtl_ops.send_msg = mtl_ipc_send_msg; 616064520e8SBard Liao sof_mtl_ops.get_mailbox_offset = mtl_dsp_ipc_get_mailbox_offset; 617064520e8SBard Liao sof_mtl_ops.get_window_offset = mtl_dsp_ipc_get_window_offset; 618064520e8SBard Liao 619064520e8SBard Liao /* debug */ 620064520e8SBard Liao sof_mtl_ops.debug_map = mtl_dsp_debugfs; 621064520e8SBard Liao sof_mtl_ops.debug_map_count = ARRAY_SIZE(mtl_dsp_debugfs); 622064520e8SBard Liao sof_mtl_ops.dbg_dump = mtl_dsp_dump; 623064520e8SBard Liao sof_mtl_ops.ipc_dump = mtl_ipc_dump; 624064520e8SBard Liao 625064520e8SBard Liao /* pre/post fw run */ 626064520e8SBard Liao sof_mtl_ops.pre_fw_run = mtl_dsp_pre_fw_run; 627064520e8SBard Liao sof_mtl_ops.post_fw_run = mtl_dsp_post_fw_run; 628064520e8SBard Liao 629064520e8SBard Liao /* parse platform specific extended manifest */ 630064520e8SBard Liao sof_mtl_ops.parse_platform_ext_manifest = NULL; 631064520e8SBard Liao 632064520e8SBard Liao /* dsp core get/put */ 633064520e8SBard Liao /* TODO: add core_get and core_put */ 634064520e8SBard Liao 635064520e8SBard Liao sdev->private = devm_kzalloc(sdev->dev, sizeof(struct sof_ipc4_fw_data), GFP_KERNEL); 636064520e8SBard Liao if (!sdev->private) 637064520e8SBard Liao return -ENOMEM; 638064520e8SBard Liao 639064520e8SBard Liao ipc4_data = sdev->private; 640064520e8SBard Liao ipc4_data->manifest_fw_hdr_offset = SOF_MAN4_FW_HDR_OFFSET; 641064520e8SBard Liao 642cc4a3a19SPeter Ujfalusi ipc4_data->mtrace_type = SOF_IPC4_MTRACE_INTEL_CAVS_2; 643cc4a3a19SPeter Ujfalusi 644*3ab2c21eSPeter Ujfalusi /* External library loading support */ 645*3ab2c21eSPeter Ujfalusi ipc4_data->load_library = hda_dsp_ipc4_load_library; 646*3ab2c21eSPeter Ujfalusi 647064520e8SBard Liao /* set DAI ops */ 648064520e8SBard Liao hda_set_dai_drv_ops(sdev, &sof_mtl_ops); 649064520e8SBard Liao 650064520e8SBard Liao return 0; 651064520e8SBard Liao }; 652064520e8SBard Liao EXPORT_SYMBOL_NS(sof_mtl_ops_init, SND_SOC_SOF_INTEL_HDA_COMMON); 653064520e8SBard Liao 654064520e8SBard Liao const struct sof_intel_dsp_desc mtl_chip_info = { 655064520e8SBard Liao .cores_num = 3, 656064520e8SBard Liao .init_core_mask = BIT(0), 657064520e8SBard Liao .host_managed_cores_mask = BIT(0), 658064520e8SBard Liao .ipc_req = MTL_DSP_REG_HFIPCXIDR, 659064520e8SBard Liao .ipc_req_mask = MTL_DSP_REG_HFIPCXIDR_BUSY, 660064520e8SBard Liao .ipc_ack = MTL_DSP_REG_HFIPCXIDA, 661064520e8SBard Liao .ipc_ack_mask = MTL_DSP_REG_HFIPCXIDA_DONE, 662064520e8SBard Liao .ipc_ctl = MTL_DSP_REG_HFIPCXCTL, 663064520e8SBard Liao .rom_status_reg = MTL_DSP_ROM_STS, 664064520e8SBard Liao .rom_init_timeout = 300, 6659ccbc2e1SPierre-Louis Bossart .ssp_count = MTL_SSP_COUNT, 666064520e8SBard Liao .ssp_base_offset = CNL_SSP_BASE_OFFSET, 667064520e8SBard Liao .sdw_shim_base = SDW_SHIM_BASE_ACE, 668064520e8SBard Liao .sdw_alh_base = SDW_ALH_BASE_ACE, 669064520e8SBard Liao .check_sdw_irq = mtl_dsp_check_sdw_irq, 670064520e8SBard Liao .check_ipc_irq = mtl_dsp_check_ipc_irq, 671064520e8SBard Liao .cl_init = mtl_dsp_cl_init, 6722090cb9bSFred Oh .power_down_dsp = mtl_power_down_dsp, 67339df087fSRanjani Sridharan .disable_interrupts = mtl_dsp_disable_interrupts, 674064520e8SBard Liao .hw_ip_version = SOF_INTEL_ACE_1_0, 675064520e8SBard Liao }; 676064520e8SBard Liao EXPORT_SYMBOL_NS(mtl_chip_info, SND_SOC_SOF_INTEL_HDA_COMMON); 677