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