Merge series "SOF fixes and updates" from Ranjani Sridharan <ranjani.sridharan@linux.intel.com>:

This series includes fixes for error reporting, topology parsing and
runtime PM issues along with updates for DMIC support and IMX platforms.

Iulian Olaru (2):
  ASoC: SOF: imx: Replace sdev->private with sdev->pdata->hw_pdata
  ASoC: SOF: sof-of-dev: Add .arch_ops field

Jaska Uimonen (1):
  ASoC: SOF: intel: hda: support also devices with 1 and 3 dmics

Keyon Jie (1):
  ASoC: SOF: topology: fix the ipc_size calculation for process
    component

Rander Wang (1):
  ASoC: SOF: fix a runtime pm issue in SOF when HDMI codec doesn't work

Ranjani Sridharan (2):
  ASoC: SOF: Intel: hda: report error only for the last ROM init
    iteration
  ASoC: SOF: Intel: hda: add extended rom status dump to error log

 sound/soc/sof/imx/Kconfig        |  2 ++
 sound/soc/sof/imx/imx8.c         | 17 +++++++++----
 sound/soc/sof/imx/imx8m.c        | 10 +++++---
 sound/soc/sof/intel/hda-codec.c  |  4 +--
 sound/soc/sof/intel/hda-loader.c | 42 +++++++++++++++++++-------------
 sound/soc/sof/intel/hda.c        | 26 +++++++++++++++++++-
 sound/soc/sof/topology.c         |  4 +--
 7 files changed, 74 insertions(+), 31 deletions(-)

--
2.25.1
This commit is contained in:
Mark Brown 2020-08-26 13:19:18 +01:00
commit cd0f9228c7
No known key found for this signature in database
GPG Key ID: 24D68B725D5487D0
7 changed files with 75 additions and 32 deletions

View File

@ -30,6 +30,7 @@ config SND_SOC_SOF_IMX8_SUPPORT
config SND_SOC_SOF_IMX8 config SND_SOC_SOF_IMX8
tristate tristate
select SND_SOC_SOF_XTENSA
help help
This option is not user-selectable but automagically handled by This option is not user-selectable but automagically handled by
'select' statements at a higher level 'select' statements at a higher level
@ -44,6 +45,7 @@ config SND_SOC_SOF_IMX8M_SUPPORT
config SND_SOC_SOF_IMX8M config SND_SOC_SOF_IMX8M
tristate tristate
select SND_SOC_SOF_XTENSA
help help
This option is not user-selectable but automagically handled by This option is not user-selectable but automagically handled by
'select' statements at a higher level 'select' statements at a higher level

View File

