Skip to content

Commit 792f7b0

Browse files
committed
tools: plugin: Add support for enum controls
Add support for enum controls in the plugin. Fix the get_attribute and get_enumerated_name callbacks to use the enum control items instad of the count. Signed-off-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
1 parent 9715065 commit 792f7b0

File tree

2 files changed

+149
-8
lines changed

2 files changed

+149
-8
lines changed

tools/plugin/alsaplug/ctl.c

Lines changed: 136 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ static int plug_ctl_get_attribute(snd_ctl_ext_t *ext, snd_ctl_ext_key_t key,
119119
struct snd_soc_tplg_bytes_control *bytes_ctl;
120120
int err = 0;
121121

122-
switch (hdr->type) {
122+
switch (hdr->ops.info) {
123123
case SND_SOC_TPLG_CTL_VOLSW:
124124
case SND_SOC_TPLG_CTL_VOLSW_SX:
125125
case SND_SOC_TPLG_CTL_VOLSW_XR_SX:
@@ -138,7 +138,7 @@ static int plug_ctl_get_attribute(snd_ctl_ext_t *ext, snd_ctl_ext_key_t key,
138138
case SND_SOC_TPLG_CTL_ENUM_VALUE:
139139
enum_ctl = (struct snd_soc_tplg_enum_control *)hdr;
140140
*type = SND_CTL_ELEM_TYPE_ENUMERATED;
141-
*count = enum_ctl->num_channels;
141+
*count = enum_ctl->items;
142142
break;
143143
case SND_SOC_TPLG_CTL_RANGE:
144144
case SND_SOC_TPLG_CTL_STROBE:
@@ -373,7 +373,7 @@ static int plug_ctl_get_enumerated_info(snd_ctl_ext_t *ext, snd_ctl_ext_key_t ke
373373
(struct snd_soc_tplg_enum_control *)hdr;
374374
int err = 0;
375375

376-
switch (hdr->type) {
376+
switch (hdr->ops.info) {
377377
case SND_SOC_TPLG_CTL_ENUM:
378378
case SND_SOC_TPLG_CTL_ENUM_VALUE:
379379
*items = enum_ctl->items;
@@ -395,10 +395,8 @@ static int plug_ctl_get_enumerated_name(snd_ctl_ext_t *ext, snd_ctl_ext_key_t ke
395395
struct snd_soc_tplg_enum_control *enum_ctl =
396396
(struct snd_soc_tplg_enum_control *)hdr;
397397

398-
printf("%s %d\n", __func__, __LINE__);
399-
400-
if (item >= enum_ctl->count) {
401-
SNDERR("invalid item %d for enum using key %d", item, key);
398+
if (item >= enum_ctl->items) {
399+
SNDERR("invalid item %d for enum using key %d\n", item, key);
402400
return -EINVAL;
403401
}
404402

@@ -409,12 +407,143 @@ static int plug_ctl_get_enumerated_name(snd_ctl_ext_t *ext, snd_ctl_ext_key_t ke
409407
static int plug_ctl_read_enumerated(snd_ctl_ext_t *ext, snd_ctl_ext_key_t key,
410408
unsigned int *items)
411409
{
410+
snd_sof_ctl_t *ctl = ext->private_data;
411+
struct snd_soc_tplg_enum_control *enum_ctl = CTL_GET_TPLG_ENUM(ctl, key);
412+
struct ipc4_module_large_config config = {{ 0 }};
413+
struct ipc4_module_large_config_reply *reply;
414+
struct sof_ipc4_control_msg_payload *data;
415+
char *reply_data;
416+
void *msg;
417+
int size, reply_data_size;
418+
int i, err;
419+
420+
/* configure the IPC message */
421+
plug_ctl_ipc_message(&config, SOF_IPC4_ENUM_CONTROL_PARAM_ID, 0,
422+
ctl->glb->ctl[key].module_id, ctl->glb->ctl[key].instance_id,
423+
SOF_IPC4_MOD_LARGE_CONFIG_GET);
424+
425+
config.extension.r.final_block = 1;
426+
config.extension.r.init_block = 1;
427+
428+
size = sizeof(config);
429+
msg = calloc(size, 1);
430+
if (!msg)
431+
return -ENOMEM;
432+
433+
/* reply contains both the requested data and the reply status */
434+
reply_data_size = sizeof(*reply) + sizeof(*data) +
435+
enum_ctl->num_channels * sizeof(data->chanv[0]);
436+
reply_data = calloc(reply_data_size, 1);
437+
if (!reply_data_size) {
438+
free(msg);
439+
return -ENOMEM;
440+
}
441+
442+
/* send the IPC message */
443+
memcpy(msg, &config, sizeof(config));
444+
err = plug_mq_cmd_tx_rx(&ctl->ipc_tx, &ctl->ipc_rx,
445+
msg, size, reply_data, reply_data_size);
446+
free(msg);
447+
if (err < 0) {
448+
SNDERR("failed to get enum items for control %s\n", enum_ctl->hdr.name);
449+
goto out;
450+
}
451+
452+
reply = (struct ipc4_module_large_config_reply *)reply_data;
453+
if (reply->primary.r.status != IPC4_SUCCESS) {
454+
SNDERR("enum control %s get failed with status %d\n",
455+
enum_ctl->hdr.name, reply->primary.r.status);
456+
err = -EINVAL;
457+
goto out;
458+
}
459+
460+
/* check data sanity */
461+
data = (struct sof_ipc4_control_msg_payload *)(reply_data + sizeof(*reply));
462+
if (data->num_elems != enum_ctl->num_channels) {
463+
SNDERR("Channel count %d doesn't match the expected value %d for enum ctl %s\n",
464+
data->num_elems, enum_ctl->num_channels, enum_ctl->hdr.name);
465+
err = -EINVAL;
466+
goto out;
467+
}
468+
469+
/* set the enum items based on the received data */
470+
for (i = 0; i < enum_ctl->num_channels; i++)
471+
items[i] = data->chanv[i].value;
472+
out:
473+
free(reply_data);
412474
return 0;
413475
}
414476

415477
static int plug_ctl_write_enumerated(snd_ctl_ext_t *ext, snd_ctl_ext_key_t key,
416478
unsigned int *items)
417479
{
480+
snd_sof_ctl_t *ctl = ext->private_data;
481+
struct snd_soc_tplg_enum_control *enum_ctl = CTL_GET_TPLG_ENUM(ctl, key);
482+
struct ipc4_module_large_config config = {{ 0 }};
483+
struct sof_ipc4_control_msg_payload *data;
484+
struct ipc4_message_reply reply;
485+
void *msg;
486+
int data_size, msg_size;
487+
int err, i;
488+
489+
/* size of control data */
490+
data_size = enum_ctl->num_channels * sizeof(struct sof_ipc4_ctrl_value_chan) +
491+
sizeof(*data);
492+
493+
/* allocate memory for control data */
494+
data = calloc(data_size, 1);
495+
if (!data)
496+
return -ENOMEM;
497+
498+
/* set param ID and number of channels */
499+
data->id = ctl->glb->ctl[key].index;
500+
data->num_elems = enum_ctl->num_channels;
501+
502+
/* set the enum values */
503+
for (i = 0; i < data->num_elems; i++) {
504+
data->chanv[i].channel = i;
505+
data->chanv[i].value = items[i];
506+
}
507+
508+
/* configure the IPC message */
509+
plug_ctl_ipc_message(&config, SOF_IPC4_ENUM_CONTROL_PARAM_ID, data_size,
510+
ctl->glb->ctl[key].module_id, ctl->glb->ctl[key].instance_id,
511+
SOF_IPC4_MOD_LARGE_CONFIG_SET);
512+
513+
/*
514+
* enum controls can have a maximum of 16 texts/values. So the entire data can be sent
515+
* in a single IPC message
516+
*/
517+
config.extension.r.final_block = 1;
518+
config.extension.r.init_block = 1;
519+
520+
/* allocate memory for IPC message */
521+
msg_size = sizeof(config) + data_size;
522+
msg = calloc(msg_size, 1);
523+
if (!msg) {
524+
free(data);
525+
return -ENOMEM;
526+
}
527+
528+
/* set the IPC message data */
529+
memcpy(msg, &config, sizeof(config));
530+
memcpy(msg + sizeof(config), data, data_size);
531+
free(data);
532+
533+
/* send the message and check status */
534+
err = plug_mq_cmd_tx_rx(&ctl->ipc_tx, &ctl->ipc_rx, msg, msg_size, &reply, sizeof(reply));
535+
free(msg);
536+
if (err < 0) {
537+
SNDERR("failed to set enum control %s\n", enum_ctl->hdr.name);
538+
return err;
539+
}
540+
541+
if (reply.primary.r.status != IPC4_SUCCESS) {
542+
SNDERR("enum control %s set failed with status %d\n",
543+
enum_ctl->hdr.name, reply.primary.r.status);
544+
return -EINVAL;
545+
}
546+
418547
return 0;
419548
}
420549

tools/plugin/alsaplug/tplg_ctl.c

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,7 @@ static uint32_t vol_compute_gain(uint32_t value, struct snd_soc_tplg_tlv_dbscale
143143
/* helper function to add new kcontrols to the list of kcontrols in the global context */
144144
int plug_kcontrol_cb_new(struct snd_soc_tplg_ctl_hdr *tplg_ctl, void *_comp, void *arg, int index)
145145
{
146+
struct tplg_comp_info *comp_info = _comp;
146147
snd_sof_plug_t *plug = arg;
147148
struct plug_shm_glb_state *glb = plug->glb_ctx.addr;
148149
struct plug_shm_ctl *ctl;
@@ -159,7 +160,6 @@ int plug_kcontrol_cb_new(struct snd_soc_tplg_ctl_hdr *tplg_ctl, void *_comp, voi
159160
{
160161
struct snd_soc_tplg_mixer_control *tplg_mixer =
161162
(struct snd_soc_tplg_mixer_control *)tplg_ctl;
162-
struct tplg_comp_info *comp_info = _comp;
163163
struct snd_soc_tplg_ctl_tlv *tlv;
164164
struct snd_soc_tplg_tlv_dbscale *scale;
165165
int i;
@@ -187,6 +187,18 @@ int plug_kcontrol_cb_new(struct snd_soc_tplg_ctl_hdr *tplg_ctl, void *_comp, voi
187187
}
188188
case SND_SOC_TPLG_CTL_ENUM:
189189
case SND_SOC_TPLG_CTL_ENUM_VALUE:
190+
{
191+
struct snd_soc_tplg_enum_control *tplg_enum =
192+
(struct snd_soc_tplg_enum_control *)tplg_ctl;
193+
194+
glb->size += sizeof(struct plug_shm_ctl);
195+
ctl = &glb->ctl[glb->num_ctls++];
196+
ctl->module_id = comp_info->module_id;
197+
ctl->instance_id = comp_info->instance_id;
198+
ctl->enum_ctl = *tplg_enum;
199+
ctl->index = index;
200+
break;
201+
}
190202
case SND_SOC_TPLG_CTL_BYTES:
191203
break;
192204
case SND_SOC_TPLG_CTL_RANGE:

0 commit comments

Comments
 (0)