1 // SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) 2 // 3 // This file is provided under a dual BSD/GPLv2 license. When using or 4 // redistributing this file, you may do so under either license. 5 // 6 // Copyright(c) 2021 Intel Corporation. All rights reserved. 7 // 8 // 9 10 #include <uapi/sound/sof/tokens.h> 11 #include <sound/pcm_params.h> 12 #include "sof-priv.h" 13 #include "sof-audio.h" 14 #include "ipc3-priv.h" 15 #include "ops.h" 16 17 /* Full volume for default values */ 18 #define VOL_ZERO_DB BIT(VOLUME_FWL) 19 20 /* size of tplg ABI in bytes */ 21 #define SOF_IPC3_TPLG_ABI_SIZE 3 22 23 /* Base of SOF_DAI_INTEL_ALH, this should be aligned with SOC_SDW_INTEL_BIDIR_PDI_BASE */ 24 #define INTEL_ALH_DAI_INDEX_BASE 2 25 26 struct sof_widget_data { 27 int ctrl_type; 28 int ipc_cmd; 29 void *pdata; 30 size_t pdata_size; 31 struct snd_sof_control *control; 32 }; 33 34 struct sof_process_types { 35 const char *name; 36 enum sof_ipc_process_type type; 37 enum sof_comp_type comp_type; 38 }; 39 40 static const struct sof_process_types sof_process[] = { 41 {"EQFIR", SOF_PROCESS_EQFIR, SOF_COMP_EQ_FIR}, 42 {"EQIIR", SOF_PROCESS_EQIIR, SOF_COMP_EQ_IIR}, 43 {"KEYWORD_DETECT", SOF_PROCESS_KEYWORD_DETECT, SOF_COMP_KEYWORD_DETECT}, 44 {"KPB", SOF_PROCESS_KPB, SOF_COMP_KPB}, 45 {"CHAN_SELECTOR", SOF_PROCESS_CHAN_SELECTOR, SOF_COMP_SELECTOR}, 46 {"MUX", SOF_PROCESS_MUX, SOF_COMP_MUX}, 47 {"DEMUX", SOF_PROCESS_DEMUX, SOF_COMP_DEMUX}, 48 {"DCBLOCK", SOF_PROCESS_DCBLOCK, SOF_COMP_DCBLOCK}, 49 {"SMART_AMP", SOF_PROCESS_SMART_AMP, SOF_COMP_SMART_AMP}, 50 }; 51 52 static enum sof_ipc_process_type find_process(const char *name) 53 { 54 int i; 55 56 for (i = 0; i < ARRAY_SIZE(sof_process); i++) { 57 if (strcmp(name, sof_process[i].name) == 0) 58 return sof_process[i].type; 59 } 60 61 return SOF_PROCESS_NONE; 62 } 63 64 static int get_token_process_type(void *elem, void *object, u32 offset) 65 { 66 u32 *val = (u32 *)((u8 *)object + offset); 67 68 *val = find_process((const char *)elem); 69 return 0; 70 } 71 72 /* Buffers */ 73 static const struct sof_topology_token buffer_tokens[] = { 74 {SOF_TKN_BUF_SIZE, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, 75 offsetof(struct sof_ipc_buffer, size)}, 76 {SOF_TKN_BUF_CAPS, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, 77 offsetof(struct sof_ipc_buffer, caps)}, 78 }; 79 80 /* DAI */ 81 static const struct sof_topology_token dai_tokens[] = { 82 {SOF_TKN_DAI_TYPE, SND_SOC_TPLG_TUPLE_TYPE_STRING, get_token_dai_type, 83 offsetof(struct sof_ipc_comp_dai, type)}, 84 {SOF_TKN_DAI_INDEX, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, 85 offsetof(struct sof_ipc_comp_dai, dai_index)}, 86 {SOF_TKN_DAI_DIRECTION, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, 87 offsetof(struct sof_ipc_comp_dai, direction)}, 88 }; 89 90 /* BE DAI link */ 91 static const struct sof_topology_token dai_link_tokens[] = { 92 {SOF_TKN_DAI_TYPE, SND_SOC_TPLG_TUPLE_TYPE_STRING, get_token_dai_type, 93 offsetof(struct sof_ipc_dai_config, type)}, 94 {SOF_TKN_DAI_INDEX, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, 95 offsetof(struct sof_ipc_dai_config, dai_index)}, 96 }; 97 98 /* scheduling */ 99 static const struct sof_topology_token sched_tokens[] = { 100 {SOF_TKN_SCHED_PERIOD, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, 101 offsetof(struct sof_ipc_pipe_new, period)}, 102 {SOF_TKN_SCHED_PRIORITY, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, 103 offsetof(struct sof_ipc_pipe_new, priority)}, 104 {SOF_TKN_SCHED_MIPS, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, 105 offsetof(struct sof_ipc_pipe_new, period_mips)}, 106 {SOF_TKN_SCHED_CORE, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, 107 offsetof(struct sof_ipc_pipe_new, core)}, 108 {SOF_TKN_SCHED_FRAMES, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, 109 offsetof(struct sof_ipc_pipe_new, frames_per_sched)}, 110 {SOF_TKN_SCHED_TIME_DOMAIN, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, 111 offsetof(struct sof_ipc_pipe_new, time_domain)}, 112 }; 113 114 static const struct sof_topology_token pipeline_tokens[] = { 115 {SOF_TKN_SCHED_DYNAMIC_PIPELINE, SND_SOC_TPLG_TUPLE_TYPE_BOOL, get_token_u16, 116 offsetof(struct snd_sof_widget, dynamic_pipeline_widget)}, 117 118 }; 119 120 /* volume */ 121 static const struct sof_topology_token volume_tokens[] = { 122 {SOF_TKN_VOLUME_RAMP_STEP_TYPE, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, 123 offsetof(struct sof_ipc_comp_volume, ramp)}, 124 {SOF_TKN_VOLUME_RAMP_STEP_MS, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, 125 offsetof(struct sof_ipc_comp_volume, initial_ramp)}, 126 }; 127 128 /* SRC */ 129 static const struct sof_topology_token src_tokens[] = { 130 {SOF_TKN_SRC_RATE_IN, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, 131 offsetof(struct sof_ipc_comp_src, source_rate)}, 132 {SOF_TKN_SRC_RATE_OUT, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, 133 offsetof(struct sof_ipc_comp_src, sink_rate)}, 134 }; 135 136 /* ASRC */ 137 static const struct sof_topology_token asrc_tokens[] = { 138 {SOF_TKN_ASRC_RATE_IN, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, 139 offsetof(struct sof_ipc_comp_asrc, source_rate)}, 140 {SOF_TKN_ASRC_RATE_OUT, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, 141 offsetof(struct sof_ipc_comp_asrc, sink_rate)}, 142 {SOF_TKN_ASRC_ASYNCHRONOUS_MODE, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, 143 offsetof(struct sof_ipc_comp_asrc, asynchronous_mode)}, 144 {SOF_TKN_ASRC_OPERATION_MODE, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, 145 offsetof(struct sof_ipc_comp_asrc, operation_mode)}, 146 }; 147 148 /* EFFECT */ 149 static const struct sof_topology_token process_tokens[] = { 150 {SOF_TKN_PROCESS_TYPE, SND_SOC_TPLG_TUPLE_TYPE_STRING, get_token_process_type, 151 offsetof(struct sof_ipc_comp_process, type)}, 152 }; 153 154 /* PCM */ 155 static const struct sof_topology_token pcm_tokens[] = { 156 {SOF_TKN_PCM_DMAC_CONFIG, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, 157 offsetof(struct sof_ipc_comp_host, dmac_config)}, 158 }; 159 160 /* Generic components */ 161 static const struct sof_topology_token comp_tokens[] = { 162 {SOF_TKN_COMP_PERIOD_SINK_COUNT, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, 163 offsetof(struct sof_ipc_comp_config, periods_sink)}, 164 {SOF_TKN_COMP_PERIOD_SOURCE_COUNT, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, 165 offsetof(struct sof_ipc_comp_config, periods_source)}, 166 {SOF_TKN_COMP_FORMAT, 167 SND_SOC_TPLG_TUPLE_TYPE_STRING, get_token_comp_format, 168 offsetof(struct sof_ipc_comp_config, frame_fmt)}, 169 }; 170 171 /* SSP */ 172 static const struct sof_topology_token ssp_tokens[] = { 173 {SOF_TKN_INTEL_SSP_CLKS_CONTROL, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, 174 offsetof(struct sof_ipc_dai_ssp_params, clks_control)}, 175 {SOF_TKN_INTEL_SSP_MCLK_ID, SND_SOC_TPLG_TUPLE_TYPE_SHORT, get_token_u16, 176 offsetof(struct sof_ipc_dai_ssp_params, mclk_id)}, 177 {SOF_TKN_INTEL_SSP_SAMPLE_BITS, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, 178 offsetof(struct sof_ipc_dai_ssp_params, sample_valid_bits)}, 179 {SOF_TKN_INTEL_SSP_FRAME_PULSE_WIDTH, SND_SOC_TPLG_TUPLE_TYPE_SHORT, get_token_u16, 180 offsetof(struct sof_ipc_dai_ssp_params, frame_pulse_width)}, 181 {SOF_TKN_INTEL_SSP_QUIRKS, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, 182 offsetof(struct sof_ipc_dai_ssp_params, quirks)}, 183 {SOF_TKN_INTEL_SSP_TDM_PADDING_PER_SLOT, SND_SOC_TPLG_TUPLE_TYPE_BOOL, get_token_u16, 184 offsetof(struct sof_ipc_dai_ssp_params, tdm_per_slot_padding_flag)}, 185 {SOF_TKN_INTEL_SSP_BCLK_DELAY, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, 186 offsetof(struct sof_ipc_dai_ssp_params, bclk_delay)}, 187 }; 188 189 /* ALH */ 190 static const struct sof_topology_token alh_tokens[] = { 191 {SOF_TKN_INTEL_ALH_RATE, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, 192 offsetof(struct sof_ipc_dai_alh_params, rate)}, 193 {SOF_TKN_INTEL_ALH_CH, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, 194 offsetof(struct sof_ipc_dai_alh_params, channels)}, 195 }; 196 197 /* DMIC */ 198 static const struct sof_topology_token dmic_tokens[] = { 199 {SOF_TKN_INTEL_DMIC_DRIVER_VERSION, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, 200 offsetof(struct sof_ipc_dai_dmic_params, driver_ipc_version)}, 201 {SOF_TKN_INTEL_DMIC_CLK_MIN, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, 202 offsetof(struct sof_ipc_dai_dmic_params, pdmclk_min)}, 203 {SOF_TKN_INTEL_DMIC_CLK_MAX, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, 204 offsetof(struct sof_ipc_dai_dmic_params, pdmclk_max)}, 205 {SOF_TKN_INTEL_DMIC_SAMPLE_RATE, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, 206 offsetof(struct sof_ipc_dai_dmic_params, fifo_fs)}, 207 {SOF_TKN_INTEL_DMIC_DUTY_MIN, SND_SOC_TPLG_TUPLE_TYPE_SHORT, get_token_u16, 208 offsetof(struct sof_ipc_dai_dmic_params, duty_min)}, 209 {SOF_TKN_INTEL_DMIC_DUTY_MAX, SND_SOC_TPLG_TUPLE_TYPE_SHORT, get_token_u16, 210 offsetof(struct sof_ipc_dai_dmic_params, duty_max)}, 211 {SOF_TKN_INTEL_DMIC_NUM_PDM_ACTIVE, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, 212 offsetof(struct sof_ipc_dai_dmic_params, num_pdm_active)}, 213 {SOF_TKN_INTEL_DMIC_FIFO_WORD_LENGTH, SND_SOC_TPLG_TUPLE_TYPE_SHORT, get_token_u16, 214 offsetof(struct sof_ipc_dai_dmic_params, fifo_bits)}, 215 {SOF_TKN_INTEL_DMIC_UNMUTE_RAMP_TIME_MS, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, 216 offsetof(struct sof_ipc_dai_dmic_params, unmute_ramp_time)}, 217 }; 218 219 /* ESAI */ 220 static const struct sof_topology_token esai_tokens[] = { 221 {SOF_TKN_IMX_ESAI_MCLK_ID, SND_SOC_TPLG_TUPLE_TYPE_SHORT, get_token_u16, 222 offsetof(struct sof_ipc_dai_esai_params, mclk_id)}, 223 }; 224 225 /* SAI */ 226 static const struct sof_topology_token sai_tokens[] = { 227 {SOF_TKN_IMX_SAI_MCLK_ID, SND_SOC_TPLG_TUPLE_TYPE_SHORT, get_token_u16, 228 offsetof(struct sof_ipc_dai_sai_params, mclk_id)}, 229 }; 230 231 /* 232 * DMIC PDM Tokens 233 * SOF_TKN_INTEL_DMIC_PDM_CTRL_ID should be the first token 234 * as it increments the index while parsing the array of pdm tokens 235 * and determines the correct offset 236 */ 237 static const struct sof_topology_token dmic_pdm_tokens[] = { 238 {SOF_TKN_INTEL_DMIC_PDM_CTRL_ID, SND_SOC_TPLG_TUPLE_TYPE_SHORT, get_token_u16, 239 offsetof(struct sof_ipc_dai_dmic_pdm_ctrl, id)}, 240 {SOF_TKN_INTEL_DMIC_PDM_MIC_A_Enable, SND_SOC_TPLG_TUPLE_TYPE_SHORT, get_token_u16, 241 offsetof(struct sof_ipc_dai_dmic_pdm_ctrl, enable_mic_a)}, 242 {SOF_TKN_INTEL_DMIC_PDM_MIC_B_Enable, SND_SOC_TPLG_TUPLE_TYPE_SHORT, get_token_u16, 243 offsetof(struct sof_ipc_dai_dmic_pdm_ctrl, enable_mic_b)}, 244 {SOF_TKN_INTEL_DMIC_PDM_POLARITY_A, SND_SOC_TPLG_TUPLE_TYPE_SHORT, get_token_u16, 245 offsetof(struct sof_ipc_dai_dmic_pdm_ctrl, polarity_mic_a)}, 246 {SOF_TKN_INTEL_DMIC_PDM_POLARITY_B, SND_SOC_TPLG_TUPLE_TYPE_SHORT, get_token_u16, 247 offsetof(struct sof_ipc_dai_dmic_pdm_ctrl, polarity_mic_b)}, 248 {SOF_TKN_INTEL_DMIC_PDM_CLK_EDGE, SND_SOC_TPLG_TUPLE_TYPE_SHORT, get_token_u16, 249 offsetof(struct sof_ipc_dai_dmic_pdm_ctrl, clk_edge)}, 250 {SOF_TKN_INTEL_DMIC_PDM_SKEW, SND_SOC_TPLG_TUPLE_TYPE_SHORT, get_token_u16, 251 offsetof(struct sof_ipc_dai_dmic_pdm_ctrl, skew)}, 252 }; 253 254 /* HDA */ 255 static const struct sof_topology_token hda_tokens[] = { 256 {SOF_TKN_INTEL_HDA_RATE, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, 257 offsetof(struct sof_ipc_dai_hda_params, rate)}, 258 {SOF_TKN_INTEL_HDA_CH, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, 259 offsetof(struct sof_ipc_dai_hda_params, channels)}, 260 }; 261 262 /* AFE */ 263 static const struct sof_topology_token afe_tokens[] = { 264 {SOF_TKN_MEDIATEK_AFE_RATE, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, 265 offsetof(struct sof_ipc_dai_mtk_afe_params, rate)}, 266 {SOF_TKN_MEDIATEK_AFE_CH, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, 267 offsetof(struct sof_ipc_dai_mtk_afe_params, channels)}, 268 {SOF_TKN_MEDIATEK_AFE_FORMAT, SND_SOC_TPLG_TUPLE_TYPE_STRING, get_token_comp_format, 269 offsetof(struct sof_ipc_dai_mtk_afe_params, format)}, 270 }; 271 272 /* ACPDMIC */ 273 static const struct sof_topology_token acpdmic_tokens[] = { 274 {SOF_TKN_AMD_ACPDMIC_RATE, 275 SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, 276 offsetof(struct sof_ipc_dai_acpdmic_params, pdm_rate)}, 277 {SOF_TKN_AMD_ACPDMIC_CH, 278 SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, 279 offsetof(struct sof_ipc_dai_acpdmic_params, pdm_ch)}, 280 }; 281 282 /* ACPI2S */ 283 static const struct sof_topology_token acpi2s_tokens[] = { 284 {SOF_TKN_AMD_ACPI2S_RATE, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, 285 offsetof(struct sof_ipc_dai_acp_params, fsync_rate)}, 286 {SOF_TKN_AMD_ACPI2S_CH, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, 287 offsetof(struct sof_ipc_dai_acp_params, tdm_slots)}, 288 {SOF_TKN_AMD_ACPI2S_TDM_MODE, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, 289 offsetof(struct sof_ipc_dai_acp_params, tdm_mode)}, 290 }; 291 292 /* Core tokens */ 293 static const struct sof_topology_token core_tokens[] = { 294 {SOF_TKN_COMP_CORE_ID, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, 295 offsetof(struct sof_ipc_comp, core)}, 296 }; 297 298 /* Component extended tokens */ 299 static const struct sof_topology_token comp_ext_tokens[] = { 300 {SOF_TKN_COMP_UUID, SND_SOC_TPLG_TUPLE_TYPE_UUID, get_token_uuid, 301 offsetof(struct snd_sof_widget, uuid)}, 302 }; 303 304 static const struct sof_token_info ipc3_token_list[SOF_TOKEN_COUNT] = { 305 [SOF_PCM_TOKENS] = {"PCM tokens", pcm_tokens, ARRAY_SIZE(pcm_tokens)}, 306 [SOF_PIPELINE_TOKENS] = {"Pipeline tokens", pipeline_tokens, ARRAY_SIZE(pipeline_tokens)}, 307 [SOF_SCHED_TOKENS] = {"Scheduler tokens", sched_tokens, ARRAY_SIZE(sched_tokens)}, 308 [SOF_COMP_TOKENS] = {"Comp tokens", comp_tokens, ARRAY_SIZE(comp_tokens)}, 309 [SOF_CORE_TOKENS] = {"Core tokens", core_tokens, ARRAY_SIZE(core_tokens)}, 310 [SOF_COMP_EXT_TOKENS] = {"AFE tokens", comp_ext_tokens, ARRAY_SIZE(comp_ext_tokens)}, 311 [SOF_BUFFER_TOKENS] = {"Buffer tokens", buffer_tokens, ARRAY_SIZE(buffer_tokens)}, 312 [SOF_VOLUME_TOKENS] = {"Volume tokens", volume_tokens, ARRAY_SIZE(volume_tokens)}, 313 [SOF_SRC_TOKENS] = {"SRC tokens", src_tokens, ARRAY_SIZE(src_tokens)}, 314 [SOF_ASRC_TOKENS] = {"ASRC tokens", asrc_tokens, ARRAY_SIZE(asrc_tokens)}, 315 [SOF_PROCESS_TOKENS] = {"Process tokens", process_tokens, ARRAY_SIZE(process_tokens)}, 316 [SOF_DAI_TOKENS] = {"DAI tokens", dai_tokens, ARRAY_SIZE(dai_tokens)}, 317 [SOF_DAI_LINK_TOKENS] = {"DAI link tokens", dai_link_tokens, ARRAY_SIZE(dai_link_tokens)}, 318 [SOF_HDA_TOKENS] = {"HDA tokens", hda_tokens, ARRAY_SIZE(hda_tokens)}, 319 [SOF_SSP_TOKENS] = {"SSP tokens", ssp_tokens, ARRAY_SIZE(ssp_tokens)}, 320 [SOF_ALH_TOKENS] = {"ALH tokens", alh_tokens, ARRAY_SIZE(alh_tokens)}, 321 [SOF_DMIC_TOKENS] = {"DMIC tokens", dmic_tokens, ARRAY_SIZE(dmic_tokens)}, 322 [SOF_DMIC_PDM_TOKENS] = {"DMIC PDM tokens", dmic_pdm_tokens, ARRAY_SIZE(dmic_pdm_tokens)}, 323 [SOF_ESAI_TOKENS] = {"ESAI tokens", esai_tokens, ARRAY_SIZE(esai_tokens)}, 324 [SOF_SAI_TOKENS] = {"SAI tokens", sai_tokens, ARRAY_SIZE(sai_tokens)}, 325 [SOF_AFE_TOKENS] = {"AFE tokens", afe_tokens, ARRAY_SIZE(afe_tokens)}, 326 [SOF_ACPDMIC_TOKENS] = {"ACPDMIC tokens", acpdmic_tokens, ARRAY_SIZE(acpdmic_tokens)}, 327 [SOF_ACPI2S_TOKENS] = {"ACPI2S tokens", acpi2s_tokens, ARRAY_SIZE(acpi2s_tokens)}, 328 }; 329 330 /** 331 * sof_comp_alloc - allocate and initialize buffer for a new component 332 * @swidget: pointer to struct snd_sof_widget containing extended data 333 * @ipc_size: IPC payload size that will be updated depending on valid 334 * extended data. 335 * @index: ID of the pipeline the component belongs to 336 * 337 * Return: The pointer to the new allocated component, NULL if failed. 338 */ 339 static void *sof_comp_alloc(struct snd_sof_widget *swidget, size_t *ipc_size, 340 int index) 341 { 342 struct sof_ipc_comp *comp; 343 size_t total_size = *ipc_size; 344 size_t ext_size = sizeof(swidget->uuid); 345 346 /* only non-zero UUID is valid */ 347 if (!guid_is_null(&swidget->uuid)) 348 total_size += ext_size; 349 350 comp = kzalloc(total_size, GFP_KERNEL); 351 if (!comp) 352 return NULL; 353 354 /* configure comp new IPC message */ 355 comp->hdr.size = total_size; 356 comp->hdr.cmd = SOF_IPC_GLB_TPLG_MSG | SOF_IPC_TPLG_COMP_NEW; 357 comp->id = swidget->comp_id; 358 comp->pipeline_id = index; 359 comp->core = swidget->core; 360 361 /* handle the extended data if needed */ 362 if (total_size > *ipc_size) { 363 /* append extended data to the end of the component */ 364 memcpy((u8 *)comp + *ipc_size, &swidget->uuid, ext_size); 365 comp->ext_data_length = ext_size; 366 } 367 368 /* update ipc_size and return */ 369 *ipc_size = total_size; 370 return comp; 371 } 372 373 static void sof_dbg_comp_config(struct snd_soc_component *scomp, struct sof_ipc_comp_config *config) 374 { 375 dev_dbg(scomp->dev, " config: periods snk %d src %d fmt %d\n", 376 config->periods_sink, config->periods_source, 377 config->frame_fmt); 378 } 379 380 static int sof_ipc3_widget_setup_comp_host(struct snd_sof_widget *swidget) 381 { 382 struct snd_soc_component *scomp = swidget->scomp; 383 struct sof_ipc_comp_host *host; 384 size_t ipc_size = sizeof(*host); 385 int ret; 386 387 host = sof_comp_alloc(swidget, &ipc_size, swidget->pipeline_id); 388 if (!host) 389 return -ENOMEM; 390 swidget->private = host; 391 392 /* configure host comp IPC message */ 393 host->comp.type = SOF_COMP_HOST; 394 host->config.hdr.size = sizeof(host->config); 395 396 if (swidget->id == snd_soc_dapm_aif_out) 397 host->direction = SOF_IPC_STREAM_CAPTURE; 398 else 399 host->direction = SOF_IPC_STREAM_PLAYBACK; 400 401 /* parse one set of pcm_tokens */ 402 ret = sof_update_ipc_object(scomp, host, SOF_PCM_TOKENS, swidget->tuples, 403 swidget->num_tuples, sizeof(*host), 1); 404 if (ret < 0) 405 goto err; 406 407 /* parse one set of comp_tokens */ 408 ret = sof_update_ipc_object(scomp, &host->config, SOF_COMP_TOKENS, swidget->tuples, 409 swidget->num_tuples, sizeof(host->config), 1); 410 if (ret < 0) 411 goto err; 412 413 dev_dbg(scomp->dev, "loaded host %s\n", swidget->widget->name); 414 sof_dbg_comp_config(scomp, &host->config); 415 416 return 0; 417 err: 418 kfree(swidget->private); 419 swidget->private = NULL; 420 421 return ret; 422 } 423 424 static void sof_ipc3_widget_free_comp(struct snd_sof_widget *swidget) 425 { 426 kfree(swidget->private); 427 } 428 429 static int sof_ipc3_widget_setup_comp_tone(struct snd_sof_widget *swidget) 430 { 431 struct snd_soc_component *scomp = swidget->scomp; 432 struct sof_ipc_comp_tone *tone; 433 size_t ipc_size = sizeof(*tone); 434 int ret; 435 436 tone = sof_comp_alloc(swidget, &ipc_size, swidget->pipeline_id); 437 if (!tone) 438 return -ENOMEM; 439 440 swidget->private = tone; 441 442 /* configure siggen IPC message */ 443 tone->comp.type = SOF_COMP_TONE; 444 tone->config.hdr.size = sizeof(tone->config); 445 446 /* parse one set of comp tokens */ 447 ret = sof_update_ipc_object(scomp, &tone->config, SOF_COMP_TOKENS, swidget->tuples, 448 swidget->num_tuples, sizeof(tone->config), 1); 449 if (ret < 0) { 450 kfree(swidget->private); 451 swidget->private = NULL; 452 return ret; 453 } 454 455 dev_dbg(scomp->dev, "tone %s: frequency %d amplitude %d\n", 456 swidget->widget->name, tone->frequency, tone->amplitude); 457 sof_dbg_comp_config(scomp, &tone->config); 458 459 return 0; 460 } 461 462 static int sof_ipc3_widget_setup_comp_mixer(struct snd_sof_widget *swidget) 463 { 464 struct snd_soc_component *scomp = swidget->scomp; 465 struct sof_ipc_comp_mixer *mixer; 466 size_t ipc_size = sizeof(*mixer); 467 int ret; 468 469 mixer = sof_comp_alloc(swidget, &ipc_size, swidget->pipeline_id); 470 if (!mixer) 471 return -ENOMEM; 472 473 swidget->private = mixer; 474 475 /* configure mixer IPC message */ 476 mixer->comp.type = SOF_COMP_MIXER; 477 mixer->config.hdr.size = sizeof(mixer->config); 478 479 /* parse one set of comp tokens */ 480 ret = sof_update_ipc_object(scomp, &mixer->config, SOF_COMP_TOKENS, 481 swidget->tuples, swidget->num_tuples, 482 sizeof(mixer->config), 1); 483 if (ret < 0) { 484 kfree(swidget->private); 485 swidget->private = NULL; 486 487 return ret; 488 } 489 490 dev_dbg(scomp->dev, "loaded mixer %s\n", swidget->widget->name); 491 sof_dbg_comp_config(scomp, &mixer->config); 492 493 return 0; 494 } 495 496 static int sof_ipc3_widget_setup_comp_pipeline(struct snd_sof_widget *swidget) 497 { 498 struct snd_soc_component *scomp = swidget->scomp; 499 struct snd_sof_pipeline *spipe = swidget->spipe; 500 struct sof_ipc_pipe_new *pipeline; 501 struct snd_sof_widget *comp_swidget; 502 int ret; 503 504 pipeline = kzalloc(sizeof(*pipeline), GFP_KERNEL); 505 if (!pipeline) 506 return -ENOMEM; 507 508 /* configure pipeline IPC message */ 509 pipeline->hdr.size = sizeof(*pipeline); 510 pipeline->hdr.cmd = SOF_IPC_GLB_TPLG_MSG | SOF_IPC_TPLG_PIPE_NEW; 511 pipeline->pipeline_id = swidget->pipeline_id; 512 pipeline->comp_id = swidget->comp_id; 513 514 swidget->private = pipeline; 515 516 /* component at start of pipeline is our stream id */ 517 comp_swidget = snd_sof_find_swidget(scomp, swidget->widget->sname); 518 if (!comp_swidget) { 519 dev_err(scomp->dev, "scheduler %s refers to non existent widget %s\n", 520 swidget->widget->name, swidget->widget->sname); 521 ret = -EINVAL; 522 goto err; 523 } 524 525 pipeline->sched_id = comp_swidget->comp_id; 526 527 /* parse one set of scheduler tokens */ 528 ret = sof_update_ipc_object(scomp, pipeline, SOF_SCHED_TOKENS, swidget->tuples, 529 swidget->num_tuples, sizeof(*pipeline), 1); 530 if (ret < 0) 531 goto err; 532 533 /* parse one set of pipeline tokens */ 534 ret = sof_update_ipc_object(scomp, swidget, SOF_PIPELINE_TOKENS, swidget->tuples, 535 swidget->num_tuples, sizeof(*swidget), 1); 536 if (ret < 0) 537 goto err; 538 539 if (sof_debug_check_flag(SOF_DBG_DISABLE_MULTICORE)) 540 pipeline->core = SOF_DSP_PRIMARY_CORE; 541 542 if (sof_debug_check_flag(SOF_DBG_DYNAMIC_PIPELINES_OVERRIDE)) 543 swidget->dynamic_pipeline_widget = 544 sof_debug_check_flag(SOF_DBG_DYNAMIC_PIPELINES_ENABLE); 545 546 dev_dbg(scomp->dev, "pipeline %s: period %d pri %d mips %d core %d frames %d dynamic %d\n", 547 swidget->widget->name, pipeline->period, pipeline->priority, 548 pipeline->period_mips, pipeline->core, pipeline->frames_per_sched, 549 swidget->dynamic_pipeline_widget); 550 551 swidget->core = pipeline->core; 552 spipe->core_mask |= BIT(pipeline->core); 553 554 return 0; 555 556 err: 557 kfree(swidget->private); 558 swidget->private = NULL; 559 560 return ret; 561 } 562 563 static int sof_ipc3_widget_setup_comp_buffer(struct snd_sof_widget *swidget) 564 { 565 struct snd_soc_component *scomp = swidget->scomp; 566 struct sof_ipc_buffer *buffer; 567 int ret; 568 569 buffer = kzalloc(sizeof(*buffer), GFP_KERNEL); 570 if (!buffer) 571 return -ENOMEM; 572 573 swidget->private = buffer; 574 575 /* configure dai IPC message */ 576 buffer->comp.hdr.size = sizeof(*buffer); 577 buffer->comp.hdr.cmd = SOF_IPC_GLB_TPLG_MSG | SOF_IPC_TPLG_BUFFER_NEW; 578 buffer->comp.id = swidget->comp_id; 579 buffer->comp.type = SOF_COMP_BUFFER; 580 buffer->comp.pipeline_id = swidget->pipeline_id; 581 buffer->comp.core = swidget->core; 582 583 /* parse one set of buffer tokens */ 584 ret = sof_update_ipc_object(scomp, buffer, SOF_BUFFER_TOKENS, swidget->tuples, 585 swidget->num_tuples, sizeof(*buffer), 1); 586 if (ret < 0) { 587 kfree(swidget->private); 588 swidget->private = NULL; 589 return ret; 590 } 591 592 dev_dbg(scomp->dev, "buffer %s: size %d caps 0x%x\n", 593 swidget->widget->name, buffer->size, buffer->caps); 594 595 return 0; 596 } 597 598 static int sof_ipc3_widget_setup_comp_src(struct snd_sof_widget *swidget) 599 { 600 struct snd_soc_component *scomp = swidget->scomp; 601 struct sof_ipc_comp_src *src; 602 size_t ipc_size = sizeof(*src); 603 int ret; 604 605 src = sof_comp_alloc(swidget, &ipc_size, swidget->pipeline_id); 606 if (!src) 607 return -ENOMEM; 608 609 swidget->private = src; 610 611 /* configure src IPC message */ 612 src->comp.type = SOF_COMP_SRC; 613 src->config.hdr.size = sizeof(src->config); 614 615 /* parse one set of src tokens */ 616 ret = sof_update_ipc_object(scomp, src, SOF_SRC_TOKENS, swidget->tuples, 617 swidget->num_tuples, sizeof(*src), 1); 618 if (ret < 0) 619 goto err; 620 621 /* parse one set of comp tokens */ 622 ret = sof_update_ipc_object(scomp, &src->config, SOF_COMP_TOKENS, 623 swidget->tuples, swidget->num_tuples, sizeof(src->config), 1); 624 if (ret < 0) 625 goto err; 626 627 dev_dbg(scomp->dev, "src %s: source rate %d sink rate %d\n", 628 swidget->widget->name, src->source_rate, src->sink_rate); 629 sof_dbg_comp_config(scomp, &src->config); 630 631 return 0; 632 err: 633 kfree(swidget->private); 634 swidget->private = NULL; 635 636 return ret; 637 } 638 639 static int sof_ipc3_widget_setup_comp_asrc(struct snd_sof_widget *swidget) 640 { 641 struct snd_soc_component *scomp = swidget->scomp; 642 struct sof_ipc_comp_asrc *asrc; 643 size_t ipc_size = sizeof(*asrc); 644 int ret; 645 646 asrc = sof_comp_alloc(swidget, &ipc_size, swidget->pipeline_id); 647 if (!asrc) 648 return -ENOMEM; 649 650 swidget->private = asrc; 651 652 /* configure ASRC IPC message */ 653 asrc->comp.type = SOF_COMP_ASRC; 654 asrc->config.hdr.size = sizeof(asrc->config); 655 656 /* parse one set of asrc tokens */ 657 ret = sof_update_ipc_object(scomp, asrc, SOF_ASRC_TOKENS, swidget->tuples, 658 swidget->num_tuples, sizeof(*asrc), 1); 659 if (ret < 0) 660 goto err; 661 662 /* parse one set of comp tokens */ 663 ret = sof_update_ipc_object(scomp, &asrc->config, SOF_COMP_TOKENS, 664 swidget->tuples, swidget->num_tuples, sizeof(asrc->config), 1); 665 if (ret < 0) 666 goto err; 667 668 dev_dbg(scomp->dev, "asrc %s: source rate %d sink rate %d asynch %d operation %d\n", 669 swidget->widget->name, asrc->source_rate, asrc->sink_rate, 670 asrc->asynchronous_mode, asrc->operation_mode); 671 672 sof_dbg_comp_config(scomp, &asrc->config); 673 674 return 0; 675 err: 676 kfree(swidget->private); 677 swidget->private = NULL; 678 679 return ret; 680 } 681 682 /* 683 * Mux topology 684 */ 685 static int sof_ipc3_widget_setup_comp_mux(struct snd_sof_widget *swidget) 686 { 687 struct snd_soc_component *scomp = swidget->scomp; 688 struct sof_ipc_comp_mux *mux; 689 size_t ipc_size = sizeof(*mux); 690 int ret; 691 692 mux = sof_comp_alloc(swidget, &ipc_size, swidget->pipeline_id); 693 if (!mux) 694 return -ENOMEM; 695 696 swidget->private = mux; 697 698 /* configure mux IPC message */ 699 mux->comp.type = SOF_COMP_MUX; 700 mux->config.hdr.size = sizeof(mux->config); 701 702 /* parse one set of comp tokens */ 703 ret = sof_update_ipc_object(scomp, &mux->config, SOF_COMP_TOKENS, 704 swidget->tuples, swidget->num_tuples, sizeof(mux->config), 1); 705 if (ret < 0) { 706 kfree(swidget->private); 707 swidget->private = NULL; 708 return ret; 709 } 710 711 dev_dbg(scomp->dev, "loaded mux %s\n", swidget->widget->name); 712 sof_dbg_comp_config(scomp, &mux->config); 713 714 return 0; 715 } 716 717 /* 718 * PGA Topology 719 */ 720 721 static int sof_ipc3_widget_setup_comp_pga(struct snd_sof_widget *swidget) 722 { 723 struct snd_soc_component *scomp = swidget->scomp; 724 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); 725 struct sof_ipc_comp_volume *volume; 726 struct snd_sof_control *scontrol; 727 size_t ipc_size = sizeof(*volume); 728 int min_step, max_step; 729 int ret; 730 731 volume = sof_comp_alloc(swidget, &ipc_size, swidget->pipeline_id); 732 if (!volume) 733 return -ENOMEM; 734 735 swidget->private = volume; 736 737 /* configure volume IPC message */ 738 volume->comp.type = SOF_COMP_VOLUME; 739 volume->config.hdr.size = sizeof(volume->config); 740 741 /* parse one set of volume tokens */ 742 ret = sof_update_ipc_object(scomp, volume, SOF_VOLUME_TOKENS, swidget->tuples, 743 swidget->num_tuples, sizeof(*volume), 1); 744 if (ret < 0) 745 goto err; 746 747 /* parse one set of comp tokens */ 748 ret = sof_update_ipc_object(scomp, &volume->config, SOF_COMP_TOKENS, 749 swidget->tuples, swidget->num_tuples, 750 sizeof(volume->config), 1); 751 if (ret < 0) 752 goto err; 753 754 dev_dbg(scomp->dev, "loaded PGA %s\n", swidget->widget->name); 755 sof_dbg_comp_config(scomp, &volume->config); 756 757 list_for_each_entry(scontrol, &sdev->kcontrol_list, list) { 758 if (scontrol->comp_id == swidget->comp_id && 759 scontrol->volume_table) { 760 min_step = scontrol->min_volume_step; 761 max_step = scontrol->max_volume_step; 762 volume->min_value = scontrol->volume_table[min_step]; 763 volume->max_value = scontrol->volume_table[max_step]; 764 volume->channels = scontrol->num_channels; 765 break; 766 } 767 } 768 769 return 0; 770 err: 771 kfree(swidget->private); 772 swidget->private = NULL; 773 774 return ret; 775 } 776 777 static int sof_get_control_data(struct snd_soc_component *scomp, 778 struct snd_soc_dapm_widget *widget, 779 struct sof_widget_data *wdata, size_t *size) 780 { 781 const struct snd_kcontrol_new *kc; 782 struct sof_ipc_ctrl_data *cdata; 783 struct soc_mixer_control *sm; 784 struct soc_bytes_ext *sbe; 785 struct soc_enum *se; 786 int i; 787 788 *size = 0; 789 790 for (i = 0; i < widget->num_kcontrols; i++) { 791 kc = &widget->kcontrol_news[i]; 792 793 switch (widget->dobj.widget.kcontrol_type[i]) { 794 case SND_SOC_TPLG_TYPE_MIXER: 795 sm = (struct soc_mixer_control *)kc->private_value; 796 wdata[i].control = sm->dobj.private; 797 break; 798 case SND_SOC_TPLG_TYPE_BYTES: 799 sbe = (struct soc_bytes_ext *)kc->private_value; 800 wdata[i].control = sbe->dobj.private; 801 break; 802 case SND_SOC_TPLG_TYPE_ENUM: 803 se = (struct soc_enum *)kc->private_value; 804 wdata[i].control = se->dobj.private; 805 break; 806 default: 807 dev_err(scomp->dev, "Unknown kcontrol type %u in widget %s\n", 808 widget->dobj.widget.kcontrol_type[i], widget->name); 809 return -EINVAL; 810 } 811 812 if (!wdata[i].control) { 813 dev_err(scomp->dev, "No scontrol for widget %s\n", widget->name); 814 return -EINVAL; 815 } 816 817 cdata = wdata[i].control->ipc_control_data; 818 819 if (widget->dobj.widget.kcontrol_type[i] == SND_SOC_TPLG_TYPE_BYTES) { 820 /* make sure data is valid - data can be updated at runtime */ 821 if (cdata->data->magic != SOF_ABI_MAGIC) 822 return -EINVAL; 823 824 wdata[i].pdata = cdata->data->data; 825 wdata[i].pdata_size = cdata->data->size; 826 } else { 827 /* points to the control data union */ 828 wdata[i].pdata = cdata->chanv; 829 /* 830 * wdata[i].control->size is calculated with struct_size 831 * and includes the size of struct sof_ipc_ctrl_data 832 */ 833 wdata[i].pdata_size = wdata[i].control->size - 834 sizeof(struct sof_ipc_ctrl_data); 835 } 836 837 *size += wdata[i].pdata_size; 838 839 /* get data type */ 840 switch (cdata->cmd) { 841 case SOF_CTRL_CMD_VOLUME: 842 case SOF_CTRL_CMD_ENUM: 843 case SOF_CTRL_CMD_SWITCH: 844 wdata[i].ipc_cmd = SOF_IPC_COMP_SET_VALUE; 845 wdata[i].ctrl_type = SOF_CTRL_TYPE_VALUE_CHAN_SET; 846 break; 847 case SOF_CTRL_CMD_BINARY: 848 wdata[i].ipc_cmd = SOF_IPC_COMP_SET_DATA; 849 wdata[i].ctrl_type = SOF_CTRL_TYPE_DATA_SET; 850 break; 851 default: 852 break; 853 } 854 } 855 856 return 0; 857 } 858 859 static int sof_process_load(struct snd_soc_component *scomp, 860 struct snd_sof_widget *swidget, int type) 861 { 862 struct snd_soc_dapm_widget *widget = swidget->widget; 863 struct sof_ipc_comp_process *process; 864 struct sof_widget_data *wdata = NULL; 865 size_t ipc_data_size = 0; 866 size_t ipc_size; 867 int offset = 0; 868 int ret; 869 int i; 870 871 /* allocate struct for widget control data sizes and types */ 872 if (widget->num_kcontrols) { 873 wdata = kcalloc(widget->num_kcontrols, sizeof(*wdata), GFP_KERNEL); 874 if (!wdata) 875 return -ENOMEM; 876 877 /* get possible component controls and get size of all pdata */ 878 ret = sof_get_control_data(scomp, widget, wdata, &ipc_data_size); 879 if (ret < 0) 880 goto out; 881 } 882 883 ipc_size = sizeof(struct sof_ipc_comp_process) + ipc_data_size; 884 885 /* we are exceeding max ipc size, config needs to be sent separately */ 886 if (ipc_size > SOF_IPC_MSG_MAX_SIZE) { 887 ipc_size -= ipc_data_size; 888 ipc_data_size = 0; 889 } 890 891 process = sof_comp_alloc(swidget, &ipc_size, swidget->pipeline_id); 892 if (!process) { 893 ret = -ENOMEM; 894 goto out; 895 } 896 897 swidget->private = process; 898 899 /* configure iir IPC message */ 900 process->comp.type = type; 901 process->config.hdr.size = sizeof(process->config); 902 903 /* parse one set of comp tokens */ 904 ret = sof_update_ipc_object(scomp, &process->config, SOF_COMP_TOKENS, 905 swidget->tuples, swidget->num_tuples, 906 sizeof(process->config), 1); 907 if (ret < 0) 908 goto err; 909 910 dev_dbg(scomp->dev, "loaded process %s\n", swidget->widget->name); 911 sof_dbg_comp_config(scomp, &process->config); 912 913 /* 914 * found private data in control, so copy it. 915 * get possible component controls - get size of all pdata, 916 * then memcpy with headers 917 */ 918 if (ipc_data_size) { 919 for (i = 0; i < widget->num_kcontrols; i++) { 920 if (!wdata[i].pdata_size) 921 continue; 922 923 memcpy(&process->data[offset], wdata[i].pdata, 924 wdata[i].pdata_size); 925 offset += wdata[i].pdata_size; 926 } 927 } 928 929 process->size = ipc_data_size; 930 931 kfree(wdata); 932 933 return 0; 934 err: 935 kfree(swidget->private); 936 swidget->private = NULL; 937 out: 938 kfree(wdata); 939 return ret; 940 } 941 942 static enum sof_comp_type find_process_comp_type(enum sof_ipc_process_type type) 943 { 944 int i; 945 946 for (i = 0; i < ARRAY_SIZE(sof_process); i++) { 947 if (sof_process[i].type == type) 948 return sof_process[i].comp_type; 949 } 950 951 return SOF_COMP_NONE; 952 } 953 954 /* 955 * Processing Component Topology - can be "effect", "codec", or general 956 * "processing". 957 */ 958 959 static int sof_widget_update_ipc_comp_process(struct snd_sof_widget *swidget) 960 { 961 struct snd_soc_component *scomp = swidget->scomp; 962 struct sof_ipc_comp_process config; 963 int ret; 964 965 memset(&config, 0, sizeof(config)); 966 config.comp.core = swidget->core; 967 968 /* parse one set of process tokens */ 969 ret = sof_update_ipc_object(scomp, &config, SOF_PROCESS_TOKENS, swidget->tuples, 970 swidget->num_tuples, sizeof(config), 1); 971 if (ret < 0) 972 return ret; 973 974 /* now load process specific data and send IPC */ 975 return sof_process_load(scomp, swidget, find_process_comp_type(config.type)); 976 } 977 978 static int sof_link_hda_load(struct snd_soc_component *scomp, struct snd_sof_dai_link *slink, 979 struct sof_ipc_dai_config *config, struct snd_sof_dai *dai) 980 { 981 struct sof_dai_private_data *private = dai->private; 982 u32 size = sizeof(*config); 983 int ret; 984 985 /* init IPC */ 986 memset(&config->hda, 0, sizeof(config->hda)); 987 config->hdr.size = size; 988 989 /* parse one set of HDA tokens */ 990 ret = sof_update_ipc_object(scomp, &config->hda, SOF_HDA_TOKENS, slink->tuples, 991 slink->num_tuples, size, 1); 992 if (ret < 0) 993 return ret; 994 995 dev_dbg(scomp->dev, "HDA config rate %d channels %d\n", 996 config->hda.rate, config->hda.channels); 997 998 config->hda.link_dma_ch = DMA_CHAN_INVALID; 999 1000 dai->number_configs = 1; 1001 dai->current_config = 0; 1002 private->dai_config = kmemdup(config, size, GFP_KERNEL); 1003 if (!private->dai_config) 1004 return -ENOMEM; 1005 1006 return 0; 1007 } 1008 1009 static void sof_dai_set_format(struct snd_soc_tplg_hw_config *hw_config, 1010 struct sof_ipc_dai_config *config) 1011 { 1012 /* clock directions wrt codec */ 1013 config->format &= ~SOF_DAI_FMT_CLOCK_PROVIDER_MASK; 1014 if (hw_config->bclk_provider == SND_SOC_TPLG_BCLK_CP) { 1015 /* codec is bclk provider */ 1016 if (hw_config->fsync_provider == SND_SOC_TPLG_FSYNC_CP) 1017 config->format |= SOF_DAI_FMT_CBP_CFP; 1018 else 1019 config->format |= SOF_DAI_FMT_CBP_CFC; 1020 } else { 1021 /* codec is bclk consumer */ 1022 if (hw_config->fsync_provider == SND_SOC_TPLG_FSYNC_CP) 1023 config->format |= SOF_DAI_FMT_CBC_CFP; 1024 else 1025 config->format |= SOF_DAI_FMT_CBC_CFC; 1026 } 1027 1028 /* inverted clocks ? */ 1029 config->format &= ~SOF_DAI_FMT_INV_MASK; 1030 if (hw_config->invert_bclk) { 1031 if (hw_config->invert_fsync) 1032 config->format |= SOF_DAI_FMT_IB_IF; 1033 else 1034 config->format |= SOF_DAI_FMT_IB_NF; 1035 } else { 1036 if (hw_config->invert_fsync) 1037 config->format |= SOF_DAI_FMT_NB_IF; 1038 else 1039 config->format |= SOF_DAI_FMT_NB_NF; 1040 } 1041 } 1042 1043 static int sof_link_sai_load(struct snd_soc_component *scomp, struct snd_sof_dai_link *slink, 1044 struct sof_ipc_dai_config *config, struct snd_sof_dai *dai) 1045 { 1046 struct snd_soc_tplg_hw_config *hw_config = slink->hw_configs; 1047 struct sof_dai_private_data *private = dai->private; 1048 u32 size = sizeof(*config); 1049 int ret; 1050 1051 /* handle master/slave and inverted clocks */ 1052 sof_dai_set_format(hw_config, config); 1053 1054 /* init IPC */ 1055 memset(&config->sai, 0, sizeof(config->sai)); 1056 config->hdr.size = size; 1057 1058 /* parse one set of SAI tokens */ 1059 ret = sof_update_ipc_object(scomp, &config->sai, SOF_SAI_TOKENS, slink->tuples, 1060 slink->num_tuples, size, 1); 1061 if (ret < 0) 1062 return ret; 1063 1064 config->sai.mclk_rate = le32_to_cpu(hw_config->mclk_rate); 1065 config->sai.bclk_rate = le32_to_cpu(hw_config->bclk_rate); 1066 config->sai.fsync_rate = le32_to_cpu(hw_config->fsync_rate); 1067 config->sai.mclk_direction = hw_config->mclk_direction; 1068 1069 config->sai.tdm_slots = le32_to_cpu(hw_config->tdm_slots); 1070 config->sai.tdm_slot_width = le32_to_cpu(hw_config->tdm_slot_width); 1071 config->sai.rx_slots = le32_to_cpu(hw_config->rx_slots); 1072 config->sai.tx_slots = le32_to_cpu(hw_config->tx_slots); 1073 1074 dev_info(scomp->dev, 1075 "tplg: config SAI%d fmt 0x%x mclk %d width %d slots %d mclk id %d\n", 1076 config->dai_index, config->format, 1077 config->sai.mclk_rate, config->sai.tdm_slot_width, 1078 config->sai.tdm_slots, config->sai.mclk_id); 1079 1080 if (config->sai.tdm_slots < 1 || config->sai.tdm_slots > 8) { 1081 dev_err(scomp->dev, "Invalid channel count for SAI%d\n", config->dai_index); 1082 return -EINVAL; 1083 } 1084 1085 dai->number_configs = 1; 1086 dai->current_config = 0; 1087 private->dai_config = kmemdup(config, size, GFP_KERNEL); 1088 if (!private->dai_config) 1089 return -ENOMEM; 1090 1091 return 0; 1092 } 1093 1094 static int sof_link_esai_load(struct snd_soc_component *scomp, struct snd_sof_dai_link *slink, 1095 struct sof_ipc_dai_config *config, struct snd_sof_dai *dai) 1096 { 1097 struct snd_soc_tplg_hw_config *hw_config = slink->hw_configs; 1098 struct sof_dai_private_data *private = dai->private; 1099 u32 size = sizeof(*config); 1100 int ret; 1101 1102 /* handle master/slave and inverted clocks */ 1103 sof_dai_set_format(hw_config, config); 1104 1105 /* init IPC */ 1106 memset(&config->esai, 0, sizeof(config->esai)); 1107 config->hdr.size = size; 1108 1109 /* parse one set of ESAI tokens */ 1110 ret = sof_update_ipc_object(scomp, &config->esai, SOF_ESAI_TOKENS, slink->tuples, 1111 slink->num_tuples, size, 1); 1112 if (ret < 0) 1113 return ret; 1114 1115 config->esai.mclk_rate = le32_to_cpu(hw_config->mclk_rate); 1116 config->esai.bclk_rate = le32_to_cpu(hw_config->bclk_rate); 1117 config->esai.fsync_rate = le32_to_cpu(hw_config->fsync_rate); 1118 config->esai.mclk_direction = hw_config->mclk_direction; 1119 config->esai.tdm_slots = le32_to_cpu(hw_config->tdm_slots); 1120 config->esai.tdm_slot_width = le32_to_cpu(hw_config->tdm_slot_width); 1121 config->esai.rx_slots = le32_to_cpu(hw_config->rx_slots); 1122 config->esai.tx_slots = le32_to_cpu(hw_config->tx_slots); 1123 1124 dev_info(scomp->dev, 1125 "tplg: config ESAI%d fmt 0x%x mclk %d width %d slots %d mclk id %d\n", 1126 config->dai_index, config->format, 1127 config->esai.mclk_rate, config->esai.tdm_slot_width, 1128 config->esai.tdm_slots, config->esai.mclk_id); 1129 1130 if (config->esai.tdm_slots < 1 || config->esai.tdm_slots > 8) { 1131 dev_err(scomp->dev, "Invalid channel count for ESAI%d\n", config->dai_index); 1132 return -EINVAL; 1133 } 1134 1135 dai->number_configs = 1; 1136 dai->current_config = 0; 1137 private->dai_config = kmemdup(config, size, GFP_KERNEL); 1138 if (!private->dai_config) 1139 return -ENOMEM; 1140 1141 return 0; 1142 } 1143 1144 static int sof_link_acp_dmic_load(struct snd_soc_component *scomp, struct snd_sof_dai_link *slink, 1145 struct sof_ipc_dai_config *config, struct snd_sof_dai *dai) 1146 { 1147 struct snd_soc_tplg_hw_config *hw_config = slink->hw_configs; 1148 struct sof_dai_private_data *private = dai->private; 1149 u32 size = sizeof(*config); 1150 int ret; 1151 1152 /* handle master/slave and inverted clocks */ 1153 sof_dai_set_format(hw_config, config); 1154 1155 config->hdr.size = size; 1156 1157 /* parse the required set of ACPDMIC tokens based on num_hw_cfgs */ 1158 ret = sof_update_ipc_object(scomp, &config->acpdmic, SOF_ACPDMIC_TOKENS, slink->tuples, 1159 slink->num_tuples, size, slink->num_hw_configs); 1160 if (ret < 0) 1161 return ret; 1162 1163 dev_info(scomp->dev, "ACP_DMIC config ACP%d channel %d rate %d\n", 1164 config->dai_index, config->acpdmic.pdm_ch, 1165 config->acpdmic.pdm_rate); 1166 1167 dai->number_configs = 1; 1168 dai->current_config = 0; 1169 private->dai_config = kmemdup(config, size, GFP_KERNEL); 1170 if (!private->dai_config) 1171 return -ENOMEM; 1172 1173 return 0; 1174 } 1175 1176 static int sof_link_acp_bt_load(struct snd_soc_component *scomp, struct snd_sof_dai_link *slink, 1177 struct sof_ipc_dai_config *config, struct snd_sof_dai *dai) 1178 { 1179 struct snd_soc_tplg_hw_config *hw_config = slink->hw_configs; 1180 struct sof_dai_private_data *private = dai->private; 1181 u32 size = sizeof(*config); 1182 1183 /* handle master/slave and inverted clocks */ 1184 sof_dai_set_format(hw_config, config); 1185 1186 /* init IPC */ 1187 memset(&config->acpbt, 0, sizeof(config->acpbt)); 1188 config->hdr.size = size; 1189 1190 config->acpbt.fsync_rate = le32_to_cpu(hw_config->fsync_rate); 1191 config->acpbt.tdm_slots = le32_to_cpu(hw_config->tdm_slots); 1192 1193 dev_info(scomp->dev, "ACP_BT config ACP%d channel %d rate %d\n", 1194 config->dai_index, config->acpbt.tdm_slots, 1195 config->acpbt.fsync_rate); 1196 1197 dai->number_configs = 1; 1198 dai->current_config = 0; 1199 private->dai_config = kmemdup(config, size, GFP_KERNEL); 1200 if (!private->dai_config) 1201 return -ENOMEM; 1202 1203 return 0; 1204 } 1205 1206 static int sof_link_acp_sp_load(struct snd_soc_component *scomp, struct snd_sof_dai_link *slink, 1207 struct sof_ipc_dai_config *config, struct snd_sof_dai *dai) 1208 { 1209 struct snd_soc_tplg_hw_config *hw_config = slink->hw_configs; 1210 struct sof_dai_private_data *private = dai->private; 1211 u32 size = sizeof(*config); 1212 int ret; 1213 1214 /* handle master/slave and inverted clocks */ 1215 sof_dai_set_format(hw_config, config); 1216 1217 /* init IPC */ 1218 memset(&config->acpsp, 0, sizeof(config->acpsp)); 1219 config->hdr.size = size; 1220 1221 ret = sof_update_ipc_object(scomp, &config->acpsp, SOF_ACPI2S_TOKENS, slink->tuples, 1222 slink->num_tuples, size, slink->num_hw_configs); 1223 if (ret < 0) 1224 return ret; 1225 1226 1227 dev_info(scomp->dev, "ACP_SP config ACP%d channel %d rate %d tdm_mode %d\n", 1228 config->dai_index, config->acpsp.tdm_slots, 1229 config->acpsp.fsync_rate, config->acpsp.tdm_mode); 1230 1231 dai->number_configs = 1; 1232 dai->current_config = 0; 1233 private->dai_config = kmemdup(config, size, GFP_KERNEL); 1234 if (!private->dai_config) 1235 return -ENOMEM; 1236 1237 return 0; 1238 } 1239 1240 static int sof_link_acp_hs_load(struct snd_soc_component *scomp, struct snd_sof_dai_link *slink, 1241 struct sof_ipc_dai_config *config, struct snd_sof_dai *dai) 1242 { 1243 struct snd_soc_tplg_hw_config *hw_config = slink->hw_configs; 1244 struct sof_dai_private_data *private = dai->private; 1245 u32 size = sizeof(*config); 1246 int ret; 1247 1248 /* Configures the DAI hardware format and inverted clocks */ 1249 sof_dai_set_format(hw_config, config); 1250 1251 /* init IPC */ 1252 memset(&config->acphs, 0, sizeof(config->acphs)); 1253 config->hdr.size = size; 1254 1255 ret = sof_update_ipc_object(scomp, &config->acphs, SOF_ACPI2S_TOKENS, slink->tuples, 1256 slink->num_tuples, size, slink->num_hw_configs); 1257 if (ret < 0) 1258 return ret; 1259 1260 dev_info(scomp->dev, "ACP_HS config ACP%d channel %d rate %d tdm_mode %d\n", 1261 config->dai_index, config->acphs.tdm_slots, 1262 config->acphs.fsync_rate, config->acphs.tdm_mode); 1263 1264 dai->number_configs = 1; 1265 dai->current_config = 0; 1266 private->dai_config = kmemdup(config, size, GFP_KERNEL); 1267 if (!private->dai_config) 1268 return -ENOMEM; 1269 1270 return 0; 1271 } 1272 1273 static int sof_link_afe_load(struct snd_soc_component *scomp, struct snd_sof_dai_link *slink, 1274 struct sof_ipc_dai_config *config, struct snd_sof_dai *dai) 1275 { 1276 struct sof_dai_private_data *private = dai->private; 1277 u32 size = sizeof(*config); 1278 int ret; 1279 1280 config->hdr.size = size; 1281 1282 /* parse the required set of AFE tokens based on num_hw_cfgs */ 1283 ret = sof_update_ipc_object(scomp, &config->afe, SOF_AFE_TOKENS, slink->tuples, 1284 slink->num_tuples, size, slink->num_hw_configs); 1285 if (ret < 0) 1286 return ret; 1287 1288 dev_dbg(scomp->dev, "AFE config rate %d channels %d format:%d\n", 1289 config->afe.rate, config->afe.channels, config->afe.format); 1290 1291 config->afe.stream_id = DMA_CHAN_INVALID; 1292 1293 dai->number_configs = 1; 1294 dai->current_config = 0; 1295 private->dai_config = kmemdup(config, size, GFP_KERNEL); 1296 if (!private->dai_config) 1297 return -ENOMEM; 1298 1299 return 0; 1300 } 1301 1302 static int sof_link_ssp_load(struct snd_soc_component *scomp, struct snd_sof_dai_link *slink, 1303 struct sof_ipc_dai_config *config, struct snd_sof_dai *dai) 1304 { 1305 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); 1306 struct snd_soc_tplg_hw_config *hw_config = slink->hw_configs; 1307 struct sof_dai_private_data *private = dai->private; 1308 u32 size = sizeof(*config); 1309 int current_config = 0; 1310 int i, ret; 1311 1312 /* 1313 * Parse common data, we should have 1 common data per hw_config. 1314 */ 1315 ret = sof_update_ipc_object(scomp, &config->ssp, SOF_SSP_TOKENS, slink->tuples, 1316 slink->num_tuples, size, slink->num_hw_configs); 1317 if (ret < 0) 1318 return ret; 1319 1320 /* process all possible hw configs */ 1321 for (i = 0; i < slink->num_hw_configs; i++) { 1322 if (le32_to_cpu(hw_config[i].id) == slink->default_hw_cfg_id) 1323 current_config = i; 1324 1325 /* handle master/slave and inverted clocks */ 1326 sof_dai_set_format(&hw_config[i], &config[i]); 1327 1328 config[i].hdr.size = size; 1329 1330 if (sdev->mclk_id_override) { 1331 dev_dbg(scomp->dev, "tplg: overriding topology mclk_id %d by quirk %d\n", 1332 config[i].ssp.mclk_id, sdev->mclk_id_quirk); 1333 config[i].ssp.mclk_id = sdev->mclk_id_quirk; 1334 } 1335 1336 /* copy differentiating hw configs to ipc structs */ 1337 config[i].ssp.mclk_rate = le32_to_cpu(hw_config[i].mclk_rate); 1338 config[i].ssp.bclk_rate = le32_to_cpu(hw_config[i].bclk_rate); 1339 config[i].ssp.fsync_rate = le32_to_cpu(hw_config[i].fsync_rate); 1340 config[i].ssp.tdm_slots = le32_to_cpu(hw_config[i].tdm_slots); 1341 config[i].ssp.tdm_slot_width = le32_to_cpu(hw_config[i].tdm_slot_width); 1342 config[i].ssp.mclk_direction = hw_config[i].mclk_direction; 1343 config[i].ssp.rx_slots = le32_to_cpu(hw_config[i].rx_slots); 1344 config[i].ssp.tx_slots = le32_to_cpu(hw_config[i].tx_slots); 1345 1346 dev_dbg(scomp->dev, "tplg: config SSP%d fmt %#x mclk %d bclk %d fclk %d width (%d)%d slots %d mclk id %d quirks %d clks_control %#x\n", 1347 config[i].dai_index, config[i].format, 1348 config[i].ssp.mclk_rate, config[i].ssp.bclk_rate, 1349 config[i].ssp.fsync_rate, config[i].ssp.sample_valid_bits, 1350 config[i].ssp.tdm_slot_width, config[i].ssp.tdm_slots, 1351 config[i].ssp.mclk_id, config[i].ssp.quirks, config[i].ssp.clks_control); 1352 1353 /* validate SSP fsync rate and channel count */ 1354 if (config[i].ssp.fsync_rate < 8000 || config[i].ssp.fsync_rate > 192000) { 1355 dev_err(scomp->dev, "Invalid fsync rate for SSP%d\n", config[i].dai_index); 1356 return -EINVAL; 1357 } 1358 1359 if (config[i].ssp.tdm_slots < 1 || config[i].ssp.tdm_slots > 8) { 1360 dev_err(scomp->dev, "Invalid channel count for SSP%d\n", 1361 config[i].dai_index); 1362 return -EINVAL; 1363 } 1364 } 1365 1366 dai->number_configs = slink->num_hw_configs; 1367 dai->current_config = current_config; 1368 private->dai_config = kmemdup(config, size * slink->num_hw_configs, GFP_KERNEL); 1369 if (!private->dai_config) 1370 return -ENOMEM; 1371 1372 return 0; 1373 } 1374 1375 static int sof_link_dmic_load(struct snd_soc_component *scomp, struct snd_sof_dai_link *slink, 1376 struct sof_ipc_dai_config *config, struct snd_sof_dai *dai) 1377 { 1378 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); 1379 struct sof_dai_private_data *private = dai->private; 1380 struct sof_ipc_fw_ready *ready = &sdev->fw_ready; 1381 struct sof_ipc_fw_version *v = &ready->version; 1382 size_t size = sizeof(*config); 1383 int i, ret; 1384 1385 /* Ensure the entire DMIC config struct is zeros */ 1386 memset(&config->dmic, 0, sizeof(config->dmic)); 1387 1388 /* parse the required set of DMIC tokens based on num_hw_cfgs */ 1389 ret = sof_update_ipc_object(scomp, &config->dmic, SOF_DMIC_TOKENS, slink->tuples, 1390 slink->num_tuples, size, slink->num_hw_configs); 1391 if (ret < 0) 1392 return ret; 1393 1394 /* parse the required set of DMIC PDM tokens based on number of active PDM's */ 1395 ret = sof_update_ipc_object(scomp, &config->dmic.pdm[0], SOF_DMIC_PDM_TOKENS, 1396 slink->tuples, slink->num_tuples, 1397 sizeof(struct sof_ipc_dai_dmic_pdm_ctrl), 1398 config->dmic.num_pdm_active); 1399 if (ret < 0) 1400 return ret; 1401 1402 /* set IPC header size */ 1403 config->hdr.size = size; 1404 1405 /* debug messages */ 1406 dev_dbg(scomp->dev, "tplg: config DMIC%d driver version %d\n", 1407 config->dai_index, config->dmic.driver_ipc_version); 1408 dev_dbg(scomp->dev, "pdmclk_min %d pdm_clkmax %d duty_min %d\n", 1409 config->dmic.pdmclk_min, config->dmic.pdmclk_max, 1410 config->dmic.duty_min); 1411 dev_dbg(scomp->dev, "duty_max %d fifo_fs %d num_pdms active %d\n", 1412 config->dmic.duty_max, config->dmic.fifo_fs, 1413 config->dmic.num_pdm_active); 1414 dev_dbg(scomp->dev, "fifo word length %d\n", config->dmic.fifo_bits); 1415 1416 for (i = 0; i < config->dmic.num_pdm_active; i++) { 1417 dev_dbg(scomp->dev, "pdm %d mic a %d mic b %d\n", 1418 config->dmic.pdm[i].id, 1419 config->dmic.pdm[i].enable_mic_a, 1420 config->dmic.pdm[i].enable_mic_b); 1421 dev_dbg(scomp->dev, "pdm %d polarity a %d polarity b %d\n", 1422 config->dmic.pdm[i].id, 1423 config->dmic.pdm[i].polarity_mic_a, 1424 config->dmic.pdm[i].polarity_mic_b); 1425 dev_dbg(scomp->dev, "pdm %d clk_edge %d skew %d\n", 1426 config->dmic.pdm[i].id, 1427 config->dmic.pdm[i].clk_edge, 1428 config->dmic.pdm[i].skew); 1429 } 1430 1431 /* 1432 * this takes care of backwards compatible handling of fifo_bits_b. 1433 * It is deprecated since firmware ABI version 3.0.1. 1434 */ 1435 if (SOF_ABI_VER(v->major, v->minor, v->micro) < SOF_ABI_VER(3, 0, 1)) 1436 config->dmic.fifo_bits_b = config->dmic.fifo_bits; 1437 1438 dai->number_configs = 1; 1439 dai->current_config = 0; 1440 private->dai_config = kmemdup(config, size, GFP_KERNEL); 1441 if (!private->dai_config) 1442 return -ENOMEM; 1443 1444 return 0; 1445 } 1446 1447 static int sof_link_alh_load(struct snd_soc_component *scomp, struct snd_sof_dai_link *slink, 1448 struct sof_ipc_dai_config *config, struct snd_sof_dai *dai) 1449 { 1450 struct sof_dai_private_data *private = dai->private; 1451 u32 size = sizeof(*config); 1452 int ret; 1453 1454 /* parse the required set of ALH tokens based on num_hw_cfgs */ 1455 ret = sof_update_ipc_object(scomp, &config->alh, SOF_ALH_TOKENS, slink->tuples, 1456 slink->num_tuples, size, slink->num_hw_configs); 1457 if (ret < 0) 1458 return ret; 1459 1460 /* init IPC */ 1461 config->hdr.size = size; 1462 1463 /* set config for all DAI's with name matching the link name */ 1464 dai->number_configs = 1; 1465 dai->current_config = 0; 1466 private->dai_config = kmemdup(config, size, GFP_KERNEL); 1467 if (!private->dai_config) 1468 return -ENOMEM; 1469 1470 return 0; 1471 } 1472 1473 static int sof_ipc3_widget_setup_comp_dai(struct snd_sof_widget *swidget) 1474 { 1475 struct snd_soc_component *scomp = swidget->scomp; 1476 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); 1477 struct snd_sof_dai *dai = swidget->private; 1478 struct sof_dai_private_data *private; 1479 struct sof_ipc_comp_dai *comp_dai; 1480 size_t ipc_size = sizeof(*comp_dai); 1481 struct sof_ipc_dai_config *config; 1482 struct snd_sof_dai_link *slink; 1483 int ret; 1484 1485 private = kzalloc(sizeof(*private), GFP_KERNEL); 1486 if (!private) 1487 return -ENOMEM; 1488 1489 dai->private = private; 1490 1491 private->comp_dai = sof_comp_alloc(swidget, &ipc_size, swidget->pipeline_id); 1492 if (!private->comp_dai) { 1493 ret = -ENOMEM; 1494 goto free; 1495 } 1496 1497 /* configure dai IPC message */ 1498 comp_dai = private->comp_dai; 1499 comp_dai->comp.type = SOF_COMP_DAI; 1500 comp_dai->config.hdr.size = sizeof(comp_dai->config); 1501 1502 /* parse one set of DAI tokens */ 1503 ret = sof_update_ipc_object(scomp, comp_dai, SOF_DAI_TOKENS, swidget->tuples, 1504 swidget->num_tuples, sizeof(*comp_dai), 1); 1505 if (ret < 0) 1506 goto free_comp; 1507 1508 /* update comp_tokens */ 1509 ret = sof_update_ipc_object(scomp, &comp_dai->config, SOF_COMP_TOKENS, 1510 swidget->tuples, swidget->num_tuples, 1511 sizeof(comp_dai->config), 1); 1512 if (ret < 0) 1513 goto free_comp; 1514 1515 /* Subtract the base to match the FW dai index. */ 1516 if (comp_dai->type == SOF_DAI_INTEL_ALH) { 1517 if (comp_dai->dai_index < INTEL_ALH_DAI_INDEX_BASE) { 1518 dev_err(sdev->dev, 1519 "Invalid ALH dai index %d, only Pin numbers >= %d can be used\n", 1520 comp_dai->dai_index, INTEL_ALH_DAI_INDEX_BASE); 1521 ret = -EINVAL; 1522 goto free_comp; 1523 } 1524 comp_dai->dai_index -= INTEL_ALH_DAI_INDEX_BASE; 1525 } 1526 1527 dev_dbg(scomp->dev, "dai %s: type %d index %d\n", 1528 swidget->widget->name, comp_dai->type, comp_dai->dai_index); 1529 sof_dbg_comp_config(scomp, &comp_dai->config); 1530 1531 /* now update DAI config */ 1532 list_for_each_entry(slink, &sdev->dai_link_list, list) { 1533 struct sof_ipc_dai_config common_config; 1534 int i; 1535 1536 if (strcmp(slink->link->name, dai->name)) 1537 continue; 1538 1539 /* Reserve memory for all hw configs, eventually freed by widget */ 1540 config = kcalloc(slink->num_hw_configs, sizeof(*config), GFP_KERNEL); 1541 if (!config) { 1542 ret = -ENOMEM; 1543 goto free_comp; 1544 } 1545 1546 /* parse one set of DAI link tokens */ 1547 ret = sof_update_ipc_object(scomp, &common_config, SOF_DAI_LINK_TOKENS, 1548 slink->tuples, slink->num_tuples, 1549 sizeof(common_config), 1); 1550 if (ret < 0) 1551 goto free_config; 1552 1553 for (i = 0; i < slink->num_hw_configs; i++) { 1554 config[i].hdr.cmd = SOF_IPC_GLB_DAI_MSG | SOF_IPC_DAI_CONFIG; 1555 config[i].format = le32_to_cpu(slink->hw_configs[i].fmt); 1556 config[i].type = common_config.type; 1557 config[i].dai_index = comp_dai->dai_index; 1558 } 1559 1560 switch (common_config.type) { 1561 case SOF_DAI_INTEL_SSP: 1562 ret = sof_link_ssp_load(scomp, slink, config, dai); 1563 break; 1564 case SOF_DAI_INTEL_DMIC: 1565 ret = sof_link_dmic_load(scomp, slink, config, dai); 1566 break; 1567 case SOF_DAI_INTEL_HDA: 1568 ret = sof_link_hda_load(scomp, slink, config, dai); 1569 break; 1570 case SOF_DAI_INTEL_ALH: 1571 ret = sof_link_alh_load(scomp, slink, config, dai); 1572 break; 1573 case SOF_DAI_IMX_SAI: 1574 ret = sof_link_sai_load(scomp, slink, config, dai); 1575 break; 1576 case SOF_DAI_IMX_ESAI: 1577 ret = sof_link_esai_load(scomp, slink, config, dai); 1578 break; 1579 case SOF_DAI_AMD_BT: 1580 ret = sof_link_acp_bt_load(scomp, slink, config, dai); 1581 break; 1582 case SOF_DAI_AMD_SP: 1583 case SOF_DAI_AMD_SP_VIRTUAL: 1584 ret = sof_link_acp_sp_load(scomp, slink, config, dai); 1585 break; 1586 case SOF_DAI_AMD_HS: 1587 case SOF_DAI_AMD_HS_VIRTUAL: 1588 ret = sof_link_acp_hs_load(scomp, slink, config, dai); 1589 break; 1590 case SOF_DAI_AMD_DMIC: 1591 ret = sof_link_acp_dmic_load(scomp, slink, config, dai); 1592 break; 1593 case SOF_DAI_MEDIATEK_AFE: 1594 ret = sof_link_afe_load(scomp, slink, config, dai); 1595 break; 1596 default: 1597 break; 1598 } 1599 if (ret < 0) { 1600 dev_err(scomp->dev, "failed to load config for dai %s\n", dai->name); 1601 goto free_config; 1602 } 1603 1604 kfree(config); 1605 } 1606 1607 return 0; 1608 free_config: 1609 kfree(config); 1610 free_comp: 1611 kfree(comp_dai); 1612 free: 1613 kfree(private); 1614 dai->private = NULL; 1615 return ret; 1616 } 1617 1618 static void sof_ipc3_widget_free_comp_dai(struct snd_sof_widget *swidget) 1619 { 1620 switch (swidget->id) { 1621 case snd_soc_dapm_dai_in: 1622 case snd_soc_dapm_dai_out: 1623 { 1624 struct snd_sof_dai *dai = swidget->private; 1625 struct sof_dai_private_data *dai_data; 1626 1627 if (!dai) 1628 return; 1629 1630 dai_data = dai->private; 1631 if (dai_data) { 1632 kfree(dai_data->comp_dai); 1633 kfree(dai_data->dai_config); 1634 kfree(dai_data); 1635 } 1636 kfree(dai); 1637 break; 1638 } 1639 default: 1640 break; 1641 } 1642 } 1643 1644 static int sof_ipc3_route_setup(struct snd_sof_dev *sdev, struct snd_sof_route *sroute) 1645 { 1646 struct sof_ipc_pipe_comp_connect connect; 1647 int ret; 1648 1649 connect.hdr.size = sizeof(connect); 1650 connect.hdr.cmd = SOF_IPC_GLB_TPLG_MSG | SOF_IPC_TPLG_COMP_CONNECT; 1651 connect.source_id = sroute->src_widget->comp_id; 1652 connect.sink_id = sroute->sink_widget->comp_id; 1653 1654 dev_dbg(sdev->dev, "setting up route %s -> %s\n", 1655 sroute->src_widget->widget->name, 1656 sroute->sink_widget->widget->name); 1657 1658 /* send ipc */ 1659 ret = sof_ipc_tx_message_no_reply(sdev->ipc, &connect, sizeof(connect)); 1660 if (ret < 0) 1661 dev_err(sdev->dev, "%s: route %s -> %s failed\n", __func__, 1662 sroute->src_widget->widget->name, sroute->sink_widget->widget->name); 1663 1664 return ret; 1665 } 1666 1667 static int sof_ipc3_control_load_bytes(struct snd_sof_dev *sdev, struct snd_sof_control *scontrol) 1668 { 1669 struct sof_ipc_ctrl_data *cdata; 1670 size_t priv_size_check; 1671 int ret; 1672 1673 if (scontrol->max_size < (sizeof(*cdata) + sizeof(struct sof_abi_hdr))) { 1674 dev_err(sdev->dev, "%s: insufficient size for a bytes control: %zu.\n", 1675 __func__, scontrol->max_size); 1676 return -EINVAL; 1677 } 1678 1679 if (scontrol->priv_size > scontrol->max_size - sizeof(*cdata)) { 1680 dev_err(sdev->dev, 1681 "%s: bytes data size %zu exceeds max %zu.\n", __func__, 1682 scontrol->priv_size, scontrol->max_size - sizeof(*cdata)); 1683 return -EINVAL; 1684 } 1685 1686 scontrol->ipc_control_data = kzalloc(scontrol->max_size, GFP_KERNEL); 1687 if (!scontrol->ipc_control_data) 1688 return -ENOMEM; 1689 1690 scontrol->size = sizeof(struct sof_ipc_ctrl_data) + scontrol->priv_size; 1691 1692 cdata = scontrol->ipc_control_data; 1693 cdata->cmd = SOF_CTRL_CMD_BINARY; 1694 cdata->index = scontrol->index; 1695 1696 if (scontrol->priv_size > 0) { 1697 memcpy(cdata->data, scontrol->priv, scontrol->priv_size); 1698 kfree(scontrol->priv); 1699 scontrol->priv = NULL; 1700 1701 if (cdata->data->magic != SOF_ABI_MAGIC) { 1702 dev_err(sdev->dev, "Wrong ABI magic 0x%08x.\n", cdata->data->magic); 1703 ret = -EINVAL; 1704 goto err; 1705 } 1706 1707 if (SOF_ABI_VERSION_INCOMPATIBLE(SOF_ABI_VERSION, cdata->data->abi)) { 1708 dev_err(sdev->dev, "Incompatible ABI version 0x%08x.\n", 1709 cdata->data->abi); 1710 ret = -EINVAL; 1711 goto err; 1712 } 1713 1714 priv_size_check = cdata->data->size + sizeof(struct sof_abi_hdr); 1715 if (priv_size_check != scontrol->priv_size) { 1716 dev_err(sdev->dev, "Conflict in bytes (%zu) vs. priv size (%zu).\n", 1717 priv_size_check, scontrol->priv_size); 1718 ret = -EINVAL; 1719 goto err; 1720 } 1721 } 1722 1723 return 0; 1724 err: 1725 kfree(scontrol->ipc_control_data); 1726 scontrol->ipc_control_data = NULL; 1727 return ret; 1728 } 1729 1730 static int sof_ipc3_control_load_volume(struct snd_sof_dev *sdev, struct snd_sof_control *scontrol) 1731 { 1732 struct sof_ipc_ctrl_data *cdata; 1733 int i; 1734 1735 /* init the volume get/put data */ 1736 scontrol->size = struct_size(cdata, chanv, scontrol->num_channels); 1737 1738 scontrol->ipc_control_data = kzalloc(scontrol->size, GFP_KERNEL); 1739 if (!scontrol->ipc_control_data) 1740 return -ENOMEM; 1741 1742 cdata = scontrol->ipc_control_data; 1743 cdata->index = scontrol->index; 1744 1745 /* set cmd for mixer control */ 1746 if (scontrol->max == 1) { 1747 cdata->cmd = SOF_CTRL_CMD_SWITCH; 1748 return 0; 1749 } 1750 1751 cdata->cmd = SOF_CTRL_CMD_VOLUME; 1752 1753 /* set default volume values to 0dB in control */ 1754 for (i = 0; i < scontrol->num_channels; i++) { 1755 cdata->chanv[i].channel = i; 1756 cdata->chanv[i].value = VOL_ZERO_DB; 1757 } 1758 1759 return 0; 1760 } 1761 1762 static int sof_ipc3_control_load_enum(struct snd_sof_dev *sdev, struct snd_sof_control *scontrol) 1763 { 1764 struct sof_ipc_ctrl_data *cdata; 1765 1766 /* init the enum get/put data */ 1767 scontrol->size = struct_size(cdata, chanv, scontrol->num_channels); 1768 1769 scontrol->ipc_control_data = kzalloc(scontrol->size, GFP_KERNEL); 1770 if (!scontrol->ipc_control_data) 1771 return -ENOMEM; 1772 1773 cdata = scontrol->ipc_control_data; 1774 cdata->index = scontrol->index; 1775 cdata->cmd = SOF_CTRL_CMD_ENUM; 1776 1777 return 0; 1778 } 1779 1780 static int sof_ipc3_control_setup(struct snd_sof_dev *sdev, struct snd_sof_control *scontrol) 1781 { 1782 switch (scontrol->info_type) { 1783 case SND_SOC_TPLG_CTL_VOLSW: 1784 case SND_SOC_TPLG_CTL_VOLSW_SX: 1785 case SND_SOC_TPLG_CTL_VOLSW_XR_SX: 1786 return sof_ipc3_control_load_volume(sdev, scontrol); 1787 case SND_SOC_TPLG_CTL_BYTES: 1788 return sof_ipc3_control_load_bytes(sdev, scontrol); 1789 case SND_SOC_TPLG_CTL_ENUM: 1790 case SND_SOC_TPLG_CTL_ENUM_VALUE: 1791 return sof_ipc3_control_load_enum(sdev, scontrol); 1792 default: 1793 break; 1794 } 1795 1796 return 0; 1797 } 1798 1799 static int sof_ipc3_control_free(struct snd_sof_dev *sdev, struct snd_sof_control *scontrol) 1800 { 1801 struct sof_ipc_free fcomp; 1802 1803 fcomp.hdr.cmd = SOF_IPC_GLB_TPLG_MSG | SOF_IPC_TPLG_COMP_FREE; 1804 fcomp.hdr.size = sizeof(fcomp); 1805 fcomp.id = scontrol->comp_id; 1806 1807 /* send IPC to the DSP */ 1808 return sof_ipc_tx_message_no_reply(sdev->ipc, &fcomp, sizeof(fcomp)); 1809 } 1810 1811 /* send pcm params ipc */ 1812 static int sof_ipc3_keyword_detect_pcm_params(struct snd_sof_widget *swidget, int dir) 1813 { 1814 struct snd_soc_component *scomp = swidget->scomp; 1815 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); 1816 struct snd_pcm_hw_params *params; 1817 struct sof_ipc_pcm_params pcm; 1818 struct snd_sof_pcm *spcm; 1819 int ret; 1820 1821 /* get runtime PCM params using widget's stream name */ 1822 spcm = snd_sof_find_spcm_name(scomp, swidget->widget->sname); 1823 if (!spcm) { 1824 dev_err(scomp->dev, "Cannot find PCM for %s\n", swidget->widget->name); 1825 return -EINVAL; 1826 } 1827 1828 params = &spcm->params[dir]; 1829 1830 /* set IPC PCM params */ 1831 memset(&pcm, 0, sizeof(pcm)); 1832 pcm.hdr.size = sizeof(pcm); 1833 pcm.hdr.cmd = SOF_IPC_GLB_STREAM_MSG | SOF_IPC_STREAM_PCM_PARAMS; 1834 pcm.comp_id = swidget->comp_id; 1835 pcm.params.hdr.size = sizeof(pcm.params); 1836 pcm.params.direction = dir; 1837 pcm.params.sample_valid_bytes = params_width(params) >> 3; 1838 pcm.params.buffer_fmt = SOF_IPC_BUFFER_INTERLEAVED; 1839 pcm.params.rate = params_rate(params); 1840 pcm.params.channels = params_channels(params); 1841 pcm.params.host_period_bytes = params_period_bytes(params); 1842 1843 /* set format */ 1844 switch (params_format(params)) { 1845 case SNDRV_PCM_FORMAT_S16: 1846 pcm.params.frame_fmt = SOF_IPC_FRAME_S16_LE; 1847 break; 1848 case SNDRV_PCM_FORMAT_S24: 1849 pcm.params.frame_fmt = SOF_IPC_FRAME_S24_4LE; 1850 break; 1851 case SNDRV_PCM_FORMAT_S32: 1852 pcm.params.frame_fmt = SOF_IPC_FRAME_S32_LE; 1853 break; 1854 default: 1855 return -EINVAL; 1856 } 1857 1858 /* send IPC to the DSP */ 1859 ret = sof_ipc_tx_message_no_reply(sdev->ipc, &pcm, sizeof(pcm)); 1860 if (ret < 0) 1861 dev_err(scomp->dev, "%s: PCM params failed for %s\n", __func__, 1862 swidget->widget->name); 1863 1864 return ret; 1865 } 1866 1867 /* send stream trigger ipc */ 1868 static int sof_ipc3_keyword_detect_trigger(struct snd_sof_widget *swidget, int cmd) 1869 { 1870 struct snd_soc_component *scomp = swidget->scomp; 1871 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); 1872 struct sof_ipc_stream stream; 1873 int ret; 1874 1875 /* set IPC stream params */ 1876 stream.hdr.size = sizeof(stream); 1877 stream.hdr.cmd = SOF_IPC_GLB_STREAM_MSG | cmd; 1878 stream.comp_id = swidget->comp_id; 1879 1880 /* send IPC to the DSP */ 1881 ret = sof_ipc_tx_message_no_reply(sdev->ipc, &stream, sizeof(stream)); 1882 if (ret < 0) 1883 dev_err(scomp->dev, "%s: Failed to trigger %s\n", __func__, swidget->widget->name); 1884 1885 return ret; 1886 } 1887 1888 static int sof_ipc3_keyword_dapm_event(struct snd_soc_dapm_widget *w, 1889 struct snd_kcontrol *k, int event) 1890 { 1891 struct snd_sof_widget *swidget = w->dobj.private; 1892 struct snd_soc_component *scomp; 1893 int stream = SNDRV_PCM_STREAM_CAPTURE; 1894 struct snd_sof_pcm *spcm; 1895 int ret = 0; 1896 1897 if (!swidget) 1898 return 0; 1899 1900 scomp = swidget->scomp; 1901 1902 dev_dbg(scomp->dev, "received event %d for widget %s\n", 1903 event, w->name); 1904 1905 /* get runtime PCM params using widget's stream name */ 1906 spcm = snd_sof_find_spcm_name(scomp, swidget->widget->sname); 1907 if (!spcm) { 1908 dev_err(scomp->dev, "%s: Cannot find PCM for %s\n", __func__, 1909 swidget->widget->name); 1910 return -EINVAL; 1911 } 1912 1913 /* process events */ 1914 switch (event) { 1915 case SND_SOC_DAPM_PRE_PMU: 1916 if (spcm->stream[stream].suspend_ignored) { 1917 dev_dbg(scomp->dev, "PRE_PMU event ignored, KWD pipeline is already RUNNING\n"); 1918 return 0; 1919 } 1920 1921 /* set pcm params */ 1922 ret = sof_ipc3_keyword_detect_pcm_params(swidget, stream); 1923 if (ret < 0) { 1924 dev_err(scomp->dev, "%s: Failed to set pcm params for widget %s\n", 1925 __func__, swidget->widget->name); 1926 break; 1927 } 1928 1929 /* start trigger */ 1930 ret = sof_ipc3_keyword_detect_trigger(swidget, SOF_IPC_STREAM_TRIG_START); 1931 if (ret < 0) 1932 dev_err(scomp->dev, "%s: Failed to trigger widget %s\n", __func__, 1933 swidget->widget->name); 1934 break; 1935 case SND_SOC_DAPM_POST_PMD: 1936 if (spcm->stream[stream].suspend_ignored) { 1937 dev_dbg(scomp->dev, 1938 "POST_PMD event ignored, KWD pipeline will remain RUNNING\n"); 1939 return 0; 1940 } 1941 1942 /* stop trigger */ 1943 ret = sof_ipc3_keyword_detect_trigger(swidget, SOF_IPC_STREAM_TRIG_STOP); 1944 if (ret < 0) 1945 dev_err(scomp->dev, "%s: Failed to trigger widget %s\n", __func__, 1946 swidget->widget->name); 1947 1948 /* pcm free */ 1949 ret = sof_ipc3_keyword_detect_trigger(swidget, SOF_IPC_STREAM_PCM_FREE); 1950 if (ret < 0) 1951 dev_err(scomp->dev, "%s: Failed to free PCM for widget %s\n", __func__, 1952 swidget->widget->name); 1953 break; 1954 default: 1955 break; 1956 } 1957 1958 return ret; 1959 } 1960 1961 /* event handlers for keyword detect component */ 1962 static const struct snd_soc_tplg_widget_events sof_kwd_events[] = { 1963 {SOF_KEYWORD_DETECT_DAPM_EVENT, sof_ipc3_keyword_dapm_event}, 1964 }; 1965 1966 static int sof_ipc3_widget_bind_event(struct snd_soc_component *scomp, 1967 struct snd_sof_widget *swidget, u16 event_type) 1968 { 1969 struct sof_ipc_comp *ipc_comp; 1970 1971 /* validate widget event type */ 1972 switch (event_type) { 1973 case SOF_KEYWORD_DETECT_DAPM_EVENT: 1974 /* only KEYWORD_DETECT comps should handle this */ 1975 if (swidget->id != snd_soc_dapm_effect) 1976 break; 1977 1978 ipc_comp = swidget->private; 1979 if (ipc_comp && ipc_comp->type != SOF_COMP_KEYWORD_DETECT) 1980 break; 1981 1982 /* bind event to keyword detect comp */ 1983 return snd_soc_tplg_widget_bind_event(swidget->widget, sof_kwd_events, 1984 ARRAY_SIZE(sof_kwd_events), event_type); 1985 default: 1986 break; 1987 } 1988 1989 dev_err(scomp->dev, "Invalid event type %d for widget %s\n", event_type, 1990 swidget->widget->name); 1991 1992 return -EINVAL; 1993 } 1994 1995 static int sof_ipc3_complete_pipeline(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget) 1996 { 1997 struct sof_ipc_pipe_ready ready; 1998 int ret; 1999 2000 dev_dbg(sdev->dev, "tplg: complete pipeline %s id %d\n", 2001 swidget->widget->name, swidget->comp_id); 2002 2003 memset(&ready, 0, sizeof(ready)); 2004 ready.hdr.size = sizeof(ready); 2005 ready.hdr.cmd = SOF_IPC_GLB_TPLG_MSG | SOF_IPC_TPLG_PIPE_COMPLETE; 2006 ready.comp_id = swidget->comp_id; 2007 2008 ret = sof_ipc_tx_message_no_reply(sdev->ipc, &ready, sizeof(ready)); 2009 if (ret < 0) 2010 return ret; 2011 2012 return 1; 2013 } 2014 2015 static int sof_ipc3_widget_free(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget) 2016 { 2017 struct sof_ipc_free ipc_free = { 2018 .hdr = { 2019 .size = sizeof(ipc_free), 2020 .cmd = SOF_IPC_GLB_TPLG_MSG, 2021 }, 2022 .id = swidget->comp_id, 2023 }; 2024 int ret; 2025 2026 if (!swidget->private) 2027 return 0; 2028 2029 switch (swidget->id) { 2030 case snd_soc_dapm_scheduler: 2031 { 2032 ipc_free.hdr.cmd |= SOF_IPC_TPLG_PIPE_FREE; 2033 break; 2034 } 2035 case snd_soc_dapm_buffer: 2036 ipc_free.hdr.cmd |= SOF_IPC_TPLG_BUFFER_FREE; 2037 break; 2038 default: 2039 ipc_free.hdr.cmd |= SOF_IPC_TPLG_COMP_FREE; 2040 break; 2041 } 2042 2043 ret = sof_ipc_tx_message_no_reply(sdev->ipc, &ipc_free, sizeof(ipc_free)); 2044 if (ret < 0) 2045 dev_err(sdev->dev, "failed to free widget %s\n", swidget->widget->name); 2046 2047 return ret; 2048 } 2049 2050 static int sof_ipc3_dai_config(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget, 2051 unsigned int flags, struct snd_sof_dai_config_data *data) 2052 { 2053 struct sof_ipc_fw_version *v = &sdev->fw_ready.version; 2054 struct snd_sof_dai *dai = swidget->private; 2055 struct sof_dai_private_data *private; 2056 struct sof_ipc_dai_config *config; 2057 int ret = 0; 2058 2059 if (!dai || !dai->private) { 2060 dev_err(sdev->dev, "No private data for DAI %s\n", swidget->widget->name); 2061 return -EINVAL; 2062 } 2063 2064 private = dai->private; 2065 if (!private->dai_config) { 2066 dev_err(sdev->dev, "No config for DAI %s\n", dai->name); 2067 return -EINVAL; 2068 } 2069 2070 config = &private->dai_config[dai->current_config]; 2071 if (!config) { 2072 dev_err(sdev->dev, "Invalid current config for DAI %s\n", dai->name); 2073 return -EINVAL; 2074 } 2075 2076 switch (config->type) { 2077 case SOF_DAI_INTEL_SSP: 2078 /* 2079 * DAI_CONFIG IPC during hw_params/hw_free for SSP DAI's is not supported in older 2080 * firmware 2081 */ 2082 if (v->abi_version < SOF_ABI_VER(3, 18, 0) && 2083 ((flags & SOF_DAI_CONFIG_FLAGS_HW_PARAMS) || 2084 (flags & SOF_DAI_CONFIG_FLAGS_HW_FREE))) 2085 return 0; 2086 break; 2087 case SOF_DAI_INTEL_HDA: 2088 if (data) 2089 config->hda.link_dma_ch = data->dai_data; 2090 break; 2091 case SOF_DAI_INTEL_ALH: 2092 if (data) { 2093 /* save the dai_index during hw_params and reuse it for hw_free */ 2094 if (flags & SOF_DAI_CONFIG_FLAGS_HW_PARAMS) { 2095 /* Subtract the base to match the FW dai index. */ 2096 if (data->dai_index < INTEL_ALH_DAI_INDEX_BASE) { 2097 dev_err(sdev->dev, 2098 "Invalid ALH dai index %d, only Pin numbers >= %d can be used\n", 2099 config->dai_index, INTEL_ALH_DAI_INDEX_BASE); 2100 return -EINVAL; 2101 } 2102 config->dai_index = data->dai_index - INTEL_ALH_DAI_INDEX_BASE; 2103 } 2104 config->alh.stream_id = data->dai_data; 2105 } 2106 break; 2107 default: 2108 break; 2109 } 2110 2111 /* 2112 * The dai_config op is invoked several times and the flags argument varies as below: 2113 * BE DAI hw_params: When the op is invoked during the BE DAI hw_params, flags contains 2114 * SOF_DAI_CONFIG_FLAGS_HW_PARAMS along with quirks 2115 * FE DAI hw_params: When invoked during FE DAI hw_params after the DAI widget has 2116 * just been set up in the DSP, flags is set to SOF_DAI_CONFIG_FLAGS_HW_PARAMS with no 2117 * quirks 2118 * BE DAI trigger: When invoked during the BE DAI trigger, flags is set to 2119 * SOF_DAI_CONFIG_FLAGS_PAUSE and contains no quirks 2120 * BE DAI hw_free: When invoked during the BE DAI hw_free, flags is set to 2121 * SOF_DAI_CONFIG_FLAGS_HW_FREE and contains no quirks 2122 * FE DAI hw_free: When invoked during the FE DAI hw_free, flags is set to 2123 * SOF_DAI_CONFIG_FLAGS_HW_FREE and contains no quirks 2124 * 2125 * The DAI_CONFIG IPC is sent to the DSP, only after the widget is set up during the FE 2126 * DAI hw_params. But since the BE DAI hw_params precedes the FE DAI hw_params, the quirks 2127 * need to be preserved when assigning the flags before sending the IPC. 2128 * For the case of PAUSE/HW_FREE, since there are no quirks, flags can be used as is. 2129 */ 2130 2131 if (flags & SOF_DAI_CONFIG_FLAGS_HW_PARAMS) { 2132 /* Clear stale command */ 2133 config->flags &= ~SOF_DAI_CONFIG_FLAGS_CMD_MASK; 2134 config->flags |= flags; 2135 } else { 2136 config->flags = flags; 2137 } 2138 2139 /* only send the IPC if the widget is set up in the DSP */ 2140 if (swidget->use_count > 0) { 2141 ret = sof_ipc_tx_message_no_reply(sdev->ipc, config, config->hdr.size); 2142 if (ret < 0) 2143 dev_err(sdev->dev, "Failed to set dai config for %s\n", dai->name); 2144 2145 /* clear the flags once the IPC has been sent even if it fails */ 2146 config->flags = SOF_DAI_CONFIG_FLAGS_NONE; 2147 } 2148 2149 return ret; 2150 } 2151 2152 static int sof_ipc3_widget_setup(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget) 2153 { 2154 int ret; 2155 2156 if (!swidget->private) 2157 return 0; 2158 2159 switch (swidget->id) { 2160 case snd_soc_dapm_dai_in: 2161 case snd_soc_dapm_dai_out: 2162 { 2163 struct snd_sof_dai *dai = swidget->private; 2164 struct sof_dai_private_data *dai_data = dai->private; 2165 struct sof_ipc_comp *comp = &dai_data->comp_dai->comp; 2166 2167 ret = sof_ipc_tx_message_no_reply(sdev->ipc, dai_data->comp_dai, comp->hdr.size); 2168 break; 2169 } 2170 case snd_soc_dapm_scheduler: 2171 { 2172 struct sof_ipc_pipe_new *pipeline; 2173 2174 pipeline = swidget->private; 2175 ret = sof_ipc_tx_message_no_reply(sdev->ipc, pipeline, sizeof(*pipeline)); 2176 break; 2177 } 2178 default: 2179 { 2180 struct sof_ipc_cmd_hdr *hdr; 2181 2182 hdr = swidget->private; 2183 ret = sof_ipc_tx_message_no_reply(sdev->ipc, swidget->private, hdr->size); 2184 break; 2185 } 2186 } 2187 if (ret < 0) 2188 dev_err(sdev->dev, "Failed to setup widget %s\n", swidget->widget->name); 2189 2190 return ret; 2191 } 2192 2193 static int sof_ipc3_set_up_all_pipelines(struct snd_sof_dev *sdev, bool verify) 2194 { 2195 struct sof_ipc_fw_version *v = &sdev->fw_ready.version; 2196 struct snd_sof_widget *swidget; 2197 struct snd_sof_route *sroute; 2198 int ret; 2199 2200 /* restore pipeline components */ 2201 list_for_each_entry(swidget, &sdev->widget_list, list) { 2202 /* only set up the widgets belonging to static pipelines */ 2203 if (!verify && swidget->dynamic_pipeline_widget) 2204 continue; 2205 2206 /* 2207 * For older firmware, skip scheduler widgets in this loop, 2208 * sof_widget_setup() will be called in the 'complete pipeline' loop 2209 */ 2210 if (v->abi_version < SOF_ABI_VER(3, 19, 0) && 2211 swidget->id == snd_soc_dapm_scheduler) 2212 continue; 2213 2214 /* update DAI config. The IPC will be sent in sof_widget_setup() */ 2215 if (WIDGET_IS_DAI(swidget->id)) { 2216 struct snd_sof_dai *dai = swidget->private; 2217 struct sof_dai_private_data *private; 2218 struct sof_ipc_dai_config *config; 2219 2220 if (!dai || !dai->private) 2221 continue; 2222 private = dai->private; 2223 if (!private->dai_config) 2224 continue; 2225 2226 config = private->dai_config; 2227 /* 2228 * The link DMA channel would be invalidated for running 2229 * streams but not for streams that were in the PAUSED 2230 * state during suspend. So invalidate it here before setting 2231 * the dai config in the DSP. 2232 */ 2233 if (config->type == SOF_DAI_INTEL_HDA) 2234 config->hda.link_dma_ch = DMA_CHAN_INVALID; 2235 } 2236 2237 ret = sof_widget_setup(sdev, swidget); 2238 if (ret < 0) 2239 return ret; 2240 } 2241 2242 /* restore pipeline connections */ 2243 list_for_each_entry(sroute, &sdev->route_list, list) { 2244 /* only set up routes belonging to static pipelines */ 2245 if (!verify && (sroute->src_widget->dynamic_pipeline_widget || 2246 sroute->sink_widget->dynamic_pipeline_widget)) 2247 continue; 2248 2249 /* 2250 * For virtual routes, both sink and source are not buffer. IPC3 only supports 2251 * connections between a buffer and a component. Ignore the rest. 2252 */ 2253 if (sroute->src_widget->id != snd_soc_dapm_buffer && 2254 sroute->sink_widget->id != snd_soc_dapm_buffer) 2255 continue; 2256 2257 ret = sof_route_setup(sdev, sroute->src_widget->widget, 2258 sroute->sink_widget->widget); 2259 if (ret < 0) { 2260 dev_err(sdev->dev, "%s: route set up failed\n", __func__); 2261 return ret; 2262 } 2263 } 2264 2265 /* complete pipeline */ 2266 list_for_each_entry(swidget, &sdev->widget_list, list) { 2267 switch (swidget->id) { 2268 case snd_soc_dapm_scheduler: 2269 /* only complete static pipelines */ 2270 if (!verify && swidget->dynamic_pipeline_widget) 2271 continue; 2272 2273 if (v->abi_version < SOF_ABI_VER(3, 19, 0)) { 2274 ret = sof_widget_setup(sdev, swidget); 2275 if (ret < 0) 2276 return ret; 2277 } 2278 2279 swidget->spipe->complete = sof_ipc3_complete_pipeline(sdev, swidget); 2280 if (swidget->spipe->complete < 0) 2281 return swidget->spipe->complete; 2282 break; 2283 default: 2284 break; 2285 } 2286 } 2287 2288 return 0; 2289 } 2290 2291 /* 2292 * Free the PCM, its associated widgets and set the prepared flag to false for all PCMs that 2293 * did not get suspended(ex: paused streams) so the widgets can be set up again during resume. 2294 */ 2295 static int sof_tear_down_left_over_pipelines(struct snd_sof_dev *sdev) 2296 { 2297 struct snd_sof_widget *swidget; 2298 struct snd_sof_pcm *spcm; 2299 int dir, ret; 2300 2301 /* 2302 * free all PCMs and their associated DAPM widgets if their connected DAPM widget 2303 * list is not NULL. This should only be true for paused streams at this point. 2304 * This is equivalent to the handling of FE DAI suspend trigger for running streams. 2305 */ 2306 list_for_each_entry(spcm, &sdev->pcm_list, list) { 2307 for_each_pcm_streams(dir) { 2308 struct snd_pcm_substream *substream = spcm->stream[dir].substream; 2309 2310 if (!substream || !substream->runtime || spcm->stream[dir].suspend_ignored) 2311 continue; 2312 2313 if (spcm->stream[dir].list) { 2314 ret = sof_pcm_stream_free(sdev, substream, spcm, dir, true); 2315 if (ret < 0) 2316 return ret; 2317 } 2318 } 2319 } 2320 2321 /* 2322 * free any left over DAI widgets. This is equivalent to the handling of suspend trigger 2323 * for the BE DAI for running streams. 2324 */ 2325 list_for_each_entry(swidget, &sdev->widget_list, list) 2326 if (WIDGET_IS_DAI(swidget->id) && swidget->use_count == 1) { 2327 ret = sof_widget_free(sdev, swidget); 2328 if (ret < 0) 2329 return ret; 2330 } 2331 2332 return 0; 2333 } 2334 2335 static int sof_ipc3_free_widgets_in_list(struct snd_sof_dev *sdev, bool include_scheduler, 2336 bool *dyn_widgets, bool verify) 2337 { 2338 struct sof_ipc_fw_version *v = &sdev->fw_ready.version; 2339 struct snd_sof_widget *swidget; 2340 int ret; 2341 2342 list_for_each_entry(swidget, &sdev->widget_list, list) { 2343 if (swidget->dynamic_pipeline_widget) { 2344 *dyn_widgets = true; 2345 continue; 2346 } 2347 2348 /* Do not free widgets for static pipelines with FW older than SOF2.2 */ 2349 if (!verify && !swidget->dynamic_pipeline_widget && 2350 SOF_FW_VER(v->major, v->minor, v->micro) < SOF_FW_VER(2, 2, 0)) { 2351 mutex_lock(&swidget->setup_mutex); 2352 swidget->use_count = 0; 2353 mutex_unlock(&swidget->setup_mutex); 2354 if (swidget->spipe) 2355 swidget->spipe->complete = 0; 2356 continue; 2357 } 2358 2359 if (include_scheduler && swidget->id != snd_soc_dapm_scheduler) 2360 continue; 2361 2362 if (!include_scheduler && swidget->id == snd_soc_dapm_scheduler) 2363 continue; 2364 2365 ret = sof_widget_free(sdev, swidget); 2366 if (ret < 0) 2367 return ret; 2368 } 2369 2370 return 0; 2371 } 2372 2373 /* 2374 * For older firmware, this function doesn't free widgets for static pipelines during suspend. 2375 * It only resets use_count for all widgets. 2376 */ 2377 static int sof_ipc3_tear_down_all_pipelines(struct snd_sof_dev *sdev, bool verify) 2378 { 2379 struct sof_ipc_fw_version *v = &sdev->fw_ready.version; 2380 struct snd_sof_widget *swidget; 2381 struct snd_sof_route *sroute; 2382 bool dyn_widgets = false; 2383 int ret; 2384 2385 /* 2386 * This function is called during suspend and for one-time topology verification during 2387 * first boot. In both cases, there is no need to protect swidget->use_count and 2388 * sroute->setup because during suspend all running streams are suspended and during 2389 * topology loading the sound card unavailable to open PCMs. Do not free the scheduler 2390 * widgets yet so that the secondary cores do not get powered down before all the widgets 2391 * associated with the scheduler are freed. 2392 */ 2393 ret = sof_ipc3_free_widgets_in_list(sdev, false, &dyn_widgets, verify); 2394 if (ret < 0) 2395 return ret; 2396 2397 /* free all the scheduler widgets now */ 2398 ret = sof_ipc3_free_widgets_in_list(sdev, true, &dyn_widgets, verify); 2399 if (ret < 0) 2400 return ret; 2401 2402 /* 2403 * Tear down all pipelines associated with PCMs that did not get suspended 2404 * and unset the prepare flag so that they can be set up again during resume. 2405 * Skip this step for older firmware unless topology has any 2406 * dynamic pipeline (in which case the step is mandatory). 2407 */ 2408 if (!verify && (dyn_widgets || SOF_FW_VER(v->major, v->minor, v->micro) >= 2409 SOF_FW_VER(2, 2, 0))) { 2410 ret = sof_tear_down_left_over_pipelines(sdev); 2411 if (ret < 0) { 2412 dev_err(sdev->dev, "failed to tear down paused pipelines\n"); 2413 return ret; 2414 } 2415 } 2416 2417 list_for_each_entry(sroute, &sdev->route_list, list) 2418 sroute->setup = false; 2419 2420 /* 2421 * before suspending, make sure the refcounts are all zeroed out. There's no way 2422 * to recover at this point but this will help root cause bad sequences leading to 2423 * more issues on resume 2424 */ 2425 list_for_each_entry(swidget, &sdev->widget_list, list) { 2426 if (swidget->use_count != 0) { 2427 dev_err(sdev->dev, "%s: widget %s is still in use: count %d\n", 2428 __func__, swidget->widget->name, swidget->use_count); 2429 } 2430 } 2431 2432 return 0; 2433 } 2434 2435 static int sof_ipc3_dai_get_clk(struct snd_sof_dev *sdev, struct snd_sof_dai *dai, int clk_type) 2436 { 2437 struct sof_dai_private_data *private = dai->private; 2438 2439 if (!private || !private->dai_config) 2440 return 0; 2441 2442 switch (private->dai_config->type) { 2443 case SOF_DAI_INTEL_SSP: 2444 switch (clk_type) { 2445 case SOF_DAI_CLK_INTEL_SSP_MCLK: 2446 return private->dai_config->ssp.mclk_rate; 2447 case SOF_DAI_CLK_INTEL_SSP_BCLK: 2448 return private->dai_config->ssp.bclk_rate; 2449 default: 2450 break; 2451 } 2452 dev_err(sdev->dev, "fail to get SSP clk %d rate\n", clk_type); 2453 break; 2454 default: 2455 /* not yet implemented for platforms other than the above */ 2456 dev_err(sdev->dev, "DAI type %d not supported yet!\n", private->dai_config->type); 2457 break; 2458 } 2459 2460 return -EINVAL; 2461 } 2462 2463 static int sof_ipc3_parse_manifest(struct snd_soc_component *scomp, int index, 2464 struct snd_soc_tplg_manifest *man) 2465 { 2466 u32 size = le32_to_cpu(man->priv.size); 2467 u32 abi_version; 2468 2469 /* backward compatible with tplg without ABI info */ 2470 if (!size) { 2471 dev_dbg(scomp->dev, "No topology ABI info\n"); 2472 return 0; 2473 } 2474 2475 if (size != SOF_IPC3_TPLG_ABI_SIZE) { 2476 dev_err(scomp->dev, "%s: Invalid topology ABI size: %u\n", 2477 __func__, size); 2478 return -EINVAL; 2479 } 2480 2481 dev_info(scomp->dev, 2482 "Topology: ABI %d:%d:%d Kernel ABI %d:%d:%d\n", 2483 man->priv.data[0], man->priv.data[1], man->priv.data[2], 2484 SOF_ABI_MAJOR, SOF_ABI_MINOR, SOF_ABI_PATCH); 2485 2486 abi_version = SOF_ABI_VER(man->priv.data[0], man->priv.data[1], man->priv.data[2]); 2487 2488 if (SOF_ABI_VERSION_INCOMPATIBLE(SOF_ABI_VERSION, abi_version)) { 2489 dev_err(scomp->dev, "%s: Incompatible topology ABI version\n", __func__); 2490 return -EINVAL; 2491 } 2492 2493 if (IS_ENABLED(CONFIG_SND_SOC_SOF_STRICT_ABI_CHECKS) && 2494 SOF_ABI_VERSION_MINOR(abi_version) > SOF_ABI_MINOR) { 2495 dev_err(scomp->dev, "%s: Topology ABI is more recent than kernel\n", __func__); 2496 return -EINVAL; 2497 } 2498 2499 return 0; 2500 } 2501 2502 static int sof_ipc3_link_setup(struct snd_sof_dev *sdev, struct snd_soc_dai_link *link) 2503 { 2504 if (link->no_pcm) 2505 return 0; 2506 2507 /* 2508 * set default trigger order for all links. Exceptions to 2509 * the rule will be handled in sof_pcm_dai_link_fixup() 2510 * For playback, the sequence is the following: start FE, 2511 * start BE, stop BE, stop FE; for Capture the sequence is 2512 * inverted start BE, start FE, stop FE, stop BE 2513 */ 2514 link->trigger[SNDRV_PCM_STREAM_PLAYBACK] = SND_SOC_DPCM_TRIGGER_PRE; 2515 link->trigger[SNDRV_PCM_STREAM_CAPTURE] = SND_SOC_DPCM_TRIGGER_POST; 2516 2517 return 0; 2518 } 2519 2520 /* token list for each topology object */ 2521 static enum sof_tokens host_token_list[] = { 2522 SOF_CORE_TOKENS, 2523 SOF_COMP_EXT_TOKENS, 2524 SOF_PCM_TOKENS, 2525 SOF_COMP_TOKENS, 2526 }; 2527 2528 static enum sof_tokens comp_generic_token_list[] = { 2529 SOF_CORE_TOKENS, 2530 SOF_COMP_EXT_TOKENS, 2531 SOF_COMP_TOKENS, 2532 }; 2533 2534 static enum sof_tokens buffer_token_list[] = { 2535 SOF_BUFFER_TOKENS, 2536 }; 2537 2538 static enum sof_tokens pipeline_token_list[] = { 2539 SOF_CORE_TOKENS, 2540 SOF_COMP_EXT_TOKENS, 2541 SOF_PIPELINE_TOKENS, 2542 SOF_SCHED_TOKENS, 2543 }; 2544 2545 static enum sof_tokens asrc_token_list[] = { 2546 SOF_CORE_TOKENS, 2547 SOF_COMP_EXT_TOKENS, 2548 SOF_ASRC_TOKENS, 2549 SOF_COMP_TOKENS, 2550 }; 2551 2552 static enum sof_tokens src_token_list[] = { 2553 SOF_CORE_TOKENS, 2554 SOF_COMP_EXT_TOKENS, 2555 SOF_SRC_TOKENS, 2556 SOF_COMP_TOKENS 2557 }; 2558 2559 static enum sof_tokens pga_token_list[] = { 2560 SOF_CORE_TOKENS, 2561 SOF_COMP_EXT_TOKENS, 2562 SOF_VOLUME_TOKENS, 2563 SOF_COMP_TOKENS, 2564 }; 2565 2566 static enum sof_tokens dai_token_list[] = { 2567 SOF_CORE_TOKENS, 2568 SOF_COMP_EXT_TOKENS, 2569 SOF_DAI_TOKENS, 2570 SOF_COMP_TOKENS, 2571 }; 2572 2573 static enum sof_tokens process_token_list[] = { 2574 SOF_CORE_TOKENS, 2575 SOF_COMP_EXT_TOKENS, 2576 SOF_PROCESS_TOKENS, 2577 SOF_COMP_TOKENS, 2578 }; 2579 2580 static const struct sof_ipc_tplg_widget_ops tplg_ipc3_widget_ops[SND_SOC_DAPM_TYPE_COUNT] = { 2581 [snd_soc_dapm_aif_in] = {sof_ipc3_widget_setup_comp_host, sof_ipc3_widget_free_comp, 2582 host_token_list, ARRAY_SIZE(host_token_list), NULL}, 2583 [snd_soc_dapm_aif_out] = {sof_ipc3_widget_setup_comp_host, sof_ipc3_widget_free_comp, 2584 host_token_list, ARRAY_SIZE(host_token_list), NULL}, 2585 2586 [snd_soc_dapm_dai_in] = {sof_ipc3_widget_setup_comp_dai, sof_ipc3_widget_free_comp_dai, 2587 dai_token_list, ARRAY_SIZE(dai_token_list), NULL}, 2588 [snd_soc_dapm_dai_out] = {sof_ipc3_widget_setup_comp_dai, sof_ipc3_widget_free_comp_dai, 2589 dai_token_list, ARRAY_SIZE(dai_token_list), NULL}, 2590 [snd_soc_dapm_buffer] = {sof_ipc3_widget_setup_comp_buffer, sof_ipc3_widget_free_comp, 2591 buffer_token_list, ARRAY_SIZE(buffer_token_list), NULL}, 2592 [snd_soc_dapm_mixer] = {sof_ipc3_widget_setup_comp_mixer, sof_ipc3_widget_free_comp, 2593 comp_generic_token_list, ARRAY_SIZE(comp_generic_token_list), 2594 NULL}, 2595 [snd_soc_dapm_src] = {sof_ipc3_widget_setup_comp_src, sof_ipc3_widget_free_comp, 2596 src_token_list, ARRAY_SIZE(src_token_list), NULL}, 2597 [snd_soc_dapm_asrc] = {sof_ipc3_widget_setup_comp_asrc, sof_ipc3_widget_free_comp, 2598 asrc_token_list, ARRAY_SIZE(asrc_token_list), NULL}, 2599 [snd_soc_dapm_siggen] = {sof_ipc3_widget_setup_comp_tone, sof_ipc3_widget_free_comp, 2600 comp_generic_token_list, ARRAY_SIZE(comp_generic_token_list), 2601 NULL}, 2602 [snd_soc_dapm_scheduler] = {sof_ipc3_widget_setup_comp_pipeline, sof_ipc3_widget_free_comp, 2603 pipeline_token_list, ARRAY_SIZE(pipeline_token_list), NULL}, 2604 [snd_soc_dapm_pga] = {sof_ipc3_widget_setup_comp_pga, sof_ipc3_widget_free_comp, 2605 pga_token_list, ARRAY_SIZE(pga_token_list), NULL}, 2606 [snd_soc_dapm_mux] = {sof_ipc3_widget_setup_comp_mux, sof_ipc3_widget_free_comp, 2607 comp_generic_token_list, ARRAY_SIZE(comp_generic_token_list), NULL}, 2608 [snd_soc_dapm_demux] = {sof_ipc3_widget_setup_comp_mux, sof_ipc3_widget_free_comp, 2609 comp_generic_token_list, ARRAY_SIZE(comp_generic_token_list), 2610 NULL}, 2611 [snd_soc_dapm_effect] = {sof_widget_update_ipc_comp_process, sof_ipc3_widget_free_comp, 2612 process_token_list, ARRAY_SIZE(process_token_list), 2613 sof_ipc3_widget_bind_event}, 2614 }; 2615 2616 const struct sof_ipc_tplg_ops ipc3_tplg_ops = { 2617 .widget = tplg_ipc3_widget_ops, 2618 .control = &tplg_ipc3_control_ops, 2619 .route_setup = sof_ipc3_route_setup, 2620 .control_setup = sof_ipc3_control_setup, 2621 .control_free = sof_ipc3_control_free, 2622 .pipeline_complete = sof_ipc3_complete_pipeline, 2623 .token_list = ipc3_token_list, 2624 .widget_free = sof_ipc3_widget_free, 2625 .widget_setup = sof_ipc3_widget_setup, 2626 .dai_config = sof_ipc3_dai_config, 2627 .dai_get_clk = sof_ipc3_dai_get_clk, 2628 .set_up_all_pipelines = sof_ipc3_set_up_all_pipelines, 2629 .tear_down_all_pipelines = sof_ipc3_tear_down_all_pipelines, 2630 .parse_manifest = sof_ipc3_parse_manifest, 2631 .link_setup = sof_ipc3_link_setup, 2632 }; 2633