Skip to content

Commit 88cde10

Browse files
ranj063lgirdwood
authored andcommitted
tools: plugin: ctl: Add support for bytes control
Add a new field in struct plug_shm_ctl to save the bytes data from topology for bytes controls. This will be used to send the kcontrol data to the modules right after they are instantiated. Fix the tlv callback in the control to handle the tlv bytes read/write when using sof-ctl. Signed-off-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
1 parent ec8c6c7 commit 88cde10

File tree

6 files changed

+232
-17
lines changed

6 files changed

+232
-17
lines changed

tools/plugin/README.md

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,21 @@ or
7979
```
8080
amixer -Dsof:plugin cset numid=1 20
8181
```
82-
Right now, only volume controls are supported. Support for bytes and enum controls is pending.
82+
Bytes control data can be set using sof-ctl as follows:
83+
84+
```
85+
./sof-ctl -Dsof:plugin -n 4 -r -i 4 -p 2 -s ~/data.txt
86+
```
87+
where -n is the numid of the kcontrol, -i is the IPC version, -p is the param ID and -s specifies
88+
the data in csv format.
89+
90+
Bytes control data can be read using sof-ctl as follows:
91+
```
92+
./sof-ctl -Dsof:plugin -n 4 -i 4 -p 2
93+
```
94+
where -n is the numid of the kcontrol, -i is the IPC version and -p is the param ID.
95+
96+
Note: Bytes controls must have tlv_read/tlv_write and tlv_callback access.
8397

8498
# Instructions for testing OpenVino noise suppression model with the SOF plugin:
8599
1. Fetch the model from the Open Model zoo repository ex: noise-suppression-poconetlike-0001.xml

tools/plugin/alsaplug/ctl.c

Lines changed: 125 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -145,10 +145,9 @@ static int plug_ctl_get_attribute(snd_ctl_ext_t *ext, snd_ctl_ext_key_t key,
145145
// TODO: ??
146146
break;
147147
case SND_SOC_TPLG_CTL_BYTES:
148-
printf("%s %d\n", __func__, __LINE__);
149148
bytes_ctl = (struct snd_soc_tplg_bytes_control *)hdr;
150149
*type = SND_CTL_ELEM_TYPE_BYTES;
151-
*count = bytes_ctl->size; // Not sure if size is correct
150+
*count = bytes_ctl->max;
152151
break;
153152
}
154153

