diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-07-31 02:25:02 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-07-31 02:25:02 -0700 |
commit | c9b95e5961c0294e0efffeaa847c1a1e6369204c (patch) | |
tree | 384daa5e36a795d48475d445b3857b47e0b3f8d3 /sound/soc/intel/skylake/skl-sst.c | |
parent | bad60e6f259a01cf9f29a1ef8d435ab6c60b2de9 (diff) | |
parent | 0984d159c8ad6618c6ebd9f00bc3f374fa52bc35 (diff) | |
download | op-kernel-dev-c9b95e5961c0294e0efffeaa847c1a1e6369204c.zip op-kernel-dev-c9b95e5961c0294e0efffeaa847c1a1e6369204c.tar.gz |
Merge tag 'sound-4.8-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound
Pull sound updates from Takashi Iwai:
"The majority of this update is about ASoC, including a few new
drivers, and the rest are mostly minor changes. The only substantial
change in ALSA core is about the additional error handling in the
compress-offload API. Below are highlights:
- Add the error propagating support in compress-offload API
- HD-audio: a usual Dell headset fixup, an Intel HDMI/DP fix, and the
default mixer setup change ot turn off the loopback
- Lots of updates for ASoC Intel drivers, mostly board support and
bug fixing, and to the NAU8825 driver
- Work on generalizing bits of simple-card to allow more code sharing
with the Renesas rsrc-card (which can't use simple-card due to DPCM)
- Removal of the Odroid X2 driver due to replacement with simple-card
- Support for several new Mediatek platforms and associated boards
- New ASoC drivers for Allwinner A10, Analog Devices ADAU7002,
Broadcom Cygnus, Cirrus Logic CS35L33 and CS53L30, Maxim MAX8960
and MAX98504, Realtek RT5514 and Wolfson WM8758"
* tag 'sound-4.8-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: (278 commits)
sound: oss: Use kernel_read_file_from_path() for mod_firmware_load()
ASoC: Intel: Skylake: Delete an unnecessary check before the function call "release_firmware"
ASoC: Intel: Skylake: Fix NULL Pointer exception in dynamic_debug.
ASoC: samsung: Specify DMA channels through struct snd_dmaengine_pcm_config
ASoC: samsung: Fix error paths in the I2S driver's probe()
ASoC: cs53l30: Fix bit shift issue of TDM mode
ASoC: cs53l30: Fix a bug for TDM slot location validation
ASoC: rockchip: correct the spdif clk
ALSA: echoaudio: purge contradictions between dimension matrix members and total number of members
ASoC: rsrc-card: use asoc_simple_card_parse_card_name()
ASoC: rsrc-card: use asoc_simple_dai instead of rsrc_card_dai
ASoC: rsrc-card: use asoc_simple_card_parse_dailink_name()
ASoC: simple-card: use asoc_simple_card_parse_card_name()
ASoC: simple-card-utils: add asoc_simple_card_parse_card_name()
ASoC: simple-card: use asoc_simple_card_parse_dailink_name()
ASoC: simple-card-utils: add asoc_simple_card_set_dailink_name()
ASoC: nau8825: drop redundant idiom when converting integer to boolean
ASoC: nau8825: jack connection decision with different insertion logic
ASoC: mediatek: Add HDMI dai-links to the mt8173-rt5650 machine driver
ASoC: mediatek: mt2701: fix non static symbol warning
...
Diffstat (limited to 'sound/soc/intel/skylake/skl-sst.c')
-rw-r--r-- | sound/soc/intel/skylake/skl-sst.c | 124 |
1 files changed, 90 insertions, 34 deletions
diff --git a/sound/soc/intel/skylake/skl-sst.c b/sound/soc/intel/skylake/skl-sst.c index 13ec8d5..588f899 100644 --- a/sound/soc/intel/skylake/skl-sst.c +++ b/sound/soc/intel/skylake/skl-sst.c @@ -68,10 +68,13 @@ static int skl_transfer_firmware(struct sst_dsp *ctx, return ret; } +#define SKL_ADSP_FW_BIN_HDR_OFFSET 0x284 + static int skl_load_base_firmware(struct sst_dsp *ctx) { int ret = 0, i; struct skl_sst *skl = ctx->thread_context; + struct firmware stripped_fw; u32 reg; skl->boot_complete = false; @@ -81,11 +84,25 @@ static int skl_load_base_firmware(struct sst_dsp *ctx) ret = request_firmware(&ctx->fw, ctx->fw_name, ctx->dev); if (ret < 0) { dev_err(ctx->dev, "Request firmware failed %d\n", ret); - skl_dsp_disable_core(ctx); return -EIO; } } + ret = snd_skl_parse_uuids(ctx, SKL_ADSP_FW_BIN_HDR_OFFSET); + if (ret < 0) { + dev_err(ctx->dev, + "UUID parsing err: %d\n", ret); + release_firmware(ctx->fw); + skl_dsp_disable_core(ctx, SKL_DSP_CORE0_MASK); + return ret; + } + + /* check for extended manifest */ + stripped_fw.data = ctx->fw->data; + stripped_fw.size = ctx->fw->size; + + skl_dsp_strip_extended_manifest(&stripped_fw); + ret = skl_dsp_boot(ctx); if (ret < 0) { dev_err(ctx->dev, "Boot dsp core failed ret: %d", ret); @@ -119,7 +136,7 @@ static int skl_load_base_firmware(struct sst_dsp *ctx) goto transfer_firmware_failed; } - ret = skl_transfer_firmware(ctx, ctx->fw->data, ctx->fw->size); + ret = skl_transfer_firmware(ctx, stripped_fw.data, stripped_fw.size); if (ret < 0) { dev_err(ctx->dev, "Transfer firmware failed%d\n", ret); goto transfer_firmware_failed; @@ -133,67 +150,87 @@ static int skl_load_base_firmware(struct sst_dsp *ctx) } dev_dbg(ctx->dev, "Download firmware successful%d\n", ret); - skl_dsp_set_state_locked(ctx, SKL_DSP_RUNNING); + skl->fw_loaded = true; } return 0; transfer_firmware_failed: ctx->cl_dev.ops.cl_cleanup_controller(ctx); skl_load_base_firmware_failed: - skl_dsp_disable_core(ctx); + skl_dsp_disable_core(ctx, SKL_DSP_CORE0_MASK); release_firmware(ctx->fw); ctx->fw = NULL; return ret; } -static int skl_set_dsp_D0(struct sst_dsp *ctx) +static int skl_set_dsp_D0(struct sst_dsp *ctx, unsigned int core_id) { int ret; + struct skl_ipc_dxstate_info dx; + struct skl_sst *skl = ctx->thread_context; + unsigned int core_mask = SKL_DSP_CORE_MASK(core_id); - ret = skl_load_base_firmware(ctx); - if (ret < 0) { - dev_err(ctx->dev, "unable to load firmware\n"); - return ret; + /* If core0 is being turned on, we need to load the FW */ + if (core_id == SKL_DSP_CORE0_ID) { + ret = skl_load_base_firmware(ctx); + if (ret < 0) { + dev_err(ctx->dev, "unable to load firmware\n"); + return ret; + } } - skl_dsp_set_state_locked(ctx, SKL_DSP_RUNNING); + /* + * If any core other than core 0 is being moved to D0, enable the + * core and send the set dx IPC for the core. + */ + if (core_id != SKL_DSP_CORE0_ID) { + ret = skl_dsp_enable_core(ctx, core_mask); + if (ret < 0) + return ret; + + dx.core_mask = core_mask; + dx.dx_mask = core_mask; + + ret = skl_ipc_set_dx(&skl->ipc, SKL_INSTANCE_ID, + SKL_BASE_FW_MODULE_ID, &dx); + if (ret < 0) { + dev_err(ctx->dev, "Failed to set dsp to D0:core id= %d\n", + core_id); + skl_dsp_disable_core(ctx, core_mask); + } + } + + skl->cores.state[core_id] = SKL_DSP_RUNNING; return ret; } -static int skl_set_dsp_D3(struct sst_dsp *ctx) +static int skl_set_dsp_D3(struct sst_dsp *ctx, unsigned int core_id) { int ret; struct skl_ipc_dxstate_info dx; struct skl_sst *skl = ctx->thread_context; + unsigned int core_mask = SKL_DSP_CORE_MASK(core_id); - dev_dbg(ctx->dev, "In %s:\n", __func__); - mutex_lock(&ctx->mutex); - if (!is_skl_dsp_running(ctx)) { - mutex_unlock(&ctx->mutex); - return 0; - } - mutex_unlock(&ctx->mutex); - - dx.core_mask = SKL_DSP_CORE0_MASK; + dx.core_mask = core_mask; dx.dx_mask = SKL_IPC_D3_MASK; + ret = skl_ipc_set_dx(&skl->ipc, SKL_INSTANCE_ID, SKL_BASE_FW_MODULE_ID, &dx); if (ret < 0) - dev_err(ctx->dev, - "D3 request to FW failed, continuing reset: %d", ret); - - /* disable Interrupt */ - ctx->cl_dev.ops.cl_cleanup_controller(ctx); - skl_cldma_int_disable(ctx); - skl_ipc_op_int_disable(ctx); - skl_ipc_int_disable(ctx); - - ret = skl_dsp_disable_core(ctx); - if (ret < 0) { - dev_err(ctx->dev, "disable dsp core failed ret: %d\n", ret); - ret = -EIO; + dev_err(ctx->dev, "set Dx core %d fail: %d\n", core_id, ret); + + if (core_id == SKL_DSP_CORE0_ID) { + /* disable Interrupt */ + ctx->cl_dev.ops.cl_cleanup_controller(ctx); + skl_cldma_int_disable(ctx); + skl_ipc_op_int_disable(ctx); + skl_ipc_int_disable(ctx); } - skl_dsp_set_state_locked(ctx, SKL_DSP_RESET); + ret = skl_dsp_disable_core(ctx, core_mask); + if (ret < 0) + return ret; + + skl->cores.state[core_id] = SKL_DSP_RESET; return ret; } @@ -360,6 +397,19 @@ static int skl_unload_module(struct sst_dsp *ctx, u16 mod_id) return ret; } +void skl_clear_module_cnt(struct sst_dsp *ctx) +{ + struct skl_module_table *module; + + if (list_empty(&ctx->module_list)) + return; + + list_for_each_entry(module, &ctx->module_list, list) { + module->usage_cnt = 0; + } +} +EXPORT_SYMBOL_GPL(skl_clear_module_cnt); + static void skl_clear_module_table(struct sst_dsp *ctx) { struct skl_module_table *module, *tmp; @@ -409,6 +459,7 @@ int skl_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq, skl->dev = dev; skl_dev.thread_context = skl; + INIT_LIST_HEAD(&skl->uuid_list); skl->dsp = skl_dsp_ctx_init(dev, &skl_dev, irq); if (!skl->dsp) { @@ -432,12 +483,16 @@ int skl_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq, if (ret) return ret; + skl->cores.count = 2; + ret = sst->fw_ops.load_fw(sst); if (ret < 0) { dev_err(dev, "Load base fw failed : %d", ret); goto cleanup; } + skl_dsp_init_core_state(sst); + if (dsp) *dsp = skl; @@ -452,6 +507,7 @@ EXPORT_SYMBOL_GPL(skl_sst_dsp_init); void skl_sst_dsp_cleanup(struct device *dev, struct skl_sst *ctx) { skl_clear_module_table(ctx->dsp); + skl_freeup_uuid_list(ctx); skl_ipc_free(&ctx->ipc); ctx->dsp->ops->free(ctx->dsp); if (ctx->boot_complete) { |