@ -126,7 +126,7 @@ static struct imx_dsp_ops dsp_ops = {
static int imx8_send_msg(struct snd_sof_dev *sdev, struct snd_sof_ipc_msg *msg) static int imx8_send_msg(struct snd_sof_dev *sdev, struct snd_sof_ipc_msg *msg)
{ {
struct imx8_priv *priv = (struct imx8_priv *)sdev->private; struct imx8_priv *priv = sdev->pdata->hw_pdata;
sof_mailbox_write(sdev, sdev->host_box.offset, msg->msg_data, sof_mailbox_write(sdev, sdev->host_box.offset, msg->msg_data,
msg->msg_size); msg->msg_size);
@ -140,7 +140,7 @@ static int imx8_send_msg(struct snd_sof_dev *sdev, struct snd_sof_ipc_msg *msg)
*/ */
static int imx8x_run(struct snd_sof_dev *sdev) static int imx8x_run(struct snd_sof_dev *sdev)
{ {
struct imx8_priv *dsp_priv = (struct imx8_priv *)sdev->private; struct imx8_priv *dsp_priv = sdev->pdata->hw_pdata;
int ret; int ret;
ret = imx_sc_misc_set_control(dsp_priv->sc_ipc, IMX_SC_R_DSP, ret = imx_sc_misc_set_control(dsp_priv->sc_ipc, IMX_SC_R_DSP,
@ -180,7 +180,7 @@ static int imx8x_run(struct snd_sof_dev *sdev)
static int imx8_run(struct snd_sof_dev *sdev) static int imx8_run(struct snd_sof_dev *sdev)
{ {
struct imx8_priv *dsp_priv = (struct imx8_priv *)sdev->private; struct imx8_priv *dsp_priv = sdev->pdata->hw_pdata;
int ret; int ret;
ret = imx_sc_misc_set_control(dsp_priv->sc_ipc, IMX_SC_R_DSP, ret = imx_sc_misc_set_control(dsp_priv->sc_ipc, IMX_SC_R_DSP,
@ -213,7 +213,7 @@ static int imx8_probe(struct snd_sof_dev *sdev)
if (!priv) if (!priv)
return -ENOMEM; return -ENOMEM;
sdev->private = priv; sdev->pdata->hw_pdata = priv;
priv->dev = sdev->dev; priv->dev = sdev->dev;
priv->sdev = sdev; priv->sdev = sdev;
@ -339,7 +339,7 @@ static int imx8_probe(struct snd_sof_dev *sdev)
static int imx8_remove(struct snd_sof_dev *sdev) static int imx8_remove(struct snd_sof_dev *sdev)
{ {
struct imx8_priv *priv = (struct imx8_priv *)sdev->private; struct imx8_priv *priv = sdev->pdata->hw_pdata;
int i; int i;
platform_device_unregister(priv->ipc_dev); platform_device_unregister(priv->ipc_dev);
@ -424,6 +424,9 @@ struct snd_sof_dsp_ops sof_imx8_ops = {
/* firmware loading */ /* firmware loading */
.load_firmware = snd_sof_load_firmware_memcpy, .load_firmware = snd_sof_load_firmware_memcpy,
/* Firmware ops */
.arch_ops = &sof_xtensa_arch_ops,
/* DAI drivers */ /* DAI drivers */
.drv = imx8_dai, .drv = imx8_dai,
.num_drv = ARRAY_SIZE(imx8_dai), .num_drv = ARRAY_SIZE(imx8_dai),
@ -464,6 +467,9 @@ struct snd_sof_dsp_ops sof_imx8x_ops = {
/* firmware loading */ /* firmware loading */
.load_firmware = snd_sof_load_firmware_memcpy, .load_firmware = snd_sof_load_firmware_memcpy,
/* Firmware ops */
.arch_ops = &sof_xtensa_arch_ops,
/* DAI drivers */ /* DAI drivers */
.drv = imx8_dai, .drv = imx8_dai,
.num_drv = ARRAY_SIZE(imx8_dai), .num_drv = ARRAY_SIZE(imx8_dai),
@ -477,4 +483,5 @@ struct snd_sof_dsp_ops sof_imx8x_ops = {
}; };
EXPORT_SYMBOL(sof_imx8x_ops); EXPORT_SYMBOL(sof_imx8x_ops);
MODULE_IMPORT_NS(SND_SOC_SOF_XTENSA);
MODULE_LICENSE("Dual BSD/GPL"); MODULE_LICENSE("Dual BSD/GPL");

View File

@ -99,7 +99,7 @@ static struct imx_dsp_ops imx8m_dsp_ops = {
static int imx8m_send_msg(struct snd_sof_dev *sdev, struct snd_sof_ipc_msg *msg) static int imx8m_send_msg(struct snd_sof_dev *sdev, struct snd_sof_ipc_msg *msg)
{ {
struct imx8m_priv *priv = (struct imx8m_priv *)sdev->private; struct imx8m_priv *priv = sdev->pdata->hw_pdata;
sof_mailbox_write(sdev, sdev->host_box.offset, msg->msg_data, sof_mailbox_write(sdev, sdev->host_box.offset, msg->msg_data,
msg->msg_size); msg->msg_size);
@ -133,7 +133,7 @@ static int imx8m_probe(struct snd_sof_dev *sdev)
if (!priv) if (!priv)
return -ENOMEM; return -ENOMEM;
sdev->private = priv; sdev->pdata->hw_pdata = priv;
priv->dev = sdev->dev; priv->dev = sdev->dev;
priv->sdev = sdev; priv->sdev = sdev;
@ -209,7 +209,7 @@ static int imx8m_probe(struct snd_sof_dev *sdev)
static int imx8m_remove(struct snd_sof_dev *sdev) static int imx8m_remove(struct snd_sof_dev *sdev)
{ {
struct imx8m_priv *priv = (struct imx8m_priv *)sdev->private; struct imx8m_priv *priv = sdev->pdata->hw_pdata;
platform_device_unregister(priv->ipc_dev); platform_device_unregister(priv->ipc_dev);
@ -277,6 +277,9 @@ struct snd_sof_dsp_ops sof_imx8m_ops = {
/* firmware loading */ /* firmware loading */
.load_firmware = snd_sof_load_firmware_memcpy, .load_firmware = snd_sof_load_firmware_memcpy,
/* Firmware ops */
.arch_ops = &sof_xtensa_arch_ops,
/* DAI drivers */ /* DAI drivers */
.drv = imx8m_dai, .drv = imx8m_dai,
.num_drv = ARRAY_SIZE(imx8m_dai), .num_drv = ARRAY_SIZE(imx8m_dai),
@ -289,4 +292,5 @@ struct snd_sof_dsp_ops sof_imx8m_ops = {
}; };
EXPORT_SYMBOL(sof_imx8m_ops); EXPORT_SYMBOL(sof_imx8m_ops);
MODULE_IMPORT_NS(SND_SOC_SOF_XTENSA);
MODULE_LICENSE("Dual BSD/GPL"); MODULE_LICENSE("Dual BSD/GPL");

View File

@ -151,7 +151,7 @@ static int hda_codec_probe(struct snd_sof_dev *sdev, int address,
if (!hdev->bus->audio_component) { if (!hdev->bus->audio_component) {
dev_dbg(sdev->dev, dev_dbg(sdev->dev,
"iDisp hw present but no driver\n"); "iDisp hw present but no driver\n");
return -ENOENT; goto error;
} }
hda_priv->need_display_power = true; hda_priv->need_display_power = true;
} }
@ -174,7 +174,7 @@ static int hda_codec_probe(struct snd_sof_dev *sdev, int address,
* other return codes without modification * other return codes without modification
*/ */
if (ret == 0) if (ret == 0)
ret = -ENOENT; goto error;
} }
return ret; return ret;

View File

@ -79,7 +79,7 @@ static int cl_stream_prepare(struct snd_sof_dev *sdev, unsigned int format,
* reset/stall and then turn it off * reset/stall and then turn it off
*/ */
static int cl_dsp_init(struct snd_sof_dev *sdev, const void *fwdata, static int cl_dsp_init(struct snd_sof_dev *sdev, const void *fwdata,
u32 fwsize, int stream_tag) u32 fwsize, int stream_tag, int iteration)
{ {
struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata; struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata;
const struct sof_intel_dsp_desc *chip = hda->desc; const struct sof_intel_dsp_desc *chip = hda->desc;
@ -90,7 +90,8 @@ static int cl_dsp_init(struct snd_sof_dev *sdev, const void *fwdata,
/* step 1: power up corex */ /* step 1: power up corex */
ret = hda_dsp_core_power_up(sdev, chip->cores_mask); ret = hda_dsp_core_power_up(sdev, chip->cores_mask);
if (ret < 0) { if (ret < 0) {
dev_err(sdev->dev, "error: dsp core 0/1 power up failed\n"); if (iteration == HDA_FW_BOOT_ATTEMPTS)
dev_err(sdev->dev, "error: dsp core 0/1 power up failed\n");
goto err; goto err;
} }
@ -112,7 +113,9 @@ static int cl_dsp_init(struct snd_sof_dev *sdev, const void *fwdata,
/* step 3: unset core 0 reset state & unstall/run core 0 */ /* step 3: unset core 0 reset state & unstall/run core 0 */
ret = hda_dsp_core_run(sdev, HDA_DSP_CORE_MASK(0)); ret = hda_dsp_core_run(sdev, HDA_DSP_CORE_MASK(0));
if (ret < 0) { if (ret < 0) {
dev_err(sdev->dev, "error: dsp core start failed %d\n", ret); if (iteration == HDA_FW_BOOT_ATTEMPTS)
dev_err(sdev->dev,
"error: dsp core start failed %d\n", ret);
ret = -EIO; ret = -EIO;
goto err; goto err;
} }
@ -126,8 +129,10 @@ static int cl_dsp_init(struct snd_sof_dev *sdev, const void *fwdata,
HDA_DSP_INIT_TIMEOUT_US); HDA_DSP_INIT_TIMEOUT_US);
if (ret < 0) { if (ret < 0) {
dev_err(sdev->dev, "error: %s: timeout for HIPCIE done\n", if (iteration == HDA_FW_BOOT_ATTEMPTS)
__func__); dev_err(sdev->dev,
"error: %s: timeout for HIPCIE done\n",
__func__);
goto err; goto err;
} }
@ -141,7 +146,9 @@ static int cl_dsp_init(struct snd_sof_dev *sdev, const void *fwdata,
ret = hda_dsp_core_power_down(sdev, ret = hda_dsp_core_power_down(sdev,
chip->cores_mask & ~(HDA_DSP_CORE_MASK(0))); chip->cores_mask & ~(HDA_DSP_CORE_MASK(0)));
if (ret < 0) { if (ret < 0) {
dev_err(sdev->dev, "error: dsp core x power down failed\n"); if (iteration == HDA_FW_BOOT_ATTEMPTS)
dev_err(sdev->dev,
"error: dsp core x power down failed\n");
goto err; goto err;
} }
@ -159,9 +166,10 @@ static int cl_dsp_init(struct snd_sof_dev *sdev, const void *fwdata,
if (!ret) if (!ret)
return 0; return 0;
dev_err(sdev->dev, if (iteration == HDA_FW_BOOT_ATTEMPTS)
"error: %s: timeout HDA_DSP_SRAM_REG_ROM_STATUS read\n", dev_err(sdev->dev,
__func__); "error: %s: timeout HDA_DSP_SRAM_REG_ROM_STATUS read\n",
__func__);
err: err:
hda_dsp_dump(sdev, SOF_DBG_REGS | SOF_DBG_PCI | SOF_DBG_MBOX); hda_dsp_dump(sdev, SOF_DBG_REGS | SOF_DBG_PCI | SOF_DBG_MBOX);
@ -329,25 +337,25 @@ int hda_dsp_cl_boot_firmware(struct snd_sof_dev *sdev)
/* try ROM init a few times before giving up */ /* try ROM init a few times before giving up */
for (i = 0; i < HDA_FW_BOOT_ATTEMPTS; i++) { for (i = 0; i < HDA_FW_BOOT_ATTEMPTS; i++) {
dev_dbg(sdev->dev,
"Attempting iteration %d of Core En/ROM load...\n", i);
ret = cl_dsp_init(sdev, stripped_firmware.data, ret = cl_dsp_init(sdev, stripped_firmware.data,
stripped_firmware.size, tag); stripped_firmware.size, tag, i + 1);
/* don't retry anymore if successful */ /* don't retry anymore if successful */
if (!ret) if (!ret)
break; break;
dev_dbg(sdev->dev, "iteration %d of Core En/ROM load failed: %d\n",
i, ret);
dev_dbg(sdev->dev, "Error code=0x%x: FW status=0x%x\n",
snd_sof_dsp_read(sdev, HDA_DSP_BAR,
HDA_DSP_SRAM_REG_ROM_ERROR),
snd_sof_dsp_read(sdev, HDA_DSP_BAR,
HDA_DSP_SRAM_REG_ROM_STATUS));
} }
if (i == HDA_FW_BOOT_ATTEMPTS) { if (i == HDA_FW_BOOT_ATTEMPTS) {
dev_err(sdev->dev, "error: dsp init failed after %d attempts with err: %d\n", dev_err(sdev->dev, "error: dsp init failed after %d attempts with err: %d\n",
i, ret); i, ret);
dev_err(sdev->dev, "ROM error=0x%x: FW status=0x%x\n",
snd_sof_dsp_read(sdev, HDA_DSP_BAR,
HDA_DSP_SRAM_REG_ROM_ERROR),
snd_sof_dsp_read(sdev, HDA_DSP_BAR,
HDA_DSP_SRAM_REG_ROM_STATUS));
goto cleanup; goto cleanup;
} }

View File

@ -37,6 +37,7 @@
#include "shim.h" #include "shim.h"
#define EXCEPT_MAX_HDR_SIZE 0x400 #define EXCEPT_MAX_HDR_SIZE 0x400
#define HDA_EXT_ROM_STATUS_SIZE 8
#if IS_ENABLED(CONFIG_SND_SOC_SOF_INTEL_SOUNDWIRE) #if IS_ENABLED(CONFIG_SND_SOC_SOF_INTEL_SOUNDWIRE)
@ -414,6 +415,22 @@ void hda_dsp_dump_skl(struct snd_sof_dev *sdev, u32 flags)
} }
} }
/* dump the first 8 dwords representing the extended ROM status */
static void hda_dsp_dump_ext_rom_status(struct snd_sof_dev *sdev)
{
char msg[128];
int len = 0;
u32 value;
int i;
for (i = 0; i < HDA_EXT_ROM_STATUS_SIZE; i++) {
value = snd_sof_dsp_read(sdev, HDA_DSP_BAR, HDA_DSP_SRAM_REG_ROM_STATUS + i * 0x4);
len += snprintf(msg + len, sizeof(msg) - len, " 0x%x", value);
}
dev_err(sdev->dev, "error: extended rom status:%s", msg);
}
void hda_dsp_dump(struct snd_sof_dev *sdev, u32 flags) void hda_dsp_dump(struct snd_sof_dev *sdev, u32 flags)
{ {
struct sof_ipc_dsp_oops_xtensa xoops; struct sof_ipc_dsp_oops_xtensa xoops;
@ -437,6 +454,7 @@ void hda_dsp_dump(struct snd_sof_dev *sdev, u32 flags)
} else { } else {
dev_err(sdev->dev, "error: status = 0x%8.8x panic = 0x%8.8x\n", dev_err(sdev->dev, "error: status = 0x%8.8x panic = 0x%8.8x\n",
status, panic); status, panic);
hda_dsp_dump_ext_rom_status(sdev);
hda_dsp_get_status(sdev); hda_dsp_get_status(sdev);
} }
} }
@ -544,7 +562,7 @@ static int check_nhlt_dmic(struct snd_sof_dev *sdev)
if (nhlt) { if (nhlt) {
dmic_num = intel_nhlt_get_dmic_geo(sdev->dev, nhlt); dmic_num = intel_nhlt_get_dmic_geo(sdev->dev, nhlt);
intel_nhlt_free(nhlt); intel_nhlt_free(nhlt);
if (dmic_num == 2 || dmic_num == 4) if (dmic_num >= 1 && dmic_num <= 4)
return dmic_num; return dmic_num;
} }
@ -992,9 +1010,15 @@ static int hda_generic_machine_select(struct snd_sof_dev *sdev)
dmic_num = hda_dmic_num; dmic_num = hda_dmic_num;
switch (dmic_num) { switch (dmic_num) {
case 1:
dmic_str = "-1ch";
break;
case 2: case 2:
dmic_str = "-2ch"; dmic_str = "-2ch";
break; break;
case 3:
dmic_str = "-3ch";
break;
case 4: case 4:
dmic_str = "-4ch"; dmic_str = "-4ch";
break; break;

View File

@ -2114,9 +2114,7 @@ static int sof_process_load(struct snd_soc_component *scomp, int index,
goto out; goto out;
} }
ipc_size = sizeof(struct sof_ipc_comp_process) + ipc_size = sizeof(struct sof_ipc_comp_process) + ipc_data_size;
le32_to_cpu(private->size) +
ipc_data_size;
/* we are exceeding max ipc size, config needs to be sent separately */ /* we are exceeding max ipc size, config needs to be sent separately */
if (ipc_size > SOF_IPC_MSG_MAX_SIZE) { if (ipc_size > SOF_IPC_MSG_MAX_SIZE) {