0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018 #include <sound/sof/ext_manifest4.h>
0019 #include <sound/sof/ipc4/header.h>
0020 #include "../ipc4-priv.h"
0021 #include "../ops.h"
0022 #include "hda.h"
0023 #include "hda-ipc.h"
0024 #include "../sof-audio.h"
0025
0026 static const struct snd_sof_debugfs_map cnl_dsp_debugfs[] = {
0027 {"hda", HDA_DSP_HDA_BAR, 0, 0x4000, SOF_DEBUGFS_ACCESS_ALWAYS},
0028 {"pp", HDA_DSP_PP_BAR, 0, 0x1000, SOF_DEBUGFS_ACCESS_ALWAYS},
0029 {"dsp", HDA_DSP_BAR, 0, 0x10000, SOF_DEBUGFS_ACCESS_ALWAYS},
0030 };
0031
0032 static void cnl_ipc_host_done(struct snd_sof_dev *sdev);
0033 static void cnl_ipc_dsp_done(struct snd_sof_dev *sdev);
0034
0035 irqreturn_t cnl_ipc4_irq_thread(int irq, void *context)
0036 {
0037 struct sof_ipc4_msg notification_data = {{ 0 }};
0038 struct snd_sof_dev *sdev = context;
0039 bool ipc_irq = false;
0040 u32 hipcida, hipctdr;
0041
0042 hipcida = snd_sof_dsp_read(sdev, HDA_DSP_BAR, CNL_DSP_REG_HIPCIDA);
0043 if (hipcida & CNL_DSP_REG_HIPCIDA_DONE) {
0044
0045 snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR,
0046 CNL_DSP_REG_HIPCCTL,
0047 CNL_DSP_REG_HIPCCTL_DONE, 0);
0048 cnl_ipc_dsp_done(sdev);
0049
0050 ipc_irq = true;
0051 }
0052
0053 hipctdr = snd_sof_dsp_read(sdev, HDA_DSP_BAR, CNL_DSP_REG_HIPCTDR);
0054 if (hipctdr & CNL_DSP_REG_HIPCTDR_BUSY) {
0055
0056 u32 hipctdd = snd_sof_dsp_read(sdev, HDA_DSP_BAR,
0057 CNL_DSP_REG_HIPCTDD);
0058 u32 primary = hipctdr & CNL_DSP_REG_HIPCTDR_MSG_MASK;
0059 u32 extension = hipctdd & CNL_DSP_REG_HIPCTDD_MSG_MASK;
0060
0061 if (primary & SOF_IPC4_MSG_DIR_MASK) {
0062
0063 if (likely(sdev->fw_state == SOF_FW_BOOT_COMPLETE)) {
0064 struct sof_ipc4_msg *data = sdev->ipc->msg.reply_data;
0065
0066 data->primary = primary;
0067 data->extension = extension;
0068
0069 spin_lock_irq(&sdev->ipc_lock);
0070
0071 snd_sof_ipc_get_reply(sdev);
0072 snd_sof_ipc_reply(sdev, data->primary);
0073
0074 spin_unlock_irq(&sdev->ipc_lock);
0075 } else {
0076 dev_dbg_ratelimited(sdev->dev,
0077 "IPC reply before FW_READY: %#x|%#x\n",
0078 primary, extension);
0079 }
0080 } else {
0081
0082 notification_data.primary = primary;
0083 notification_data.extension = extension;
0084
0085 sdev->ipc->msg.rx_data = ¬ification_data;
0086 snd_sof_ipc_msgs_rx(sdev);
0087 sdev->ipc->msg.rx_data = NULL;
0088 }
0089
0090
0091 cnl_ipc_host_done(sdev);
0092
0093 ipc_irq = true;
0094 }
0095
0096 if (!ipc_irq)
0097
0098 dev_dbg_ratelimited(sdev->dev, "nothing to do in IPC IRQ thread\n");
0099
0100 return IRQ_HANDLED;
0101 }
0102
0103 irqreturn_t cnl_ipc_irq_thread(int irq, void *context)
0104 {
0105 struct snd_sof_dev *sdev = context;
0106 u32 hipci;
0107 u32 hipcida;
0108 u32 hipctdr;
0109 u32 hipctdd;
0110 u32 msg;
0111 u32 msg_ext;
0112 bool ipc_irq = false;
0113
0114 hipcida = snd_sof_dsp_read(sdev, HDA_DSP_BAR, CNL_DSP_REG_HIPCIDA);
0115 hipctdr = snd_sof_dsp_read(sdev, HDA_DSP_BAR, CNL_DSP_REG_HIPCTDR);
0116 hipctdd = snd_sof_dsp_read(sdev, HDA_DSP_BAR, CNL_DSP_REG_HIPCTDD);
0117 hipci = snd_sof_dsp_read(sdev, HDA_DSP_BAR, CNL_DSP_REG_HIPCIDR);
0118
0119
0120 if (hipcida & CNL_DSP_REG_HIPCIDA_DONE) {
0121 msg_ext = hipci & CNL_DSP_REG_HIPCIDR_MSG_MASK;
0122 msg = hipcida & CNL_DSP_REG_HIPCIDA_MSG_MASK;
0123
0124 dev_vdbg(sdev->dev,
0125 "ipc: firmware response, msg:0x%x, msg_ext:0x%x\n",
0126 msg, msg_ext);
0127
0128
0129 snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR,
0130 CNL_DSP_REG_HIPCCTL,
0131 CNL_DSP_REG_HIPCCTL_DONE, 0);
0132
0133 if (likely(sdev->fw_state == SOF_FW_BOOT_COMPLETE)) {
0134 spin_lock_irq(&sdev->ipc_lock);
0135
0136
0137 hda_dsp_ipc_get_reply(sdev);
0138 snd_sof_ipc_reply(sdev, msg);
0139
0140 cnl_ipc_dsp_done(sdev);
0141
0142 spin_unlock_irq(&sdev->ipc_lock);
0143 } else {
0144 dev_dbg_ratelimited(sdev->dev, "IPC reply before FW_READY: %#x\n",
0145 msg);
0146 }
0147
0148 ipc_irq = true;
0149 }
0150
0151
0152 if (hipctdr & CNL_DSP_REG_HIPCTDR_BUSY) {
0153 msg = hipctdr & CNL_DSP_REG_HIPCTDR_MSG_MASK;
0154 msg_ext = hipctdd & CNL_DSP_REG_HIPCTDD_MSG_MASK;
0155
0156 dev_vdbg(sdev->dev,
0157 "ipc: firmware initiated, msg:0x%x, msg_ext:0x%x\n",
0158 msg, msg_ext);
0159
0160
0161 if ((hipctdr & SOF_IPC_PANIC_MAGIC_MASK) == SOF_IPC_PANIC_MAGIC) {
0162 struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata;
0163 bool non_recoverable = true;
0164
0165
0166
0167
0168
0169
0170
0171
0172
0173 if (sdev->fw_state == SOF_FW_BOOT_IN_PROGRESS &&
0174 hda->boot_iteration < HDA_FW_BOOT_ATTEMPTS)
0175 non_recoverable = false;
0176
0177 snd_sof_dsp_panic(sdev, HDA_DSP_PANIC_OFFSET(msg_ext),
0178 non_recoverable);
0179 } else {
0180 snd_sof_ipc_msgs_rx(sdev);
0181 }
0182
0183 cnl_ipc_host_done(sdev);
0184
0185 ipc_irq = true;
0186 }
0187
0188 if (!ipc_irq) {
0189
0190
0191
0192 dev_dbg_ratelimited(sdev->dev,
0193 "nothing to do in IPC IRQ thread\n");
0194 }
0195
0196 return IRQ_HANDLED;
0197 }
0198
0199 static void cnl_ipc_host_done(struct snd_sof_dev *sdev)
0200 {
0201
0202
0203
0204
0205 snd_sof_dsp_update_bits_forced(sdev, HDA_DSP_BAR,
0206 CNL_DSP_REG_HIPCTDR,
0207 CNL_DSP_REG_HIPCTDR_BUSY,
0208 CNL_DSP_REG_HIPCTDR_BUSY);
0209
0210
0211
0212
0213 snd_sof_dsp_update_bits_forced(sdev, HDA_DSP_BAR,
0214 CNL_DSP_REG_HIPCTDA,
0215 CNL_DSP_REG_HIPCTDA_DONE,
0216 CNL_DSP_REG_HIPCTDA_DONE);
0217 }
0218
0219 static void cnl_ipc_dsp_done(struct snd_sof_dev *sdev)
0220 {
0221
0222
0223
0224
0225 snd_sof_dsp_update_bits_forced(sdev, HDA_DSP_BAR,
0226 CNL_DSP_REG_HIPCIDA,
0227 CNL_DSP_REG_HIPCIDA_DONE,
0228 CNL_DSP_REG_HIPCIDA_DONE);
0229
0230
0231 snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR,
0232 CNL_DSP_REG_HIPCCTL,
0233 CNL_DSP_REG_HIPCCTL_DONE,
0234 CNL_DSP_REG_HIPCCTL_DONE);
0235 }
0236
0237 static bool cnl_compact_ipc_compress(struct snd_sof_ipc_msg *msg,
0238 u32 *dr, u32 *dd)
0239 {
0240 struct sof_ipc_pm_gate *pm_gate = msg->msg_data;
0241
0242 if (pm_gate->hdr.cmd == (SOF_IPC_GLB_PM_MSG | SOF_IPC_PM_GATE)) {
0243
0244 *dr = HDA_IPC_MSG_COMPACT | HDA_IPC_PM_GATE;
0245
0246
0247 *dd = pm_gate->flags;
0248
0249 return true;
0250 }
0251
0252 return false;
0253 }
0254
0255 int cnl_ipc4_send_msg(struct snd_sof_dev *sdev, struct snd_sof_ipc_msg *msg)
0256 {
0257 struct sof_ipc4_msg *msg_data = msg->msg_data;
0258
0259
0260 if (msg_data->data_size)
0261 sof_mailbox_write(sdev, sdev->host_box.offset, msg_data->data_ptr,
0262 msg_data->data_size);
0263
0264 snd_sof_dsp_write(sdev, HDA_DSP_BAR, CNL_DSP_REG_HIPCIDD, msg_data->extension);
0265 snd_sof_dsp_write(sdev, HDA_DSP_BAR, CNL_DSP_REG_HIPCIDR,
0266 msg_data->primary | CNL_DSP_REG_HIPCIDR_BUSY);
0267
0268 return 0;
0269 }
0270
0271 int cnl_ipc_send_msg(struct snd_sof_dev *sdev, struct snd_sof_ipc_msg *msg)
0272 {
0273 struct sof_intel_hda_dev *hdev = sdev->pdata->hw_pdata;
0274 struct sof_ipc_cmd_hdr *hdr;
0275 u32 dr = 0;
0276 u32 dd = 0;
0277
0278
0279
0280
0281
0282
0283
0284
0285
0286 if (cnl_compact_ipc_compress(msg, &dr, &dd)) {
0287
0288 snd_sof_dsp_write(sdev, HDA_DSP_BAR, CNL_DSP_REG_HIPCIDD,
0289 dd);
0290 snd_sof_dsp_write(sdev, HDA_DSP_BAR, CNL_DSP_REG_HIPCIDR,
0291 CNL_DSP_REG_HIPCIDR_BUSY | dr);
0292 return 0;
0293 }
0294
0295
0296 sof_mailbox_write(sdev, sdev->host_box.offset, msg->msg_data,
0297 msg->msg_size);
0298 snd_sof_dsp_write(sdev, HDA_DSP_BAR, CNL_DSP_REG_HIPCIDR,
0299 CNL_DSP_REG_HIPCIDR_BUSY);
0300
0301 hdr = msg->msg_data;
0302
0303
0304
0305
0306
0307
0308
0309
0310
0311 if (hdr->cmd != (SOF_IPC_GLB_PM_MSG | SOF_IPC_PM_CTX_SAVE))
0312 mod_delayed_work(system_wq, &hdev->d0i3_work,
0313 msecs_to_jiffies(SOF_HDA_D0I3_WORK_DELAY_MS));
0314
0315 return 0;
0316 }
0317
0318 void cnl_ipc_dump(struct snd_sof_dev *sdev)
0319 {
0320 u32 hipcctl;
0321 u32 hipcida;
0322 u32 hipctdr;
0323
0324 hda_ipc_irq_dump(sdev);
0325
0326
0327 hipcida = snd_sof_dsp_read(sdev, HDA_DSP_BAR, CNL_DSP_REG_HIPCIDA);
0328 hipcctl = snd_sof_dsp_read(sdev, HDA_DSP_BAR, CNL_DSP_REG_HIPCCTL);
0329 hipctdr = snd_sof_dsp_read(sdev, HDA_DSP_BAR, CNL_DSP_REG_HIPCTDR);
0330
0331
0332
0333 dev_err(sdev->dev,
0334 "error: host status 0x%8.8x dsp status 0x%8.8x mask 0x%8.8x\n",
0335 hipcida, hipctdr, hipcctl);
0336 }
0337
0338
0339 struct snd_sof_dsp_ops sof_cnl_ops;
0340 EXPORT_SYMBOL_NS(sof_cnl_ops, SND_SOC_SOF_INTEL_HDA_COMMON);
0341
0342 int sof_cnl_ops_init(struct snd_sof_dev *sdev)
0343 {
0344
0345 memcpy(&sof_cnl_ops, &sof_hda_common_ops, sizeof(struct snd_sof_dsp_ops));
0346
0347
0348 sof_cnl_ops.shutdown = hda_dsp_shutdown;
0349
0350
0351 if (sdev->pdata->ipc_type == SOF_IPC) {
0352
0353 sof_cnl_ops.irq_thread = cnl_ipc_irq_thread;
0354
0355
0356 sof_cnl_ops.send_msg = cnl_ipc_send_msg;
0357 }
0358
0359 if (sdev->pdata->ipc_type == SOF_INTEL_IPC4) {
0360 struct sof_ipc4_fw_data *ipc4_data;
0361
0362 sdev->private = devm_kzalloc(sdev->dev, sizeof(*ipc4_data), GFP_KERNEL);
0363 if (!sdev->private)
0364 return -ENOMEM;
0365
0366 ipc4_data = sdev->private;
0367 ipc4_data->manifest_fw_hdr_offset = SOF_MAN4_FW_HDR_OFFSET;
0368
0369
0370 sof_cnl_ops.irq_thread = cnl_ipc4_irq_thread;
0371
0372
0373 sof_cnl_ops.send_msg = cnl_ipc4_send_msg;
0374 }
0375
0376
0377 hda_set_dai_drv_ops(sdev, &sof_cnl_ops);
0378
0379
0380 sof_cnl_ops.debug_map = cnl_dsp_debugfs;
0381 sof_cnl_ops.debug_map_count = ARRAY_SIZE(cnl_dsp_debugfs);
0382 sof_cnl_ops.ipc_dump = cnl_ipc_dump;
0383
0384
0385 sof_cnl_ops.post_fw_run = hda_dsp_post_fw_run;
0386
0387
0388 sof_cnl_ops.run = hda_dsp_cl_boot_firmware;
0389
0390
0391 sof_cnl_ops.core_get = hda_dsp_core_get;
0392
0393 return 0;
0394 };
0395 EXPORT_SYMBOL_NS(sof_cnl_ops_init, SND_SOC_SOF_INTEL_HDA_COMMON);
0396
0397 const struct sof_intel_dsp_desc cnl_chip_info = {
0398
0399 .cores_num = 4,
0400 .init_core_mask = 1,
0401 .host_managed_cores_mask = GENMASK(3, 0),
0402 .ipc_req = CNL_DSP_REG_HIPCIDR,
0403 .ipc_req_mask = CNL_DSP_REG_HIPCIDR_BUSY,
0404 .ipc_ack = CNL_DSP_REG_HIPCIDA,
0405 .ipc_ack_mask = CNL_DSP_REG_HIPCIDA_DONE,
0406 .ipc_ctl = CNL_DSP_REG_HIPCCTL,
0407 .rom_status_reg = HDA_DSP_SRAM_REG_ROM_STATUS,
0408 .rom_init_timeout = 300,
0409 .ssp_count = CNL_SSP_COUNT,
0410 .ssp_base_offset = CNL_SSP_BASE_OFFSET,
0411 .sdw_shim_base = SDW_SHIM_BASE,
0412 .sdw_alh_base = SDW_ALH_BASE,
0413 .check_sdw_irq = hda_common_check_sdw_irq,
0414 .check_ipc_irq = hda_dsp_check_ipc_irq,
0415 .cl_init = cl_dsp_init,
0416 .hw_ip_version = SOF_INTEL_CAVS_1_8,
0417 };
0418 EXPORT_SYMBOL_NS(cnl_chip_info, SND_SOC_SOF_INTEL_HDA_COMMON);
0419
0420
0421
0422
0423
0424
0425
0426
0427 const struct sof_intel_dsp_desc jsl_chip_info = {
0428
0429 .cores_num = 2,
0430 .init_core_mask = 1,
0431 .host_managed_cores_mask = GENMASK(1, 0),
0432 .ipc_req = CNL_DSP_REG_HIPCIDR,
0433 .ipc_req_mask = CNL_DSP_REG_HIPCIDR_BUSY,
0434 .ipc_ack = CNL_DSP_REG_HIPCIDA,
0435 .ipc_ack_mask = CNL_DSP_REG_HIPCIDA_DONE,
0436 .ipc_ctl = CNL_DSP_REG_HIPCCTL,
0437 .rom_status_reg = HDA_DSP_SRAM_REG_ROM_STATUS,
0438 .rom_init_timeout = 300,
0439 .ssp_count = ICL_SSP_COUNT,
0440 .ssp_base_offset = CNL_SSP_BASE_OFFSET,
0441 .sdw_shim_base = SDW_SHIM_BASE,
0442 .sdw_alh_base = SDW_ALH_BASE,
0443 .check_sdw_irq = hda_common_check_sdw_irq,
0444 .check_ipc_irq = hda_dsp_check_ipc_irq,
0445 .cl_init = cl_dsp_init,
0446 .hw_ip_version = SOF_INTEL_CAVS_2_0,
0447 };
0448 EXPORT_SYMBOL_NS(jsl_chip_info, SND_SOC_SOF_INTEL_HDA_COMMON);