[alsa-devel] [PATCH 0/8] ASoC: Intel: Skylake: Add Broxton DSP support
Broxton DSP is similar to Skylake with similar DSP capabilities but differs in a few subtle ways. It doesn't have Code Loader DMA and use HDA DMA. The DSP power up/down routines are also bit different in the two platforms. Also the FW needs to be downloaded only once and not on every power sequence as it is cached by DSP in protected memory region.
All these changes for new DSP ops are abstracted in a new BXTN-dsp ops file.
This patch series starts with moving code around to prepare for new code and also fix whitespace issue in existing code. Since we have different loader ops we move Skylake ones to newly defined ops. Then we add device IDs and lastly the broxton ops.
Jayachandran B (1): ASoC: Intel: Skylake: Unstatify skl_dsp_enable_core
Jeeja KP (4): ASoC: Intel: add dmabuffer to common sst_dsp ASoC: Intel: Skylake: Move Skylake dsp ops & loader ops ASoC: hdac_hdmi: Add broxton device ID ASoC: Intel: Bxtn: Add Broxton DSP support
Senthilnathan Veppur (1): ASoC: Intel: Bxtn: Add Broxton PCI ID
Vinod Koul (2): ASoC: Intel: Skylake: Move module id defines ASoC: Intel: Skylake: Fix whitepsace issues
sound/soc/codecs/hdac_hdmi.c | 1 + sound/soc/intel/Kconfig | 1 + sound/soc/intel/common/sst-dsp-priv.h | 1 + sound/soc/intel/skylake/Makefile | 2 +- sound/soc/intel/skylake/bxt-sst.c | 328 +++++++++++++++++++++++++++++++++ sound/soc/intel/skylake/skl-messages.c | 182 +++++++++++++++++- sound/soc/intel/skylake/skl-sst-dsp.c | 14 +- sound/soc/intel/skylake/skl-sst-dsp.h | 20 +- sound/soc/intel/skylake/skl-sst.c | 3 - sound/soc/intel/skylake/skl.c | 7 + sound/soc/intel/skylake/skl.h | 12 +- 11 files changed, 549 insertions(+), 22 deletions(-) create mode 100644 sound/soc/intel/skylake/bxt-sst.c
The module ID defines are common to other platforms so can be reused if moved to a common driver header so move it
Signed-off-by: Jeeja KP jeeja.kp@intel.com Signed-off-by: Vinod Koul vinod.koul@intel.com --- sound/soc/intel/skylake/skl-sst-dsp.h | 4 ++++ sound/soc/intel/skylake/skl-sst.c | 3 --- 2 files changed, 4 insertions(+), 3 deletions(-)
diff --git a/sound/soc/intel/skylake/skl-sst-dsp.h b/sound/soc/intel/skylake/skl-sst-dsp.h index cbb40751c37e..a82c3de1a228 100644 --- a/sound/soc/intel/skylake/skl-sst-dsp.h +++ b/sound/soc/intel/skylake/skl-sst-dsp.h @@ -53,6 +53,10 @@ struct sst_dsp_device; /* HIPCT */ #define SKL_ADSP_REG_HIPCT_BUSY BIT(31)
+/* FW base IDs */ +#define SKL_INSTANCE_ID 0 +#define SKL_BASE_FW_MODULE_ID 0 + /* Intel HD Audio SRAM Window 1 */ #define SKL_ADSP_SRAM1_BASE 0xA000
diff --git a/sound/soc/intel/skylake/skl-sst.c b/sound/soc/intel/skylake/skl-sst.c index e26f4746afb7..348a734f8e24 100644 --- a/sound/soc/intel/skylake/skl-sst.c +++ b/sound/soc/intel/skylake/skl-sst.c @@ -35,9 +35,6 @@ #define SKL_ADSP_FW_STATUS SKL_ADSP_SRAM0_BASE #define SKL_ADSP_ERROR_CODE (SKL_ADSP_FW_STATUS + 0x4)
-#define SKL_INSTANCE_ID 0 -#define SKL_BASE_FW_MODULE_ID 0 - #define SKL_NUM_MODULES 1
static bool skl_check_fw_status(struct sst_dsp *ctx, u32 status)
The patch
ASoC: Intel: Skylake: Move module id defines
has been applied to the asoc tree at
git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git
All being well this means that it will be integrated into the linux-next tree (usually sometime in the next 24 hours) and sent to Linus during the next merge window (or sooner if it is a bug fix), however if problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing and review of the tree, please engage with people reporting problems and send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they should be sent as incremental updates against current git, existing patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying to this mail.
Thanks, Mark
From 39fa37d51ae904968c49ef49165df7fec66fd9ea Mon Sep 17 00:00:00 2001
From: Vinod Koul vinod.koul@intel.com Date: Fri, 11 Mar 2016 10:12:49 +0530 Subject: [PATCH] ASoC: Intel: Skylake: Move module id defines
The module ID defines are common to other platforms so can be reused if moved to a common driver header so move it
Signed-off-by: Jeeja KP jeeja.kp@intel.com Signed-off-by: Vinod Koul vinod.koul@intel.com Signed-off-by: Mark Brown broonie@kernel.org --- sound/soc/intel/skylake/skl-sst-dsp.h | 4 ++++ sound/soc/intel/skylake/skl-sst.c | 3 --- 2 files changed, 4 insertions(+), 3 deletions(-)
diff --git a/sound/soc/intel/skylake/skl-sst-dsp.h b/sound/soc/intel/skylake/skl-sst-dsp.h index cbb40751c37e..a82c3de1a228 100644 --- a/sound/soc/intel/skylake/skl-sst-dsp.h +++ b/sound/soc/intel/skylake/skl-sst-dsp.h @@ -53,6 +53,10 @@ struct sst_dsp_device; /* HIPCT */ #define SKL_ADSP_REG_HIPCT_BUSY BIT(31)
+/* FW base IDs */ +#define SKL_INSTANCE_ID 0 +#define SKL_BASE_FW_MODULE_ID 0 + /* Intel HD Audio SRAM Window 1 */ #define SKL_ADSP_SRAM1_BASE 0xA000
diff --git a/sound/soc/intel/skylake/skl-sst.c b/sound/soc/intel/skylake/skl-sst.c index e26f4746afb7..348a734f8e24 100644 --- a/sound/soc/intel/skylake/skl-sst.c +++ b/sound/soc/intel/skylake/skl-sst.c @@ -35,9 +35,6 @@ #define SKL_ADSP_FW_STATUS SKL_ADSP_SRAM0_BASE #define SKL_ADSP_ERROR_CODE (SKL_ADSP_FW_STATUS + 0x4)
-#define SKL_INSTANCE_ID 0 -#define SKL_BASE_FW_MODULE_ID 0 - #define SKL_NUM_MODULES 1
static bool skl_check_fw_status(struct sst_dsp *ctx, u32 status)
Some double whitespaces issues existed in driver, so fix them up.
Signed-off-by: Vinod Koul vinod.koul@intel.com --- sound/soc/intel/skylake/skl-sst-dsp.c | 14 +++++++------- sound/soc/intel/skylake/skl-sst-dsp.h | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/sound/soc/intel/skylake/skl-sst-dsp.c b/sound/soc/intel/skylake/skl-sst-dsp.c index 1bfb7f63b572..646d10a0d176 100644 --- a/sound/soc/intel/skylake/skl-sst-dsp.c +++ b/sound/soc/intel/skylake/skl-sst-dsp.c @@ -34,7 +34,7 @@ void skl_dsp_set_state_locked(struct sst_dsp *ctx, int state) mutex_unlock(&ctx->mutex); }
-static int skl_dsp_core_set_reset_state(struct sst_dsp *ctx) +static int skl_dsp_core_set_reset_state(struct sst_dsp *ctx) { int ret;
@@ -60,7 +60,7 @@ static int skl_dsp_core_set_reset_state(struct sst_dsp *ctx) return ret; }
-static int skl_dsp_core_unset_reset_state(struct sst_dsp *ctx) +static int skl_dsp_core_unset_reset_state(struct sst_dsp *ctx) { int ret;
@@ -87,7 +87,7 @@ static int skl_dsp_core_unset_reset_state(struct sst_dsp *ctx) return ret; }
-static bool is_skl_dsp_core_enable(struct sst_dsp *ctx) +static bool is_skl_dsp_core_enable(struct sst_dsp *ctx) { int val; bool is_enable; @@ -140,7 +140,7 @@ static int skl_dsp_start_core(struct sst_dsp *ctx) return ret; }
-static int skl_dsp_core_power_up(struct sst_dsp *ctx) +static int skl_dsp_core_power_up(struct sst_dsp *ctx) { int ret;
@@ -166,7 +166,7 @@ static int skl_dsp_core_power_up(struct sst_dsp *ctx) return ret; }
-static int skl_dsp_core_power_down(struct sst_dsp *ctx) +static int skl_dsp_core_power_down(struct sst_dsp *ctx) { /* update bits */ sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_ADSPCS, @@ -181,7 +181,7 @@ static int skl_dsp_core_power_down(struct sst_dsp *ctx) "Power down"); }
-static int skl_dsp_enable_core(struct sst_dsp *ctx) +static int skl_dsp_enable_core(struct sst_dsp *ctx) { int ret;
@@ -195,7 +195,7 @@ static int skl_dsp_enable_core(struct sst_dsp *ctx) return skl_dsp_start_core(ctx); }
-int skl_dsp_disable_core(struct sst_dsp *ctx) +int skl_dsp_disable_core(struct sst_dsp *ctx) { int ret;
diff --git a/sound/soc/intel/skylake/skl-sst-dsp.h b/sound/soc/intel/skylake/skl-sst-dsp.h index a82c3de1a228..676e78be0169 100644 --- a/sound/soc/intel/skylake/skl-sst-dsp.h +++ b/sound/soc/intel/skylake/skl-sst-dsp.h @@ -148,7 +148,7 @@ int skl_cldma_prepare(struct sst_dsp *ctx); void skl_dsp_set_state_locked(struct sst_dsp *ctx, int state); struct sst_dsp *skl_dsp_ctx_init(struct device *dev, struct sst_dsp_device *sst_dev, int irq); -int skl_dsp_disable_core(struct sst_dsp *ctx); +int skl_dsp_disable_core(struct sst_dsp *ctx); bool is_skl_dsp_running(struct sst_dsp *ctx); irqreturn_t skl_dsp_sst_interrupt(int irq, void *dev_id); int skl_dsp_wake(struct sst_dsp *ctx);
The patch
ASoC: Intel: Skylake: Fix whitepsace issues
has been applied to the asoc tree at
git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git
All being well this means that it will be integrated into the linux-next tree (usually sometime in the next 24 hours) and sent to Linus during the next merge window (or sooner if it is a bug fix), however if problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing and review of the tree, please engage with people reporting problems and send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they should be sent as incremental updates against current git, existing patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying to this mail.
Thanks, Mark
From a360b623fc5593d896a8762153bacdabfe29dfb9 Mon Sep 17 00:00:00 2001
From: Vinod Koul vinod.koul@intel.com Date: Fri, 11 Mar 2016 10:12:50 +0530 Subject: [PATCH] ASoC: Intel: Skylake: Fix whitepsace issues
Some double whitespaces issues existed in driver, so fix them up.
Signed-off-by: Vinod Koul vinod.koul@intel.com Signed-off-by: Mark Brown broonie@kernel.org --- sound/soc/intel/skylake/skl-sst-dsp.c | 14 +++++++------- sound/soc/intel/skylake/skl-sst-dsp.h | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/sound/soc/intel/skylake/skl-sst-dsp.c b/sound/soc/intel/skylake/skl-sst-dsp.c index 1bfb7f63b572..646d10a0d176 100644 --- a/sound/soc/intel/skylake/skl-sst-dsp.c +++ b/sound/soc/intel/skylake/skl-sst-dsp.c @@ -34,7 +34,7 @@ void skl_dsp_set_state_locked(struct sst_dsp *ctx, int state) mutex_unlock(&ctx->mutex); }
-static int skl_dsp_core_set_reset_state(struct sst_dsp *ctx) +static int skl_dsp_core_set_reset_state(struct sst_dsp *ctx) { int ret;
@@ -60,7 +60,7 @@ static int skl_dsp_core_set_reset_state(struct sst_dsp *ctx) return ret; }
-static int skl_dsp_core_unset_reset_state(struct sst_dsp *ctx) +static int skl_dsp_core_unset_reset_state(struct sst_dsp *ctx) { int ret;
@@ -87,7 +87,7 @@ static int skl_dsp_core_unset_reset_state(struct sst_dsp *ctx) return ret; }
-static bool is_skl_dsp_core_enable(struct sst_dsp *ctx) +static bool is_skl_dsp_core_enable(struct sst_dsp *ctx) { int val; bool is_enable; @@ -140,7 +140,7 @@ static int skl_dsp_start_core(struct sst_dsp *ctx) return ret; }
-static int skl_dsp_core_power_up(struct sst_dsp *ctx) +static int skl_dsp_core_power_up(struct sst_dsp *ctx) { int ret;
@@ -166,7 +166,7 @@ static int skl_dsp_core_power_up(struct sst_dsp *ctx) return ret; }
-static int skl_dsp_core_power_down(struct sst_dsp *ctx) +static int skl_dsp_core_power_down(struct sst_dsp *ctx) { /* update bits */ sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_ADSPCS, @@ -181,7 +181,7 @@ static int skl_dsp_core_power_down(struct sst_dsp *ctx) "Power down"); }
-static int skl_dsp_enable_core(struct sst_dsp *ctx) +static int skl_dsp_enable_core(struct sst_dsp *ctx) { int ret;
@@ -195,7 +195,7 @@ static int skl_dsp_enable_core(struct sst_dsp *ctx) return skl_dsp_start_core(ctx); }
-int skl_dsp_disable_core(struct sst_dsp *ctx) +int skl_dsp_disable_core(struct sst_dsp *ctx) { int ret;
diff --git a/sound/soc/intel/skylake/skl-sst-dsp.h b/sound/soc/intel/skylake/skl-sst-dsp.h index a82c3de1a228..676e78be0169 100644 --- a/sound/soc/intel/skylake/skl-sst-dsp.h +++ b/sound/soc/intel/skylake/skl-sst-dsp.h @@ -148,7 +148,7 @@ int skl_cldma_prepare(struct sst_dsp *ctx); void skl_dsp_set_state_locked(struct sst_dsp *ctx, int state); struct sst_dsp *skl_dsp_ctx_init(struct device *dev, struct sst_dsp_device *sst_dev, int irq); -int skl_dsp_disable_core(struct sst_dsp *ctx); +int skl_dsp_disable_core(struct sst_dsp *ctx); bool is_skl_dsp_running(struct sst_dsp *ctx); irqreturn_t skl_dsp_sst_interrupt(int irq, void *dev_id); int skl_dsp_wake(struct sst_dsp *ctx);
From: Jayachandran B jayachandran.b@intel.com
The function skl_dsp_enable_core will be called by other parts of driver so this can no longer be a static function.
Signed-off-by: Jayachandran B jayachandran.b@intel.com Signed-off-by: GuruprasadX Pawse guruprasadx.pawse@intel.com Signed-off-by: Vinod Koul vinod.koul@intel.com --- sound/soc/intel/skylake/skl-sst-dsp.c | 2 +- sound/soc/intel/skylake/skl-sst-dsp.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-)
diff --git a/sound/soc/intel/skylake/skl-sst-dsp.c b/sound/soc/intel/skylake/skl-sst-dsp.c index 646d10a0d176..a5267e8a96e0 100644 --- a/sound/soc/intel/skylake/skl-sst-dsp.c +++ b/sound/soc/intel/skylake/skl-sst-dsp.c @@ -181,7 +181,7 @@ static int skl_dsp_core_power_down(struct sst_dsp *ctx) "Power down"); }
-static int skl_dsp_enable_core(struct sst_dsp *ctx) +int skl_dsp_enable_core(struct sst_dsp *ctx) { int ret;
diff --git a/sound/soc/intel/skylake/skl-sst-dsp.h b/sound/soc/intel/skylake/skl-sst-dsp.h index 676e78be0169..b6e310d49dd6 100644 --- a/sound/soc/intel/skylake/skl-sst-dsp.h +++ b/sound/soc/intel/skylake/skl-sst-dsp.h @@ -148,6 +148,7 @@ int skl_cldma_prepare(struct sst_dsp *ctx); void skl_dsp_set_state_locked(struct sst_dsp *ctx, int state); struct sst_dsp *skl_dsp_ctx_init(struct device *dev, struct sst_dsp_device *sst_dev, int irq); +int skl_dsp_enable_core(struct sst_dsp *ctx); int skl_dsp_disable_core(struct sst_dsp *ctx); bool is_skl_dsp_running(struct sst_dsp *ctx); irqreturn_t skl_dsp_sst_interrupt(int irq, void *dev_id);
The patch
ASoC: Intel: Skylake: Unstatify skl_dsp_enable_core
has been applied to the asoc tree at
git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git
All being well this means that it will be integrated into the linux-next tree (usually sometime in the next 24 hours) and sent to Linus during the next merge window (or sooner if it is a bug fix), however if problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing and review of the tree, please engage with people reporting problems and send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they should be sent as incremental updates against current git, existing patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying to this mail.
Thanks, Mark
From 130e69a4773fb65af284d3fd1f3de762324d06e6 Mon Sep 17 00:00:00 2001
From: Jayachandran B jayachandran.b@intel.com Date: Fri, 11 Mar 2016 10:12:51 +0530 Subject: [PATCH] ASoC: Intel: Skylake: Unstatify skl_dsp_enable_core
The function skl_dsp_enable_core will be called by other parts of driver so this can no longer be a static function.
Signed-off-by: Jayachandran B jayachandran.b@intel.com Signed-off-by: GuruprasadX Pawse guruprasadx.pawse@intel.com Signed-off-by: Vinod Koul vinod.koul@intel.com Signed-off-by: Mark Brown broonie@kernel.org --- sound/soc/intel/skylake/skl-sst-dsp.c | 2 +- sound/soc/intel/skylake/skl-sst-dsp.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-)
diff --git a/sound/soc/intel/skylake/skl-sst-dsp.c b/sound/soc/intel/skylake/skl-sst-dsp.c index 646d10a0d176..a5267e8a96e0 100644 --- a/sound/soc/intel/skylake/skl-sst-dsp.c +++ b/sound/soc/intel/skylake/skl-sst-dsp.c @@ -181,7 +181,7 @@ static int skl_dsp_core_power_down(struct sst_dsp *ctx) "Power down"); }
-static int skl_dsp_enable_core(struct sst_dsp *ctx) +int skl_dsp_enable_core(struct sst_dsp *ctx) { int ret;
diff --git a/sound/soc/intel/skylake/skl-sst-dsp.h b/sound/soc/intel/skylake/skl-sst-dsp.h index 676e78be0169..b6e310d49dd6 100644 --- a/sound/soc/intel/skylake/skl-sst-dsp.h +++ b/sound/soc/intel/skylake/skl-sst-dsp.h @@ -148,6 +148,7 @@ int skl_cldma_prepare(struct sst_dsp *ctx); void skl_dsp_set_state_locked(struct sst_dsp *ctx, int state); struct sst_dsp *skl_dsp_ctx_init(struct device *dev, struct sst_dsp_device *sst_dev, int irq); +int skl_dsp_enable_core(struct sst_dsp *ctx); int skl_dsp_disable_core(struct sst_dsp *ctx); bool is_skl_dsp_running(struct sst_dsp *ctx); irqreturn_t skl_dsp_sst_interrupt(int irq, void *dev_id);
From: Jeeja KP jeeja.kp@intel.com
Broxton uses HDA DMA so needs to keep dmab in the driver context so add it
Signed-off-by: GuruprasadX Pawse guruprasadx.pawse@intel.com Signed-off-by: Jeeja KP jeeja.kp@intel.com Signed-off-by: Vinod Koul vinod.koul@intel.com --- sound/soc/intel/common/sst-dsp-priv.h | 1 + 1 file changed, 1 insertion(+)
diff --git a/sound/soc/intel/common/sst-dsp-priv.h b/sound/soc/intel/common/sst-dsp-priv.h index 81aa1ed64201..97dc1ae05e69 100644 --- a/sound/soc/intel/common/sst-dsp-priv.h +++ b/sound/soc/intel/common/sst-dsp-priv.h @@ -317,6 +317,7 @@ struct sst_dsp { struct skl_cl_dev cl_dev; u32 intr_status; const struct firmware *fw; + struct snd_dma_buffer dmab; };
/* Size optimised DRAM/IRAM memcpy */
The patch
ASoC: Intel: add dmabuffer to common sst_dsp
has been applied to the asoc tree at
git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git
All being well this means that it will be integrated into the linux-next tree (usually sometime in the next 24 hours) and sent to Linus during the next merge window (or sooner if it is a bug fix), however if problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing and review of the tree, please engage with people reporting problems and send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they should be sent as incremental updates against current git, existing patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying to this mail.
Thanks, Mark
From b822ee63586c7150c10b445ae6b4bb29486f01e4 Mon Sep 17 00:00:00 2001
From: Jeeja KP jeeja.kp@intel.com Date: Fri, 11 Mar 2016 10:12:52 +0530 Subject: [PATCH] ASoC: Intel: add dmabuffer to common sst_dsp
Broxton uses HDA DMA so needs to keep dmab in the driver context so add it
Signed-off-by: GuruprasadX Pawse guruprasadx.pawse@intel.com Signed-off-by: Jeeja KP jeeja.kp@intel.com Signed-off-by: Vinod Koul vinod.koul@intel.com Signed-off-by: Mark Brown broonie@kernel.org --- sound/soc/intel/common/sst-dsp-priv.h | 1 + 1 file changed, 1 insertion(+)
diff --git a/sound/soc/intel/common/sst-dsp-priv.h b/sound/soc/intel/common/sst-dsp-priv.h index 81aa1ed64201..97dc1ae05e69 100644 --- a/sound/soc/intel/common/sst-dsp-priv.h +++ b/sound/soc/intel/common/sst-dsp-priv.h @@ -317,6 +317,7 @@ struct sst_dsp { struct skl_cl_dev cl_dev; u32 intr_status; const struct firmware *fw; + struct snd_dma_buffer dmab; };
/* Size optimised DRAM/IRAM memcpy */
From: Jeeja KP jeeja.kp@intel.com
The code loading for Skylake and other platforms is different, so add a dsp_ops and a loader_ops which can be defined for each platform.
Move the dsp init, cleanup and loader ops (alloc and free dma) to these ops
Signed-off-by: Jeeja KP jeeja.kp@intel.com Signed-off-by: Vinod Koul vinod.koul@intel.com --- sound/soc/intel/skylake/skl-messages.c | 62 +++++++++++++++++++++++++++++----- sound/soc/intel/skylake/skl.h | 12 ++++++- 2 files changed, 64 insertions(+), 10 deletions(-)
diff --git a/sound/soc/intel/skylake/skl-messages.c b/sound/soc/intel/skylake/skl-messages.c index 737934cc620d..79c5089b85d6 100644 --- a/sound/soc/intel/skylake/skl-messages.c +++ b/sound/soc/intel/skylake/skl-messages.c @@ -72,17 +72,47 @@ static void skl_dsp_enable_notification(struct skl_sst *ctx, bool enable) skl_ipc_set_large_config(&ctx->ipc, &msg, (u32 *)&mask); }
+static struct skl_dsp_loader_ops skl_get_loader_ops(void) +{ + struct skl_dsp_loader_ops loader_ops; + + memset(&loader_ops, 0, sizeof(struct skl_dsp_loader_ops)); + + loader_ops.alloc_dma_buf = skl_alloc_dma_buf; + loader_ops.free_dma_buf = skl_free_dma_buf; + + return loader_ops; +}; + +static const struct skl_dsp_ops dsp_ops[] = { + { + .id = 0x9d70, + .loader_ops = skl_get_loader_ops, + .init = skl_sst_dsp_init, + .cleanup = skl_sst_dsp_cleanup + }, +}; + +static int skl_get_dsp_ops(int pci_id) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(dsp_ops); i++) { + if (dsp_ops[i].id == pci_id) + return i; + } + + return -EINVAL; +} + int skl_init_dsp(struct skl *skl) { void __iomem *mmio_base; struct hdac_ext_bus *ebus = &skl->ebus; struct hdac_bus *bus = ebus_to_hbus(ebus); - int irq = bus->irq; struct skl_dsp_loader_ops loader_ops; - int ret; - - loader_ops.alloc_dma_buf = skl_alloc_dma_buf; - loader_ops.free_dma_buf = skl_free_dma_buf; + int irq = bus->irq; + int ret, index;
/* enable ppcap interrupt */ snd_hdac_ext_bus_ppcap_enable(&skl->ebus, true); @@ -95,8 +125,14 @@ int skl_init_dsp(struct skl *skl) return -ENXIO; }
- ret = skl_sst_dsp_init(bus->dev, mmio_base, irq, + index = skl_get_dsp_ops(skl->pci->device); + if (index < 0) + return -EINVAL; + + loader_ops = dsp_ops[index].loader_ops(); + ret = dsp_ops[index].init(bus->dev, mmio_base, irq, skl->fw_name, loader_ops, &skl->skl_sst); + if (ret < 0) return ret;
@@ -106,18 +142,26 @@ int skl_init_dsp(struct skl *skl) return ret; }
-void skl_free_dsp(struct skl *skl) +int skl_free_dsp(struct skl *skl) { struct hdac_ext_bus *ebus = &skl->ebus; struct hdac_bus *bus = ebus_to_hbus(ebus); - struct skl_sst *ctx = skl->skl_sst; + struct skl_sst *ctx = skl->skl_sst; + int index;
/* disable ppcap interrupt */ snd_hdac_ext_bus_ppcap_int_enable(&skl->ebus, false);
- skl_sst_dsp_cleanup(bus->dev, ctx); + index = skl_get_dsp_ops(skl->pci->device); + if (index < 0) + return -EIO; + + dsp_ops[index].cleanup(bus->dev, ctx); + if (ctx->dsp->addr.lpe) iounmap(ctx->dsp->addr.lpe); + + return 0; }
int skl_suspend_dsp(struct skl *skl) diff --git a/sound/soc/intel/skylake/skl.h b/sound/soc/intel/skylake/skl.h index 1ca1911f1587..39e16fa7a92b 100644 --- a/sound/soc/intel/skylake/skl.h +++ b/sound/soc/intel/skylake/skl.h @@ -90,6 +90,16 @@ struct skl_dma_params { u8 stream_tag; };
+struct skl_dsp_ops { + int id; + struct skl_dsp_loader_ops (*loader_ops)(void); + int (*init)(struct device *dev, void __iomem *mmio_base, + int irq, const char *fw_name, + struct skl_dsp_loader_ops loader_ops, + struct skl_sst **skl_sst); + void (*cleanup)(struct device *dev, struct skl_sst *ctx); +}; + int skl_platform_unregister(struct device *dev); int skl_platform_register(struct device *dev);
@@ -100,7 +110,7 @@ struct nhlt_specific_cfg *skl_get_ep_blob(struct skl *skl, u32 instance,
int skl_nhlt_update_topology_bin(struct skl *skl); int skl_init_dsp(struct skl *skl); -void skl_free_dsp(struct skl *skl); +int skl_free_dsp(struct skl *skl); int skl_suspend_dsp(struct skl *skl); int skl_resume_dsp(struct skl *skl); #endif /* __SOUND_SOC_SKL_H */
The patch
ASoC: Intel: Skylake: Move Skylake dsp ops & loader ops
has been applied to the asoc tree at
git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git
All being well this means that it will be integrated into the linux-next tree (usually sometime in the next 24 hours) and sent to Linus during the next merge window (or sooner if it is a bug fix), however if problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing and review of the tree, please engage with people reporting problems and send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they should be sent as incremental updates against current git, existing patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying to this mail.
Thanks, Mark
From bc23ca35cfb18b0a98afa42de1df1efc7e2e9f8f Mon Sep 17 00:00:00 2001
From: Jeeja KP jeeja.kp@intel.com Date: Fri, 11 Mar 2016 10:12:53 +0530 Subject: [PATCH] ASoC: Intel: Skylake: Move Skylake dsp ops & loader ops
The code loading for Skylake and other platforms is different, so add a dsp_ops and a loader_ops which can be defined for each platform.
Move the dsp init, cleanup and loader ops (alloc and free dma) to these ops
Signed-off-by: Jeeja KP jeeja.kp@intel.com Signed-off-by: Vinod Koul vinod.koul@intel.com Signed-off-by: Mark Brown broonie@kernel.org --- sound/soc/intel/skylake/skl-messages.c | 62 +++++++++++++++++++++++++++++----- sound/soc/intel/skylake/skl.h | 12 ++++++- 2 files changed, 64 insertions(+), 10 deletions(-)
diff --git a/sound/soc/intel/skylake/skl-messages.c b/sound/soc/intel/skylake/skl-messages.c index 737934cc620d..79c5089b85d6 100644 --- a/sound/soc/intel/skylake/skl-messages.c +++ b/sound/soc/intel/skylake/skl-messages.c @@ -72,17 +72,47 @@ static void skl_dsp_enable_notification(struct skl_sst *ctx, bool enable) skl_ipc_set_large_config(&ctx->ipc, &msg, (u32 *)&mask); }
+static struct skl_dsp_loader_ops skl_get_loader_ops(void) +{ + struct skl_dsp_loader_ops loader_ops; + + memset(&loader_ops, 0, sizeof(struct skl_dsp_loader_ops)); + + loader_ops.alloc_dma_buf = skl_alloc_dma_buf; + loader_ops.free_dma_buf = skl_free_dma_buf; + + return loader_ops; +}; + +static const struct skl_dsp_ops dsp_ops[] = { + { + .id = 0x9d70, + .loader_ops = skl_get_loader_ops, + .init = skl_sst_dsp_init, + .cleanup = skl_sst_dsp_cleanup + }, +}; + +static int skl_get_dsp_ops(int pci_id) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(dsp_ops); i++) { + if (dsp_ops[i].id == pci_id) + return i; + } + + return -EINVAL; +} + int skl_init_dsp(struct skl *skl) { void __iomem *mmio_base; struct hdac_ext_bus *ebus = &skl->ebus; struct hdac_bus *bus = ebus_to_hbus(ebus); - int irq = bus->irq; struct skl_dsp_loader_ops loader_ops; - int ret; - - loader_ops.alloc_dma_buf = skl_alloc_dma_buf; - loader_ops.free_dma_buf = skl_free_dma_buf; + int irq = bus->irq; + int ret, index;
/* enable ppcap interrupt */ snd_hdac_ext_bus_ppcap_enable(&skl->ebus, true); @@ -95,8 +125,14 @@ int skl_init_dsp(struct skl *skl) return -ENXIO; }
- ret = skl_sst_dsp_init(bus->dev, mmio_base, irq, + index = skl_get_dsp_ops(skl->pci->device); + if (index < 0) + return -EINVAL; + + loader_ops = dsp_ops[index].loader_ops(); + ret = dsp_ops[index].init(bus->dev, mmio_base, irq, skl->fw_name, loader_ops, &skl->skl_sst); + if (ret < 0) return ret;
@@ -106,18 +142,26 @@ int skl_init_dsp(struct skl *skl) return ret; }
-void skl_free_dsp(struct skl *skl) +int skl_free_dsp(struct skl *skl) { struct hdac_ext_bus *ebus = &skl->ebus; struct hdac_bus *bus = ebus_to_hbus(ebus); - struct skl_sst *ctx = skl->skl_sst; + struct skl_sst *ctx = skl->skl_sst; + int index;
/* disable ppcap interrupt */ snd_hdac_ext_bus_ppcap_int_enable(&skl->ebus, false);
- skl_sst_dsp_cleanup(bus->dev, ctx); + index = skl_get_dsp_ops(skl->pci->device); + if (index < 0) + return -EIO; + + dsp_ops[index].cleanup(bus->dev, ctx); + if (ctx->dsp->addr.lpe) iounmap(ctx->dsp->addr.lpe); + + return 0; }
int skl_suspend_dsp(struct skl *skl) diff --git a/sound/soc/intel/skylake/skl.h b/sound/soc/intel/skylake/skl.h index 1ca1911f1587..39e16fa7a92b 100644 --- a/sound/soc/intel/skylake/skl.h +++ b/sound/soc/intel/skylake/skl.h @@ -90,6 +90,16 @@ struct skl_dma_params { u8 stream_tag; };
+struct skl_dsp_ops { + int id; + struct skl_dsp_loader_ops (*loader_ops)(void); + int (*init)(struct device *dev, void __iomem *mmio_base, + int irq, const char *fw_name, + struct skl_dsp_loader_ops loader_ops, + struct skl_sst **skl_sst); + void (*cleanup)(struct device *dev, struct skl_sst *ctx); +}; + int skl_platform_unregister(struct device *dev); int skl_platform_register(struct device *dev);
@@ -100,7 +110,7 @@ struct nhlt_specific_cfg *skl_get_ep_blob(struct skl *skl, u32 instance,
int skl_nhlt_update_topology_bin(struct skl *skl); int skl_init_dsp(struct skl *skl); -void skl_free_dsp(struct skl *skl); +int skl_free_dsp(struct skl *skl); int skl_suspend_dsp(struct skl *skl); int skl_resume_dsp(struct skl *skl); #endif /* __SOUND_SOC_SKL_H */
From: Senthilnathan Veppur senthilnathanx.veppur@intel.com
Broxton is an Intel SoC which sports a DSP and system is quite like Skylake. So add this ID in Skylake driver
Signed-off-by: Senthilnathan Veppur senthilnathanx.veppur@intel.com Signed-off-by: Vinod Koul vinod.koul@intel.com --- sound/soc/intel/skylake/skl.c | 7 +++++++ 1 file changed, 7 insertions(+)
diff --git a/sound/soc/intel/skylake/skl.c b/sound/soc/intel/skylake/skl.c index 0d38bdb8321b..ab5e25aaeee3 100644 --- a/sound/soc/intel/skylake/skl.c +++ b/sound/soc/intel/skylake/skl.c @@ -742,11 +742,18 @@ static struct sst_acpi_mach sst_skl_devdata[] = { {} };
+static struct sst_acpi_mach sst_bxtp_devdata[] = { + { "INT343A", "bxt_alc298s_i2s", "intel/dsp_fw_bxtn.bin", NULL, NULL, NULL }, +}; + /* PCI IDs */ static const struct pci_device_id skl_ids[] = { /* Sunrise Point-LP */ { PCI_DEVICE(0x8086, 0x9d70), .driver_data = (unsigned long)&sst_skl_devdata}, + /* BXT-P */ + { PCI_DEVICE(0x8086, 0x5a98), + .driver_data = (unsigned long)&sst_bxtp_devdata}, { 0, } }; MODULE_DEVICE_TABLE(pci, skl_ids);
The patch
ASoC: Intel: Bxtn: Add Broxton PCI ID
has been applied to the asoc tree at
git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git
All being well this means that it will be integrated into the linux-next tree (usually sometime in the next 24 hours) and sent to Linus during the next merge window (or sooner if it is a bug fix), however if problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing and review of the tree, please engage with people reporting problems and send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they should be sent as incremental updates against current git, existing patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying to this mail.
Thanks, Mark
From b379b1fad6e80274309f650f3a82c6f3c4fe9d6b Mon Sep 17 00:00:00 2001
From: Senthilnathan Veppur senthilnathanx.veppur@intel.com Date: Fri, 11 Mar 2016 10:12:54 +0530 Subject: [PATCH] ASoC: Intel: Bxtn: Add Broxton PCI ID
Broxton is an Intel SoC which sports a DSP and system is quite like Skylake. So add this ID in Skylake driver
Signed-off-by: Senthilnathan Veppur senthilnathanx.veppur@intel.com Signed-off-by: Vinod Koul vinod.koul@intel.com Signed-off-by: Mark Brown broonie@kernel.org --- sound/soc/intel/skylake/skl.c | 7 +++++++ 1 file changed, 7 insertions(+)
diff --git a/sound/soc/intel/skylake/skl.c b/sound/soc/intel/skylake/skl.c index 0d38bdb8321b..ab5e25aaeee3 100644 --- a/sound/soc/intel/skylake/skl.c +++ b/sound/soc/intel/skylake/skl.c @@ -742,11 +742,18 @@ static struct sst_acpi_mach sst_skl_devdata[] = { {} };
+static struct sst_acpi_mach sst_bxtp_devdata[] = { + { "INT343A", "bxt_alc298s_i2s", "intel/dsp_fw_bxtn.bin", NULL, NULL, NULL }, +}; + /* PCI IDs */ static const struct pci_device_id skl_ids[] = { /* Sunrise Point-LP */ { PCI_DEVICE(0x8086, 0x9d70), .driver_data = (unsigned long)&sst_skl_devdata}, + /* BXT-P */ + { PCI_DEVICE(0x8086, 0x5a98), + .driver_data = (unsigned long)&sst_bxtp_devdata}, { 0, } }; MODULE_DEVICE_TABLE(pci, skl_ids);
From: Jeeja KP jeeja.kp@intel.com
Broxton HDMI codec is similar to Skylake so add the device ID
Signed-off-by: Jeeja KP jeeja.kp@intel.com Signed-off-by: GuruprasadX Pawse guruprasadx.pawse@intel.com Signed-off-by: Vinod Koul vinod.koul@intel.com --- sound/soc/codecs/hdac_hdmi.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/sound/soc/codecs/hdac_hdmi.c b/sound/soc/codecs/hdac_hdmi.c index 7851dd204a49..cb0b036a1139 100644 --- a/sound/soc/codecs/hdac_hdmi.c +++ b/sound/soc/codecs/hdac_hdmi.c @@ -1634,6 +1634,7 @@ static const struct dev_pm_ops hdac_hdmi_pm = {
static const struct hda_device_id hdmi_list[] = { HDA_CODEC_EXT_ENTRY(0x80862809, 0x100000, "Skylake HDMI", 0), + HDA_CODEC_EXT_ENTRY(0x8086280a, 0x100000, "Broxton HDMI", 0), {} };
The patch
ASoC: hdac_hdmi: Add broxton device ID
has been applied to the asoc tree at
git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git
All being well this means that it will be integrated into the linux-next tree (usually sometime in the next 24 hours) and sent to Linus during the next merge window (or sooner if it is a bug fix), however if problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing and review of the tree, please engage with people reporting problems and send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they should be sent as incremental updates against current git, existing patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying to this mail.
Thanks, Mark
From e2304803fd05eac509c8e37bb626c192510e4e77 Mon Sep 17 00:00:00 2001
From: Jeeja KP jeeja.kp@intel.com Date: Fri, 11 Mar 2016 10:12:55 +0530 Subject: [PATCH] ASoC: hdac_hdmi: Add broxton device ID
Broxton HDMI codec is similar to Skylake so add the device ID
Signed-off-by: Jeeja KP jeeja.kp@intel.com Signed-off-by: GuruprasadX Pawse guruprasadx.pawse@intel.com Signed-off-by: Vinod Koul vinod.koul@intel.com Signed-off-by: Mark Brown broonie@kernel.org --- sound/soc/codecs/hdac_hdmi.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/sound/soc/codecs/hdac_hdmi.c b/sound/soc/codecs/hdac_hdmi.c index 7851dd204a49..cb0b036a1139 100644 --- a/sound/soc/codecs/hdac_hdmi.c +++ b/sound/soc/codecs/hdac_hdmi.c @@ -1634,6 +1634,7 @@ static const struct dev_pm_ops hdac_hdmi_pm = {
static const struct hda_device_id hdmi_list[] = { HDA_CODEC_EXT_ENTRY(0x80862809, 0x100000, "Skylake HDMI", 0), + HDA_CODEC_EXT_ENTRY(0x8086280a, 0x100000, "Broxton HDMI", 0), {} };
From: Jeeja KP jeeja.kp@intel.com
Broxton DSP is mostly similar to Skylake one but with subtle differences like no Code Load DMA and uses HDA DMA for code loading, DSP D0 and D3 sequences are different.
These changes are comprehended by adding different DSP power up and down handlers, and new loader ops and also adding prepare and trigger which HDA DSP DMA requires
Signed-off-by: Jeeja KP jeeja.kp@intel.com Signed-off-by: Jayachandran B jayachandran.b@intel.com Signed-off-by: GuruprasadX Pawse guruprasadx.pawse@intel.com Signed-off-by: Kranthi G gudishax.kranthikumar@intel.com Signed-off-by: Dharageswari R dharageswari.r@intel.com Signed-off-by: Ramesh Babu ramesh.babu@intel.com Signed-off-by: Vinod Koul vinod.koul@intel.com --- sound/soc/intel/Kconfig | 1 + sound/soc/intel/skylake/Makefile | 2 +- sound/soc/intel/skylake/bxt-sst.c | 328 +++++++++++++++++++++++++++++++++ sound/soc/intel/skylake/skl-messages.c | 120 ++++++++++++ sound/soc/intel/skylake/skl-sst-dsp.h | 13 ++ 5 files changed, 463 insertions(+), 1 deletion(-) create mode 100644 sound/soc/intel/skylake/bxt-sst.c
diff --git a/sound/soc/intel/Kconfig b/sound/soc/intel/Kconfig index cb968da5a308..7b485597643d 100644 --- a/sound/soc/intel/Kconfig +++ b/sound/soc/intel/Kconfig @@ -153,6 +153,7 @@ config SND_SOC_INTEL_CHT_BSW_MAX98090_TI_MACH config SND_SOC_INTEL_SKYLAKE tristate select SND_HDA_EXT_CORE + select SND_HDA_DSP_LOADER select SND_SOC_TOPOLOGY select SND_HDA_I915 select SND_SOC_INTEL_SST diff --git a/sound/soc/intel/skylake/Makefile b/sound/soc/intel/skylake/Makefile index 914b6dab9bea..c28f5d0e1d99 100644 --- a/sound/soc/intel/skylake/Makefile +++ b/sound/soc/intel/skylake/Makefile @@ -5,6 +5,6 @@ obj-$(CONFIG_SND_SOC_INTEL_SKYLAKE) += snd-soc-skl.o
# Skylake IPC Support snd-soc-skl-ipc-objs := skl-sst-ipc.o skl-sst-dsp.o skl-sst-cldma.o \ - skl-sst.o + skl-sst.o bxt-sst.o
obj-$(CONFIG_SND_SOC_INTEL_SKYLAKE) += snd-soc-skl-ipc.o diff --git a/sound/soc/intel/skylake/bxt-sst.c b/sound/soc/intel/skylake/bxt-sst.c new file mode 100644 index 000000000000..965ce40ce752 --- /dev/null +++ b/sound/soc/intel/skylake/bxt-sst.c @@ -0,0 +1,328 @@ +/* + * bxt-sst.c - DSP library functions for BXT platform + * + * Copyright (C) 2015-16 Intel Corp + * Author:Rafal Redzimski rafal.f.redzimski@intel.com + * Jeeja KP jeeja.kp@intel.com + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + */ + +#include <linux/module.h> +#include <linux/delay.h> +#include <linux/firmware.h> +#include <linux/device.h> + +#include "../common/sst-dsp.h" +#include "../common/sst-dsp-priv.h" +#include "skl-sst-ipc.h" + +#define BXT_BASEFW_TIMEOUT 3000 +#define BXT_INIT_TIMEOUT 500 +#define BXT_IPC_PURGE_FW 0x01004000 + +#define BXT_ROM_INIT 0x5 +#define BXT_ADSP_SRAM0_BASE 0x80000 + +/* Firmware status window */ +#define BXT_ADSP_FW_STATUS BXT_ADSP_SRAM0_BASE +#define BXT_ADSP_ERROR_CODE (BXT_ADSP_FW_STATUS + 0x4) + +#define BXT_ADSP_SRAM1_BASE 0xA0000 + +static unsigned int bxt_get_errorcode(struct sst_dsp *ctx) +{ + return sst_dsp_shim_read(ctx, BXT_ADSP_ERROR_CODE); +} + +static int sst_bxt_prepare_fw(struct sst_dsp *ctx, + const void *fwdata, u32 fwsize) +{ + int stream_tag, ret, i; + u32 reg; + + stream_tag = ctx->dsp_ops.prepare(ctx->dev, 0x40, fwsize, &ctx->dmab); + if (stream_tag < 0) { + dev_err(ctx->dev, "Failed to prepare DMA FW loading err: %x\n", + stream_tag); + return stream_tag; + } + + ctx->dsp_ops.stream_tag = stream_tag; + memcpy(ctx->dmab.area, fwdata, fwsize); + + /* Purge FW request */ + sst_dsp_shim_write(ctx, SKL_ADSP_REG_HIPCI, SKL_ADSP_REG_HIPCI_BUSY | + BXT_IPC_PURGE_FW | (stream_tag - 1)); + + ret = skl_dsp_enable_core(ctx); + if (ret < 0) { + dev_err(ctx->dev, "Boot dsp core failed ret: %d\n", ret); + ret = -EIO; + goto base_fw_load_failed; + } + + for (i = BXT_INIT_TIMEOUT; i > 0; --i) { + reg = sst_dsp_shim_read(ctx, SKL_ADSP_REG_HIPCIE); + + if (reg & SKL_ADSP_REG_HIPCIE_DONE) { + sst_dsp_shim_update_bits_forced(ctx, + SKL_ADSP_REG_HIPCIE, + SKL_ADSP_REG_HIPCIE_DONE, + SKL_ADSP_REG_HIPCIE_DONE); + break; + } + mdelay(1); + } + if (!i) { + dev_info(ctx->dev, "Waiting for HIPCIE done, reg: 0x%x\n", reg); + sst_dsp_shim_update_bits(ctx, SKL_ADSP_REG_HIPCIE, + SKL_ADSP_REG_HIPCIE_DONE, + SKL_ADSP_REG_HIPCIE_DONE); + } + + /* enable Interrupt */ + skl_ipc_int_enable(ctx); + skl_ipc_op_int_enable(ctx); + + for (i = BXT_INIT_TIMEOUT; i > 0; --i) { + if (SKL_FW_INIT == + (sst_dsp_shim_read(ctx, BXT_ADSP_FW_STATUS) & + SKL_FW_STS_MASK)) { + + dev_info(ctx->dev, "ROM loaded, continue FW loading\n"); + break; + } + mdelay(1); + } + if (!i) { + dev_err(ctx->dev, "Timeout for ROM init, HIPCIE: 0x%x\n", reg); + ret = -EIO; + goto base_fw_load_failed; + } + + return ret; + +base_fw_load_failed: + ctx->dsp_ops.cleanup(ctx->dev, &ctx->dmab, stream_tag); + skl_dsp_disable_core(ctx); + return ret; +} + +static int sst_transfer_fw_host_dma(struct sst_dsp *ctx) +{ + int ret; + + ctx->dsp_ops.trigger(ctx->dev, true, ctx->dsp_ops.stream_tag); + ret = sst_dsp_register_poll(ctx, BXT_ADSP_FW_STATUS, SKL_FW_STS_MASK, + BXT_ROM_INIT, BXT_BASEFW_TIMEOUT, "Firmware boot"); + + ctx->dsp_ops.trigger(ctx->dev, false, ctx->dsp_ops.stream_tag); + ctx->dsp_ops.cleanup(ctx->dev, &ctx->dmab, ctx->dsp_ops.stream_tag); + + return ret; +} + +static int bxt_load_base_firmware(struct sst_dsp *ctx) +{ + const struct firmware *fw = NULL; + struct skl_sst *skl = ctx->thread_context; + int ret; + + ret = request_firmware(&fw, ctx->fw_name, ctx->dev); + if (ret < 0) { + dev_err(ctx->dev, "Request firmware failed %d\n", ret); + goto sst_load_base_firmware_failed; + } + + ret = sst_bxt_prepare_fw(ctx, fw->data, fw->size); + /* Retry Enabling core and ROM load. Retry seemed to help */ + if (ret < 0) { + ret = sst_bxt_prepare_fw(ctx, fw->data, fw->size); + if (ret < 0) { + dev_err(ctx->dev, "Core En/ROM load fail:%d\n", ret); + goto sst_load_base_firmware_failed; + } + } + + ret = sst_transfer_fw_host_dma(ctx); + if (ret < 0) { + dev_err(ctx->dev, "Transfer firmware failed %d\n", ret); + dev_info(ctx->dev, "Error code=0x%x: FW status=0x%x\n", + sst_dsp_shim_read(ctx, BXT_ADSP_ERROR_CODE), + sst_dsp_shim_read(ctx, BXT_ADSP_FW_STATUS)); + + skl_dsp_disable_core(ctx); + } else { + dev_dbg(ctx->dev, "Firmware download successful\n"); + ret = wait_event_timeout(skl->boot_wait, skl->boot_complete, + msecs_to_jiffies(SKL_IPC_BOOT_MSECS)); + if (ret == 0) { + dev_err(ctx->dev, "DSP boot fail, FW Ready timeout\n"); + skl_dsp_disable_core(ctx); + ret = -EIO; + } else { + skl_dsp_set_state_locked(ctx, SKL_DSP_RUNNING); + ret = 0; + } + } + +sst_load_base_firmware_failed: + release_firmware(fw); + return ret; +} + +static int bxt_set_dsp_D0(struct sst_dsp *ctx) +{ + struct skl_sst *skl = ctx->thread_context; + int ret; + + skl->boot_complete = false; + + ret = skl_dsp_enable_core(ctx); + if (ret < 0) { + dev_err(ctx->dev, "enable dsp core failed ret: %d\n", ret); + return ret; + } + + /* enable interrupt */ + skl_ipc_int_enable(ctx); + skl_ipc_op_int_enable(ctx); + + ret = wait_event_timeout(skl->boot_wait, skl->boot_complete, + msecs_to_jiffies(SKL_IPC_BOOT_MSECS)); + if (ret == 0) { + dev_err(ctx->dev, "ipc: error DSP boot timeout\n"); + dev_err(ctx->dev, "Error code=0x%x: FW status=0x%x\n", + sst_dsp_shim_read(ctx, BXT_ADSP_ERROR_CODE), + sst_dsp_shim_read(ctx, BXT_ADSP_FW_STATUS)); + return -EIO; + } + + skl_dsp_set_state_locked(ctx, SKL_DSP_RUNNING); + return 0; +} + +static int bxt_set_dsp_D3(struct sst_dsp *ctx) +{ + struct skl_ipc_dxstate_info dx; + struct skl_sst *skl = ctx->thread_context; + int ret = 0; + + if (!is_skl_dsp_running(ctx)) + return ret; + + dx.core_mask = SKL_DSP_CORE0_MASK; + dx.dx_mask = SKL_IPC_D3_MASK; + + ret = skl_ipc_set_dx(&skl->ipc, SKL_INSTANCE_ID, + SKL_BASE_FW_MODULE_ID, &dx); + if (ret < 0) { + dev_err(ctx->dev, "Failed to set DSP to D3 state: %d\n", ret); + return ret; + } + + ret = skl_dsp_disable_core(ctx); + if (ret < 0) { + dev_err(ctx->dev, "disbale dsp core failed: %d\n", ret); + ret = -EIO; + } + + skl_dsp_set_state_locked(ctx, SKL_DSP_RESET); + return 0; +} + +static struct skl_dsp_fw_ops bxt_fw_ops = { + .set_state_D0 = bxt_set_dsp_D0, + .set_state_D3 = bxt_set_dsp_D3, + .load_fw = bxt_load_base_firmware, + .get_fw_errcode = bxt_get_errorcode, +}; + +static struct sst_ops skl_ops = { + .irq_handler = skl_dsp_sst_interrupt, + .write = sst_shim32_write, + .read = sst_shim32_read, + .ram_read = sst_memcpy_fromio_32, + .ram_write = sst_memcpy_toio_32, + .free = skl_dsp_free, +}; + +static struct sst_dsp_device skl_dev = { + .thread = skl_dsp_irq_thread_handler, + .ops = &skl_ops, +}; + +int bxt_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq, + const char *fw_name, struct skl_dsp_loader_ops dsp_ops, + struct skl_sst **dsp) +{ + struct skl_sst *skl; + struct sst_dsp *sst; + int ret; + + skl = devm_kzalloc(dev, sizeof(*skl), GFP_KERNEL); + if (skl == NULL) + return -ENOMEM; + + skl->dev = dev; + skl_dev.thread_context = skl; + + skl->dsp = skl_dsp_ctx_init(dev, &skl_dev, irq); + if (!skl->dsp) { + dev_err(skl->dev, "skl_dsp_ctx_init failed\n"); + return -ENODEV; + } + + sst = skl->dsp; + sst->fw_name = fw_name; + sst->dsp_ops = dsp_ops; + sst->fw_ops = bxt_fw_ops; + sst->addr.lpe = mmio_base; + sst->addr.shim = mmio_base; + + sst_dsp_mailbox_init(sst, (BXT_ADSP_SRAM0_BASE + SKL_ADSP_W0_STAT_SZ), + SKL_ADSP_W0_UP_SZ, BXT_ADSP_SRAM1_BASE, SKL_ADSP_W1_SZ); + + ret = skl_ipc_init(dev, skl); + if (ret) + return ret; + + skl->boot_complete = false; + init_waitqueue_head(&skl->boot_wait); + + ret = sst->fw_ops.load_fw(sst); + if (ret < 0) { + dev_err(dev, "Load base fw failed: %x", ret); + return ret; + } + + if (dsp) + *dsp = skl; + + return 0; +} +EXPORT_SYMBOL_GPL(bxt_sst_dsp_init); + + +void bxt_sst_dsp_cleanup(struct device *dev, struct skl_sst *ctx) +{ + skl_ipc_free(&ctx->ipc); + ctx->dsp->cl_dev.ops.cl_cleanup_controller(ctx->dsp); + + if (ctx->dsp->addr.lpe) + iounmap(ctx->dsp->addr.lpe); + + ctx->dsp->ops->free(ctx->dsp); +} +EXPORT_SYMBOL_GPL(bxt_sst_dsp_cleanup); + +MODULE_LICENSE("GPL v2"); +MODULE_DESCRIPTION("Intel Broxton IPC driver"); diff --git a/sound/soc/intel/skylake/skl-messages.c b/sound/soc/intel/skylake/skl-messages.c index 79c5089b85d6..e3d149c68bbf 100644 --- a/sound/soc/intel/skylake/skl-messages.c +++ b/sound/soc/intel/skylake/skl-messages.c @@ -72,6 +72,105 @@ static void skl_dsp_enable_notification(struct skl_sst *ctx, bool enable) skl_ipc_set_large_config(&ctx->ipc, &msg, (u32 *)&mask); }
+static int skl_dsp_setup_spib(struct device *dev, unsigned int size, + int stream_tag, int enable) +{ + struct hdac_ext_bus *ebus = dev_get_drvdata(dev); + struct hdac_bus *bus = ebus_to_hbus(ebus); + struct hdac_stream *stream = snd_hdac_get_stream(bus, + SNDRV_PCM_STREAM_PLAYBACK, stream_tag); + struct hdac_ext_stream *estream; + + if (!stream) + return -EINVAL; + + estream = stream_to_hdac_ext_stream(stream); + /* enable/disable SPIB for this hdac stream */ + snd_hdac_ext_stream_spbcap_enable(ebus, enable, stream->index); + + /* set the spib value */ + snd_hdac_ext_stream_set_spib(ebus, estream, size); + + return 0; +} + +static int skl_dsp_prepare(struct device *dev, unsigned int format, + unsigned int size, struct snd_dma_buffer *dmab) +{ + struct hdac_ext_bus *ebus = dev_get_drvdata(dev); + struct hdac_bus *bus = ebus_to_hbus(ebus); + struct hdac_ext_stream *estream; + struct hdac_stream *stream; + struct snd_pcm_substream substream; + int ret; + + if (!bus) + return -ENODEV; + + memset(&substream, 0, sizeof(substream)); + substream.stream = SNDRV_PCM_STREAM_PLAYBACK; + + estream = snd_hdac_ext_stream_assign(ebus, &substream, + HDAC_EXT_STREAM_TYPE_HOST); + if (!estream) + return -ENODEV; + + stream = hdac_stream(estream); + + /* assign decouple host dma channel */ + ret = snd_hdac_dsp_prepare(stream, format, size, dmab); + if (ret < 0) + return ret; + + skl_dsp_setup_spib(dev, size, stream->stream_tag, true); + + return stream->stream_tag; +} + +static int skl_dsp_trigger(struct device *dev, bool start, int stream_tag) +{ + struct hdac_ext_bus *ebus = dev_get_drvdata(dev); + struct hdac_stream *stream; + struct hdac_bus *bus = ebus_to_hbus(ebus); + + if (!bus) + return -ENODEV; + + stream = snd_hdac_get_stream(bus, + SNDRV_PCM_STREAM_PLAYBACK, stream_tag); + if (!stream) + return -EINVAL; + + snd_hdac_dsp_trigger(stream, start); + + return 0; +} + +static int skl_dsp_cleanup(struct device *dev, + struct snd_dma_buffer *dmab, int stream_tag) +{ + struct hdac_ext_bus *ebus = dev_get_drvdata(dev); + struct hdac_stream *stream; + struct hdac_ext_stream *estream; + struct hdac_bus *bus = ebus_to_hbus(ebus); + + if (!bus) + return -ENODEV; + + stream = snd_hdac_get_stream(bus, + SNDRV_PCM_STREAM_PLAYBACK, stream_tag); + if (!stream) + return -EINVAL; + + estream = stream_to_hdac_ext_stream(stream); + skl_dsp_setup_spib(dev, 0, stream_tag, false); + snd_hdac_ext_stream_release(estream, HDAC_EXT_STREAM_TYPE_HOST); + + snd_hdac_dsp_cleanup(stream, dmab); + + return 0; +} + static struct skl_dsp_loader_ops skl_get_loader_ops(void) { struct skl_dsp_loader_ops loader_ops; @@ -84,6 +183,21 @@ static struct skl_dsp_loader_ops skl_get_loader_ops(void) return loader_ops; };
+static struct skl_dsp_loader_ops bxt_get_loader_ops(void) +{ + struct skl_dsp_loader_ops loader_ops; + + memset(&loader_ops, 0, sizeof(loader_ops)); + + loader_ops.alloc_dma_buf = skl_alloc_dma_buf; + loader_ops.free_dma_buf = skl_free_dma_buf; + loader_ops.prepare = skl_dsp_prepare; + loader_ops.trigger = skl_dsp_trigger; + loader_ops.cleanup = skl_dsp_cleanup; + + return loader_ops; +}; + static const struct skl_dsp_ops dsp_ops[] = { { .id = 0x9d70, @@ -91,6 +205,12 @@ static const struct skl_dsp_ops dsp_ops[] = { .init = skl_sst_dsp_init, .cleanup = skl_sst_dsp_cleanup }, + { + .id = 0x5a98, + .loader_ops = bxt_get_loader_ops, + .init = bxt_sst_dsp_init, + .cleanup = bxt_sst_dsp_cleanup + }, };
static int skl_get_dsp_ops(int pci_id) diff --git a/sound/soc/intel/skylake/skl-sst-dsp.h b/sound/soc/intel/skylake/skl-sst-dsp.h index b6e310d49dd6..ff31e6615251 100644 --- a/sound/soc/intel/skylake/skl-sst-dsp.h +++ b/sound/soc/intel/skylake/skl-sst-dsp.h @@ -124,10 +124,19 @@ struct skl_dsp_fw_ops { };
struct skl_dsp_loader_ops { + int stream_tag; + int (*alloc_dma_buf)(struct device *dev, struct snd_dma_buffer *dmab, size_t size); int (*free_dma_buf)(struct device *dev, struct snd_dma_buffer *dmab); + int (*prepare)(struct device *dev, unsigned int format, + unsigned int byte_size, + struct snd_dma_buffer *bufp); + int (*trigger)(struct device *dev, bool start, int stream_tag); + + int (*cleanup)(struct device *dev, struct snd_dma_buffer *dmab, + int stream_tag); };
struct skl_load_module_info { @@ -160,6 +169,10 @@ int skl_dsp_boot(struct sst_dsp *ctx); int skl_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq, const char *fw_name, struct skl_dsp_loader_ops dsp_ops, struct skl_sst **dsp); +int bxt_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq, + const char *fw_name, struct skl_dsp_loader_ops dsp_ops, + struct skl_sst **dsp); void skl_sst_dsp_cleanup(struct device *dev, struct skl_sst *ctx); +void bxt_sst_dsp_cleanup(struct device *dev, struct skl_sst *ctx);
#endif /*__SKL_SST_DSP_H__*/
The patch
ASoC: Intel: Bxtn: Add Broxton DSP support
has been applied to the asoc tree at
git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git
All being well this means that it will be integrated into the linux-next tree (usually sometime in the next 24 hours) and sent to Linus during the next merge window (or sooner if it is a bug fix), however if problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing and review of the tree, please engage with people reporting problems and send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they should be sent as incremental updates against current git, existing patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying to this mail.
Thanks, Mark
From 040b4ab8bf025adcdd860a70d56e1aa76762b5c2 Mon Sep 17 00:00:00 2001
From: Jeeja KP jeeja.kp@intel.com Date: Fri, 11 Mar 2016 10:12:56 +0530 Subject: [PATCH] ASoC: Intel: Bxtn: Add Broxton DSP support
Broxton DSP is mostly similar to Skylake one but with subtle differences like no Code Load DMA and uses HDA DMA for code loading, DSP D0 and D3 sequences are different.
These changes are comprehended by adding different DSP power up and down handlers, and new loader ops and also adding prepare and trigger which HDA DSP DMA requires
Signed-off-by: Jeeja KP jeeja.kp@intel.com Signed-off-by: Jayachandran B jayachandran.b@intel.com Signed-off-by: GuruprasadX Pawse guruprasadx.pawse@intel.com Signed-off-by: Kranthi G gudishax.kranthikumar@intel.com Signed-off-by: Dharageswari R dharageswari.r@intel.com Signed-off-by: Ramesh Babu ramesh.babu@intel.com Signed-off-by: Vinod Koul vinod.koul@intel.com Signed-off-by: Mark Brown broonie@kernel.org --- sound/soc/intel/Kconfig | 1 + sound/soc/intel/skylake/Makefile | 2 +- sound/soc/intel/skylake/bxt-sst.c | 328 +++++++++++++++++++++++++++++++++ sound/soc/intel/skylake/skl-messages.c | 120 ++++++++++++ sound/soc/intel/skylake/skl-sst-dsp.h | 13 ++ 5 files changed, 463 insertions(+), 1 deletion(-) create mode 100644 sound/soc/intel/skylake/bxt-sst.c
diff --git a/sound/soc/intel/Kconfig b/sound/soc/intel/Kconfig index b3e6c2300457..5a94f74d31dd 100644 --- a/sound/soc/intel/Kconfig +++ b/sound/soc/intel/Kconfig @@ -162,6 +162,7 @@ config SND_SOC_INTEL_CHT_BSW_MAX98090_TI_MACH config SND_SOC_INTEL_SKYLAKE tristate select SND_HDA_EXT_CORE + select SND_HDA_DSP_LOADER select SND_SOC_TOPOLOGY select SND_HDA_I915 select SND_SOC_INTEL_SST diff --git a/sound/soc/intel/skylake/Makefile b/sound/soc/intel/skylake/Makefile index 914b6dab9bea..c28f5d0e1d99 100644 --- a/sound/soc/intel/skylake/Makefile +++ b/sound/soc/intel/skylake/Makefile @@ -5,6 +5,6 @@ obj-$(CONFIG_SND_SOC_INTEL_SKYLAKE) += snd-soc-skl.o
# Skylake IPC Support snd-soc-skl-ipc-objs := skl-sst-ipc.o skl-sst-dsp.o skl-sst-cldma.o \ - skl-sst.o + skl-sst.o bxt-sst.o
obj-$(CONFIG_SND_SOC_INTEL_SKYLAKE) += snd-soc-skl-ipc.o diff --git a/sound/soc/intel/skylake/bxt-sst.c b/sound/soc/intel/skylake/bxt-sst.c new file mode 100644 index 000000000000..965ce40ce752 --- /dev/null +++ b/sound/soc/intel/skylake/bxt-sst.c @@ -0,0 +1,328 @@ +/* + * bxt-sst.c - DSP library functions for BXT platform + * + * Copyright (C) 2015-16 Intel Corp + * Author:Rafal Redzimski rafal.f.redzimski@intel.com + * Jeeja KP jeeja.kp@intel.com + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + */ + +#include <linux/module.h> +#include <linux/delay.h> +#include <linux/firmware.h> +#include <linux/device.h> + +#include "../common/sst-dsp.h" +#include "../common/sst-dsp-priv.h" +#include "skl-sst-ipc.h" + +#define BXT_BASEFW_TIMEOUT 3000 +#define BXT_INIT_TIMEOUT 500 +#define BXT_IPC_PURGE_FW 0x01004000 + +#define BXT_ROM_INIT 0x5 +#define BXT_ADSP_SRAM0_BASE 0x80000 + +/* Firmware status window */ +#define BXT_ADSP_FW_STATUS BXT_ADSP_SRAM0_BASE +#define BXT_ADSP_ERROR_CODE (BXT_ADSP_FW_STATUS + 0x4) + +#define BXT_ADSP_SRAM1_BASE 0xA0000 + +static unsigned int bxt_get_errorcode(struct sst_dsp *ctx) +{ + return sst_dsp_shim_read(ctx, BXT_ADSP_ERROR_CODE); +} + +static int sst_bxt_prepare_fw(struct sst_dsp *ctx, + const void *fwdata, u32 fwsize) +{ + int stream_tag, ret, i; + u32 reg; + + stream_tag = ctx->dsp_ops.prepare(ctx->dev, 0x40, fwsize, &ctx->dmab); + if (stream_tag < 0) { + dev_err(ctx->dev, "Failed to prepare DMA FW loading err: %x\n", + stream_tag); + return stream_tag; + } + + ctx->dsp_ops.stream_tag = stream_tag; + memcpy(ctx->dmab.area, fwdata, fwsize); + + /* Purge FW request */ + sst_dsp_shim_write(ctx, SKL_ADSP_REG_HIPCI, SKL_ADSP_REG_HIPCI_BUSY | + BXT_IPC_PURGE_FW | (stream_tag - 1)); + + ret = skl_dsp_enable_core(ctx); + if (ret < 0) { + dev_err(ctx->dev, "Boot dsp core failed ret: %d\n", ret); + ret = -EIO; + goto base_fw_load_failed; + } + + for (i = BXT_INIT_TIMEOUT; i > 0; --i) { + reg = sst_dsp_shim_read(ctx, SKL_ADSP_REG_HIPCIE); + + if (reg & SKL_ADSP_REG_HIPCIE_DONE) { + sst_dsp_shim_update_bits_forced(ctx, + SKL_ADSP_REG_HIPCIE, + SKL_ADSP_REG_HIPCIE_DONE, + SKL_ADSP_REG_HIPCIE_DONE); + break; + } + mdelay(1); + } + if (!i) { + dev_info(ctx->dev, "Waiting for HIPCIE done, reg: 0x%x\n", reg); + sst_dsp_shim_update_bits(ctx, SKL_ADSP_REG_HIPCIE, + SKL_ADSP_REG_HIPCIE_DONE, + SKL_ADSP_REG_HIPCIE_DONE); + } + + /* enable Interrupt */ + skl_ipc_int_enable(ctx); + skl_ipc_op_int_enable(ctx); + + for (i = BXT_INIT_TIMEOUT; i > 0; --i) { + if (SKL_FW_INIT == + (sst_dsp_shim_read(ctx, BXT_ADSP_FW_STATUS) & + SKL_FW_STS_MASK)) { + + dev_info(ctx->dev, "ROM loaded, continue FW loading\n"); + break; + } + mdelay(1); + } + if (!i) { + dev_err(ctx->dev, "Timeout for ROM init, HIPCIE: 0x%x\n", reg); + ret = -EIO; + goto base_fw_load_failed; + } + + return ret; + +base_fw_load_failed: + ctx->dsp_ops.cleanup(ctx->dev, &ctx->dmab, stream_tag); + skl_dsp_disable_core(ctx); + return ret; +} + +static int sst_transfer_fw_host_dma(struct sst_dsp *ctx) +{ + int ret; + + ctx->dsp_ops.trigger(ctx->dev, true, ctx->dsp_ops.stream_tag); + ret = sst_dsp_register_poll(ctx, BXT_ADSP_FW_STATUS, SKL_FW_STS_MASK, + BXT_ROM_INIT, BXT_BASEFW_TIMEOUT, "Firmware boot"); + + ctx->dsp_ops.trigger(ctx->dev, false, ctx->dsp_ops.stream_tag); + ctx->dsp_ops.cleanup(ctx->dev, &ctx->dmab, ctx->dsp_ops.stream_tag); + + return ret; +} + +static int bxt_load_base_firmware(struct sst_dsp *ctx) +{ + const struct firmware *fw = NULL; + struct skl_sst *skl = ctx->thread_context; + int ret; + + ret = request_firmware(&fw, ctx->fw_name, ctx->dev); + if (ret < 0) { + dev_err(ctx->dev, "Request firmware failed %d\n", ret); + goto sst_load_base_firmware_failed; + } + + ret = sst_bxt_prepare_fw(ctx, fw->data, fw->size); + /* Retry Enabling core and ROM load. Retry seemed to help */ + if (ret < 0) { + ret = sst_bxt_prepare_fw(ctx, fw->data, fw->size); + if (ret < 0) { + dev_err(ctx->dev, "Core En/ROM load fail:%d\n", ret); + goto sst_load_base_firmware_failed; + } + } + + ret = sst_transfer_fw_host_dma(ctx); + if (ret < 0) { + dev_err(ctx->dev, "Transfer firmware failed %d\n", ret); + dev_info(ctx->dev, "Error code=0x%x: FW status=0x%x\n", + sst_dsp_shim_read(ctx, BXT_ADSP_ERROR_CODE), + sst_dsp_shim_read(ctx, BXT_ADSP_FW_STATUS)); + + skl_dsp_disable_core(ctx); + } else { + dev_dbg(ctx->dev, "Firmware download successful\n"); + ret = wait_event_timeout(skl->boot_wait, skl->boot_complete, + msecs_to_jiffies(SKL_IPC_BOOT_MSECS)); + if (ret == 0) { + dev_err(ctx->dev, "DSP boot fail, FW Ready timeout\n"); + skl_dsp_disable_core(ctx); + ret = -EIO; + } else { + skl_dsp_set_state_locked(ctx, SKL_DSP_RUNNING); + ret = 0; + } + } + +sst_load_base_firmware_failed: + release_firmware(fw); + return ret; +} + +static int bxt_set_dsp_D0(struct sst_dsp *ctx) +{ + struct skl_sst *skl = ctx->thread_context; + int ret; + + skl->boot_complete = false; + + ret = skl_dsp_enable_core(ctx); + if (ret < 0) { + dev_err(ctx->dev, "enable dsp core failed ret: %d\n", ret); + return ret; + } + + /* enable interrupt */ + skl_ipc_int_enable(ctx); + skl_ipc_op_int_enable(ctx); + + ret = wait_event_timeout(skl->boot_wait, skl->boot_complete, + msecs_to_jiffies(SKL_IPC_BOOT_MSECS)); + if (ret == 0) { + dev_err(ctx->dev, "ipc: error DSP boot timeout\n"); + dev_err(ctx->dev, "Error code=0x%x: FW status=0x%x\n", + sst_dsp_shim_read(ctx, BXT_ADSP_ERROR_CODE), + sst_dsp_shim_read(ctx, BXT_ADSP_FW_STATUS)); + return -EIO; + } + + skl_dsp_set_state_locked(ctx, SKL_DSP_RUNNING); + return 0; +} + +static int bxt_set_dsp_D3(struct sst_dsp *ctx) +{ + struct skl_ipc_dxstate_info dx; + struct skl_sst *skl = ctx->thread_context; + int ret = 0; + + if (!is_skl_dsp_running(ctx)) + return ret; + + dx.core_mask = SKL_DSP_CORE0_MASK; + dx.dx_mask = SKL_IPC_D3_MASK; + + ret = skl_ipc_set_dx(&skl->ipc, SKL_INSTANCE_ID, + SKL_BASE_FW_MODULE_ID, &dx); + if (ret < 0) { + dev_err(ctx->dev, "Failed to set DSP to D3 state: %d\n", ret); + return ret; + } + + ret = skl_dsp_disable_core(ctx); + if (ret < 0) { + dev_err(ctx->dev, "disbale dsp core failed: %d\n", ret); + ret = -EIO; + } + + skl_dsp_set_state_locked(ctx, SKL_DSP_RESET); + return 0; +} + +static struct skl_dsp_fw_ops bxt_fw_ops = { + .set_state_D0 = bxt_set_dsp_D0, + .set_state_D3 = bxt_set_dsp_D3, + .load_fw = bxt_load_base_firmware, + .get_fw_errcode = bxt_get_errorcode, +}; + +static struct sst_ops skl_ops = { + .irq_handler = skl_dsp_sst_interrupt, + .write = sst_shim32_write, + .read = sst_shim32_read, + .ram_read = sst_memcpy_fromio_32, + .ram_write = sst_memcpy_toio_32, + .free = skl_dsp_free, +}; + +static struct sst_dsp_device skl_dev = { + .thread = skl_dsp_irq_thread_handler, + .ops = &skl_ops, +}; + +int bxt_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq, + const char *fw_name, struct skl_dsp_loader_ops dsp_ops, + struct skl_sst **dsp) +{ + struct skl_sst *skl; + struct sst_dsp *sst; + int ret; + + skl = devm_kzalloc(dev, sizeof(*skl), GFP_KERNEL); + if (skl == NULL) + return -ENOMEM; + + skl->dev = dev; + skl_dev.thread_context = skl; + + skl->dsp = skl_dsp_ctx_init(dev, &skl_dev, irq); + if (!skl->dsp) { + dev_err(skl->dev, "skl_dsp_ctx_init failed\n"); + return -ENODEV; + } + + sst = skl->dsp; + sst->fw_name = fw_name; + sst->dsp_ops = dsp_ops; + sst->fw_ops = bxt_fw_ops; + sst->addr.lpe = mmio_base; + sst->addr.shim = mmio_base; + + sst_dsp_mailbox_init(sst, (BXT_ADSP_SRAM0_BASE + SKL_ADSP_W0_STAT_SZ), + SKL_ADSP_W0_UP_SZ, BXT_ADSP_SRAM1_BASE, SKL_ADSP_W1_SZ); + + ret = skl_ipc_init(dev, skl); + if (ret) + return ret; + + skl->boot_complete = false; + init_waitqueue_head(&skl->boot_wait); + + ret = sst->fw_ops.load_fw(sst); + if (ret < 0) { + dev_err(dev, "Load base fw failed: %x", ret); + return ret; + } + + if (dsp) + *dsp = skl; + + return 0; +} +EXPORT_SYMBOL_GPL(bxt_sst_dsp_init); + + +void bxt_sst_dsp_cleanup(struct device *dev, struct skl_sst *ctx) +{ + skl_ipc_free(&ctx->ipc); + ctx->dsp->cl_dev.ops.cl_cleanup_controller(ctx->dsp); + + if (ctx->dsp->addr.lpe) + iounmap(ctx->dsp->addr.lpe); + + ctx->dsp->ops->free(ctx->dsp); +} +EXPORT_SYMBOL_GPL(bxt_sst_dsp_cleanup); + +MODULE_LICENSE("GPL v2"); +MODULE_DESCRIPTION("Intel Broxton IPC driver"); diff --git a/sound/soc/intel/skylake/skl-messages.c b/sound/soc/intel/skylake/skl-messages.c index 79c5089b85d6..e3d149c68bbf 100644 --- a/sound/soc/intel/skylake/skl-messages.c +++ b/sound/soc/intel/skylake/skl-messages.c @@ -72,6 +72,105 @@ static void skl_dsp_enable_notification(struct skl_sst *ctx, bool enable) skl_ipc_set_large_config(&ctx->ipc, &msg, (u32 *)&mask); }
+static int skl_dsp_setup_spib(struct device *dev, unsigned int size, + int stream_tag, int enable) +{ + struct hdac_ext_bus *ebus = dev_get_drvdata(dev); + struct hdac_bus *bus = ebus_to_hbus(ebus); + struct hdac_stream *stream = snd_hdac_get_stream(bus, + SNDRV_PCM_STREAM_PLAYBACK, stream_tag); + struct hdac_ext_stream *estream; + + if (!stream) + return -EINVAL; + + estream = stream_to_hdac_ext_stream(stream); + /* enable/disable SPIB for this hdac stream */ + snd_hdac_ext_stream_spbcap_enable(ebus, enable, stream->index); + + /* set the spib value */ + snd_hdac_ext_stream_set_spib(ebus, estream, size); + + return 0; +} + +static int skl_dsp_prepare(struct device *dev, unsigned int format, + unsigned int size, struct snd_dma_buffer *dmab) +{ + struct hdac_ext_bus *ebus = dev_get_drvdata(dev); + struct hdac_bus *bus = ebus_to_hbus(ebus); + struct hdac_ext_stream *estream; + struct hdac_stream *stream; + struct snd_pcm_substream substream; + int ret; + + if (!bus) + return -ENODEV; + + memset(&substream, 0, sizeof(substream)); + substream.stream = SNDRV_PCM_STREAM_PLAYBACK; + + estream = snd_hdac_ext_stream_assign(ebus, &substream, + HDAC_EXT_STREAM_TYPE_HOST); + if (!estream) + return -ENODEV; + + stream = hdac_stream(estream); + + /* assign decouple host dma channel */ + ret = snd_hdac_dsp_prepare(stream, format, size, dmab); + if (ret < 0) + return ret; + + skl_dsp_setup_spib(dev, size, stream->stream_tag, true); + + return stream->stream_tag; +} + +static int skl_dsp_trigger(struct device *dev, bool start, int stream_tag) +{ + struct hdac_ext_bus *ebus = dev_get_drvdata(dev); + struct hdac_stream *stream; + struct hdac_bus *bus = ebus_to_hbus(ebus); + + if (!bus) + return -ENODEV; + + stream = snd_hdac_get_stream(bus, + SNDRV_PCM_STREAM_PLAYBACK, stream_tag); + if (!stream) + return -EINVAL; + + snd_hdac_dsp_trigger(stream, start); + + return 0; +} + +static int skl_dsp_cleanup(struct device *dev, + struct snd_dma_buffer *dmab, int stream_tag) +{ + struct hdac_ext_bus *ebus = dev_get_drvdata(dev); + struct hdac_stream *stream; + struct hdac_ext_stream *estream; + struct hdac_bus *bus = ebus_to_hbus(ebus); + + if (!bus) + return -ENODEV; + + stream = snd_hdac_get_stream(bus, + SNDRV_PCM_STREAM_PLAYBACK, stream_tag); + if (!stream) + return -EINVAL; + + estream = stream_to_hdac_ext_stream(stream); + skl_dsp_setup_spib(dev, 0, stream_tag, false); + snd_hdac_ext_stream_release(estream, HDAC_EXT_STREAM_TYPE_HOST); + + snd_hdac_dsp_cleanup(stream, dmab); + + return 0; +} + static struct skl_dsp_loader_ops skl_get_loader_ops(void) { struct skl_dsp_loader_ops loader_ops; @@ -84,6 +183,21 @@ static struct skl_dsp_loader_ops skl_get_loader_ops(void) return loader_ops; };
+static struct skl_dsp_loader_ops bxt_get_loader_ops(void) +{ + struct skl_dsp_loader_ops loader_ops; + + memset(&loader_ops, 0, sizeof(loader_ops)); + + loader_ops.alloc_dma_buf = skl_alloc_dma_buf; + loader_ops.free_dma_buf = skl_free_dma_buf; + loader_ops.prepare = skl_dsp_prepare; + loader_ops.trigger = skl_dsp_trigger; + loader_ops.cleanup = skl_dsp_cleanup; + + return loader_ops; +}; + static const struct skl_dsp_ops dsp_ops[] = { { .id = 0x9d70, @@ -91,6 +205,12 @@ static const struct skl_dsp_ops dsp_ops[] = { .init = skl_sst_dsp_init, .cleanup = skl_sst_dsp_cleanup }, + { + .id = 0x5a98, + .loader_ops = bxt_get_loader_ops, + .init = bxt_sst_dsp_init, + .cleanup = bxt_sst_dsp_cleanup + }, };
static int skl_get_dsp_ops(int pci_id) diff --git a/sound/soc/intel/skylake/skl-sst-dsp.h b/sound/soc/intel/skylake/skl-sst-dsp.h index b6e310d49dd6..ff31e6615251 100644 --- a/sound/soc/intel/skylake/skl-sst-dsp.h +++ b/sound/soc/intel/skylake/skl-sst-dsp.h @@ -124,10 +124,19 @@ struct skl_dsp_fw_ops { };
struct skl_dsp_loader_ops { + int stream_tag; + int (*alloc_dma_buf)(struct device *dev, struct snd_dma_buffer *dmab, size_t size); int (*free_dma_buf)(struct device *dev, struct snd_dma_buffer *dmab); + int (*prepare)(struct device *dev, unsigned int format, + unsigned int byte_size, + struct snd_dma_buffer *bufp); + int (*trigger)(struct device *dev, bool start, int stream_tag); + + int (*cleanup)(struct device *dev, struct snd_dma_buffer *dmab, + int stream_tag); };
struct skl_load_module_info { @@ -160,6 +169,10 @@ int skl_dsp_boot(struct sst_dsp *ctx); int skl_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq, const char *fw_name, struct skl_dsp_loader_ops dsp_ops, struct skl_sst **dsp); +int bxt_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq, + const char *fw_name, struct skl_dsp_loader_ops dsp_ops, + struct skl_sst **dsp); void skl_sst_dsp_cleanup(struct device *dev, struct skl_sst *ctx); +void bxt_sst_dsp_cleanup(struct device *dev, struct skl_sst *ctx);
#endif /*__SKL_SST_DSP_H__*/
participants (2)
-
Mark Brown
-
Vinod Koul