Skip to content

Commit

Permalink
ASoC: SOF: misc updates for 6.5
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
Mark Brown committed Jun 16, 2023
2 parents 60e07fa + fd4e9e9 commit 0f00a3f
Show file tree
Hide file tree
Showing 7 changed files with 116 additions and 52 deletions.
4 changes: 3 additions & 1 deletion sound/soc/sof/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
19 changes: 15 additions & 4 deletions sound/soc/sof/intel/mtl.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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)
Expand Down
39 changes: 39 additions & 0 deletions sound/soc/sof/ipc3.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down
44 changes: 21 additions & 23 deletions sound/soc/sof/ipc4.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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)
Expand All @@ -386,18 +381,20 @@ 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);

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 */
if (msg_bytes)
msg = msg_data;
else if (reply_bytes)
msg = reply_data;
/* 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
if (msg)
sof_ipc4_dump_payload(sdev, msg->data_ptr, msg->data_size);
}

mutex_unlock(&ipc->tx_mutex);

return ret;
}
Expand Down Expand Up @@ -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);
Expand Down
12 changes: 4 additions & 8 deletions sound/soc/sof/pm.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
47 changes: 31 additions & 16 deletions sound/soc/sof/sof-audio.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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;
Expand Down
3 changes: 3 additions & 0 deletions sound/soc/sof/sof-priv.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down

0 comments on commit 0f00a3f

Please sign in to comment.