mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-10-06 00:39:48 +00:00
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:
commit
0f00a3fa5a
7 changed files with 117 additions and 53 deletions
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 */
|
||||
|
|
Loading…
Reference in a new issue