[alsa-devel] [PATCH 0/9] Add Cannonlake Audio DSP support
Cannonlake (CNL) audio is similar to Broxton with a substantial difference in ipc registers. This series enables CNL support by adding required dsp library functions and ipc register programming. CNL has 4 dsp cores, additional core support is also added here.
To accommodate the above changes in the current code, existing helper functions, common functions that are reusable and dsp ops are modified.
Dharageswari R (1): ASoC: Intel: Skylake: Add num of cores in dsp ops
Guneshwor Singh (7): ASoC: Intel: Skylake: Use num_core to allocate instead of macro ASoC: Intel: cnl: Add cnl dsp functions and registers ASoC: Intel: Skylake: Move platform specific init to platform dsp_init() ASoC: Intel: cnl: Unstatify common ipc functions ASoC: Intel: cnl: Add sst library functions for cnl platform ASoC: Intel: cnl: add dsp ops for cannonlake ASoC: Intel: cnl: add pci id for cnl
Pardha Saradhi K (1): ASoC: Intel: Skylake: Add dsp cores management
sound/soc/intel/skylake/Makefile | 5 +- sound/soc/intel/skylake/bxt-sst.c | 5 +- sound/soc/intel/skylake/cnl-sst-dsp.c | 274 ++++++++++++++++++ sound/soc/intel/skylake/cnl-sst-dsp.h | 112 ++++++++ sound/soc/intel/skylake/cnl-sst.c | 495 ++++++++++++++++++++++++++++++++ sound/soc/intel/skylake/skl-messages.c | 31 ++ sound/soc/intel/skylake/skl-sst-dsp.c | 2 +- sound/soc/intel/skylake/skl-sst-ipc.c | 6 +- sound/soc/intel/skylake/skl-sst-ipc.h | 12 +- sound/soc/intel/skylake/skl-sst-utils.c | 6 +- sound/soc/intel/skylake/skl-sst.c | 6 +- sound/soc/intel/skylake/skl-topology.c | 26 +- sound/soc/intel/skylake/skl.c | 11 + sound/soc/intel/skylake/skl.h | 1 + 14 files changed, 970 insertions(+), 22 deletions(-) create mode 100644 sound/soc/intel/skylake/cnl-sst-dsp.c create mode 100644 sound/soc/intel/skylake/cnl-sst-dsp.h create mode 100644 sound/soc/intel/skylake/cnl-sst.c
From: Dharageswari R dharageswari.r@intel.com
Number of dsp cores may differ for different platforms hence adding it in dsp ops.
Signed-off-by: Dharageswari R dharageswari.r@intel.com Signed-off-by: Guneshwor Singh guneshwor.o.singh@intel.com --- sound/soc/intel/skylake/bxt-sst.c | 1 - sound/soc/intel/skylake/skl-messages.c | 6 ++++++ sound/soc/intel/skylake/skl-sst.c | 2 -- sound/soc/intel/skylake/skl.h | 1 + 4 files changed, 7 insertions(+), 3 deletions(-)
diff --git a/sound/soc/intel/skylake/bxt-sst.c b/sound/soc/intel/skylake/bxt-sst.c index 08a2c5eb59fa..c404a42b670a 100644 --- a/sound/soc/intel/skylake/bxt-sst.c +++ b/sound/soc/intel/skylake/bxt-sst.c @@ -584,7 +584,6 @@ int bxt_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq, /* set the D0i3 check */ skl->ipc.ops.check_dsp_lp_on = skl_ipc_check_D0i0;
- skl->cores.count = 2; skl->boot_complete = false; init_waitqueue_head(&skl->boot_wait); INIT_DELAYED_WORK(&skl->d0i3.work, bxt_set_dsp_D0i3); diff --git a/sound/soc/intel/skylake/skl-messages.c b/sound/soc/intel/skylake/skl-messages.c index c5b4e0a9946c..7892e445e87b 100644 --- a/sound/soc/intel/skylake/skl-messages.c +++ b/sound/soc/intel/skylake/skl-messages.c @@ -201,6 +201,7 @@ static struct skl_dsp_loader_ops bxt_get_loader_ops(void) static const struct skl_dsp_ops dsp_ops[] = { { .id = 0x9d70, + .num_cores = 2, .loader_ops = skl_get_loader_ops, .init = skl_sst_dsp_init, .init_fw = skl_sst_init_fw, @@ -208,6 +209,7 @@ static const struct skl_dsp_ops dsp_ops[] = { }, { .id = 0x9d71, + .num_cores = 2, .loader_ops = skl_get_loader_ops, .init = kbl_sst_dsp_init, .init_fw = skl_sst_init_fw, @@ -215,6 +217,7 @@ static const struct skl_dsp_ops dsp_ops[] = { }, { .id = 0x5a98, + .num_cores = 2, .loader_ops = bxt_get_loader_ops, .init = bxt_sst_dsp_init, .init_fw = bxt_sst_init_fw, @@ -222,6 +225,7 @@ static const struct skl_dsp_ops dsp_ops[] = { }, { .id = 0x3198, + .num_cores = 2, .loader_ops = bxt_get_loader_ops, .init = bxt_sst_dsp_init, .init_fw = bxt_sst_init_fw, @@ -275,6 +279,8 @@ int skl_init_dsp(struct skl *skl) return ret;
skl->skl_sst->dsp_ops = ops; + skl->skl_sst->cores.count = ops->num_cores; + dev_dbg(bus->dev, "dsp registration status=%d\n", ret);
return ret; diff --git a/sound/soc/intel/skylake/skl-sst.c b/sound/soc/intel/skylake/skl-sst.c index aba9ea11ac74..fd99e74cda03 100644 --- a/sound/soc/intel/skylake/skl-sst.c +++ b/sound/soc/intel/skylake/skl-sst.c @@ -563,8 +563,6 @@ int skl_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq,
sst->fw_ops = skl_fw_ops;
- skl->cores.count = 2; - return 0; } EXPORT_SYMBOL_GPL(skl_sst_dsp_init); diff --git a/sound/soc/intel/skylake/skl.h b/sound/soc/intel/skylake/skl.h index a6b134b4c037..20017ee4685c 100644 --- a/sound/soc/intel/skylake/skl.h +++ b/sound/soc/intel/skylake/skl.h @@ -90,6 +90,7 @@ struct skl_machine_pdata {
struct skl_dsp_ops { int id; + unsigned int num_cores; struct skl_dsp_loader_ops (*loader_ops)(void); int (*init)(struct device *dev, void __iomem *mmio_base, int irq, const char *fw_name,
The patch
ASoC: Intel: Skylake: Add num of cores in dsp 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 363d45385f403fdf60fe9f563ba87093289d7b35 Mon Sep 17 00:00:00 2001
From: Dharageswari R dharageswari.r@intel.com Date: Wed, 2 Aug 2017 21:51:12 +0530 Subject: [PATCH] ASoC: Intel: Skylake: Add num of cores in dsp ops
Number of dsp cores may differ for different platforms hence adding it in dsp ops.
Signed-off-by: Dharageswari R dharageswari.r@intel.com Signed-off-by: Guneshwor Singh guneshwor.o.singh@intel.com Acked-By: Vinod Koul vinod.koul@intel.com Signed-off-by: Mark Brown broonie@kernel.org --- sound/soc/intel/skylake/bxt-sst.c | 1 - sound/soc/intel/skylake/skl-messages.c | 6 ++++++ sound/soc/intel/skylake/skl-sst.c | 2 -- sound/soc/intel/skylake/skl.h | 1 + 4 files changed, 7 insertions(+), 3 deletions(-)
diff --git a/sound/soc/intel/skylake/bxt-sst.c b/sound/soc/intel/skylake/bxt-sst.c index 08a2c5eb59fa..c404a42b670a 100644 --- a/sound/soc/intel/skylake/bxt-sst.c +++ b/sound/soc/intel/skylake/bxt-sst.c @@ -584,7 +584,6 @@ int bxt_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq, /* set the D0i3 check */ skl->ipc.ops.check_dsp_lp_on = skl_ipc_check_D0i0;
- skl->cores.count = 2; skl->boot_complete = false; init_waitqueue_head(&skl->boot_wait); INIT_DELAYED_WORK(&skl->d0i3.work, bxt_set_dsp_D0i3); diff --git a/sound/soc/intel/skylake/skl-messages.c b/sound/soc/intel/skylake/skl-messages.c index c5b4e0a9946c..7892e445e87b 100644 --- a/sound/soc/intel/skylake/skl-messages.c +++ b/sound/soc/intel/skylake/skl-messages.c @@ -201,6 +201,7 @@ static struct skl_dsp_loader_ops bxt_get_loader_ops(void) static const struct skl_dsp_ops dsp_ops[] = { { .id = 0x9d70, + .num_cores = 2, .loader_ops = skl_get_loader_ops, .init = skl_sst_dsp_init, .init_fw = skl_sst_init_fw, @@ -208,6 +209,7 @@ static const struct skl_dsp_ops dsp_ops[] = { }, { .id = 0x9d71, + .num_cores = 2, .loader_ops = skl_get_loader_ops, .init = kbl_sst_dsp_init, .init_fw = skl_sst_init_fw, @@ -215,6 +217,7 @@ static const struct skl_dsp_ops dsp_ops[] = { }, { .id = 0x5a98, + .num_cores = 2, .loader_ops = bxt_get_loader_ops, .init = bxt_sst_dsp_init, .init_fw = bxt_sst_init_fw, @@ -222,6 +225,7 @@ static const struct skl_dsp_ops dsp_ops[] = { }, { .id = 0x3198, + .num_cores = 2, .loader_ops = bxt_get_loader_ops, .init = bxt_sst_dsp_init, .init_fw = bxt_sst_init_fw, @@ -275,6 +279,8 @@ int skl_init_dsp(struct skl *skl) return ret;
skl->skl_sst->dsp_ops = ops; + skl->skl_sst->cores.count = ops->num_cores; + dev_dbg(bus->dev, "dsp registration status=%d\n", ret);
return ret; diff --git a/sound/soc/intel/skylake/skl-sst.c b/sound/soc/intel/skylake/skl-sst.c index aba9ea11ac74..fd99e74cda03 100644 --- a/sound/soc/intel/skylake/skl-sst.c +++ b/sound/soc/intel/skylake/skl-sst.c @@ -563,8 +563,6 @@ int skl_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq,
sst->fw_ops = skl_fw_ops;
- skl->cores.count = 2; - return 0; } EXPORT_SYMBOL_GPL(skl_sst_dsp_init); diff --git a/sound/soc/intel/skylake/skl.h b/sound/soc/intel/skylake/skl.h index a6b134b4c037..20017ee4685c 100644 --- a/sound/soc/intel/skylake/skl.h +++ b/sound/soc/intel/skylake/skl.h @@ -90,6 +90,7 @@ struct skl_machine_pdata {
struct skl_dsp_ops { int id; + unsigned int num_cores; struct skl_dsp_loader_ops (*loader_ops)(void); int (*init)(struct device *dev, void __iomem *mmio_base, int irq, const char *fw_name,
For different platforms, number of dsp cores can vary. So instead of creating array of size SKL_DSP_CORES_MAX, use num_core in dsp_ops() of the respective platform to allocate core usage counts and states.
Signed-off-by: Guneshwor Singh guneshwor.o.singh@intel.com --- sound/soc/intel/skylake/skl-messages.c | 18 +++++++++++++++++- sound/soc/intel/skylake/skl-sst-dsp.c | 2 +- sound/soc/intel/skylake/skl-sst-ipc.h | 6 ++---- 3 files changed, 20 insertions(+), 6 deletions(-)
diff --git a/sound/soc/intel/skylake/skl-messages.c b/sound/soc/intel/skylake/skl-messages.c index 7892e445e87b..c6b60ee5b196 100644 --- a/sound/soc/intel/skylake/skl-messages.c +++ b/sound/soc/intel/skylake/skl-messages.c @@ -253,6 +253,7 @@ int skl_init_dsp(struct skl *skl) struct skl_dsp_loader_ops loader_ops; int irq = bus->irq; const struct skl_dsp_ops *ops; + struct skl_dsp_cores *cores; int ret;
/* enable ppcap interrupt */ @@ -279,7 +280,19 @@ int skl_init_dsp(struct skl *skl) return ret;
skl->skl_sst->dsp_ops = ops; - skl->skl_sst->cores.count = ops->num_cores; + cores = &skl->skl_sst->cores; + cores->count = ops->num_cores; + + cores->state = kcalloc(cores->count, sizeof(*cores->state), GFP_KERNEL); + if (!cores->state) + return -ENOMEM; + + cores->usage_count = kcalloc(cores->count, sizeof(*cores->usage_count), + GFP_KERNEL); + if (!cores->usage_count) { + kfree(cores->state); + return -ENOMEM; + }
dev_dbg(bus->dev, "dsp registration status=%d\n", ret);
@@ -297,6 +310,9 @@ int skl_free_dsp(struct skl *skl)
ctx->dsp_ops->cleanup(bus->dev, ctx);
+ kfree(ctx->cores.state); + kfree(ctx->cores.usage_count); + if (ctx->dsp->addr.lpe) iounmap(ctx->dsp->addr.lpe);
diff --git a/sound/soc/intel/skylake/skl-sst-dsp.c b/sound/soc/intel/skylake/skl-sst-dsp.c index 08332723c700..c2ba5ff1632c 100644 --- a/sound/soc/intel/skylake/skl-sst-dsp.c +++ b/sound/soc/intel/skylake/skl-sst-dsp.c @@ -47,7 +47,7 @@ void skl_dsp_init_core_state(struct sst_dsp *ctx) skl->cores.state[SKL_DSP_CORE0_ID] = SKL_DSP_RUNNING; skl->cores.usage_count[SKL_DSP_CORE0_ID] = 1;
- for (i = SKL_DSP_CORE0_ID + 1; i < SKL_DSP_CORES_MAX; i++) { + for (i = SKL_DSP_CORE0_ID + 1; i < skl->cores.count; i++) { skl->cores.state[i] = SKL_DSP_RESET; skl->cores.usage_count[i] = 0; } diff --git a/sound/soc/intel/skylake/skl-sst-ipc.h b/sound/soc/intel/skylake/skl-sst-ipc.h index e057da2713c6..e485e8f5ea2c 100644 --- a/sound/soc/intel/skylake/skl-sst-ipc.h +++ b/sound/soc/intel/skylake/skl-sst-ipc.h @@ -44,12 +44,10 @@ struct skl_ipc_header { u32 extension; };
-#define SKL_DSP_CORES_MAX 2 - struct skl_dsp_cores { unsigned int count; - enum skl_dsp_states state[SKL_DSP_CORES_MAX]; - int usage_count[SKL_DSP_CORES_MAX]; + enum skl_dsp_states *state; + int *usage_count; };
/**
The patch
ASoC: Intel: Skylake: Use num_core to allocate instead of macro
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 f0a550a88373b0b076785e059cca15f32ae9ffeb Mon Sep 17 00:00:00 2001
From: Guneshwor Singh guneshwor.o.singh@intel.com Date: Wed, 2 Aug 2017 21:51:13 +0530 Subject: [PATCH] ASoC: Intel: Skylake: Use num_core to allocate instead of macro
For different platforms, number of dsp cores can vary. So instead of creating array of size SKL_DSP_CORES_MAX, use num_core in dsp_ops() of the respective platform to allocate core usage counts and states.
Signed-off-by: Guneshwor Singh guneshwor.o.singh@intel.com Acked-By: Vinod Koul vinod.koul@intel.com Signed-off-by: Mark Brown broonie@kernel.org --- sound/soc/intel/skylake/skl-messages.c | 18 +++++++++++++++++- sound/soc/intel/skylake/skl-sst-dsp.c | 2 +- sound/soc/intel/skylake/skl-sst-ipc.h | 6 ++---- 3 files changed, 20 insertions(+), 6 deletions(-)
diff --git a/sound/soc/intel/skylake/skl-messages.c b/sound/soc/intel/skylake/skl-messages.c index 7892e445e87b..c6b60ee5b196 100644 --- a/sound/soc/intel/skylake/skl-messages.c +++ b/sound/soc/intel/skylake/skl-messages.c @@ -253,6 +253,7 @@ int skl_init_dsp(struct skl *skl) struct skl_dsp_loader_ops loader_ops; int irq = bus->irq; const struct skl_dsp_ops *ops; + struct skl_dsp_cores *cores; int ret;
/* enable ppcap interrupt */ @@ -279,7 +280,19 @@ int skl_init_dsp(struct skl *skl) return ret;
skl->skl_sst->dsp_ops = ops; - skl->skl_sst->cores.count = ops->num_cores; + cores = &skl->skl_sst->cores; + cores->count = ops->num_cores; + + cores->state = kcalloc(cores->count, sizeof(*cores->state), GFP_KERNEL); + if (!cores->state) + return -ENOMEM; + + cores->usage_count = kcalloc(cores->count, sizeof(*cores->usage_count), + GFP_KERNEL); + if (!cores->usage_count) { + kfree(cores->state); + return -ENOMEM; + }
dev_dbg(bus->dev, "dsp registration status=%d\n", ret);
@@ -297,6 +310,9 @@ int skl_free_dsp(struct skl *skl)
ctx->dsp_ops->cleanup(bus->dev, ctx);
+ kfree(ctx->cores.state); + kfree(ctx->cores.usage_count); + if (ctx->dsp->addr.lpe) iounmap(ctx->dsp->addr.lpe);
diff --git a/sound/soc/intel/skylake/skl-sst-dsp.c b/sound/soc/intel/skylake/skl-sst-dsp.c index 08332723c700..c2ba5ff1632c 100644 --- a/sound/soc/intel/skylake/skl-sst-dsp.c +++ b/sound/soc/intel/skylake/skl-sst-dsp.c @@ -47,7 +47,7 @@ void skl_dsp_init_core_state(struct sst_dsp *ctx) skl->cores.state[SKL_DSP_CORE0_ID] = SKL_DSP_RUNNING; skl->cores.usage_count[SKL_DSP_CORE0_ID] = 1;
- for (i = SKL_DSP_CORE0_ID + 1; i < SKL_DSP_CORES_MAX; i++) { + for (i = SKL_DSP_CORE0_ID + 1; i < skl->cores.count; i++) { skl->cores.state[i] = SKL_DSP_RESET; skl->cores.usage_count[i] = 0; } diff --git a/sound/soc/intel/skylake/skl-sst-ipc.h b/sound/soc/intel/skylake/skl-sst-ipc.h index e057da2713c6..e485e8f5ea2c 100644 --- a/sound/soc/intel/skylake/skl-sst-ipc.h +++ b/sound/soc/intel/skylake/skl-sst-ipc.h @@ -44,12 +44,10 @@ struct skl_ipc_header { u32 extension; };
-#define SKL_DSP_CORES_MAX 2 - struct skl_dsp_cores { unsigned int count; - enum skl_dsp_states state[SKL_DSP_CORES_MAX]; - int usage_count[SKL_DSP_CORES_MAX]; + enum skl_dsp_states *state; + int *usage_count; };
/**
From: Pardha Saradhi K pardha.saradhi.kesapragada@intel.com
This patch adds support to manage additional cores on a demand basis. For instance, if module is set to run on certain core, the particular core is powered up in module init. The same is again powered down in module unload.
Signed-off-by: Pardha Saradhi K pardha.saradhi.kesapragada@intel.com Signed-off-by: Guneshwor Singh guneshwor.o.singh@intel.com --- sound/soc/intel/skylake/skl-topology.c | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-)
diff --git a/sound/soc/intel/skylake/skl-topology.c b/sound/soc/intel/skylake/skl-topology.c index 8c3ce08f366d..350d2387f737 100644 --- a/sound/soc/intel/skylake/skl-topology.c +++ b/sound/soc/intel/skylake/skl-topology.c @@ -596,24 +596,35 @@ skl_tplg_init_pipe_modules(struct skl *skl, struct skl_pipe *pipe) if (mconfig->id.pvt_id < 0) return ret; skl_tplg_set_module_init_data(w); + + ret = skl_dsp_get_core(ctx->dsp, mconfig->core_id); + if (ret < 0) { + dev_err(ctx->dev, "Failed to wake up core %d ret=%d\n", + mconfig->core_id, ret); + return ret; + } + ret = skl_init_module(ctx, mconfig); if (ret < 0) { skl_put_pvt_id(ctx, uuid_mod, &mconfig->id.pvt_id); - return ret; + goto err; } skl_tplg_alloc_pipe_mcps(skl, mconfig); ret = skl_tplg_set_module_params(w, ctx); if (ret < 0) - return ret; + goto err; }
return 0; +err: + skl_dsp_put_core(ctx->dsp, mconfig->core_id); + return ret; }
static int skl_tplg_unload_pipe_modules(struct skl_sst *ctx, struct skl_pipe *pipe) { - int ret; + int ret = 0; struct skl_pipe_module *w_module = NULL; struct skl_module_cfg *mconfig = NULL;
@@ -630,10 +641,17 @@ static int skl_tplg_unload_pipe_modules(struct skl_sst *ctx, return -EIO; } skl_put_pvt_id(ctx, uuid_mod, &mconfig->id.pvt_id); + + ret = skl_dsp_put_core(ctx->dsp, mconfig->core_id); + if (ret < 0) { + /* don't return; continue with other modules */ + dev_err(ctx->dev, "Failed to sleep core %d ret=%d\n", + mconfig->core_id, ret); + } }
/* no modules to unload in this path, so return */ - return 0; + return ret; }
/*
The patch
ASoC: Intel: Skylake: Add dsp cores management
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 4147a6e59a5c0b9cb0eeaa3e1f39fd9da491f35a Mon Sep 17 00:00:00 2001
From: Pardha Saradhi K pardha.saradhi.kesapragada@intel.com Date: Wed, 2 Aug 2017 21:51:14 +0530 Subject: [PATCH] ASoC: Intel: Skylake: Add dsp cores management
This patch adds support to manage additional cores on a demand basis. For instance, if module is set to run on certain core, the particular core is powered up in module init. The same is again powered down in module unload.
Signed-off-by: Pardha Saradhi K pardha.saradhi.kesapragada@intel.com Signed-off-by: Guneshwor Singh guneshwor.o.singh@intel.com Acked-By: Vinod Koul vinod.koul@intel.com Signed-off-by: Mark Brown broonie@kernel.org --- sound/soc/intel/skylake/skl-topology.c | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-)
diff --git a/sound/soc/intel/skylake/skl-topology.c b/sound/soc/intel/skylake/skl-topology.c index 8c3ce08f366d..350d2387f737 100644 --- a/sound/soc/intel/skylake/skl-topology.c +++ b/sound/soc/intel/skylake/skl-topology.c @@ -596,24 +596,35 @@ skl_tplg_init_pipe_modules(struct skl *skl, struct skl_pipe *pipe) if (mconfig->id.pvt_id < 0) return ret; skl_tplg_set_module_init_data(w); + + ret = skl_dsp_get_core(ctx->dsp, mconfig->core_id); + if (ret < 0) { + dev_err(ctx->dev, "Failed to wake up core %d ret=%d\n", + mconfig->core_id, ret); + return ret; + } + ret = skl_init_module(ctx, mconfig); if (ret < 0) { skl_put_pvt_id(ctx, uuid_mod, &mconfig->id.pvt_id); - return ret; + goto err; } skl_tplg_alloc_pipe_mcps(skl, mconfig); ret = skl_tplg_set_module_params(w, ctx); if (ret < 0) - return ret; + goto err; }
return 0; +err: + skl_dsp_put_core(ctx->dsp, mconfig->core_id); + return ret; }
static int skl_tplg_unload_pipe_modules(struct skl_sst *ctx, struct skl_pipe *pipe) { - int ret; + int ret = 0; struct skl_pipe_module *w_module = NULL; struct skl_module_cfg *mconfig = NULL;
@@ -630,10 +641,17 @@ static int skl_tplg_unload_pipe_modules(struct skl_sst *ctx, return -EIO; } skl_put_pvt_id(ctx, uuid_mod, &mconfig->id.pvt_id); + + ret = skl_dsp_put_core(ctx->dsp, mconfig->core_id); + if (ret < 0) { + /* don't return; continue with other modules */ + dev_err(ctx->dev, "Failed to sleep core %d ret=%d\n", + mconfig->core_id, ret); + } }
/* no modules to unload in this path, so return */ - return 0; + return ret; }
/*
This adds Cannonlake specific registers and support for CNL dsp related library functions for programming the registers to power up/down dsp cores, set/unset reset states for each core, enable/disable ipc interrupts and few wrappers to be called from elsewhere.
Signed-off-by: Guneshwor Singh guneshwor.o.singh@intel.com --- sound/soc/intel/skylake/cnl-sst-dsp.c | 274 ++++++++++++++++++++++++++++++++++ sound/soc/intel/skylake/cnl-sst-dsp.h | 106 +++++++++++++ 2 files changed, 380 insertions(+) create mode 100644 sound/soc/intel/skylake/cnl-sst-dsp.c create mode 100644 sound/soc/intel/skylake/cnl-sst-dsp.h
diff --git a/sound/soc/intel/skylake/cnl-sst-dsp.c b/sound/soc/intel/skylake/cnl-sst-dsp.c new file mode 100644 index 000000000000..2f8326707c21 --- /dev/null +++ b/sound/soc/intel/skylake/cnl-sst-dsp.c @@ -0,0 +1,274 @@ +/* + * cnl-sst-dsp.c - CNL SST library generic function + * + * Copyright (C) 2016-17, Intel Corporation. + * Author: Guneshwor Singh guneshwor.o.singh@intel.com + * + * Modified from: + * SKL SST library generic function + * Copyright (C) 2014-15, Intel Corporation. + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as version 2, as + * published by the Free Software Foundation. + * + * 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/device.h> +#include "../common/sst-dsp.h" +#include "../common/sst-ipc.h" +#include "../common/sst-dsp-priv.h" +#include "cnl-sst-dsp.h" + +/* various timeout values */ +#define CNL_DSP_PU_TO 50 +#define CNL_DSP_PD_TO 50 +#define CNL_DSP_RESET_TO 50 + +static int +cnl_dsp_core_set_reset_state(struct sst_dsp *ctx, unsigned int core_mask) +{ + /* update bits */ + sst_dsp_shim_update_bits_unlocked(ctx, + CNL_ADSP_REG_ADSPCS, CNL_ADSPCS_CRST(core_mask), + CNL_ADSPCS_CRST(core_mask)); + + /* poll with timeout to check if operation successful */ + return sst_dsp_register_poll(ctx, + CNL_ADSP_REG_ADSPCS, + CNL_ADSPCS_CRST(core_mask), + CNL_ADSPCS_CRST(core_mask), + CNL_DSP_RESET_TO, + "Set reset"); +} + +static int +cnl_dsp_core_unset_reset_state(struct sst_dsp *ctx, unsigned int core_mask) +{ + /* update bits */ + sst_dsp_shim_update_bits_unlocked(ctx, CNL_ADSP_REG_ADSPCS, + CNL_ADSPCS_CRST(core_mask), 0); + + /* poll with timeout to check if operation successful */ + return sst_dsp_register_poll(ctx, + CNL_ADSP_REG_ADSPCS, + CNL_ADSPCS_CRST(core_mask), + 0, + CNL_DSP_RESET_TO, + "Unset reset"); +} + +static bool is_cnl_dsp_core_enable(struct sst_dsp *ctx, unsigned int core_mask) +{ + int val; + bool is_enable; + + val = sst_dsp_shim_read_unlocked(ctx, CNL_ADSP_REG_ADSPCS); + + is_enable = (val & CNL_ADSPCS_CPA(core_mask)) && + (val & CNL_ADSPCS_SPA(core_mask)) && + !(val & CNL_ADSPCS_CRST(core_mask)) && + !(val & CNL_ADSPCS_CSTALL(core_mask)); + + dev_dbg(ctx->dev, "DSP core(s) enabled? %d: core_mask %#x\n", + is_enable, core_mask); + + return is_enable; +} + +static int cnl_dsp_reset_core(struct sst_dsp *ctx, unsigned int core_mask) +{ + /* stall core */ + sst_dsp_shim_update_bits_unlocked(ctx, CNL_ADSP_REG_ADSPCS, + CNL_ADSPCS_CSTALL(core_mask), + CNL_ADSPCS_CSTALL(core_mask)); + + /* set reset state */ + return cnl_dsp_core_set_reset_state(ctx, core_mask); +} + +static int cnl_dsp_start_core(struct sst_dsp *ctx, unsigned int core_mask) +{ + int ret; + + /* unset reset state */ + ret = cnl_dsp_core_unset_reset_state(ctx, core_mask); + if (ret < 0) + return ret; + + /* run core */ + sst_dsp_shim_update_bits_unlocked(ctx, CNL_ADSP_REG_ADSPCS, + CNL_ADSPCS_CSTALL(core_mask), 0); + + if (!is_cnl_dsp_core_enable(ctx, core_mask)) { + cnl_dsp_reset_core(ctx, core_mask); + dev_err(ctx->dev, "DSP core mask %#x enable failed\n", + core_mask); + ret = -EIO; + } + + return ret; +} + +static int cnl_dsp_core_power_up(struct sst_dsp *ctx, unsigned int core_mask) +{ + /* update bits */ + sst_dsp_shim_update_bits_unlocked(ctx, CNL_ADSP_REG_ADSPCS, + CNL_ADSPCS_SPA(core_mask), + CNL_ADSPCS_SPA(core_mask)); + + /* poll with timeout to check if operation successful */ + return sst_dsp_register_poll(ctx, CNL_ADSP_REG_ADSPCS, + CNL_ADSPCS_CPA(core_mask), + CNL_ADSPCS_CPA(core_mask), + CNL_DSP_PU_TO, + "Power up"); +} + +static int cnl_dsp_core_power_down(struct sst_dsp *ctx, unsigned int core_mask) +{ + /* update bits */ + sst_dsp_shim_update_bits_unlocked(ctx, CNL_ADSP_REG_ADSPCS, + CNL_ADSPCS_SPA(core_mask), 0); + + /* poll with timeout to check if operation successful */ + return sst_dsp_register_poll(ctx, + CNL_ADSP_REG_ADSPCS, + CNL_ADSPCS_CPA(core_mask), + 0, + CNL_DSP_PD_TO, + "Power down"); +} + +int cnl_dsp_enable_core(struct sst_dsp *ctx, unsigned int core_mask) +{ + int ret; + + /* power up */ + ret = cnl_dsp_core_power_up(ctx, core_mask); + if (ret < 0) { + dev_dbg(ctx->dev, "DSP core mask %#x power up failed", + core_mask); + return ret; + } + + return cnl_dsp_start_core(ctx, core_mask); +} + +int cnl_dsp_disable_core(struct sst_dsp *ctx, unsigned int core_mask) +{ + int ret; + + ret = cnl_dsp_reset_core(ctx, core_mask); + if (ret < 0) { + dev_err(ctx->dev, "DSP core mask %#x reset failed\n", + core_mask); + return ret; + } + + /* power down core*/ + ret = cnl_dsp_core_power_down(ctx, core_mask); + if (ret < 0) { + dev_err(ctx->dev, "DSP core mask %#x power down failed\n", + core_mask); + return ret; + } + + if (is_cnl_dsp_core_enable(ctx, core_mask)) { + dev_err(ctx->dev, "DSP core mask %#x disable failed\n", + core_mask); + ret = -EIO; + } + + return ret; +} + +irqreturn_t cnl_dsp_sst_interrupt(int irq, void *dev_id) +{ + struct sst_dsp *ctx = dev_id; + u32 val; + irqreturn_t ret = IRQ_NONE; + + spin_lock(&ctx->spinlock); + + val = sst_dsp_shim_read_unlocked(ctx, CNL_ADSP_REG_ADSPIS); + ctx->intr_status = val; + + if (val == 0xffffffff) { + spin_unlock(&ctx->spinlock); + return IRQ_NONE; + } + + if (val & CNL_ADSPIS_IPC) { + cnl_ipc_int_disable(ctx); + ret = IRQ_WAKE_THREAD; + } + + spin_unlock(&ctx->spinlock); + + return ret; +} + +void cnl_dsp_free(struct sst_dsp *dsp) +{ + cnl_ipc_int_disable(dsp); + + free_irq(dsp->irq, dsp); + cnl_ipc_op_int_disable(dsp); + cnl_dsp_disable_core(dsp, SKL_DSP_CORE0_MASK); +} +EXPORT_SYMBOL_GPL(cnl_dsp_free); + +void cnl_ipc_int_enable(struct sst_dsp *ctx) +{ + sst_dsp_shim_update_bits(ctx, CNL_ADSP_REG_ADSPIC, + CNL_ADSPIC_IPC, CNL_ADSPIC_IPC); +} + +void cnl_ipc_int_disable(struct sst_dsp *ctx) +{ + sst_dsp_shim_update_bits_unlocked(ctx, CNL_ADSP_REG_ADSPIC, + CNL_ADSPIC_IPC, 0); +} + +void cnl_ipc_op_int_enable(struct sst_dsp *ctx) +{ + /* enable IPC DONE interrupt */ + sst_dsp_shim_update_bits(ctx, CNL_ADSP_REG_HIPCCTL, + CNL_ADSP_REG_HIPCCTL_DONE, + CNL_ADSP_REG_HIPCCTL_DONE); + + /* enable IPC BUSY interrupt */ + sst_dsp_shim_update_bits(ctx, CNL_ADSP_REG_HIPCCTL, + CNL_ADSP_REG_HIPCCTL_BUSY, + CNL_ADSP_REG_HIPCCTL_BUSY); +} + +void cnl_ipc_op_int_disable(struct sst_dsp *ctx) +{ + /* disable IPC DONE interrupt */ + sst_dsp_shim_update_bits(ctx, CNL_ADSP_REG_HIPCCTL, + CNL_ADSP_REG_HIPCCTL_DONE, 0); + + /* disable IPC BUSY interrupt */ + sst_dsp_shim_update_bits(ctx, CNL_ADSP_REG_HIPCCTL, + CNL_ADSP_REG_HIPCCTL_BUSY, 0); +} + +bool cnl_ipc_int_status(struct sst_dsp *ctx) +{ + return sst_dsp_shim_read_unlocked(ctx, CNL_ADSP_REG_ADSPIS) & + CNL_ADSPIS_IPC; +} + +void cnl_ipc_free(struct sst_generic_ipc *ipc) +{ + cnl_ipc_op_int_disable(ipc->dsp); + sst_ipc_fini(ipc); +} diff --git a/sound/soc/intel/skylake/cnl-sst-dsp.h b/sound/soc/intel/skylake/cnl-sst-dsp.h new file mode 100644 index 000000000000..2fe41b137a2c --- /dev/null +++ b/sound/soc/intel/skylake/cnl-sst-dsp.h @@ -0,0 +1,106 @@ +/* + * Cannonlake SST DSP Support + * + * Copyright (C) 2016-17, Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as version 2, as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef __CNL_SST_DSP_H__ +#define __CNL_SST_DSP_H__ + +struct sst_dsp; +struct skl_sst; +struct sst_dsp_device; +struct sst_generic_ipc; + +/* Intel HD Audio General DSP Registers */ +#define CNL_ADSP_GEN_BASE 0x0 +#define CNL_ADSP_REG_ADSPCS (CNL_ADSP_GEN_BASE + 0x04) +#define CNL_ADSP_REG_ADSPIC (CNL_ADSP_GEN_BASE + 0x08) +#define CNL_ADSP_REG_ADSPIS (CNL_ADSP_GEN_BASE + 0x0c) + +/* Intel HD Audio Inter-Processor Communication Registers */ +#define CNL_ADSP_IPC_BASE 0xc0 +#define CNL_ADSP_REG_HIPCTDR (CNL_ADSP_IPC_BASE + 0x00) +#define CNL_ADSP_REG_HIPCTDA (CNL_ADSP_IPC_BASE + 0x04) +#define CNL_ADSP_REG_HIPCTDD (CNL_ADSP_IPC_BASE + 0x08) +#define CNL_ADSP_REG_HIPCIDR (CNL_ADSP_IPC_BASE + 0x10) +#define CNL_ADSP_REG_HIPCIDA (CNL_ADSP_IPC_BASE + 0x14) +#define CNL_ADSP_REG_HIPCIDD (CNL_ADSP_IPC_BASE + 0x18) +#define CNL_ADSP_REG_HIPCCTL (CNL_ADSP_IPC_BASE + 0x28) + +/* HIPCTDR */ +#define CNL_ADSP_REG_HIPCTDR_BUSY BIT(31) + +/* HIPCTDA */ +#define CNL_ADSP_REG_HIPCTDA_DONE BIT(31) + +/* HIPCIDR */ +#define CNL_ADSP_REG_HIPCIDR_BUSY BIT(31) + +/* HIPCIDA */ +#define CNL_ADSP_REG_HIPCIDA_DONE BIT(31) + +/* CNL HIPCCTL */ +#define CNL_ADSP_REG_HIPCCTL_DONE BIT(1) +#define CNL_ADSP_REG_HIPCCTL_BUSY BIT(0) + +/* CNL HIPCT */ +#define CNL_ADSP_REG_HIPCT_BUSY BIT(31) + +/* Intel HD Audio SRAM Window 1 */ +#define CNL_ADSP_SRAM1_BASE 0xa0000 + +#define CNL_ADSP_MMIO_LEN 0x10000 + +#define CNL_ADSP_W0_STAT_SZ 0x1000 + +#define CNL_ADSP_W0_UP_SZ 0x1000 + +#define CNL_ADSP_W1_SZ 0x1000 + +#define CNL_FW_STS_MASK 0xf + +#define CNL_ADSPIC_IPC 0x1 +#define CNL_ADSPIS_IPC 0x1 + +#define CNL_DSP_CORES 4 +#define CNL_DSP_CORES_MASK ((1 << CNL_DSP_CORES) - 1) + +/* core reset - asserted high */ +#define CNL_ADSPCS_CRST_SHIFT 0 +#define CNL_ADSPCS_CRST(x) (x << CNL_ADSPCS_CRST_SHIFT) + +/* core run/stall - when set to 1 core is stalled */ +#define CNL_ADSPCS_CSTALL_SHIFT 8 +#define CNL_ADSPCS_CSTALL(x) (x << CNL_ADSPCS_CSTALL_SHIFT) + +/* set power active - when set to 1 turn core on */ +#define CNL_ADSPCS_SPA_SHIFT 16 +#define CNL_ADSPCS_SPA(x) (x << CNL_ADSPCS_SPA_SHIFT) + +/* current power active - power status of cores, set by hardware */ +#define CNL_ADSPCS_CPA_SHIFT 24 +#define CNL_ADSPCS_CPA(x) (x << CNL_ADSPCS_CPA_SHIFT) + +int cnl_dsp_enable_core(struct sst_dsp *ctx, unsigned int core); +int cnl_dsp_disable_core(struct sst_dsp *ctx, unsigned int core); +irqreturn_t cnl_dsp_sst_interrupt(int irq, void *dev_id); +void cnl_dsp_free(struct sst_dsp *dsp); + +void cnl_ipc_int_enable(struct sst_dsp *ctx); +void cnl_ipc_int_disable(struct sst_dsp *ctx); +void cnl_ipc_op_int_enable(struct sst_dsp *ctx); +void cnl_ipc_op_int_disable(struct sst_dsp *ctx); +bool cnl_ipc_int_status(struct sst_dsp *ctx); +void cnl_ipc_free(struct sst_generic_ipc *ipc); + +#endif /*__CNL_SST_DSP_H__*/
The patch
ASoC: Intel: cnl: Add cnl dsp functions and registers
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 a838dcc286754f6ea6bcbee8eb76a5d626642fa7 Mon Sep 17 00:00:00 2001
From: Guneshwor Singh guneshwor.o.singh@intel.com Date: Wed, 2 Aug 2017 21:51:15 +0530 Subject: [PATCH] ASoC: Intel: cnl: Add cnl dsp functions and registers
This adds Cannonlake specific registers and support for CNL dsp related library functions for programming the registers to power up/down dsp cores, set/unset reset states for each core, enable/disable ipc interrupts and few wrappers to be called from elsewhere.
Signed-off-by: Guneshwor Singh guneshwor.o.singh@intel.com Acked-By: Vinod Koul vinod.koul@intel.com Signed-off-by: Mark Brown broonie@kernel.org --- sound/soc/intel/skylake/cnl-sst-dsp.c | 274 ++++++++++++++++++++++++++++++++++ sound/soc/intel/skylake/cnl-sst-dsp.h | 106 +++++++++++++ 2 files changed, 380 insertions(+) create mode 100644 sound/soc/intel/skylake/cnl-sst-dsp.c create mode 100644 sound/soc/intel/skylake/cnl-sst-dsp.h
diff --git a/sound/soc/intel/skylake/cnl-sst-dsp.c b/sound/soc/intel/skylake/cnl-sst-dsp.c new file mode 100644 index 000000000000..2f8326707c21 --- /dev/null +++ b/sound/soc/intel/skylake/cnl-sst-dsp.c @@ -0,0 +1,274 @@ +/* + * cnl-sst-dsp.c - CNL SST library generic function + * + * Copyright (C) 2016-17, Intel Corporation. + * Author: Guneshwor Singh guneshwor.o.singh@intel.com + * + * Modified from: + * SKL SST library generic function + * Copyright (C) 2014-15, Intel Corporation. + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as version 2, as + * published by the Free Software Foundation. + * + * 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/device.h> +#include "../common/sst-dsp.h" +#include "../common/sst-ipc.h" +#include "../common/sst-dsp-priv.h" +#include "cnl-sst-dsp.h" + +/* various timeout values */ +#define CNL_DSP_PU_TO 50 +#define CNL_DSP_PD_TO 50 +#define CNL_DSP_RESET_TO 50 + +static int +cnl_dsp_core_set_reset_state(struct sst_dsp *ctx, unsigned int core_mask) +{ + /* update bits */ + sst_dsp_shim_update_bits_unlocked(ctx, + CNL_ADSP_REG_ADSPCS, CNL_ADSPCS_CRST(core_mask), + CNL_ADSPCS_CRST(core_mask)); + + /* poll with timeout to check if operation successful */ + return sst_dsp_register_poll(ctx, + CNL_ADSP_REG_ADSPCS, + CNL_ADSPCS_CRST(core_mask), + CNL_ADSPCS_CRST(core_mask), + CNL_DSP_RESET_TO, + "Set reset"); +} + +static int +cnl_dsp_core_unset_reset_state(struct sst_dsp *ctx, unsigned int core_mask) +{ + /* update bits */ + sst_dsp_shim_update_bits_unlocked(ctx, CNL_ADSP_REG_ADSPCS, + CNL_ADSPCS_CRST(core_mask), 0); + + /* poll with timeout to check if operation successful */ + return sst_dsp_register_poll(ctx, + CNL_ADSP_REG_ADSPCS, + CNL_ADSPCS_CRST(core_mask), + 0, + CNL_DSP_RESET_TO, + "Unset reset"); +} + +static bool is_cnl_dsp_core_enable(struct sst_dsp *ctx, unsigned int core_mask) +{ + int val; + bool is_enable; + + val = sst_dsp_shim_read_unlocked(ctx, CNL_ADSP_REG_ADSPCS); + + is_enable = (val & CNL_ADSPCS_CPA(core_mask)) && + (val & CNL_ADSPCS_SPA(core_mask)) && + !(val & CNL_ADSPCS_CRST(core_mask)) && + !(val & CNL_ADSPCS_CSTALL(core_mask)); + + dev_dbg(ctx->dev, "DSP core(s) enabled? %d: core_mask %#x\n", + is_enable, core_mask); + + return is_enable; +} + +static int cnl_dsp_reset_core(struct sst_dsp *ctx, unsigned int core_mask) +{ + /* stall core */ + sst_dsp_shim_update_bits_unlocked(ctx, CNL_ADSP_REG_ADSPCS, + CNL_ADSPCS_CSTALL(core_mask), + CNL_ADSPCS_CSTALL(core_mask)); + + /* set reset state */ + return cnl_dsp_core_set_reset_state(ctx, core_mask); +} + +static int cnl_dsp_start_core(struct sst_dsp *ctx, unsigned int core_mask) +{ + int ret; + + /* unset reset state */ + ret = cnl_dsp_core_unset_reset_state(ctx, core_mask); + if (ret < 0) + return ret; + + /* run core */ + sst_dsp_shim_update_bits_unlocked(ctx, CNL_ADSP_REG_ADSPCS, + CNL_ADSPCS_CSTALL(core_mask), 0); + + if (!is_cnl_dsp_core_enable(ctx, core_mask)) { + cnl_dsp_reset_core(ctx, core_mask); + dev_err(ctx->dev, "DSP core mask %#x enable failed\n", + core_mask); + ret = -EIO; + } + + return ret; +} + +static int cnl_dsp_core_power_up(struct sst_dsp *ctx, unsigned int core_mask) +{ + /* update bits */ + sst_dsp_shim_update_bits_unlocked(ctx, CNL_ADSP_REG_ADSPCS, + CNL_ADSPCS_SPA(core_mask), + CNL_ADSPCS_SPA(core_mask)); + + /* poll with timeout to check if operation successful */ + return sst_dsp_register_poll(ctx, CNL_ADSP_REG_ADSPCS, + CNL_ADSPCS_CPA(core_mask), + CNL_ADSPCS_CPA(core_mask), + CNL_DSP_PU_TO, + "Power up"); +} + +static int cnl_dsp_core_power_down(struct sst_dsp *ctx, unsigned int core_mask) +{ + /* update bits */ + sst_dsp_shim_update_bits_unlocked(ctx, CNL_ADSP_REG_ADSPCS, + CNL_ADSPCS_SPA(core_mask), 0); + + /* poll with timeout to check if operation successful */ + return sst_dsp_register_poll(ctx, + CNL_ADSP_REG_ADSPCS, + CNL_ADSPCS_CPA(core_mask), + 0, + CNL_DSP_PD_TO, + "Power down"); +} + +int cnl_dsp_enable_core(struct sst_dsp *ctx, unsigned int core_mask) +{ + int ret; + + /* power up */ + ret = cnl_dsp_core_power_up(ctx, core_mask); + if (ret < 0) { + dev_dbg(ctx->dev, "DSP core mask %#x power up failed", + core_mask); + return ret; + } + + return cnl_dsp_start_core(ctx, core_mask); +} + +int cnl_dsp_disable_core(struct sst_dsp *ctx, unsigned int core_mask) +{ + int ret; + + ret = cnl_dsp_reset_core(ctx, core_mask); + if (ret < 0) { + dev_err(ctx->dev, "DSP core mask %#x reset failed\n", + core_mask); + return ret; + } + + /* power down core*/ + ret = cnl_dsp_core_power_down(ctx, core_mask); + if (ret < 0) { + dev_err(ctx->dev, "DSP core mask %#x power down failed\n", + core_mask); + return ret; + } + + if (is_cnl_dsp_core_enable(ctx, core_mask)) { + dev_err(ctx->dev, "DSP core mask %#x disable failed\n", + core_mask); + ret = -EIO; + } + + return ret; +} + +irqreturn_t cnl_dsp_sst_interrupt(int irq, void *dev_id) +{ + struct sst_dsp *ctx = dev_id; + u32 val; + irqreturn_t ret = IRQ_NONE; + + spin_lock(&ctx->spinlock); + + val = sst_dsp_shim_read_unlocked(ctx, CNL_ADSP_REG_ADSPIS); + ctx->intr_status = val; + + if (val == 0xffffffff) { + spin_unlock(&ctx->spinlock); + return IRQ_NONE; + } + + if (val & CNL_ADSPIS_IPC) { + cnl_ipc_int_disable(ctx); + ret = IRQ_WAKE_THREAD; + } + + spin_unlock(&ctx->spinlock); + + return ret; +} + +void cnl_dsp_free(struct sst_dsp *dsp) +{ + cnl_ipc_int_disable(dsp); + + free_irq(dsp->irq, dsp); + cnl_ipc_op_int_disable(dsp); + cnl_dsp_disable_core(dsp, SKL_DSP_CORE0_MASK); +} +EXPORT_SYMBOL_GPL(cnl_dsp_free); + +void cnl_ipc_int_enable(struct sst_dsp *ctx) +{ + sst_dsp_shim_update_bits(ctx, CNL_ADSP_REG_ADSPIC, + CNL_ADSPIC_IPC, CNL_ADSPIC_IPC); +} + +void cnl_ipc_int_disable(struct sst_dsp *ctx) +{ + sst_dsp_shim_update_bits_unlocked(ctx, CNL_ADSP_REG_ADSPIC, + CNL_ADSPIC_IPC, 0); +} + +void cnl_ipc_op_int_enable(struct sst_dsp *ctx) +{ + /* enable IPC DONE interrupt */ + sst_dsp_shim_update_bits(ctx, CNL_ADSP_REG_HIPCCTL, + CNL_ADSP_REG_HIPCCTL_DONE, + CNL_ADSP_REG_HIPCCTL_DONE); + + /* enable IPC BUSY interrupt */ + sst_dsp_shim_update_bits(ctx, CNL_ADSP_REG_HIPCCTL, + CNL_ADSP_REG_HIPCCTL_BUSY, + CNL_ADSP_REG_HIPCCTL_BUSY); +} + +void cnl_ipc_op_int_disable(struct sst_dsp *ctx) +{ + /* disable IPC DONE interrupt */ + sst_dsp_shim_update_bits(ctx, CNL_ADSP_REG_HIPCCTL, + CNL_ADSP_REG_HIPCCTL_DONE, 0); + + /* disable IPC BUSY interrupt */ + sst_dsp_shim_update_bits(ctx, CNL_ADSP_REG_HIPCCTL, + CNL_ADSP_REG_HIPCCTL_BUSY, 0); +} + +bool cnl_ipc_int_status(struct sst_dsp *ctx) +{ + return sst_dsp_shim_read_unlocked(ctx, CNL_ADSP_REG_ADSPIS) & + CNL_ADSPIS_IPC; +} + +void cnl_ipc_free(struct sst_generic_ipc *ipc) +{ + cnl_ipc_op_int_disable(ipc->dsp); + sst_ipc_fini(ipc); +} diff --git a/sound/soc/intel/skylake/cnl-sst-dsp.h b/sound/soc/intel/skylake/cnl-sst-dsp.h new file mode 100644 index 000000000000..2fe41b137a2c --- /dev/null +++ b/sound/soc/intel/skylake/cnl-sst-dsp.h @@ -0,0 +1,106 @@ +/* + * Cannonlake SST DSP Support + * + * Copyright (C) 2016-17, Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as version 2, as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef __CNL_SST_DSP_H__ +#define __CNL_SST_DSP_H__ + +struct sst_dsp; +struct skl_sst; +struct sst_dsp_device; +struct sst_generic_ipc; + +/* Intel HD Audio General DSP Registers */ +#define CNL_ADSP_GEN_BASE 0x0 +#define CNL_ADSP_REG_ADSPCS (CNL_ADSP_GEN_BASE + 0x04) +#define CNL_ADSP_REG_ADSPIC (CNL_ADSP_GEN_BASE + 0x08) +#define CNL_ADSP_REG_ADSPIS (CNL_ADSP_GEN_BASE + 0x0c) + +/* Intel HD Audio Inter-Processor Communication Registers */ +#define CNL_ADSP_IPC_BASE 0xc0 +#define CNL_ADSP_REG_HIPCTDR (CNL_ADSP_IPC_BASE + 0x00) +#define CNL_ADSP_REG_HIPCTDA (CNL_ADSP_IPC_BASE + 0x04) +#define CNL_ADSP_REG_HIPCTDD (CNL_ADSP_IPC_BASE + 0x08) +#define CNL_ADSP_REG_HIPCIDR (CNL_ADSP_IPC_BASE + 0x10) +#define CNL_ADSP_REG_HIPCIDA (CNL_ADSP_IPC_BASE + 0x14) +#define CNL_ADSP_REG_HIPCIDD (CNL_ADSP_IPC_BASE + 0x18) +#define CNL_ADSP_REG_HIPCCTL (CNL_ADSP_IPC_BASE + 0x28) + +/* HIPCTDR */ +#define CNL_ADSP_REG_HIPCTDR_BUSY BIT(31) + +/* HIPCTDA */ +#define CNL_ADSP_REG_HIPCTDA_DONE BIT(31) + +/* HIPCIDR */ +#define CNL_ADSP_REG_HIPCIDR_BUSY BIT(31) + +/* HIPCIDA */ +#define CNL_ADSP_REG_HIPCIDA_DONE BIT(31) + +/* CNL HIPCCTL */ +#define CNL_ADSP_REG_HIPCCTL_DONE BIT(1) +#define CNL_ADSP_REG_HIPCCTL_BUSY BIT(0) + +/* CNL HIPCT */ +#define CNL_ADSP_REG_HIPCT_BUSY BIT(31) + +/* Intel HD Audio SRAM Window 1 */ +#define CNL_ADSP_SRAM1_BASE 0xa0000 + +#define CNL_ADSP_MMIO_LEN 0x10000 + +#define CNL_ADSP_W0_STAT_SZ 0x1000 + +#define CNL_ADSP_W0_UP_SZ 0x1000 + +#define CNL_ADSP_W1_SZ 0x1000 + +#define CNL_FW_STS_MASK 0xf + +#define CNL_ADSPIC_IPC 0x1 +#define CNL_ADSPIS_IPC 0x1 + +#define CNL_DSP_CORES 4 +#define CNL_DSP_CORES_MASK ((1 << CNL_DSP_CORES) - 1) + +/* core reset - asserted high */ +#define CNL_ADSPCS_CRST_SHIFT 0 +#define CNL_ADSPCS_CRST(x) (x << CNL_ADSPCS_CRST_SHIFT) + +/* core run/stall - when set to 1 core is stalled */ +#define CNL_ADSPCS_CSTALL_SHIFT 8 +#define CNL_ADSPCS_CSTALL(x) (x << CNL_ADSPCS_CSTALL_SHIFT) + +/* set power active - when set to 1 turn core on */ +#define CNL_ADSPCS_SPA_SHIFT 16 +#define CNL_ADSPCS_SPA(x) (x << CNL_ADSPCS_SPA_SHIFT) + +/* current power active - power status of cores, set by hardware */ +#define CNL_ADSPCS_CPA_SHIFT 24 +#define CNL_ADSPCS_CPA(x) (x << CNL_ADSPCS_CPA_SHIFT) + +int cnl_dsp_enable_core(struct sst_dsp *ctx, unsigned int core); +int cnl_dsp_disable_core(struct sst_dsp *ctx, unsigned int core); +irqreturn_t cnl_dsp_sst_interrupt(int irq, void *dev_id); +void cnl_dsp_free(struct sst_dsp *dsp); + +void cnl_ipc_int_enable(struct sst_dsp *ctx); +void cnl_ipc_int_disable(struct sst_dsp *ctx); +void cnl_ipc_op_int_enable(struct sst_dsp *ctx); +void cnl_ipc_op_int_disable(struct sst_dsp *ctx); +bool cnl_ipc_int_status(struct sst_dsp *ctx); +void cnl_ipc_free(struct sst_generic_ipc *ipc); + +#endif /*__CNL_SST_DSP_H__*/
Move ipc_init() from helper function to respective platform's dsp_init() as ipc_init() per platform can be different.
Signed-off-by: Guneshwor Singh guneshwor.o.singh@intel.com --- sound/soc/intel/skylake/bxt-sst.c | 4 ++++ sound/soc/intel/skylake/skl-sst-utils.c | 6 +----- sound/soc/intel/skylake/skl-sst.c | 4 ++++ 3 files changed, 9 insertions(+), 5 deletions(-)
diff --git a/sound/soc/intel/skylake/bxt-sst.c b/sound/soc/intel/skylake/bxt-sst.c index c404a42b670a..71042aceb25f 100644 --- a/sound/soc/intel/skylake/bxt-sst.c +++ b/sound/soc/intel/skylake/bxt-sst.c @@ -581,6 +581,10 @@ int bxt_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq, 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; + /* set the D0i3 check */ skl->ipc.ops.check_dsp_lp_on = skl_ipc_check_D0i0;
diff --git a/sound/soc/intel/skylake/skl-sst-utils.c b/sound/soc/intel/skylake/skl-sst-utils.c index 81ee251881b4..369ef7ce981c 100644 --- a/sound/soc/intel/skylake/skl-sst-utils.c +++ b/sound/soc/intel/skylake/skl-sst-utils.c @@ -368,7 +368,6 @@ int skl_sst_ctx_init(struct device *dev, int irq, const char *fw_name, { struct skl_sst *skl; struct sst_dsp *sst; - int ret;
skl = devm_kzalloc(dev, sizeof(*skl), GFP_KERNEL); if (skl == NULL) @@ -388,15 +387,12 @@ int skl_sst_ctx_init(struct device *dev, int irq, const char *fw_name, sst->dsp_ops = dsp_ops; init_waitqueue_head(&skl->mod_load_wait); INIT_LIST_HEAD(&sst->module_list); - ret = skl_ipc_init(dev, skl); - if (ret) - return ret;
skl->is_first_boot = true; if (dsp) *dsp = skl;
- return ret; + return 0; }
int skl_prepare_lib_load(struct skl_sst *skl, struct skl_lib_info *linfo, diff --git a/sound/soc/intel/skylake/skl-sst.c b/sound/soc/intel/skylake/skl-sst.c index fd99e74cda03..6cc586d3f03b 100644 --- a/sound/soc/intel/skylake/skl-sst.c +++ b/sound/soc/intel/skylake/skl-sst.c @@ -561,6 +561,10 @@ int skl_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq, sst_dsp_mailbox_init(sst, (SKL_ADSP_SRAM0_BASE + SKL_ADSP_W0_STAT_SZ), SKL_ADSP_W0_UP_SZ, SKL_ADSP_SRAM1_BASE, SKL_ADSP_W1_SZ);
+ ret = skl_ipc_init(dev, skl); + if (ret) + return ret; + sst->fw_ops = skl_fw_ops;
return 0;
The patch
ASoC: Intel: Skylake: Move platform specific init to platform dsp_init()
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 2eed1b024a11b497766604ee8f95e22711859af2 Mon Sep 17 00:00:00 2001
From: Guneshwor Singh guneshwor.o.singh@intel.com Date: Wed, 2 Aug 2017 21:51:16 +0530 Subject: [PATCH] ASoC: Intel: Skylake: Move platform specific init to platform dsp_init()
Move ipc_init() from helper function to respective platform's dsp_init() as ipc_init() per platform can be different.
Signed-off-by: Guneshwor Singh guneshwor.o.singh@intel.com Acked-By: Vinod Koul vinod.koul@intel.com Signed-off-by: Mark Brown broonie@kernel.org --- sound/soc/intel/skylake/bxt-sst.c | 4 ++++ sound/soc/intel/skylake/skl-sst-utils.c | 6 +----- sound/soc/intel/skylake/skl-sst.c | 4 ++++ 3 files changed, 9 insertions(+), 5 deletions(-)
diff --git a/sound/soc/intel/skylake/bxt-sst.c b/sound/soc/intel/skylake/bxt-sst.c index c404a42b670a..71042aceb25f 100644 --- a/sound/soc/intel/skylake/bxt-sst.c +++ b/sound/soc/intel/skylake/bxt-sst.c @@ -581,6 +581,10 @@ int bxt_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq, 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; + /* set the D0i3 check */ skl->ipc.ops.check_dsp_lp_on = skl_ipc_check_D0i0;
diff --git a/sound/soc/intel/skylake/skl-sst-utils.c b/sound/soc/intel/skylake/skl-sst-utils.c index 81ee251881b4..369ef7ce981c 100644 --- a/sound/soc/intel/skylake/skl-sst-utils.c +++ b/sound/soc/intel/skylake/skl-sst-utils.c @@ -368,7 +368,6 @@ int skl_sst_ctx_init(struct device *dev, int irq, const char *fw_name, { struct skl_sst *skl; struct sst_dsp *sst; - int ret;
skl = devm_kzalloc(dev, sizeof(*skl), GFP_KERNEL); if (skl == NULL) @@ -388,15 +387,12 @@ int skl_sst_ctx_init(struct device *dev, int irq, const char *fw_name, sst->dsp_ops = dsp_ops; init_waitqueue_head(&skl->mod_load_wait); INIT_LIST_HEAD(&sst->module_list); - ret = skl_ipc_init(dev, skl); - if (ret) - return ret;
skl->is_first_boot = true; if (dsp) *dsp = skl;
- return ret; + return 0; }
int skl_prepare_lib_load(struct skl_sst *skl, struct skl_lib_info *linfo, diff --git a/sound/soc/intel/skylake/skl-sst.c b/sound/soc/intel/skylake/skl-sst.c index fd99e74cda03..6cc586d3f03b 100644 --- a/sound/soc/intel/skylake/skl-sst.c +++ b/sound/soc/intel/skylake/skl-sst.c @@ -561,6 +561,10 @@ int skl_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq, sst_dsp_mailbox_init(sst, (SKL_ADSP_SRAM0_BASE + SKL_ADSP_W0_STAT_SZ), SKL_ADSP_W0_UP_SZ, SKL_ADSP_SRAM1_BASE, SKL_ADSP_W1_SZ);
+ ret = skl_ipc_init(dev, skl); + if (ret) + return ret; + sst->fw_ops = skl_fw_ops;
return 0;
Common ipc functions can be reused for cnl, so make them non-static.
Signed-off-by: Guneshwor Singh guneshwor.o.singh@intel.com --- sound/soc/intel/skylake/skl-sst-ipc.c | 6 +++--- sound/soc/intel/skylake/skl-sst-ipc.h | 6 ++++++ 2 files changed, 9 insertions(+), 3 deletions(-)
diff --git a/sound/soc/intel/skylake/skl-sst-ipc.c b/sound/soc/intel/skylake/skl-sst-ipc.c index 498b15345b1a..5234fafb758a 100644 --- a/sound/soc/intel/skylake/skl-sst-ipc.c +++ b/sound/soc/intel/skylake/skl-sst-ipc.c @@ -283,7 +283,7 @@ enum skl_ipc_module_msg { IPC_MOD_SET_D0IX = 8 };
-static void skl_ipc_tx_data_copy(struct ipc_message *msg, char *tx_data, +void skl_ipc_tx_data_copy(struct ipc_message *msg, char *tx_data, size_t tx_size) { if (tx_size) @@ -347,7 +347,7 @@ static struct ipc_message *skl_ipc_reply_get_msg(struct sst_generic_ipc *ipc,
}
-static int skl_ipc_process_notification(struct sst_generic_ipc *ipc, +int skl_ipc_process_notification(struct sst_generic_ipc *ipc, struct skl_ipc_header header) { struct skl_sst *skl = container_of(ipc, struct skl_sst, ipc); @@ -406,7 +406,7 @@ static int skl_ipc_set_reply_error_code(u32 reply) } }
-static void skl_ipc_process_reply(struct sst_generic_ipc *ipc, +void skl_ipc_process_reply(struct sst_generic_ipc *ipc, struct skl_ipc_header header) { struct ipc_message *msg; diff --git a/sound/soc/intel/skylake/skl-sst-ipc.h b/sound/soc/intel/skylake/skl-sst-ipc.h index e485e8f5ea2c..55f2d2ce09df 100644 --- a/sound/soc/intel/skylake/skl-sst-ipc.h +++ b/sound/soc/intel/skylake/skl-sst-ipc.h @@ -212,4 +212,10 @@ void skl_ipc_free(struct sst_generic_ipc *ipc); int skl_ipc_init(struct device *dev, struct skl_sst *skl); void skl_clear_module_cnt(struct sst_dsp *ctx);
+void skl_ipc_process_reply(struct sst_generic_ipc *ipc, + struct skl_ipc_header header); +int skl_ipc_process_notification(struct sst_generic_ipc *ipc, + struct skl_ipc_header header); +void skl_ipc_tx_data_copy(struct ipc_message *msg, char *tx_data, + size_t tx_size); #endif /* __SKL_IPC_H */
The patch
ASoC: Intel: cnl: Unstatify common ipc functions
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 4bdb04f0e1b7600b87a92b4f98ba5490ceffdf4f Mon Sep 17 00:00:00 2001
From: Guneshwor Singh guneshwor.o.singh@intel.com Date: Wed, 2 Aug 2017 21:51:17 +0530 Subject: [PATCH] ASoC: Intel: cnl: Unstatify common ipc functions
Common ipc functions can be reused for cnl, so make them non-static.
Signed-off-by: Guneshwor Singh guneshwor.o.singh@intel.com Acked-By: Vinod Koul vinod.koul@intel.com Signed-off-by: Mark Brown broonie@kernel.org --- sound/soc/intel/skylake/skl-sst-ipc.c | 6 +++--- sound/soc/intel/skylake/skl-sst-ipc.h | 6 ++++++ 2 files changed, 9 insertions(+), 3 deletions(-)
diff --git a/sound/soc/intel/skylake/skl-sst-ipc.c b/sound/soc/intel/skylake/skl-sst-ipc.c index 498b15345b1a..5234fafb758a 100644 --- a/sound/soc/intel/skylake/skl-sst-ipc.c +++ b/sound/soc/intel/skylake/skl-sst-ipc.c @@ -283,7 +283,7 @@ enum skl_ipc_module_msg { IPC_MOD_SET_D0IX = 8 };
-static void skl_ipc_tx_data_copy(struct ipc_message *msg, char *tx_data, +void skl_ipc_tx_data_copy(struct ipc_message *msg, char *tx_data, size_t tx_size) { if (tx_size) @@ -347,7 +347,7 @@ static struct ipc_message *skl_ipc_reply_get_msg(struct sst_generic_ipc *ipc,
}
-static int skl_ipc_process_notification(struct sst_generic_ipc *ipc, +int skl_ipc_process_notification(struct sst_generic_ipc *ipc, struct skl_ipc_header header) { struct skl_sst *skl = container_of(ipc, struct skl_sst, ipc); @@ -406,7 +406,7 @@ static int skl_ipc_set_reply_error_code(u32 reply) } }
-static void skl_ipc_process_reply(struct sst_generic_ipc *ipc, +void skl_ipc_process_reply(struct sst_generic_ipc *ipc, struct skl_ipc_header header) { struct ipc_message *msg; diff --git a/sound/soc/intel/skylake/skl-sst-ipc.h b/sound/soc/intel/skylake/skl-sst-ipc.h index e485e8f5ea2c..55f2d2ce09df 100644 --- a/sound/soc/intel/skylake/skl-sst-ipc.h +++ b/sound/soc/intel/skylake/skl-sst-ipc.h @@ -212,4 +212,10 @@ void skl_ipc_free(struct sst_generic_ipc *ipc); int skl_ipc_init(struct device *dev, struct skl_sst *skl); void skl_clear_module_cnt(struct sst_dsp *ctx);
+void skl_ipc_process_reply(struct sst_generic_ipc *ipc, + struct skl_ipc_header header); +int skl_ipc_process_notification(struct sst_generic_ipc *ipc, + struct skl_ipc_header header); +void skl_ipc_tx_data_copy(struct ipc_message *msg, char *tx_data, + size_t tx_size); #endif /* __SKL_IPC_H */
This adds the necessary DSP functions specific for the Cannonlake platform which includes firmware download using host DMA, DO/D3 handlers, irq_thread handlers and sst ops.
Signed-off-by: Guneshwor Singh guneshwor.o.singh@intel.com --- sound/soc/intel/skylake/Makefile | 5 +- sound/soc/intel/skylake/cnl-sst-dsp.h | 6 + sound/soc/intel/skylake/cnl-sst.c | 495 ++++++++++++++++++++++++++++++++++ 3 files changed, 504 insertions(+), 2 deletions(-) create mode 100644 sound/soc/intel/skylake/cnl-sst.c
diff --git a/sound/soc/intel/skylake/Makefile b/sound/soc/intel/skylake/Makefile index e7d77722d560..3380deb81015 100644 --- a/sound/soc/intel/skylake/Makefile +++ b/sound/soc/intel/skylake/Makefile @@ -8,7 +8,8 @@ endif 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 bxt-sst.o skl-sst-utils.o +snd-soc-skl-ipc-objs := skl-sst-ipc.o skl-sst-dsp.o cnl-sst-dsp.o \ + skl-sst-cldma.o skl-sst.o bxt-sst.o cnl-sst.o \ + skl-sst-utils.o
obj-$(CONFIG_SND_SOC_INTEL_SKYLAKE) += snd-soc-skl-ipc.o diff --git a/sound/soc/intel/skylake/cnl-sst-dsp.h b/sound/soc/intel/skylake/cnl-sst-dsp.h index 2fe41b137a2c..09bd218df5c4 100644 --- a/sound/soc/intel/skylake/cnl-sst-dsp.h +++ b/sound/soc/intel/skylake/cnl-sst-dsp.h @@ -103,4 +103,10 @@ void cnl_ipc_op_int_disable(struct sst_dsp *ctx); bool cnl_ipc_int_status(struct sst_dsp *ctx); void cnl_ipc_free(struct sst_generic_ipc *ipc);
+int cnl_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 cnl_sst_init_fw(struct device *dev, struct skl_sst *ctx); +void cnl_sst_dsp_cleanup(struct device *dev, struct skl_sst *ctx); + #endif /*__CNL_SST_DSP_H__*/ diff --git a/sound/soc/intel/skylake/cnl-sst.c b/sound/soc/intel/skylake/cnl-sst.c new file mode 100644 index 000000000000..7dcfe66a20e2 --- /dev/null +++ b/sound/soc/intel/skylake/cnl-sst.c @@ -0,0 +1,495 @@ +/* + * cnl-sst.c - DSP library functions for CNL platform + * + * Copyright (C) 2016-17, Intel Corporation. + * + * Author: Guneshwor Singh guneshwor.o.singh@intel.com + * + * Modified from: + * HDA DSP library functions for SKL platform + * Copyright (C) 2014-15, Intel Corporation. + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as version 2, as + * published by the Free Software Foundation. + * + * 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 "../common/sst-ipc.h" +#include "cnl-sst-dsp.h" +#include "skl-sst-dsp.h" +#include "skl-sst-ipc.h" + +#define CNL_FW_ROM_INIT 0x1 +#define CNL_FW_INIT 0x5 +#define CNL_IPC_PURGE 0x01004000 +#define CNL_INIT_TIMEOUT 300 +#define CNL_BASEFW_TIMEOUT 3000 + +#define CNL_ADSP_SRAM0_BASE 0x80000 + +/* Firmware status window */ +#define CNL_ADSP_FW_STATUS CNL_ADSP_SRAM0_BASE +#define CNL_ADSP_ERROR_CODE (CNL_ADSP_FW_STATUS + 0x4) + +#define CNL_INSTANCE_ID 0 +#define CNL_BASE_FW_MODULE_ID 0 +#define CNL_ADSP_FW_HDR_OFFSET 0x2000 +#define CNL_ROM_CTRL_DMA_ID 0x9 + +static int cnl_prepare_fw(struct sst_dsp *ctx, const void *fwdata, u32 fwsize) +{ + + int ret, stream_tag; + + stream_tag = ctx->dsp_ops.prepare(ctx->dev, 0x40, fwsize, &ctx->dmab); + if (stream_tag <= 0) { + dev_err(ctx->dev, "dma prepare failed: 0%#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, CNL_ADSP_REG_HIPCIDR, + CNL_ADSP_REG_HIPCIDR_BUSY | (CNL_IPC_PURGE | + ((stream_tag - 1) << CNL_ROM_CTRL_DMA_ID))); + + ret = cnl_dsp_enable_core(ctx, SKL_DSP_CORE0_MASK); + if (ret < 0) { + dev_err(ctx->dev, "dsp boot core failed ret: %d\n", ret); + ret = -EIO; + goto base_fw_load_failed; + } + + /* enable interrupt */ + cnl_ipc_int_enable(ctx); + cnl_ipc_op_int_enable(ctx); + + ret = sst_dsp_register_poll(ctx, CNL_ADSP_FW_STATUS, CNL_FW_STS_MASK, + CNL_FW_ROM_INIT, CNL_INIT_TIMEOUT, + "rom load"); + if (ret < 0) { + dev_err(ctx->dev, "rom init timeout, ret: %d\n", ret); + goto base_fw_load_failed; + } + + return 0; + +base_fw_load_failed: + ctx->dsp_ops.cleanup(ctx->dev, &ctx->dmab, stream_tag); + cnl_dsp_disable_core(ctx, SKL_DSP_CORE0_MASK); + + 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, CNL_ADSP_FW_STATUS, CNL_FW_STS_MASK, + CNL_FW_INIT, CNL_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 cnl_load_base_firmware(struct sst_dsp *ctx) +{ + struct firmware stripped_fw; + struct skl_sst *cnl = ctx->thread_context; + int ret; + + if (!ctx->fw) { + ret = request_firmware(&ctx->fw, ctx->fw_name, ctx->dev); + if (ret < 0) { + dev_err(ctx->dev, "request firmware failed: %d\n", ret); + goto cnl_load_base_firmware_failed; + } + } + + /* parse uuids if first boot */ + if (cnl->is_first_boot) { + ret = snd_skl_parse_uuids(ctx, ctx->fw, + CNL_ADSP_FW_HDR_OFFSET, 0); + if (ret < 0) + goto cnl_load_base_firmware_failed; + } + + stripped_fw.data = ctx->fw->data; + stripped_fw.size = ctx->fw->size; + skl_dsp_strip_extended_manifest(&stripped_fw); + + ret = cnl_prepare_fw(ctx, stripped_fw.data, stripped_fw.size); + if (ret < 0) { + dev_err(ctx->dev, "prepare firmware failed: %d\n", ret); + goto cnl_load_base_firmware_failed; + } + + ret = sst_transfer_fw_host_dma(ctx); + if (ret < 0) { + dev_err(ctx->dev, "transfer firmware failed: %d\n", ret); + cnl_dsp_disable_core(ctx, SKL_DSP_CORE0_MASK); + goto cnl_load_base_firmware_failed; + } + + ret = wait_event_timeout(cnl->boot_wait, cnl->boot_complete, + msecs_to_jiffies(SKL_IPC_BOOT_MSECS)); + if (ret == 0) { + dev_err(ctx->dev, "FW ready timed-out\n"); + cnl_dsp_disable_core(ctx, SKL_DSP_CORE0_MASK); + ret = -EIO; + goto cnl_load_base_firmware_failed; + } + + cnl->fw_loaded = true; + + return 0; + +cnl_load_base_firmware_failed: + release_firmware(ctx->fw); + ctx->fw = NULL; + + return ret; +} + +static int cnl_set_dsp_D0(struct sst_dsp *ctx, unsigned int core_id) +{ + struct skl_sst *cnl = ctx->thread_context; + unsigned int core_mask = SKL_DSP_CORE_MASK(core_id); + struct skl_ipc_dxstate_info dx; + int ret; + + if (!cnl->fw_loaded) { + cnl->boot_complete = false; + ret = cnl_load_base_firmware(ctx); + if (ret < 0) { + dev_err(ctx->dev, "fw reload failed: %d\n", ret); + return ret; + } + + cnl->cores.state[core_id] = SKL_DSP_RUNNING; + return ret; + } + + ret = cnl_dsp_enable_core(ctx, core_mask); + if (ret < 0) { + dev_err(ctx->dev, "enable dsp core %d failed: %d\n", + core_id, ret); + goto err; + } + + if (core_id == SKL_DSP_CORE0_ID) { + /* enable interrupt */ + cnl_ipc_int_enable(ctx); + cnl_ipc_op_int_enable(ctx); + cnl->boot_complete = false; + + ret = wait_event_timeout(cnl->boot_wait, cnl->boot_complete, + msecs_to_jiffies(SKL_IPC_BOOT_MSECS)); + if (ret == 0) { + dev_err(ctx->dev, + "dsp boot timeout, status=%#x error=%#x\n", + sst_dsp_shim_read(ctx, CNL_ADSP_FW_STATUS), + sst_dsp_shim_read(ctx, CNL_ADSP_ERROR_CODE)); + goto err; + } + } else { + dx.core_mask = core_mask; + dx.dx_mask = core_mask; + + ret = skl_ipc_set_dx(&cnl->ipc, CNL_INSTANCE_ID, + CNL_BASE_FW_MODULE_ID, &dx); + if (ret < 0) { + dev_err(ctx->dev, "set_dx failed, core: %d ret: %d\n", + core_id, ret); + goto err; + } + } + cnl->cores.state[core_id] = SKL_DSP_RUNNING; + + return 0; +err: + cnl_dsp_disable_core(ctx, core_mask); + + return ret; +} + +static int cnl_set_dsp_D3(struct sst_dsp *ctx, unsigned int core_id) +{ + struct skl_sst *cnl = ctx->thread_context; + unsigned int core_mask = SKL_DSP_CORE_MASK(core_id); + struct skl_ipc_dxstate_info dx; + int ret; + + dx.core_mask = core_mask; + dx.dx_mask = SKL_IPC_D3_MASK; + + ret = skl_ipc_set_dx(&cnl->ipc, CNL_INSTANCE_ID, + CNL_BASE_FW_MODULE_ID, &dx); + if (ret < 0) { + dev_err(ctx->dev, + "dsp core %d to d3 failed; continue reset\n", + core_id); + cnl->fw_loaded = false; + } + + /* disable interrupts if core 0 */ + if (core_id == SKL_DSP_CORE0_ID) { + skl_ipc_op_int_disable(ctx); + skl_ipc_int_disable(ctx); + } + + ret = cnl_dsp_disable_core(ctx, core_mask); + if (ret < 0) { + dev_err(ctx->dev, "disable dsp core %d failed: %d\n", + core_id, ret); + return ret; + } + + cnl->cores.state[core_id] = SKL_DSP_RESET; + + return ret; +} + +static unsigned int cnl_get_errno(struct sst_dsp *ctx) +{ + return sst_dsp_shim_read(ctx, CNL_ADSP_ERROR_CODE); +} + +static struct skl_dsp_fw_ops cnl_fw_ops = { + .set_state_D0 = cnl_set_dsp_D0, + .set_state_D3 = cnl_set_dsp_D3, + .load_fw = cnl_load_base_firmware, + .get_fw_errcode = cnl_get_errno, +}; + +static struct sst_ops cnl_ops = { + .irq_handler = cnl_dsp_sst_interrupt, + .write = sst_shim32_write, + .read = sst_shim32_read, + .ram_read = sst_memcpy_fromio_32, + .ram_write = sst_memcpy_toio_32, + .free = cnl_dsp_free, +}; + +#define CNL_IPC_GLB_NOTIFY_RSP_SHIFT 29 +#define CNL_IPC_GLB_NOTIFY_RSP_MASK 0x1 +#define CNL_IPC_GLB_NOTIFY_RSP_TYPE(x) (((x) >> CNL_IPC_GLB_NOTIFY_RSP_SHIFT) \ + & CNL_IPC_GLB_NOTIFY_RSP_MASK) + +static irqreturn_t cnl_dsp_irq_thread_handler(int irq, void *context) +{ + struct sst_dsp *dsp = context; + struct skl_sst *cnl = sst_dsp_get_thread_context(dsp); + struct sst_generic_ipc *ipc = &cnl->ipc; + struct skl_ipc_header header = {0}; + u32 hipcida, hipctdr, hipctdd; + int ipc_irq = 0; + + /* here we handle ipc interrupts only */ + if (!(dsp->intr_status & CNL_ADSPIS_IPC)) + return IRQ_NONE; + + hipcida = sst_dsp_shim_read_unlocked(dsp, CNL_ADSP_REG_HIPCIDA); + hipctdr = sst_dsp_shim_read_unlocked(dsp, CNL_ADSP_REG_HIPCTDR); + + /* reply message from dsp */ + if (hipcida & CNL_ADSP_REG_HIPCIDA_DONE) { + sst_dsp_shim_update_bits(dsp, CNL_ADSP_REG_HIPCCTL, + CNL_ADSP_REG_HIPCCTL_DONE, 0); + + /* clear done bit - tell dsp operation is complete */ + sst_dsp_shim_update_bits_forced(dsp, CNL_ADSP_REG_HIPCIDA, + CNL_ADSP_REG_HIPCIDA_DONE, CNL_ADSP_REG_HIPCIDA_DONE); + + ipc_irq = 1; + + /* unmask done interrupt */ + sst_dsp_shim_update_bits(dsp, CNL_ADSP_REG_HIPCCTL, + CNL_ADSP_REG_HIPCCTL_DONE, CNL_ADSP_REG_HIPCCTL_DONE); + } + + /* new message from dsp */ + if (hipctdr & CNL_ADSP_REG_HIPCTDR_BUSY) { + hipctdd = sst_dsp_shim_read_unlocked(dsp, CNL_ADSP_REG_HIPCTDD); + header.primary = hipctdr; + header.extension = hipctdd; + dev_dbg(dsp->dev, "IPC irq: Firmware respond primary:%x", + header.primary); + dev_dbg(dsp->dev, "IPC irq: Firmware respond extension:%x", + header.extension); + + if (CNL_IPC_GLB_NOTIFY_RSP_TYPE(header.primary)) { + /* Handle Immediate reply from DSP Core */ + skl_ipc_process_reply(ipc, header); + } else { + dev_dbg(dsp->dev, "IPC irq: Notification from firmware\n"); + skl_ipc_process_notification(ipc, header); + } + /* clear busy interrupt */ + sst_dsp_shim_update_bits_forced(dsp, CNL_ADSP_REG_HIPCTDR, + CNL_ADSP_REG_HIPCTDR_BUSY, CNL_ADSP_REG_HIPCTDR_BUSY); + + /* set done bit to ack dsp */ + sst_dsp_shim_update_bits_forced(dsp, CNL_ADSP_REG_HIPCTDA, + CNL_ADSP_REG_HIPCTDA_DONE, CNL_ADSP_REG_HIPCTDA_DONE); + ipc_irq = 1; + } + + if (ipc_irq == 0) + return IRQ_NONE; + + cnl_ipc_int_enable(dsp); + + /* continue to send any remaining messages */ + schedule_work(&ipc->kwork); + + return IRQ_HANDLED; +} + +static struct sst_dsp_device cnl_dev = { + .thread = cnl_dsp_irq_thread_handler, + .ops = &cnl_ops, +}; + +static void cnl_ipc_tx_msg(struct sst_generic_ipc *ipc, struct ipc_message *msg) +{ + struct skl_ipc_header *header = (struct skl_ipc_header *)(&msg->header); + + if (msg->tx_size) + sst_dsp_outbox_write(ipc->dsp, msg->tx_data, msg->tx_size); + sst_dsp_shim_write_unlocked(ipc->dsp, CNL_ADSP_REG_HIPCIDD, + header->extension); + sst_dsp_shim_write_unlocked(ipc->dsp, CNL_ADSP_REG_HIPCIDR, + header->primary | CNL_ADSP_REG_HIPCIDR_BUSY); +} + +static bool cnl_ipc_is_dsp_busy(struct sst_dsp *dsp) +{ + u32 hipcidr; + + hipcidr = sst_dsp_shim_read_unlocked(dsp, CNL_ADSP_REG_HIPCIDR); + + return (hipcidr & CNL_ADSP_REG_HIPCIDR_BUSY); +} + +static int cnl_ipc_init(struct device *dev, struct skl_sst *cnl) +{ + struct sst_generic_ipc *ipc; + int err; + + ipc = &cnl->ipc; + ipc->dsp = cnl->dsp; + ipc->dev = dev; + + ipc->tx_data_max_size = CNL_ADSP_W1_SZ; + ipc->rx_data_max_size = CNL_ADSP_W0_UP_SZ; + + err = sst_ipc_init(ipc); + if (err) + return err; + + /* + * overriding tx_msg and is_dsp_busy since + * ipc registers are different for cnl + */ + ipc->ops.tx_msg = cnl_ipc_tx_msg; + ipc->ops.tx_data_copy = skl_ipc_tx_data_copy; + ipc->ops.is_dsp_busy = cnl_ipc_is_dsp_busy; + + return 0; +} + +int cnl_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 *cnl; + struct sst_dsp *sst; + int ret; + + ret = skl_sst_ctx_init(dev, irq, fw_name, dsp_ops, dsp, &cnl_dev); + if (ret < 0) { + dev_err(dev, "%s: no device\n", __func__); + return ret; + } + + cnl = *dsp; + sst = cnl->dsp; + sst->fw_ops = cnl_fw_ops; + sst->addr.lpe = mmio_base; + sst->addr.shim = mmio_base; + sst->addr.sram0_base = CNL_ADSP_SRAM0_BASE; + sst->addr.sram1_base = CNL_ADSP_SRAM1_BASE; + sst->addr.w0_stat_sz = CNL_ADSP_W0_STAT_SZ; + sst->addr.w0_up_sz = CNL_ADSP_W0_UP_SZ; + + sst_dsp_mailbox_init(sst, (CNL_ADSP_SRAM0_BASE + CNL_ADSP_W0_STAT_SZ), + CNL_ADSP_W0_UP_SZ, CNL_ADSP_SRAM1_BASE, + CNL_ADSP_W1_SZ); + + ret = cnl_ipc_init(dev, cnl); + if (ret) + return ret; + + cnl->boot_complete = false; + init_waitqueue_head(&cnl->boot_wait); + + return 0; +} +EXPORT_SYMBOL_GPL(cnl_sst_dsp_init); + +int cnl_sst_init_fw(struct device *dev, struct skl_sst *ctx) +{ + int ret; + struct sst_dsp *sst = ctx->dsp; + + ret = ctx->dsp->fw_ops.load_fw(sst); + if (ret < 0) { + dev_err(dev, "load base fw failed: %d", ret); + return ret; + } + + skl_dsp_init_core_state(sst); + + ctx->is_first_boot = false; + + return 0; +} +EXPORT_SYMBOL_GPL(cnl_sst_init_fw); + +void cnl_sst_dsp_cleanup(struct device *dev, struct skl_sst *ctx) +{ + if (ctx->dsp->fw) + release_firmware(ctx->dsp->fw); + + skl_freeup_uuid_list(ctx); + cnl_ipc_free(&ctx->ipc); + + ctx->dsp->ops->free(ctx->dsp); +} +EXPORT_SYMBOL_GPL(cnl_sst_dsp_cleanup); + +MODULE_LICENSE("GPL v2"); +MODULE_DESCRIPTION("Intel Cannonlake IPC driver");
The patch
ASoC: Intel: cnl: Add sst library functions for cnl platform
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 cb6a552846297094aac942a588fe7ed7922a6c11 Mon Sep 17 00:00:00 2001
From: Guneshwor Singh guneshwor.o.singh@intel.com Date: Wed, 2 Aug 2017 21:51:18 +0530 Subject: [PATCH] ASoC: Intel: cnl: Add sst library functions for cnl platform
This adds the necessary DSP functions specific for the Cannonlake platform which includes firmware download using host DMA, DO/D3 handlers, irq_thread handlers and sst ops.
Signed-off-by: Guneshwor Singh guneshwor.o.singh@intel.com Acked-By: Vinod Koul vinod.koul@intel.com Signed-off-by: Mark Brown broonie@kernel.org --- sound/soc/intel/skylake/Makefile | 5 +- sound/soc/intel/skylake/cnl-sst-dsp.h | 6 + sound/soc/intel/skylake/cnl-sst.c | 495 ++++++++++++++++++++++++++++++++++ 3 files changed, 504 insertions(+), 2 deletions(-) create mode 100644 sound/soc/intel/skylake/cnl-sst.c
diff --git a/sound/soc/intel/skylake/Makefile b/sound/soc/intel/skylake/Makefile index e7d77722d560..3380deb81015 100644 --- a/sound/soc/intel/skylake/Makefile +++ b/sound/soc/intel/skylake/Makefile @@ -8,7 +8,8 @@ endif 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 bxt-sst.o skl-sst-utils.o +snd-soc-skl-ipc-objs := skl-sst-ipc.o skl-sst-dsp.o cnl-sst-dsp.o \ + skl-sst-cldma.o skl-sst.o bxt-sst.o cnl-sst.o \ + skl-sst-utils.o
obj-$(CONFIG_SND_SOC_INTEL_SKYLAKE) += snd-soc-skl-ipc.o diff --git a/sound/soc/intel/skylake/cnl-sst-dsp.h b/sound/soc/intel/skylake/cnl-sst-dsp.h index 2fe41b137a2c..09bd218df5c4 100644 --- a/sound/soc/intel/skylake/cnl-sst-dsp.h +++ b/sound/soc/intel/skylake/cnl-sst-dsp.h @@ -103,4 +103,10 @@ void cnl_ipc_op_int_disable(struct sst_dsp *ctx); bool cnl_ipc_int_status(struct sst_dsp *ctx); void cnl_ipc_free(struct sst_generic_ipc *ipc);
+int cnl_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 cnl_sst_init_fw(struct device *dev, struct skl_sst *ctx); +void cnl_sst_dsp_cleanup(struct device *dev, struct skl_sst *ctx); + #endif /*__CNL_SST_DSP_H__*/ diff --git a/sound/soc/intel/skylake/cnl-sst.c b/sound/soc/intel/skylake/cnl-sst.c new file mode 100644 index 000000000000..7dcfe66a20e2 --- /dev/null +++ b/sound/soc/intel/skylake/cnl-sst.c @@ -0,0 +1,495 @@ +/* + * cnl-sst.c - DSP library functions for CNL platform + * + * Copyright (C) 2016-17, Intel Corporation. + * + * Author: Guneshwor Singh guneshwor.o.singh@intel.com + * + * Modified from: + * HDA DSP library functions for SKL platform + * Copyright (C) 2014-15, Intel Corporation. + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as version 2, as + * published by the Free Software Foundation. + * + * 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 "../common/sst-ipc.h" +#include "cnl-sst-dsp.h" +#include "skl-sst-dsp.h" +#include "skl-sst-ipc.h" + +#define CNL_FW_ROM_INIT 0x1 +#define CNL_FW_INIT 0x5 +#define CNL_IPC_PURGE 0x01004000 +#define CNL_INIT_TIMEOUT 300 +#define CNL_BASEFW_TIMEOUT 3000 + +#define CNL_ADSP_SRAM0_BASE 0x80000 + +/* Firmware status window */ +#define CNL_ADSP_FW_STATUS CNL_ADSP_SRAM0_BASE +#define CNL_ADSP_ERROR_CODE (CNL_ADSP_FW_STATUS + 0x4) + +#define CNL_INSTANCE_ID 0 +#define CNL_BASE_FW_MODULE_ID 0 +#define CNL_ADSP_FW_HDR_OFFSET 0x2000 +#define CNL_ROM_CTRL_DMA_ID 0x9 + +static int cnl_prepare_fw(struct sst_dsp *ctx, const void *fwdata, u32 fwsize) +{ + + int ret, stream_tag; + + stream_tag = ctx->dsp_ops.prepare(ctx->dev, 0x40, fwsize, &ctx->dmab); + if (stream_tag <= 0) { + dev_err(ctx->dev, "dma prepare failed: 0%#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, CNL_ADSP_REG_HIPCIDR, + CNL_ADSP_REG_HIPCIDR_BUSY | (CNL_IPC_PURGE | + ((stream_tag - 1) << CNL_ROM_CTRL_DMA_ID))); + + ret = cnl_dsp_enable_core(ctx, SKL_DSP_CORE0_MASK); + if (ret < 0) { + dev_err(ctx->dev, "dsp boot core failed ret: %d\n", ret); + ret = -EIO; + goto base_fw_load_failed; + } + + /* enable interrupt */ + cnl_ipc_int_enable(ctx); + cnl_ipc_op_int_enable(ctx); + + ret = sst_dsp_register_poll(ctx, CNL_ADSP_FW_STATUS, CNL_FW_STS_MASK, + CNL_FW_ROM_INIT, CNL_INIT_TIMEOUT, + "rom load"); + if (ret < 0) { + dev_err(ctx->dev, "rom init timeout, ret: %d\n", ret); + goto base_fw_load_failed; + } + + return 0; + +base_fw_load_failed: + ctx->dsp_ops.cleanup(ctx->dev, &ctx->dmab, stream_tag); + cnl_dsp_disable_core(ctx, SKL_DSP_CORE0_MASK); + + 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, CNL_ADSP_FW_STATUS, CNL_FW_STS_MASK, + CNL_FW_INIT, CNL_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 cnl_load_base_firmware(struct sst_dsp *ctx) +{ + struct firmware stripped_fw; + struct skl_sst *cnl = ctx->thread_context; + int ret; + + if (!ctx->fw) { + ret = request_firmware(&ctx->fw, ctx->fw_name, ctx->dev); + if (ret < 0) { + dev_err(ctx->dev, "request firmware failed: %d\n", ret); + goto cnl_load_base_firmware_failed; + } + } + + /* parse uuids if first boot */ + if (cnl->is_first_boot) { + ret = snd_skl_parse_uuids(ctx, ctx->fw, + CNL_ADSP_FW_HDR_OFFSET, 0); + if (ret < 0) + goto cnl_load_base_firmware_failed; + } + + stripped_fw.data = ctx->fw->data; + stripped_fw.size = ctx->fw->size; + skl_dsp_strip_extended_manifest(&stripped_fw); + + ret = cnl_prepare_fw(ctx, stripped_fw.data, stripped_fw.size); + if (ret < 0) { + dev_err(ctx->dev, "prepare firmware failed: %d\n", ret); + goto cnl_load_base_firmware_failed; + } + + ret = sst_transfer_fw_host_dma(ctx); + if (ret < 0) { + dev_err(ctx->dev, "transfer firmware failed: %d\n", ret); + cnl_dsp_disable_core(ctx, SKL_DSP_CORE0_MASK); + goto cnl_load_base_firmware_failed; + } + + ret = wait_event_timeout(cnl->boot_wait, cnl->boot_complete, + msecs_to_jiffies(SKL_IPC_BOOT_MSECS)); + if (ret == 0) { + dev_err(ctx->dev, "FW ready timed-out\n"); + cnl_dsp_disable_core(ctx, SKL_DSP_CORE0_MASK); + ret = -EIO; + goto cnl_load_base_firmware_failed; + } + + cnl->fw_loaded = true; + + return 0; + +cnl_load_base_firmware_failed: + release_firmware(ctx->fw); + ctx->fw = NULL; + + return ret; +} + +static int cnl_set_dsp_D0(struct sst_dsp *ctx, unsigned int core_id) +{ + struct skl_sst *cnl = ctx->thread_context; + unsigned int core_mask = SKL_DSP_CORE_MASK(core_id); + struct skl_ipc_dxstate_info dx; + int ret; + + if (!cnl->fw_loaded) { + cnl->boot_complete = false; + ret = cnl_load_base_firmware(ctx); + if (ret < 0) { + dev_err(ctx->dev, "fw reload failed: %d\n", ret); + return ret; + } + + cnl->cores.state[core_id] = SKL_DSP_RUNNING; + return ret; + } + + ret = cnl_dsp_enable_core(ctx, core_mask); + if (ret < 0) { + dev_err(ctx->dev, "enable dsp core %d failed: %d\n", + core_id, ret); + goto err; + } + + if (core_id == SKL_DSP_CORE0_ID) { + /* enable interrupt */ + cnl_ipc_int_enable(ctx); + cnl_ipc_op_int_enable(ctx); + cnl->boot_complete = false; + + ret = wait_event_timeout(cnl->boot_wait, cnl->boot_complete, + msecs_to_jiffies(SKL_IPC_BOOT_MSECS)); + if (ret == 0) { + dev_err(ctx->dev, + "dsp boot timeout, status=%#x error=%#x\n", + sst_dsp_shim_read(ctx, CNL_ADSP_FW_STATUS), + sst_dsp_shim_read(ctx, CNL_ADSP_ERROR_CODE)); + goto err; + } + } else { + dx.core_mask = core_mask; + dx.dx_mask = core_mask; + + ret = skl_ipc_set_dx(&cnl->ipc, CNL_INSTANCE_ID, + CNL_BASE_FW_MODULE_ID, &dx); + if (ret < 0) { + dev_err(ctx->dev, "set_dx failed, core: %d ret: %d\n", + core_id, ret); + goto err; + } + } + cnl->cores.state[core_id] = SKL_DSP_RUNNING; + + return 0; +err: + cnl_dsp_disable_core(ctx, core_mask); + + return ret; +} + +static int cnl_set_dsp_D3(struct sst_dsp *ctx, unsigned int core_id) +{ + struct skl_sst *cnl = ctx->thread_context; + unsigned int core_mask = SKL_DSP_CORE_MASK(core_id); + struct skl_ipc_dxstate_info dx; + int ret; + + dx.core_mask = core_mask; + dx.dx_mask = SKL_IPC_D3_MASK; + + ret = skl_ipc_set_dx(&cnl->ipc, CNL_INSTANCE_ID, + CNL_BASE_FW_MODULE_ID, &dx); + if (ret < 0) { + dev_err(ctx->dev, + "dsp core %d to d3 failed; continue reset\n", + core_id); + cnl->fw_loaded = false; + } + + /* disable interrupts if core 0 */ + if (core_id == SKL_DSP_CORE0_ID) { + skl_ipc_op_int_disable(ctx); + skl_ipc_int_disable(ctx); + } + + ret = cnl_dsp_disable_core(ctx, core_mask); + if (ret < 0) { + dev_err(ctx->dev, "disable dsp core %d failed: %d\n", + core_id, ret); + return ret; + } + + cnl->cores.state[core_id] = SKL_DSP_RESET; + + return ret; +} + +static unsigned int cnl_get_errno(struct sst_dsp *ctx) +{ + return sst_dsp_shim_read(ctx, CNL_ADSP_ERROR_CODE); +} + +static struct skl_dsp_fw_ops cnl_fw_ops = { + .set_state_D0 = cnl_set_dsp_D0, + .set_state_D3 = cnl_set_dsp_D3, + .load_fw = cnl_load_base_firmware, + .get_fw_errcode = cnl_get_errno, +}; + +static struct sst_ops cnl_ops = { + .irq_handler = cnl_dsp_sst_interrupt, + .write = sst_shim32_write, + .read = sst_shim32_read, + .ram_read = sst_memcpy_fromio_32, + .ram_write = sst_memcpy_toio_32, + .free = cnl_dsp_free, +}; + +#define CNL_IPC_GLB_NOTIFY_RSP_SHIFT 29 +#define CNL_IPC_GLB_NOTIFY_RSP_MASK 0x1 +#define CNL_IPC_GLB_NOTIFY_RSP_TYPE(x) (((x) >> CNL_IPC_GLB_NOTIFY_RSP_SHIFT) \ + & CNL_IPC_GLB_NOTIFY_RSP_MASK) + +static irqreturn_t cnl_dsp_irq_thread_handler(int irq, void *context) +{ + struct sst_dsp *dsp = context; + struct skl_sst *cnl = sst_dsp_get_thread_context(dsp); + struct sst_generic_ipc *ipc = &cnl->ipc; + struct skl_ipc_header header = {0}; + u32 hipcida, hipctdr, hipctdd; + int ipc_irq = 0; + + /* here we handle ipc interrupts only */ + if (!(dsp->intr_status & CNL_ADSPIS_IPC)) + return IRQ_NONE; + + hipcida = sst_dsp_shim_read_unlocked(dsp, CNL_ADSP_REG_HIPCIDA); + hipctdr = sst_dsp_shim_read_unlocked(dsp, CNL_ADSP_REG_HIPCTDR); + + /* reply message from dsp */ + if (hipcida & CNL_ADSP_REG_HIPCIDA_DONE) { + sst_dsp_shim_update_bits(dsp, CNL_ADSP_REG_HIPCCTL, + CNL_ADSP_REG_HIPCCTL_DONE, 0); + + /* clear done bit - tell dsp operation is complete */ + sst_dsp_shim_update_bits_forced(dsp, CNL_ADSP_REG_HIPCIDA, + CNL_ADSP_REG_HIPCIDA_DONE, CNL_ADSP_REG_HIPCIDA_DONE); + + ipc_irq = 1; + + /* unmask done interrupt */ + sst_dsp_shim_update_bits(dsp, CNL_ADSP_REG_HIPCCTL, + CNL_ADSP_REG_HIPCCTL_DONE, CNL_ADSP_REG_HIPCCTL_DONE); + } + + /* new message from dsp */ + if (hipctdr & CNL_ADSP_REG_HIPCTDR_BUSY) { + hipctdd = sst_dsp_shim_read_unlocked(dsp, CNL_ADSP_REG_HIPCTDD); + header.primary = hipctdr; + header.extension = hipctdd; + dev_dbg(dsp->dev, "IPC irq: Firmware respond primary:%x", + header.primary); + dev_dbg(dsp->dev, "IPC irq: Firmware respond extension:%x", + header.extension); + + if (CNL_IPC_GLB_NOTIFY_RSP_TYPE(header.primary)) { + /* Handle Immediate reply from DSP Core */ + skl_ipc_process_reply(ipc, header); + } else { + dev_dbg(dsp->dev, "IPC irq: Notification from firmware\n"); + skl_ipc_process_notification(ipc, header); + } + /* clear busy interrupt */ + sst_dsp_shim_update_bits_forced(dsp, CNL_ADSP_REG_HIPCTDR, + CNL_ADSP_REG_HIPCTDR_BUSY, CNL_ADSP_REG_HIPCTDR_BUSY); + + /* set done bit to ack dsp */ + sst_dsp_shim_update_bits_forced(dsp, CNL_ADSP_REG_HIPCTDA, + CNL_ADSP_REG_HIPCTDA_DONE, CNL_ADSP_REG_HIPCTDA_DONE); + ipc_irq = 1; + } + + if (ipc_irq == 0) + return IRQ_NONE; + + cnl_ipc_int_enable(dsp); + + /* continue to send any remaining messages */ + schedule_work(&ipc->kwork); + + return IRQ_HANDLED; +} + +static struct sst_dsp_device cnl_dev = { + .thread = cnl_dsp_irq_thread_handler, + .ops = &cnl_ops, +}; + +static void cnl_ipc_tx_msg(struct sst_generic_ipc *ipc, struct ipc_message *msg) +{ + struct skl_ipc_header *header = (struct skl_ipc_header *)(&msg->header); + + if (msg->tx_size) + sst_dsp_outbox_write(ipc->dsp, msg->tx_data, msg->tx_size); + sst_dsp_shim_write_unlocked(ipc->dsp, CNL_ADSP_REG_HIPCIDD, + header->extension); + sst_dsp_shim_write_unlocked(ipc->dsp, CNL_ADSP_REG_HIPCIDR, + header->primary | CNL_ADSP_REG_HIPCIDR_BUSY); +} + +static bool cnl_ipc_is_dsp_busy(struct sst_dsp *dsp) +{ + u32 hipcidr; + + hipcidr = sst_dsp_shim_read_unlocked(dsp, CNL_ADSP_REG_HIPCIDR); + + return (hipcidr & CNL_ADSP_REG_HIPCIDR_BUSY); +} + +static int cnl_ipc_init(struct device *dev, struct skl_sst *cnl) +{ + struct sst_generic_ipc *ipc; + int err; + + ipc = &cnl->ipc; + ipc->dsp = cnl->dsp; + ipc->dev = dev; + + ipc->tx_data_max_size = CNL_ADSP_W1_SZ; + ipc->rx_data_max_size = CNL_ADSP_W0_UP_SZ; + + err = sst_ipc_init(ipc); + if (err) + return err; + + /* + * overriding tx_msg and is_dsp_busy since + * ipc registers are different for cnl + */ + ipc->ops.tx_msg = cnl_ipc_tx_msg; + ipc->ops.tx_data_copy = skl_ipc_tx_data_copy; + ipc->ops.is_dsp_busy = cnl_ipc_is_dsp_busy; + + return 0; +} + +int cnl_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 *cnl; + struct sst_dsp *sst; + int ret; + + ret = skl_sst_ctx_init(dev, irq, fw_name, dsp_ops, dsp, &cnl_dev); + if (ret < 0) { + dev_err(dev, "%s: no device\n", __func__); + return ret; + } + + cnl = *dsp; + sst = cnl->dsp; + sst->fw_ops = cnl_fw_ops; + sst->addr.lpe = mmio_base; + sst->addr.shim = mmio_base; + sst->addr.sram0_base = CNL_ADSP_SRAM0_BASE; + sst->addr.sram1_base = CNL_ADSP_SRAM1_BASE; + sst->addr.w0_stat_sz = CNL_ADSP_W0_STAT_SZ; + sst->addr.w0_up_sz = CNL_ADSP_W0_UP_SZ; + + sst_dsp_mailbox_init(sst, (CNL_ADSP_SRAM0_BASE + CNL_ADSP_W0_STAT_SZ), + CNL_ADSP_W0_UP_SZ, CNL_ADSP_SRAM1_BASE, + CNL_ADSP_W1_SZ); + + ret = cnl_ipc_init(dev, cnl); + if (ret) + return ret; + + cnl->boot_complete = false; + init_waitqueue_head(&cnl->boot_wait); + + return 0; +} +EXPORT_SYMBOL_GPL(cnl_sst_dsp_init); + +int cnl_sst_init_fw(struct device *dev, struct skl_sst *ctx) +{ + int ret; + struct sst_dsp *sst = ctx->dsp; + + ret = ctx->dsp->fw_ops.load_fw(sst); + if (ret < 0) { + dev_err(dev, "load base fw failed: %d", ret); + return ret; + } + + skl_dsp_init_core_state(sst); + + ctx->is_first_boot = false; + + return 0; +} +EXPORT_SYMBOL_GPL(cnl_sst_init_fw); + +void cnl_sst_dsp_cleanup(struct device *dev, struct skl_sst *ctx) +{ + if (ctx->dsp->fw) + release_firmware(ctx->dsp->fw); + + skl_freeup_uuid_list(ctx); + cnl_ipc_free(&ctx->ipc); + + ctx->dsp->ops->free(ctx->dsp); +} +EXPORT_SYMBOL_GPL(cnl_sst_dsp_cleanup); + +MODULE_LICENSE("GPL v2"); +MODULE_DESCRIPTION("Intel Cannonlake IPC driver");
Add cannonlake dsp support by adding its dsp_ops.
Signed-off-by: Guneshwor Singh guneshwor.o.singh@intel.com --- sound/soc/intel/skylake/skl-messages.c | 9 +++++++++ 1 file changed, 9 insertions(+)
diff --git a/sound/soc/intel/skylake/skl-messages.c b/sound/soc/intel/skylake/skl-messages.c index c6b60ee5b196..bfb3332a77ca 100644 --- a/sound/soc/intel/skylake/skl-messages.c +++ b/sound/soc/intel/skylake/skl-messages.c @@ -22,6 +22,7 @@ #include <sound/core.h> #include <sound/pcm.h> #include "skl-sst-dsp.h" +#include "cnl-sst-dsp.h" #include "skl-sst-ipc.h" #include "skl.h" #include "../common/sst-dsp.h" @@ -231,6 +232,14 @@ static const struct skl_dsp_ops dsp_ops[] = { .init_fw = bxt_sst_init_fw, .cleanup = bxt_sst_dsp_cleanup }, + { + .id = 0x9dc8, + .num_cores = 4, + .loader_ops = bxt_get_loader_ops, + .init = cnl_sst_dsp_init, + .init_fw = cnl_sst_init_fw, + .cleanup = cnl_sst_dsp_cleanup + }, };
const struct skl_dsp_ops *skl_get_dsp_ops(int pci_id)
The patch
ASoC: Intel: cnl: add dsp ops for cannonlake
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 b003a345dc67c7a1c468ad8ff10b24d7dd12e12c Mon Sep 17 00:00:00 2001
From: Guneshwor Singh guneshwor.o.singh@intel.com Date: Wed, 2 Aug 2017 21:51:19 +0530 Subject: [PATCH] ASoC: Intel: cnl: add dsp ops for cannonlake
Add cannonlake dsp support by adding its dsp_ops.
Signed-off-by: Guneshwor Singh guneshwor.o.singh@intel.com Acked-By: Vinod Koul vinod.koul@intel.com Signed-off-by: Mark Brown broonie@kernel.org --- sound/soc/intel/skylake/skl-messages.c | 9 +++++++++ 1 file changed, 9 insertions(+)
diff --git a/sound/soc/intel/skylake/skl-messages.c b/sound/soc/intel/skylake/skl-messages.c index c6b60ee5b196..bfb3332a77ca 100644 --- a/sound/soc/intel/skylake/skl-messages.c +++ b/sound/soc/intel/skylake/skl-messages.c @@ -22,6 +22,7 @@ #include <sound/core.h> #include <sound/pcm.h> #include "skl-sst-dsp.h" +#include "cnl-sst-dsp.h" #include "skl-sst-ipc.h" #include "skl.h" #include "../common/sst-dsp.h" @@ -231,6 +232,14 @@ static const struct skl_dsp_ops dsp_ops[] = { .init_fw = bxt_sst_init_fw, .cleanup = bxt_sst_dsp_cleanup }, + { + .id = 0x9dc8, + .num_cores = 4, + .loader_ops = bxt_get_loader_ops, + .init = cnl_sst_dsp_init, + .init_fw = cnl_sst_init_fw, + .cleanup = cnl_sst_dsp_cleanup + }, };
const struct skl_dsp_ops *skl_get_dsp_ops(int pci_id)
Enable cnl by adding its pci id in skl_ids[].
Signed-off-by: Guneshwor Singh guneshwor.o.singh@intel.com --- sound/soc/intel/skylake/skl.c | 11 +++++++++++ 1 file changed, 11 insertions(+)
diff --git a/sound/soc/intel/skylake/skl.c b/sound/soc/intel/skylake/skl.c index ab651517e8b8..e612a4097275 100644 --- a/sound/soc/intel/skylake/skl.c +++ b/sound/soc/intel/skylake/skl.c @@ -996,6 +996,14 @@ static struct sst_acpi_mach sst_glk_devdata[] = { }, };
+static const struct sst_acpi_mach sst_cnl_devdata[] = { + { + .id = "INT34C2", + .drv_name = "cnl_rt274", + .fw_filename = "intel/dsp_fw_cnl.bin", + }, +}; + /* PCI IDs */ static const struct pci_device_id skl_ids[] = { /* Sunrise Point-LP */ @@ -1010,6 +1018,9 @@ static const struct pci_device_id skl_ids[] = { /* GLK */ { PCI_DEVICE(0x8086, 0x3198), .driver_data = (unsigned long)&sst_glk_devdata}, + /* CNL */ + { PCI_DEVICE(0x8086, 0x9dc8), + .driver_data = (unsigned long)&sst_cnl_devdata}, { 0, } }; MODULE_DEVICE_TABLE(pci, skl_ids);
The patch
ASoC: Intel: cnl: add pci id for cnl
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 86d7ce3dd717e09a442d35dae3f9c62c03e024d8 Mon Sep 17 00:00:00 2001
From: Guneshwor Singh guneshwor.o.singh@intel.com Date: Wed, 2 Aug 2017 21:51:20 +0530 Subject: [PATCH] ASoC: Intel: cnl: add pci id for cnl
Enable cnl by adding its pci id in skl_ids[].
Signed-off-by: Guneshwor Singh guneshwor.o.singh@intel.com Acked-By: Vinod Koul vinod.koul@intel.com Signed-off-by: Mark Brown broonie@kernel.org --- sound/soc/intel/skylake/skl.c | 11 +++++++++++ 1 file changed, 11 insertions(+)
diff --git a/sound/soc/intel/skylake/skl.c b/sound/soc/intel/skylake/skl.c index ab651517e8b8..e612a4097275 100644 --- a/sound/soc/intel/skylake/skl.c +++ b/sound/soc/intel/skylake/skl.c @@ -996,6 +996,14 @@ static struct sst_acpi_mach sst_glk_devdata[] = { }, };
+static const struct sst_acpi_mach sst_cnl_devdata[] = { + { + .id = "INT34C2", + .drv_name = "cnl_rt274", + .fw_filename = "intel/dsp_fw_cnl.bin", + }, +}; + /* PCI IDs */ static const struct pci_device_id skl_ids[] = { /* Sunrise Point-LP */ @@ -1010,6 +1018,9 @@ static const struct pci_device_id skl_ids[] = { /* GLK */ { PCI_DEVICE(0x8086, 0x3198), .driver_data = (unsigned long)&sst_glk_devdata}, + /* CNL */ + { PCI_DEVICE(0x8086, 0x9dc8), + .driver_data = (unsigned long)&sst_cnl_devdata}, { 0, } }; MODULE_DEVICE_TABLE(pci, skl_ids);
On Wed, Aug 02, 2017 at 09:51:11PM +0530, Guneshwor Singh wrote:
Cannonlake (CNL) audio is similar to Broxton with a substantial difference in ipc registers. This series enables CNL support by adding required dsp library functions and ipc register programming. CNL has 4 dsp cores, additional core support is also added here.
To accommodate the above changes in the current code, existing helper functions, common functions that are reusable and dsp ops are modified.
Acked-By: Vinod Koul vinod.koul@intel.com
Dharageswari R (1): ASoC: Intel: Skylake: Add num of cores in dsp ops
Guneshwor Singh (7): ASoC: Intel: Skylake: Use num_core to allocate instead of macro ASoC: Intel: cnl: Add cnl dsp functions and registers ASoC: Intel: Skylake: Move platform specific init to platform dsp_init() ASoC: Intel: cnl: Unstatify common ipc functions ASoC: Intel: cnl: Add sst library functions for cnl platform ASoC: Intel: cnl: add dsp ops for cannonlake ASoC: Intel: cnl: add pci id for cnl
Pardha Saradhi K (1): ASoC: Intel: Skylake: Add dsp cores management
sound/soc/intel/skylake/Makefile | 5 +- sound/soc/intel/skylake/bxt-sst.c | 5 +- sound/soc/intel/skylake/cnl-sst-dsp.c | 274 ++++++++++++++++++ sound/soc/intel/skylake/cnl-sst-dsp.h | 112 ++++++++ sound/soc/intel/skylake/cnl-sst.c | 495 ++++++++++++++++++++++++++++++++ sound/soc/intel/skylake/skl-messages.c | 31 ++ sound/soc/intel/skylake/skl-sst-dsp.c | 2 +- sound/soc/intel/skylake/skl-sst-ipc.c | 6 +- sound/soc/intel/skylake/skl-sst-ipc.h | 12 +- sound/soc/intel/skylake/skl-sst-utils.c | 6 +- sound/soc/intel/skylake/skl-sst.c | 6 +- sound/soc/intel/skylake/skl-topology.c | 26 +- sound/soc/intel/skylake/skl.c | 11 + sound/soc/intel/skylake/skl.h | 1 + 14 files changed, 970 insertions(+), 22 deletions(-) create mode 100644 sound/soc/intel/skylake/cnl-sst-dsp.c create mode 100644 sound/soc/intel/skylake/cnl-sst-dsp.h create mode 100644 sound/soc/intel/skylake/cnl-sst.c
-- 2.13.0
participants (3)
-
Guneshwor Singh
-
Mark Brown
-
Vinod Koul