hda-loader.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681
  1. // SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
  2. //
  3. // This file is provided under a dual BSD/GPLv2 license. When using or
  4. // redistributing this file, you may do so under either license.
  5. //
  6. // Copyright(c) 2018 Intel Corporation
  7. //
  8. // Authors: Liam Girdwood <liam.r.girdwood@linux.intel.com>
  9. // Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
  10. // Rander Wang <rander.wang@intel.com>
  11. // Keyon Jie <yang.jie@linux.intel.com>
  12. //
  13. /*
  14. * Hardware interface for HDA DSP code loader
  15. */
  16. #include <linux/firmware.h>
  17. #include <sound/hdaudio_ext.h>
  18. #include <sound/hda_register.h>
  19. #include <sound/sof.h>
  20. #include <sound/sof/ipc4/header.h>
  21. #include "ext_manifest.h"
  22. #include "../ipc4-priv.h"
  23. #include "../ops.h"
  24. #include "../sof-priv.h"
  25. #include "hda.h"
  26. static void hda_ssp_set_cbp_cfp(struct snd_sof_dev *sdev)
  27. {
  28. struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata;
  29. const struct sof_intel_dsp_desc *chip = hda->desc;
  30. int i;
  31. /* DSP is powered up, set all SSPs to clock consumer/codec provider mode */
  32. for (i = 0; i < chip->ssp_count; i++) {
  33. snd_sof_dsp_update_bits_unlocked(sdev, HDA_DSP_BAR,
  34. chip->ssp_base_offset
  35. + i * SSP_DEV_MEM_SIZE
  36. + SSP_SSC1_OFFSET,
  37. SSP_SET_CBP_CFP,
  38. SSP_SET_CBP_CFP);
  39. }
  40. }
  41. struct hdac_ext_stream *hda_cl_prepare(struct device *dev, unsigned int format,
  42. unsigned int size, struct snd_dma_buffer *dmab,
  43. int direction, bool is_iccmax)
  44. {
  45. struct snd_sof_dev *sdev = dev_get_drvdata(dev);
  46. struct hdac_ext_stream *hext_stream;
  47. struct hdac_stream *hstream;
  48. int ret;
  49. hext_stream = hda_dsp_stream_get(sdev, direction, 0);
  50. if (!hext_stream) {
  51. dev_err(sdev->dev, "error: no stream available\n");
  52. return ERR_PTR(-ENODEV);
  53. }
  54. hstream = &hext_stream->hstream;
  55. hstream->substream = NULL;
  56. /* allocate DMA buffer */
  57. ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV_SG, dev, size, dmab);
  58. if (ret < 0) {
  59. dev_err(sdev->dev, "error: memory alloc failed: %d\n", ret);
  60. goto out_put;
  61. }
  62. hstream->period_bytes = 0;/* initialize period_bytes */
  63. hstream->format_val = format;
  64. hstream->bufsize = size;
  65. if (is_iccmax) {
  66. ret = hda_dsp_iccmax_stream_hw_params(sdev, hext_stream, dmab, NULL);
  67. if (ret < 0) {
  68. dev_err(sdev->dev, "error: iccmax stream prepare failed: %d\n", ret);
  69. goto out_free;
  70. }
  71. } else {
  72. ret = hda_dsp_stream_hw_params(sdev, hext_stream, dmab, NULL);
  73. if (ret < 0) {
  74. dev_err(sdev->dev, "error: hdac prepare failed: %d\n", ret);
  75. goto out_free;
  76. }
  77. hda_dsp_stream_spib_config(sdev, hext_stream, HDA_DSP_SPIB_ENABLE, size);
  78. }
  79. return hext_stream;
  80. out_free:
  81. snd_dma_free_pages(dmab);
  82. out_put:
  83. hda_dsp_stream_put(sdev, direction, hstream->stream_tag);
  84. return ERR_PTR(ret);
  85. }
  86. EXPORT_SYMBOL_NS(hda_cl_prepare, SND_SOC_SOF_INTEL_HDA_COMMON);
  87. /*
  88. * first boot sequence has some extra steps.
  89. * power on all host managed cores and only unstall/run the boot core to boot the
  90. * DSP then turn off all non boot cores (if any) is powered on.
  91. */
  92. int cl_dsp_init(struct snd_sof_dev *sdev, int stream_tag, bool imr_boot)
  93. {
  94. struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata;
  95. const struct sof_intel_dsp_desc *chip = hda->desc;
  96. unsigned int status, target_status;
  97. u32 flags, ipc_hdr, j;
  98. unsigned long mask;
  99. char *dump_msg;
  100. int ret;
  101. /* step 1: power up corex */
  102. ret = hda_dsp_core_power_up(sdev, chip->host_managed_cores_mask);
  103. if (ret < 0) {
  104. if (hda->boot_iteration == HDA_FW_BOOT_ATTEMPTS)
  105. dev_err(sdev->dev, "error: dsp core 0/1 power up failed\n");
  106. goto err;
  107. }
  108. hda_ssp_set_cbp_cfp(sdev);
  109. /* step 2: Send ROM_CONTROL command (stream_tag is ignored for IMR boot) */
  110. ipc_hdr = chip->ipc_req_mask | HDA_DSP_ROM_IPC_CONTROL;
  111. if (!imr_boot)
  112. ipc_hdr |= HDA_DSP_ROM_IPC_PURGE_FW | ((stream_tag - 1) << 9);
  113. snd_sof_dsp_write(sdev, HDA_DSP_BAR, chip->ipc_req, ipc_hdr);
  114. /* step 3: unset core 0 reset state & unstall/run core 0 */
  115. ret = hda_dsp_core_run(sdev, chip->init_core_mask);
  116. if (ret < 0) {
  117. if (hda->boot_iteration == HDA_FW_BOOT_ATTEMPTS)
  118. dev_err(sdev->dev,
  119. "error: dsp core start failed %d\n", ret);
  120. ret = -EIO;
  121. goto err;
  122. }
  123. /* step 4: wait for IPC DONE bit from ROM */
  124. ret = snd_sof_dsp_read_poll_timeout(sdev, HDA_DSP_BAR,
  125. chip->ipc_ack, status,
  126. ((status & chip->ipc_ack_mask)
  127. == chip->ipc_ack_mask),
  128. HDA_DSP_REG_POLL_INTERVAL_US,
  129. HDA_DSP_INIT_TIMEOUT_US);
  130. if (ret < 0) {
  131. if (hda->boot_iteration == HDA_FW_BOOT_ATTEMPTS)
  132. dev_err(sdev->dev,
  133. "error: %s: timeout for HIPCIE done\n",
  134. __func__);
  135. goto err;
  136. }
  137. /* set DONE bit to clear the reply IPC message */
  138. snd_sof_dsp_update_bits_forced(sdev, HDA_DSP_BAR,
  139. chip->ipc_ack,
  140. chip->ipc_ack_mask,
  141. chip->ipc_ack_mask);
  142. /* step 5: power down cores that are no longer needed */
  143. ret = hda_dsp_core_reset_power_down(sdev, chip->host_managed_cores_mask &
  144. ~(chip->init_core_mask));
  145. if (ret < 0) {
  146. if (hda->boot_iteration == HDA_FW_BOOT_ATTEMPTS)
  147. dev_err(sdev->dev,
  148. "error: dsp core x power down failed\n");
  149. goto err;
  150. }
  151. /* step 6: enable IPC interrupts */
  152. hda_dsp_ipc_int_enable(sdev);
  153. /*
  154. * step 7:
  155. * - Cold/Full boot: wait for ROM init to proceed to download the firmware
  156. * - IMR boot: wait for ROM firmware entered (firmware booted up from IMR)
  157. */
  158. if (imr_boot)
  159. target_status = FSR_STATE_FW_ENTERED;
  160. else
  161. target_status = FSR_STATE_INIT_DONE;
  162. ret = snd_sof_dsp_read_poll_timeout(sdev, HDA_DSP_BAR,
  163. chip->rom_status_reg, status,
  164. (FSR_TO_STATE_CODE(status) == target_status),
  165. HDA_DSP_REG_POLL_INTERVAL_US,
  166. chip->rom_init_timeout *
  167. USEC_PER_MSEC);
  168. if (!ret) {
  169. /* set enabled cores mask and increment ref count for cores in init_core_mask */
  170. sdev->enabled_cores_mask |= chip->init_core_mask;
  171. mask = sdev->enabled_cores_mask;
  172. for_each_set_bit(j, &mask, SOF_MAX_DSP_NUM_CORES)
  173. sdev->dsp_core_ref_count[j]++;
  174. return 0;
  175. }
  176. if (hda->boot_iteration == HDA_FW_BOOT_ATTEMPTS)
  177. dev_err(sdev->dev,
  178. "%s: timeout with rom_status_reg (%#x) read\n",
  179. __func__, chip->rom_status_reg);
  180. err:
  181. flags = SOF_DBG_DUMP_PCI | SOF_DBG_DUMP_MBOX | SOF_DBG_DUMP_OPTIONAL;
  182. /* after max boot attempts make sure that the dump is printed */
  183. if (hda->boot_iteration == HDA_FW_BOOT_ATTEMPTS)
  184. flags &= ~SOF_DBG_DUMP_OPTIONAL;
  185. dump_msg = kasprintf(GFP_KERNEL, "Boot iteration failed: %d/%d",
  186. hda->boot_iteration, HDA_FW_BOOT_ATTEMPTS);
  187. snd_sof_dsp_dbg_dump(sdev, dump_msg, flags);
  188. hda_dsp_core_reset_power_down(sdev, chip->host_managed_cores_mask);
  189. kfree(dump_msg);
  190. return ret;
  191. }
  192. EXPORT_SYMBOL_NS(cl_dsp_init, SND_SOC_SOF_INTEL_HDA_COMMON);
  193. int hda_cl_trigger(struct device *dev, struct hdac_ext_stream *hext_stream, int cmd)
  194. {
  195. struct snd_sof_dev *sdev = dev_get_drvdata(dev);
  196. struct hdac_stream *hstream = &hext_stream->hstream;
  197. int sd_offset = SOF_STREAM_SD_OFFSET(hstream);
  198. struct sof_intel_hda_stream *hda_stream;
  199. /* code loader is special case that reuses stream ops */
  200. switch (cmd) {
  201. case SNDRV_PCM_TRIGGER_START:
  202. hda_stream = container_of(hext_stream, struct sof_intel_hda_stream,
  203. hext_stream);
  204. reinit_completion(&hda_stream->ioc);
  205. snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, SOF_HDA_INTCTL,
  206. 1 << hstream->index,
  207. 1 << hstream->index);
  208. snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR,
  209. sd_offset,
  210. SOF_HDA_SD_CTL_DMA_START |
  211. SOF_HDA_CL_DMA_SD_INT_MASK,
  212. SOF_HDA_SD_CTL_DMA_START |
  213. SOF_HDA_CL_DMA_SD_INT_MASK);
  214. hstream->running = true;
  215. return 0;
  216. default:
  217. return hda_dsp_stream_trigger(sdev, hext_stream, cmd);
  218. }
  219. }
  220. EXPORT_SYMBOL_NS(hda_cl_trigger, SND_SOC_SOF_INTEL_HDA_COMMON);
  221. int hda_cl_cleanup(struct device *dev, struct snd_dma_buffer *dmab,
  222. struct hdac_ext_stream *hext_stream)
  223. {
  224. struct snd_sof_dev *sdev = dev_get_drvdata(dev);
  225. struct hdac_stream *hstream = &hext_stream->hstream;
  226. int sd_offset = SOF_STREAM_SD_OFFSET(hstream);
  227. int ret = 0;
  228. if (hstream->direction == SNDRV_PCM_STREAM_PLAYBACK)
  229. ret = hda_dsp_stream_spib_config(sdev, hext_stream, HDA_DSP_SPIB_DISABLE, 0);
  230. else
  231. snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, sd_offset,
  232. SOF_HDA_SD_CTL_DMA_START, 0);
  233. hda_dsp_stream_put(sdev, hstream->direction, hstream->stream_tag);
  234. hstream->running = 0;
  235. hstream->substream = NULL;
  236. /* reset BDL address */
  237. snd_sof_dsp_write(sdev, HDA_DSP_HDA_BAR,
  238. sd_offset + SOF_HDA_ADSP_REG_SD_BDLPL, 0);
  239. snd_sof_dsp_write(sdev, HDA_DSP_HDA_BAR,
  240. sd_offset + SOF_HDA_ADSP_REG_SD_BDLPU, 0);
  241. snd_sof_dsp_write(sdev, HDA_DSP_HDA_BAR, sd_offset, 0);
  242. snd_dma_free_pages(dmab);
  243. dmab->area = NULL;
  244. hstream->bufsize = 0;
  245. hstream->format_val = 0;
  246. return ret;
  247. }
  248. EXPORT_SYMBOL_NS(hda_cl_cleanup, SND_SOC_SOF_INTEL_HDA_COMMON);
  249. #define HDA_CL_DMA_IOC_TIMEOUT_MS 500
  250. int hda_cl_copy_fw(struct snd_sof_dev *sdev, struct hdac_ext_stream *hext_stream)
  251. {
  252. struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata;
  253. const struct sof_intel_dsp_desc *chip = hda->desc;
  254. unsigned int reg;
  255. int ret, status;
  256. dev_dbg(sdev->dev, "Code loader DMA starting\n");
  257. ret = hda_cl_trigger(sdev->dev, hext_stream, SNDRV_PCM_TRIGGER_START);
  258. if (ret < 0) {
  259. dev_err(sdev->dev, "error: DMA trigger start failed\n");
  260. return ret;
  261. }
  262. dev_dbg(sdev->dev, "waiting for FW_ENTERED status\n");
  263. status = snd_sof_dsp_read_poll_timeout(sdev, HDA_DSP_BAR,
  264. chip->rom_status_reg, reg,
  265. (FSR_TO_STATE_CODE(reg) == FSR_STATE_FW_ENTERED),
  266. HDA_DSP_REG_POLL_INTERVAL_US,
  267. HDA_DSP_BASEFW_TIMEOUT_US);
  268. /*
  269. * even in case of errors we still need to stop the DMAs,
  270. * but we return the initial error should the DMA stop also fail
  271. */
  272. if (status < 0) {
  273. dev_err(sdev->dev,
  274. "%s: timeout with rom_status_reg (%#x) read\n",
  275. __func__, chip->rom_status_reg);
  276. } else {
  277. dev_dbg(sdev->dev, "Code loader FW_ENTERED status\n");
  278. }
  279. ret = hda_cl_trigger(sdev->dev, hext_stream, SNDRV_PCM_TRIGGER_STOP);
  280. if (ret < 0) {
  281. dev_err(sdev->dev, "error: DMA trigger stop failed\n");
  282. if (!status)
  283. status = ret;
  284. } else {
  285. dev_dbg(sdev->dev, "Code loader DMA stopped\n");
  286. }
  287. return status;
  288. }
  289. int hda_dsp_cl_boot_firmware_iccmax(struct snd_sof_dev *sdev)
  290. {
  291. struct hdac_ext_stream *iccmax_stream;
  292. struct snd_dma_buffer dmab_bdl;
  293. int ret, ret1;
  294. u8 original_gb;
  295. /* save the original LTRP guardband value */
  296. original_gb = snd_sof_dsp_read8(sdev, HDA_DSP_HDA_BAR, HDA_VS_INTEL_LTRP) &
  297. HDA_VS_INTEL_LTRP_GB_MASK;
  298. /*
  299. * Prepare capture stream for ICCMAX. We do not need to store
  300. * the data, so use a buffer of PAGE_SIZE for receiving.
  301. */
  302. iccmax_stream = hda_cl_prepare(sdev->dev, HDA_CL_STREAM_FORMAT, PAGE_SIZE,
  303. &dmab_bdl, SNDRV_PCM_STREAM_CAPTURE, true);
  304. if (IS_ERR(iccmax_stream)) {
  305. dev_err(sdev->dev, "error: dma prepare for ICCMAX stream failed\n");
  306. return PTR_ERR(iccmax_stream);
  307. }
  308. ret = hda_dsp_cl_boot_firmware(sdev);
  309. /*
  310. * Perform iccmax stream cleanup. This should be done even if firmware loading fails.
  311. * If the cleanup also fails, we return the initial error
  312. */
  313. ret1 = hda_cl_cleanup(sdev->dev, &dmab_bdl, iccmax_stream);
  314. if (ret1 < 0) {
  315. dev_err(sdev->dev, "error: ICCMAX stream cleanup failed\n");
  316. /* set return value to indicate cleanup failure */
  317. if (!ret)
  318. ret = ret1;
  319. }
  320. /* restore the original guardband value after FW boot */
  321. snd_sof_dsp_update8(sdev, HDA_DSP_HDA_BAR, HDA_VS_INTEL_LTRP,
  322. HDA_VS_INTEL_LTRP_GB_MASK, original_gb);
  323. return ret;
  324. }
  325. EXPORT_SYMBOL_NS(hda_dsp_cl_boot_firmware_iccmax, SND_SOC_SOF_INTEL_CNL);
  326. static int hda_dsp_boot_imr(struct snd_sof_dev *sdev)
  327. {
  328. const struct sof_intel_dsp_desc *chip_info;
  329. int ret;
  330. chip_info = get_chip_info(sdev->pdata);
  331. if (chip_info->cl_init)
  332. ret = chip_info->cl_init(sdev, 0, true);
  333. else
  334. ret = -EINVAL;
  335. if (!ret)
  336. hda_sdw_process_wakeen(sdev);
  337. return ret;
  338. }
  339. int hda_dsp_cl_boot_firmware(struct snd_sof_dev *sdev)
  340. {
  341. struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata;
  342. struct snd_sof_pdata *plat_data = sdev->pdata;
  343. const struct sof_dev_desc *desc = plat_data->desc;
  344. const struct sof_intel_dsp_desc *chip_info;
  345. struct hdac_ext_stream *hext_stream;
  346. struct firmware stripped_firmware;
  347. struct snd_dma_buffer dmab;
  348. int ret, ret1, i;
  349. if (hda->imrboot_supported && !sdev->first_boot && !hda->skip_imr_boot) {
  350. dev_dbg(sdev->dev, "IMR restore supported, booting from IMR directly\n");
  351. hda->boot_iteration = 0;
  352. ret = hda_dsp_boot_imr(sdev);
  353. if (!ret) {
  354. hda->booted_from_imr = true;
  355. return 0;
  356. }
  357. dev_warn(sdev->dev, "IMR restore failed, trying to cold boot\n");
  358. }
  359. hda->booted_from_imr = false;
  360. chip_info = desc->chip_info;
  361. if (sdev->basefw.fw->size <= sdev->basefw.payload_offset) {
  362. dev_err(sdev->dev, "error: firmware size must be greater than firmware offset\n");
  363. return -EINVAL;
  364. }
  365. stripped_firmware.data = sdev->basefw.fw->data + sdev->basefw.payload_offset;
  366. stripped_firmware.size = sdev->basefw.fw->size - sdev->basefw.payload_offset;
  367. /* init for booting wait */
  368. init_waitqueue_head(&sdev->boot_wait);
  369. /* prepare DMA for code loader stream */
  370. hext_stream = hda_cl_prepare(sdev->dev, HDA_CL_STREAM_FORMAT,
  371. stripped_firmware.size,
  372. &dmab, SNDRV_PCM_STREAM_PLAYBACK, false);
  373. if (IS_ERR(hext_stream)) {
  374. dev_err(sdev->dev, "error: dma prepare for fw loading failed\n");
  375. return PTR_ERR(hext_stream);
  376. }
  377. memcpy(dmab.area, stripped_firmware.data,
  378. stripped_firmware.size);
  379. /* try ROM init a few times before giving up */
  380. for (i = 0; i < HDA_FW_BOOT_ATTEMPTS; i++) {
  381. dev_dbg(sdev->dev,
  382. "Attempting iteration %d of Core En/ROM load...\n", i);
  383. hda->boot_iteration = i + 1;
  384. if (chip_info->cl_init)
  385. ret = chip_info->cl_init(sdev, hext_stream->hstream.stream_tag, false);
  386. else
  387. ret = -EINVAL;
  388. /* don't retry anymore if successful */
  389. if (!ret)
  390. break;
  391. }
  392. if (i == HDA_FW_BOOT_ATTEMPTS) {
  393. dev_err(sdev->dev, "error: dsp init failed after %d attempts with err: %d\n",
  394. i, ret);
  395. goto cleanup;
  396. }
  397. /*
  398. * When a SoundWire link is in clock stop state, a Slave
  399. * device may trigger in-band wakes for events such as jack
  400. * insertion or acoustic event detection. This event will lead
  401. * to a WAKEEN interrupt, handled by the PCI device and routed
  402. * to PME if the PCI device is in D3. The resume function in
  403. * audio PCI driver will be invoked by ACPI for PME event and
  404. * initialize the device and process WAKEEN interrupt.
  405. *
  406. * The WAKEEN interrupt should be processed ASAP to prevent an
  407. * interrupt flood, otherwise other interrupts, such IPC,
  408. * cannot work normally. The WAKEEN is handled after the ROM
  409. * is initialized successfully, which ensures power rails are
  410. * enabled before accessing the SoundWire SHIM registers
  411. */
  412. if (!sdev->first_boot)
  413. hda_sdw_process_wakeen(sdev);
  414. /*
  415. * Set the boot_iteration to the last attempt, indicating that the
  416. * DSP ROM has been initialized and from this point there will be no
  417. * retry done to boot.
  418. *
  419. * Continue with code loading and firmware boot
  420. */
  421. hda->boot_iteration = HDA_FW_BOOT_ATTEMPTS;
  422. ret = hda_cl_copy_fw(sdev, hext_stream);
  423. if (!ret) {
  424. dev_dbg(sdev->dev, "Firmware download successful, booting...\n");
  425. hda->skip_imr_boot = false;
  426. } else {
  427. snd_sof_dsp_dbg_dump(sdev, "Firmware download failed",
  428. SOF_DBG_DUMP_PCI | SOF_DBG_DUMP_MBOX);
  429. hda->skip_imr_boot = true;
  430. }
  431. cleanup:
  432. /*
  433. * Perform codeloader stream cleanup.
  434. * This should be done even if firmware loading fails.
  435. * If the cleanup also fails, we return the initial error
  436. */
  437. ret1 = hda_cl_cleanup(sdev->dev, &dmab, hext_stream);
  438. if (ret1 < 0) {
  439. dev_err(sdev->dev, "error: Code loader DSP cleanup failed\n");
  440. /* set return value to indicate cleanup failure */
  441. if (!ret)
  442. ret = ret1;
  443. }
  444. /*
  445. * return primary core id if both fw copy
  446. * and stream clean up are successful
  447. */
  448. if (!ret)
  449. return chip_info->init_core_mask;
  450. /* disable DSP */
  451. hda_dsp_ctrl_ppcap_enable(sdev, false);
  452. return ret;
  453. }
  454. EXPORT_SYMBOL_NS(hda_dsp_cl_boot_firmware, SND_SOC_SOF_INTEL_HDA_COMMON);
  455. int hda_dsp_ipc4_load_library(struct snd_sof_dev *sdev,
  456. struct sof_ipc4_fw_library *fw_lib, bool reload)
  457. {
  458. struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata;
  459. struct sof_ipc4_fw_data *ipc4_data = sdev->private;
  460. struct hdac_ext_stream *hext_stream;
  461. struct firmware stripped_firmware;
  462. struct sof_ipc4_msg msg = {};
  463. struct snd_dma_buffer dmab;
  464. int ret, ret1;
  465. /* if IMR booting is enabled and fw context is saved for D3 state, skip the loading */
  466. if (reload && hda->booted_from_imr && ipc4_data->fw_context_save)
  467. return 0;
  468. /* the fw_lib has been verified during loading, we can trust the validity here */
  469. stripped_firmware.data = fw_lib->sof_fw.fw->data + fw_lib->sof_fw.payload_offset;
  470. stripped_firmware.size = fw_lib->sof_fw.fw->size - fw_lib->sof_fw.payload_offset;
  471. /* prepare DMA for code loader stream */
  472. hext_stream = hda_cl_prepare(sdev->dev, HDA_CL_STREAM_FORMAT,
  473. stripped_firmware.size,
  474. &dmab, SNDRV_PCM_STREAM_PLAYBACK, false);
  475. if (IS_ERR(hext_stream)) {
  476. dev_err(sdev->dev, "%s: DMA prepare failed\n", __func__);
  477. return PTR_ERR(hext_stream);
  478. }
  479. memcpy(dmab.area, stripped_firmware.data, stripped_firmware.size);
  480. /*
  481. * 1st stage: SOF_IPC4_GLB_LOAD_LIBRARY_PREPARE
  482. * Message includes the dma_id to be prepared for the library loading.
  483. * If the firmware does not have support for the message, we will
  484. * receive -EOPNOTSUPP. In this case we will use single step library
  485. * loading and proceed to send the LOAD_LIBRARY message.
  486. */
  487. msg.primary = hext_stream->hstream.stream_tag - 1;
  488. msg.primary |= SOF_IPC4_MSG_TYPE_SET(SOF_IPC4_GLB_LOAD_LIBRARY_PREPARE);
  489. msg.primary |= SOF_IPC4_MSG_DIR(SOF_IPC4_MSG_REQUEST);
  490. msg.primary |= SOF_IPC4_MSG_TARGET(SOF_IPC4_FW_GEN_MSG);
  491. ret = sof_ipc_tx_message_no_reply(sdev->ipc, &msg, 0);
  492. if (!ret) {
  493. int sd_offset = SOF_STREAM_SD_OFFSET(&hext_stream->hstream);
  494. unsigned int status;
  495. /*
  496. * Make sure that the FIFOS value is not 0 in SDxFIFOS register
  497. * which indicates that the firmware set the GEN bit and we can
  498. * continue to start the DMA
  499. */
  500. ret = snd_sof_dsp_read_poll_timeout(sdev, HDA_DSP_HDA_BAR,
  501. sd_offset + SOF_HDA_ADSP_REG_SD_FIFOSIZE,
  502. status,
  503. status & SOF_HDA_SD_FIFOSIZE_FIFOS_MASK,
  504. HDA_DSP_REG_POLL_INTERVAL_US,
  505. HDA_DSP_BASEFW_TIMEOUT_US);
  506. if (ret < 0)
  507. dev_warn(sdev->dev,
  508. "%s: timeout waiting for FIFOS\n", __func__);
  509. } else if (ret != -EOPNOTSUPP) {
  510. goto cleanup;
  511. }
  512. ret = hda_cl_trigger(sdev->dev, hext_stream, SNDRV_PCM_TRIGGER_START);
  513. if (ret < 0) {
  514. dev_err(sdev->dev, "%s: DMA trigger start failed\n", __func__);
  515. goto cleanup;
  516. }
  517. /*
  518. * 2nd stage: LOAD_LIBRARY
  519. * Message includes the dma_id and the lib_id, the dma_id must be
  520. * identical to the one sent via LOAD_LIBRARY_PREPARE
  521. */
  522. msg.primary &= ~SOF_IPC4_MSG_TYPE_MASK;
  523. msg.primary |= SOF_IPC4_MSG_TYPE_SET(SOF_IPC4_GLB_LOAD_LIBRARY);
  524. msg.primary |= SOF_IPC4_GLB_LOAD_LIBRARY_LIB_ID(fw_lib->id);
  525. ret = sof_ipc_tx_message_no_reply(sdev->ipc, &msg, 0);
  526. /* Stop the DMA channel */
  527. ret1 = hda_cl_trigger(sdev->dev, hext_stream, SNDRV_PCM_TRIGGER_STOP);
  528. if (ret1 < 0) {
  529. dev_err(sdev->dev, "%s: DMA trigger stop failed\n", __func__);
  530. if (!ret)
  531. ret = ret1;
  532. }
  533. cleanup:
  534. /* clean up even in case of error and return the first error */
  535. ret1 = hda_cl_cleanup(sdev->dev, &dmab, hext_stream);
  536. if (ret1 < 0) {
  537. dev_err(sdev->dev, "%s: Code loader DSP cleanup failed\n", __func__);
  538. /* set return value to indicate cleanup failure */
  539. if (!ret)
  540. ret = ret1;
  541. }
  542. return ret;
  543. }
  544. EXPORT_SYMBOL_NS(hda_dsp_ipc4_load_library, SND_SOC_SOF_INTEL_HDA_COMMON);
  545. int hda_dsp_ext_man_get_cavs_config_data(struct snd_sof_dev *sdev,
  546. const struct sof_ext_man_elem_header *hdr)
  547. {
  548. const struct sof_ext_man_cavs_config_data *config_data =
  549. container_of(hdr, struct sof_ext_man_cavs_config_data, hdr);
  550. struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata;
  551. int i, elem_num;
  552. /* calculate total number of config data elements */
  553. elem_num = (hdr->size - sizeof(struct sof_ext_man_elem_header))
  554. / sizeof(struct sof_config_elem);
  555. if (elem_num <= 0) {
  556. dev_err(sdev->dev, "cavs config data is inconsistent: %d\n", elem_num);
  557. return -EINVAL;
  558. }
  559. for (i = 0; i < elem_num; i++)
  560. switch (config_data->elems[i].token) {
  561. case SOF_EXT_MAN_CAVS_CONFIG_EMPTY:
  562. /* skip empty token */
  563. break;
  564. case SOF_EXT_MAN_CAVS_CONFIG_CAVS_LPRO:
  565. hda->clk_config_lpro = config_data->elems[i].value;
  566. dev_dbg(sdev->dev, "FW clock config: %s\n",
  567. hda->clk_config_lpro ? "LPRO" : "HPRO");
  568. break;
  569. case SOF_EXT_MAN_CAVS_CONFIG_OUTBOX_SIZE:
  570. case SOF_EXT_MAN_CAVS_CONFIG_INBOX_SIZE:
  571. /* These elements are defined but not being used yet. No warn is required */
  572. break;
  573. default:
  574. dev_info(sdev->dev, "unsupported token type: %d\n",
  575. config_data->elems[i].token);
  576. }
  577. return 0;
  578. }
  579. EXPORT_SYMBOL_NS(hda_dsp_ext_man_get_cavs_config_data, SND_SOC_SOF_INTEL_HDA_COMMON);