sof/tools/tplg_parser/audio_formats.c

151 lines
6.5 KiB
C

// SPDX-License-Identifier: BSD-3-Clause
//
// Copyright(c) 2023 Intel Corporation. All rights reserved.
//
// Author: Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
/* Audio format token parser */
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stddef.h>
#include <errno.h>
#include <string.h>
#include <math.h>
#include <ipc/topology.h>
#include <sof/ipc/topology.h>
#include <tplg_parser/topology.h>
#include <tplg_parser/tokens.h>
static const struct sof_topology_token ipc4_audio_fmt_num_tokens[] = {
{SOF_TKN_COMP_NUM_INPUT_AUDIO_FORMATS, SND_SOC_TPLG_TUPLE_TYPE_WORD,
tplg_token_get_uint32_t,
offsetof(struct sof_ipc4_available_audio_format, num_input_formats)},
{SOF_TKN_COMP_NUM_OUTPUT_AUDIO_FORMATS, SND_SOC_TPLG_TUPLE_TYPE_WORD,
tplg_token_get_uint32_t,
offsetof(struct sof_ipc4_available_audio_format, num_output_formats)},
};
static const struct sof_topology_token ipc4_in_audio_format_tokens[] = {
{SOF_TKN_CAVS_AUDIO_FORMAT_IN_RATE, SND_SOC_TPLG_TUPLE_TYPE_WORD, tplg_token_get_uint32_t,
offsetof(struct sof_ipc4_pin_format, audio_fmt.sampling_frequency)},
{SOF_TKN_CAVS_AUDIO_FORMAT_IN_BIT_DEPTH, SND_SOC_TPLG_TUPLE_TYPE_WORD,
tplg_token_get_uint32_t, offsetof(struct sof_ipc4_pin_format, audio_fmt.bit_depth)},
{SOF_TKN_CAVS_AUDIO_FORMAT_IN_CH_MAP, SND_SOC_TPLG_TUPLE_TYPE_WORD,
tplg_token_get_uint32_t, offsetof(struct sof_ipc4_pin_format, audio_fmt.ch_map)},
{SOF_TKN_CAVS_AUDIO_FORMAT_IN_CH_CFG, SND_SOC_TPLG_TUPLE_TYPE_WORD,
tplg_token_get_uint32_t, offsetof(struct sof_ipc4_pin_format, audio_fmt.ch_cfg)},
{SOF_TKN_CAVS_AUDIO_FORMAT_IN_INTERLEAVING_STYLE, SND_SOC_TPLG_TUPLE_TYPE_WORD,
tplg_token_get_uint32_t,
offsetof(struct sof_ipc4_pin_format, audio_fmt.interleaving_style)},
{SOF_TKN_CAVS_AUDIO_FORMAT_IN_FMT_CFG, SND_SOC_TPLG_TUPLE_TYPE_WORD,
tplg_token_get_uint32_t, offsetof(struct sof_ipc4_pin_format, audio_fmt.fmt_cfg)},
{SOF_TKN_CAVS_AUDIO_FORMAT_INPUT_PIN_INDEX, SND_SOC_TPLG_TUPLE_TYPE_WORD,
tplg_token_get_uint32_t, offsetof(struct sof_ipc4_pin_format, pin_index)},
{SOF_TKN_CAVS_AUDIO_FORMAT_IBS, SND_SOC_TPLG_TUPLE_TYPE_WORD,
tplg_token_get_uint32_t, offsetof(struct sof_ipc4_pin_format, buffer_size)},
};
static const struct sof_topology_token ipc4_out_audio_format_tokens[] = {
{SOF_TKN_CAVS_AUDIO_FORMAT_OUT_RATE, SND_SOC_TPLG_TUPLE_TYPE_WORD,
tplg_token_get_uint32_t,
offsetof(struct sof_ipc4_pin_format, audio_fmt.sampling_frequency)},
{SOF_TKN_CAVS_AUDIO_FORMAT_OUT_BIT_DEPTH, SND_SOC_TPLG_TUPLE_TYPE_WORD,
tplg_token_get_uint32_t, offsetof(struct sof_ipc4_pin_format, audio_fmt.bit_depth)},
{SOF_TKN_CAVS_AUDIO_FORMAT_OUT_CH_MAP, SND_SOC_TPLG_TUPLE_TYPE_WORD,
tplg_token_get_uint32_t, offsetof(struct sof_ipc4_pin_format, audio_fmt.ch_map)},
{SOF_TKN_CAVS_AUDIO_FORMAT_OUT_CH_CFG, SND_SOC_TPLG_TUPLE_TYPE_WORD,
tplg_token_get_uint32_t, offsetof(struct sof_ipc4_pin_format, audio_fmt.ch_cfg)},
{SOF_TKN_CAVS_AUDIO_FORMAT_OUT_INTERLEAVING_STYLE, SND_SOC_TPLG_TUPLE_TYPE_WORD,
tplg_token_get_uint32_t,
offsetof(struct sof_ipc4_pin_format, audio_fmt.interleaving_style)},
{SOF_TKN_CAVS_AUDIO_FORMAT_OUT_FMT_CFG, SND_SOC_TPLG_TUPLE_TYPE_WORD,
tplg_token_get_uint32_t, offsetof(struct sof_ipc4_pin_format, audio_fmt.fmt_cfg)},
{SOF_TKN_CAVS_AUDIO_FORMAT_OUTPUT_PIN_INDEX, SND_SOC_TPLG_TUPLE_TYPE_WORD,
tplg_token_get_uint32_t, offsetof(struct sof_ipc4_pin_format, pin_index)},
{SOF_TKN_CAVS_AUDIO_FORMAT_OBS, SND_SOC_TPLG_TUPLE_TYPE_WORD, tplg_token_get_uint32_t,
offsetof(struct sof_ipc4_pin_format, buffer_size)},
};
int tplg_parse_widget_audio_formats(struct tplg_context *ctx)
{
struct snd_soc_tplg_vendor_array *array = &ctx->widget->priv.array[0];
struct tplg_comp_info *comp_info = ctx->current_comp_info;
struct sof_ipc4_available_audio_format *available_fmts = &comp_info->available_fmt;
struct sof_ipc4_pin_format *pin_fmt;
struct sof_ipc4_audio_format *fmt;
int size = ctx->widget->priv.size;
int ret, i;
/* first parse the number of input and output pin formats */
ret = sof_parse_token_sets(available_fmts, ipc4_audio_fmt_num_tokens,
ARRAY_SIZE(ipc4_audio_fmt_num_tokens), array, size, 1, 0);
if (ret < 0) {
fprintf(stderr, "widget: %s: Failed to parse audio_fmt_num_tokens\n",
ctx->widget->name);
return ret;
}
tplg_debug("widget: %s: number of input formats: %d number of output formats: %d\n",
ctx->widget->name, available_fmts->num_input_formats,
available_fmts->num_output_formats);
/* allocated memory for the audio formats */
available_fmts->output_pin_fmts =
calloc(sizeof(struct sof_ipc4_pin_format) * available_fmts->num_output_formats, 1);
if (!available_fmts->output_pin_fmts)
return -ENOMEM;
available_fmts->input_pin_fmts =
calloc(sizeof(struct sof_ipc4_pin_format) * available_fmts->num_input_formats, 1);
if (!available_fmts->input_pin_fmts) {
free(available_fmts->output_pin_fmts);
return -ENOMEM;
}
/* now parse the pin audio formats */
array = &ctx->widget->priv.array[0];
ret = sof_parse_token_sets(available_fmts->input_pin_fmts, ipc4_in_audio_format_tokens,
ARRAY_SIZE(ipc4_in_audio_format_tokens), array, size,
available_fmts->num_input_formats,
sizeof(struct sof_ipc4_pin_format));
if (ret < 0) {
fprintf(stderr, "widget: %s: failed to parse ipc4_in_audio_format_tokens\n",
ctx->widget->name);
return ret;
}
array = &ctx->widget->priv.array[0];
ret = sof_parse_token_sets(available_fmts->output_pin_fmts, ipc4_out_audio_format_tokens,
ARRAY_SIZE(ipc4_out_audio_format_tokens), array, size,
available_fmts->num_output_formats,
sizeof(struct sof_ipc4_pin_format));
if (ret < 0) {
fprintf(stderr, "widget: %s: failed to parse ipc4_out_audio_format_tokens\n",
ctx->widget->name);
return ret;
}
/* print available audio formats */
pin_fmt = available_fmts->output_pin_fmts;
for (i = 0; i < available_fmts->num_output_formats; i++) {
fmt = &pin_fmt[i].audio_fmt;
tplg_debug("Output Pin index #%d: %uHz, %ubit (ch_map %#x ch_cfg %u interleaving_style %u fmt_cfg %#x) buffer size %d\n",
pin_fmt[i].pin_index, fmt->sampling_frequency, fmt->bit_depth, fmt->ch_map,
fmt->ch_cfg, fmt->interleaving_style, fmt->fmt_cfg,
pin_fmt[i].buffer_size);
}
pin_fmt = available_fmts->input_pin_fmts;
for (i = 0; i < available_fmts->num_input_formats; i++) {
fmt = &pin_fmt[i].audio_fmt;
tplg_debug("Input Pin index #%d: %uHz, %ubit (ch_map %#x ch_cfg %u interleaving_style %u fmt_cfg %#x) buffer size %d\n",
pin_fmt[i].pin_index, fmt->sampling_frequency, fmt->bit_depth,
fmt->ch_map, fmt->ch_cfg, fmt->interleaving_style, fmt->fmt_cfg,
pin_fmt[i].buffer_size);
}
return 0;
}