Skip to content

Commit b055a0c

Browse files
committed
ASoC: SOF: ipc4: Support for sending payload along with LARGE_CONFIG_GET
There are message types when we would need to send a payload along with the LARGE_CONFIG_GET message to provide information to the firmware on what data is requested. Such cases are the ALSA Kcontrol related messages when the high level param_id tells only the type of the control, but the ID/index of the exact control is specified in the payload area. The caller must place the payload for TX before calling the set_get_data() and this payload will be sent alongside with the message to the firmware. The data area will be overwritten by the received data from firmware. Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
1 parent 63231d5 commit b055a0c

1 file changed

Lines changed: 42 additions & 2 deletions

File tree

sound/soc/sof/ipc4.c

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include "sof-audio.h"
1616
#include "ipc4-fw-reg.h"
1717
#include "ipc4-priv.h"
18+
#include "ipc4-topology.h"
1819
#include "ipc4-telemetry.h"
1920
#include "ops.h"
2021

@@ -434,6 +435,23 @@ static int sof_ipc4_tx_msg(struct snd_sof_dev *sdev, void *msg_data, size_t msg_
434435
return ret;
435436
}
436437

438+
static bool sof_ipc4_tx_payload_for_get_data(struct sof_ipc4_msg *tx)
439+
{
440+
/*
441+
* Messages that require TX payload with LARGE_CONFIG_GET.
442+
* The TX payload is placed into the IPC message data section by caller,
443+
* which needs to be copied to temporary buffer since the received data
444+
* will overwrite it.
445+
*/
446+
switch (tx->extension & SOF_IPC4_MOD_EXT_MSG_PARAM_ID_MASK) {
447+
case SOF_IPC4_MOD_EXT_MSG_PARAM_ID(SOF_IPC4_SWITCH_CONTROL_PARAM_ID):
448+
case SOF_IPC4_MOD_EXT_MSG_PARAM_ID(SOF_IPC4_ENUM_CONTROL_PARAM_ID):
449+
return true;
450+
default:
451+
return false;
452+
}
453+
}
454+
437455
static int sof_ipc4_set_get_data(struct snd_sof_dev *sdev, void *data,
438456
size_t payload_bytes, bool set)
439457
{
@@ -445,6 +463,8 @@ static int sof_ipc4_set_get_data(struct snd_sof_dev *sdev, void *data,
445463
struct sof_ipc4_msg tx = {{ 0 }};
446464
struct sof_ipc4_msg rx = {{ 0 }};
447465
size_t remaining = payload_bytes;
466+
void *tx_payload_for_get = NULL;
467+
size_t tx_data_size = 0;
448468
size_t offset = 0;
449469
size_t chunk_size;
450470
int ret;
@@ -470,10 +490,20 @@ static int sof_ipc4_set_get_data(struct snd_sof_dev *sdev, void *data,
470490

471491
tx.extension |= SOF_IPC4_MOD_EXT_MSG_FIRST_BLOCK(1);
472492

493+
if (sof_ipc4_tx_payload_for_get_data(&tx)) {
494+
tx_data_size = min(ipc4_msg->data_size, payload_limit);
495+
tx_payload_for_get = kmemdup(ipc4_msg->data_ptr, tx_data_size,
496+
GFP_KERNEL);
497+
if (!tx_payload_for_get)
498+
return -ENOMEM;
499+
}
500+
473501
/* ensure the DSP is in D0i0 before sending IPC */
474502
ret = snd_sof_dsp_set_power_state(sdev, &target_state);
475-
if (ret < 0)
503+
if (ret < 0) {
504+
kfree(tx_payload_for_get);
476505
return ret;
506+
}
477507

478508
/* Serialise IPC TX */
479509
mutex_lock(&sdev->ipc->tx_mutex);
@@ -507,7 +537,15 @@ static int sof_ipc4_set_get_data(struct snd_sof_dev *sdev, void *data,
507537
rx.data_size = chunk_size;
508538
rx.data_ptr = ipc4_msg->data_ptr + offset;
509539

510-
tx_size = 0;
540+
if (tx_payload_for_get) {
541+
tx_size = tx_data_size;
542+
tx.data_size = tx_size;
543+
tx.data_ptr = tx_payload_for_get;
544+
} else {
545+
tx_size = 0;
546+
tx.data_size = 0;
547+
tx.data_ptr = NULL;
548+
}
511549
rx_size = chunk_size;
512550
}
513551

@@ -554,6 +592,8 @@ static int sof_ipc4_set_get_data(struct snd_sof_dev *sdev, void *data,
554592

555593
mutex_unlock(&sdev->ipc->tx_mutex);
556594

595+
kfree(tx_payload_for_get);
596+
557597
return ret;
558598
}
559599

0 commit comments

Comments
 (0)