From 2310452bd36b7b151dc6c631eb27436aad7539c5 Mon Sep 17 00:00:00 2001 From: Zhu Yingjiang Date: Mon, 10 Sep 2018 17:06:29 +0800 Subject: [PATCH] ASoC:SOF:skl:enable the core and get the ROM init 1. enable the skl core 2. get the ROM int Signed-off-by: Zhu Yingjiang --- sound/soc/sof/intel/hda-dsp.c | 15 +++ sound/soc/sof/intel/hda-loader.c | 153 +++++++++++++++++++++++++++++++ sound/soc/sof/intel/hda.h | 4 + sound/soc/sof/intel/skl.c | 2 +- 4 files changed, 173 insertions(+), 1 deletion(-) diff --git a/sound/soc/sof/intel/hda-dsp.c b/sound/soc/sof/intel/hda-dsp.c index 640bf0692413c0..d8400d85c9ae39 100644 --- a/sound/soc/sof/intel/hda-dsp.c +++ b/sound/soc/sof/intel/hda-dsp.c @@ -208,6 +208,21 @@ bool hda_dsp_core_is_enabled(struct snd_sof_dev *sdev, return is_enable; } +int hda_dsp_enable_core(struct snd_sof_dev *sdev, unsigned int core_mask) +{ + int ret; + + /* power up */ + ret = hda_dsp_core_power_up(sdev, core_mask); + if (ret < 0) { + dev_err(sdev->dev, "dsp core power up failed: core_mask %x\n", + core_mask); + return ret; + } + + return hda_dsp_core_run(sdev, core_mask); +} + int hda_dsp_core_reset_power_down(struct snd_sof_dev *sdev, unsigned int core_mask) { diff --git a/sound/soc/sof/intel/hda-loader.c b/sound/soc/sof/intel/hda-loader.c index 796d772a6a8d30..e6bc88af88f164 100644 --- a/sound/soc/sof/intel/hda-loader.c +++ b/sound/soc/sof/intel/hda-loader.c @@ -372,3 +372,156 @@ int hda_dsp_cl_boot_firmware(struct snd_sof_dev *sdev) dev_err(sdev->dev, "error: load fw failed err: %d\n", ret); return ret; } + +/* + * skl/kbl enable core and code loader DMA has some difference with apl/cnl + * add the APIs for skl/kbl + */ +static int cl_stream_prepare_skl(struct snd_sof_dev *sdev, unsigned int format, + unsigned int size, struct snd_dma_buffer *dmab, + int direction) +{ + /* the skl cl dma don't use stream tag, ret is for debug */ + int ret = 0; + return ret; +} + +static int cl_dsp_init_skl(struct snd_sof_dev *sdev, const void *fwdata, + u32 fwsize) +{ + const struct sof_intel_dsp_desc *chip = sdev->hda->desc; + int ret, i; + u32 hipcie; + u32 reg; + + /* check if the core is already enabled, if yes, reset and make it run, + * if not, powerdown and enable it again. + */ + if (hda_dsp_core_is_enabled(sdev, HDA_DSP_CORE_MASK(0))) { + /* if enabled, reset it, and run the core. */ + ret = hda_dsp_core_stall_reset(sdev, HDA_DSP_CORE_MASK(0)); + if (ret < 0) + goto err; + + ret = hda_dsp_core_run(sdev, HDA_DSP_CORE_MASK(0)); + if (ret < 0) { + dev_err(sdev->dev, "error: dsp core start failed %d\n", + ret); + ret = -EIO; + goto err; + } + } else { + /* if not enabled, power down it first and then powerup and run + * the core. + */ + ret = hda_dsp_core_reset_power_down(sdev, HDA_DSP_CORE_MASK(0)); + if (ret < 0) { + dev_err(sdev->dev, "dsp core0 disable fail: %d\n", ret); + return ret; + } + ret = hda_dsp_enable_core(sdev, HDA_DSP_CORE_MASK(0)); + } + + /* prepare DMA for code loader stream */ + ret = cl_stream_prepare_skl(sdev, 0x40, fwsize, &sdev->dmab, + SNDRV_PCM_STREAM_PLAYBACK); + + if (ret <= 0) { + dev_err(sdev->dev, "error: dma prepare fw loading err: %x\n", + ret); + return ret; + } + + memcpy(sdev->dmab.area, fwdata, fwsize); + + /* enable the interrupt */ + snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, HDA_DSP_REG_ADSPIC, + HDA_DSP_ADSPIC_IPC, HDA_DSP_ADSPIC_IPC); + + /* enable IPC DONE interrupt */ + snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, chip->ipc_ctl, + HDA_DSP_REG_HIPCCTL_DONE, + HDA_DSP_REG_HIPCCTL_DONE); + + /* enable IPC BUSY interrupt */ + snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, chip->ipc_ctl, + HDA_DSP_REG_HIPCCTL_BUSY, + HDA_DSP_REG_HIPCCTL_BUSY); + + /* polling the ROM init status information. */ + ret = snd_sof_dsp_register_poll(sdev, HDA_DSP_BAR, + HDA_DSP_SRAM_REG_ROM_STATUS_SKL, + HDA_DSP_ROM_STS_MASK, HDA_DSP_ROM_INIT, + HDA_DSP_INIT_TIMEOUT); + if (ret >= 0) { + dev_err(sdev->dev, "error: can't read the ROM status!"); + goto out; + } + + ret = -EIO; + +err: + hda_dsp_dump(sdev, SOF_DBG_REGS | SOF_DBG_PCI | SOF_DBG_MBOX); + hda_dsp_core_reset_power_down(sdev, HDA_DSP_CORE_MASK(0)); +out: + return ret; +} + +static int cl_copy_fw_skl(struct snd_sof_dev *sdev) +{ + return -1; +} + +int hda_dsp_cl_boot_firmware_skl(struct snd_sof_dev *sdev) +{ + struct snd_sof_pdata *plat_data = dev_get_platdata(sdev->dev); + struct firmware stripped_firmware; + int ret; + + stripped_firmware.data = plat_data->fw->data; + stripped_firmware.size = plat_data->fw->size; + + ret = cl_dsp_init_skl(sdev, stripped_firmware.data, + stripped_firmware.size); + + /* retry enabling core and ROM load. seemed to help */ + if (ret < 0) { + ret = cl_dsp_init_skl(sdev, stripped_firmware.data, + stripped_firmware.size); + if (ret <= 0) { + dev_err(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)); + dev_err(sdev->dev, "Core En/ROM load fail:%d\n", ret); + goto irq_err; + } + } + + /* init for booting wait */ + init_waitqueue_head(&sdev->boot_wait); + sdev->boot_complete = false; + + /* at this point DSP ROM has been initialized and should be ready for + * code loading and firmware boot + */ + ret = cl_copy_fw_skl(sdev); + if (ret < 0) { + dev_err(sdev->dev, "error: load fw failed err: %d\n", ret); + goto irq_err; + } + + dev_dbg(sdev->dev, "Firmware download successful, booting...\n"); + + return ret; + +irq_err: + hda_dsp_dump(sdev, SOF_DBG_REGS | SOF_DBG_PCI | SOF_DBG_MBOX); + + /* disable DSP */ + snd_sof_dsp_update_bits(sdev, HDA_DSP_PP_BAR, SOF_HDA_REG_PP_PPCTL, + SOF_HDA_PPCTL_GPROCEN, 0); + dev_err(sdev->dev, "error: load fw failed err: %d\n", ret); + return ret; +} diff --git a/sound/soc/sof/intel/hda.h b/sound/soc/sof/intel/hda.h index d44b2550e87fcd..e49547313511bf 100644 --- a/sound/soc/sof/intel/hda.h +++ b/sound/soc/sof/intel/hda.h @@ -322,6 +322,8 @@ #define SOF_SKL_NUM_DAIS 8 #endif +#define HDA_DSP_SRAM_REG_ROM_STATUS_SKL 0x8000 + struct sof_intel_dsp_bdl { u32 addr_l; u32 addr_h; @@ -377,6 +379,7 @@ int hda_dsp_core_reset_leave(struct snd_sof_dev *sdev, int hda_dsp_core_stall_reset(struct snd_sof_dev *sdev, unsigned int core_mask); int hda_dsp_core_run(struct snd_sof_dev *sdev, unsigned int core_mask); int hda_dsp_core_power_up(struct snd_sof_dev *sdev, unsigned int core_mask); +int hda_dsp_enable_core(struct snd_sof_dev *sdev, unsigned int core_mask); int hda_dsp_core_power_down(struct snd_sof_dev *sdev, unsigned int core_mask); bool hda_dsp_core_is_enabled(struct snd_sof_dev *sdev, unsigned int core_mask); @@ -466,6 +469,7 @@ int hda_dsp_ipc_cmd_done(struct snd_sof_dev *sdev, int dir); */ int hda_dsp_cl_load_fw(struct snd_sof_dev *sdev, bool first_boot); int hda_dsp_cl_boot_firmware(struct snd_sof_dev *sdev); +int hda_dsp_cl_boot_firmware_skl(struct snd_sof_dev *sdev); /* * HDA Controller Operations. diff --git a/sound/soc/sof/intel/skl.c b/sound/soc/sof/intel/skl.c index ab7cd2b689cba9..43b0bc169438fe 100644 --- a/sound/soc/sof/intel/skl.c +++ b/sound/soc/sof/intel/skl.c @@ -86,7 +86,7 @@ struct snd_sof_dsp_ops sof_skl_ops = { .load_firmware = hda_dsp_cl_load_fw, /* firmware run */ - .run = hda_dsp_cl_boot_firmware, + .run = hda_dsp_cl_boot_firmware_skl, /* trace callback */ .trace_init = hda_dsp_trace_init,