Lines Matching +full:mode +full:- +full:loader

1 // SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
15 * Hardware interface for HDA DSP code loader
24 #include "../ipc4-priv.h"
26 #include "../sof-priv.h"
31 MODULE_PARM_DESC(persistent_cl_buffer, "Persistent Code Loader DMA buffer "
32 "(default = Y, use N to force buffer re-allocation)");
36 struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata; in hda_ssp_set_cbp_cfp()
37 const struct sof_intel_dsp_desc *chip = hda->desc; in hda_ssp_set_cbp_cfp()
40 /* DSP is powered up, set all SSPs to clock consumer/codec provider mode */ in hda_ssp_set_cbp_cfp()
41 for (i = 0; i < chip->ssp_count; i++) { in hda_ssp_set_cbp_cfp()
43 chip->ssp_base_offset in hda_ssp_set_cbp_cfp()
64 dev_err(sdev->dev, "error: no stream available\n"); in hda_cl_prepare()
65 return ERR_PTR(-ENODEV); in hda_cl_prepare()
67 hstream = &hext_stream->hstream; in hda_cl_prepare()
68 hstream->substream = NULL; in hda_cl_prepare()
73 * We cannot rely solely on !dmab->area as caller might use a struct on in hda_cl_prepare()
76 if (!persistent_buffer || !dmab->area) { in hda_cl_prepare()
79 dev_err(sdev->dev, "%s: memory alloc failed: %d\n", in hda_cl_prepare()
85 hstream->period_bytes = 0;/* initialize period_bytes */ in hda_cl_prepare()
86 hstream->format_val = format; in hda_cl_prepare()
87 hstream->bufsize = size; in hda_cl_prepare()
92 dev_err(sdev->dev, "error: iccmax stream prepare failed: %d\n", ret); in hda_cl_prepare()
98 dev_err(sdev->dev, "error: hdac prepare failed: %d\n", ret); in hda_cl_prepare()
108 dmab->area = NULL; in hda_cl_prepare()
109 dmab->bytes = 0; in hda_cl_prepare()
110 hstream->bufsize = 0; in hda_cl_prepare()
111 hstream->format_val = 0; in hda_cl_prepare()
113 hda_dsp_stream_put(sdev, direction, hstream->stream_tag); in hda_cl_prepare()
125 struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata; in cl_dsp_init()
126 const struct sof_intel_dsp_desc *chip = hda->desc; in cl_dsp_init()
134 ret = hda_dsp_core_power_up(sdev, chip->host_managed_cores_mask); in cl_dsp_init()
136 if (hda->boot_iteration == HDA_FW_BOOT_ATTEMPTS) in cl_dsp_init()
137 dev_err(sdev->dev, "error: dsp core 0/1 power up failed\n"); in cl_dsp_init()
144 ipc_hdr = chip->ipc_req_mask | HDA_DSP_ROM_IPC_CONTROL; in cl_dsp_init()
146 ipc_hdr |= HDA_DSP_ROM_IPC_PURGE_FW | ((stream_tag - 1) << 9); in cl_dsp_init()
148 snd_sof_dsp_write(sdev, HDA_DSP_BAR, chip->ipc_req, ipc_hdr); in cl_dsp_init()
151 ret = hda_dsp_core_run(sdev, chip->init_core_mask); in cl_dsp_init()
153 if (hda->boot_iteration == HDA_FW_BOOT_ATTEMPTS) in cl_dsp_init()
154 dev_err(sdev->dev, in cl_dsp_init()
156 ret = -EIO; in cl_dsp_init()
162 chip->ipc_ack, status, in cl_dsp_init()
163 ((status & chip->ipc_ack_mask) in cl_dsp_init()
164 == chip->ipc_ack_mask), in cl_dsp_init()
169 if (hda->boot_iteration == HDA_FW_BOOT_ATTEMPTS) in cl_dsp_init()
170 dev_err(sdev->dev, in cl_dsp_init()
178 chip->ipc_ack, in cl_dsp_init()
179 chip->ipc_ack_mask, in cl_dsp_init()
180 chip->ipc_ack_mask); in cl_dsp_init()
183 ret = hda_dsp_core_reset_power_down(sdev, chip->host_managed_cores_mask & in cl_dsp_init()
184 ~(chip->init_core_mask)); in cl_dsp_init()
186 if (hda->boot_iteration == HDA_FW_BOOT_ATTEMPTS) in cl_dsp_init()
187 dev_err(sdev->dev, in cl_dsp_init()
197 * - Cold/Full boot: wait for ROM init to proceed to download the firmware in cl_dsp_init()
198 * - IMR boot: wait for ROM firmware entered (firmware booted up from IMR) in cl_dsp_init()
206 chip->rom_status_reg, status, in cl_dsp_init()
209 chip->rom_init_timeout * in cl_dsp_init()
213 sdev->enabled_cores_mask |= chip->init_core_mask; in cl_dsp_init()
214 mask = sdev->enabled_cores_mask; in cl_dsp_init()
216 sdev->dsp_core_ref_count[j]++; in cl_dsp_init()
220 if (hda->boot_iteration == HDA_FW_BOOT_ATTEMPTS) in cl_dsp_init()
221 dev_err(sdev->dev, in cl_dsp_init()
223 __func__, chip->rom_status_reg); in cl_dsp_init()
229 if (hda->boot_iteration == HDA_FW_BOOT_ATTEMPTS) in cl_dsp_init()
233 hda->boot_iteration, HDA_FW_BOOT_ATTEMPTS); in cl_dsp_init()
235 hda_dsp_core_reset_power_down(sdev, chip->host_managed_cores_mask); in cl_dsp_init()
245 struct hdac_stream *hstream = &hext_stream->hstream; in hda_cl_trigger()
249 /* code loader is special case that reuses stream ops */ in hda_cl_trigger()
254 reinit_completion(&hda_stream->ioc); in hda_cl_trigger()
257 1 << hstream->index, in hda_cl_trigger()
258 1 << hstream->index); in hda_cl_trigger()
267 hstream->running = true; in hda_cl_trigger()
279 struct hdac_stream *hstream = &hext_stream->hstream; in hda_cl_cleanup()
283 if (hstream->direction == SNDRV_PCM_STREAM_PLAYBACK) in hda_cl_cleanup()
289 hda_dsp_stream_put(sdev, hstream->direction, hstream->stream_tag); in hda_cl_cleanup()
290 hstream->running = 0; in hda_cl_cleanup()
291 hstream->substream = NULL; in hda_cl_cleanup()
303 dmab->area = NULL; in hda_cl_cleanup()
304 dmab->bytes = 0; in hda_cl_cleanup()
305 hstream->bufsize = 0; in hda_cl_cleanup()
306 hstream->format_val = 0; in hda_cl_cleanup()
317 struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata; in hda_cl_copy_fw()
318 const struct sof_intel_dsp_desc *chip = hda->desc; in hda_cl_copy_fw()
322 dev_dbg(sdev->dev, "Code loader DMA starting\n"); in hda_cl_copy_fw()
324 ret = hda_cl_trigger(sdev->dev, hext_stream, SNDRV_PCM_TRIGGER_START); in hda_cl_copy_fw()
326 dev_err(sdev->dev, "error: DMA trigger start failed\n"); in hda_cl_copy_fw()
330 dev_dbg(sdev->dev, "waiting for FW_ENTERED status\n"); in hda_cl_copy_fw()
333 chip->rom_status_reg, reg, in hda_cl_copy_fw()
344 dev_err(sdev->dev, in hda_cl_copy_fw()
346 __func__, chip->rom_status_reg); in hda_cl_copy_fw()
348 dev_dbg(sdev->dev, "Code loader FW_ENTERED status\n"); in hda_cl_copy_fw()
351 ret = hda_cl_trigger(sdev->dev, hext_stream, SNDRV_PCM_TRIGGER_STOP); in hda_cl_copy_fw()
353 dev_err(sdev->dev, "error: DMA trigger stop failed\n"); in hda_cl_copy_fw()
357 dev_dbg(sdev->dev, "Code loader DMA stopped\n"); in hda_cl_copy_fw()
365 struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata; in hda_dsp_cl_boot_firmware_iccmax()
378 iccmax_stream = hda_cl_prepare(sdev->dev, HDA_CL_STREAM_FORMAT, PAGE_SIZE, in hda_dsp_cl_boot_firmware_iccmax()
379 &hda->iccmax_dmab, persistent_cl_buffer, in hda_dsp_cl_boot_firmware_iccmax()
382 dev_err(sdev->dev, "error: dma prepare for ICCMAX stream failed\n"); in hda_dsp_cl_boot_firmware_iccmax()
392 ret1 = hda_cl_cleanup(sdev->dev, &hda->iccmax_dmab, in hda_dsp_cl_boot_firmware_iccmax()
395 dev_err(sdev->dev, "error: ICCMAX stream cleanup failed\n"); in hda_dsp_cl_boot_firmware_iccmax()
415 chip_info = get_chip_info(sdev->pdata); in hda_dsp_boot_imr()
416 if (chip_info->cl_init) in hda_dsp_boot_imr()
417 ret = chip_info->cl_init(sdev, 0, true); in hda_dsp_boot_imr()
419 ret = -EINVAL; in hda_dsp_boot_imr()
429 struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata; in hda_dsp_cl_boot_firmware()
430 struct snd_sof_pdata *plat_data = sdev->pdata; in hda_dsp_cl_boot_firmware()
431 const struct sof_dev_desc *desc = plat_data->desc; in hda_dsp_cl_boot_firmware()
437 if (hda->imrboot_supported && !sdev->first_boot && !hda->skip_imr_boot) { in hda_dsp_cl_boot_firmware()
438 dev_dbg(sdev->dev, "IMR restore supported, booting from IMR directly\n"); in hda_dsp_cl_boot_firmware()
439 hda->boot_iteration = 0; in hda_dsp_cl_boot_firmware()
442 hda->booted_from_imr = true; in hda_dsp_cl_boot_firmware()
446 dev_warn(sdev->dev, "IMR restore failed, trying to cold boot\n"); in hda_dsp_cl_boot_firmware()
449 hda->booted_from_imr = false; in hda_dsp_cl_boot_firmware()
451 chip_info = desc->chip_info; in hda_dsp_cl_boot_firmware()
453 if (sdev->basefw.fw->size <= sdev->basefw.payload_offset) { in hda_dsp_cl_boot_firmware()
454 dev_err(sdev->dev, "error: firmware size must be greater than firmware offset\n"); in hda_dsp_cl_boot_firmware()
455 return -EINVAL; in hda_dsp_cl_boot_firmware()
459 init_waitqueue_head(&sdev->boot_wait); in hda_dsp_cl_boot_firmware()
461 /* prepare DMA for code loader stream */ in hda_dsp_cl_boot_firmware()
462 stripped_firmware.size = sdev->basefw.fw->size - sdev->basefw.payload_offset; in hda_dsp_cl_boot_firmware()
463 hext_stream = hda_cl_prepare(sdev->dev, HDA_CL_STREAM_FORMAT, in hda_dsp_cl_boot_firmware()
465 &hda->cl_dmab, persistent_cl_buffer, in hda_dsp_cl_boot_firmware()
468 dev_err(sdev->dev, "error: dma prepare for fw loading failed\n"); in hda_dsp_cl_boot_firmware()
478 if (!persistent_cl_buffer || !hda->cl_dmab_contains_basefw) { in hda_dsp_cl_boot_firmware()
479 stripped_firmware.data = sdev->basefw.fw->data + sdev->basefw.payload_offset; in hda_dsp_cl_boot_firmware()
480 memcpy(hda->cl_dmab.area, stripped_firmware.data, stripped_firmware.size); in hda_dsp_cl_boot_firmware()
481 hda->cl_dmab_contains_basefw = true; in hda_dsp_cl_boot_firmware()
486 dev_dbg(sdev->dev, in hda_dsp_cl_boot_firmware()
489 hda->boot_iteration = i + 1; in hda_dsp_cl_boot_firmware()
490 if (chip_info->cl_init) in hda_dsp_cl_boot_firmware()
491 ret = chip_info->cl_init(sdev, hext_stream->hstream.stream_tag, false); in hda_dsp_cl_boot_firmware()
493 ret = -EINVAL; in hda_dsp_cl_boot_firmware()
501 dev_err(sdev->dev, "error: dsp init failed after %d attempts with err: %d\n", in hda_dsp_cl_boot_firmware()
508 * device may trigger in-band wakes for events such as jack in hda_dsp_cl_boot_firmware()
521 if (!sdev->first_boot) in hda_dsp_cl_boot_firmware()
531 hda->boot_iteration = HDA_FW_BOOT_ATTEMPTS; in hda_dsp_cl_boot_firmware()
534 dev_dbg(sdev->dev, "Firmware download successful, booting...\n"); in hda_dsp_cl_boot_firmware()
535 hda->skip_imr_boot = false; in hda_dsp_cl_boot_firmware()
539 hda->skip_imr_boot = true; in hda_dsp_cl_boot_firmware()
548 ret1 = hda_cl_cleanup(sdev->dev, &hda->cl_dmab, in hda_dsp_cl_boot_firmware()
551 dev_err(sdev->dev, "error: Code loader DSP cleanup failed\n"); in hda_dsp_cl_boot_firmware()
563 return chip_info->init_core_mask; in hda_dsp_cl_boot_firmware()
575 struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata; in hda_dsp_ipc4_load_library()
576 struct sof_ipc4_fw_data *ipc4_data = sdev->private; in hda_dsp_ipc4_load_library()
583 if (reload && hda->booted_from_imr && ipc4_data->fw_context_save) in hda_dsp_ipc4_load_library()
587 stripped_firmware.data = fw_lib->sof_fw.fw->data + fw_lib->sof_fw.payload_offset; in hda_dsp_ipc4_load_library()
588 stripped_firmware.size = fw_lib->sof_fw.fw->size - fw_lib->sof_fw.payload_offset; in hda_dsp_ipc4_load_library()
591 * force re-allocation of the cl_dmab if the preserved DMA buffer is in hda_dsp_ipc4_load_library()
594 if (persistent_cl_buffer && stripped_firmware.size > hda->cl_dmab.bytes) { in hda_dsp_ipc4_load_library()
595 snd_dma_free_pages(&hda->cl_dmab); in hda_dsp_ipc4_load_library()
596 hda->cl_dmab.area = NULL; in hda_dsp_ipc4_load_library()
597 hda->cl_dmab.bytes = 0; in hda_dsp_ipc4_load_library()
600 /* prepare DMA for code loader stream */ in hda_dsp_ipc4_load_library()
601 hext_stream = hda_cl_prepare(sdev->dev, HDA_CL_STREAM_FORMAT, in hda_dsp_ipc4_load_library()
603 &hda->cl_dmab, persistent_cl_buffer, in hda_dsp_ipc4_load_library()
606 dev_err(sdev->dev, "%s: DMA prepare failed\n", __func__); in hda_dsp_ipc4_load_library()
610 memcpy(hda->cl_dmab.area, stripped_firmware.data, stripped_firmware.size); in hda_dsp_ipc4_load_library()
611 hda->cl_dmab_contains_basefw = false; in hda_dsp_ipc4_load_library()
617 * receive -EOPNOTSUPP. In this case we will use single step library in hda_dsp_ipc4_load_library()
620 msg.primary = hext_stream->hstream.stream_tag - 1; in hda_dsp_ipc4_load_library()
624 ret = sof_ipc_tx_message_no_reply(sdev->ipc, &msg, 0); in hda_dsp_ipc4_load_library()
626 int sd_offset = SOF_STREAM_SD_OFFSET(&hext_stream->hstream); in hda_dsp_ipc4_load_library()
642 dev_warn(sdev->dev, in hda_dsp_ipc4_load_library()
644 } else if (ret != -EOPNOTSUPP) { in hda_dsp_ipc4_load_library()
648 ret = hda_cl_trigger(sdev->dev, hext_stream, SNDRV_PCM_TRIGGER_START); in hda_dsp_ipc4_load_library()
650 dev_err(sdev->dev, "%s: DMA trigger start failed\n", __func__); in hda_dsp_ipc4_load_library()
661 msg.primary |= SOF_IPC4_GLB_LOAD_LIBRARY_LIB_ID(fw_lib->id); in hda_dsp_ipc4_load_library()
662 ret = sof_ipc_tx_message_no_reply(sdev->ipc, &msg, 0); in hda_dsp_ipc4_load_library()
665 ret1 = hda_cl_trigger(sdev->dev, hext_stream, SNDRV_PCM_TRIGGER_STOP); in hda_dsp_ipc4_load_library()
667 dev_err(sdev->dev, "%s: DMA trigger stop failed\n", __func__); in hda_dsp_ipc4_load_library()
674 ret1 = hda_cl_cleanup(sdev->dev, &hda->cl_dmab, persistent_cl_buffer, in hda_dsp_ipc4_load_library()
677 dev_err(sdev->dev, "%s: Code loader DSP cleanup failed\n", __func__); in hda_dsp_ipc4_load_library()
693 struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata; in hda_dsp_ext_man_get_cavs_config_data()
697 elem_num = (hdr->size - sizeof(struct sof_ext_man_elem_header)) in hda_dsp_ext_man_get_cavs_config_data()
700 dev_err(sdev->dev, "cavs config data is inconsistent: %d\n", elem_num); in hda_dsp_ext_man_get_cavs_config_data()
701 return -EINVAL; in hda_dsp_ext_man_get_cavs_config_data()
705 switch (config_data->elems[i].token) { in hda_dsp_ext_man_get_cavs_config_data()
710 hda->clk_config_lpro = config_data->elems[i].value; in hda_dsp_ext_man_get_cavs_config_data()
711 dev_dbg(sdev->dev, "FW clock config: %s\n", in hda_dsp_ext_man_get_cavs_config_data()
712 hda->clk_config_lpro ? "LPRO" : "HPRO"); in hda_dsp_ext_man_get_cavs_config_data()
719 dev_info(sdev->dev, "unsupported token type: %d\n", in hda_dsp_ext_man_get_cavs_config_data()
720 config_data->elems[i].token); in hda_dsp_ext_man_get_cavs_config_data()