@@ -536,36 +535,147 @@ static int plug_ctl_write_enumerated(snd_ctl_ext_t *ext, snd_ctl_ext_key_t key,
536535
/*
537536
* Bytes ops
538537
*/
538+
static int plug_ctl_get_bytes_data(snd_sof_ctl_t *ctl, snd_ctl_ext_key_t key,
539+
struct sof_abi_hdr *abi, unsigned int max_bytes)
540+
{
541+
struct snd_soc_tplg_bytes_control *bytes_ctl = CTL_GET_TPLG_BYTES(ctl, key);
542+
struct ipc4_module_large_config config = {{ 0 }};
543+
struct ipc4_module_large_config_reply *reply;
544+
char *reply_data, *data;
545+
void *msg;
546+
uint32_t data_size;
547+
int size, reply_data_size;
548+
int err;
549+
550+
/* configure the IPC message */
551+
plug_ctl_ipc_message(&config, abi->type, 0,
552+
ctl->glb->ctl[key].module_id, ctl->glb->ctl[key].instance_id,
553+
SOF_IPC4_MOD_LARGE_CONFIG_GET);
554+
555+
config.extension.r.final_block = 1;
556+
config.extension.r.init_block = 1;
557+
558+
size = sizeof(config);
559+
msg = calloc(size, 1);
560+
if (!msg)
561+
return -ENOMEM;
562+
563+
/*
564+
* reply contains both the requested data and the reply status. Allocate enough memory
565+
* for max data
566+
*/
567+
reply_data_size = sizeof(*reply) + sizeof(*data) + bytes_ctl->max;
568+
reply_data = calloc(reply_data_size, 1);
569+
if (!reply_data_size) {
570+
free(msg);
571+
return -ENOMEM;
572+
}
573+
574+
/* send the IPC message */
575+
memcpy(msg, &config, sizeof(config));
576+
err = plug_mq_cmd_tx_rx(&ctl->ipc_tx, &ctl->ipc_rx,
577+
msg, size, reply_data, reply_data_size);
578+
free(msg);
579+
if (err < 0) {
580+
SNDERR("failed to get bytes data for control %s\n", bytes_ctl->hdr.name);
581+
goto out;
582+
}
583+
584+
reply = (struct ipc4_module_large_config_reply *)reply_data;
585+
if (reply->primary.r.status != IPC4_SUCCESS) {
586+
SNDERR("bytes control %s get failed with status %d\n",
587+
bytes_ctl->hdr.name, reply->primary.r.status);
588+
err = -EINVAL;
589+
goto out;
590+
}
591+
592+
/* check data sanity */
593+
data = (char *)(reply_data + sizeof(*reply));
594+
data_size = reply->extension.r.data_off_size;
595+
if (data_size > bytes_ctl->max) {
596+
SNDERR("received data size %d is larger than max %d for bytes control %s\n",
597+
data_size, bytes_ctl->max, bytes_ctl->hdr.name);
598+
err = -EINVAL;
599+
goto out;
600+
}
601+
602+
abi->size = data_size;
603+
604+
if (data_size)
605+
memcpy(abi->data, data, MIN(data_size, max_bytes));
606+
607+
err = data_size;
608+
out:
609+
free(reply_data);
610+
return err;
611+
}
612+
539613
static int plug_ctl_read_bytes(snd_ctl_ext_t *ext, snd_ctl_ext_key_t key,
540614
unsigned char *data, size_t max_bytes)
541615
{
616+
snd_sof_ctl_t *ctl = ext->private_data;
617+
struct sof_abi_hdr *abi = (struct sof_abi_hdr *)data;
618+
int data_size;
619+
620+
data_size = plug_ctl_get_bytes_data(ctl, key, abi, max_bytes);
621+
if (data_size < 0)
622+
return data_size;
623+
542624
return 0;
543625
}
544626

545627
static int plug_ctl_write_bytes(snd_ctl_ext_t *ext, snd_ctl_ext_key_t key,
546628
unsigned char *data, size_t max_bytes)
547629
{
630+
snd_sof_ctl_t *ctl = ext->private_data;
631+
struct snd_soc_tplg_bytes_control *bytes_ctl = CTL_GET_TPLG_BYTES(ctl, key);
632+
struct sof_abi_hdr *abi = (struct sof_abi_hdr *)data;
633+
int err;
634+
635+
/* send IPC with kcontrol data */
636+
err = plug_send_bytes_data(&ctl->ipc_tx, &ctl->ipc_rx,
637+
ctl->glb->ctl[key].module_id, ctl->glb->ctl[key].instance_id,
638+
abi);
639+
if (err < 0) {
640+
SNDERR("failed to set bytes data for control %s\n", bytes_ctl->hdr.name);
641+
return err;
642+
}
643+
548644
return 0;
549645
}
550646

551-
/*
552-
* TLV ops
553-
*
554-
* The format of an array of \a tlv argument is:
555-
* tlv[0]: Type. One of SND_CTL_TLVT_XXX.
556-
* tlv[1]: Length. The length of value in units of byte.
557-
* tlv[2..]: Value. Depending on the type.
558-
*/
647+
/* TLV ops used for TLV bytes control callback */
559648
static int plug_tlv_rw(snd_ctl_ext_t *ext, snd_ctl_ext_key_t key, int op_flag,
560649
unsigned int numid, unsigned int *tlv, unsigned int tlv_size)
561650
{
562651
snd_sof_ctl_t *ctl = ext->private_data;
563-
struct snd_soc_tplg_ctl_hdr *hdr = CTL_GET_TPLG_HDR(ctl, key);
652+
struct snd_soc_tplg_bytes_control *bytes_ctl = CTL_GET_TPLG_BYTES(ctl, key);
653+
struct sof_abi_hdr *abi = (struct sof_abi_hdr *)(tlv + 2); /* skip TLV header */
654+
int data_size;
655+
656+
/* send IPC with kcontrol data if op_flag is > 0 else send IPC to get kcontrol data */
657+
if (op_flag) {
658+
int err;
659+
660+
err = plug_send_bytes_data(&ctl->ipc_tx, &ctl->ipc_rx,
661+
ctl->glb->ctl[key].module_id,
662+
ctl->glb->ctl[key].instance_id, abi);
663+
if (err < 0) {
664+
SNDERR("failed to set bytes data for control %s\n", bytes_ctl->hdr.name);
665+
return err;
666+
}
667+
668+
return 0;
669+
}
670+
671+
/* read kcontrol data */
672+
data_size = plug_ctl_get_bytes_data(ctl, key, abi, tlv_size);
673+
if (data_size < 0)
674+
return data_size;
564675

565-
//TODO: alsamixer showing wrong dB scales
566-
tlv[0] = hdr->tlv.type;
567-
tlv[1] = hdr->tlv.size - sizeof(uint32_t) * 2;
568-
memcpy(&tlv[2], hdr->tlv.data, hdr->tlv.size - sizeof(uint32_t) * 2);
676+
/* set data size and numid */
677+
tlv[0] = numid;
678+
tlv[1] = data_size + sizeof(*abi);
569679

570680
return 0;
571681
}

tools/plugin/alsaplug/tplg.c

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include <assert.h>
2424
#include <errno.h>
2525
#include <dlfcn.h>
26+
#include <kernel/header.h>
2627

2728
#include <ipc4/error_status.h>
2829

@@ -1105,7 +1106,9 @@ static int plug_set_up_route(snd_sof_plug_t *plug, struct tplg_route_info *route
11051106
static int plug_set_up_widget(snd_sof_plug_t *plug, struct tplg_comp_info *comp_info)
11061107
{
11071108
struct tplg_pipeline_info *pipe_info = comp_info->pipe_info;
1108-
int ret;
1109+
struct plug_shm_glb_state *glb = plug->glb_ctx.addr;
1110+
struct plug_shm_ctl *ctl;
1111+
int ret, i;
11091112

11101113
pipe_info->usage_count++;
11111114

@@ -1123,6 +1126,33 @@ static int plug_set_up_widget(snd_sof_plug_t *plug, struct tplg_comp_info *comp_
11231126
if (ret < 0)
11241127
return ret;
11251128

1129+
/* send kcontrol bytes data */
1130+
for (i = 0; i < glb->num_ctls; i++) {
1131+
struct snd_soc_tplg_bytes_control *tplg_bytes;
1132+
struct sof_abi_hdr *abi;
1133+
int priv_size;
1134+
1135+
ctl = &glb->ctl[i];
1136+
1137+
/* send the bytes data from kcontrols associated with current widget */
1138+
if (ctl->module_id != comp_info->module_id ||
1139+
ctl->instance_id != comp_info->instance_id ||
1140+
ctl->type != SND_SOC_TPLG_TYPE_BYTES)
1141+
continue;
1142+
1143+
tplg_bytes = &ctl->bytes_ctl;
1144+
priv_size = tplg_bytes->priv.size;
1145+
abi = (struct sof_abi_hdr *)ctl->data;
1146+
1147+
/* send IPC with kcontrol data */
1148+
ret = plug_send_bytes_data(&plug->ipc_tx, &plug->ipc_rx,
1149+
comp_info->module_id, comp_info->instance_id, abi);
1150+
if (ret < 0) {
1151+
SNDERR("failed to set bytes data for widget %s\n", comp_info->name);
1152+
return ret;
1153+
}
1154+
}
1155+
11261156
tplg_debug("widget %s set up\n", comp_info->name);
11271157

11281158
return 0;

tools/plugin/alsaplug/tplg_ctl.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,20 @@ int plug_kcontrol_cb_new(struct snd_soc_tplg_ctl_hdr *tplg_ctl, void *_comp, voi
202202
break;
203203
}
204204
case SND_SOC_TPLG_CTL_BYTES:
205+
{
206+
struct snd_soc_tplg_bytes_control *tplg_bytes =
207+
(struct snd_soc_tplg_bytes_control *)tplg_ctl;
208+
209+
glb->size += sizeof(struct plug_shm_ctl);
210+
ctl = &glb->ctl[glb->num_ctls++];
211+
ctl->module_id = comp_info->module_id;
212+
ctl->instance_id = comp_info->instance_id;
213+
ctl->bytes_ctl = *tplg_bytes;
214+
ctl->index = index;
215+
ctl->type = tplg_ctl->type;
216+
memcpy(ctl->data, tplg_bytes->priv.data, tplg_bytes->priv.size);
205217
break;
218+
}
206219
case SND_SOC_TPLG_CTL_RANGE:
207220
case SND_SOC_TPLG_CTL_STROBE:
208221
default:

tools/plugin/common.c

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -264,3 +264,45 @@ void plug_ctl_ipc_message(struct ipc4_module_large_config *config, int param_id,
264264
config->extension.r.data_off_size = size;
265265
config->extension.r.large_param_id = param_id;
266266
}
267+
268+
int plug_send_bytes_data(struct plug_mq_desc *ipc_tx, struct plug_mq_desc *ipc_rx,
269+
uint32_t module_id, uint32_t instance_id, struct sof_abi_hdr *abi)
270+
{
271+
struct ipc4_module_large_config config = {{ 0 }};
272+
struct ipc4_message_reply reply;
273+
void *msg;
274+
int msg_size;
275+
int err;
276+
277+
/* configure the IPC message */
278+
plug_ctl_ipc_message(&config, abi->type, abi->size, module_id, instance_id,
279+
SOF_IPC4_MOD_LARGE_CONFIG_SET);
280+
281+
config.extension.r.final_block = 1;
282+
config.extension.r.init_block = 1;
283+
284+
/* allocate memory for IPC message */
285+
msg_size = sizeof(config) + abi->size;
286+
msg = calloc(msg_size, 1);
287+
if (!msg)
288+
return -ENOMEM;
289+
290+
/* set the IPC message data */
291+
memcpy(msg, &config, sizeof(config));
292+
memcpy(msg + sizeof(config), abi->data, abi->size);
293+
294+
/* send the message and check status */
295+
err = plug_mq_cmd_tx_rx(ipc_tx, ipc_rx, msg, msg_size, &reply, sizeof(reply));
296+
free(msg);
297+
if (err < 0) {
298+
SNDERR("failed to send IPC to set bytes data\n");
299+
return err;
300+
}
301+
302+
if (reply.primary.r.status != IPC4_SUCCESS) {
303+
SNDERR("IPC failed with status %d\n", reply.primary.r.status);
304+
return -EINVAL;
305+
}
306+
307+
return 0;
308+
}

tools/plugin/common.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
#include <mqueue.h>
1313
#include <semaphore.h>
1414
#include <alsa/asoundlib.h>
15+
#include <ipc/control.h>
16+
#include <tplg_parser/topology.h>
1517

1618
/* temporary - current MAXLEN is not define in UAPI header - fix pending */
1719
#ifndef SNDRV_CTL_ELEM_ID_NAME_MAXLEN
@@ -52,6 +54,7 @@
5254

5355
#define SOF_MAGIC "sofpipe"
5456
#define MAX_VOLUME_SIZE 120
57+
#define MAX_DATA_SIZE 512
5558

5659
enum plugin_state {
5760
SOF_PLUGIN_STATE_INIT = 0,
@@ -67,6 +70,7 @@ struct plug_shm_ctl {
6770
unsigned int type;
6871
unsigned int volume_table[MAX_VOLUME_SIZE];
6972
unsigned int index;
73+
char data[MAX_DATA_SIZE];
7074
union {
7175
struct snd_soc_tplg_mixer_control mixer_ctl;
7276
struct snd_soc_tplg_enum_control enum_ctl;
@@ -320,5 +324,7 @@ static inline void data_dump(void *vdata, size_t bytes)
320324
void plug_ctl_ipc_message(struct ipc4_module_large_config *config, int param_id,
321325
size_t size, uint32_t module_id, uint32_t instance_id,
322326
uint32_t type);
327+
int plug_send_bytes_data(struct plug_mq_desc *ipc_tx, struct plug_mq_desc *ipc_rx,
328+
uint32_t module_id, uint32_t instance_id, struct sof_abi_hdr *abi);
323329

324330
#endif

0 commit comments

Comments
 (0)