Commit 0f00a3fa authored by Mark Brown's avatar Mark Brown

ASoC: SOF: misc updates for 6.5

Merge series from Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>:

Couple of improvements on virtual_widget support, firmware trace free,
IPC payload dump, duplicated code in suspend and MeteorLake primary
code support.
parents 60e07fa4 fd4e9e9b
...@@ -504,8 +504,10 @@ int snd_sof_device_shutdown(struct device *dev) ...@@ -504,8 +504,10 @@ int snd_sof_device_shutdown(struct device *dev)
if (IS_ENABLED(CONFIG_SND_SOC_SOF_PROBE_WORK_QUEUE)) if (IS_ENABLED(CONFIG_SND_SOC_SOF_PROBE_WORK_QUEUE))
cancel_work_sync(&sdev->probe_work); cancel_work_sync(&sdev->probe_work);
if (sdev->fw_state == SOF_FW_BOOT_COMPLETE) if (sdev->fw_state == SOF_FW_BOOT_COMPLETE) {
sof_fw_trace_free(sdev);
return snd_sof_shutdown(sdev); return snd_sof_shutdown(sdev);
}
return 0; return 0;
} }
......
...@@ -361,11 +361,17 @@ static int mtl_dsp_core_power_up(struct snd_sof_dev *sdev, int core) ...@@ -361,11 +361,17 @@ static int mtl_dsp_core_power_up(struct snd_sof_dev *sdev, int core)
ret = snd_sof_dsp_read_poll_timeout(sdev, HDA_DSP_BAR, MTL_DSP2CXCTL_PRIMARY_CORE, dspcxctl, ret = snd_sof_dsp_read_poll_timeout(sdev, HDA_DSP_BAR, MTL_DSP2CXCTL_PRIMARY_CORE, dspcxctl,
(dspcxctl & cpa) == cpa, HDA_DSP_REG_POLL_INTERVAL_US, (dspcxctl & cpa) == cpa, HDA_DSP_REG_POLL_INTERVAL_US,
HDA_DSP_RESET_TIMEOUT_US); HDA_DSP_RESET_TIMEOUT_US);
if (ret < 0) if (ret < 0) {
dev_err(sdev->dev, "%s: timeout on MTL_DSP2CXCTL_PRIMARY_CORE read\n", dev_err(sdev->dev, "%s: timeout on MTL_DSP2CXCTL_PRIMARY_CORE read\n",
__func__); __func__);
return ret; return ret;
}
/* set primary core mask and refcount to 1 */
sdev->enabled_cores_mask = BIT(SOF_DSP_PRIMARY_CORE);
sdev->dsp_core_ref_count[SOF_DSP_PRIMARY_CORE] = 1;
return 0;
} }
static int mtl_dsp_core_power_down(struct snd_sof_dev *sdev, int core) static int mtl_dsp_core_power_down(struct snd_sof_dev *sdev, int core)
...@@ -388,10 +394,15 @@ static int mtl_dsp_core_power_down(struct snd_sof_dev *sdev, int core) ...@@ -388,10 +394,15 @@ static int mtl_dsp_core_power_down(struct snd_sof_dev *sdev, int core)
!(dspcxctl & MTL_DSP2CXCTL_PRIMARY_CORE_CPA_MASK), !(dspcxctl & MTL_DSP2CXCTL_PRIMARY_CORE_CPA_MASK),
HDA_DSP_REG_POLL_INTERVAL_US, HDA_DSP_REG_POLL_INTERVAL_US,
HDA_DSP_PD_TIMEOUT * USEC_PER_MSEC); HDA_DSP_PD_TIMEOUT * USEC_PER_MSEC);
if (ret < 0) if (ret < 0) {
dev_err(sdev->dev, "failed to power down primary core\n"); dev_err(sdev->dev, "failed to power down primary core\n");
return ret; return ret;
}
sdev->enabled_cores_mask = 0;
sdev->dsp_core_ref_count[SOF_DSP_PRIMARY_CORE] = 0;
return 0;
} }
int mtl_power_down_dsp(struct snd_sof_dev *sdev) int mtl_power_down_dsp(struct snd_sof_dev *sdev)
......
...@@ -223,6 +223,14 @@ static inline void ipc3_log_header(struct device *dev, u8 *text, u32 cmd) ...@@ -223,6 +223,14 @@ static inline void ipc3_log_header(struct device *dev, u8 *text, u32 cmd)
} }
#endif #endif
static void sof_ipc3_dump_payload(struct snd_sof_dev *sdev,
void *ipc_data, size_t size)
{
printk(KERN_DEBUG "Size of payload following the header: %zu\n", size);
print_hex_dump_debug("Message payload: ", DUMP_PREFIX_OFFSET,
16, 4, ipc_data, size, false);
}
static int sof_ipc3_get_reply(struct snd_sof_dev *sdev) static int sof_ipc3_get_reply(struct snd_sof_dev *sdev)
{ {
struct snd_sof_ipc_msg *msg = sdev->msg; struct snd_sof_ipc_msg *msg = sdev->msg;
...@@ -374,6 +382,29 @@ static int sof_ipc3_tx_msg(struct snd_sof_dev *sdev, void *msg_data, size_t msg_ ...@@ -374,6 +382,29 @@ static int sof_ipc3_tx_msg(struct snd_sof_dev *sdev, void *msg_data, size_t msg_
ret = ipc3_tx_msg_unlocked(ipc, msg_data, msg_bytes, reply_data, reply_bytes); ret = ipc3_tx_msg_unlocked(ipc, msg_data, msg_bytes, reply_data, reply_bytes);
if (sof_debug_check_flag(SOF_DBG_DUMP_IPC_MESSAGE_PAYLOAD)) {
size_t payload_bytes, header_bytes;
char *payload = NULL;
/* payload is indicated by non zero msg/reply_bytes */
if (msg_bytes > sizeof(struct sof_ipc_cmd_hdr)) {
payload = msg_data;
header_bytes = sizeof(struct sof_ipc_cmd_hdr);
payload_bytes = msg_bytes - header_bytes;
} else if (reply_bytes > sizeof(struct sof_ipc_reply)) {
payload = reply_data;
header_bytes = sizeof(struct sof_ipc_reply);
payload_bytes = reply_bytes - header_bytes;
}
if (payload) {
payload += header_bytes;
sof_ipc3_dump_payload(sdev, payload, payload_bytes);
}
}
mutex_unlock(&ipc->tx_mutex); mutex_unlock(&ipc->tx_mutex);
return ret; return ret;
...@@ -472,6 +503,14 @@ static int sof_ipc3_set_get_data(struct snd_sof_dev *sdev, void *data, size_t da ...@@ -472,6 +503,14 @@ static int sof_ipc3_set_get_data(struct snd_sof_dev *sdev, void *data, size_t da
offset += payload_size; offset += payload_size;
} }
if (sof_debug_check_flag(SOF_DBG_DUMP_IPC_MESSAGE_PAYLOAD)) {
size_t header_bytes = sizeof(struct sof_ipc_reply);
char *payload = (char *)cdata;
payload += header_bytes;
sof_ipc3_dump_payload(sdev, payload, data_bytes - header_bytes);
}
mutex_unlock(&sdev->ipc->tx_mutex); mutex_unlock(&sdev->ipc->tx_mutex);
kfree(cdata_chunk); kfree(cdata_chunk);
......
...@@ -17,15 +17,6 @@ ...@@ -17,15 +17,6 @@
#include "ipc4-priv.h" #include "ipc4-priv.h"
#include "ops.h" #include "ops.h"
#ifdef DEBUG_VERBOSE
#define sof_ipc4_dump_payload(sdev, ipc_data, size) \
print_hex_dump_debug("Message payload: ", \
DUMP_PREFIX_OFFSET, \
16, 4, ipc_data, size, false)
#else
#define sof_ipc4_dump_payload(sdev, ipc_data, size) do { } while (0)
#endif
static const struct sof_ipc4_fw_status { static const struct sof_ipc4_fw_status {
int status; int status;
char *msg; char *msg;
...@@ -256,6 +247,13 @@ static void sof_ipc4_log_header(struct device *dev, u8 *text, struct sof_ipc4_ms ...@@ -256,6 +247,13 @@ static void sof_ipc4_log_header(struct device *dev, u8 *text, struct sof_ipc4_ms
} }
#endif #endif
static void sof_ipc4_dump_payload(struct snd_sof_dev *sdev,
void *ipc_data, size_t size)
{
print_hex_dump_debug("Message payload: ", DUMP_PREFIX_OFFSET,
16, 4, ipc_data, size, false);
}
static int sof_ipc4_get_reply(struct snd_sof_dev *sdev) static int sof_ipc4_get_reply(struct snd_sof_dev *sdev)
{ {
struct snd_sof_ipc_msg *msg = sdev->msg; struct snd_sof_ipc_msg *msg = sdev->msg;
...@@ -362,9 +360,6 @@ static int sof_ipc4_tx_msg(struct snd_sof_dev *sdev, void *msg_data, size_t msg_ ...@@ -362,9 +360,6 @@ static int sof_ipc4_tx_msg(struct snd_sof_dev *sdev, void *msg_data, size_t msg_
void *reply_data, size_t reply_bytes, bool no_pm) void *reply_data, size_t reply_bytes, bool no_pm)
{ {
struct snd_sof_ipc *ipc = sdev->ipc; struct snd_sof_ipc *ipc = sdev->ipc;
#ifdef DEBUG_VERBOSE
struct sof_ipc4_msg *msg = NULL;
#endif
int ret; int ret;
if (!msg_data) if (!msg_data)
...@@ -386,9 +381,9 @@ static int sof_ipc4_tx_msg(struct snd_sof_dev *sdev, void *msg_data, size_t msg_ ...@@ -386,9 +381,9 @@ static int sof_ipc4_tx_msg(struct snd_sof_dev *sdev, void *msg_data, size_t msg_
ret = ipc4_tx_msg_unlocked(ipc, msg_data, msg_bytes, reply_data, reply_bytes); ret = ipc4_tx_msg_unlocked(ipc, msg_data, msg_bytes, reply_data, reply_bytes);
mutex_unlock(&ipc->tx_mutex); if (sof_debug_check_flag(SOF_DBG_DUMP_IPC_MESSAGE_PAYLOAD)) {
struct sof_ipc4_msg *msg = NULL;
#ifdef DEBUG_VERBOSE
/* payload is indicated by non zero msg/reply_bytes */ /* payload is indicated by non zero msg/reply_bytes */
if (msg_bytes) if (msg_bytes)
msg = msg_data; msg = msg_data;
...@@ -397,7 +392,9 @@ static int sof_ipc4_tx_msg(struct snd_sof_dev *sdev, void *msg_data, size_t msg_ ...@@ -397,7 +392,9 @@ static int sof_ipc4_tx_msg(struct snd_sof_dev *sdev, void *msg_data, size_t msg_
if (msg) if (msg)
sof_ipc4_dump_payload(sdev, msg->data_ptr, msg->data_size); sof_ipc4_dump_payload(sdev, msg->data_ptr, msg->data_size);
#endif }
mutex_unlock(&ipc->tx_mutex);
return ret; return ret;
} }
...@@ -516,6 +513,7 @@ static int sof_ipc4_set_get_data(struct snd_sof_dev *sdev, void *data, ...@@ -516,6 +513,7 @@ static int sof_ipc4_set_get_data(struct snd_sof_dev *sdev, void *data,
if (!set && payload_bytes != offset) if (!set && payload_bytes != offset)
ipc4_msg->data_size = offset; ipc4_msg->data_size = offset;
if (sof_debug_check_flag(SOF_DBG_DUMP_IPC_MESSAGE_PAYLOAD))
sof_ipc4_dump_payload(sdev, ipc4_msg->data_ptr, ipc4_msg->data_size); sof_ipc4_dump_payload(sdev, ipc4_msg->data_ptr, ipc4_msg->data_size);
out: out:
......
...@@ -234,20 +234,16 @@ static int sof_suspend(struct device *dev, bool runtime_suspend) ...@@ -234,20 +234,16 @@ static int sof_suspend(struct device *dev, bool runtime_suspend)
pm_state.event = target_state; pm_state.event = target_state;
/* Skip to platform-specific suspend if DSP is entering D0 */
if (target_state == SOF_DSP_PM_D0) {
sof_fw_trace_suspend(sdev, pm_state);
/* Notify clients not managed by pm framework about core suspend */
sof_suspend_clients(sdev, pm_state);
goto suspend;
}
/* suspend DMA trace */ /* suspend DMA trace */
sof_fw_trace_suspend(sdev, pm_state); sof_fw_trace_suspend(sdev, pm_state);
/* Notify clients not managed by pm framework about core suspend */ /* Notify clients not managed by pm framework about core suspend */
sof_suspend_clients(sdev, pm_state); sof_suspend_clients(sdev, pm_state);
/* Skip to platform-specific suspend if DSP is entering D0 */
if (target_state == SOF_DSP_PM_D0)
goto suspend;
#if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_ENABLE_DEBUGFS_CACHE) #if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_ENABLE_DEBUGFS_CACHE)
/* cache debugfs contents during runtime suspend */ /* cache debugfs contents during runtime suspend */
if (runtime_suspend) if (runtime_suspend)
......
...@@ -14,6 +14,20 @@ ...@@ -14,6 +14,20 @@
#include "sof-of-dev.h" #include "sof-of-dev.h"
#include "ops.h" #include "ops.h"
static bool is_virtual_widget(struct snd_sof_dev *sdev, struct snd_soc_dapm_widget *widget,
const char *func)
{
switch (widget->id) {
case snd_soc_dapm_out_drv:
case snd_soc_dapm_output:
case snd_soc_dapm_input:
dev_dbg(sdev->dev, "%s: %s is a virtual widget\n", func, widget->name);
return true;
default:
return false;
}
}
static void sof_reset_route_setup_status(struct snd_sof_dev *sdev, struct snd_sof_widget *widget) static void sof_reset_route_setup_status(struct snd_sof_dev *sdev, struct snd_sof_widget *widget)
{ {
const struct sof_ipc_tplg_ops *tplg_ops = sof_ipc_get_ops(sdev, tplg); const struct sof_ipc_tplg_ops *tplg_ops = sof_ipc_get_ops(sdev, tplg);
...@@ -231,23 +245,9 @@ int sof_route_setup(struct snd_sof_dev *sdev, struct snd_soc_dapm_widget *wsourc ...@@ -231,23 +245,9 @@ int sof_route_setup(struct snd_sof_dev *sdev, struct snd_soc_dapm_widget *wsourc
bool route_found = false; bool route_found = false;
/* ignore routes involving virtual widgets in topology */ /* ignore routes involving virtual widgets in topology */
switch (src_widget->id) { if (is_virtual_widget(sdev, src_widget->widget, __func__) ||
case snd_soc_dapm_out_drv: is_virtual_widget(sdev, sink_widget->widget, __func__))
case snd_soc_dapm_output:
case snd_soc_dapm_input:
return 0; return 0;
default:
break;
}
switch (sink_widget->id) {
case snd_soc_dapm_out_drv:
case snd_soc_dapm_output:
case snd_soc_dapm_input:
return 0;
default:
break;
}
/* find route matching source and sink widgets */ /* find route matching source and sink widgets */
list_for_each_entry(sroute, &sdev->route_list, list) list_for_each_entry(sroute, &sdev->route_list, list)
...@@ -396,6 +396,9 @@ sof_unprepare_widgets_in_path(struct snd_sof_dev *sdev, struct snd_soc_dapm_widg ...@@ -396,6 +396,9 @@ sof_unprepare_widgets_in_path(struct snd_sof_dev *sdev, struct snd_soc_dapm_widg
const struct sof_ipc_tplg_widget_ops *widget_ops; const struct sof_ipc_tplg_widget_ops *widget_ops;
struct snd_soc_dapm_path *p; struct snd_soc_dapm_path *p;
if (is_virtual_widget(sdev, widget, __func__))
return;
/* skip if the widget is in use or if it is already unprepared */ /* skip if the widget is in use or if it is already unprepared */
if (!swidget || !swidget->prepared || swidget->use_count > 0) if (!swidget || !swidget->prepared || swidget->use_count > 0)
goto sink_unprepare; goto sink_unprepare;
...@@ -433,6 +436,9 @@ sof_prepare_widgets_in_path(struct snd_sof_dev *sdev, struct snd_soc_dapm_widget ...@@ -433,6 +436,9 @@ sof_prepare_widgets_in_path(struct snd_sof_dev *sdev, struct snd_soc_dapm_widget
struct snd_soc_dapm_path *p; struct snd_soc_dapm_path *p;
int ret; int ret;
if (is_virtual_widget(sdev, widget, __func__))
return 0;
widget_ops = tplg_ops ? tplg_ops->widget : NULL; widget_ops = tplg_ops ? tplg_ops->widget : NULL;
if (!widget_ops) if (!widget_ops)
return 0; return 0;
...@@ -488,6 +494,9 @@ static int sof_free_widgets_in_path(struct snd_sof_dev *sdev, struct snd_soc_dap ...@@ -488,6 +494,9 @@ static int sof_free_widgets_in_path(struct snd_sof_dev *sdev, struct snd_soc_dap
int err; int err;
int ret = 0; int ret = 0;
if (is_virtual_widget(sdev, widget, __func__))
return 0;
if (widget->dobj.private) { if (widget->dobj.private) {
err = sof_widget_free(sdev, widget->dobj.private); err = sof_widget_free(sdev, widget->dobj.private);
if (err < 0) if (err < 0)
...@@ -527,6 +536,9 @@ static int sof_set_up_widgets_in_path(struct snd_sof_dev *sdev, struct snd_soc_d ...@@ -527,6 +536,9 @@ static int sof_set_up_widgets_in_path(struct snd_sof_dev *sdev, struct snd_soc_d
struct snd_soc_dapm_path *p; struct snd_soc_dapm_path *p;
int ret; int ret;
if (is_virtual_widget(sdev, widget, __func__))
return 0;
if (swidget) { if (swidget) {
int i; int i;
...@@ -592,6 +604,9 @@ sof_walk_widgets_in_order(struct snd_sof_dev *sdev, struct snd_sof_pcm *spcm, ...@@ -592,6 +604,9 @@ sof_walk_widgets_in_order(struct snd_sof_dev *sdev, struct snd_sof_pcm *spcm,
return 0; return 0;
for_each_dapm_widgets(list, i, widget) { for_each_dapm_widgets(list, i, widget) {
if (is_virtual_widget(sdev, widget, __func__))
continue;
/* starting widget for playback is AIF type */ /* starting widget for playback is AIF type */
if (dir == SNDRV_PCM_STREAM_PLAYBACK && widget->id != snd_soc_dapm_aif_in) if (dir == SNDRV_PCM_STREAM_PLAYBACK && widget->id != snd_soc_dapm_aif_in)
continue; continue;
......
...@@ -48,6 +48,9 @@ struct snd_sof_pcm_stream; ...@@ -48,6 +48,9 @@ struct snd_sof_pcm_stream;
#define SOF_DBG_FORCE_NOCODEC BIT(10) /* ignore all codec-related #define SOF_DBG_FORCE_NOCODEC BIT(10) /* ignore all codec-related
* configurations * configurations
*/ */
#define SOF_DBG_DUMP_IPC_MESSAGE_PAYLOAD BIT(11) /* On top of the IPC message header
* dump the message payload also
*/
#define SOF_DBG_DSPLESS_MODE BIT(15) /* Do not initialize and use the DSP */ #define SOF_DBG_DSPLESS_MODE BIT(15) /* Do not initialize and use the DSP */
/* Flag definitions used for controlling the DSP dump behavior */ /* Flag definitions used for controlling the DSP dump behavior */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment