// SPDX-License-Identifier: BSD-3-Clause // // Copyright(c) 2019 Intel Corporation. All rights reserved. // // Author: Ranjani Sridharan /* Topology parser */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* load mixer dapm widget */ int tplg_create_mixer(struct tplg_context *ctx, struct sof_ipc_comp_mixer *mixer) { struct snd_soc_tplg_vendor_array *array = NULL; size_t total_array_size = 0, read_size; FILE *file = ctx->file; int size = ctx->widget->priv.size; int comp_id = ctx->comp_id; int ret; /* allocate memory for vendor tuple array */ array = (struct snd_soc_tplg_vendor_array *)malloc(size); if (!array) { fprintf(stderr, "error: mem alloc for src vendor array\n"); return -errno; } /* read vendor tokens */ while (total_array_size < size) { read_size = sizeof(struct snd_soc_tplg_vendor_array); ret = fread(array, read_size, 1, file); if (ret != 1) { free(MOVE_POINTER_BY_BYTES(array, -total_array_size)); return -EINVAL; } /* check for array size mismatch */ if (!is_valid_priv_size(total_array_size, size, array)) { fprintf(stderr, "error: load mixer array size mismatch\n"); free(MOVE_POINTER_BY_BYTES(array, -total_array_size)); return -EINVAL; } ret = tplg_read_array(array, file); if (ret) { fprintf(stderr, "error: read array fail\n"); free(MOVE_POINTER_BY_BYTES(array, -total_array_size)); return ret; } /* parse comp tokens */ ret = sof_parse_tokens(&mixer->config, comp_tokens, ARRAY_SIZE(comp_tokens), array, array->size); if (ret != 0) { fprintf(stderr, "error: parse src comp_tokens %d\n", size); free(MOVE_POINTER_BY_BYTES(array, -total_array_size)); return -EINVAL; } total_array_size += array->size; /* read next array */ array = MOVE_POINTER_BY_BYTES(array, array->size); } /* point to the start of array so it gets freed properly */ array = MOVE_POINTER_BY_BYTES(array, -total_array_size); /* configure src */ mixer->comp.hdr.cmd = SOF_IPC_GLB_TPLG_MSG | SOF_IPC_TPLG_COMP_NEW; mixer->comp.id = comp_id; mixer->comp.hdr.size = sizeof(struct sof_ipc_comp_src); mixer->comp.type = SOF_COMP_MIXER; mixer->comp.pipeline_id = ctx->pipeline_id; mixer->config.hdr.size = sizeof(struct sof_ipc_comp_config); free(array); return 0; } /* load mixer dapm widget */ int tplg_register_mixer(struct tplg_context *ctx) { struct sof_ipc_comp_mixer mixer = {0}; struct sof *sof = ctx->sof; FILE *file = ctx->file; int ret = 0; ret = tplg_create_mixer(ctx, &mixer); if (ret < 0) return ret; if (tplg_create_controls(ctx->widget->num_kcontrols, file) < 0) { fprintf(stderr, "error: loading controls\n"); return -EINVAL; } /* load mixer component */ register_comp(mixer.comp.type, NULL); if (ipc_comp_new(sof->ipc, ipc_to_comp_new(&mixer)) < 0) { fprintf(stderr, "error: new mixer comp\n"); return -EINVAL; } return ret; }