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.
This commit is contained in:
Mark Brown 2023-06-16 17:16:21 +01:00
commit 0f00a3fa5a
No known key found for this signature in database
GPG key ID: 24D68B725D5487D0
7 changed files with 117 additions and 53 deletions

View file

@ -504,8 +504,10 @@ int snd_sof_device_shutdown(struct device *dev)
if (IS_ENABLED(CONFIG_SND_SOC_SOF_PROBE_WORK_QUEUE))
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 0;
}

View file

@ -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,
(dspcxctl & cpa) == cpa, HDA_DSP_REG_POLL_INTERVAL_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",
__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)
@ -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),
HDA_DSP_REG_POLL_INTERVAL_US,
HDA_DSP_PD_TIMEOUT * USEC_PER_MSEC);
if (ret < 0)
if (ret < 0) {
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)

View file

@ -223,6 +223,14 @@ static inline void ipc3_log_header(struct device *dev, u8 *text, u32 cmd)
}
#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)
{
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_
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);
return ret;
@ -472,6 +503,14 @@ static int sof_ipc3_set_get_data(struct snd_sof_dev *sdev, void *data, size_t da
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);
kfree(cdata_chunk);

View file

@ -17,15 +17,6 @@
#include "ipc4-priv.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 {
int status;
char *msg;
@ -256,6 +247,13 @@ static void sof_ipc4_log_header(struct device *dev, u8 *text, struct sof_ipc4_ms
}
#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)
{
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_
void *reply_data, size_t reply_bytes, bool no_pm)
{
struct snd_sof_ipc *ipc = sdev->ipc;
#ifdef DEBUG_VERBOSE
struct sof_ipc4_msg *msg = NULL;
#endif
int ret;
if (!msg_data)
@ -386,19 +381,21 @@ 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);
if (sof_debug_check_flag(SOF_DBG_DUMP_IPC_MESSAGE_PAYLOAD)) {
struct sof_ipc4_msg *msg = NULL;
/* payload is indicated by non zero msg/reply_bytes */
if (msg_bytes)
msg = msg_data;
else if (reply_bytes)
msg = reply_data;
if (msg)
sof_ipc4_dump_payload(sdev, msg->data_ptr, msg->data_size);
}
mutex_unlock(&ipc->tx_mutex);
#ifdef DEBUG_VERBOSE
/* payload is indicated by non zero msg/reply_bytes */
if (msg_bytes)
msg = msg_data;
else if (reply_bytes)
msg = reply_data;
if (msg)
sof_ipc4_dump_payload(sdev, msg->data_ptr, msg->data_size);
#endif
return ret;
}
@ -516,7 +513,8 @@ static int sof_ipc4_set_get_data(struct snd_sof_dev *sdev, void *data,
if (!set && payload_bytes != offset)
ipc4_msg->data_size = offset;
sof_ipc4_dump_payload(sdev, ipc4_msg->data_ptr, ipc4_msg->data_size);
if (sof_debug_check_flag(SOF_DBG_DUMP_IPC_MESSAGE_PAYLOAD))
sof_ipc4_dump_payload(sdev, ipc4_msg->data_ptr, ipc4_msg->data_size);
out:
mutex_unlock(&sdev->ipc->tx_mutex);

View file

@ -234,20 +234,16 @@ static int sof_suspend(struct device *dev, bool runtime_suspend)
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 */
sof_fw_trace_suspend(sdev, pm_state);
/* Notify clients not managed by pm framework about core suspend */
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)
/* cache debugfs contents during runtime suspend */
if (runtime_suspend)

View file

@ -14,6 +14,20 @@
#include "sof-of-dev.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)
{
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
bool route_found = false;
/* ignore routes involving virtual widgets in topology */
switch (src_widget->id) {
case snd_soc_dapm_out_drv:
case snd_soc_dapm_output:
case snd_soc_dapm_input:
if (is_virtual_widget(sdev, src_widget->widget, __func__) ||
is_virtual_widget(sdev, sink_widget->widget, __func__))
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 */
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
const struct sof_ipc_tplg_widget_ops *widget_ops;
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 */
if (!swidget || !swidget->prepared || swidget->use_count > 0)
goto sink_unprepare;
@ -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;
int ret;
if (is_virtual_widget(sdev, widget, __func__))
return 0;
widget_ops = tplg_ops ? tplg_ops->widget : NULL;
if (!widget_ops)
return 0;
@ -488,6 +494,9 @@ static int sof_free_widgets_in_path(struct snd_sof_dev *sdev, struct snd_soc_dap
int err;
int ret = 0;
if (is_virtual_widget(sdev, widget, __func__))
return 0;
if (widget->dobj.private) {
err = sof_widget_free(sdev, widget->dobj.private);
if (err < 0)
@ -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;
int ret;
if (is_virtual_widget(sdev, widget, __func__))
return 0;
if (swidget) {
int i;
@ -592,6 +604,9 @@ sof_walk_widgets_in_order(struct snd_sof_dev *sdev, struct snd_sof_pcm *spcm,
return 0;
for_each_dapm_widgets(list, i, widget) {
if (is_virtual_widget(sdev, widget, __func__))
continue;
/* starting widget for playback is AIF type */
if (dir == SNDRV_PCM_STREAM_PLAYBACK && widget->id != snd_soc_dapm_aif_in)
continue;

View file

@ -48,6 +48,9 @@ struct snd_sof_pcm_stream;
#define SOF_DBG_FORCE_NOCODEC BIT(10) /* ignore all codec-related
* 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 */
/* Flag definitions used for controlling the DSP dump behavior */