From 2ab4c50f6955514150f83b47b7aee3ba5fe3ac1d Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 27 Sep 2019 15:05:28 -0500 Subject: ASoC: SOF: trace: move to opt-in with Kconfig and module parameter In a number of debug cases, the DMA-based trace can add problems (e.g. with HDaudio channel allocation). It also generates additional traffic on the bus and if the DMA handling is unreliable will prevent audio use-cases from working normally. Using the trace also requires tools to be installed on the target. The trace can be instead handled as dynamic debug. We can use a Kconfig to force the trace to be enabled in all cases, or use a module parameter to enable it on a need-basis, e.g. by setting "options snd_sof sof_debug=0x1" in a /etc/modprobe.d file. Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20190927200538.660-4-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/Kconfig | 8 ++++++++ sound/soc/sof/core.c | 25 +++++++++++++++++++------ sound/soc/sof/sof-priv.h | 13 +++++++++---- sound/soc/sof/trace.c | 17 ++++++++++++++++- 4 files changed, 52 insertions(+), 11 deletions(-) (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/Kconfig b/sound/soc/sof/Kconfig index bb8036ae567e..cc592bcadae7 100644 --- a/sound/soc/sof/Kconfig +++ b/sound/soc/sof/Kconfig @@ -142,6 +142,14 @@ config SND_SOC_SOF_DEBUG_ENABLE_DEBUGFS_CACHE Say Y if you want to enable caching the memory windows. If unsure, select "N". +config SND_SOC_SOF_DEBUG_ENABLE_FIRMWARE_TRACE + bool "SOF enable firmware trace" + help + The firmware trace can be enabled either at build-time with + this option, or dynamically by setting flags in the SOF core + module parameter (similar to dynamic debug) + If unsure, select "N". + config SND_SOC_SOF_DEBUG_IPC_FLOOD_TEST bool "SOF enable IPC flood test" help diff --git a/sound/soc/sof/core.c b/sound/soc/sof/core.c index 81f28f7ff1a0..15167b8220ed 100644 --- a/sound/soc/sof/core.c +++ b/sound/soc/sof/core.c @@ -16,6 +16,11 @@ #include "sof-priv.h" #include "ops.h" +/* see SOF_DBG_ flags */ +int sof_core_debug; +module_param_named(sof_debug, sof_core_debug, int, 0444); +MODULE_PARM_DESC(sof_debug, "SOF core debug options (0x0 all off)"); + /* SOF defaults if not provided by the platform in ms */ #define TIMEOUT_DEFAULT_IPC_MS 500 #define TIMEOUT_DEFAULT_BOOT_MS 2000 @@ -350,12 +355,20 @@ static int sof_probe_continue(struct snd_sof_dev *sdev) goto fw_run_err; } - /* init DMA trace */ - ret = snd_sof_init_trace(sdev); - if (ret < 0) { - /* non fatal */ - dev_warn(sdev->dev, - "warning: failed to initialize trace %d\n", ret); + if (IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_ENABLE_FIRMWARE_TRACE) || + (sof_core_debug & SOF_DBG_ENABLE_TRACE)) { + sdev->dtrace_is_supported = true; + + /* init DMA trace */ + ret = snd_sof_init_trace(sdev); + if (ret < 0) { + /* non fatal */ + dev_warn(sdev->dev, + "warning: failed to initialize trace %d\n", + ret); + } + } else { + dev_dbg(sdev->dev, "SOF firmware trace disabled\n"); } /* hereafter all FW boot flows are for PM reasons */ diff --git a/sound/soc/sof/sof-priv.h b/sound/soc/sof/sof-priv.h index 730f3259dd02..d5b1a4f895da 100644 --- a/sound/soc/sof/sof-priv.h +++ b/sound/soc/sof/sof-priv.h @@ -28,10 +28,14 @@ #include /* debug flags */ -#define SOF_DBG_REGS BIT(1) -#define SOF_DBG_MBOX BIT(2) -#define SOF_DBG_TEXT BIT(3) -#define SOF_DBG_PCI BIT(4) +#define SOF_DBG_ENABLE_TRACE BIT(0) +#define SOF_DBG_REGS BIT(1) +#define SOF_DBG_MBOX BIT(2) +#define SOF_DBG_TEXT BIT(3) +#define SOF_DBG_PCI BIT(4) + +/* global debug state set by SOF_DBG_ flags */ +extern int sof_core_debug; /* max BARs mmaped devices can use */ #define SND_SOF_BARS 8 @@ -434,6 +438,7 @@ struct snd_sof_dev { int dma_trace_pages; wait_queue_head_t trace_sleep; u32 host_offset; + u32 dtrace_is_supported; /* set with Kconfig or module parameter */ u32 dtrace_is_enabled; u32 dtrace_error; u32 dtrace_draining; diff --git a/sound/soc/sof/trace.c b/sound/soc/sof/trace.c index 4c3cff031fd6..b0e4556c8536 100644 --- a/sound/soc/sof/trace.c +++ b/sound/soc/sof/trace.c @@ -162,6 +162,9 @@ int snd_sof_init_trace_ipc(struct snd_sof_dev *sdev) struct sof_ipc_reply ipc_reply; int ret; + if (!sdev->dtrace_is_supported) + return 0; + if (sdev->dtrace_is_enabled || !sdev->dma_trace_pages) return -EINVAL; @@ -222,6 +225,9 @@ int snd_sof_init_trace(struct snd_sof_dev *sdev) { int ret; + if (!sdev->dtrace_is_supported) + return 0; + /* set false before start initialization */ sdev->dtrace_is_enabled = false; @@ -277,6 +283,9 @@ EXPORT_SYMBOL(snd_sof_init_trace); int snd_sof_trace_update_pos(struct snd_sof_dev *sdev, struct sof_ipc_dma_trace_posn *posn) { + if (!sdev->dtrace_is_supported) + return 0; + if (sdev->dtrace_is_enabled && sdev->host_offset != posn->host_offset) { sdev->host_offset = posn->host_offset; wake_up(&sdev->trace_sleep); @@ -293,6 +302,9 @@ int snd_sof_trace_update_pos(struct snd_sof_dev *sdev, /* an error has occurred within the DSP that prevents further trace */ void snd_sof_trace_notify_for_error(struct snd_sof_dev *sdev) { + if (!sdev->dtrace_is_supported) + return; + if (sdev->dtrace_is_enabled) { dev_err(sdev->dev, "error: waking up any trace sleepers\n"); sdev->dtrace_error = true; @@ -305,7 +317,7 @@ void snd_sof_release_trace(struct snd_sof_dev *sdev) { int ret; - if (!sdev->dtrace_is_enabled) + if (!sdev->dtrace_is_supported || !sdev->dtrace_is_enabled) return; ret = snd_sof_dma_trace_trigger(sdev, SNDRV_PCM_TRIGGER_STOP); @@ -326,6 +338,9 @@ EXPORT_SYMBOL(snd_sof_release_trace); void snd_sof_free_trace(struct snd_sof_dev *sdev) { + if (!sdev->dtrace_is_supported) + return; + snd_sof_release_trace(sdev); snd_dma_free_pages(&sdev->dmatb); -- cgit v1.2.3 From 9a06508bf7824ba34f2e1e9e08df505ac14a44c2 Mon Sep 17 00:00:00 2001 From: Liam Girdwood Date: Fri, 27 Sep 2019 15:05:29 -0500 Subject: ASoC: SOF: ipc: retain DSP context after FW exception. Add config option to prevent DSP entering D3 after any FW exception. This can then be used to dump FW context for debug. Signed-off-by: Liam Girdwood Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20190927200538.660-5-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/Kconfig | 8 ++++++++ sound/soc/sof/debug.c | 16 ++++++++++++++++ sound/soc/sof/ipc.c | 4 +--- sound/soc/sof/sof-priv.h | 2 ++ 4 files changed, 27 insertions(+), 3 deletions(-) (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/Kconfig b/sound/soc/sof/Kconfig index cc592bcadae7..56a3ab66b46b 100644 --- a/sound/soc/sof/Kconfig +++ b/sound/soc/sof/Kconfig @@ -158,6 +158,14 @@ config SND_SOC_SOF_DEBUG_IPC_FLOOD_TEST Say Y if you want to enable IPC flood test. If unsure, select "N". +config SND_SOC_SOF_DEBUG_RETAIN_DSP_CONTEXT + bool "SOF retain DSP context on any FW exceptions" + help + This option keeps the DSP in D0 state so that firmware debug + information can be retained and dumped to userspace. + Say Y if you want to retain DSP context for FW exceptions. + If unsure, select "N". + endif ## SND_SOC_SOF_DEBUG endif ## SND_SOC_SOF_OPTIONS diff --git a/sound/soc/sof/debug.c b/sound/soc/sof/debug.c index 54cd431faab7..b8a4e899154c 100644 --- a/sound/soc/sof/debug.c +++ b/sound/soc/sof/debug.c @@ -461,3 +461,19 @@ void snd_sof_free_debug(struct snd_sof_dev *sdev) debugfs_remove_recursive(sdev->debugfs_root); } EXPORT_SYMBOL_GPL(snd_sof_free_debug); + +void snd_sof_handle_fw_exception(struct snd_sof_dev *sdev) +{ + if (IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_RETAIN_DSP_CONTEXT) || + (sof_core_debug & SOF_DBG_RETAIN_CTX)) { + /* should we prevent DSP entering D3 ? */ + dev_info(sdev->dev, "info: preventing DSP entering D3 state to preserve context\n"); + pm_runtime_get_noresume(sdev->dev); + } + + /* dump vital information to the logs */ + snd_sof_dsp_dbg_dump(sdev, SOF_DBG_REGS | SOF_DBG_MBOX); + snd_sof_ipc_dump(sdev); + snd_sof_trace_notify_for_error(sdev); +} +EXPORT_SYMBOL(snd_sof_handle_fw_exception); diff --git a/sound/soc/sof/ipc.c b/sound/soc/sof/ipc.c index b2f359d2f7e5..b946c81197a1 100644 --- a/sound/soc/sof/ipc.c +++ b/sound/soc/sof/ipc.c @@ -210,9 +210,7 @@ static int tx_wait_done(struct snd_sof_ipc *ipc, struct snd_sof_ipc_msg *msg, if (ret == 0) { dev_err(sdev->dev, "error: ipc timed out for 0x%x size %d\n", hdr->cmd, hdr->size); - snd_sof_dsp_dbg_dump(ipc->sdev, SOF_DBG_REGS | SOF_DBG_MBOX); - snd_sof_ipc_dump(ipc->sdev); - snd_sof_trace_notify_for_error(ipc->sdev); + snd_sof_handle_fw_exception(ipc->sdev); ret = -ETIMEDOUT; } else { /* copy the data returned from DSP */ diff --git a/sound/soc/sof/sof-priv.h b/sound/soc/sof/sof-priv.h index d5b1a4f895da..348759035dd0 100644 --- a/sound/soc/sof/sof-priv.h +++ b/sound/soc/sof/sof-priv.h @@ -33,6 +33,7 @@ #define SOF_DBG_MBOX BIT(2) #define SOF_DBG_TEXT BIT(3) #define SOF_DBG_PCI BIT(4) +#define SOF_DBG_RETAIN_CTX BIT(5) /* prevent DSP D3 on FW exception */ /* global debug state set by SOF_DBG_ flags */ extern int sof_core_debug; @@ -580,6 +581,7 @@ void snd_sof_get_status(struct snd_sof_dev *sdev, u32 panic_code, struct sof_ipc_panic_info *panic_info, void *stack, size_t stack_words); int snd_sof_init_trace_ipc(struct snd_sof_dev *sdev); +void snd_sof_handle_fw_exception(struct snd_sof_dev *sdev); /* * Platform specific ops. -- cgit v1.2.3 From 8692d498d675e2e1433274c5f03b855824f3f35d Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Fri, 27 Sep 2019 15:05:32 -0500 Subject: ASoC: SOF: core: check for mandatory fw_ready op during SOF probe fw_ready should be a mandatory op. Make sure fw_ready ops is set during probe. Signed-off-by: Ranjani Sridharan Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20190927200538.660-8-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/core.c | 3 ++- sound/soc/sof/ipc.c | 6 ------ sound/soc/sof/sof-priv.h | 2 +- 3 files changed, 3 insertions(+), 8 deletions(-) (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/core.c b/sound/soc/sof/core.c index 15167b8220ed..5998861a9002 100644 --- a/sound/soc/sof/core.c +++ b/sound/soc/sof/core.c @@ -466,7 +466,8 @@ int snd_sof_device_probe(struct device *dev, struct snd_sof_pdata *plat_data) if (!sof_ops(sdev) || !sof_ops(sdev)->probe || !sof_ops(sdev)->run || !sof_ops(sdev)->block_read || !sof_ops(sdev)->block_write || !sof_ops(sdev)->send_msg || !sof_ops(sdev)->load_firmware || - !sof_ops(sdev)->ipc_msg_data || !sof_ops(sdev)->ipc_pcm_params) + !sof_ops(sdev)->ipc_msg_data || !sof_ops(sdev)->ipc_pcm_params || + !sof_ops(sdev)->fw_ready) return -EINVAL; INIT_LIST_HEAD(&sdev->pcm_list); diff --git a/sound/soc/sof/ipc.c b/sound/soc/sof/ipc.c index b946c81197a1..26675dfe0240 100644 --- a/sound/soc/sof/ipc.c +++ b/sound/soc/sof/ipc.c @@ -792,12 +792,6 @@ struct snd_sof_ipc *snd_sof_ipc_init(struct snd_sof_dev *sdev) struct snd_sof_ipc *ipc; struct snd_sof_ipc_msg *msg; - /* check if mandatory ops required for ipc are defined */ - if (!sof_ops(sdev)->fw_ready) { - dev_err(sdev->dev, "error: ipc mandatory ops not defined\n"); - return NULL; - } - ipc = devm_kzalloc(sdev->dev, sizeof(*ipc), GFP_KERNEL); if (!ipc) return NULL; diff --git a/sound/soc/sof/sof-priv.h b/sound/soc/sof/sof-priv.h index 348759035dd0..44f789bf7fb0 100644 --- a/sound/soc/sof/sof-priv.h +++ b/sound/soc/sof/sof-priv.h @@ -133,7 +133,7 @@ struct snd_sof_dsp_ops { * FW ready checks for ABI compatibility and creates * memory windows at first boot */ - int (*fw_ready)(struct snd_sof_dev *sdev, u32 msg_id); /* optional */ + int (*fw_ready)(struct snd_sof_dev *sdev, u32 msg_id); /* mandatory */ /* connect pcm substream to a host stream */ int (*pcm_open)(struct snd_sof_dev *sdev, -- cgit v1.2.3 From f567ff6c76f7e9b317248fcab7a0eb3ef432dc9e Mon Sep 17 00:00:00 2001 From: Marcin Rajwa Date: Fri, 27 Sep 2019 15:05:34 -0500 Subject: ASoC: SOF: Intel: hda: fix reset of host_period_bytes This patch prevents the reset of host period bytes and uses no_stream_position to record requests for stream position. Signed-off-by: Marcin Rajwa Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20190927200538.660-10-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-pcm.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/intel/hda-pcm.c b/sound/soc/sof/intel/hda-pcm.c index 9b730f183529..575f5f5877d8 100644 --- a/sound/soc/sof/intel/hda-pcm.c +++ b/sound/soc/sof/intel/hda-pcm.c @@ -89,6 +89,7 @@ int hda_dsp_pcm_hw_params(struct snd_sof_dev *sdev, struct hdac_ext_stream *stream = stream_to_hdac_ext_stream(hstream); struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata; struct snd_dma_buffer *dmab; + struct sof_ipc_fw_version *v = &sdev->fw_ready.version; int ret; u32 size, rate, bits; @@ -116,9 +117,17 @@ int hda_dsp_pcm_hw_params(struct snd_sof_dev *sdev, /* disable SPIB, to enable buffer wrap for stream */ hda_dsp_stream_spib_config(sdev, stream, HDA_DSP_SPIB_DISABLE, 0); - /* set host_period_bytes to 0 if no IPC position */ - if (hda && hda->no_ipc_position) - ipc_params->host_period_bytes = 0; + /* update no_stream_position flag for ipc params */ + if (hda && hda->no_ipc_position) { + /* For older ABIs set host_period_bytes to zero to inform + * FW we don't want position updates. Newer versions use + * no_stream_position for this purpose. + */ + if (v->abi_version < SOF_ABI_VER(3, 10, 0)) + ipc_params->host_period_bytes = 0; + else + ipc_params->no_stream_position = 1; + } ipc_params->stream_tag = hstream->stream_tag; -- cgit v1.2.3 From 3a9e204d4e36904a464a2e53206b053a7ffc7bad Mon Sep 17 00:00:00 2001 From: Liam Girdwood Date: Fri, 27 Sep 2019 15:05:37 -0500 Subject: ASoC: SOF: Intel: Add context data to any IPC timeout. Helps with FW debug as it provides DSP IPC processing context. Signed-off-by: Liam Girdwood Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20190927200538.660-13-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/bdw.c | 22 +++++++++++++++++++++- sound/soc/sof/intel/byt.c | 23 ++++++++++++++++++++++- 2 files changed, 43 insertions(+), 2 deletions(-) (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/intel/bdw.c b/sound/soc/sof/intel/bdw.c index e282179263e8..170c74dc13b1 100644 --- a/sound/soc/sof/intel/bdw.c +++ b/sound/soc/sof/intel/bdw.c @@ -241,7 +241,7 @@ static void bdw_dump(struct snd_sof_dev *sdev, u32 flags) struct sof_ipc_dsp_oops_xtensa xoops; struct sof_ipc_panic_info panic_info; u32 stack[BDW_STACK_DUMP_SIZE]; - u32 status, panic; + u32 status, panic, imrx, imrd; /* now try generic SOF status messages */ status = snd_sof_dsp_read(sdev, BDW_DSP_BAR, SHIM_IPCD); @@ -250,6 +250,26 @@ static void bdw_dump(struct snd_sof_dev *sdev, u32 flags) BDW_STACK_DUMP_SIZE); snd_sof_get_status(sdev, status, panic, &xoops, &panic_info, stack, BDW_STACK_DUMP_SIZE); + + /* provide some context for firmware debug */ + imrx = snd_sof_dsp_read(sdev, BDW_DSP_BAR, SHIM_IMRX); + imrd = snd_sof_dsp_read(sdev, BDW_DSP_BAR, SHIM_IMRD); + dev_err(sdev->dev, + "error: ipc host -> DSP: pending %s complete %s raw 0x%8.8x\n", + panic & SHIM_IPCX_BUSY ? "yes" : "no", + panic & SHIM_IPCX_DONE ? "yes" : "no", panic); + dev_err(sdev->dev, + "error: mask host: pending %s complete %s raw 0x%8.8x\n", + imrx & SHIM_IMRX_BUSY ? "yes" : "no", + imrx & SHIM_IMRX_DONE ? "yes" : "no", imrx); + dev_err(sdev->dev, + "error: ipc DSP -> host: pending %s complete %s raw 0x%8.8x\n", + status & SHIM_IPCD_BUSY ? "yes" : "no", + status & SHIM_IPCD_DONE ? "yes" : "no", status); + dev_err(sdev->dev, + "error: mask DSP: pending %s complete %s raw 0x%8.8x\n", + imrd & SHIM_IMRD_BUSY ? "yes" : "no", + imrd & SHIM_IMRD_DONE ? "yes" : "no", imrd); } /* diff --git a/sound/soc/sof/intel/byt.c b/sound/soc/sof/intel/byt.c index 5e7a6aaa627a..ecbc9c79bcad 100644 --- a/sound/soc/sof/intel/byt.c +++ b/sound/soc/sof/intel/byt.c @@ -139,7 +139,7 @@ static void byt_dump(struct snd_sof_dev *sdev, u32 flags) struct sof_ipc_dsp_oops_xtensa xoops; struct sof_ipc_panic_info panic_info; u32 stack[BYT_STACK_DUMP_SIZE]; - u32 status, panic; + u32 status, panic, imrd, imrx; /* now try generic SOF status messages */ status = snd_sof_dsp_read(sdev, BYT_DSP_BAR, SHIM_IPCD); @@ -148,6 +148,27 @@ static void byt_dump(struct snd_sof_dev *sdev, u32 flags) BYT_STACK_DUMP_SIZE); snd_sof_get_status(sdev, status, panic, &xoops, &panic_info, stack, BYT_STACK_DUMP_SIZE); + + /* provide some context for firmware debug */ + imrx = snd_sof_dsp_read(sdev, BYT_DSP_BAR, SHIM_IMRX); + imrd = snd_sof_dsp_read(sdev, BYT_DSP_BAR, SHIM_IMRD); + dev_err(sdev->dev, + "error: ipc host -> DSP: pending %s complete %s raw 0x%8.8x\n", + panic & SHIM_IPCX_BUSY ? "yes" : "no", + panic & SHIM_IPCX_DONE ? "yes" : "no", panic); + dev_err(sdev->dev, + "error: mask host: pending %s complete %s raw 0x%8.8x\n", + imrx & SHIM_IMRX_BUSY ? "yes" : "no", + imrx & SHIM_IMRX_DONE ? "yes" : "no", imrx); + dev_err(sdev->dev, + "error: ipc DSP -> host: pending %s complete %s raw 0x%8.8x\n", + status & SHIM_IPCD_BUSY ? "yes" : "no", + status & SHIM_IPCD_DONE ? "yes" : "no", status); + dev_err(sdev->dev, + "error: mask DSP: pending %s complete %s raw 0x%8.8x\n", + imrd & SHIM_IMRD_BUSY ? "yes" : "no", + imrd & SHIM_IMRD_DONE ? "yes" : "no", imrd); + } /* -- cgit v1.2.3 From 1c91d77e1775e0d497382cc3494f42e08582f065 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 2 Oct 2019 14:32:56 +0900 Subject: ASoC: sof: pcm: remove snd_pcm_ops snd_pcm_ops is no longer needed. Let's use component driver callback. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/8736gbaf07.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/sof/pcm.c | 88 ++++++++++++++++++++++++++--------------------------- 1 file changed, 44 insertions(+), 44 deletions(-) (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/pcm.c b/sound/soc/sof/pcm.c index 2b876d497447..6490b1577152 100644 --- a/sound/soc/sof/pcm.c +++ b/sound/soc/sof/pcm.c @@ -19,12 +19,11 @@ #define DRV_NAME "sof-audio-component" /* Create DMA buffer page table for DSP */ -static int create_page_table(struct snd_pcm_substream *substream, +static int create_page_table(struct snd_soc_component *component, + struct snd_pcm_substream *substream, unsigned char *dma_area, size_t size) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_component *component = - snd_soc_rtdcom_lookup(rtd, DRV_NAME); struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component); struct snd_sof_pcm *spcm; struct snd_dma_buffer *dmab = snd_pcm_get_dma_buf(substream); @@ -95,13 +94,12 @@ void snd_sof_pcm_period_elapsed(struct snd_pcm_substream *substream) EXPORT_SYMBOL(snd_sof_pcm_period_elapsed); /* this may get called several times by oss emulation */ -static int sof_pcm_hw_params(struct snd_pcm_substream *substream, +static int sof_pcm_hw_params(struct snd_soc_component *component, + struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_soc_component *component = - snd_soc_rtdcom_lookup(rtd, DRV_NAME); struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component); struct snd_sof_pcm *spcm; struct sof_ipc_pcm_params pcm; @@ -135,7 +133,7 @@ static int sof_pcm_hw_params(struct snd_pcm_substream *substream, * ret == 0 means the buffer is not changed * so no need to regenerate the page table */ - ret = create_page_table(substream, runtime->dma_area, + ret = create_page_table(component, substream, runtime->dma_area, runtime->dma_bytes); if (ret < 0) return ret; @@ -237,11 +235,10 @@ static int sof_pcm_dsp_pcm_free(struct snd_pcm_substream *substream, return ret; } -static int sof_pcm_hw_free(struct snd_pcm_substream *substream) +static int sof_pcm_hw_free(struct snd_soc_component *component, + struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_component *component = - snd_soc_rtdcom_lookup(rtd, DRV_NAME); struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component); struct snd_sof_pcm *spcm; int ret, err = 0; @@ -276,11 +273,10 @@ static int sof_pcm_hw_free(struct snd_pcm_substream *substream) return err; } -static int sof_pcm_prepare(struct snd_pcm_substream *substream) +static int sof_pcm_prepare(struct snd_soc_component *component, + struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_component *component = - snd_soc_rtdcom_lookup(rtd, DRV_NAME); struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component); struct snd_sof_pcm *spcm; int ret; @@ -300,7 +296,8 @@ static int sof_pcm_prepare(struct snd_pcm_substream *substream) substream->stream); /* set hw_params */ - ret = sof_pcm_hw_params(substream, &spcm->params[substream->stream]); + ret = sof_pcm_hw_params(component, + substream, &spcm->params[substream->stream]); if (ret < 0) { dev_err(sdev->dev, "error: set pcm hw_params after resume\n"); return ret; @@ -313,11 +310,10 @@ static int sof_pcm_prepare(struct snd_pcm_substream *substream) * FE dai link trigger actions are always executed in non-atomic context because * they involve IPC's. */ -static int sof_pcm_trigger(struct snd_pcm_substream *substream, int cmd) +static int sof_pcm_trigger(struct snd_soc_component *component, + struct snd_pcm_substream *substream, int cmd) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_component *component = - snd_soc_rtdcom_lookup(rtd, DRV_NAME); struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component); struct snd_sof_pcm *spcm; struct sof_ipc_stream stream; @@ -351,7 +347,7 @@ static int sof_pcm_trigger(struct snd_pcm_substream *substream, int cmd) break; case SNDRV_PCM_TRIGGER_RESUME: /* set up hw_params */ - ret = sof_pcm_prepare(substream); + ret = sof_pcm_prepare(component, substream); if (ret < 0) { dev_err(sdev->dev, "error: failed to set up hw_params upon resume\n"); @@ -395,11 +391,10 @@ static int sof_pcm_trigger(struct snd_pcm_substream *substream, int cmd) return ret; } -static snd_pcm_uframes_t sof_pcm_pointer(struct snd_pcm_substream *substream) +static snd_pcm_uframes_t sof_pcm_pointer(struct snd_soc_component *component, + struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_component *component = - snd_soc_rtdcom_lookup(rtd, DRV_NAME); struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component); struct snd_sof_pcm *spcm; snd_pcm_uframes_t host, dai; @@ -428,12 +423,22 @@ static snd_pcm_uframes_t sof_pcm_pointer(struct snd_pcm_substream *substream) return host; } -static int sof_pcm_open(struct snd_pcm_substream *substream) +#ifdef CONFIG_SND_DMA_SGBUF +static struct page *sof_pcm_page(struct snd_soc_component *component, + struct snd_pcm_substream *substream, + unsigned long offset) +{ + return snd_pcm_sgbuf_ops_page(substream, offset); +} +#else +#define sof_pcm_page NULL +#endif /* CONFIG_SND_DMA_SGBUF */ + +static int sof_pcm_open(struct snd_soc_component *component, + struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_soc_component *component = - snd_soc_rtdcom_lookup(rtd, DRV_NAME); struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component); struct snd_sof_pcm *spcm; struct snd_soc_tplg_stream_caps *caps; @@ -505,11 +510,10 @@ static int sof_pcm_open(struct snd_pcm_substream *substream) return ret; } -static int sof_pcm_close(struct snd_pcm_substream *substream) +static int sof_pcm_close(struct snd_soc_component *component, + struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_component *component = - snd_soc_rtdcom_lookup(rtd, DRV_NAME); struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component); struct snd_sof_pcm *spcm; int err; @@ -538,27 +542,14 @@ static int sof_pcm_close(struct snd_pcm_substream *substream) return 0; } -static struct snd_pcm_ops sof_pcm_ops = { - .open = sof_pcm_open, - .close = sof_pcm_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = sof_pcm_hw_params, - .prepare = sof_pcm_prepare, - .hw_free = sof_pcm_hw_free, - .trigger = sof_pcm_trigger, - .pointer = sof_pcm_pointer, - .page = snd_pcm_sgbuf_ops_page, -}; - /* * Pre-allocate playback/capture audio buffer pages. * no need to explicitly release memory preallocated by sof_pcm_new in pcm_free * snd_pcm_lib_preallocate_free_for_all() is called by the core. */ -static int sof_pcm_new(struct snd_soc_pcm_runtime *rtd) +static int sof_pcm_new(struct snd_soc_component *component, + struct snd_soc_pcm_runtime *rtd) { - struct snd_soc_component *component = - snd_soc_rtdcom_lookup(rtd, DRV_NAME); struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component); struct snd_sof_pcm *spcm; struct snd_pcm *pcm = rtd->pcm; @@ -752,11 +743,20 @@ void snd_sof_new_platform_drv(struct snd_sof_dev *sdev) pd->name = "sof-audio-component"; pd->probe = sof_pcm_probe; pd->remove = sof_pcm_remove; - pd->ops = &sof_pcm_ops; + pd->open = sof_pcm_open; + pd->close = sof_pcm_close; + pd->ioctl = snd_soc_pcm_lib_ioctl; + pd->hw_params = sof_pcm_hw_params; + pd->prepare = sof_pcm_prepare; + pd->hw_free = sof_pcm_hw_free; + pd->trigger = sof_pcm_trigger; + pd->pointer = sof_pcm_pointer; + pd->page = sof_pcm_page; + #if IS_ENABLED(CONFIG_SND_SOC_SOF_COMPRESS) pd->compr_ops = &sof_compressed_ops; #endif - pd->pcm_new = sof_pcm_new; + pd->pcm_construct = sof_pcm_new; pd->ignore_machine = drv_name; pd->be_hw_params_fixup = sof_pcm_dai_link_fixup; pd->be_pcm_base = SOF_BE_PCM_BASE; -- cgit v1.2.3 From f3416e7144f5d4ba0fc5dcef6ebfff891266c46a Mon Sep 17 00:00:00 2001 From: Kai Vehmanen Date: Tue, 8 Oct 2019 11:44:35 -0500 Subject: ASoC: SOF: enable sync_write in hdac_bus Align SOF HDA implementation with snd-hda-intel driver and enable sync_write flag for all supported Intel platforms in SOF. When set, a sync is issued after each verb write. Sync after write has helped to overcome intermittent delays in system resume flow on Intel Coffee Lake systems, and most recently probe errors related to the HDMI codec on Ice Lake systems. Matches the snd-hda-intel driver change done in commit 2756d9143aa5 ("ALSA: hda - Fix intermittent CORB/RIRB stall on Intel chips"). Signed-off-by: Kai Vehmanen Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20191008164443.1358-2-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda.c | 1 + 1 file changed, 1 insertion(+) (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index 06e84679087b..5a5163eef2ef 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -268,6 +268,7 @@ static int hda_init(struct snd_sof_dev *sdev) bus->use_posbuf = 1; bus->bdl_pos_adj = 0; + bus->sync_write = 1; mutex_init(&hbus->prepare_mutex); hbus->pci = pci; -- cgit v1.2.3 From a68c6b6cc77b841dc37c17a5d9a7074e26801af5 Mon Sep 17 00:00:00 2001 From: Jaska Uimonen Date: Tue, 8 Oct 2019 11:44:41 -0500 Subject: ASoC: SOF: enable dual control for pga Currently sof pga element supports only 1 kcontrol and you can't create for example a mixer element with combined volume slider and mute switch. So enable sof pga to have more than 1 kcontrol associated with it. Also check for possible NULL tlv pointer as switch element might not have it. Signed-off-by: Jaska Uimonen Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20191008164443.1358-8-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/topology.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c index 0aabb3190ddc..a0b1c38e666b 100644 --- a/sound/soc/sof/topology.c +++ b/sound/soc/sof/topology.c @@ -1580,7 +1580,7 @@ static int sof_widget_load_pga(struct snd_soc_component *scomp, int index, if (!volume) return -ENOMEM; - if (le32_to_cpu(tw->num_kcontrols) != 1) { + if (!le32_to_cpu(tw->num_kcontrols)) { dev_err(sdev->dev, "error: invalid kcontrol count %d for volume\n", tw->num_kcontrols); ret = -EINVAL; @@ -1617,7 +1617,8 @@ static int sof_widget_load_pga(struct snd_soc_component *scomp, int index, swidget->private = volume; list_for_each_entry(scontrol, &sdev->kcontrol_list, list) { - if (scontrol->comp_id == swidget->comp_id) { + if (scontrol->comp_id == swidget->comp_id && + scontrol->volume_table) { min_step = scontrol->min_volume_step; max_step = scontrol->max_volume_step; volume->min_value = scontrol->volume_table[min_step]; -- cgit v1.2.3 From acf1b71cb693263c7c9373296e872a8fa61a5cf3 Mon Sep 17 00:00:00 2001 From: Jaska Uimonen Date: Tue, 8 Oct 2019 11:44:42 -0500 Subject: AsoC: SOF: refactor control load code Move code around to enable token parsing in control load. Signed-off-by: Jaska Uimonen Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20191008164443.1358-9-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/topology.c | 314 +++++++++++++++++++++++------------------------ 1 file changed, 157 insertions(+), 157 deletions(-) (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c index a0b1c38e666b..3918301c573b 100644 --- a/sound/soc/sof/topology.c +++ b/sound/soc/sof/topology.c @@ -432,163 +432,6 @@ static enum sof_comp_type find_process_comp_type(enum sof_ipc_process_type type) return SOF_COMP_NONE; } -/* - * Standard Kcontrols. - */ - -static int sof_control_load_volume(struct snd_soc_component *scomp, - struct snd_sof_control *scontrol, - struct snd_kcontrol_new *kc, - struct snd_soc_tplg_ctl_hdr *hdr) -{ - struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); - struct snd_soc_tplg_mixer_control *mc = - container_of(hdr, struct snd_soc_tplg_mixer_control, hdr); - struct sof_ipc_ctrl_data *cdata; - int tlv[TLV_ITEMS]; - unsigned int i; - int ret; - - /* validate topology data */ - if (le32_to_cpu(mc->num_channels) > SND_SOC_TPLG_MAX_CHAN) - return -EINVAL; - - /* init the volume get/put data */ - scontrol->size = struct_size(scontrol->control_data, chanv, - le32_to_cpu(mc->num_channels)); - scontrol->control_data = kzalloc(scontrol->size, GFP_KERNEL); - if (!scontrol->control_data) - return -ENOMEM; - - scontrol->comp_id = sdev->next_comp_id; - scontrol->min_volume_step = le32_to_cpu(mc->min); - scontrol->max_volume_step = le32_to_cpu(mc->max); - scontrol->num_channels = le32_to_cpu(mc->num_channels); - - /* set cmd for mixer control */ - if (le32_to_cpu(mc->max) == 1) { - scontrol->cmd = SOF_CTRL_CMD_SWITCH; - goto out; - } - - scontrol->cmd = SOF_CTRL_CMD_VOLUME; - - /* extract tlv data */ - if (get_tlv_data(kc->tlv.p, tlv) < 0) { - dev_err(sdev->dev, "error: invalid TLV data\n"); - return -EINVAL; - } - - /* set up volume table */ - ret = set_up_volume_table(scontrol, tlv, le32_to_cpu(mc->max) + 1); - if (ret < 0) { - dev_err(sdev->dev, "error: setting up volume table\n"); - return ret; - } - - /* set default volume values to 0dB in control */ - cdata = scontrol->control_data; - for (i = 0; i < scontrol->num_channels; i++) { - cdata->chanv[i].channel = i; - cdata->chanv[i].value = VOL_ZERO_DB; - } - -out: - dev_dbg(sdev->dev, "tplg: load kcontrol index %d chans %d\n", - scontrol->comp_id, scontrol->num_channels); - - return 0; -} - -static int sof_control_load_enum(struct snd_soc_component *scomp, - struct snd_sof_control *scontrol, - struct snd_kcontrol_new *kc, - struct snd_soc_tplg_ctl_hdr *hdr) -{ - struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); - struct snd_soc_tplg_enum_control *ec = - container_of(hdr, struct snd_soc_tplg_enum_control, hdr); - - /* validate topology data */ - if (le32_to_cpu(ec->num_channels) > SND_SOC_TPLG_MAX_CHAN) - return -EINVAL; - - /* init the enum get/put data */ - scontrol->size = struct_size(scontrol->control_data, chanv, - le32_to_cpu(ec->num_channels)); - scontrol->control_data = kzalloc(scontrol->size, GFP_KERNEL); - if (!scontrol->control_data) - return -ENOMEM; - - scontrol->comp_id = sdev->next_comp_id; - scontrol->num_channels = le32_to_cpu(ec->num_channels); - - scontrol->cmd = SOF_CTRL_CMD_ENUM; - - dev_dbg(sdev->dev, "tplg: load kcontrol index %d chans %d comp_id %d\n", - scontrol->comp_id, scontrol->num_channels, scontrol->comp_id); - - return 0; -} - -static int sof_control_load_bytes(struct snd_soc_component *scomp, - struct snd_sof_control *scontrol, - struct snd_kcontrol_new *kc, - struct snd_soc_tplg_ctl_hdr *hdr) -{ - struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); - struct sof_ipc_ctrl_data *cdata; - struct snd_soc_tplg_bytes_control *control = - container_of(hdr, struct snd_soc_tplg_bytes_control, hdr); - struct soc_bytes_ext *sbe = (struct soc_bytes_ext *)kc->private_value; - int max_size = sbe->max; - - if (le32_to_cpu(control->priv.size) > max_size) { - dev_err(sdev->dev, "err: bytes data size %d exceeds max %d.\n", - control->priv.size, max_size); - return -EINVAL; - } - - /* init the get/put bytes data */ - scontrol->size = sizeof(struct sof_ipc_ctrl_data) + - le32_to_cpu(control->priv.size); - scontrol->control_data = kzalloc(max_size, GFP_KERNEL); - cdata = scontrol->control_data; - if (!scontrol->control_data) - return -ENOMEM; - - scontrol->comp_id = sdev->next_comp_id; - scontrol->cmd = SOF_CTRL_CMD_BINARY; - - dev_dbg(sdev->dev, "tplg: load kcontrol index %d chans %d\n", - scontrol->comp_id, scontrol->num_channels); - - if (le32_to_cpu(control->priv.size) > 0) { - memcpy(cdata->data, control->priv.data, - le32_to_cpu(control->priv.size)); - - if (cdata->data->magic != SOF_ABI_MAGIC) { - dev_err(sdev->dev, "error: Wrong ABI magic 0x%08x.\n", - cdata->data->magic); - return -EINVAL; - } - if (SOF_ABI_VERSION_INCOMPATIBLE(SOF_ABI_VERSION, - cdata->data->abi)) { - dev_err(sdev->dev, - "error: Incompatible ABI version 0x%08x.\n", - cdata->data->abi); - return -EINVAL; - } - if (cdata->data->size + sizeof(const struct sof_abi_hdr) != - le32_to_cpu(control->priv.size)) { - dev_err(sdev->dev, - "error: Conflict in bytes vs. priv size.\n"); - return -EINVAL; - } - } - return 0; -} - /* * Topology Token Parsing. * New tokens should be added to headers and parsing tables below. @@ -1039,6 +882,163 @@ static void sof_dbg_comp_config(struct snd_soc_component *scomp, config->frame_fmt); } +/* + * Standard Kcontrols. + */ + +static int sof_control_load_volume(struct snd_soc_component *scomp, + struct snd_sof_control *scontrol, + struct snd_kcontrol_new *kc, + struct snd_soc_tplg_ctl_hdr *hdr) +{ + struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); + struct snd_soc_tplg_mixer_control *mc = + container_of(hdr, struct snd_soc_tplg_mixer_control, hdr); + struct sof_ipc_ctrl_data *cdata; + int tlv[TLV_ITEMS]; + unsigned int i; + int ret; + + /* validate topology data */ + if (le32_to_cpu(mc->num_channels) > SND_SOC_TPLG_MAX_CHAN) + return -EINVAL; + + /* init the volume get/put data */ + scontrol->size = struct_size(scontrol->control_data, chanv, + le32_to_cpu(mc->num_channels)); + scontrol->control_data = kzalloc(scontrol->size, GFP_KERNEL); + if (!scontrol->control_data) + return -ENOMEM; + + scontrol->comp_id = sdev->next_comp_id; + scontrol->min_volume_step = le32_to_cpu(mc->min); + scontrol->max_volume_step = le32_to_cpu(mc->max); + scontrol->num_channels = le32_to_cpu(mc->num_channels); + + /* set cmd for mixer control */ + if (le32_to_cpu(mc->max) == 1) { + scontrol->cmd = SOF_CTRL_CMD_SWITCH; + goto out; + } + + scontrol->cmd = SOF_CTRL_CMD_VOLUME; + + /* extract tlv data */ + if (get_tlv_data(kc->tlv.p, tlv) < 0) { + dev_err(sdev->dev, "error: invalid TLV data\n"); + return -EINVAL; + } + + /* set up volume table */ + ret = set_up_volume_table(scontrol, tlv, le32_to_cpu(mc->max) + 1); + if (ret < 0) { + dev_err(sdev->dev, "error: setting up volume table\n"); + return ret; + } + + /* set default volume values to 0dB in control */ + cdata = scontrol->control_data; + for (i = 0; i < scontrol->num_channels; i++) { + cdata->chanv[i].channel = i; + cdata->chanv[i].value = VOL_ZERO_DB; + } + +out: + dev_dbg(sdev->dev, "tplg: load kcontrol index %d chans %d\n", + scontrol->comp_id, scontrol->num_channels); + + return 0; +} + +static int sof_control_load_enum(struct snd_soc_component *scomp, + struct snd_sof_control *scontrol, + struct snd_kcontrol_new *kc, + struct snd_soc_tplg_ctl_hdr *hdr) +{ + struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); + struct snd_soc_tplg_enum_control *ec = + container_of(hdr, struct snd_soc_tplg_enum_control, hdr); + + /* validate topology data */ + if (le32_to_cpu(ec->num_channels) > SND_SOC_TPLG_MAX_CHAN) + return -EINVAL; + + /* init the enum get/put data */ + scontrol->size = struct_size(scontrol->control_data, chanv, + le32_to_cpu(ec->num_channels)); + scontrol->control_data = kzalloc(scontrol->size, GFP_KERNEL); + if (!scontrol->control_data) + return -ENOMEM; + + scontrol->comp_id = sdev->next_comp_id; + scontrol->num_channels = le32_to_cpu(ec->num_channels); + + scontrol->cmd = SOF_CTRL_CMD_ENUM; + + dev_dbg(sdev->dev, "tplg: load kcontrol index %d chans %d comp_id %d\n", + scontrol->comp_id, scontrol->num_channels, scontrol->comp_id); + + return 0; +} + +static int sof_control_load_bytes(struct snd_soc_component *scomp, + struct snd_sof_control *scontrol, + struct snd_kcontrol_new *kc, + struct snd_soc_tplg_ctl_hdr *hdr) +{ + struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); + struct sof_ipc_ctrl_data *cdata; + struct snd_soc_tplg_bytes_control *control = + container_of(hdr, struct snd_soc_tplg_bytes_control, hdr); + struct soc_bytes_ext *sbe = (struct soc_bytes_ext *)kc->private_value; + int max_size = sbe->max; + + if (le32_to_cpu(control->priv.size) > max_size) { + dev_err(sdev->dev, "err: bytes data size %d exceeds max %d.\n", + control->priv.size, max_size); + return -EINVAL; + } + + /* init the get/put bytes data */ + scontrol->size = sizeof(struct sof_ipc_ctrl_data) + + le32_to_cpu(control->priv.size); + scontrol->control_data = kzalloc(max_size, GFP_KERNEL); + cdata = scontrol->control_data; + if (!scontrol->control_data) + return -ENOMEM; + + scontrol->comp_id = sdev->next_comp_id; + scontrol->cmd = SOF_CTRL_CMD_BINARY; + + dev_dbg(sdev->dev, "tplg: load kcontrol index %d chans %d\n", + scontrol->comp_id, scontrol->num_channels); + + if (le32_to_cpu(control->priv.size) > 0) { + memcpy(cdata->data, control->priv.data, + le32_to_cpu(control->priv.size)); + + if (cdata->data->magic != SOF_ABI_MAGIC) { + dev_err(sdev->dev, "error: Wrong ABI magic 0x%08x.\n", + cdata->data->magic); + return -EINVAL; + } + if (SOF_ABI_VERSION_INCOMPATIBLE(SOF_ABI_VERSION, + cdata->data->abi)) { + dev_err(sdev->dev, + "error: Incompatible ABI version 0x%08x.\n", + cdata->data->abi); + return -EINVAL; + } + if (cdata->data->size + sizeof(const struct sof_abi_hdr) != + le32_to_cpu(control->priv.size)) { + dev_err(sdev->dev, + "error: Conflict in bytes vs. priv size.\n"); + return -EINVAL; + } + } + return 0; +} + /* external kcontrol init - used for any driver specific init */ static int sof_control_load(struct snd_soc_component *scomp, int index, struct snd_kcontrol_new *kc, -- cgit v1.2.3 From 902fd492d5ea2c02666ddadc1da977ca94e6b52c Mon Sep 17 00:00:00 2001 From: Kai Vehmanen Date: Tue, 8 Oct 2019 11:44:36 -0500 Subject: Revert "ASoC: SOF: Force polling mode on CFL and CNL" This reverts commit 64ca9d9fcb3e3c86b1417e3d17a90b43dd660f81. The workaround is no longer needed after configuring HDAC bus with sync_write=1. Signed-off-by: Kai Vehmanen Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20191008164443.1358-3-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda.c | 7 ------- 1 file changed, 7 deletions(-) (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index 5a5163eef2ef..103f4273c4d3 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -32,9 +32,6 @@ /* platform specific devices */ #include "shim.h" -#define IS_CFL(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0xa348) -#define IS_CNL(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0x9dc8) - #define EXCEPT_MAX_HDR_SIZE 0x400 /* @@ -262,10 +259,6 @@ static int hda_init(struct snd_sof_dev *sdev) /* HDA bus init */ sof_hda_bus_init(bus, &pci->dev); - /* Workaround for a communication error on CFL (bko#199007) and CNL */ - if (IS_CFL(pci) || IS_CNL(pci)) - bus->polling_mode = 1; - bus->use_posbuf = 1; bus->bdl_pos_adj = 0; bus->sync_write = 1; -- cgit v1.2.3 From 70b0c75ae1e3d35f829b5fe7ae5692efae63ca71 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 8 Oct 2019 11:44:37 -0500 Subject: ASoC: SOF: acpi: add debug module param Add debug parameter for snd-sof-acpi. One of the usages for this debug parameter to disable pm_runtime, which can be useful for platform bringup, or keep the parent device active while enabling pm_runtime for child devices (e.g. with SoundWire or MFD). This can also be useful to measure suspend-resume latencies or child devices. Signed-off-by: Kai Vehmanen Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20191008164443.1358-4-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/sof-acpi-dev.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/sof-acpi-dev.c b/sound/soc/sof/sof-acpi-dev.c index ea7b8b895412..df318f50dd0b 100644 --- a/sound/soc/sof/sof-acpi-dev.c +++ b/sound/soc/sof/sof-acpi-dev.c @@ -29,6 +29,12 @@ static char *tplg_path; module_param(tplg_path, charp, 0444); MODULE_PARM_DESC(tplg_path, "alternate path for SOF topology."); +static int sof_acpi_debug; +module_param_named(sof_acpi_debug, sof_acpi_debug, int, 0444); +MODULE_PARM_DESC(sof_acpi_debug, "SOF ACPI debug options (0x0 all off)"); + +#define SOF_ACPI_DISABLE_PM_RUNTIME BIT(0) + #if IS_ENABLED(CONFIG_SND_SOC_SOF_HASWELL) static const struct sof_dev_desc sof_acpi_haswell_desc = { .machines = snd_soc_acpi_intel_haswell_machines, @@ -121,6 +127,9 @@ static const struct dev_pm_ops sof_acpi_pm = { static void sof_acpi_probe_complete(struct device *dev) { + if (sof_acpi_debug & SOF_ACPI_DISABLE_PM_RUNTIME) + return; + /* allow runtime_pm */ pm_runtime_set_autosuspend_delay(dev, SND_SOF_SUSPEND_DELAY_MS); pm_runtime_use_autosuspend(dev); @@ -221,7 +230,8 @@ static int sof_acpi_probe(struct platform_device *pdev) static int sof_acpi_remove(struct platform_device *pdev) { - pm_runtime_disable(&pdev->dev); + if (!(sof_acpi_debug & SOF_ACPI_DISABLE_PM_RUNTIME)) + pm_runtime_disable(&pdev->dev); /* call sof helper for DSP hardware remove */ snd_sof_device_remove(&pdev->dev); -- cgit v1.2.3 From 8b160dc2a92c83a566b0596c79febb5933f9a6b5 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 8 Oct 2019 11:44:38 -0500 Subject: ASoC: SOF: pci: add debug module param Add debug parameter for snd-sof-pci. One of the usages for this debug parameter to disable pm_runtime, which can be useful for platform bringup, or keep the parent device active while enabling pm_runtime for child devices (e.g. with SoundWire or MFD). This can also be useful to measure suspend-resume latencies or child devices. Signed-off-by: Kai Vehmanen Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20191008164443.1358-5-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/sof-pci-dev.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/sof-pci-dev.c b/sound/soc/sof/sof-pci-dev.c index d66412a77873..030f2cb06921 100644 --- a/sound/soc/sof/sof-pci-dev.c +++ b/sound/soc/sof/sof-pci-dev.c @@ -29,6 +29,12 @@ static char *tplg_path; module_param(tplg_path, charp, 0444); MODULE_PARM_DESC(tplg_path, "alternate path for SOF topology."); +static int sof_pci_debug; +module_param_named(sof_pci_debug, sof_pci_debug, int, 0444); +MODULE_PARM_DESC(sof_pci_debug, "SOF PCI debug options (0x0 all off)"); + +#define SOF_PCI_DISABLE_PM_RUNTIME BIT(0) + #if IS_ENABLED(CONFIG_SND_SOC_SOF_APOLLOLAKE) static const struct sof_dev_desc bxt_desc = { .machines = snd_soc_acpi_intel_bxt_machines, @@ -249,6 +255,9 @@ static void sof_pci_probe_complete(struct device *dev) { dev_dbg(dev, "Completing SOF PCI probe"); + if (sof_pci_debug & SOF_PCI_DISABLE_PM_RUNTIME) + return; + /* allow runtime_pm */ pm_runtime_set_autosuspend_delay(dev, SND_SOF_SUSPEND_DELAY_MS); pm_runtime_use_autosuspend(dev); @@ -370,7 +379,8 @@ static void sof_pci_remove(struct pci_dev *pci) snd_sof_device_remove(&pci->dev); /* follow recommendation in pci-driver.c to increment usage counter */ - pm_runtime_get_noresume(&pci->dev); + if (!(sof_pci_debug & SOF_PCI_DISABLE_PM_RUNTIME)) + pm_runtime_get_noresume(&pci->dev); /* release pci regions and disable device */ pci_release_regions(pci); -- cgit v1.2.3 From 5d43001ae43606dc525f55c482c545afba01bb55 Mon Sep 17 00:00:00 2001 From: Jaska Uimonen Date: Tue, 8 Oct 2019 11:44:43 -0500 Subject: ASoC: SOF: acpi led support for switch controls Currently sof doesn't support acpi leds with mute switches. So implement acpi leds following quite shamelessly existing HDA implementation by Takashi Iwai. Mute leds can be enabled in topology by adding led and direction token in switch control private data. Signed-off-by: Jaska Uimonen Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20191008164443.1358-10-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- include/uapi/sound/sof/tokens.h | 4 ++++ sound/soc/sof/control.c | 32 ++++++++++++++++++++++++++++++++ sound/soc/sof/sof-priv.h | 9 +++++++++ sound/soc/sof/topology.c | 13 +++++++++++++ 4 files changed, 58 insertions(+) (limited to 'sound/soc/sof') diff --git a/include/uapi/sound/sof/tokens.h b/include/uapi/sound/sof/tokens.h index da18c9de1056..d65406f34361 100644 --- a/include/uapi/sound/sof/tokens.h +++ b/include/uapi/sound/sof/tokens.h @@ -113,4 +113,8 @@ /* ESAI */ #define SOF_TKN_IMX_ESAI_MCLK_ID 1100 +/* Led control for mute switches */ +#define SOF_TKN_MUTE_LED_USE 1300 +#define SOF_TKN_MUTE_LED_DIRECTION 1301 + #endif diff --git a/sound/soc/sof/control.c b/sound/soc/sof/control.c index a4983f90ff5b..41551e8f6ac3 100644 --- a/sound/soc/sof/control.c +++ b/sound/soc/sof/control.c @@ -11,8 +11,37 @@ /* Mixer Controls */ #include +#include #include "sof-priv.h" +static void update_mute_led(struct snd_sof_control *scontrol, + struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + unsigned int temp = 0; + unsigned int mask; + int i; + + mask = 1U << snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); + + for (i = 0; i < scontrol->num_channels; i++) { + if (ucontrol->value.integer.value[i]) { + temp |= mask; + break; + } + } + + if (temp == scontrol->led_ctl.led_value) + return; + + scontrol->led_ctl.led_value = temp; + + if (!scontrol->led_ctl.direction) + ledtrig_audio_set(LED_AUDIO_MUTE, temp ? LED_OFF : LED_ON); + else + ledtrig_audio_set(LED_AUDIO_MICMUTE, temp ? LED_OFF : LED_ON); +} + static inline u32 mixer_to_ipc(unsigned int value, u32 *volume_map, int size) { if (value >= size) @@ -112,6 +141,9 @@ int snd_sof_switch_put(struct snd_kcontrol *kcontrol, cdata->chanv[i].channel = i; } + if (scontrol->led_ctl.use_led) + update_mute_led(scontrol, kcontrol, ucontrol); + /* notify DSP of mixer updates */ if (pm_runtime_active(sdev->dev)) snd_sof_ipc_set_get_comp_data(sdev->ipc, scontrol, diff --git a/sound/soc/sof/sof-priv.h b/sound/soc/sof/sof-priv.h index 44f789bf7fb0..5a11a8517fa5 100644 --- a/sound/soc/sof/sof-priv.h +++ b/sound/soc/sof/sof-priv.h @@ -15,6 +15,7 @@ #include #include +#include #include #include /* needs to be included before control.h */ @@ -310,6 +311,12 @@ struct snd_sof_pcm { bool prepared[2]; /* PCM_PARAMS set successfully */ }; +struct snd_sof_led_control { + unsigned int use_led; + unsigned int direction; + unsigned int led_value; +}; + /* ALSA SOF Kcontrol device */ struct snd_sof_control { struct snd_sof_dev *sdev; @@ -324,6 +331,8 @@ struct snd_sof_control { u32 *volume_table; /* volume table computed from tlv data*/ struct list_head list; /* list in sdev control list */ + + struct snd_sof_led_control led_ctl; }; /* ASoC SOF DAPM widget */ diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c index 3918301c573b..2e5fab1cfbb4 100644 --- a/sound/soc/sof/topology.c +++ b/sound/soc/sof/topology.c @@ -682,6 +682,14 @@ static const struct sof_topology_token dmic_pdm_tokens[] = { static const struct sof_topology_token hda_tokens[] = { }; +/* Leds */ +static const struct sof_topology_token led_tokens[] = { + {SOF_TKN_MUTE_LED_USE, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, + offsetof(struct snd_sof_led_control, use_led), 0}, + {SOF_TKN_MUTE_LED_DIRECTION, SND_SOC_TPLG_TUPLE_TYPE_WORD, + get_token_u32, offsetof(struct snd_sof_led_control, direction), 0}, +}; + static void sof_parse_uuid_tokens(struct snd_soc_component *scomp, void *object, const struct sof_topology_token *tokens, @@ -944,6 +952,11 @@ static int sof_control_load_volume(struct snd_soc_component *scomp, } out: + /* set up possible led control from mixer private data */ + ret = sof_parse_tokens(scomp, &scontrol->led_ctl, led_tokens, + ARRAY_SIZE(led_tokens), mc->priv.array, + le32_to_cpu(mc->priv.size)); + dev_dbg(sdev->dev, "tplg: load kcontrol index %d chans %d\n", scontrol->comp_id, scontrol->num_channels); -- cgit v1.2.3 From a4eff5f86c9c5e7d07d880bd86ce8faad19d7063 Mon Sep 17 00:00:00 2001 From: Daniel Baluta Date: Tue, 8 Oct 2019 11:44:40 -0500 Subject: ASoC: SOF: imx: Read ESAI parameters and send them to DSP ESAI parameters are read for topology file, packed into sof_ipc_dai_esai_parms struct and then sent to DSP. Signed-off-by: Daniel Baluta Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20191008164443.1358-7-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/pcm.c | 8 ++++++ sound/soc/sof/topology.c | 69 ++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 75 insertions(+), 2 deletions(-) (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/pcm.c b/sound/soc/sof/pcm.c index 6490b1577152..d72798d2b302 100644 --- a/sound/soc/sof/pcm.c +++ b/sound/soc/sof/pcm.c @@ -682,6 +682,14 @@ static int sof_pcm_dai_link_fixup(struct snd_soc_pcm_runtime *rtd, case SOF_DAI_INTEL_ALH: /* do nothing for ALH dai_link */ break; + case SOF_DAI_IMX_ESAI: + channels->min = dai->dai_config->esai.tdm_slots; + channels->max = dai->dai_config->esai.tdm_slots; + + dev_dbg(sdev->dev, + "channels_min: %d channels_max: %d\n", + channels->min, channels->max); + break; default: dev_err(sdev->dev, "error: invalid DAI type %d\n", dai->dai_config->type); diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c index 2e5fab1cfbb4..a29109ea3c06 100644 --- a/sound/soc/sof/topology.c +++ b/sound/soc/sof/topology.c @@ -641,6 +641,13 @@ static const struct sof_topology_token dmic_tokens[] = { }; +/* ESAI */ +static const struct sof_topology_token esai_tokens[] = { + {SOF_TKN_IMX_ESAI_MCLK_ID, + SND_SOC_TPLG_TUPLE_TYPE_SHORT, get_token_u16, + offsetof(struct sof_ipc_dai_esai_params, mclk_id), 0}, +}; + /* * DMIC PDM Tokens * SOF_TKN_INTEL_DMIC_PDM_CTRL_ID should be the first token @@ -2549,8 +2556,66 @@ static int sof_link_esai_load(struct snd_soc_component *scomp, int index, struct snd_soc_tplg_hw_config *hw_config, struct sof_ipc_dai_config *config) { - /*TODO: Add implementation */ - return 0; + struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); + struct snd_soc_tplg_private *private = &cfg->priv; + struct sof_ipc_reply reply; + u32 size = sizeof(*config); + int ret; + + /* handle master/slave and inverted clocks */ + sof_dai_set_format(hw_config, config); + + /* init IPC */ + memset(&config->esai, 0, sizeof(struct sof_ipc_dai_esai_params)); + config->hdr.size = size; + + ret = sof_parse_tokens(scomp, &config->esai, esai_tokens, + ARRAY_SIZE(esai_tokens), private->array, + le32_to_cpu(private->size)); + if (ret != 0) { + dev_err(sdev->dev, "error: parse esai tokens failed %d\n", + le32_to_cpu(private->size)); + return ret; + } + + config->esai.mclk_rate = le32_to_cpu(hw_config->mclk_rate); + config->esai.bclk_rate = le32_to_cpu(hw_config->bclk_rate); + config->esai.fsync_rate = le32_to_cpu(hw_config->fsync_rate); + config->esai.mclk_direction = hw_config->mclk_direction; + config->esai.tdm_slots = le32_to_cpu(hw_config->tdm_slots); + config->esai.tdm_slot_width = le32_to_cpu(hw_config->tdm_slot_width); + config->esai.rx_slots = le32_to_cpu(hw_config->rx_slots); + config->esai.tx_slots = le32_to_cpu(hw_config->tx_slots); + + dev_info(sdev->dev, + "tplg: config ESAI%d fmt 0x%x mclk %d width %d slots %d mclk id %d\n", + config->dai_index, config->format, + config->esai.mclk_rate, config->esai.tdm_slot_width, + config->esai.tdm_slots, config->esai.mclk_id); + + if (config->esai.tdm_slots < 1 || config->esai.tdm_slots > 8) { + dev_err(sdev->dev, "error: invalid channel count for ESAI%d\n", + config->dai_index); + return -EINVAL; + } + + /* send message to DSP */ + ret = sof_ipc_tx_message(sdev->ipc, + config->hdr.cmd, config, size, &reply, + sizeof(reply)); + if (ret < 0) { + dev_err(sdev->dev, "error: failed to set DAI config for ESAI%d\n", + config->dai_index); + return ret; + } + + /* set config for all DAI's with name matching the link name */ + ret = sof_set_dai_config(sdev, size, link, config); + if (ret < 0) + dev_err(sdev->dev, "error: failed to save DAI config for ESAI%d\n", + config->dai_index); + + return ret; } static int sof_link_dmic_load(struct snd_soc_component *scomp, int index, -- cgit v1.2.3 From f9f618e7128e834db3f54d290a926c4a71104e02 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 11 Oct 2019 11:43:09 -0500 Subject: ASoC: SOF: Intel: byt: fix operator precedence warnings Address cppcheck warnings sound/soc/sof/intel/byt.c:163:26: style: Clarify calculation precedence for '&' and '?'. [clarifyCalculation] panic & SHIM_IPCX_BUSY ? "yes" : "no", ^ sound/soc/sof/intel/byt.c:164:26: style: Clarify calculation precedence for '&' and '?'. [clarifyCalculation] panic & SHIM_IPCX_DONE ? "yes" : "no", panic); ^ sound/soc/sof/intel/byt.c:167:25: style: Clarify calculation precedence for '&' and '?'. [clarifyCalculation] imrx & SHIM_IMRX_BUSY ? "yes" : "no", ^ sound/soc/sof/intel/byt.c:168:25: style: Clarify calculation precedence for '&' and '?'. [clarifyCalculation] imrx & SHIM_IMRX_DONE ? "yes" : "no", imrx); ^ sound/soc/sof/intel/byt.c:171:27: style: Clarify calculation precedence for '&' and '?'. [clarifyCalculation] status & SHIM_IPCD_BUSY ? "yes" : "no", ^ sound/soc/sof/intel/byt.c:172:27: style: Clarify calculation precedence for '&' and '?'. [clarifyCalculation] status & SHIM_IPCD_DONE ? "yes" : "no", status); ^ sound/soc/sof/intel/byt.c:175:25: style: Clarify calculation precedence for '&' and '?'. [clarifyCalculation] imrd & SHIM_IMRD_BUSY ? "yes" : "no", ^ sound/soc/sof/intel/byt.c:176:25: style: Clarify calculation precedence for '&' and '?'. [clarifyCalculation] imrd & SHIM_IMRD_DONE ? "yes" : "no", imrd); ^ Fixes: 3a9e204d4e369 ("ASoC: SOF: Intel: Add context data to any IPC timeout.") Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20191011164312.7988-2-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/byt.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/intel/byt.c b/sound/soc/sof/intel/byt.c index b2597ecfdc1c..07e5efe4945c 100644 --- a/sound/soc/sof/intel/byt.c +++ b/sound/soc/sof/intel/byt.c @@ -160,20 +160,20 @@ static void byt_dump(struct snd_sof_dev *sdev, u32 flags) imrd = snd_sof_dsp_read(sdev, BYT_DSP_BAR, SHIM_IMRD); dev_err(sdev->dev, "error: ipc host -> DSP: pending %s complete %s raw 0x%8.8x\n", - panic & SHIM_IPCX_BUSY ? "yes" : "no", - panic & SHIM_IPCX_DONE ? "yes" : "no", panic); + (panic & SHIM_IPCX_BUSY) ? "yes" : "no", + (panic & SHIM_IPCX_DONE) ? "yes" : "no", panic); dev_err(sdev->dev, "error: mask host: pending %s complete %s raw 0x%8.8x\n", - imrx & SHIM_IMRX_BUSY ? "yes" : "no", - imrx & SHIM_IMRX_DONE ? "yes" : "no", imrx); + (imrx & SHIM_IMRX_BUSY) ? "yes" : "no", + (imrx & SHIM_IMRX_DONE) ? "yes" : "no", imrx); dev_err(sdev->dev, "error: ipc DSP -> host: pending %s complete %s raw 0x%8.8x\n", - status & SHIM_IPCD_BUSY ? "yes" : "no", - status & SHIM_IPCD_DONE ? "yes" : "no", status); + (status & SHIM_IPCD_BUSY) ? "yes" : "no", + (status & SHIM_IPCD_DONE) ? "yes" : "no", status); dev_err(sdev->dev, "error: mask DSP: pending %s complete %s raw 0x%8.8x\n", - imrd & SHIM_IMRD_BUSY ? "yes" : "no", - imrd & SHIM_IMRD_DONE ? "yes" : "no", imrd); + (imrd & SHIM_IMRD_BUSY) ? "yes" : "no", + (imrd & SHIM_IMRD_DONE) ? "yes" : "no", imrd); } -- cgit v1.2.3 From 7ad03a2c848f6fb0a8dea656c9c161929696878e Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 11 Oct 2019 11:43:10 -0500 Subject: ASoC: SOF: Intel: bdw: fix operator precedence warnings Address cppcheck warnings sound/soc/sof/intel/bdw.c:265:26: style: Clarify calculation precedence for '&' and '?'. [clarifyCalculation] panic & SHIM_IPCX_BUSY ? "yes" : "no", ^ sound/soc/sof/intel/bdw.c:266:26: style: Clarify calculation precedence for '&' and '?'. [clarifyCalculation] panic & SHIM_IPCX_DONE ? "yes" : "no", panic); ^ sound/soc/sof/intel/bdw.c:269:25: style: Clarify calculation precedence for '&' and '?'. [clarifyCalculation] imrx & SHIM_IMRX_BUSY ? "yes" : "no", ^ sound/soc/sof/intel/bdw.c:270:25: style: Clarify calculation precedence for '&' and '?'. [clarifyCalculation] imrx & SHIM_IMRX_DONE ? "yes" : "no", imrx); ^ sound/soc/sof/intel/bdw.c:273:27: style: Clarify calculation precedence for '&' and '?'. [clarifyCalculation] status & SHIM_IPCD_BUSY ? "yes" : "no", ^ sound/soc/sof/intel/bdw.c:274:27: style: Clarify calculation precedence for '&' and '?'. [clarifyCalculation] status & SHIM_IPCD_DONE ? "yes" : "no", status); ^ sound/soc/sof/intel/bdw.c:277:25: style: Clarify calculation precedence for '&' and '?'. [clarifyCalculation] imrd & SHIM_IMRD_BUSY ? "yes" : "no", ^ sound/soc/sof/intel/bdw.c:278:25: style: Clarify calculation precedence for '&' and '?'. [clarifyCalculation] imrd & SHIM_IMRD_DONE ? "yes" : "no", imrd); ^ Fixes: 3a9e204d4e369 ("ASoC: SOF: Intel: Add context data to any IPC timeout.") Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20191011164312.7988-3-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/bdw.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/intel/bdw.c b/sound/soc/sof/intel/bdw.c index f395d0638876..bf961a8798a7 100644 --- a/sound/soc/sof/intel/bdw.c +++ b/sound/soc/sof/intel/bdw.c @@ -262,20 +262,20 @@ static void bdw_dump(struct snd_sof_dev *sdev, u32 flags) imrd = snd_sof_dsp_read(sdev, BDW_DSP_BAR, SHIM_IMRD); dev_err(sdev->dev, "error: ipc host -> DSP: pending %s complete %s raw 0x%8.8x\n", - panic & SHIM_IPCX_BUSY ? "yes" : "no", - panic & SHIM_IPCX_DONE ? "yes" : "no", panic); + (panic & SHIM_IPCX_BUSY) ? "yes" : "no", + (panic & SHIM_IPCX_DONE) ? "yes" : "no", panic); dev_err(sdev->dev, "error: mask host: pending %s complete %s raw 0x%8.8x\n", - imrx & SHIM_IMRX_BUSY ? "yes" : "no", - imrx & SHIM_IMRX_DONE ? "yes" : "no", imrx); + (imrx & SHIM_IMRX_BUSY) ? "yes" : "no", + (imrx & SHIM_IMRX_DONE) ? "yes" : "no", imrx); dev_err(sdev->dev, "error: ipc DSP -> host: pending %s complete %s raw 0x%8.8x\n", - status & SHIM_IPCD_BUSY ? "yes" : "no", - status & SHIM_IPCD_DONE ? "yes" : "no", status); + (status & SHIM_IPCD_BUSY) ? "yes" : "no", + (status & SHIM_IPCD_DONE) ? "yes" : "no", status); dev_err(sdev->dev, "error: mask DSP: pending %s complete %s raw 0x%8.8x\n", - imrd & SHIM_IMRD_BUSY ? "yes" : "no", - imrd & SHIM_IMRD_DONE ? "yes" : "no", imrd); + (imrd & SHIM_IMRD_BUSY) ? "yes" : "no", + (imrd & SHIM_IMRD_DONE) ? "yes" : "no", imrd); } /* -- cgit v1.2.3 From 494e8f65da24d550a5e7c6a85b9433ffb181705c Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 11 Oct 2019 11:43:11 -0500 Subject: ASoC: SOF: topology: remove always-true redundant test Address cppcheck warning: sound/soc/sof/topology.c:2322:6: style: Condition 'pcm' is always true [knownConditionTrueFalse] if (pcm) { ^ sound/soc/sof/topology.c:2311:6: note: Assuming that condition '!pcm' is not redundant if (!pcm) ^ sound/soc/sof/topology.c:2322:6: note: Condition 'pcm' is always true if (pcm) { ^ Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20191011164312.7988-4-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/topology.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c index a29109ea3c06..3fad1d5cb2ca 100644 --- a/sound/soc/sof/topology.c +++ b/sound/soc/sof/topology.c @@ -2308,10 +2308,9 @@ static int sof_dai_load(struct snd_soc_component *scomp, int index, spcm->stream[SNDRV_PCM_STREAM_PLAYBACK].comp_id = COMP_ID_UNASSIGNED; spcm->stream[SNDRV_PCM_STREAM_CAPTURE].comp_id = COMP_ID_UNASSIGNED; - if (pcm) { - spcm->pcm = *pcm; - dev_dbg(sdev->dev, "tplg: load pcm %s\n", pcm->dai_name); - } + spcm->pcm = *pcm; + dev_dbg(sdev->dev, "tplg: load pcm %s\n", pcm->dai_name); + dai_drv->dobj.private = spcm; list_add(&spcm->list, &sdev->pcm_list); -- cgit v1.2.3 From 8a3ab38c36926ddbda3d2a3086c0a741fa175cff Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 11 Oct 2019 11:43:12 -0500 Subject: ASoC: SOF: topology: check errors when parsing LED tokens sof_parse_tokens() returns a value that is checked on every call except for LED tokens, fix with explicit test. Detected with cppcheck warning: sound/soc/sof/topology.c:973:6: style: Variable 'ret' is assigned a value that is never used. [unreadVariable] ret = sof_parse_tokens(scomp, &scontrol->led_ctl, led_tokens, ^ Fixes: 5d43001ae4360 ("ASoC: SOF: acpi led support for switch controls") Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20191011164312.7988-5-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/topology.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c index 3fad1d5cb2ca..b3ab6f23fc93 100644 --- a/sound/soc/sof/topology.c +++ b/sound/soc/sof/topology.c @@ -963,6 +963,11 @@ out: ret = sof_parse_tokens(scomp, &scontrol->led_ctl, led_tokens, ARRAY_SIZE(led_tokens), mc->priv.array, le32_to_cpu(mc->priv.size)); + if (ret != 0) { + dev_err(sdev->dev, "error: parse led tokens failed %d\n", + le32_to_cpu(mc->priv.size)); + return ret; + } dev_dbg(sdev->dev, "tplg: load kcontrol index %d chans %d\n", scontrol->comp_id, scontrol->num_channels); -- cgit v1.2.3 From 9899a7a869935c4c93247b290ac7a70e0deab202 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Mon, 14 Oct 2019 17:13:08 +0800 Subject: ASoC: SOF: Fix randbuild error When LEDS_TRIGGER_AUDIO is m and SND_SOC_SOF is y, sound/soc/sof/control.o: In function `snd_sof_switch_put': control.c:(.text+0x587): undefined reference to `ledtrig_audio_set' control.c:(.text+0x593): undefined reference to `ledtrig_audio_set' Reported-by: Hulk Robot Fixes: 5d43001ae436 ("ASoC: SOF: acpi led support for switch controls") Signed-off-by: YueHaibing Acked-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20191014091308.23688-1-yuehaibing@huawei.com Signed-off-by: Mark Brown --- sound/soc/sof/control.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/control.c b/sound/soc/sof/control.c index 41551e8f6ac3..2c4abd406c4f 100644 --- a/sound/soc/sof/control.c +++ b/sound/soc/sof/control.c @@ -36,10 +36,12 @@ static void update_mute_led(struct snd_sof_control *scontrol, scontrol->led_ctl.led_value = temp; +#if IS_REACHABLE(CONFIG_LEDS_TRIGGER_AUDIO) if (!scontrol->led_ctl.direction) ledtrig_audio_set(LED_AUDIO_MUTE, temp ? LED_OFF : LED_ON); else ledtrig_audio_set(LED_AUDIO_MICMUTE, temp ? LED_OFF : LED_ON); +#endif } static inline u32 mixer_to_ipc(unsigned int value, u32 *volume_map, int size) -- cgit v1.2.3 From 76dc6a2b312d15c91ff4b4d171e98cdc73ba3745 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 22 Oct 2019 14:28:43 -0500 Subject: ASoC: SOF: Intel: hda-loader: improve error handling If a ROM timeout is detected, we still stop the DMA but will return the initial error should the DMA stop also fail. Likewise the cleanup is handled regardless of the status, but we return the initial error. Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20191022192844.21022-2-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-loader.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/intel/hda-loader.c b/sound/soc/sof/intel/hda-loader.c index 65c2af3fcaab..7956dbf5be88 100644 --- a/sound/soc/sof/intel/hda-loader.c +++ b/sound/soc/sof/intel/hda-loader.c @@ -253,10 +253,16 @@ static int cl_copy_fw(struct snd_sof_dev *sdev, struct hdac_ext_stream *stream) HDA_DSP_REG_POLL_INTERVAL_US, HDA_DSP_BASEFW_TIMEOUT_US); + /* + * even in case of errors we still need to stop the DMAs, + * but we return the initial error should the DMA stop also fail + */ + ret = cl_trigger(sdev, stream, SNDRV_PCM_TRIGGER_STOP); if (ret < 0) { dev_err(sdev->dev, "error: DMA trigger stop failed\n"); - return ret; + if (!status) + status = ret; } return status; @@ -341,13 +347,15 @@ cleanup: /* * Perform codeloader stream cleanup. * This should be done even if firmware loading fails. + * If the cleanup also fails, we return the initial error */ ret1 = cl_cleanup(sdev, &sdev->dmab, stream); if (ret1 < 0) { dev_err(sdev->dev, "error: Code loader DSP cleanup failed\n"); /* set return value to indicate cleanup failure */ - ret = ret1; + if (!ret) + ret = ret1; } /* -- cgit v1.2.3 From 6a414489e0f3309a221f26b3d11c19d1a96a3635 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 22 Oct 2019 14:28:44 -0500 Subject: ASoC: SOF: Intel: hda: add dev_err() traces for snd_sof_dsp_read_poll_timeout() Such traces should be extremely rare but extremely useful for debug. Report errors for all calls to sdn_sof_dsp_read_poll_timeout(), but only on negative values for consistency. Add traces that enable each timeout to be uniquely identified. Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20191022192844.21022-3-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-dsp.c | 30 +++++++++++++++++++++++++++--- sound/soc/sof/intel/hda-loader.c | 13 ++++++++++++- sound/soc/sof/intel/hda-stream.c | 24 ++++++++++++++++++++---- 3 files changed, 59 insertions(+), 8 deletions(-) (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/intel/hda-dsp.c b/sound/soc/sof/intel/hda-dsp.c index fb55a3c5afd0..3ea401646e0c 100644 --- a/sound/soc/sof/intel/hda-dsp.c +++ b/sound/soc/sof/intel/hda-dsp.c @@ -42,6 +42,12 @@ int hda_dsp_core_reset_enter(struct snd_sof_dev *sdev, unsigned int core_mask) ((adspcs & reset) == reset), HDA_DSP_REG_POLL_INTERVAL_US, HDA_DSP_RESET_TIMEOUT_US); + if (ret < 0) { + dev_err(sdev->dev, + "error: %s: timeout on HDA_DSP_REG_ADSPCS read\n", + __func__); + return ret; + } /* has core entered reset ? */ adspcs = snd_sof_dsp_read(sdev, HDA_DSP_BAR, @@ -77,6 +83,13 @@ int hda_dsp_core_reset_leave(struct snd_sof_dev *sdev, unsigned int core_mask) HDA_DSP_REG_POLL_INTERVAL_US, HDA_DSP_RESET_TIMEOUT_US); + if (ret < 0) { + dev_err(sdev->dev, + "error: %s: timeout on HDA_DSP_REG_ADSPCS read\n", + __func__); + return ret; + } + /* has core left reset ? */ adspcs = snd_sof_dsp_read(sdev, HDA_DSP_BAR, HDA_DSP_REG_ADSPCS); @@ -151,8 +164,12 @@ int hda_dsp_core_power_up(struct snd_sof_dev *sdev, unsigned int core_mask) (adspcs & cpa) == cpa, HDA_DSP_REG_POLL_INTERVAL_US, HDA_DSP_RESET_TIMEOUT_US); - if (ret < 0) - dev_err(sdev->dev, "error: timeout on core powerup\n"); + if (ret < 0) { + dev_err(sdev->dev, + "error: %s: timeout on HDA_DSP_REG_ADSPCS read\n", + __func__); + return ret; + } /* did core power up ? */ adspcs = snd_sof_dsp_read(sdev, HDA_DSP_BAR, @@ -171,17 +188,24 @@ int hda_dsp_core_power_up(struct snd_sof_dev *sdev, unsigned int core_mask) int hda_dsp_core_power_down(struct snd_sof_dev *sdev, unsigned int core_mask) { u32 adspcs; + int ret; /* update bits */ snd_sof_dsp_update_bits_unlocked(sdev, HDA_DSP_BAR, HDA_DSP_REG_ADSPCS, HDA_DSP_ADSPCS_SPA_MASK(core_mask), 0); - return snd_sof_dsp_read_poll_timeout(sdev, HDA_DSP_BAR, + ret = snd_sof_dsp_read_poll_timeout(sdev, HDA_DSP_BAR, HDA_DSP_REG_ADSPCS, adspcs, !(adspcs & HDA_DSP_ADSPCS_SPA_MASK(core_mask)), HDA_DSP_REG_POLL_INTERVAL_US, HDA_DSP_PD_TIMEOUT * USEC_PER_MSEC); + if (ret < 0) + dev_err(sdev->dev, + "error: %s: timeout on HDA_DSP_REG_ADSPCS read\n", + __func__); + + return ret; } bool hda_dsp_core_is_enabled(struct snd_sof_dev *sdev, diff --git a/sound/soc/sof/intel/hda-loader.c b/sound/soc/sof/intel/hda-loader.c index 7956dbf5be88..b1783360fe10 100644 --- a/sound/soc/sof/intel/hda-loader.c +++ b/sound/soc/sof/intel/hda-loader.c @@ -126,7 +126,8 @@ static int cl_dsp_init(struct snd_sof_dev *sdev, const void *fwdata, HDA_DSP_INIT_TIMEOUT_US); if (ret < 0) { - dev_err(sdev->dev, "error: waiting for HIPCIE done\n"); + dev_err(sdev->dev, "error: %s: timeout for HIPCIE done\n", + __func__); goto err; } @@ -152,6 +153,10 @@ static int cl_dsp_init(struct snd_sof_dev *sdev, const void *fwdata, if (!ret) return 0; + dev_err(sdev->dev, + "error: %s: timeout HDA_DSP_SRAM_REG_ROM_STATUS read\n", + __func__); + err: hda_dsp_dump(sdev, SOF_DBG_REGS | SOF_DBG_PCI | SOF_DBG_MBOX); hda_dsp_core_reset_power_down(sdev, chip->cores_mask); @@ -258,6 +263,12 @@ static int cl_copy_fw(struct snd_sof_dev *sdev, struct hdac_ext_stream *stream) * but we return the initial error should the DMA stop also fail */ + if (status < 0) { + dev_err(sdev->dev, + "error: %s: timeout HDA_DSP_SRAM_REG_ROM_STATUS read\n", + __func__); + } + ret = cl_trigger(sdev, stream, SNDRV_PCM_TRIGGER_STOP); if (ret < 0) { dev_err(sdev->dev, "error: DMA trigger stop failed\n"); diff --git a/sound/soc/sof/intel/hda-stream.c b/sound/soc/sof/intel/hda-stream.c index 2c7447188402..450f9c55785f 100644 --- a/sound/soc/sof/intel/hda-stream.c +++ b/sound/soc/sof/intel/hda-stream.c @@ -275,8 +275,12 @@ int hda_dsp_stream_trigger(struct snd_sof_dev *sdev, HDA_DSP_REG_POLL_INTERVAL_US, HDA_DSP_STREAM_RUN_TIMEOUT); - if (ret) + if (ret < 0) { + dev_err(sdev->dev, + "error: %s: cmd %d: timeout on STREAM_SD_OFFSET read\n", + __func__, cmd); return ret; + } hstream->running = true; break; @@ -294,8 +298,12 @@ int hda_dsp_stream_trigger(struct snd_sof_dev *sdev, HDA_DSP_REG_POLL_INTERVAL_US, HDA_DSP_STREAM_RUN_TIMEOUT); - if (ret) + if (ret < 0) { + dev_err(sdev->dev, + "error: %s: cmd %d: timeout on STREAM_SD_OFFSET read\n", + __func__, cmd); return ret; + } snd_sof_dsp_write(sdev, HDA_DSP_HDA_BAR, sd_offset + SOF_HDA_ADSP_REG_CL_SD_STS, @@ -356,8 +364,12 @@ int hda_dsp_stream_hw_params(struct snd_sof_dev *sdev, HDA_DSP_REG_POLL_INTERVAL_US, HDA_DSP_STREAM_RUN_TIMEOUT); - if (ret) + if (ret < 0) { + dev_err(sdev->dev, + "error: %s: timeout on STREAM_SD_OFFSET read1\n", + __func__); return ret; + } snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, sd_offset + SOF_HDA_ADSP_REG_CL_SD_STS, @@ -418,8 +430,12 @@ int hda_dsp_stream_hw_params(struct snd_sof_dev *sdev, HDA_DSP_REG_POLL_INTERVAL_US, HDA_DSP_STREAM_RUN_TIMEOUT); - if (ret) + if (ret < 0) { + dev_err(sdev->dev, + "error: %s: timeout on STREAM_SD_OFFSET read2\n", + __func__); return ret; + } snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, sd_offset + SOF_HDA_ADSP_REG_CL_SD_STS, -- cgit v1.2.3 From 6fd9903527bf103167004022a0199b8fac1b8b29 Mon Sep 17 00:00:00 2001 From: Pan Xiuli Date: Tue, 22 Oct 2019 14:47:05 -0500 Subject: ASoC: SOF: Intel: initial support to JasperLake. Add Kconfig, PCI ID and chip info for JSL platform. The DSP only has 2 cores for this platform. Signed-off-by: Pan Xiuli Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20191022194705.23347-3-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/Kconfig | 16 ++++++++++++++++ sound/soc/sof/intel/cnl.c | 17 +++++++++++++++++ sound/soc/sof/intel/hda.h | 1 + sound/soc/sof/sof-pci-dev.c | 22 ++++++++++++++++++++++ 4 files changed, 56 insertions(+) (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/intel/Kconfig b/sound/soc/sof/intel/Kconfig index d62f51d33be1..342f22a7c64f 100644 --- a/sound/soc/sof/intel/Kconfig +++ b/sound/soc/sof/intel/Kconfig @@ -29,6 +29,7 @@ config SND_SOC_SOF_INTEL_PCI select SND_SOC_SOF_COMETLAKE_H if SND_SOC_SOF_COMETLAKE_H_SUPPORT select SND_SOC_SOF_TIGERLAKE if SND_SOC_SOF_TIGERLAKE_SUPPORT select SND_SOC_SOF_ELKHARTLAKE if SND_SOC_SOF_ELKHARTLAKE_SUPPORT + select SND_SOC_SOF_JASPERLAKE if SND_SOC_SOF_JASPERLAKE_SUPPORT help This option is not user-selectable but automagically handled by 'select' statements at a higher level @@ -244,6 +245,21 @@ config SND_SOC_SOF_ELKHARTLAKE This option is not user-selectable but automagically handled by 'select' statements at a higher level +config SND_SOC_SOF_JASPERLAKE_SUPPORT + bool "SOF support for JasperLake" + help + This adds support for Sound Open Firmware for Intel(R) platforms + using the JasperLake processors. + Say Y if you have such a device. + If unsure select "N". + +config SND_SOC_SOF_JASPERLAKE + tristate + select SND_SOC_SOF_HDA_COMMON + help + This option is not user-selectable but automagically handled by + 'select' statements at a higher level + config SND_SOC_SOF_HDA_COMMON tristate select SND_SOC_SOF_INTEL_COMMON diff --git a/sound/soc/sof/intel/cnl.c b/sound/soc/sof/intel/cnl.c index 4ddd73762d81..5b97bdfba823 100644 --- a/sound/soc/sof/intel/cnl.c +++ b/sound/soc/sof/intel/cnl.c @@ -327,3 +327,20 @@ const struct sof_intel_dsp_desc ehl_chip_info = { .ssp_base_offset = CNL_SSP_BASE_OFFSET, }; EXPORT_SYMBOL(ehl_chip_info); + +const struct sof_intel_dsp_desc jsl_chip_info = { + /* Jasperlake */ + .cores_num = 2, + .init_core_mask = 1, + .cores_mask = HDA_DSP_CORE_MASK(0) | + HDA_DSP_CORE_MASK(1), + .ipc_req = CNL_DSP_REG_HIPCIDR, + .ipc_req_mask = CNL_DSP_REG_HIPCIDR_BUSY, + .ipc_ack = CNL_DSP_REG_HIPCIDA, + .ipc_ack_mask = CNL_DSP_REG_HIPCIDA_DONE, + .ipc_ctl = CNL_DSP_REG_HIPCCTL, + .rom_init_timeout = 300, + .ssp_count = ICL_SSP_COUNT, + .ssp_base_offset = CNL_SSP_BASE_OFFSET, +}; +EXPORT_SYMBOL(jsl_chip_info); diff --git a/sound/soc/sof/intel/hda.h b/sound/soc/sof/intel/hda.h index 23e430d3e056..ea02bf40cb25 100644 --- a/sound/soc/sof/intel/hda.h +++ b/sound/soc/sof/intel/hda.h @@ -604,5 +604,6 @@ extern const struct sof_intel_dsp_desc skl_chip_info; extern const struct sof_intel_dsp_desc icl_chip_info; extern const struct sof_intel_dsp_desc tgl_chip_info; extern const struct sof_intel_dsp_desc ehl_chip_info; +extern const struct sof_intel_dsp_desc jsl_chip_info; #endif diff --git a/sound/soc/sof/sof-pci-dev.c b/sound/soc/sof/sof-pci-dev.c index 030f2cb06921..4adbb27c76c5 100644 --- a/sound/soc/sof/sof-pci-dev.c +++ b/sound/soc/sof/sof-pci-dev.c @@ -245,6 +245,24 @@ static const struct sof_dev_desc ehl_desc = { }; #endif +#if IS_ENABLED(CONFIG_SND_SOC_SOF_JASPERLAKE) +static const struct sof_dev_desc jsl_desc = { + .machines = snd_soc_acpi_intel_jsl_machines, + .resindex_lpe_base = 0, + .resindex_pcicfg_base = -1, + .resindex_imr_base = -1, + .irqindex_host_ipc = -1, + .resindex_dma_base = -1, + .chip_info = &jsl_chip_info, + .default_fw_path = "intel/sof", + .default_tplg_path = "intel/sof-tplg", + .nocodec_fw_filename = "sof-jsl.ri", + .nocodec_tplg_filename = "sof-jsl-nocodec.tplg", + .ops = &sof_cnl_ops, + .arch_ops = &sof_xtensa_arch_ops +}; +#endif + static const struct dev_pm_ops sof_pci_pm = { SET_SYSTEM_SLEEP_PM_OPS(snd_sof_suspend, snd_sof_resume) SET_RUNTIME_PM_OPS(snd_sof_runtime_suspend, snd_sof_runtime_resume, @@ -423,6 +441,10 @@ static const struct pci_device_id sof_pci_ids[] = { { PCI_DEVICE(0x8086, 0x34C8), .driver_data = (unsigned long)&icl_desc}, #endif +#if IS_ENABLED(CONFIG_SND_SOC_SOF_JASPERLAKE) + { PCI_DEVICE(0x8086, 0x38c8), + .driver_data = (unsigned long)&jsl_desc}, +#endif #if IS_ENABLED(CONFIG_SND_SOC_SOF_COMETLAKE_LP) { PCI_DEVICE(0x8086, 0x02c8), .driver_data = (unsigned long)&cml_desc}, -- cgit v1.2.3 From 27e322fabd508ba73ced625fc41f0b7ceee26416 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Thu, 24 Oct 2019 16:03:17 -0500 Subject: ASoC: SOF: define INFO_ flags in dsp_ops Currently the INFO_ flags such as PAUSE/NO_PERIOD_WAKEUP are defined in the SOF PCM core, which doesn't scale. To account for platform variations, these flags need to be set in DSP ops. This patch only moves the definitions and does not change any functionality. Reviewed-by: Jaska Uimonen Reviewed-by: Ranjani Sridharan Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20191024210318.30068-2-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/imx/imx8.c | 7 +++++++ sound/soc/sof/intel/apl.c | 7 +++++++ sound/soc/sof/intel/bdw.c | 9 ++++++++- sound/soc/sof/intel/byt.c | 21 +++++++++++++++++++++ sound/soc/sof/intel/cnl.c | 7 +++++++ sound/soc/sof/pcm.c | 8 +++----- sound/soc/sof/sof-priv.h | 3 +++ 7 files changed, 56 insertions(+), 6 deletions(-) (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/imx/imx8.c b/sound/soc/sof/imx/imx8.c index 2a22b18e5ec0..cfefcfd92798 100644 --- a/sound/soc/sof/imx/imx8.c +++ b/sound/soc/sof/imx/imx8.c @@ -388,6 +388,13 @@ struct snd_sof_dsp_ops sof_imx8_ops = { /* DAI drivers */ .drv = imx8_dai, .num_drv = 1, /* we have only 1 ESAI interface on i.MX8 */ + + /* ALSA HW info flags */ + .hw_info = SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_PAUSE | + SNDRV_PCM_INFO_NO_PERIOD_WAKEUP }; EXPORT_SYMBOL(sof_imx8_ops); diff --git a/sound/soc/sof/intel/apl.c b/sound/soc/sof/intel/apl.c index 8dc7a5558da4..15d26e8d90a9 100644 --- a/sound/soc/sof/intel/apl.c +++ b/sound/soc/sof/intel/apl.c @@ -97,6 +97,13 @@ const struct snd_sof_dsp_ops sof_apl_ops = { .runtime_resume = hda_dsp_runtime_resume, .runtime_idle = hda_dsp_runtime_idle, .set_hw_params_upon_resume = hda_dsp_set_hw_params_upon_resume, + + /* ALSA HW info flags */ + .hw_info = SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_PAUSE | + SNDRV_PCM_INFO_NO_PERIOD_WAKEUP, }; EXPORT_SYMBOL(sof_apl_ops); diff --git a/sound/soc/sof/intel/bdw.c b/sound/soc/sof/intel/bdw.c index bf961a8798a7..7b4cd1f456bf 100644 --- a/sound/soc/sof/intel/bdw.c +++ b/sound/soc/sof/intel/bdw.c @@ -591,7 +591,14 @@ const struct snd_sof_dsp_ops sof_bdw_ops = { /* DAI drivers */ .drv = bdw_dai, - .num_drv = ARRAY_SIZE(bdw_dai) + .num_drv = ARRAY_SIZE(bdw_dai), + + /* ALSA HW info flags */ + .hw_info = SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_PAUSE | + SNDRV_PCM_INFO_NO_PERIOD_WAKEUP, }; EXPORT_SYMBOL(sof_bdw_ops); diff --git a/sound/soc/sof/intel/byt.c b/sound/soc/sof/intel/byt.c index 07e5efe4945c..62edb959f1fc 100644 --- a/sound/soc/sof/intel/byt.c +++ b/sound/soc/sof/intel/byt.c @@ -532,6 +532,13 @@ const struct snd_sof_dsp_ops sof_tng_ops = { /* DAI drivers */ .drv = byt_dai, .num_drv = 3, /* we have only 3 SSPs on byt*/ + + /* ALSA HW info flags */ + .hw_info = SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_PAUSE | + SNDRV_PCM_INFO_NO_PERIOD_WAKEUP, }; EXPORT_SYMBOL(sof_tng_ops); @@ -693,6 +700,13 @@ const struct snd_sof_dsp_ops sof_byt_ops = { /* DAI drivers */ .drv = byt_dai, .num_drv = 3, /* we have only 3 SSPs on byt*/ + + /* ALSA HW info flags */ + .hw_info = SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_PAUSE | + SNDRV_PCM_INFO_NO_PERIOD_WAKEUP, }; EXPORT_SYMBOL(sof_byt_ops); @@ -753,6 +767,13 @@ const struct snd_sof_dsp_ops sof_cht_ops = { .drv = byt_dai, /* all 6 SSPs may be available for cherrytrail */ .num_drv = ARRAY_SIZE(byt_dai), + + /* ALSA HW info flags */ + .hw_info = SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_PAUSE | + SNDRV_PCM_INFO_NO_PERIOD_WAKEUP, }; EXPORT_SYMBOL(sof_cht_ops); diff --git a/sound/soc/sof/intel/cnl.c b/sound/soc/sof/intel/cnl.c index 5b97bdfba823..e9cdcc040fb5 100644 --- a/sound/soc/sof/intel/cnl.c +++ b/sound/soc/sof/intel/cnl.c @@ -255,6 +255,13 @@ const struct snd_sof_dsp_ops sof_cnl_ops = { .runtime_resume = hda_dsp_runtime_resume, .runtime_idle = hda_dsp_runtime_idle, .set_hw_params_upon_resume = hda_dsp_set_hw_params_upon_resume, + + /* ALSA HW info flags */ + .hw_info = SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_PAUSE | + SNDRV_PCM_INFO_NO_PERIOD_WAKEUP, }; EXPORT_SYMBOL(sof_cnl_ops); diff --git a/sound/soc/sof/pcm.c b/sound/soc/sof/pcm.c index d72798d2b302..9ba505cf5966 100644 --- a/sound/soc/sof/pcm.c +++ b/sound/soc/sof/pcm.c @@ -440,6 +440,7 @@ static int sof_pcm_open(struct snd_soc_component *component, struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_pcm_runtime *runtime = substream->runtime; struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component); + const struct snd_sof_dsp_ops *ops = sof_ops(sdev); struct snd_sof_pcm *spcm; struct snd_soc_tplg_stream_caps *caps; int ret; @@ -469,11 +470,8 @@ static int sof_pcm_open(struct snd_soc_component *component, le32_to_cpu(caps->period_size_min)); /* set runtime config */ - runtime->hw.info = SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_PAUSE | - SNDRV_PCM_INFO_NO_PERIOD_WAKEUP; + runtime->hw.info = ops->hw_info; /* platform-specific */ + runtime->hw.formats = le64_to_cpu(caps->formats); runtime->hw.period_bytes_min = le32_to_cpu(caps->period_size_min); runtime->hw.period_bytes_max = le32_to_cpu(caps->period_size_max); diff --git a/sound/soc/sof/sof-priv.h b/sound/soc/sof/sof-priv.h index 5a11a8517fa5..2d40de5ee285 100644 --- a/sound/soc/sof/sof-priv.h +++ b/sound/soc/sof/sof-priv.h @@ -211,6 +211,9 @@ struct snd_sof_dsp_ops { /* DAI ops */ struct snd_soc_dai_driver *drv; int num_drv; + + /* ALSA HW info flags, will be stored in snd_pcm_runtime.hw.info */ + u32 hw_info; }; /* DSP architecture specific callbacks for oops and stack dumps */ -- cgit v1.2.3 From 4c02a7bd43e22f4de53ad55b94d24e4388f712f0 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Thu, 24 Oct 2019 16:03:18 -0500 Subject: ASoC: SOF: Intel: only support INFO_BATCH for legacy platforms The current position update is not precise enough for PulseAudio to work reliably with the timer-based scheduling on Baytrail, Cherrytrail, Broadwell. Disable the NO_PERIOD_WAKEUP capability and use BATCH to signal that the position is only reliable and updated during period_elapsed events. This will be reverted when the firmware provides a more accurate position for those platforms. Reviewed-by: Jaska Uimonen Reviewed-by: Ranjani Sridharan Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20191024210318.30068-3-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/bdw.c | 2 +- sound/soc/sof/intel/byt.c | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/intel/bdw.c b/sound/soc/sof/intel/bdw.c index 7b4cd1f456bf..141dad554764 100644 --- a/sound/soc/sof/intel/bdw.c +++ b/sound/soc/sof/intel/bdw.c @@ -598,7 +598,7 @@ const struct snd_sof_dsp_ops sof_bdw_ops = { SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_PAUSE | - SNDRV_PCM_INFO_NO_PERIOD_WAKEUP, + SNDRV_PCM_INFO_BATCH, }; EXPORT_SYMBOL(sof_bdw_ops); diff --git a/sound/soc/sof/intel/byt.c b/sound/soc/sof/intel/byt.c index 62edb959f1fc..2abf80b3eb52 100644 --- a/sound/soc/sof/intel/byt.c +++ b/sound/soc/sof/intel/byt.c @@ -538,7 +538,7 @@ const struct snd_sof_dsp_ops sof_tng_ops = { SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_PAUSE | - SNDRV_PCM_INFO_NO_PERIOD_WAKEUP, + SNDRV_PCM_INFO_BATCH, }; EXPORT_SYMBOL(sof_tng_ops); @@ -706,7 +706,7 @@ const struct snd_sof_dsp_ops sof_byt_ops = { SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_PAUSE | - SNDRV_PCM_INFO_NO_PERIOD_WAKEUP, + SNDRV_PCM_INFO_BATCH, }; EXPORT_SYMBOL(sof_byt_ops); @@ -773,7 +773,7 @@ const struct snd_sof_dsp_ops sof_cht_ops = { SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_PAUSE | - SNDRV_PCM_INFO_NO_PERIOD_WAKEUP, + SNDRV_PCM_INFO_BATCH, }; EXPORT_SYMBOL(sof_cht_ops); -- cgit v1.2.3 From f792bd173a6fd51d1a4dde04263085ce67486aa3 Mon Sep 17 00:00:00 2001 From: Keyon Jie Date: Fri, 25 Oct 2019 17:15:38 -0500 Subject: ASoC: SOF: Intel: hda-stream: fix the CONFIG_ prefix missing We are missing the 'CONFIG_' prefix when using the kernel configure item SND_SOC_SOF_HDA_ALWAYS_ENABLE_DMI_L1, here correct them. Fixes: 43b2ab9009b13b ('ASoC: SOF: Intel: hda: Disable DMI L1 entry during capture') Signed-off-by: Keyon Jie Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20191025221538.6668-1-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-stream.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/intel/hda-stream.c b/sound/soc/sof/intel/hda-stream.c index 2c7447188402..0c11fceb28a7 100644 --- a/sound/soc/sof/intel/hda-stream.c +++ b/sound/soc/sof/intel/hda-stream.c @@ -190,7 +190,7 @@ hda_dsp_stream_get(struct snd_sof_dev *sdev, int direction) * Workaround to address a known issue with host DMA that results * in xruns during pause/release in capture scenarios. */ - if (!IS_ENABLED(SND_SOC_SOF_HDA_ALWAYS_ENABLE_DMI_L1)) + if (!IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_ALWAYS_ENABLE_DMI_L1)) if (stream && direction == SNDRV_PCM_STREAM_CAPTURE) snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, HDA_VS_INTEL_EM2, @@ -228,7 +228,7 @@ int hda_dsp_stream_put(struct snd_sof_dev *sdev, int direction, int stream_tag) spin_unlock_irq(&bus->reg_lock); /* Enable DMI L1 entry if there are no capture streams open */ - if (!IS_ENABLED(SND_SOC_SOF_HDA_ALWAYS_ENABLE_DMI_L1)) + if (!IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_ALWAYS_ENABLE_DMI_L1)) if (!active_capture_stream) snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, HDA_VS_INTEL_EM2, -- cgit v1.2.3 From c0a333d842ef67ac04adc72ff79dc1ccc3dca4ed Mon Sep 17 00:00:00 2001 From: Navid Emamdoost Date: Sun, 27 Oct 2019 14:48:47 -0500 Subject: ASoC: SOF: Fix memory leak in sof_dfsentry_write In the implementation of sof_dfsentry_write() memory allocated for string is leaked in case of an error. Go to error handling path if the d_name.name is not valid. Fixes: 091c12e1f50c ("ASoC: SOF: debug: add new debugfs entries for IPC flood test") Signed-off-by: Navid Emamdoost Link: https://lore.kernel.org/r/20191027194856.4056-1-navid.emamdoost@gmail.com Signed-off-by: Mark Brown --- sound/soc/sof/debug.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/debug.c b/sound/soc/sof/debug.c index 54cd431faab7..5529e8eeca46 100644 --- a/sound/soc/sof/debug.c +++ b/sound/soc/sof/debug.c @@ -152,8 +152,10 @@ static ssize_t sof_dfsentry_write(struct file *file, const char __user *buffer, */ dentry = file->f_path.dentry; if (strcmp(dentry->d_name.name, "ipc_flood_count") && - strcmp(dentry->d_name.name, "ipc_flood_duration_ms")) - return -EINVAL; + strcmp(dentry->d_name.name, "ipc_flood_duration_ms")) { + ret = -EINVAL; + goto out; + } if (!strcmp(dentry->d_name.name, "ipc_flood_duration_ms")) flood_duration_test = true; -- cgit v1.2.3 From 45c1380358b12bf2d1db20a5874e9544f56b34ab Mon Sep 17 00:00:00 2001 From: Navid Emamdoost Date: Sun, 27 Oct 2019 16:53:24 -0500 Subject: ASoC: SOF: ipc: Fix memory leak in sof_set_get_large_ctrl_data In the implementation of sof_set_get_large_ctrl_data() there is a memory leak in case an error. Release partdata if sof_get_ctrl_copy_params() fails. Fixes: 54d198d5019d ("ASoC: SOF: Propagate sof_get_ctrl_copy_params() error properly") Signed-off-by: Navid Emamdoost Link: https://lore.kernel.org/r/20191027215330.12729-1-navid.emamdoost@gmail.com Signed-off-by: Mark Brown --- sound/soc/sof/ipc.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/ipc.c b/sound/soc/sof/ipc.c index b2f359d2f7e5..086eeeab8679 100644 --- a/sound/soc/sof/ipc.c +++ b/sound/soc/sof/ipc.c @@ -572,8 +572,10 @@ static int sof_set_get_large_ctrl_data(struct snd_sof_dev *sdev, else err = sof_get_ctrl_copy_params(cdata->type, partdata, cdata, sparams); - if (err < 0) + if (err < 0) { + kfree(partdata); return err; + } msg_bytes = sparams->msg_bytes; pl_size = sparams->pl_size; -- cgit v1.2.3 From 4c19030c511fd6eab029bae838f736256d2f43cd Mon Sep 17 00:00:00 2001 From: Keyon Jie Date: Fri, 25 Oct 2019 17:40:57 -0500 Subject: ASoC: SOF: add a field to store the current D0 substate of DSP Add field d0_substate to struct snd_sof_dev to store the current DSP D0 sub-state(only meaningful when DSP in D0), which could be D0I0 or D0I3. Signed-off-by: Keyon Jie Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20191025224122.7718-2-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/sof-priv.h | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/sof-priv.h b/sound/soc/sof/sof-priv.h index 2d40de5ee285..481dfe4ee2d0 100644 --- a/sound/soc/sof/sof-priv.h +++ b/sound/soc/sof/sof-priv.h @@ -68,6 +68,12 @@ extern int sof_core_debug; #define DMA_CHAN_INVALID 0xFFFFFFFF +/* DSP D0ix sub-state */ +enum sof_d0_substate { + SOF_DSP_D0I0 = 0, /* DSP default D0 substate */ + SOF_DSP_D0I3, /* DSP D0i3(low power) substate*/ +}; + struct snd_sof_dev; struct snd_sof_ipc_msg; struct snd_sof_ipc; @@ -387,6 +393,9 @@ struct snd_sof_dev { */ struct snd_soc_component_driver plat_drv; + /* power states related */ + enum sof_d0_substate d0_substate; + /* DSP firmware boot */ wait_queue_head_t boot_wait; u32 boot_complete; -- cgit v1.2.3 From 09fe6b528886c0d07ce539b837749edcc46618d0 Mon Sep 17 00:00:00 2001 From: Keyon Jie Date: Fri, 25 Oct 2019 17:40:58 -0500 Subject: ASoC: SOF: reset default d0_substate at probe() and resume() We initialize/reset d0_substate to default d0i0 value when doing transition D3-->D0, e.g. at success of probing and resuming. Signed-off-by: Keyon Jie Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20191025224122.7718-3-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/core.c | 3 +++ sound/soc/sof/pm.c | 3 +++ 2 files changed, 6 insertions(+) (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/core.c b/sound/soc/sof/core.c index 5998861a9002..8661c2cca76b 100644 --- a/sound/soc/sof/core.c +++ b/sound/soc/sof/core.c @@ -458,6 +458,9 @@ int snd_sof_device_probe(struct device *dev, struct snd_sof_pdata *plat_data) /* initialize sof device */ sdev->dev = dev; + /* initialize default D0 sub-state */ + sdev->d0_substate = SOF_DSP_D0I0; + sdev->pdata = plat_data; sdev->first_boot = true; dev_set_drvdata(dev, sdev); diff --git a/sound/soc/sof/pm.c b/sound/soc/sof/pm.c index e23beaeefe00..81e623dfc7e5 100644 --- a/sound/soc/sof/pm.c +++ b/sound/soc/sof/pm.c @@ -326,6 +326,9 @@ static int sof_resume(struct device *dev, bool runtime_resume) "error: ctx_restore ipc error during resume %d\n", ret); + /* initialize default D0 sub-state */ + sdev->d0_substate = SOF_DSP_D0I0; + return ret; } -- cgit v1.2.3 From e8f112d8c29f44ded83f97828c104bf0904871ec Mon Sep 17 00:00:00 2001 From: Keyon Jie Date: Fri, 25 Oct 2019 17:40:59 -0500 Subject: ASoC: SOF: add set_power_state() to dsp_ops for power state update D0i3 is a platform-defined substate of D0, so we need a platform-specific callback in dsp_ops to handle the relevant configurations. Signed-off-by: Keyon Jie Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20191025224122.7718-4-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/ops.h | 9 +++++++++ sound/soc/sof/sof-priv.h | 2 ++ 2 files changed, 11 insertions(+) (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/ops.h b/sound/soc/sof/ops.h index 824d36fe59fd..d7c8fc06f961 100644 --- a/sound/soc/sof/ops.h +++ b/sound/soc/sof/ops.h @@ -193,6 +193,15 @@ static inline int snd_sof_dsp_set_clk(struct snd_sof_dev *sdev, u32 freq) return 0; } +static inline int snd_sof_dsp_set_power_state(struct snd_sof_dev *sdev, + enum sof_d0_substate substate) +{ + if (sof_ops(sdev)->set_power_state) + return sof_ops(sdev)->set_power_state(sdev, substate); + + return 0; +} + /* debug */ static inline void snd_sof_dsp_dbg_dump(struct snd_sof_dev *sdev, u32 flags) { diff --git a/sound/soc/sof/sof-priv.h b/sound/soc/sof/sof-priv.h index 481dfe4ee2d0..e9902e4e8e55 100644 --- a/sound/soc/sof/sof-priv.h +++ b/sound/soc/sof/sof-priv.h @@ -189,6 +189,8 @@ struct snd_sof_dsp_ops { int (*runtime_resume)(struct snd_sof_dev *sof_dev); /* optional */ int (*runtime_idle)(struct snd_sof_dev *sof_dev); /* optional */ int (*set_hw_params_upon_resume)(struct snd_sof_dev *sdev); /* optional */ + int (*set_power_state)(struct snd_sof_dev *sdev, + enum sof_d0_substate d0_substate); /* optional */ /* DSP clocking */ int (*set_clk)(struct snd_sof_dev *sof_dev, u32 freq); /* optional */ -- cgit v1.2.3 From 62f8f76604623980d41cf73691ca45288871efd9 Mon Sep 17 00:00:00 2001 From: Keyon Jie Date: Fri, 25 Oct 2019 17:41:00 -0500 Subject: ASoC: SOF: Intel: hda-dsp: Add helper for setting DSP D0ix substate Adding helper to implement setting dsp to d0i3 or d0i0 status, this will be needed for driver D0ix support. Signed-off-by: Keyon Jie Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20191025224122.7718-5-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-dsp.c | 46 +++++++++++++++++++++++++++++++++++++++++++ sound/soc/sof/intel/hda.h | 10 ++++++++++ 2 files changed, 56 insertions(+) (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/intel/hda-dsp.c b/sound/soc/sof/intel/hda-dsp.c index 3ea401646e0c..fa2f1f66c72c 100644 --- a/sound/soc/sof/intel/hda-dsp.c +++ b/sound/soc/sof/intel/hda-dsp.c @@ -306,6 +306,52 @@ void hda_dsp_ipc_int_disable(struct snd_sof_dev *sdev) HDA_DSP_REG_HIPCCTL_BUSY | HDA_DSP_REG_HIPCCTL_DONE, 0); } +static int hda_dsp_wait_d0i3c_done(struct snd_sof_dev *sdev, int retry) +{ + struct hdac_bus *bus = sof_to_bus(sdev); + + while (snd_hdac_chip_readb(bus, VS_D0I3C) & SOF_HDA_VS_D0I3C_CIP) { + if (!retry--) + return -ETIMEDOUT; + usleep_range(10, 15); + } + + return 0; +} + +int hda_dsp_set_power_state(struct snd_sof_dev *sdev, + enum sof_d0_substate d0_substate) +{ + struct hdac_bus *bus = sof_to_bus(sdev); + int retry = 50; + int ret; + u8 value; + + /* Write to D0I3C after Command-In-Progress bit is cleared */ + ret = hda_dsp_wait_d0i3c_done(sdev, retry); + if (ret < 0) { + dev_err(bus->dev, "CIP timeout before update D0I3C!\n"); + return ret; + } + + /* Update D0I3C register */ + value = d0_substate == SOF_DSP_D0I3 ? SOF_HDA_VS_D0I3C_I3 : 0; + snd_hdac_chip_updateb(bus, VS_D0I3C, SOF_HDA_VS_D0I3C_I3, value); + + /* Wait for cmd in progress to be cleared before exiting the function */ + retry = 50; + ret = hda_dsp_wait_d0i3c_done(sdev, retry); + if (ret < 0) { + dev_err(bus->dev, "CIP timeout after D0I3C updated!\n"); + return ret; + } + + dev_vdbg(bus->dev, "D0I3C updated, register = 0x%x\n", + snd_hdac_chip_readb(bus, VS_D0I3C)); + + return 0; +} + static int hda_suspend(struct snd_sof_dev *sdev, bool runtime_suspend) { struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata; diff --git a/sound/soc/sof/intel/hda.h b/sound/soc/sof/intel/hda.h index ea02bf40cb25..0e7c366b8f71 100644 --- a/sound/soc/sof/intel/hda.h +++ b/sound/soc/sof/intel/hda.h @@ -64,6 +64,13 @@ #define SOF_HDA_PPCTL_PIE BIT(31) #define SOF_HDA_PPCTL_GPROCEN BIT(30) +/*Vendor Specific Registers*/ +#define SOF_HDA_VS_D0I3C 0x104A + +/* D0I3C Register fields */ +#define SOF_HDA_VS_D0I3C_CIP BIT(0) /* Command-In-Progress */ +#define SOF_HDA_VS_D0I3C_I3 BIT(2) /* D0i3 enable bit */ + /* DPIB entry size: 8 Bytes = 2 DWords */ #define SOF_HDA_DPIB_ENTRY_SIZE 0x8 @@ -455,6 +462,9 @@ int hda_dsp_core_reset_power_down(struct snd_sof_dev *sdev, void hda_dsp_ipc_int_enable(struct snd_sof_dev *sdev); void hda_dsp_ipc_int_disable(struct snd_sof_dev *sdev); +int hda_dsp_set_power_state(struct snd_sof_dev *sdev, + enum sof_d0_substate d0_substate); + int hda_dsp_suspend(struct snd_sof_dev *sdev); int hda_dsp_resume(struct snd_sof_dev *sdev); int hda_dsp_runtime_suspend(struct snd_sof_dev *sdev); -- cgit v1.2.3 From 73b51957122dc47a40325a5359b44ef337cbf217 Mon Sep 17 00:00:00 2001 From: Keyon Jie Date: Fri, 25 Oct 2019 17:41:01 -0500 Subject: ASoC: SOF: Intel: CNL: add set_power_state() ops Using hda_dsp_set_power_state() as set_power_state() ops for cnl to do d0ix platform configuration updates. Signed-off-by: Keyon Jie Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20191025224122.7718-6-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/cnl.c | 1 + 1 file changed, 1 insertion(+) (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/intel/cnl.c b/sound/soc/sof/intel/cnl.c index e9cdcc040fb5..982b81a0b13a 100644 --- a/sound/soc/sof/intel/cnl.c +++ b/sound/soc/sof/intel/cnl.c @@ -255,6 +255,7 @@ const struct snd_sof_dsp_ops sof_cnl_ops = { .runtime_resume = hda_dsp_runtime_resume, .runtime_idle = hda_dsp_runtime_idle, .set_hw_params_upon_resume = hda_dsp_set_hw_params_upon_resume, + .set_power_state = hda_dsp_set_power_state, /* ALSA HW info flags */ .hw_info = SNDRV_PCM_INFO_MMAP | -- cgit v1.2.3 From 35c930ba6025964ac71f041065ae212a0fcc7cca Mon Sep 17 00:00:00 2001 From: Keyon Jie Date: Fri, 25 Oct 2019 17:41:02 -0500 Subject: ASoC: SOF: Intel: APL: add set_power_state() ops Using hda_dsp_set_power_state() as set_power_state() ops for apl to do d0ix platform configuration updates. Signed-off-by: Keyon Jie Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20191025224122.7718-7-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/apl.c | 1 + 1 file changed, 1 insertion(+) (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/intel/apl.c b/sound/soc/sof/intel/apl.c index 15d26e8d90a9..7daa8eb456c8 100644 --- a/sound/soc/sof/intel/apl.c +++ b/sound/soc/sof/intel/apl.c @@ -97,6 +97,7 @@ const struct snd_sof_dsp_ops sof_apl_ops = { .runtime_resume = hda_dsp_runtime_resume, .runtime_idle = hda_dsp_runtime_idle, .set_hw_params_upon_resume = hda_dsp_set_hw_params_upon_resume, + .set_power_state = hda_dsp_set_power_state, /* ALSA HW info flags */ .hw_info = SNDRV_PCM_INFO_MMAP | -- cgit v1.2.3 From e5c97e88084b8dca6850eba5d2937716b88306c1 Mon Sep 17 00:00:00 2001 From: Keyon Jie Date: Fri, 25 Oct 2019 17:41:03 -0500 Subject: ASoC: SOF: add flag to snd_sof_pcm_stream for D0i3 compatible stream Add flag d0i3_compatible to struct snd_sof_pcm_stream to denote if the stream can tolerate a transition to the D0i3 substate while opened (thus seen as 'active' by pm_runtime). Signed-off-by: Keyon Jie Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20191025224122.7718-8-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/sof-priv.h | 1 + 1 file changed, 1 insertion(+) (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/sof-priv.h b/sound/soc/sof/sof-priv.h index e9902e4e8e55..7a21a45d3635 100644 --- a/sound/soc/sof/sof-priv.h +++ b/sound/soc/sof/sof-priv.h @@ -310,6 +310,7 @@ struct snd_sof_pcm_stream { struct sof_ipc_stream_posn posn; struct snd_pcm_substream *substream; struct work_struct period_elapsed_work; + bool d0i3_compatible; /* DSP can be in D0I3 when this pcm is opened */ }; /* ALSA SOF PCM device */ -- cgit v1.2.3 From 4a94940988cc44adeb383401dea0beeac4abbe63 Mon Sep 17 00:00:00 2001 From: Keyon Jie Date: Fri, 25 Oct 2019 17:41:04 -0500 Subject: ASoC: SOF: token: add tokens for PCM compatible with D0i3 substate Add stream token SOF_TKN_STREAM_PLAYBACK_COMPATIBLE_D0I3 and SOF_TKN_STREAM_CAPTURE_COMPATIBLE_D0I3 to denote if the stream can be opened at low power d0i3 status or not. Signed-off-by: Keyon Jie Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20191025224122.7718-9-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- include/uapi/sound/sof/tokens.h | 4 ++++ sound/soc/sof/topology.c | 10 ++++++++++ 2 files changed, 14 insertions(+) (limited to 'sound/soc/sof') diff --git a/include/uapi/sound/sof/tokens.h b/include/uapi/sound/sof/tokens.h index d65406f34361..76883e6fb750 100644 --- a/include/uapi/sound/sof/tokens.h +++ b/include/uapi/sound/sof/tokens.h @@ -113,6 +113,10 @@ /* ESAI */ #define SOF_TKN_IMX_ESAI_MCLK_ID 1100 +/* Stream */ +#define SOF_TKN_STREAM_PLAYBACK_COMPATIBLE_D0I3 1200 +#define SOF_TKN_STREAM_CAPTURE_COMPATIBLE_D0I3 1201 + /* Led control for mute switches */ #define SOF_TKN_MUTE_LED_USE 1300 #define SOF_TKN_MUTE_LED_DIRECTION 1301 diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c index b3ab6f23fc93..121e5d6f8477 100644 --- a/sound/soc/sof/topology.c +++ b/sound/soc/sof/topology.c @@ -567,6 +567,16 @@ static const struct sof_topology_token pcm_tokens[] = { offsetof(struct sof_ipc_comp_host, dmac_config), 0}, }; +/* PCM */ +static const struct sof_topology_token stream_tokens[] = { + {SOF_TKN_STREAM_PLAYBACK_COMPATIBLE_D0I3, + SND_SOC_TPLG_TUPLE_TYPE_BOOL, get_token_u16, + offsetof(struct snd_sof_pcm, stream[0].d0i3_compatible), 0}, + {SOF_TKN_STREAM_CAPTURE_COMPATIBLE_D0I3, + SND_SOC_TPLG_TUPLE_TYPE_BOOL, get_token_u16, + offsetof(struct snd_sof_pcm, stream[1].d0i3_compatible), 0}, +}; + /* Generic components */ static const struct sof_topology_token comp_tokens[] = { {SOF_TKN_COMP_PERIOD_SINK_COUNT, -- cgit v1.2.3 From c5232c0171428f005a3204e1c264231fb5999b28 Mon Sep 17 00:00:00 2001 From: Keyon Jie Date: Fri, 25 Oct 2019 17:41:05 -0500 Subject: ASoC: SOF: topology: parse and store d0i3_compatible flag Parses the token from tplg file and store it to snd_sof_pcm_stream d0i3_compatible flag, which can be used later for d0ix transition management. Signed-off-by: Keyon Jie Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20191025224122.7718-10-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/topology.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c index 121e5d6f8477..cc138ac6a8eb 100644 --- a/sound/soc/sof/topology.c +++ b/sound/soc/sof/topology.c @@ -2307,6 +2307,7 @@ static int sof_dai_load(struct snd_soc_component *scomp, int index, { struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); struct snd_soc_tplg_stream_caps *caps; + struct snd_soc_tplg_private *private = &pcm->priv; struct snd_sof_pcm *spcm; int stream = SNDRV_PCM_STREAM_PLAYBACK; int ret = 0; @@ -2329,10 +2330,22 @@ static int sof_dai_load(struct snd_soc_component *scomp, int index, dai_drv->dobj.private = spcm; list_add(&spcm->list, &sdev->pcm_list); + ret = sof_parse_tokens(scomp, spcm, stream_tokens, + ARRAY_SIZE(stream_tokens), private->array, + le32_to_cpu(private->size)); + if (ret) { + dev_err(sdev->dev, "error: parse stream tokens failed %d\n", + le32_to_cpu(private->size)); + return ret; + } + /* do we need to allocate playback PCM DMA pages */ if (!spcm->pcm.playback) goto capture; + dev_vdbg(sdev->dev, "tplg: pcm %s stream tokens: playback d0i3:%d\n", + spcm->pcm.pcm_name, spcm->stream[0].d0i3_compatible); + caps = &spcm->pcm.caps[stream]; /* allocate playback page table buffer */ @@ -2360,6 +2373,9 @@ capture: if (!spcm->pcm.capture) return ret; + dev_vdbg(sdev->dev, "tplg: pcm %s stream tokens: capture d0i3:%d\n", + spcm->pcm.pcm_name, spcm->stream[1].d0i3_compatible); + caps = &spcm->pcm.caps[stream]; /* allocate capture page table buffer */ -- cgit v1.2.3 From aae7c82d01219bf568a7b12f5839d7ca52b17d59 Mon Sep 17 00:00:00 2001 From: Keyon Jie Date: Fri, 25 Oct 2019 17:41:06 -0500 Subject: ASoC: SOF: Intel: hda-dsp: align the comments for D0I3C update Align the logs for CIP timeout at D0I3C.I3 updating. Signed-off-by: Keyon Jie Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20191025224122.7718-11-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-dsp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/intel/hda-dsp.c b/sound/soc/sof/intel/hda-dsp.c index fa2f1f66c72c..74805a066183 100644 --- a/sound/soc/sof/intel/hda-dsp.c +++ b/sound/soc/sof/intel/hda-dsp.c @@ -330,7 +330,7 @@ int hda_dsp_set_power_state(struct snd_sof_dev *sdev, /* Write to D0I3C after Command-In-Progress bit is cleared */ ret = hda_dsp_wait_d0i3c_done(sdev, retry); if (ret < 0) { - dev_err(bus->dev, "CIP timeout before update D0I3C!\n"); + dev_err(bus->dev, "CIP timeout before D0I3C update!\n"); return ret; } @@ -342,7 +342,7 @@ int hda_dsp_set_power_state(struct snd_sof_dev *sdev, retry = 50; ret = hda_dsp_wait_d0i3c_done(sdev, retry); if (ret < 0) { - dev_err(bus->dev, "CIP timeout after D0I3C updated!\n"); + dev_err(bus->dev, "CIP timeout after D0I3C update!\n"); return ret; } -- cgit v1.2.3 From 92f4beb718d76e93b76343a3ba872df6cb210672 Mon Sep 17 00:00:00 2001 From: Keyon Jie Date: Fri, 25 Oct 2019 17:41:07 -0500 Subject: ASoC: SOF: Intel: HDA: use macro for register polling retry count Define macro and use it for the register polling retry count. Signed-off-by: Keyon Jie Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20191025224122.7718-12-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-dsp.c | 6 ++---- sound/soc/sof/intel/hda.h | 1 + 2 files changed, 3 insertions(+), 4 deletions(-) (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/intel/hda-dsp.c b/sound/soc/sof/intel/hda-dsp.c index 74805a066183..936361bd25e9 100644 --- a/sound/soc/sof/intel/hda-dsp.c +++ b/sound/soc/sof/intel/hda-dsp.c @@ -323,12 +323,11 @@ int hda_dsp_set_power_state(struct snd_sof_dev *sdev, enum sof_d0_substate d0_substate) { struct hdac_bus *bus = sof_to_bus(sdev); - int retry = 50; int ret; u8 value; /* Write to D0I3C after Command-In-Progress bit is cleared */ - ret = hda_dsp_wait_d0i3c_done(sdev, retry); + ret = hda_dsp_wait_d0i3c_done(sdev, HDA_DSP_REG_POLL_RETRY_COUNT); if (ret < 0) { dev_err(bus->dev, "CIP timeout before D0I3C update!\n"); return ret; @@ -339,8 +338,7 @@ int hda_dsp_set_power_state(struct snd_sof_dev *sdev, snd_hdac_chip_updateb(bus, VS_D0I3C, SOF_HDA_VS_D0I3C_I3, value); /* Wait for cmd in progress to be cleared before exiting the function */ - retry = 50; - ret = hda_dsp_wait_d0i3c_done(sdev, retry); + ret = hda_dsp_wait_d0i3c_done(sdev, HDA_DSP_REG_POLL_RETRY_COUNT); if (ret < 0) { dev_err(bus->dev, "CIP timeout after D0I3C update!\n"); return ret; diff --git a/sound/soc/sof/intel/hda.h b/sound/soc/sof/intel/hda.h index 0e7c366b8f71..99ec60218c16 100644 --- a/sound/soc/sof/intel/hda.h +++ b/sound/soc/sof/intel/hda.h @@ -214,6 +214,7 @@ #define HDA_DSP_CTRL_RESET_TIMEOUT 100 #define HDA_DSP_WAIT_TIMEOUT 500 /* 500 msec */ #define HDA_DSP_REG_POLL_INTERVAL_US 500 /* 0.5 msec */ +#define HDA_DSP_REG_POLL_RETRY_COUNT 50 #define HDA_DSP_ADSPIC_IPC 1 #define HDA_DSP_ADSPIS_IPC 1 -- cgit v1.2.3 From 7c7eba2402c11137d1fa1d3fb964a2c6fc1ded3e Mon Sep 17 00:00:00 2001 From: Keyon Jie Date: Fri, 25 Oct 2019 17:41:08 -0500 Subject: ASoC: SOF: PM: rename sof_send_pm_ipc to sof_send_pm_ctx_ipc The helper sof_send_pm_ipc() is only suitable for context save/restore IPCs' sending, so rename it to sof_send_pm_ctx_ipc here. Signed-off-by: Keyon Jie Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20191025224122.7718-13-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/pm.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/pm.c b/sound/soc/sof/pm.c index 81e623dfc7e5..ac900fb3379e 100644 --- a/sound/soc/sof/pm.c +++ b/sound/soc/sof/pm.c @@ -197,7 +197,7 @@ static int sof_restore_pipelines(struct snd_sof_dev *sdev) return ret; } -static int sof_send_pm_ipc(struct snd_sof_dev *sdev, int cmd) +static int sof_send_pm_ctx_ipc(struct snd_sof_dev *sdev, int cmd) { struct sof_ipc_pm_ctx pm_ctx; struct sof_ipc_reply reply; @@ -320,7 +320,7 @@ static int sof_resume(struct device *dev, bool runtime_resume) } /* notify DSP of system resume */ - ret = sof_send_pm_ipc(sdev, SOF_IPC_PM_CTX_RESTORE); + ret = sof_send_pm_ctx_ipc(sdev, SOF_IPC_PM_CTX_RESTORE); if (ret < 0) dev_err(sdev->dev, "error: ctx_restore ipc error during resume %d\n", @@ -361,7 +361,7 @@ static int sof_suspend(struct device *dev, bool runtime_suspend) sof_cache_debugfs(sdev); #endif /* notify DSP of upcoming power down */ - ret = sof_send_pm_ipc(sdev, SOF_IPC_PM_CTX_SAVE); + ret = sof_send_pm_ctx_ipc(sdev, SOF_IPC_PM_CTX_SAVE); if (ret == -EBUSY || ret == -EAGAIN) { /* * runtime PM has logic to handle -EBUSY/-EAGAIN so -- cgit v1.2.3 From 463fbf6dc03aff41e973602bbad6cb135fa6d48a Mon Sep 17 00:00:00 2001 From: Keyon Jie Date: Fri, 25 Oct 2019 17:41:10 -0500 Subject: ASoC: SOF: Intel: hda-ipc: Don't read mailbox for PM_GATE reply Memory windows could be powered off before receiving PM_GATE IPC reply from FW, we can't read the mailbox to get reply. Signed-off-by: Keyon Jie Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20191025224122.7718-15-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-ipc.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/intel/hda-ipc.c b/sound/soc/sof/intel/hda-ipc.c index 6aae6f18b3dc..0fd2153c1769 100644 --- a/sound/soc/sof/intel/hda-ipc.c +++ b/sound/soc/sof/intel/hda-ipc.c @@ -83,10 +83,12 @@ void hda_dsp_ipc_get_reply(struct snd_sof_dev *sdev) } hdr = msg->msg_data; - if (hdr->cmd == (SOF_IPC_GLB_PM_MSG | SOF_IPC_PM_CTX_SAVE)) { + if (hdr->cmd == (SOF_IPC_GLB_PM_MSG | SOF_IPC_PM_CTX_SAVE) || + hdr->cmd == (SOF_IPC_GLB_PM_MSG | SOF_IPC_PM_GATE)) { /* * memory windows are powered off before sending IPC reply, - * so we can't read the mailbox for CTX_SAVE reply. + * so we can't read the mailbox for CTX_SAVE and PM_GATE + * replies. */ reply.error = 0; reply.hdr.cmd = SOF_IPC_GLB_REPLY; -- cgit v1.2.3 From 5056193d4d1a8b73087145add21141c46027d6a2 Mon Sep 17 00:00:00 2001 From: Keyon Jie Date: Fri, 25 Oct 2019 17:41:11 -0500 Subject: ASoC: SOF: Intel: HDA: add cAVS specific compact IPC header file On cAVS platforms, some IPCs are required to be sent via IPC registers only(e.g. when in D0i3, mailbox is unaccessible), add hda-ipc.h to hold definition of those compact IPCs. Signed-off-by: Keyon Jie Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20191025224122.7718-16-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-ipc.h | 51 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 sound/soc/sof/intel/hda-ipc.h (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/intel/hda-ipc.h b/sound/soc/sof/intel/hda-ipc.h new file mode 100644 index 000000000000..aef0ceac9803 --- /dev/null +++ b/sound/soc/sof/intel/hda-ipc.h @@ -0,0 +1,51 @@ +/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * Copyright(c) 2019 Intel Corporation. All rights reserved. + * + * Author: Keyon Jie + */ + +#ifndef __SOF_INTEL_HDA_IPC_H +#define __SOF_INTEL_HDA_IPC_H + +/* + * Primary register, mapped to + * - DIPCTDR (HIPCIDR) in sideband IPC (cAVS 1.8+) + * - DIPCT in cAVS 1.5 IPC + * + * Secondary register, mapped to: + * - DIPCTDD (HIPCIDD) in sideband IPC (cAVS 1.8+) + * - DIPCTE in cAVS 1.5 IPC + */ + +/* Common bits in primary register */ + +/* Reserved for doorbell */ +#define HDA_IPC_RSVD_31 BIT(31) +/* Target, 0 - normal message, 1 - compact message(cAVS compatible) */ +#define HDA_IPC_MSG_COMPACT BIT(30) +/* Direction, 0 - request, 1 - response */ +#define HDA_IPC_RSP BIT(29) + +#define HDA_IPC_TYPE_SHIFT 24 +#define HDA_IPC_TYPE_MASK GENMASK(28, 24) +#define HDA_IPC_TYPE(x) ((x) << HDA_IPC_TYPE_SHIFT) + +#define HDA_IPC_PM_GATE HDA_IPC_TYPE(0x8U) + +/* Command specific payload bits in secondary register */ + +/* Disable DMA tracing (0 - keep tracing, 1 - to disable DMA trace) */ +#define HDA_PM_NO_DMA_TRACE BIT(4) +/* Prevent clock gating (0 - cg allowed, 1 - DSP clock always on) */ +#define HDA_PM_PCG BIT(3) +/* Prevent power gating (0 - deep power state transitions allowed) */ +#define HDA_PM_PPG BIT(2) +/* Indicates whether streaming is active */ +#define HDA_PM_PG_STREAMING BIT(1) +#define HDA_PM_PG_RSVD BIT(0) + +#endif -- cgit v1.2.3 From 534037fddd34b58be86a826d449a5a6635ecdbf5 Mon Sep 17 00:00:00 2001 From: Keyon Jie Date: Fri, 25 Oct 2019 17:41:12 -0500 Subject: ASoC: SOF: configure D0ix IPC flags in set_power_state The configuration for D0ix in FW is platform specific, let's do this and send IPC in the platform set_power_state() ops. Signed-off-by: Keyon Jie Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20191025224122.7718-17-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-dsp.c | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/intel/hda-dsp.c b/sound/soc/sof/intel/hda-dsp.c index 936361bd25e9..b5070409a5e3 100644 --- a/sound/soc/sof/intel/hda-dsp.c +++ b/sound/soc/sof/intel/hda-dsp.c @@ -19,6 +19,7 @@ #include #include "../ops.h" #include "hda.h" +#include "hda-ipc.h" /* * DSP Core control. @@ -319,10 +320,28 @@ static int hda_dsp_wait_d0i3c_done(struct snd_sof_dev *sdev, int retry) return 0; } +static int hda_dsp_send_pm_gate_ipc(struct snd_sof_dev *sdev, u32 flags) +{ + struct sof_ipc_pm_gate pm_gate; + struct sof_ipc_reply reply; + + memset(&pm_gate, 0, sizeof(pm_gate)); + + /* configure pm_gate ipc message */ + pm_gate.hdr.size = sizeof(pm_gate); + pm_gate.hdr.cmd = SOF_IPC_GLB_PM_MSG | SOF_IPC_PM_GATE; + pm_gate.flags = flags; + + /* send pm_gate ipc to dsp */ + return sof_ipc_tx_message(sdev->ipc, pm_gate.hdr.cmd, &pm_gate, + sizeof(pm_gate), &reply, sizeof(reply)); +} + int hda_dsp_set_power_state(struct snd_sof_dev *sdev, enum sof_d0_substate d0_substate) { struct hdac_bus *bus = sof_to_bus(sdev); + u32 flags; int ret; u8 value; @@ -347,7 +366,18 @@ int hda_dsp_set_power_state(struct snd_sof_dev *sdev, dev_vdbg(bus->dev, "D0I3C updated, register = 0x%x\n", snd_hdac_chip_readb(bus, VS_D0I3C)); - return 0; + if (d0_substate == SOF_DSP_D0I0) + flags = HDA_PM_PPG;/* prevent power gating in D0 */ + else + flags = HDA_PM_NO_DMA_TRACE;/* disable DMA trace in D0I3*/ + + /* sending pm_gate IPC */ + ret = hda_dsp_send_pm_gate_ipc(sdev, flags); + if (ret < 0) + dev_err(sdev->dev, + "error: PM_GATE ipc error %d\n", ret); + + return ret; } static int hda_suspend(struct snd_sof_dev *sdev, bool runtime_suspend) -- cgit v1.2.3 From 601252869f50af6f5ab377e7f4846d7b09cc66c0 Mon Sep 17 00:00:00 2001 From: Keyon Jie Date: Fri, 25 Oct 2019 17:41:13 -0500 Subject: ASoC: SOF: PM: add helpers for setting D0 substate for ADSP Add snd_sof_set_d0_substate() helper for setting ADSP to a specific D0 substate, it will call into the platform specific implementation, and update the d0_substate at success. Signed-off-by: Keyon Jie Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20191025224122.7718-18-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/pm.c | 17 +++++++++++++++++ sound/soc/sof/sof-priv.h | 2 ++ 2 files changed, 19 insertions(+) (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/pm.c b/sound/soc/sof/pm.c index ac900fb3379e..584241e9734a 100644 --- a/sound/soc/sof/pm.c +++ b/sound/soc/sof/pm.c @@ -411,6 +411,23 @@ int snd_sof_runtime_resume(struct device *dev) } EXPORT_SYMBOL(snd_sof_runtime_resume); +int snd_sof_set_d0_substate(struct snd_sof_dev *sdev, + enum sof_d0_substate d0_substate) +{ + int ret; + + /* do platform specific set_state */ + ret = snd_sof_dsp_set_power_state(sdev, d0_substate); + if (ret < 0) + return ret; + + /* update dsp D0 sub-state */ + sdev->d0_substate = d0_substate; + + return 0; +} +EXPORT_SYMBOL(snd_sof_set_d0_substate); + int snd_sof_resume(struct device *dev) { return sof_resume(dev, false); diff --git a/sound/soc/sof/sof-priv.h b/sound/soc/sof/sof-priv.h index 7a21a45d3635..2231c673c678 100644 --- a/sound/soc/sof/sof-priv.h +++ b/sound/soc/sof/sof-priv.h @@ -485,6 +485,8 @@ int snd_sof_runtime_resume(struct device *dev); int snd_sof_runtime_idle(struct device *dev); int snd_sof_resume(struct device *dev); int snd_sof_suspend(struct device *dev); +int snd_sof_set_d0_substate(struct snd_sof_dev *sdev, + enum sof_d0_substate d0_substate); void snd_sof_new_platform_drv(struct snd_sof_dev *sdev); -- cgit v1.2.3 From 0267de58acfe5059ace739741f1533dd605ed22f Mon Sep 17 00:00:00 2001 From: Keyon Jie Date: Fri, 25 Oct 2019 17:41:14 -0500 Subject: ASoC: SOF: Intel: CNL: add support for sending compact IPC For compact IPCs, we will send the IPC header/command via the HIPCIDR register and the first 32bit payload via the HIPCIDD register, no mailbox will be used. Signed-off-by: Keyon Jie Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20191025224122.7718-19-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/cnl.c | 42 +++++++++++++++++++++++++++++++++++++----- sound/soc/sof/intel/hda.h | 1 + 2 files changed, 38 insertions(+), 5 deletions(-) (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/intel/cnl.c b/sound/soc/sof/intel/cnl.c index 982b81a0b13a..0e1e265f3f3b 100644 --- a/sound/soc/sof/intel/cnl.c +++ b/sound/soc/sof/intel/cnl.c @@ -17,6 +17,7 @@ #include "../ops.h" #include "hda.h" +#include "hda-ipc.h" static const struct snd_sof_debugfs_map cnl_dsp_debugfs[] = { {"hda", HDA_DSP_HDA_BAR, 0, 0x4000, SOF_DEBUGFS_ACCESS_ALWAYS}, @@ -150,14 +151,45 @@ static void cnl_ipc_dsp_done(struct snd_sof_dev *sdev) CNL_DSP_REG_HIPCCTL_DONE); } +static bool cnl_compact_ipc_compress(struct snd_sof_ipc_msg *msg, + u32 *dr, u32 *dd) +{ + struct sof_ipc_pm_gate *pm_gate; + + if (msg->header == (SOF_IPC_GLB_PM_MSG | SOF_IPC_PM_GATE)) { + pm_gate = msg->msg_data; + + /* send the compact message via the primary register */ + *dr = HDA_IPC_MSG_COMPACT | HDA_IPC_PM_GATE; + + /* send payload via the extended data register */ + *dd = pm_gate->flags; + + return true; + } + + return false; +} + static int cnl_ipc_send_msg(struct snd_sof_dev *sdev, struct snd_sof_ipc_msg *msg) { - /* send the message */ - sof_mailbox_write(sdev, sdev->host_box.offset, msg->msg_data, - msg->msg_size); - snd_sof_dsp_write(sdev, HDA_DSP_BAR, CNL_DSP_REG_HIPCIDR, - CNL_DSP_REG_HIPCIDR_BUSY); + u32 dr = 0; + u32 dd = 0; + + if (cnl_compact_ipc_compress(msg, &dr, &dd)) { + /* send the message via IPC registers */ + snd_sof_dsp_write(sdev, HDA_DSP_BAR, CNL_DSP_REG_HIPCIDD, + dd); + snd_sof_dsp_write(sdev, HDA_DSP_BAR, CNL_DSP_REG_HIPCIDR, + CNL_DSP_REG_HIPCIDR_BUSY | dr); + } else { + /* send the message via mailbox */ + sof_mailbox_write(sdev, sdev->host_box.offset, msg->msg_data, + msg->msg_size); + snd_sof_dsp_write(sdev, HDA_DSP_BAR, CNL_DSP_REG_HIPCIDR, + CNL_DSP_REG_HIPCIDR_BUSY); + } return 0; } diff --git a/sound/soc/sof/intel/hda.h b/sound/soc/sof/intel/hda.h index 99ec60218c16..52a87a47029d 100644 --- a/sound/soc/sof/intel/hda.h +++ b/sound/soc/sof/intel/hda.h @@ -312,6 +312,7 @@ #define CNL_DSP_REG_HIPCTDD (CNL_DSP_IPC_BASE + 0x08) #define CNL_DSP_REG_HIPCIDR (CNL_DSP_IPC_BASE + 0x10) #define CNL_DSP_REG_HIPCIDA (CNL_DSP_IPC_BASE + 0x14) +#define CNL_DSP_REG_HIPCIDD (CNL_DSP_IPC_BASE + 0x18) #define CNL_DSP_REG_HIPCCTL (CNL_DSP_IPC_BASE + 0x28) /* HIPCI */ -- cgit v1.2.3 From 7367d3096b1443e55a2c730d1966f423b15d5cad Mon Sep 17 00:00:00 2001 From: Keyon Jie Date: Fri, 25 Oct 2019 17:41:15 -0500 Subject: ASoC: SOF: add a flag to indicate the system suspend target Add flag 's0_suspend' to indicate if the system is entering S0ix or not. Signed-off-by: Keyon Jie Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20191025224122.7718-20-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/sof-priv.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/sof-priv.h b/sound/soc/sof/sof-priv.h index 2231c673c678..e715673f20e5 100644 --- a/sound/soc/sof/sof-priv.h +++ b/sound/soc/sof/sof-priv.h @@ -398,6 +398,8 @@ struct snd_sof_dev { /* power states related */ enum sof_d0_substate d0_substate; + /* flag to track if the intended power target of suspend is S0ix */ + bool s0_suspend; /* DSP firmware boot */ wait_queue_head_t boot_wait; -- cgit v1.2.3 From 4cd933abd4820da7eefe672ff439b32d199a07be Mon Sep 17 00:00:00 2001 From: Keyon Jie Date: Fri, 25 Oct 2019 17:41:16 -0500 Subject: ASoC: SOF: add a flag suspend_ignored for sof stream Add a suspend_ignored flag to snd_sof_pcm_stream that will be used to decide if the corresponding FW pipeline should be kept active to perform always on tasks when the system is entering the S0ix state. Signed-off-by: Keyon Jie Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20191025224122.7718-21-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/sof-priv.h | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/sof-priv.h b/sound/soc/sof/sof-priv.h index e715673f20e5..c2541d020bde 100644 --- a/sound/soc/sof/sof-priv.h +++ b/sound/soc/sof/sof-priv.h @@ -311,6 +311,11 @@ struct snd_sof_pcm_stream { struct snd_pcm_substream *substream; struct work_struct period_elapsed_work; bool d0i3_compatible; /* DSP can be in D0I3 when this pcm is opened */ + /* + * flag to indicate that the DSP pipelines should be kept + * active or not while suspending the stream + */ + bool suspend_ignored; }; /* ALSA SOF PCM device */ -- cgit v1.2.3 From 0b50b3b1c3bc2a2c9eeab418b3de3e60e0530cf4 Mon Sep 17 00:00:00 2001 From: Keyon Jie Date: Fri, 25 Oct 2019 17:41:17 -0500 Subject: ASoC: SOF: PM: implement prepare/complete callbacks Implement the prepare() and complete() callbacks for power management, initialize s0_suspend flag at prepare(), and reset it at complete(). Signed-off-by: Keyon Jie Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20191025224122.7718-22-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/pm.c | 23 +++++++++++++++++++++++ sound/soc/sof/sof-priv.h | 2 ++ 2 files changed, 25 insertions(+) (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/pm.c b/sound/soc/sof/pm.c index 584241e9734a..99e4e6ffff74 100644 --- a/sound/soc/sof/pm.c +++ b/sound/soc/sof/pm.c @@ -439,3 +439,26 @@ int snd_sof_suspend(struct device *dev) return sof_suspend(dev, false); } EXPORT_SYMBOL(snd_sof_suspend); + +int snd_sof_prepare(struct device *dev) +{ + struct snd_sof_dev *sdev = dev_get_drvdata(dev); + +#if defined(CONFIG_ACPI) + sdev->s0_suspend = acpi_target_system_state() == ACPI_STATE_S0; +#else + /* will suspend to S3 by default */ + sdev->s0_suspend = false; +#endif + + return 0; +} +EXPORT_SYMBOL(snd_sof_prepare); + +void snd_sof_complete(struct device *dev) +{ + struct snd_sof_dev *sdev = dev_get_drvdata(dev); + + sdev->s0_suspend = false; +} +EXPORT_SYMBOL(snd_sof_complete); diff --git a/sound/soc/sof/sof-priv.h b/sound/soc/sof/sof-priv.h index c2541d020bde..6408ac88a3e5 100644 --- a/sound/soc/sof/sof-priv.h +++ b/sound/soc/sof/sof-priv.h @@ -492,6 +492,8 @@ int snd_sof_runtime_resume(struct device *dev); int snd_sof_runtime_idle(struct device *dev); int snd_sof_resume(struct device *dev); int snd_sof_suspend(struct device *dev); +int snd_sof_prepare(struct device *dev); +void snd_sof_complete(struct device *dev); int snd_sof_set_d0_substate(struct snd_sof_dev *sdev, enum sof_d0_substate d0_substate); -- cgit v1.2.3 From ac8c046f19f94ec419c60d7a073af75a71386e97 Mon Sep 17 00:00:00 2001 From: Keyon Jie Date: Fri, 25 Oct 2019 17:41:18 -0500 Subject: ASoC: SOF: ignore suspend/resume for D0ix compatible streams During system suspend, the PM framework will freeze all applications and the ALSA/ASoC core will suspend all RUNNING PCM streams. However, D0ix-compatible PCM streams should keep the related pipelines active in the DSP when the system is entering S0ix. The TRIGGER_SUSPEND event is trapped in such cases to prevent the pipelines from being stopped. Likewise, the TRIGGER_RESUME/START events should not affect the pipeline state. The SOF driver also triggers some DSP Firmware pipelines based on the DAPM widgets power events. In such cases, we also ignore PRE_PMU and POST_PMD events to keep the pipelines active. Signed-off-by: Keyon Jie Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20191025224122.7718-23-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/pcm.c | 31 +++++++++++++++++++++++++++++++ sound/soc/sof/topology.c | 17 ++++++++++++++++- 2 files changed, 47 insertions(+), 1 deletion(-) (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/pcm.c b/sound/soc/sof/pcm.c index 9ba505cf5966..3d5cd1b445ba 100644 --- a/sound/soc/sof/pcm.c +++ b/sound/soc/sof/pcm.c @@ -346,6 +346,16 @@ static int sof_pcm_trigger(struct snd_soc_component *component, stream.hdr.cmd |= SOF_IPC_STREAM_TRIG_RELEASE; break; case SNDRV_PCM_TRIGGER_RESUME: + if (spcm->stream[substream->stream].suspend_ignored) { + /* + * this case will be triggered when INFO_RESUME is + * supported, no need to resume streams that remained + * enabled in D0ix. + */ + spcm->stream[substream->stream].suspend_ignored = false; + return 0; + } + /* set up hw_params */ ret = sof_pcm_prepare(component, substream); if (ret < 0) { @@ -356,9 +366,30 @@ static int sof_pcm_trigger(struct snd_soc_component *component, /* fallthrough */ case SNDRV_PCM_TRIGGER_START: + if (spcm->stream[substream->stream].suspend_ignored) { + /* + * This case will be triggered when INFO_RESUME is + * not supported, no need to re-start streams that + * remained enabled in D0ix. + */ + spcm->stream[substream->stream].suspend_ignored = false; + return 0; + } stream.hdr.cmd |= SOF_IPC_STREAM_TRIG_START; break; case SNDRV_PCM_TRIGGER_SUSPEND: + if (sdev->s0_suspend && + spcm->stream[substream->stream].d0i3_compatible) { + /* + * trap the event, not sending trigger stop to + * prevent the FW pipelines from being stopped, + * and mark the flag to ignore the upcoming DAPM + * PM events. + */ + spcm->stream[substream->stream].suspend_ignored = true; + return 0; + } + /* fallthrough */ case SNDRV_PCM_TRIGGER_STOP: stream.hdr.cmd |= SOF_IPC_STREAM_TRIG_STOP; ipc_first = true; diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c index cc138ac6a8eb..e0e2ae734632 100644 --- a/sound/soc/sof/topology.c +++ b/sound/soc/sof/topology.c @@ -135,7 +135,9 @@ static int sof_keyword_dapm_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *k, int event) { struct snd_sof_widget *swidget = w->dobj.private; + int stream = SNDRV_PCM_STREAM_CAPTURE; struct snd_sof_dev *sdev; + struct snd_sof_pcm *spcm; int ret = 0; if (!swidget) @@ -146,11 +148,19 @@ static int sof_keyword_dapm_event(struct snd_soc_dapm_widget *w, dev_dbg(sdev->dev, "received event %d for widget %s\n", event, w->name); + /* get runtime PCM params using widget's stream name */ + spcm = snd_sof_find_spcm_name(sdev, swidget->widget->sname); + /* process events */ switch (event) { case SND_SOC_DAPM_PRE_PMU: + if (spcm->stream[stream].suspend_ignored) { + dev_dbg(sdev->dev, "PRE_PMU event ignored, KWD pipeline is already RUNNING\n"); + return 0; + } + /* set pcm params */ - ret = ipc_pcm_params(swidget, SOF_IPC_STREAM_CAPTURE); + ret = ipc_pcm_params(swidget, stream); if (ret < 0) { dev_err(sdev->dev, "error: failed to set pcm params for widget %s\n", @@ -166,6 +176,11 @@ static int sof_keyword_dapm_event(struct snd_soc_dapm_widget *w, swidget->widget->name); break; case SND_SOC_DAPM_POST_PMD: + if (spcm->stream[stream].suspend_ignored) { + dev_dbg(sdev->dev, "POST_PMD even ignored, KWD pipeline will remain RUNNING\n"); + return 0; + } + /* stop trigger */ ret = ipc_trigger(swidget, SOF_IPC_STREAM_TRIG_STOP); if (ret < 0) -- cgit v1.2.3 From 66e40876ddc325d892c493a6d83574bbba5770ce Mon Sep 17 00:00:00 2001 From: Keyon Jie Date: Fri, 25 Oct 2019 17:41:19 -0500 Subject: ASoC: SOF: Intel: hda-dsp: implement suspend/resume for S0ix<->S0 transition Enable system wake up via IPC interrupt from DSP when the system is suspending to the S0ix state, and disable it in the corresponding resuming. Signed-off-by: Keyon Jie Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20191025224122.7718-24-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-dsp.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/intel/hda-dsp.c b/sound/soc/sof/intel/hda-dsp.c index b5070409a5e3..d23573d9e9c4 100644 --- a/sound/soc/sof/intel/hda-dsp.c +++ b/sound/soc/sof/intel/hda-dsp.c @@ -477,6 +477,15 @@ static int hda_resume(struct snd_sof_dev *sdev, bool runtime_resume) int hda_dsp_resume(struct snd_sof_dev *sdev) { + struct pci_dev *pci = to_pci_dev(sdev->dev); + + if (sdev->s0_suspend) { + /* restore and disable the system wakeup */ + pci_restore_state(pci); + disable_irq_wake(pci->irq); + return 0; + } + /* init hda controller. DSP cores will be powered up during fw boot */ return hda_resume(sdev, false); } @@ -509,8 +518,16 @@ int hda_dsp_runtime_suspend(struct snd_sof_dev *sdev) int hda_dsp_suspend(struct snd_sof_dev *sdev) { struct hdac_bus *bus = sof_to_bus(sdev); + struct pci_dev *pci = to_pci_dev(sdev->dev); int ret; + if (sdev->s0_suspend) { + /* enable the system waking up via IPC IRQ */ + enable_irq_wake(pci->irq); + pci_save_state(pci); + return 0; + } + /* stop hda controller and power dsp off */ ret = hda_suspend(sdev, false); if (ret < 0) { -- cgit v1.2.3 From 5655ce660a6d3eec4a3ad37feb99fb228540d1a9 Mon Sep 17 00:00:00 2001 From: Keyon Jie Date: Fri, 25 Oct 2019 17:41:20 -0500 Subject: ASoC: SOF: return -ENOTSUPP if D0I3 is not supported No set_power_state ops means that the platform doesn't support D0i3, return -ENOTSUPP for the case. Signed-off-by: Keyon Jie Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20191025224122.7718-25-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/ops.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/ops.h b/sound/soc/sof/ops.h index d7c8fc06f961..93512dcbaacd 100644 --- a/sound/soc/sof/ops.h +++ b/sound/soc/sof/ops.h @@ -199,7 +199,8 @@ static inline int snd_sof_dsp_set_power_state(struct snd_sof_dev *sdev, if (sof_ops(sdev)->set_power_state) return sof_ops(sdev)->set_power_state(sdev, substate); - return 0; + /* D0 substate is not supported */ + return -ENOTSUPP; } /* debug */ -- cgit v1.2.3 From c470fc3f61b25e955f8ba90fc9dc554881e4e72c Mon Sep 17 00:00:00 2001 From: Keyon Jie Date: Fri, 25 Oct 2019 17:41:21 -0500 Subject: ASoC: SOF: PM: Add support for DSP D0i3 state when entering S0ix When system is entering into S0ix, the PCI device may transition to the D0i3 substate instead of D3. In D0i3, some always-on functionality can be enabled, such as acoustic event detection, voice activity detection or hotwording. When an event is detected, the DSP firmware can wake-up the device for a transition to D0 with an interrupt. Signed-off-by: Keyon Jie Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20191025224122.7718-26-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/pm.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/pm.c b/sound/soc/sof/pm.c index 99e4e6ffff74..560a937e0484 100644 --- a/sound/soc/sof/pm.c +++ b/sound/soc/sof/pm.c @@ -430,12 +430,58 @@ EXPORT_SYMBOL(snd_sof_set_d0_substate); int snd_sof_resume(struct device *dev) { + struct snd_sof_dev *sdev = dev_get_drvdata(dev); + int ret; + + if (sdev->s0_suspend) { + /* resume from D0I3 */ + dev_dbg(sdev->dev, "DSP will exit from D0i3...\n"); + ret = snd_sof_set_d0_substate(sdev, SOF_DSP_D0I0); + if (ret == -ENOTSUPP) { + /* fallback to resume from D3 */ + dev_dbg(sdev->dev, "D0i3 not supported, fall back to resume from D3...\n"); + goto d3_resume; + } else if (ret < 0) { + dev_err(sdev->dev, "error: failed to exit from D0I3 %d\n", + ret); + return ret; + } + + /* platform-specific resume from D0i3 */ + return snd_sof_dsp_resume(sdev); + } + +d3_resume: + /* resume from D3 */ return sof_resume(dev, false); } EXPORT_SYMBOL(snd_sof_resume); int snd_sof_suspend(struct device *dev) { + struct snd_sof_dev *sdev = dev_get_drvdata(dev); + int ret; + + if (sdev->s0_suspend) { + /* suspend to D0i3 */ + dev_dbg(sdev->dev, "DSP is trying to enter D0i3...\n"); + ret = snd_sof_set_d0_substate(sdev, SOF_DSP_D0I3); + if (ret == -ENOTSUPP) { + /* fallback to D3 suspend */ + dev_dbg(sdev->dev, "D0i3 not supported, fall back to D3...\n"); + goto d3_suspend; + } else if (ret < 0) { + dev_err(sdev->dev, "error: failed to enter D0I3, %d\n", + ret); + return ret; + } + + /* platform-specific suspend to D0i3 */ + return snd_sof_dsp_suspend(sdev); + } + +d3_suspend: + /* suspend to D3 */ return sof_suspend(dev, false); } EXPORT_SYMBOL(snd_sof_suspend); -- cgit v1.2.3 From 6d407a39cc9619d0088b44333c6526924be00f8d Mon Sep 17 00:00:00 2001 From: Keyon Jie Date: Fri, 25 Oct 2019 17:41:22 -0500 Subject: ASoC: SOF: pci: Add prepare/complete PM callbacks Use the new implemented snd_sof_prepare() and snd_sof_complete() as the power management callbacks for pci probing platforms. Signed-off-by: Keyon Jie Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20191025224122.7718-27-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/sof-pci-dev.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/sof-pci-dev.c b/sound/soc/sof/sof-pci-dev.c index 4adbb27c76c5..487b1f29f84d 100644 --- a/sound/soc/sof/sof-pci-dev.c +++ b/sound/soc/sof/sof-pci-dev.c @@ -264,6 +264,8 @@ static const struct sof_dev_desc jsl_desc = { #endif static const struct dev_pm_ops sof_pci_pm = { + .prepare = snd_sof_prepare, + .complete = snd_sof_complete, SET_SYSTEM_SLEEP_PM_OPS(snd_sof_suspend, snd_sof_resume) SET_RUNTIME_PM_OPS(snd_sof_runtime_suspend, snd_sof_runtime_resume, snd_sof_runtime_idle) -- cgit v1.2.3 From c3ad1092e1069f27d0ca110dcaada8a5435ea3e0 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 28 Oct 2019 18:33:29 +0100 Subject: ASoC: SOF - remove the dead code (skylake/kabylake) Appearently the CONFIG_SND_SOC_SOF_KABYLAKE and CONFIG_SND_SOC_SOF_SKYLAKE options are not present in Kconfig and 'struct snd_sof_dsp_ops sof_skl_ops' is not declared in the code, too. Signed-off-by: Jaroslav Kysela Cc: Pierre-Louis Bossart Cc: Mark Brown Link: https://lore.kernel.org/r/20191028173329.29538-1-perex@perex.cz Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda.h | 1 - sound/soc/sof/sof-pci-dev.c | 44 -------------------------------------------- 2 files changed, 45 deletions(-) (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/intel/hda.h b/sound/soc/sof/intel/hda.h index 52a87a47029d..16376f55e420 100644 --- a/sound/soc/sof/intel/hda.h +++ b/sound/soc/sof/intel/hda.h @@ -608,7 +608,6 @@ extern struct snd_soc_dai_driver skl_dai[]; */ extern const struct snd_sof_dsp_ops sof_apl_ops; extern const struct snd_sof_dsp_ops sof_cnl_ops; -extern const struct snd_sof_dsp_ops sof_skl_ops; extern const struct sof_intel_dsp_desc apl_chip_info; extern const struct sof_intel_dsp_desc cnl_chip_info; diff --git a/sound/soc/sof/sof-pci-dev.c b/sound/soc/sof/sof-pci-dev.c index 487b1f29f84d..4de90d04a91b 100644 --- a/sound/soc/sof/sof-pci-dev.c +++ b/sound/soc/sof/sof-pci-dev.c @@ -173,42 +173,6 @@ static const struct sof_dev_desc icl_desc = { }; #endif -#if IS_ENABLED(CONFIG_SND_SOC_SOF_SKYLAKE) -static const struct sof_dev_desc skl_desc = { - .machines = snd_soc_acpi_intel_skl_machines, - .resindex_lpe_base = 0, - .resindex_pcicfg_base = -1, - .resindex_imr_base = -1, - .irqindex_host_ipc = -1, - .resindex_dma_base = -1, - .chip_info = &skl_chip_info, - .default_fw_path = "intel/sof", - .default_tplg_path = "intel/sof-tplg", - .nocodec_fw_filename = "sof-skl.ri", - .nocodec_tplg_filename = "sof-skl-nocodec.tplg", - .ops = &sof_skl_ops, - .arch_ops = &sof_xtensa_arch_ops -}; -#endif - -#if IS_ENABLED(CONFIG_SND_SOC_SOF_KABYLAKE) -static const struct sof_dev_desc kbl_desc = { - .machines = snd_soc_acpi_intel_kbl_machines, - .resindex_lpe_base = 0, - .resindex_pcicfg_base = -1, - .resindex_imr_base = -1, - .irqindex_host_ipc = -1, - .resindex_dma_base = -1, - .chip_info = &skl_chip_info, - .default_fw_path = "intel/sof", - .default_tplg_path = "intel/sof-tplg", - .nocodec_fw_filename = "sof-kbl.ri", - .nocodec_tplg_filename = "sof-kbl-nocodec.tplg", - .ops = &sof_skl_ops, - .arch_ops = &sof_xtensa_arch_ops -}; -#endif - #if IS_ENABLED(CONFIG_SND_SOC_SOF_TIGERLAKE) static const struct sof_dev_desc tgl_desc = { .machines = snd_soc_acpi_intel_tgl_machines, @@ -431,14 +395,6 @@ static const struct pci_device_id sof_pci_ids[] = { { PCI_DEVICE(0x8086, 0xa348), .driver_data = (unsigned long)&cfl_desc}, #endif -#if IS_ENABLED(CONFIG_SND_SOC_SOF_KABYLAKE) - { PCI_DEVICE(0x8086, 0x9d71), - .driver_data = (unsigned long)&kbl_desc}, -#endif -#if IS_ENABLED(CONFIG_SND_SOC_SOF_SKYLAKE) - { PCI_DEVICE(0x8086, 0x9d70), - .driver_data = (unsigned long)&skl_desc}, -#endif #if IS_ENABLED(CONFIG_SND_SOC_SOF_ICELAKE) { PCI_DEVICE(0x8086, 0x34C8), .driver_data = (unsigned long)&icl_desc}, -- cgit v1.2.3 From 139c7febad1afa221c687f3314560284e482a1f4 Mon Sep 17 00:00:00 2001 From: Kai Vehmanen Date: Tue, 29 Oct 2019 15:40:13 +0200 Subject: ASoC: SOF: Intel: add support for snd-hda-codec-hdmi Add support to implement HDMI/DP audio by using the common snd-hda-codec-hdmi driver. Change of codec driver affects user-space as the two drivers expose different mixer controls. A new kernel module option "use_common_hdmi" is added to user-space to indicate which interface should be used. The default driver can be selected via a Kconfig option. Signed-off-by: Kai Vehmanen Reviewed-by: Takashi Iwai Reviewed-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20191029134017.18901-6-kai.vehmanen@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/Kconfig | 10 ++++++++++ sound/soc/sof/intel/hda-codec.c | 22 ++++++++++++++++++---- sound/soc/sof/intel/hda.c | 6 ++++++ sound/soc/sof/intel/hda.h | 6 ++++-- 4 files changed, 38 insertions(+), 6 deletions(-) (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/intel/Kconfig b/sound/soc/sof/intel/Kconfig index 342f22a7c64f..d52298946c00 100644 --- a/sound/soc/sof/intel/Kconfig +++ b/sound/soc/sof/intel/Kconfig @@ -299,6 +299,16 @@ config SND_SOC_SOF_HDA_ALWAYS_ENABLE_DMI_L1 Say Y if you want to enable DMI Link L1 If unsure, select "N". +config SND_SOC_SOF_HDA_COMMON_HDMI_CODEC + bool "SOF common HDA HDMI codec driver" + depends on SND_SOC_SOF_HDA_LINK + depends on SND_HDA_CODEC_HDMI + help + This adds support for HDMI audio by using the common HDA + HDMI/DisplayPort codec driver. + Say Y if you want to use the common codec driver with SOF. + If unsure select "Y". + endif ## SND_SOC_SOF_HDA_COMMON config SND_SOC_SOF_HDA_LINK_BASELINE diff --git a/sound/soc/sof/intel/hda-codec.c b/sound/soc/sof/intel/hda-codec.c index 3ca6795a89ba..827f84a0722e 100644 --- a/sound/soc/sof/intel/hda-codec.c +++ b/sound/soc/sof/intel/hda-codec.c @@ -84,6 +84,8 @@ static int hda_codec_probe(struct snd_sof_dev *sdev, int address) { #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC) struct hdac_hda_priv *hda_priv; + struct snd_soc_acpi_mach_params *mach_params = NULL; + struct snd_sof_pdata *pdata = sdev->pdata; #endif struct hda_bus *hbus = sof_to_hbus(sdev); struct hdac_device *hdev; @@ -113,8 +115,19 @@ static int hda_codec_probe(struct snd_sof_dev *sdev, int address) if (ret < 0) return ret; - /* use legacy bus only for HDA codecs, idisp uses ext bus */ - if ((resp & 0xFFFF0000) != IDISP_VID_INTEL) { + if (pdata->machine) + mach_params = (struct snd_soc_acpi_mach_params *) + &pdata->machine->mach_params; + + if ((resp & 0xFFFF0000) == IDISP_VID_INTEL) + hda_priv->need_display_power = true; + + /* + * if common HDMI codec driver is not used, codec load + * is skipped here and hdac_hdmi is used instead + */ + if ((mach_params && mach_params->common_hdmi_codec_drv) || + (resp & 0xFFFF0000) != IDISP_VID_INTEL) { hdev->type = HDA_DEV_LEGACY; hda_codec_load_module(&hda_priv->codec); } @@ -155,7 +168,8 @@ int hda_codec_probe_bus(struct snd_sof_dev *sdev) } EXPORT_SYMBOL(hda_codec_probe_bus); -#if IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI) +#if IS_ENABLED(CONFIG_SND_HDA_CODEC_HDMI) || \ + IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI) void hda_codec_i915_get(struct snd_sof_dev *sdev) { @@ -204,6 +218,6 @@ int hda_codec_i915_exit(struct snd_sof_dev *sdev) } EXPORT_SYMBOL(hda_codec_i915_exit); -#endif /* CONFIG_SND_SOC_HDAC_HDMI */ +#endif MODULE_LICENSE("Dual BSD/GPL"); diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index 103f4273c4d3..7dc0018dc4c3 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -53,6 +53,11 @@ MODULE_PARM_DESC(use_msi, "SOF HDA use PCI MSI mode"); static int hda_dmic_num = -1; module_param_named(dmic_num, hda_dmic_num, int, 0444); MODULE_PARM_DESC(dmic_num, "SOF HDA DMIC number"); + +static bool hda_codec_use_common_hdmi = + IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_COMMON_HDMI_CODEC); +module_param_named(use_common_hdmi, hda_codec_use_common_hdmi, bool, 0444); +MODULE_PARM_DESC(use_common_hdmi, "SOF HDA use common HDMI codec driver"); #endif static const struct hda_dsp_msg_code hda_dsp_rom_msg[] = { @@ -459,6 +464,7 @@ static int hda_init_caps(struct snd_sof_dev *sdev) &pdata->machine->mach_params; mach_params->codec_mask = bus->codec_mask; mach_params->platform = dev_name(sdev->dev); + mach_params->common_hdmi_codec_drv = hda_codec_use_common_hdmi; } /* create codec instances */ diff --git a/sound/soc/sof/intel/hda.h b/sound/soc/sof/intel/hda.h index 16376f55e420..5ad73a34b09c 100644 --- a/sound/soc/sof/intel/hda.h +++ b/sound/soc/sof/intel/hda.h @@ -577,7 +577,9 @@ void hda_codec_jack_check(struct snd_sof_dev *sdev); #endif /* CONFIG_SND_SOC_SOF_HDA */ -#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) && IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI) +#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) && \ + (IS_ENABLED(CONFIG_SND_HDA_CODEC_HDMI) || \ + IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI)) void hda_codec_i915_get(struct snd_sof_dev *sdev); void hda_codec_i915_put(struct snd_sof_dev *sdev); @@ -591,7 +593,7 @@ static inline void hda_codec_i915_put(struct snd_sof_dev *sdev) { } static inline int hda_codec_i915_init(struct snd_sof_dev *sdev) { return 0; } static inline int hda_codec_i915_exit(struct snd_sof_dev *sdev) { return 0; } -#endif /* CONFIG_SND_SOC_SOF_HDA && CONFIG_SND_SOC_HDAC_HDMI */ +#endif /* * Trace Control. -- cgit v1.2.3 From 65c56f5dccc87ca2993a50672e144c7378189f2c Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Fri, 1 Nov 2019 12:09:16 -0500 Subject: ASoC: SOF: Intel: hda: Simplify the hda_dsp_wait_d0i3c_done() function Remove the retry argument for the hda_dsp_wait_d0i3c_done() function and use the HDA_DSP_REG_POLL_RETRY_COUNT macro directly. Signed-off-by: Ranjani Sridharan Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20191101170916.26517-4-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-dsp.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/intel/hda-dsp.c b/sound/soc/sof/intel/hda-dsp.c index d23573d9e9c4..8cd5ecc01b62 100644 --- a/sound/soc/sof/intel/hda-dsp.c +++ b/sound/soc/sof/intel/hda-dsp.c @@ -307,9 +307,10 @@ void hda_dsp_ipc_int_disable(struct snd_sof_dev *sdev) HDA_DSP_REG_HIPCCTL_BUSY | HDA_DSP_REG_HIPCCTL_DONE, 0); } -static int hda_dsp_wait_d0i3c_done(struct snd_sof_dev *sdev, int retry) +static int hda_dsp_wait_d0i3c_done(struct snd_sof_dev *sdev) { struct hdac_bus *bus = sof_to_bus(sdev); + int retry = HDA_DSP_REG_POLL_RETRY_COUNT; while (snd_hdac_chip_readb(bus, VS_D0I3C) & SOF_HDA_VS_D0I3C_CIP) { if (!retry--) @@ -346,7 +347,7 @@ int hda_dsp_set_power_state(struct snd_sof_dev *sdev, u8 value; /* Write to D0I3C after Command-In-Progress bit is cleared */ - ret = hda_dsp_wait_d0i3c_done(sdev, HDA_DSP_REG_POLL_RETRY_COUNT); + ret = hda_dsp_wait_d0i3c_done(sdev); if (ret < 0) { dev_err(bus->dev, "CIP timeout before D0I3C update!\n"); return ret; @@ -357,7 +358,7 @@ int hda_dsp_set_power_state(struct snd_sof_dev *sdev, snd_hdac_chip_updateb(bus, VS_D0I3C, SOF_HDA_VS_D0I3C_I3, value); /* Wait for cmd in progress to be cleared before exiting the function */ - ret = hda_dsp_wait_d0i3c_done(sdev, HDA_DSP_REG_POLL_RETRY_COUNT); + ret = hda_dsp_wait_d0i3c_done(sdev); if (ret < 0) { dev_err(bus->dev, "CIP timeout after D0I3C update!\n"); return ret; -- cgit v1.2.3 From df7257e544faf838c3e7ad6b4e89ffe59e87f5e1 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 1 Nov 2019 12:30:35 -0500 Subject: ASoC: SOF: Intel: Baytrail: clarify mutual exclusion with Atom/SST driver Some distros select all options blindly, which leads to confusion and bug reports. Since SOF does not support Baytrail-CR for now, and UCM/topology files are still being propagated to downstream distros, make SOF on Baytrail an opt-in option that first require distros to opt-out of existing defaults. Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20191101173045.27099-2-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/Kconfig | 3 +++ sound/soc/sof/intel/Kconfig | 10 +++++++++- 2 files changed, 12 insertions(+), 1 deletion(-) (limited to 'sound/soc/sof') diff --git a/sound/soc/intel/Kconfig b/sound/soc/intel/Kconfig index 01c99750212a..ba5b90e66e2f 100644 --- a/sound/soc/intel/Kconfig +++ b/sound/soc/intel/Kconfig @@ -101,6 +101,9 @@ config SND_SST_ATOM_HIFI2_PLATFORM_ACPI If you have a Intel Baytrail or Cherrytrail platform with an I2S codec, then enable this option by saying Y or m. This is a recommended option + This option is mutually exclusive with the SOF support on + Baytrail/Cherrytrail. If you want to enable SOF on + Baytrail/Cherrytrail, you need to deselect this option first. config SND_SOC_INTEL_SKYLAKE tristate "All Skylake/SST Platforms" diff --git a/sound/soc/sof/intel/Kconfig b/sound/soc/sof/intel/Kconfig index d52298946c00..973c137a6c5a 100644 --- a/sound/soc/sof/intel/Kconfig +++ b/sound/soc/sof/intel/Kconfig @@ -62,10 +62,18 @@ if SND_SOC_SOF_INTEL_ACPI config SND_SOC_SOF_BAYTRAIL_SUPPORT bool "SOF support for Baytrail, Braswell and Cherrytrail" + depends on SND_SST_ATOM_HIFI2_PLATFORM_ACPI=n help This adds support for Sound Open Firmware for Intel(R) platforms using the Baytrail, Braswell or Cherrytrail processors. - Say Y if you have such a device. + This option is mutually exclusive with the Atom/SST and Baytrail + legacy drivers. If you want to enable SOF on Baytrail/Cherrytrail, + you need to deselect those options first. + SOF does not support Baytrail-CR for now, so this option is not + recommended for distros. At some point all legacy drivers will be + deprecated but not before all userspace firmware/topology/UCM files + are made available to downstream distros. + Say Y if you want to enable SOF on Baytrail/Cherrytrail If unsure select "N". config SND_SOC_SOF_BAYTRAIL -- cgit v1.2.3 From a6955fe0e2309feeab5ec71e4b0dcbe498f4f497 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 1 Nov 2019 12:30:36 -0500 Subject: ASoC: SOF: Intel: Broadwell: clarify mutual exclusion with legacy driver Some distros select all options blindly, which leads to confusion and bug reports. SOF does not fully support Broadwell due to firmware dependencies, the machine drivers can only support one option, and UCM/topology files are still being propagated to downstream distros, so make SOF on Broadwell an opt-in option that first require distros to opt-out of existing defaults. Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=204237 Fixes: f35bf70f61d3 ('ASoC: Intel: Make sure BDW based machine drivers build for SOF') Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20191101173045.27099-3-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/Kconfig | 3 +++ sound/soc/sof/intel/Kconfig | 10 +++++++++- 2 files changed, 12 insertions(+), 1 deletion(-) (limited to 'sound/soc/sof') diff --git a/sound/soc/intel/Kconfig b/sound/soc/intel/Kconfig index ba5b90e66e2f..93ebe1297e41 100644 --- a/sound/soc/intel/Kconfig +++ b/sound/soc/intel/Kconfig @@ -59,6 +59,9 @@ config SND_SOC_INTEL_HASWELL If you have a Intel Haswell or Broadwell platform connected to an I2S codec, then enable this option by saying Y or m. This is typically used for Chromebooks. This is a recommended option. + This option is mutually exclusive with the SOF support on + Broadwell. If you want to enable SOF on Broadwell, you need to + deselect this option first. config SND_SOC_INTEL_BAYTRAIL tristate "Baytrail (legacy) Platforms" diff --git a/sound/soc/sof/intel/Kconfig b/sound/soc/sof/intel/Kconfig index 973c137a6c5a..cd9954bfec0b 100644 --- a/sound/soc/sof/intel/Kconfig +++ b/sound/soc/sof/intel/Kconfig @@ -85,10 +85,18 @@ config SND_SOC_SOF_BAYTRAIL config SND_SOC_SOF_BROADWELL_SUPPORT bool "SOF support for Broadwell" + depends on SND_SOC_INTEL_HASWELL=n help This adds support for Sound Open Firmware for Intel(R) platforms using the Broadwell processors. - Say Y if you have such a device. + This option is mutually exclusive with the Haswell/Broadwell legacy + driver. If you want to enable SOF on Broadwell you need to deselect + the legacy driver first. + SOF does fully support Broadwell yet, so this option is not + recommended for distros. At some point all legacy drivers will be + deprecated but not before all userspace firmware/topology/UCM files + are made available to downstream distros. + Say Y if you want to enable SOF on Broadwell If unsure select "N". config SND_SOC_SOF_BROADWELL -- cgit v1.2.3 From 70ae4eb540af32ee6a6260143ccae6054ebd433f Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 1 Nov 2019 12:30:38 -0500 Subject: ASoC: SOF: Kconfig: add EXPERT dependency for developer options, clarify help Some distros select all possible options, despite existing warnings to be careful. This leads to e.g. user reports that the HDaudio codec and DMIC are not handled by SOF. Add an explicit menu item to unlock developer options, and make them dependent on CONFIG_EXPERT. Hopefully with this double-lock these options will only be selected by developers. GitHub issue: https://github.com/thesofproject/sof/issues/1885 Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20191101173045.27099-5-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/Kconfig | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/Kconfig b/sound/soc/sof/Kconfig index 56a3ab66b46b..6435eb531668 100644 --- a/sound/soc/sof/Kconfig +++ b/sound/soc/sof/Kconfig @@ -14,7 +14,6 @@ config SND_SOC_SOF_PCI depends on PCI select SND_SOC_SOF select SND_SOC_ACPI if ACPI - select SND_SOC_SOF_OPTIONS select SND_SOC_SOF_INTEL_PCI if SND_SOC_SOF_INTEL_TOPLEVEL help This adds support for PCI enumeration. This option is @@ -27,7 +26,6 @@ config SND_SOC_SOF_ACPI depends on ACPI || COMPILE_TEST select SND_SOC_SOF select SND_SOC_ACPI if ACPI - select SND_SOC_SOF_OPTIONS select SND_SOC_SOF_INTEL_ACPI if SND_SOC_SOF_INTEL_TOPLEVEL select IOSF_MBI if X86 && PCI help @@ -40,19 +38,23 @@ config SND_SOC_SOF_OF tristate "SOF OF enumeration support" depends on OF || COMPILE_TEST select SND_SOC_SOF - select SND_SOC_SOF_OPTIONS help This adds support for Device Tree enumeration. This option is required to enable i.MX8 devices. Say Y if you need this option. If unsure select "N". -config SND_SOC_SOF_OPTIONS - tristate +config SND_SOC_SOF_DEVELOPER_SUPPORT + bool "SOF developer options support" + depends on EXPERT help - This option is not user-selectable but automagically handled by - 'select' statements at a higher level + This option unlock SOF developer options for debug/performance/ + code hardening. + Distributions should not select this option, only SOF development + teams should select it. + Say Y if you are involved in SOF development and need this option + If not, select N -if SND_SOC_SOF_OPTIONS +if SND_SOC_SOF_DEVELOPER_SUPPORT config SND_SOC_SOF_NOCODEC tristate @@ -64,6 +66,11 @@ config SND_SOC_SOF_NOCODEC_SUPPORT option if no known codec is detected. This is typically only enabled for developers or devices where the sound card is controlled externally + This option is mutually exclusive with the Intel HDaudio support, + selecting it may have negative impacts and prevent e.g. microphone + functionality from being enabled on Intel CoffeeLake and later + platforms. + Distributions should not select this option! Say Y if you need this nocodec fallback option If unsure select "N". @@ -168,7 +175,7 @@ config SND_SOC_SOF_DEBUG_RETAIN_DSP_CONTEXT endif ## SND_SOC_SOF_DEBUG -endif ## SND_SOC_SOF_OPTIONS +endif ## SND_SOC_SOF_DEVELOPER_SUPPORT config SND_SOC_SOF tristate -- cgit v1.2.3 From f9ad75468453b019b92c5296e6a04bf7c37f49e4 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 1 Nov 2019 12:30:39 -0500 Subject: ASoC: SOF: imx: fix reverse CONFIG_SND_SOC_SOF_OF dependency updated solution to the problem reported with randconfig: CONFIG_SND_SOC_SOF_IMX depends on CONFIG_SND_SOC_SOF, but is in turn referenced by the sof-of-dev driver. This creates a reverse dependency that manifests in a link error when CONFIG_SND_SOC_SOF_OF is built-in but CONFIG_SND_SOC_SOF_IMX=m: sound/soc/sof/sof-of-dev.o:(.data+0x118): undefined reference to `sof_imx8_ops' use def_trisate to propagate the right settings without select. Fixes: f4df4e4042b0 ("ASoC: SOF: imx8: Fix COMPILE_TEST error") Fixes: 202acc565a1f ("ASoC: SOF: imx: Add i.MX8 HW support") Suggested-by: Arnd Bergmann Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20191101173045.27099-6-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/imx/Kconfig | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/imx/Kconfig b/sound/soc/sof/imx/Kconfig index 5acae75f5750..71f318bc2c74 100644 --- a/sound/soc/sof/imx/Kconfig +++ b/sound/soc/sof/imx/Kconfig @@ -11,8 +11,8 @@ config SND_SOC_SOF_IMX_TOPLEVEL if SND_SOC_SOF_IMX_TOPLEVEL -config SND_SOC_SOF_IMX8 - tristate "SOF support for i.MX8" +config SND_SOC_SOF_IMX8_SUPPORT + bool "SOF support for i.MX8" depends on IMX_SCU depends on IMX_DSP help @@ -20,4 +20,8 @@ config SND_SOC_SOF_IMX8 Say Y if you have such a device. If unsure select "N". +config SND_SOC_SOF_IMX8 + def_tristate SND_SOC_SOF_OF + depends on SND_SOC_SOF_IMX8_SUPPORT + endif ## SND_SOC_SOF_IMX_IMX_TOPLEVEL -- cgit v1.2.3 From b000135e5f272118e576e9720590e5979f0abe49 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 1 Nov 2019 12:30:40 -0500 Subject: ASoC: SOF: Intel: use def_tristate, avoid using select So far we used select to use the relevant built-in/module options, but this led to blurring layers between core and Intel Kconfigs. Use def_tristate works just as well and removes Intel stuff from the code. Suggested-by: Arnd Bergmann Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20191101173045.27099-7-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/Kconfig | 2 -- sound/soc/sof/intel/Kconfig | 4 ++-- 2 files changed, 2 insertions(+), 4 deletions(-) (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/Kconfig b/sound/soc/sof/Kconfig index 6435eb531668..71a0fc075a63 100644 --- a/sound/soc/sof/Kconfig +++ b/sound/soc/sof/Kconfig @@ -14,7 +14,6 @@ config SND_SOC_SOF_PCI depends on PCI select SND_SOC_SOF select SND_SOC_ACPI if ACPI - select SND_SOC_SOF_INTEL_PCI if SND_SOC_SOF_INTEL_TOPLEVEL help This adds support for PCI enumeration. This option is required to enable Intel Skylake+ devices @@ -26,7 +25,6 @@ config SND_SOC_SOF_ACPI depends on ACPI || COMPILE_TEST select SND_SOC_SOF select SND_SOC_ACPI if ACPI - select SND_SOC_SOF_INTEL_ACPI if SND_SOC_SOF_INTEL_TOPLEVEL select IOSF_MBI if X86 && PCI help This adds support for ACPI enumeration. This option is required diff --git a/sound/soc/sof/intel/Kconfig b/sound/soc/sof/intel/Kconfig index cd9954bfec0b..04d4929cf91f 100644 --- a/sound/soc/sof/intel/Kconfig +++ b/sound/soc/sof/intel/Kconfig @@ -10,7 +10,7 @@ config SND_SOC_SOF_INTEL_TOPLEVEL if SND_SOC_SOF_INTEL_TOPLEVEL config SND_SOC_SOF_INTEL_ACPI - tristate + def_tristate SND_SOC_SOF_ACPI select SND_SOC_SOF_BAYTRAIL if SND_SOC_SOF_BAYTRAIL_SUPPORT select SND_SOC_SOF_BROADWELL if SND_SOC_SOF_BROADWELL_SUPPORT help @@ -18,7 +18,7 @@ config SND_SOC_SOF_INTEL_ACPI 'select' statements at a higher level config SND_SOC_SOF_INTEL_PCI - tristate + def_tristate SND_SOC_SOF_PCI select SND_SOC_SOF_MERRIFIELD if SND_SOC_SOF_MERRIFIELD_SUPPORT select SND_SOC_SOF_APOLLOLAKE if SND_SOC_SOF_APOLLOLAKE_SUPPORT select SND_SOC_SOF_GEMINILAKE if SND_SOC_SOF_GEMINILAKE_SUPPORT -- cgit v1.2.3 From 5eee2b3f60065a2530d13f28e771be48b989eb4c Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Mon, 4 Nov 2019 14:48:12 -0800 Subject: ASoC: SOF: topology: set trigger order for FE DAI link Set trigger order for FE DAI links to SND_SOC_DPCM_TRIGGER_POST to trigger the BE DAI's before the FE DAI's. This prevents the xruns seen on playback pipelines using the link DMA. Signed-off-by: Ranjani Sridharan Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20191104224812.3393-3-ranjani.sridharan@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/topology.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c index e0e2ae734632..e7076692119b 100644 --- a/sound/soc/sof/topology.c +++ b/sound/soc/sof/topology.c @@ -2951,6 +2951,10 @@ static int sof_link_load(struct snd_soc_component *scomp, int index, if (!link->no_pcm) { link->nonatomic = true; + /* set trigger order */ + link->trigger[0] = SND_SOC_DPCM_TRIGGER_POST; + link->trigger[1] = SND_SOC_DPCM_TRIGGER_POST; + /* nothing more to do for FE dai links */ return 0; } -- cgit v1.2.3 From 9508ef5a980f5d847cad9b932b6ada8f2a3466c1 Mon Sep 17 00:00:00 2001 From: Dragos Tarcatu Date: Wed, 6 Nov 2019 08:58:16 -0600 Subject: ASoC: SOF: topology: Fix bytes control size checks When using the example SOF amp widget topology, KASAN dumps this when the AMP bytes kcontrol gets loaded: [ 9.579548] BUG: KASAN: slab-out-of-bounds in sof_control_load+0x8cc/0xac0 [snd_sof] [ 9.588194] Write of size 40 at addr ffff8882314559dc by task systemd-udevd/2411 Fix that by rejecting the topology if the bytes data size > max_size Fixes: 311ce4fe7637d ("ASoC: SOF: Add support for loading topologies") Reviewed-by: Jaska Uimonen Reviewed-by: Ranjani Sridharan Signed-off-by: Dragos Tarcatu Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20191106145816.9367-1-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/topology.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c index 0aabb3190ddc..4452594c2e17 100644 --- a/sound/soc/sof/topology.c +++ b/sound/soc/sof/topology.c @@ -543,15 +543,16 @@ static int sof_control_load_bytes(struct snd_soc_component *scomp, struct soc_bytes_ext *sbe = (struct soc_bytes_ext *)kc->private_value; int max_size = sbe->max; - if (le32_to_cpu(control->priv.size) > max_size) { + /* init the get/put bytes data */ + scontrol->size = sizeof(struct sof_ipc_ctrl_data) + + le32_to_cpu(control->priv.size); + + if (scontrol->size > max_size) { dev_err(sdev->dev, "err: bytes data size %d exceeds max %d.\n", - control->priv.size, max_size); + scontrol->size, max_size); return -EINVAL; } - /* init the get/put bytes data */ - scontrol->size = sizeof(struct sof_ipc_ctrl_data) + - le32_to_cpu(control->priv.size); scontrol->control_data = kzalloc(max_size, GFP_KERNEL); cdata = scontrol->control_data; if (!scontrol->control_data) -- cgit v1.2.3 From 2acdcabb8a4089476208a822050dd47a6557290d Mon Sep 17 00:00:00 2001 From: Dragos Tarcatu Date: Wed, 6 Nov 2019 08:58:16 -0600 Subject: ASoC: SOF: topology: Fix bytes control size checks When using the example SOF amp widget topology, KASAN dumps this when the AMP bytes kcontrol gets loaded: [ 9.579548] BUG: KASAN: slab-out-of-bounds in sof_control_load+0x8cc/0xac0 [snd_sof] [ 9.588194] Write of size 40 at addr ffff8882314559dc by task systemd-udevd/2411 Fix that by rejecting the topology if the bytes data size > max_size Fixes: 311ce4fe7637d ("ASoC: SOF: Add support for loading topologies") Reviewed-by: Jaska Uimonen Reviewed-by: Ranjani Sridharan Signed-off-by: Dragos Tarcatu Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20191106145816.9367-1-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/topology.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'sound/soc/sof') diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c index e7076692119b..143b8259a70a 100644 --- a/sound/soc/sof/topology.c +++ b/sound/soc/sof/topology.c @@ -1043,15 +1043,16 @@ static int sof_control_load_bytes(struct snd_soc_component *scomp, struct soc_bytes_ext *sbe = (struct soc_bytes_ext *)kc->private_value; int max_size = sbe->max; - if (le32_to_cpu(control->priv.size) > max_size) { + /* init the get/put bytes data */ + scontrol->size = sizeof(struct sof_ipc_ctrl_data) + + le32_to_cpu(control->priv.size); + + if (scontrol->size > max_size) { dev_err(sdev->dev, "err: bytes data size %d exceeds max %d.\n", - control->priv.size, max_size); + scontrol->size, max_size); return -EINVAL; } - /* init the get/put bytes data */ - scontrol->size = sizeof(struct sof_ipc_ctrl_data) + - le32_to_cpu(control->priv.size); scontrol->control_data = kzalloc(max_size, GFP_KERNEL); cdata = scontrol->control_data; if (!scontrol->control_data) -- cgit v1.2.3