diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2017-05-03 20:58:59 +0200 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-05-03 20:58:59 +0200 |
commit | 221656e7c4ce342b99c31eca96c1cbb6d1dce45f (patch) | |
tree | 1af3655475361f3ec75d8e26bc8d5f4bad8a87b0 /sound/soc/intel/skylake/bxt-sst.c | |
parent | Merge tag 'drm-for-v4.12' of git://people.freedesktop.org/~airlied/linux (diff) | |
parent | Merge tag 'asoc-v4.12' of git://git.kernel.org/pub/scm/linux/kernel/git/broon... (diff) | |
download | linux-221656e7c4ce342b99c31eca96c1cbb6d1dce45f.tar.xz linux-221656e7c4ce342b99c31eca96c1cbb6d1dce45f.zip |
Merge tag 'sound-4.12-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound
Pull sound updates from Takashi Iwai:
"It was a relatively calm development cycle, and no scaring changes are
seen in both core and driver sides. Here are some highlights:
ASoC:
- A new API for hooking up jacks more generically and easily
- Card longname is set based on DMI for a unique UCM profile
- Lots of Intel driver fixes: Atom, Broxton, Skylake and newer chips
- New drivers for Cirrus CS35L35, DIO DIO2125, Everest ES7132,
HiSilicon hi6210, Maxim MAX98927, MT2701 systems with WM8960,
Nuvoton NAU8824, Odroid systems, ST STM32 SAI controllers and x86
systems with DA7213
HD-audio:
- Many new quirks to support headset for various devices (mostly ASUS
ones) as usual
- Support for dual codecs on some Gigabyte mobos and Lenovo laptop
- Improvement on PCM position reporting for Skylake and newer
FireWire:
- New drivers for MOTU and RME Fireface series
- Updates for Digidesign Digi00x and TASCAM series
- Support for tracepoints
Others:
- USB-audio: improved support for quirk_alias option
- Cleanups, constification allover the places"
* tag 'sound-4.12-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: (299 commits)
ASoC: codec: wm8960: Relax bit clock computation when using PLL
ASoC: codec: wm9860: avoid maybe-uninitialized warning
ASoC: nau8824: leave Class D gain at chip default
ASoC: nau8824: rename controls to match DAPM controls
ASoC: Intel: Skylake: Return negative error code
ASoC: Intel: Skylake: Fix unused variable warning
ASoC: Intel: Skylake: fix uninitialized pointer use
ASoC: sti: Fix error handling if of_clk_get() fails
ASoC: cs4271: configure reset GPIO as output
ASoC: dwc: Disallow building designware_pcm as a module
ALSA: ali5451: fix spelling mistake in "ali_capture_preapre"
ASoC: stm32: add SAI driver
ASoC: stm32: add bindings for SAI
ASoC: Intel: Skylake: Add loadable module support on KBL platform
ASoC: Intel: Skylake: Modify load_lib_ipc arguments for a nowait version
ASoC: Intel: Skylake: Register dsp_fw_ops for kabylake
ASoC: Intel: Skylake: Modify arguments to reuse module transfer function
ASoC: Intel: Skylake: Commonize library load
ASoC: Intel: Skylake: Move sst common initialization to a helper function
ASoC: nau8824: new driver
...
Diffstat (limited to 'sound/soc/intel/skylake/bxt-sst.c')
-rw-r--r-- | sound/soc/intel/skylake/bxt-sst.c | 118 |
1 files changed, 53 insertions, 65 deletions
diff --git a/sound/soc/intel/skylake/bxt-sst.c b/sound/soc/intel/skylake/bxt-sst.c index 15a063a403cc..f5e7dbb1ba39 100644 --- a/sound/soc/intel/skylake/bxt-sst.c +++ b/sound/soc/intel/skylake/bxt-sst.c @@ -25,7 +25,8 @@ #include "skl-sst-ipc.h" #define BXT_BASEFW_TIMEOUT 3000 -#define BXT_INIT_TIMEOUT 500 +#define BXT_INIT_TIMEOUT 300 +#define BXT_ROM_INIT_TIMEOUT 70 #define BXT_IPC_PURGE_FW 0x01004000 #define BXT_ROM_INIT 0x5 @@ -45,6 +46,8 @@ /* Delay before scheduling D0i3 entry */ #define BXT_D0I3_DELAY 5000 +#define BXT_FW_ROM_INIT_RETRY 3 + static unsigned int bxt_get_errorcode(struct sst_dsp *ctx) { return sst_dsp_shim_read(ctx, BXT_ADSP_ERROR_CODE); @@ -55,29 +58,15 @@ bxt_load_library(struct sst_dsp *ctx, struct skl_lib_info *linfo, int lib_count) { struct snd_dma_buffer dmab; struct skl_sst *skl = ctx->thread_context; - const struct firmware *fw = NULL; struct firmware stripped_fw; int ret = 0, i, dma_id, stream_tag; /* library indices start from 1 to N. 0 represents base FW */ for (i = 1; i < lib_count; i++) { - ret = request_firmware(&fw, linfo[i].name, ctx->dev); - if (ret < 0) { - dev_err(ctx->dev, "Request lib %s failed:%d\n", - linfo[i].name, ret); - return ret; - } - - if (skl->is_first_boot) { - ret = snd_skl_parse_uuids(ctx, fw, + ret = skl_prepare_lib_load(skl, &skl->lib_info[i], &stripped_fw, BXT_ADSP_FW_BIN_HDR_OFFSET, i); - if (ret < 0) - goto load_library_failed; - } - - stripped_fw.data = fw->data; - stripped_fw.size = fw->size; - skl_dsp_strip_extended_manifest(&stripped_fw); + if (ret < 0) + goto load_library_failed; stream_tag = ctx->dsp_ops.prepare(ctx->dev, 0x40, stripped_fw.size, &dmab); @@ -92,21 +81,19 @@ bxt_load_library(struct sst_dsp *ctx, struct skl_lib_info *linfo, int lib_count) memcpy(dmab.area, stripped_fw.data, stripped_fw.size); ctx->dsp_ops.trigger(ctx->dev, true, stream_tag); - ret = skl_sst_ipc_load_library(&skl->ipc, dma_id, i); + ret = skl_sst_ipc_load_library(&skl->ipc, dma_id, i, true); if (ret < 0) dev_err(ctx->dev, "IPC Load Lib for %s fail: %d\n", linfo[i].name, ret); ctx->dsp_ops.trigger(ctx->dev, false, stream_tag); ctx->dsp_ops.cleanup(ctx->dev, &dmab, stream_tag); - release_firmware(fw); - fw = NULL; } return ret; load_library_failed: - release_firmware(fw); + skl_release_library(linfo, lib_count); return ret; } @@ -156,7 +143,7 @@ static int sst_bxt_prepare_fw(struct sst_dsp *ctx, SKL_ADSP_REG_HIPCIE_DONE, BXT_INIT_TIMEOUT, "HIPCIE Done"); if (ret < 0) { - dev_err(ctx->dev, "Timout for Purge Request%d\n", ret); + dev_err(ctx->dev, "Timeout for Purge Request%d\n", ret); goto base_fw_load_failed; } @@ -173,7 +160,7 @@ static int sst_bxt_prepare_fw(struct sst_dsp *ctx, /* Step 7: Wait for ROM init */ ret = sst_dsp_register_poll(ctx, BXT_ADSP_FW_STATUS, SKL_FW_STS_MASK, - SKL_FW_INIT, BXT_INIT_TIMEOUT, "ROM Load"); + SKL_FW_INIT, BXT_ROM_INIT_TIMEOUT, "ROM Load"); if (ret < 0) { dev_err(ctx->dev, "Timeout for ROM init, ret:%d\n", ret); goto base_fw_load_failed; @@ -206,18 +193,16 @@ static int bxt_load_base_firmware(struct sst_dsp *ctx) { struct firmware stripped_fw; struct skl_sst *skl = ctx->thread_context; - int ret; + int ret, i; - ret = request_firmware(&ctx->fw, ctx->fw_name, ctx->dev); - if (ret < 0) { - dev_err(ctx->dev, "Request firmware failed %d\n", ret); - goto sst_load_base_firmware_failed; + if (ctx->fw == NULL) { + ret = request_firmware(&ctx->fw, ctx->fw_name, ctx->dev); + if (ret < 0) { + dev_err(ctx->dev, "Request firmware failed %d\n", ret); + return ret; + } } - /* check for extended manifest */ - if (ctx->fw == NULL) - goto sst_load_base_firmware_failed; - /* prase uuids on first boot */ if (skl->is_first_boot) { ret = snd_skl_parse_uuids(ctx, ctx->fw, BXT_ADSP_FW_BIN_HDR_OFFSET, 0); @@ -229,18 +214,20 @@ static int bxt_load_base_firmware(struct sst_dsp *ctx) stripped_fw.size = ctx->fw->size; skl_dsp_strip_extended_manifest(&stripped_fw); - ret = sst_bxt_prepare_fw(ctx, stripped_fw.data, stripped_fw.size); - /* Retry Enabling core and ROM load. Retry seemed to help */ - if (ret < 0) { + + for (i = 0; i < BXT_FW_ROM_INIT_RETRY; i++) { ret = sst_bxt_prepare_fw(ctx, stripped_fw.data, stripped_fw.size); - if (ret < 0) { - dev_err(ctx->dev, "Error code=0x%x: FW status=0x%x\n", + if (ret == 0) + break; + } + + if (ret < 0) { + dev_err(ctx->dev, "Error code=0x%x: FW status=0x%x\n", sst_dsp_shim_read(ctx, BXT_ADSP_ERROR_CODE), sst_dsp_shim_read(ctx, BXT_ADSP_FW_STATUS)); - dev_err(ctx->dev, "Core En/ROM load fail:%d\n", ret); - goto sst_load_base_firmware_failed; - } + dev_err(ctx->dev, "Core En/ROM load fail:%d\n", ret); + goto sst_load_base_firmware_failed; } ret = sst_transfer_fw_host_dma(ctx); @@ -265,8 +252,11 @@ static int bxt_load_base_firmware(struct sst_dsp *ctx) } } + return ret; + sst_load_base_firmware_failed: release_firmware(ctx->fw); + ctx->fw = NULL; return ret; } @@ -428,6 +418,7 @@ static int bxt_set_dsp_D0(struct sst_dsp *ctx, unsigned int core_id) return ret; } } + skl->cores.state[core_id] = SKL_DSP_RUNNING; return ret; } @@ -514,11 +505,22 @@ static int bxt_set_dsp_D3(struct sst_dsp *ctx, unsigned int core_id) ret = skl_ipc_set_dx(&skl->ipc, BXT_INSTANCE_ID, BXT_BASE_FW_MODULE_ID, &dx); - if (ret < 0) + if (ret < 0) { dev_err(ctx->dev, "Failed to set DSP to D3:core id = %d;Continue reset\n", core_id); + /* + * In case of D3 failure, re-download the firmware, so set + * fw_loaded to false. + */ + skl->fw_loaded = false; + } + if (core_id == SKL_DSP_CORE0_ID) { + /* disable Interrupt */ + skl_ipc_op_int_disable(ctx); + skl_ipc_int_disable(ctx); + } ret = skl_dsp_disable_core(ctx, core_mask); if (ret < 0) { dev_err(ctx->dev, "Failed to disable core %d\n", ret); @@ -560,23 +562,14 @@ int bxt_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq, struct sst_dsp *sst; int ret; - skl = devm_kzalloc(dev, sizeof(*skl), GFP_KERNEL); - if (skl == NULL) - return -ENOMEM; - - skl->dev = dev; - skl_dev.thread_context = skl; - INIT_LIST_HEAD(&skl->uuid_list); - - skl->dsp = skl_dsp_ctx_init(dev, &skl_dev, irq); - if (!skl->dsp) { - dev_err(skl->dev, "skl_dsp_ctx_init failed\n"); - return -ENODEV; + ret = skl_sst_ctx_init(dev, irq, fw_name, dsp_ops, dsp, &skl_dev); + if (ret < 0) { + dev_err(dev, "%s: no device\n", __func__); + return ret; } + skl = *dsp; sst = skl->dsp; - sst->fw_name = fw_name; - sst->dsp_ops = dsp_ops; sst->fw_ops = bxt_fw_ops; sst->addr.lpe = mmio_base; sst->addr.shim = mmio_base; @@ -584,24 +577,15 @@ 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); - INIT_LIST_HEAD(&sst->module_list); - 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; skl->cores.count = 2; skl->boot_complete = false; init_waitqueue_head(&skl->boot_wait); - skl->is_first_boot = true; INIT_DELAYED_WORK(&skl->d0i3.work, bxt_set_dsp_D0i3); skl->d0i3.state = SKL_DSP_D0I3_NONE; - if (dsp) - *dsp = skl; - return 0; } EXPORT_SYMBOL_GPL(bxt_sst_dsp_init); @@ -635,6 +619,10 @@ EXPORT_SYMBOL_GPL(bxt_sst_init_fw); void bxt_sst_dsp_cleanup(struct device *dev, struct skl_sst *ctx) { + + skl_release_library(ctx->lib_info, ctx->lib_count); + if (ctx->dsp->fw) + release_firmware(ctx->dsp->fw); skl_freeup_uuid_list(ctx); skl_ipc_free(&ctx->ipc); ctx->dsp->cl_dev.ops.cl_cleanup_controller(ctx->dsp); |