mirror of https://github.com/thesofproject/sof.git
160 lines
4.4 KiB
C
160 lines
4.4 KiB
C
// SPDX-License-Identifier: BSD-3-Clause
|
|
//
|
|
// Copyright(c) 2019 Intel Corporation. All rights reserved.
|
|
//
|
|
// Author: Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
|
|
|
|
/* Topology parser */
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <stdint.h>
|
|
#include <stddef.h>
|
|
#include <errno.h>
|
|
#include <string.h>
|
|
#include <ipc/topology.h>
|
|
#include <sof/lib/uuid.h>
|
|
#include <sof/ipc/topology.h>
|
|
#include <tplg_parser/topology.h>
|
|
#include <tplg_parser/tokens.h>
|
|
|
|
int tplg_get_single_control(struct tplg_context *ctx,
|
|
struct snd_soc_tplg_ctl_hdr **ctl,
|
|
struct snd_soc_tplg_private **priv_data)
|
|
{
|
|
struct snd_soc_tplg_ctl_hdr *ctl_hdr;
|
|
struct snd_soc_tplg_mixer_control *mixer_ctl = NULL;
|
|
struct snd_soc_tplg_enum_control *enum_ctl = NULL;
|
|
struct snd_soc_tplg_bytes_control *bytes_ctl = NULL;
|
|
|
|
/* These are set if success */
|
|
*ctl = NULL;
|
|
*priv_data = NULL;
|
|
|
|
ctl_hdr = tplg_get(ctx);
|
|
|
|
/* load control based on type */
|
|
switch (ctl_hdr->ops.info) {
|
|
case SND_SOC_TPLG_CTL_VOLSW:
|
|
case SND_SOC_TPLG_CTL_STROBE:
|
|
case SND_SOC_TPLG_CTL_VOLSW_SX:
|
|
case SND_SOC_TPLG_CTL_VOLSW_XR_SX:
|
|
case SND_SOC_TPLG_CTL_RANGE:
|
|
case SND_SOC_TPLG_DAPM_CTL_VOLSW:
|
|
/* load mixer type control */
|
|
mixer_ctl = (struct snd_soc_tplg_mixer_control *)ctl_hdr;
|
|
if (priv_data)
|
|
*priv_data = &mixer_ctl->priv;
|
|
/* ctl is after private data */
|
|
*ctl = tplg_get_object_priv(ctx, mixer_ctl, mixer_ctl->priv.size);
|
|
break;
|
|
|
|
case SND_SOC_TPLG_CTL_ENUM:
|
|
case SND_SOC_TPLG_CTL_ENUM_VALUE:
|
|
case SND_SOC_TPLG_DAPM_CTL_ENUM_DOUBLE:
|
|
case SND_SOC_TPLG_DAPM_CTL_ENUM_VIRT:
|
|
case SND_SOC_TPLG_DAPM_CTL_ENUM_VALUE:
|
|
/* load enum type control */
|
|
enum_ctl = (struct snd_soc_tplg_enum_control *)ctl_hdr;
|
|
if (priv_data)
|
|
*priv_data = &enum_ctl->priv;
|
|
/* ctl is after private data */
|
|
*ctl = tplg_get_object_priv(ctx, enum_ctl, enum_ctl->priv.size);
|
|
break;
|
|
case SND_SOC_TPLG_CTL_BYTES:
|
|
/* load bytes type control */
|
|
bytes_ctl = (struct snd_soc_tplg_bytes_control *)ctl_hdr;
|
|
if (priv_data)
|
|
*priv_data = &bytes_ctl->priv;
|
|
/* ctl is after private data */
|
|
*ctl = tplg_get_object_priv(ctx, bytes_ctl, bytes_ctl->priv.size);
|
|
break;
|
|
|
|
default:
|
|
printf("info: control type %d not supported\n",
|
|
ctl_hdr->ops.info);
|
|
return -EINVAL;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* load dapm widget kcontrols
|
|
* we don't use controls in the fuzzer atm.
|
|
* so just skip to the next dapm widget
|
|
*/
|
|
int tplg_create_controls(struct tplg_context *ctx, int num_kcontrols,
|
|
struct snd_soc_tplg_ctl_hdr *rctl,
|
|
size_t max_ctl_size, void *object)
|
|
{
|
|
struct snd_soc_tplg_ctl_hdr *ctl_hdr = NULL;
|
|
struct snd_soc_tplg_mixer_control *mixer_ctl;
|
|
struct snd_soc_tplg_enum_control *enum_ctl;
|
|
struct snd_soc_tplg_bytes_control *bytes_ctl;
|
|
int num_mixers = 0;
|
|
int num_enums = 0;
|
|
int num_byte_controls = 0;
|
|
int index;
|
|
int j, ret = 0;
|
|
|
|
for (j = 0; j < num_kcontrols; j++) {
|
|
|
|
ctl_hdr = tplg_get(ctx);
|
|
|
|
/* load control based on type */
|
|
switch (ctl_hdr->ops.info) {
|
|
case SND_SOC_TPLG_CTL_VOLSW:
|
|
case SND_SOC_TPLG_CTL_STROBE:
|
|
case SND_SOC_TPLG_CTL_VOLSW_SX:
|
|
case SND_SOC_TPLG_CTL_VOLSW_XR_SX:
|
|
case SND_SOC_TPLG_CTL_RANGE:
|
|
case SND_SOC_TPLG_DAPM_CTL_VOLSW:
|
|
index = num_mixers++;
|
|
/* load mixer type control */
|
|
mixer_ctl = (struct snd_soc_tplg_mixer_control *)ctl_hdr;
|
|
/* ctl is after private data */
|
|
tplg_get_object_priv(ctx, mixer_ctl, mixer_ctl->priv.size);
|
|
break;
|
|
|
|
case SND_SOC_TPLG_CTL_ENUM:
|
|
case SND_SOC_TPLG_CTL_ENUM_VALUE:
|
|
case SND_SOC_TPLG_DAPM_CTL_ENUM_DOUBLE:
|
|
case SND_SOC_TPLG_DAPM_CTL_ENUM_VIRT:
|
|
case SND_SOC_TPLG_DAPM_CTL_ENUM_VALUE:
|
|
index = num_enums++;
|
|
/* load enum_ctl type control */
|
|
enum_ctl = (struct snd_soc_tplg_enum_control *)ctl_hdr;
|
|
/* ctl is after private data */
|
|
tplg_get_object_priv(ctx, enum_ctl, enum_ctl->priv.size);
|
|
break;
|
|
|
|
case SND_SOC_TPLG_CTL_BYTES:
|
|
index = num_byte_controls++;
|
|
/* load bytes_ctl type control */
|
|
bytes_ctl = (struct snd_soc_tplg_bytes_control *)ctl_hdr;
|
|
/* ctl is after private data */
|
|
tplg_get_object_priv(ctx, bytes_ctl, bytes_ctl->priv.size);
|
|
break;
|
|
default:
|
|
printf("info: control type %d not supported\n",
|
|
ctl_hdr->ops.info);
|
|
return -EINVAL;
|
|
}
|
|
|
|
if (ctx->ctl_cb && object)
|
|
ctx->ctl_cb(ctl_hdr, object, ctx->ctl_arg, index);
|
|
}
|
|
|
|
if (rctl && ctl_hdr) {
|
|
/* make sure the CTL will fit if we need to copy it for others */
|
|
if (ctl_hdr->size > max_ctl_size) {
|
|
fprintf(stderr, "error: failed control control copy\n");
|
|
ret = -EINVAL;
|
|
goto err;
|
|
}
|
|
memcpy(rctl, ctl_hdr, ctl_hdr->size);
|
|
}
|
|
err:
|
|
return ret;
|
|
}
|