1c72fcc34Sopenharmony_ci// SPDX-License-Identifier: BSD-3-Clause 2c72fcc34Sopenharmony_ci// 3c72fcc34Sopenharmony_ci// Copyright(c) 2021 Intel Corporation. All rights reserved. 4c72fcc34Sopenharmony_ci// 5c72fcc34Sopenharmony_ci// Author: Jaska Uimonen <jaska.uimonen@linux.intel.com> 6c72fcc34Sopenharmony_ci 7c72fcc34Sopenharmony_ci#include "aconfig.h" 8c72fcc34Sopenharmony_ci#include <errno.h> 9c72fcc34Sopenharmony_ci#include <stdio.h> 10c72fcc34Sopenharmony_ci#include <stdlib.h> 11c72fcc34Sopenharmony_ci#include <string.h> 12c72fcc34Sopenharmony_ci#include <stdbool.h> 13c72fcc34Sopenharmony_ci#include <inttypes.h> 14c72fcc34Sopenharmony_ci#include <alsa/global.h> 15c72fcc34Sopenharmony_ci#include <alsa/input.h> 16c72fcc34Sopenharmony_ci#include <alsa/output.h> 17c72fcc34Sopenharmony_ci#include <alsa/conf.h> 18c72fcc34Sopenharmony_ci#include <alsa/error.h> 19c72fcc34Sopenharmony_ci#include "pre-process-external.h" 20c72fcc34Sopenharmony_ci#include "nhlt.h" 21c72fcc34Sopenharmony_ci#include "intel/intel-nhlt.h" 22c72fcc34Sopenharmony_ci#include "intel/dmic-nhlt.h" 23c72fcc34Sopenharmony_ci#include "intel/ssp-nhlt.h" 24c72fcc34Sopenharmony_ci 25c72fcc34Sopenharmony_ci#define MAX_ENDPOINT_COUNT 20 26c72fcc34Sopenharmony_ci#define ALSA_BYTE_CHARS 5 27c72fcc34Sopenharmony_ci#define SOF_ABI_CHARS 29 28c72fcc34Sopenharmony_ci#define SOF_MANIFEST_DATA_TYPE_NHLT 1 29c72fcc34Sopenharmony_ci 30c72fcc34Sopenharmony_cistruct sof_manifest_tlv { 31c72fcc34Sopenharmony_ci uint32_t type; 32c72fcc34Sopenharmony_ci uint32_t size; 33c72fcc34Sopenharmony_ci uint8_t data[]; 34c72fcc34Sopenharmony_ci} __attribute__((packed)); 35c72fcc34Sopenharmony_ci 36c72fcc34Sopenharmony_cistruct sof_manifest { 37c72fcc34Sopenharmony_ci uint16_t abi_major; 38c72fcc34Sopenharmony_ci uint16_t abi_minor; 39c72fcc34Sopenharmony_ci uint16_t abi_patch; 40c72fcc34Sopenharmony_ci uint16_t count; 41c72fcc34Sopenharmony_ci struct sof_manifest_tlv items[]; 42c72fcc34Sopenharmony_ci} __attribute__((packed)); 43c72fcc34Sopenharmony_ci 44c72fcc34Sopenharmony_ci#ifdef NHLT_DEBUG 45c72fcc34Sopenharmony_cistatic void debug_print_nhlt(struct nhlt *blob, struct endpoint_descriptor **eps) 46c72fcc34Sopenharmony_ci{ 47c72fcc34Sopenharmony_ci uint8_t *top_p = (uint8_t *)blob; 48c72fcc34Sopenharmony_ci struct endpoint_descriptor *ep; 49c72fcc34Sopenharmony_ci uint8_t *ep_p; 50c72fcc34Sopenharmony_ci int i, j, k, lines, remain; 51c72fcc34Sopenharmony_ci 52c72fcc34Sopenharmony_ci fprintf(stdout, "printing nhlt as bytes:\n"); 53c72fcc34Sopenharmony_ci 54c72fcc34Sopenharmony_ci lines = sizeof(struct nhlt) / 8; 55c72fcc34Sopenharmony_ci remain = sizeof(struct nhlt) % 8; 56c72fcc34Sopenharmony_ci for (i = 0; i < lines; i++) { 57c72fcc34Sopenharmony_ci for (j = 0; j < 8; j++) { 58c72fcc34Sopenharmony_ci fprintf(stdout, "0x%02x,", *top_p); 59c72fcc34Sopenharmony_ci top_p++; 60c72fcc34Sopenharmony_ci } 61c72fcc34Sopenharmony_ci fprintf(stdout, "\n"); 62c72fcc34Sopenharmony_ci } 63c72fcc34Sopenharmony_ci for (i = 0; i < remain; i++) { 64c72fcc34Sopenharmony_ci fprintf(stdout, "0x%02x,", *top_p); 65c72fcc34Sopenharmony_ci top_p++; 66c72fcc34Sopenharmony_ci } 67c72fcc34Sopenharmony_ci fprintf(stdout, "\n\n"); 68c72fcc34Sopenharmony_ci 69c72fcc34Sopenharmony_ci for (i = 0; i < blob->endpoint_count; i++) { 70c72fcc34Sopenharmony_ci ep = eps[i]; 71c72fcc34Sopenharmony_ci ep_p = (uint8_t *)ep; 72c72fcc34Sopenharmony_ci lines = ep->length / 8; 73c72fcc34Sopenharmony_ci remain = ep->length % 8; 74c72fcc34Sopenharmony_ci for (j = 0; j < lines; j++) { 75c72fcc34Sopenharmony_ci for (k = 0; k < 8; k++) { 76c72fcc34Sopenharmony_ci fprintf(stdout, "0x%02x,", *ep_p); 77c72fcc34Sopenharmony_ci ep_p++; 78c72fcc34Sopenharmony_ci } 79c72fcc34Sopenharmony_ci fprintf(stdout, "\n"); 80c72fcc34Sopenharmony_ci } 81c72fcc34Sopenharmony_ci for (j = 0; j < remain; j++) { 82c72fcc34Sopenharmony_ci fprintf(stdout, "0x%02x,", *ep_p); 83c72fcc34Sopenharmony_ci ep_p++; 84c72fcc34Sopenharmony_ci } 85c72fcc34Sopenharmony_ci fprintf(stdout, "\n"); 86c72fcc34Sopenharmony_ci } 87c72fcc34Sopenharmony_ci 88c72fcc34Sopenharmony_ci fprintf(stdout, "\n"); 89c72fcc34Sopenharmony_ci} 90c72fcc34Sopenharmony_ci#else 91c72fcc34Sopenharmony_cistatic void debug_print_nhlt(struct nhlt *blob ATTRIBUTE_UNUSED, 92c72fcc34Sopenharmony_ci struct endpoint_descriptor **eps ATTRIBUTE_UNUSED) {} 93c72fcc34Sopenharmony_ci#endif 94c72fcc34Sopenharmony_ci 95c72fcc34Sopenharmony_cistatic int print_as_hex_bytes(uint8_t *manifest_buffer, uint32_t manifest_size, 96c72fcc34Sopenharmony_ci uint8_t *nhlt_buffer, uint32_t nhlt_size, char **src) 97c72fcc34Sopenharmony_ci{ 98c72fcc34Sopenharmony_ci char *bytes_string_buffer; 99c72fcc34Sopenharmony_ci char *dst; 100c72fcc34Sopenharmony_ci unsigned int i; 101c72fcc34Sopenharmony_ci 102c72fcc34Sopenharmony_ci bytes_string_buffer = calloc((manifest_size + nhlt_size) * ALSA_BYTE_CHARS + 1, 103c72fcc34Sopenharmony_ci sizeof(uint8_t)); 104c72fcc34Sopenharmony_ci if (!bytes_string_buffer) 105c72fcc34Sopenharmony_ci return -ENOMEM; 106c72fcc34Sopenharmony_ci 107c72fcc34Sopenharmony_ci dst = bytes_string_buffer; 108c72fcc34Sopenharmony_ci for (i = 0; i < manifest_size; i++) { 109c72fcc34Sopenharmony_ci snprintf(dst, ALSA_BYTE_CHARS + 1, "0x%02x,", *manifest_buffer); 110c72fcc34Sopenharmony_ci dst += ALSA_BYTE_CHARS; 111c72fcc34Sopenharmony_ci manifest_buffer++; 112c72fcc34Sopenharmony_ci } 113c72fcc34Sopenharmony_ci 114c72fcc34Sopenharmony_ci for (i = 0; i < nhlt_size; i++) { 115c72fcc34Sopenharmony_ci snprintf(dst, ALSA_BYTE_CHARS + 1, "0x%02x,", *nhlt_buffer); 116c72fcc34Sopenharmony_ci dst += ALSA_BYTE_CHARS; 117c72fcc34Sopenharmony_ci nhlt_buffer++; 118c72fcc34Sopenharmony_ci } 119c72fcc34Sopenharmony_ci 120c72fcc34Sopenharmony_ci /* remove the last comma... */ 121c72fcc34Sopenharmony_ci dst--; 122c72fcc34Sopenharmony_ci *dst = '\0'; 123c72fcc34Sopenharmony_ci 124c72fcc34Sopenharmony_ci *src = bytes_string_buffer; 125c72fcc34Sopenharmony_ci 126c72fcc34Sopenharmony_ci return 0; 127c72fcc34Sopenharmony_ci} 128c72fcc34Sopenharmony_ci 129c72fcc34Sopenharmony_cistatic int merge_manifest_data(snd_config_t *cfg, uint8_t *manifest_buffer, uint32_t manifest_size, 130c72fcc34Sopenharmony_ci uint8_t *nhlt_buffer, uint32_t nhlt_size) 131c72fcc34Sopenharmony_ci{ 132c72fcc34Sopenharmony_ci const char *data_name = "SOF ABI"; 133c72fcc34Sopenharmony_ci snd_config_t *data_section; 134c72fcc34Sopenharmony_ci snd_config_t *manifest; 135c72fcc34Sopenharmony_ci snd_config_t *old_bytes; 136c72fcc34Sopenharmony_ci snd_config_t *new_bytes; 137c72fcc34Sopenharmony_ci char *src = NULL; 138c72fcc34Sopenharmony_ci int ret; 139c72fcc34Sopenharmony_ci 140c72fcc34Sopenharmony_ci /* merge manifest struct and nhlt bytes as new config into existing SectionData*/ 141c72fcc34Sopenharmony_ci ret = snd_config_search(cfg, "SectionData", &data_section); 142c72fcc34Sopenharmony_ci if (ret < 0) 143c72fcc34Sopenharmony_ci return ret; 144c72fcc34Sopenharmony_ci 145c72fcc34Sopenharmony_ci ret = snd_config_search(data_section, data_name, &manifest); 146c72fcc34Sopenharmony_ci if (ret < 0) 147c72fcc34Sopenharmony_ci return ret; 148c72fcc34Sopenharmony_ci 149c72fcc34Sopenharmony_ci ret = snd_config_search(manifest, "bytes", &old_bytes); 150c72fcc34Sopenharmony_ci if (ret < 0) 151c72fcc34Sopenharmony_ci return ret; 152c72fcc34Sopenharmony_ci 153c72fcc34Sopenharmony_ci ret = snd_config_make(&new_bytes, "bytes", SND_CONFIG_TYPE_STRING); 154c72fcc34Sopenharmony_ci if (ret < 0) 155c72fcc34Sopenharmony_ci goto err; 156c72fcc34Sopenharmony_ci 157c72fcc34Sopenharmony_ci ret = print_as_hex_bytes(manifest_buffer, manifest_size, nhlt_buffer, nhlt_size, &src); 158c72fcc34Sopenharmony_ci if (ret < 0) 159c72fcc34Sopenharmony_ci goto err; 160c72fcc34Sopenharmony_ci 161c72fcc34Sopenharmony_ci ret = snd_config_set_string(new_bytes, src); 162c72fcc34Sopenharmony_ci if (ret < 0) 163c72fcc34Sopenharmony_ci goto err; 164c72fcc34Sopenharmony_ci 165c72fcc34Sopenharmony_ci ret = snd_config_merge(old_bytes, new_bytes, true); 166c72fcc34Sopenharmony_ci if (ret < 0) 167c72fcc34Sopenharmony_ci goto err; 168c72fcc34Sopenharmony_ci 169c72fcc34Sopenharmony_ci free(src); 170c72fcc34Sopenharmony_ci 171c72fcc34Sopenharmony_ci return 0; 172c72fcc34Sopenharmony_cierr: 173c72fcc34Sopenharmony_ci if (new_bytes) 174c72fcc34Sopenharmony_ci snd_config_delete(new_bytes); 175c72fcc34Sopenharmony_ci if (src) 176c72fcc34Sopenharmony_ci free(src); 177c72fcc34Sopenharmony_ci 178c72fcc34Sopenharmony_ci return ret; 179c72fcc34Sopenharmony_ci} 180c72fcc34Sopenharmony_ci 181c72fcc34Sopenharmony_cistatic void save_nhlt_binary(struct nhlt *blob, struct endpoint_descriptor **eps, snd_config_t *cfg) 182c72fcc34Sopenharmony_ci{ 183c72fcc34Sopenharmony_ci const char *bin_file = NULL; 184c72fcc34Sopenharmony_ci snd_config_t *defines; 185c72fcc34Sopenharmony_ci FILE *fp; 186c72fcc34Sopenharmony_ci int ret; 187c72fcc34Sopenharmony_ci int i; 188c72fcc34Sopenharmony_ci 189c72fcc34Sopenharmony_ci ret = snd_config_search(cfg, "Define.NHLT_BIN", &defines); 190c72fcc34Sopenharmony_ci if (ret < 0) 191c72fcc34Sopenharmony_ci return; 192c72fcc34Sopenharmony_ci 193c72fcc34Sopenharmony_ci if (snd_config_get_string(defines, &bin_file) < 0) 194c72fcc34Sopenharmony_ci return; 195c72fcc34Sopenharmony_ci 196c72fcc34Sopenharmony_ci fp = fopen(bin_file, "wb"); 197c72fcc34Sopenharmony_ci if (fp == NULL) { 198c72fcc34Sopenharmony_ci fprintf(stderr, "can't open nhlt binary output file %s\n", bin_file); 199c72fcc34Sopenharmony_ci return; 200c72fcc34Sopenharmony_ci } 201c72fcc34Sopenharmony_ci 202c72fcc34Sopenharmony_ci fprintf(stdout, "saving nhlt as binary in %s\n", bin_file); 203c72fcc34Sopenharmony_ci 204c72fcc34Sopenharmony_ci fwrite(blob, 1, sizeof(struct nhlt), fp); 205c72fcc34Sopenharmony_ci 206c72fcc34Sopenharmony_ci for (i = 0; i < blob->endpoint_count; i++) 207c72fcc34Sopenharmony_ci fwrite(eps[i], eps[i]->length, sizeof(uint8_t), fp); 208c72fcc34Sopenharmony_ci 209c72fcc34Sopenharmony_ci fclose(fp); 210c72fcc34Sopenharmony_ci} 211c72fcc34Sopenharmony_ci 212c72fcc34Sopenharmony_cistatic int manifest_create(snd_config_t *input, uint8_t **manifest_buffer, uint32_t *size, uint32_t nhlt_size) 213c72fcc34Sopenharmony_ci{ 214c72fcc34Sopenharmony_ci struct sof_manifest_tlv manifest_tlv; 215c72fcc34Sopenharmony_ci struct sof_manifest manifest; 216c72fcc34Sopenharmony_ci snd_config_t *data_section; 217c72fcc34Sopenharmony_ci snd_config_t *data; 218c72fcc34Sopenharmony_ci snd_config_t *old_bytes; 219c72fcc34Sopenharmony_ci uint32_t manifest_size; 220c72fcc34Sopenharmony_ci uint8_t *byte_buffer; 221c72fcc34Sopenharmony_ci const char *abi; 222c72fcc34Sopenharmony_ci uint8_t *top_p; 223c72fcc34Sopenharmony_ci uint8_t *dst; 224c72fcc34Sopenharmony_ci int ret; 225c72fcc34Sopenharmony_ci unsigned int i; 226c72fcc34Sopenharmony_ci 227c72fcc34Sopenharmony_ci ret = snd_config_search(input, "SectionData", &data_section); 228c72fcc34Sopenharmony_ci if (ret < 0) 229c72fcc34Sopenharmony_ci return ret; 230c72fcc34Sopenharmony_ci 231c72fcc34Sopenharmony_ci ret = snd_config_search(data_section, "SOF ABI", &data); 232c72fcc34Sopenharmony_ci if (ret < 0) 233c72fcc34Sopenharmony_ci return ret; 234c72fcc34Sopenharmony_ci 235c72fcc34Sopenharmony_ci ret = snd_config_search(data, "bytes", &old_bytes); 236c72fcc34Sopenharmony_ci if (ret < 0) 237c72fcc34Sopenharmony_ci return ret; 238c72fcc34Sopenharmony_ci 239c72fcc34Sopenharmony_ci ret = snd_config_get_string(old_bytes, &abi); 240c72fcc34Sopenharmony_ci if (ret < 0) 241c72fcc34Sopenharmony_ci return ret; 242c72fcc34Sopenharmony_ci 243c72fcc34Sopenharmony_ci /* we have something funny in abi string */ 244c72fcc34Sopenharmony_ci if (strlen(abi) != SOF_ABI_CHARS) 245c72fcc34Sopenharmony_ci return -EINVAL; 246c72fcc34Sopenharmony_ci 247c72fcc34Sopenharmony_ci manifest.count = 1; 248c72fcc34Sopenharmony_ci manifest_tlv.type = SOF_MANIFEST_DATA_TYPE_NHLT; 249c72fcc34Sopenharmony_ci manifest_tlv.size = nhlt_size; 250c72fcc34Sopenharmony_ci 251c72fcc34Sopenharmony_ci manifest_size = sizeof(struct sof_manifest) + sizeof(struct sof_manifest_tlv); 252c72fcc34Sopenharmony_ci byte_buffer = calloc(manifest_size, sizeof(uint8_t)); 253c72fcc34Sopenharmony_ci if (!byte_buffer) 254c72fcc34Sopenharmony_ci return -ENOMEM; 255c72fcc34Sopenharmony_ci 256c72fcc34Sopenharmony_ci *size = manifest_size; 257c72fcc34Sopenharmony_ci 258c72fcc34Sopenharmony_ci dst = byte_buffer; 259c72fcc34Sopenharmony_ci 260c72fcc34Sopenharmony_ci /* copy the ABI version bytes */ 261c72fcc34Sopenharmony_ci for (i = 0; i < 6; i++) 262c72fcc34Sopenharmony_ci sscanf(&abi[i * ALSA_BYTE_CHARS], "%" SCNx8, dst++); 263c72fcc34Sopenharmony_ci 264c72fcc34Sopenharmony_ci /* set the count */ 265c72fcc34Sopenharmony_ci *dst++ = manifest.count; 266c72fcc34Sopenharmony_ci *dst++ = manifest.count >> 2; 267c72fcc34Sopenharmony_ci 268c72fcc34Sopenharmony_ci top_p = (uint8_t *)&manifest_tlv; 269c72fcc34Sopenharmony_ci for (i = 0; i < sizeof(struct sof_manifest_tlv); i++) 270c72fcc34Sopenharmony_ci *dst++ = *top_p++; 271c72fcc34Sopenharmony_ci 272c72fcc34Sopenharmony_ci *manifest_buffer = byte_buffer; 273c72fcc34Sopenharmony_ci 274c72fcc34Sopenharmony_ci return 0; 275c72fcc34Sopenharmony_ci} 276c72fcc34Sopenharmony_ci 277c72fcc34Sopenharmony_cistatic int nhlt_get_flat_buffer(struct nhlt *blob, struct endpoint_descriptor **eps, 278c72fcc34Sopenharmony_ci uint32_t eps_count, uint32_t *size, uint8_t **nhlt_buffer) 279c72fcc34Sopenharmony_ci{ 280c72fcc34Sopenharmony_ci uint8_t *top_p = (uint8_t *)blob; 281c72fcc34Sopenharmony_ci struct endpoint_descriptor *ep; 282c72fcc34Sopenharmony_ci uint8_t *byte_buffer; 283c72fcc34Sopenharmony_ci uint32_t nhlt_size; 284c72fcc34Sopenharmony_ci uint8_t *ep_p; 285c72fcc34Sopenharmony_ci uint8_t *dst; 286c72fcc34Sopenharmony_ci unsigned int i, j; 287c72fcc34Sopenharmony_ci 288c72fcc34Sopenharmony_ci /* get blob total size */ 289c72fcc34Sopenharmony_ci nhlt_size = sizeof(struct nhlt); 290c72fcc34Sopenharmony_ci for (i = 0; i < eps_count; i++) { 291c72fcc34Sopenharmony_ci if (eps[i]) 292c72fcc34Sopenharmony_ci nhlt_size += eps[i]->length; 293c72fcc34Sopenharmony_ci } 294c72fcc34Sopenharmony_ci 295c72fcc34Sopenharmony_ci *size = nhlt_size; 296c72fcc34Sopenharmony_ci 297c72fcc34Sopenharmony_ci byte_buffer = calloc(nhlt_size, sizeof(uint8_t)); 298c72fcc34Sopenharmony_ci if (!byte_buffer) 299c72fcc34Sopenharmony_ci return -ENOMEM; 300c72fcc34Sopenharmony_ci 301c72fcc34Sopenharmony_ci dst = byte_buffer; 302c72fcc34Sopenharmony_ci for (i = 0; i < sizeof(struct nhlt); i++) 303c72fcc34Sopenharmony_ci *dst++ = *top_p++; 304c72fcc34Sopenharmony_ci 305c72fcc34Sopenharmony_ci for (i = 0; i < blob->endpoint_count; i++) { 306c72fcc34Sopenharmony_ci ep = eps[i]; 307c72fcc34Sopenharmony_ci ep_p = (uint8_t *)ep; 308c72fcc34Sopenharmony_ci for (j = 0; j < ep->length; j++) 309c72fcc34Sopenharmony_ci *dst++ = *ep_p++; 310c72fcc34Sopenharmony_ci } 311c72fcc34Sopenharmony_ci 312c72fcc34Sopenharmony_ci *nhlt_buffer = byte_buffer; 313c72fcc34Sopenharmony_ci 314c72fcc34Sopenharmony_ci return 0; 315c72fcc34Sopenharmony_ci} 316c72fcc34Sopenharmony_ci 317c72fcc34Sopenharmony_ci/* called at the end of topology pre-processing, create flat buffer from variable size nhlt */ 318c72fcc34Sopenharmony_cistatic int nhlt_create(struct intel_nhlt_params *nhlt, snd_config_t *input, 319c72fcc34Sopenharmony_ci snd_config_t *output ATTRIBUTE_UNUSED, 320c72fcc34Sopenharmony_ci uint8_t **nhlt_buffer, uint32_t *nhlt_size) 321c72fcc34Sopenharmony_ci{ 322c72fcc34Sopenharmony_ci struct endpoint_descriptor *eps[MAX_ENDPOINT_COUNT]; 323c72fcc34Sopenharmony_ci int eps_count = 0; 324c72fcc34Sopenharmony_ci struct nhlt blob; 325c72fcc34Sopenharmony_ci uint32_t size; 326c72fcc34Sopenharmony_ci uint8_t dir; 327c72fcc34Sopenharmony_ci int ret; 328c72fcc34Sopenharmony_ci int i; 329c72fcc34Sopenharmony_ci 330c72fcc34Sopenharmony_ci for (i = 0; i < MAX_ENDPOINT_COUNT; i++) 331c72fcc34Sopenharmony_ci eps[i] = NULL; 332c72fcc34Sopenharmony_ci 333c72fcc34Sopenharmony_ci /* we always have only 0 or 1 dmic ep */ 334c72fcc34Sopenharmony_ci for (i = 0; i < nhlt_dmic_get_ep_count(nhlt); i++) { 335c72fcc34Sopenharmony_ci ret = nhlt_dmic_get_ep(nhlt, &eps[eps_count], i); 336c72fcc34Sopenharmony_ci if (ret < 0) 337c72fcc34Sopenharmony_ci return -EINVAL; 338c72fcc34Sopenharmony_ci eps_count++; 339c72fcc34Sopenharmony_ci } 340c72fcc34Sopenharmony_ci 341c72fcc34Sopenharmony_ci /* we can have 0 to several ssp eps */ 342c72fcc34Sopenharmony_ci for (i = 0; i < nhlt_ssp_get_ep_count(nhlt); i++) { 343c72fcc34Sopenharmony_ci nhlt_ssp_get_dir(nhlt, i, &dir); 344c72fcc34Sopenharmony_ci /* duplicate endpoint for duplex dai */ 345c72fcc34Sopenharmony_ci if (dir > NHLT_ENDPOINT_DIRECTION_FEEDBACK_FOR_RENDER) { 346c72fcc34Sopenharmony_ci ret = nhlt_ssp_get_ep(nhlt, &eps[eps_count], i, 347c72fcc34Sopenharmony_ci NHLT_ENDPOINT_DIRECTION_RENDER); 348c72fcc34Sopenharmony_ci if (ret < 0) 349c72fcc34Sopenharmony_ci goto err; 350c72fcc34Sopenharmony_ci eps_count++; 351c72fcc34Sopenharmony_ci ret = nhlt_ssp_get_ep(nhlt, &eps[eps_count], i, 352c72fcc34Sopenharmony_ci NHLT_ENDPOINT_DIRECTION_CAPTURE); 353c72fcc34Sopenharmony_ci } else { 354c72fcc34Sopenharmony_ci ret = nhlt_ssp_get_ep(nhlt, &eps[eps_count], i, dir); 355c72fcc34Sopenharmony_ci } 356c72fcc34Sopenharmony_ci if (ret < 0) 357c72fcc34Sopenharmony_ci goto err; 358c72fcc34Sopenharmony_ci eps_count++; 359c72fcc34Sopenharmony_ci } 360c72fcc34Sopenharmony_ci 361c72fcc34Sopenharmony_ci /* we don't have endpoints */ 362c72fcc34Sopenharmony_ci if (!eps_count) 363c72fcc34Sopenharmony_ci return 0; 364c72fcc34Sopenharmony_ci 365c72fcc34Sopenharmony_ci uint8_t sig[4] = {'N', 'H', 'L', 'T'}; 366c72fcc34Sopenharmony_ci blob.efi_acpi.signature = *((uint32_t *)sig); 367c72fcc34Sopenharmony_ci blob.efi_acpi.length = 0; 368c72fcc34Sopenharmony_ci blob.efi_acpi.revision = 0; 369c72fcc34Sopenharmony_ci blob.efi_acpi.checksum = 0; 370c72fcc34Sopenharmony_ci for (i = 0; i < 6; i++) 371c72fcc34Sopenharmony_ci blob.efi_acpi.oem_id[i] = 0; 372c72fcc34Sopenharmony_ci blob.efi_acpi.oem_table_id = 0; 373c72fcc34Sopenharmony_ci blob.efi_acpi.oem_revision = 0; 374c72fcc34Sopenharmony_ci blob.efi_acpi.creator_id = 0; 375c72fcc34Sopenharmony_ci blob.efi_acpi.creator_revision = 0; 376c72fcc34Sopenharmony_ci 377c72fcc34Sopenharmony_ci blob.endpoint_count = eps_count; 378c72fcc34Sopenharmony_ci 379c72fcc34Sopenharmony_ci /* get blob total size */ 380c72fcc34Sopenharmony_ci size = sizeof(struct nhlt); 381c72fcc34Sopenharmony_ci for (i = 0; i < eps_count; i++) { 382c72fcc34Sopenharmony_ci if (eps[i]) 383c72fcc34Sopenharmony_ci size += eps[i]->length; 384c72fcc34Sopenharmony_ci } 385c72fcc34Sopenharmony_ci 386c72fcc34Sopenharmony_ci /* add the total length to top level struct */ 387c72fcc34Sopenharmony_ci blob.efi_acpi.length = size; 388c72fcc34Sopenharmony_ci 389c72fcc34Sopenharmony_ci debug_print_nhlt(&blob, eps); 390c72fcc34Sopenharmony_ci 391c72fcc34Sopenharmony_ci save_nhlt_binary(&blob, eps, input); 392c72fcc34Sopenharmony_ci 393c72fcc34Sopenharmony_ci ret = nhlt_get_flat_buffer(&blob, eps, eps_count, nhlt_size, nhlt_buffer); 394c72fcc34Sopenharmony_ci 395c72fcc34Sopenharmony_cierr: 396c72fcc34Sopenharmony_ci /* remove all enpoints */ 397c72fcc34Sopenharmony_ci for (i = 0; i < eps_count; i++) 398c72fcc34Sopenharmony_ci free(eps[i]); 399c72fcc34Sopenharmony_ci 400c72fcc34Sopenharmony_ci return ret; 401c72fcc34Sopenharmony_ci} 402c72fcc34Sopenharmony_ci 403c72fcc34Sopenharmony_cistatic int do_nhlt(struct intel_nhlt_params *nhlt, snd_config_t *input, snd_config_t *output) 404c72fcc34Sopenharmony_ci{ 405c72fcc34Sopenharmony_ci uint8_t *manifest_buffer = NULL; 406c72fcc34Sopenharmony_ci uint8_t *nhlt_buffer = NULL; 407c72fcc34Sopenharmony_ci uint32_t manifest_size; 408c72fcc34Sopenharmony_ci uint32_t nhlt_size = 0; 409c72fcc34Sopenharmony_ci int ret = 0; 410c72fcc34Sopenharmony_ci 411c72fcc34Sopenharmony_ci ret = nhlt_create(nhlt, input, output, &nhlt_buffer, &nhlt_size); 412c72fcc34Sopenharmony_ci if (ret) { 413c72fcc34Sopenharmony_ci fprintf(stderr, "can't create nhlt blob, err %d\n", ret); 414c72fcc34Sopenharmony_ci return ret; 415c72fcc34Sopenharmony_ci } 416c72fcc34Sopenharmony_ci 417c72fcc34Sopenharmony_ci ret = manifest_create(output, &manifest_buffer, &manifest_size, nhlt_size); 418c72fcc34Sopenharmony_ci if (ret) { 419c72fcc34Sopenharmony_ci fprintf(stderr, "can't re-create manifest, err %d\n", ret); 420c72fcc34Sopenharmony_ci goto err; 421c72fcc34Sopenharmony_ci } 422c72fcc34Sopenharmony_ci 423c72fcc34Sopenharmony_ci ret = merge_manifest_data(output, manifest_buffer, manifest_size, nhlt_buffer, nhlt_size); 424c72fcc34Sopenharmony_ci if (ret) 425c72fcc34Sopenharmony_ci fprintf(stderr, "can't merge manifest data, err %d\n", ret); 426c72fcc34Sopenharmony_ci 427c72fcc34Sopenharmony_cierr: 428c72fcc34Sopenharmony_ci if (manifest_buffer) 429c72fcc34Sopenharmony_ci free(manifest_buffer); 430c72fcc34Sopenharmony_ci if (nhlt_buffer) 431c72fcc34Sopenharmony_ci free(nhlt_buffer); 432c72fcc34Sopenharmony_ci 433c72fcc34Sopenharmony_ci return ret; 434c72fcc34Sopenharmony_ci} 435c72fcc34Sopenharmony_ci 436c72fcc34Sopenharmony_ciSND_TOPOLOGY_PLUGIN_DEFINE_FUNC(nhlt) 437c72fcc34Sopenharmony_ci{ 438c72fcc34Sopenharmony_ci snd_config_iterator_t i, i2, next, next2; 439c72fcc34Sopenharmony_ci struct intel_nhlt_params nhlt; 440c72fcc34Sopenharmony_ci snd_config_t *n, *n2; 441c72fcc34Sopenharmony_ci snd_config_t *items; 442c72fcc34Sopenharmony_ci const char *id, *id2; 443c72fcc34Sopenharmony_ci int ret; 444c72fcc34Sopenharmony_ci 445c72fcc34Sopenharmony_ci /* initialize the internal structs */ 446c72fcc34Sopenharmony_ci ret = nhlt_ssp_init_params(&nhlt); 447c72fcc34Sopenharmony_ci if (ret < 0) 448c72fcc34Sopenharmony_ci return ret; 449c72fcc34Sopenharmony_ci 450c72fcc34Sopenharmony_ci ret = nhlt_dmic_init_params(&nhlt); 451c72fcc34Sopenharmony_ci if (ret < 0) 452c72fcc34Sopenharmony_ci return ret; 453c72fcc34Sopenharmony_ci 454c72fcc34Sopenharmony_ci /* find DAIs and set internal parameters */ 455c72fcc34Sopenharmony_ci ret = snd_config_search(input, "Object.Dai", &items); 456c72fcc34Sopenharmony_ci if (ret < 0) 457c72fcc34Sopenharmony_ci return ret; 458c72fcc34Sopenharmony_ci 459c72fcc34Sopenharmony_ci snd_config_for_each(i, next, items) { 460c72fcc34Sopenharmony_ci n = snd_config_iterator_entry(i); 461c72fcc34Sopenharmony_ci 462c72fcc34Sopenharmony_ci if (snd_config_get_id(n, &id) < 0) 463c72fcc34Sopenharmony_ci continue; 464c72fcc34Sopenharmony_ci 465c72fcc34Sopenharmony_ci snd_config_for_each(i2, next2, n) { 466c72fcc34Sopenharmony_ci n2 = snd_config_iterator_entry(i2); 467c72fcc34Sopenharmony_ci 468c72fcc34Sopenharmony_ci if (snd_config_get_id(n2, &id2) < 0) 469c72fcc34Sopenharmony_ci continue; 470c72fcc34Sopenharmony_ci 471c72fcc34Sopenharmony_ci /* set dai parameters here */ 472c72fcc34Sopenharmony_ci if (!strncmp(id, "DMIC", 4)) { 473c72fcc34Sopenharmony_ci ret = nhlt_dmic_set_params(&nhlt, n2, input); 474c72fcc34Sopenharmony_ci if (ret < 0) 475c72fcc34Sopenharmony_ci return ret; 476c72fcc34Sopenharmony_ci } 477c72fcc34Sopenharmony_ci 478c72fcc34Sopenharmony_ci if (!strncmp(id, "SSP", 3)) { 479c72fcc34Sopenharmony_ci ret = nhlt_ssp_set_params(&nhlt, n2, input); 480c72fcc34Sopenharmony_ci if (ret < 0) 481c72fcc34Sopenharmony_ci return ret; 482c72fcc34Sopenharmony_ci } 483c72fcc34Sopenharmony_ci } 484c72fcc34Sopenharmony_ci } 485c72fcc34Sopenharmony_ci 486c72fcc34Sopenharmony_ci /* create the nhlt blob from internal structs */ 487c72fcc34Sopenharmony_ci ret = do_nhlt(&nhlt, input, output); 488c72fcc34Sopenharmony_ci if (ret) 489c72fcc34Sopenharmony_ci fprintf(stderr, "error in nhlt processing\n"); 490c72fcc34Sopenharmony_ci 491c72fcc34Sopenharmony_ci free(nhlt.ssp_params); 492c72fcc34Sopenharmony_ci free(nhlt.dmic_params); 493c72fcc34Sopenharmony_ci 494c72fcc34Sopenharmony_ci return 0; 495c72fcc34Sopenharmony_ci} 496