1 // SPDX-License-Identifier: BSD-3-Clause
2 //
3 // Copyright(c) 2020 Intel Corporation. All rights reserved.
4 //
5 // Author: Jaroslaw Stelter <jaroslaw.stelter@linux.intel.com>
6 
7 #include <adsp_stddef.h>
8 #include <module_initial_settings_concrete.h>
9 #include <logger.h>
10 
11 extern "C" {
12 int memcpy_s(void * dst, size_t maxlen, const void * src, size_t len);
13 } /* extern "C" */
14 
15 using namespace intel_adsp;
16 
17 namespace dsp_fw
18 {
19 
20 #pragma pack(4) /* this directive is useless when compiling for xtensa but it highlights */
21 		/* the packing requirement. */
22 struct CompoundCfg
23 {
24 	BaseModuleCfg cfg;
25 	BaseModuleCfgExt cfg_ext;
26 };
27 #pragma pack()
28 
29 
30 /*! \brief Initializes a new ModuleInitialSettingsConcrete instance given an */
31 /*   INIT_INSTANCE IPC message blob */
ModuleInitialSettingsConcrete(DwordArray const & cfg_ipc_msg)32 ModuleInitialSettingsConcrete::ModuleInitialSettingsConcrete(DwordArray const &cfg_ipc_msg) :
33 							     cfg_(NULL), cfg_ext_(NULL)
34 {
35 	const size_t ipc_msg_size =
36 		reinterpret_cast<DwordArray const&>(cfg_ipc_msg).size() * sizeof(uint32_t);
37 
38 	if (ipc_msg_size < sizeof(BaseModuleCfg)) {
39 		/* unexpected INIT_INSTANCE message size. Simply return as message
40 		 * is unparsable.
41 		 */
42 		return;
43 	}
44 
45 	if (ipc_msg_size > sizeof(CompoundCfg) -
46 		sizeof(InputPinFormat) - sizeof(OutputPinFormat)) {
47 
48 		/* INIT_INSTANCE message seems to be compound message        */
49 		/* It shall contain BaseModuleCfg + BaseModuleCfgExt +       */
50 		/* optionally some InputPinFormat[] + OutputPinFormat[] data */
51 		CompoundCfg const * unvalidated_compound_cfg = cfg_ipc_msg.dataAs<CompoundCfg>();
52 		const size_t computed_msg_size =
53 			sizeof(CompoundCfg) -
54 			/* CompoundCfg already contains one InputPinFormat and
55 			 * one InputPinFormat
56 			 */
57 			(sizeof(InputPinFormat) + sizeof(OutputPinFormat)) +
58 			unvalidated_compound_cfg->cfg_ext.nb_input_pins*sizeof(InputPinFormat) +
59 			unvalidated_compound_cfg->cfg_ext.nb_output_pins*sizeof(InputPinFormat);
60 
61 		/* check size consistency */
62 		if (ipc_msg_size != computed_msg_size) {
63 			/* unexpected INIT_INSTANCE message size. Simply return as message
64 			 * is unparsable.
65 			 */
66 			return;
67 		}
68 
69 		/* looks like a valid compound config message has been found */
70 		cfg_ = &unvalidated_compound_cfg->cfg;
71 		cfg_ext_ = &unvalidated_compound_cfg->cfg_ext;
72 	}
73 	else if (ipc_msg_size == sizeof(BaseModuleCfg)) {
74 		/* INIT_INSTANCE message seems to be the legacy one */
75 		cfg_ = cfg_ipc_msg.dataAs<BaseModuleCfg>();
76 	}
77 }
78 
DeduceBaseModuleCfgExt(size_t in_pins_count,size_t out_pins_count)79 void ModuleInitialSettingsConcrete::DeduceBaseModuleCfgExt(size_t in_pins_count,
80 							   size_t out_pins_count)
81 {
82 	if (!cfg_ext_) {
83 		/* BaseModuleCfgExt data was not part of the INIT_INSTANCE IPC message */
84 		/* We need to create it on-the-fly */
85 		tmp_cfg_ext_.tlv.nb_input_pins = in_pins_count;
86 		tmp_cfg_ext_.tlv.nb_output_pins = out_pins_count;
87 
88 		InputPinFormat* input_pins = tmp_cfg_ext_.tlv.input_pins;
89 		/* InputPinFormat data are all identically initialized based on audio format
90 		 * available in the BaseModuleCfg data.
91 		 */
92 		for (size_t i = 0 ; i < in_pins_count ; i++) {
93 			/*  Initialize all input pins with same audio format */
94 			input_pins[i].ibs = cfg_->ibs;
95 			input_pins[i].pin_index = i;
96 			memcpy_s(&input_pins[i].audio_fmt,
97 				 sizeof(input_pins[i].audio_fmt),
98 				 &cfg_->audio_fmt,
99 				 sizeof(AudioFormat));
100 		}
101 
102 		OutputPinFormat* output_pins =
103 				reinterpret_cast<OutputPinFormat*>(&input_pins[in_pins_count]);
104 		for (size_t i = 0 ; i < out_pins_count ; i++) {
105 			/*  Initialize all pins obs with same obs value */
106 			output_pins[i].obs = cfg_->obs;
107 			output_pins[i].pin_index = i;
108 			memcpy_s(&output_pins[i].audio_fmt,
109 				 sizeof(output_pins[i].audio_fmt),
110 				 &cfg_->audio_fmt,
111 				 sizeof(AudioFormat));
112 		}
113 
114 		/* a valid BaseModuleCfgExt has been created on-the-fly */
115 		cfg_ext_ = reinterpret_cast<BaseModuleCfgExt const*>(&tmp_cfg_ext_);
116 	}
117 }
118 
GetUntypedItem(ModuleInitialSettingsKey key,size_t & length)119 void const* ModuleInitialSettingsConcrete::GetUntypedItem(ModuleInitialSettingsKey key,
120 							  size_t &length)
121 {
122 	void const* array = NULL;
123 	length = 0;
124 
125 	switch(key)
126 	{
127 	case intel_adsp::LEGACY_STRUCT:
128 		length = 1;
129 		array = cfg_;
130 		break;
131 
132 	case intel_adsp::IN_PINS_FORMAT:
133 		length = cfg_ext_->nb_input_pins;
134 		array = &cfg_ext_->input_pins[0];
135 		break;
136 
137 	case intel_adsp::OUT_PINS_FORMAT:
138 		length = cfg_ext_->nb_output_pins;
139 		/* output_pins array follows the input_pins array in BaseModuleCfgExt
140 		 * struct layout
141 		 */
142 		array = reinterpret_cast<OutputPinFormat const*>
143 					(&cfg_ext_->input_pins[cfg_ext_->nb_input_pins]);
144 		break;
145 
146 	default:
147 		break;
148 	}
149 	return array;
150 }
151 
152 } /* namespace dsp_fw */
153