1 // SPDX-License-Identifier: (GPL-2.0 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) 2018 Intel Corporation. All rights reserved. 7 // 8 // Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> 9 // 10 11 #include <linux/firmware.h> 12 #include <linux/workqueue.h> 13 #include <sound/tlv.h> 14 #include <sound/pcm_params.h> 15 #include <uapi/sound/sof/tokens.h> 16 #include "sof-priv.h" 17 #include "sof-audio.h" 18 #include "ops.h" 19 20 #define COMP_ID_UNASSIGNED 0xffffffff 21 /* 22 * Constants used in the computation of linear volume gain 23 * from dB gain 20th root of 10 in Q1.16 fixed-point notation 24 */ 25 #define VOL_TWENTIETH_ROOT_OF_TEN 73533 26 /* 40th root of 10 in Q1.16 fixed-point notation*/ 27 #define VOL_FORTIETH_ROOT_OF_TEN 69419 28 /* 29 * Volume fractional word length define to 16 sets 30 * the volume linear gain value to use Qx.16 format 31 */ 32 #define VOLUME_FWL 16 33 /* 0.5 dB step value in topology TLV */ 34 #define VOL_HALF_DB_STEP 50 35 /* Full volume for default values */ 36 #define VOL_ZERO_DB BIT(VOLUME_FWL) 37 38 /* TLV data items */ 39 #define TLV_ITEMS 3 40 #define TLV_MIN 0 41 #define TLV_STEP 1 42 #define TLV_MUTE 2 43 44 /* size of tplg abi in byte */ 45 #define SOF_TPLG_ABI_SIZE 3 46 47 struct sof_widget_data { 48 int ctrl_type; 49 int ipc_cmd; 50 struct sof_abi_hdr *pdata; 51 struct snd_sof_control *control; 52 }; 53 54 /* send pcm params ipc */ 55 static int ipc_pcm_params(struct snd_sof_widget *swidget, int dir) 56 { 57 struct sof_ipc_pcm_params_reply ipc_params_reply; 58 struct snd_soc_component *scomp = swidget->scomp; 59 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); 60 struct sof_ipc_pcm_params pcm; 61 struct snd_pcm_hw_params *params; 62 struct snd_sof_pcm *spcm; 63 int ret = 0; 64 65 memset(&pcm, 0, sizeof(pcm)); 66 67 /* get runtime PCM params using widget's stream name */ 68 spcm = snd_sof_find_spcm_name(scomp, swidget->widget->sname); 69 if (!spcm) { 70 dev_err(scomp->dev, "error: cannot find PCM for %s\n", 71 swidget->widget->name); 72 return -EINVAL; 73 } 74 75 params = &spcm->params[dir]; 76 77 /* set IPC PCM params */ 78 pcm.hdr.size = sizeof(pcm); 79 pcm.hdr.cmd = SOF_IPC_GLB_STREAM_MSG | SOF_IPC_STREAM_PCM_PARAMS; 80 pcm.comp_id = swidget->comp_id; 81 pcm.params.hdr.size = sizeof(pcm.params); 82 pcm.params.direction = dir; 83 pcm.params.sample_valid_bytes = params_width(params) >> 3; 84 pcm.params.buffer_fmt = SOF_IPC_BUFFER_INTERLEAVED; 85 pcm.params.rate = params_rate(params); 86 pcm.params.channels = params_channels(params); 87 pcm.params.host_period_bytes = params_period_bytes(params); 88 89 /* set format */ 90 switch (params_format(params)) { 91 case SNDRV_PCM_FORMAT_S16: 92 pcm.params.frame_fmt = SOF_IPC_FRAME_S16_LE; 93 break; 94 case SNDRV_PCM_FORMAT_S24: 95 pcm.params.frame_fmt = SOF_IPC_FRAME_S24_4LE; 96 break; 97 case SNDRV_PCM_FORMAT_S32: 98 pcm.params.frame_fmt = SOF_IPC_FRAME_S32_LE; 99 break; 100 default: 101 return -EINVAL; 102 } 103 104 /* send IPC to the DSP */ 105 ret = sof_ipc_tx_message(sdev->ipc, pcm.hdr.cmd, &pcm, sizeof(pcm), 106 &ipc_params_reply, sizeof(ipc_params_reply)); 107 if (ret < 0) 108 dev_err(scomp->dev, "error: pcm params failed for %s\n", 109 swidget->widget->name); 110 111 return ret; 112 } 113 114 /* send stream trigger ipc */ 115 static int ipc_trigger(struct snd_sof_widget *swidget, int cmd) 116 { 117 struct snd_soc_component *scomp = swidget->scomp; 118 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); 119 struct sof_ipc_stream stream; 120 struct sof_ipc_reply reply; 121 int ret = 0; 122 123 /* set IPC stream params */ 124 stream.hdr.size = sizeof(stream); 125 stream.hdr.cmd = SOF_IPC_GLB_STREAM_MSG | cmd; 126 stream.comp_id = swidget->comp_id; 127 128 /* send IPC to the DSP */ 129 ret = sof_ipc_tx_message(sdev->ipc, stream.hdr.cmd, &stream, 130 sizeof(stream), &reply, sizeof(reply)); 131 if (ret < 0) 132 dev_err(scomp->dev, "error: failed to trigger %s\n", 133 swidget->widget->name); 134 135 return ret; 136 } 137 138 static int sof_keyword_dapm_event(struct snd_soc_dapm_widget *w, 139 struct snd_kcontrol *k, int event) 140 { 141 struct snd_sof_widget *swidget = w->dobj.private; 142 struct snd_soc_component *scomp; 143 int stream = SNDRV_PCM_STREAM_CAPTURE; 144 struct snd_sof_pcm *spcm; 145 int ret = 0; 146 147 if (!swidget) 148 return 0; 149 150 scomp = swidget->scomp; 151 152 dev_dbg(scomp->dev, "received event %d for widget %s\n", 153 event, w->name); 154 155 /* get runtime PCM params using widget's stream name */ 156 spcm = snd_sof_find_spcm_name(scomp, swidget->widget->sname); 157 if (!spcm) { 158 dev_err(scomp->dev, "error: cannot find PCM for %s\n", 159 swidget->widget->name); 160 return -EINVAL; 161 } 162 163 /* process events */ 164 switch (event) { 165 case SND_SOC_DAPM_PRE_PMU: 166 if (spcm->stream[stream].suspend_ignored) { 167 dev_dbg(scomp->dev, "PRE_PMU event ignored, KWD pipeline is already RUNNING\n"); 168 return 0; 169 } 170 171 /* set pcm params */ 172 ret = ipc_pcm_params(swidget, stream); 173 if (ret < 0) { 174 dev_err(scomp->dev, 175 "error: failed to set pcm params for widget %s\n", 176 swidget->widget->name); 177 break; 178 } 179 180 /* start trigger */ 181 ret = ipc_trigger(swidget, SOF_IPC_STREAM_TRIG_START); 182 if (ret < 0) 183 dev_err(scomp->dev, 184 "error: failed to trigger widget %s\n", 185 swidget->widget->name); 186 break; 187 case SND_SOC_DAPM_POST_PMD: 188 if (spcm->stream[stream].suspend_ignored) { 189 dev_dbg(scomp->dev, "POST_PMD even ignored, KWD pipeline will remain RUNNING\n"); 190 return 0; 191 } 192 193 /* stop trigger */ 194 ret = ipc_trigger(swidget, SOF_IPC_STREAM_TRIG_STOP); 195 if (ret < 0) 196 dev_err(scomp->dev, 197 "error: failed to trigger widget %s\n", 198 swidget->widget->name); 199 200 /* pcm free */ 201 ret = ipc_trigger(swidget, SOF_IPC_STREAM_PCM_FREE); 202 if (ret < 0) 203 dev_err(scomp->dev, 204 "error: failed to trigger widget %s\n", 205 swidget->widget->name); 206 break; 207 default: 208 break; 209 } 210 211 return ret; 212 } 213 214 /* event handlers for keyword detect component */ 215 static const struct snd_soc_tplg_widget_events sof_kwd_events[] = { 216 {SOF_KEYWORD_DETECT_DAPM_EVENT, sof_keyword_dapm_event}, 217 }; 218 219 static inline int get_tlv_data(const int *p, int tlv[TLV_ITEMS]) 220 { 221 /* we only support dB scale TLV type at the moment */ 222 if ((int)p[SNDRV_CTL_TLVO_TYPE] != SNDRV_CTL_TLVT_DB_SCALE) 223 return -EINVAL; 224 225 /* min value in topology tlv data is multiplied by 100 */ 226 tlv[TLV_MIN] = (int)p[SNDRV_CTL_TLVO_DB_SCALE_MIN] / 100; 227 228 /* volume steps */ 229 tlv[TLV_STEP] = (int)(p[SNDRV_CTL_TLVO_DB_SCALE_MUTE_AND_STEP] & 230 TLV_DB_SCALE_MASK); 231 232 /* mute ON/OFF */ 233 if ((p[SNDRV_CTL_TLVO_DB_SCALE_MUTE_AND_STEP] & 234 TLV_DB_SCALE_MUTE) == 0) 235 tlv[TLV_MUTE] = 0; 236 else 237 tlv[TLV_MUTE] = 1; 238 239 return 0; 240 } 241 242 /* 243 * Function to truncate an unsigned 64-bit number 244 * by x bits and return 32-bit unsigned number. This 245 * function also takes care of rounding while truncating 246 */ 247 static inline u32 vol_shift_64(u64 i, u32 x) 248 { 249 /* do not truncate more than 32 bits */ 250 if (x > 32) 251 x = 32; 252 253 if (x == 0) 254 return (u32)i; 255 256 return (u32)(((i >> (x - 1)) + 1) >> 1); 257 } 258 259 /* 260 * Function to compute a ^ exp where, 261 * a is a fractional number represented by a fixed-point 262 * integer with a fractional world length of "fwl" 263 * exp is an integer 264 * fwl is the fractional word length 265 * Return value is a fractional number represented by a 266 * fixed-point integer with a fractional word length of "fwl" 267 */ 268 static u32 vol_pow32(u32 a, int exp, u32 fwl) 269 { 270 int i, iter; 271 u32 power = 1 << fwl; 272 u64 numerator; 273 274 /* if exponent is 0, return 1 */ 275 if (exp == 0) 276 return power; 277 278 /* determine the number of iterations based on the exponent */ 279 if (exp < 0) 280 iter = exp * -1; 281 else 282 iter = exp; 283 284 /* mutiply a "iter" times to compute power */ 285 for (i = 0; i < iter; i++) { 286 /* 287 * Product of 2 Qx.fwl fixed-point numbers yields a Q2*x.2*fwl 288 * Truncate product back to fwl fractional bits with rounding 289 */ 290 power = vol_shift_64((u64)power * a, fwl); 291 } 292 293 if (exp > 0) { 294 /* if exp is positive, return the result */ 295 return power; 296 } 297 298 /* if exp is negative, return the multiplicative inverse */ 299 numerator = (u64)1 << (fwl << 1); 300 do_div(numerator, power); 301 302 return (u32)numerator; 303 } 304 305 /* 306 * Function to calculate volume gain from TLV data. 307 * This function can only handle gain steps that are multiples of 0.5 dB 308 */ 309 static u32 vol_compute_gain(u32 value, int *tlv) 310 { 311 int dB_gain; 312 u32 linear_gain; 313 int f_step; 314 315 /* mute volume */ 316 if (value == 0 && tlv[TLV_MUTE]) 317 return 0; 318 319 /* 320 * compute dB gain from tlv. tlv_step 321 * in topology is multiplied by 100 322 */ 323 dB_gain = tlv[TLV_MIN] + (value * tlv[TLV_STEP]) / 100; 324 325 /* 326 * compute linear gain represented by fixed-point 327 * int with VOLUME_FWL fractional bits 328 */ 329 linear_gain = vol_pow32(VOL_TWENTIETH_ROOT_OF_TEN, dB_gain, VOLUME_FWL); 330 331 /* extract the fractional part of volume step */ 332 f_step = tlv[TLV_STEP] - (tlv[TLV_STEP] / 100); 333 334 /* if volume step is an odd multiple of 0.5 dB */ 335 if (f_step == VOL_HALF_DB_STEP && (value & 1)) 336 linear_gain = vol_shift_64((u64)linear_gain * 337 VOL_FORTIETH_ROOT_OF_TEN, 338 VOLUME_FWL); 339 340 return linear_gain; 341 } 342 343 /* 344 * Set up volume table for kcontrols from tlv data 345 * "size" specifies the number of entries in the table 346 */ 347 static int set_up_volume_table(struct snd_sof_control *scontrol, 348 int tlv[TLV_ITEMS], int size) 349 { 350 int j; 351 352 /* init the volume table */ 353 scontrol->volume_table = kcalloc(size, sizeof(u32), GFP_KERNEL); 354 if (!scontrol->volume_table) 355 return -ENOMEM; 356 357 /* populate the volume table */ 358 for (j = 0; j < size ; j++) 359 scontrol->volume_table[j] = vol_compute_gain(j, tlv); 360 361 return 0; 362 } 363 364 struct sof_dai_types { 365 const char *name; 366 enum sof_ipc_dai_type type; 367 }; 368 369 static const struct sof_dai_types sof_dais[] = { 370 {"SSP", SOF_DAI_INTEL_SSP}, 371 {"HDA", SOF_DAI_INTEL_HDA}, 372 {"DMIC", SOF_DAI_INTEL_DMIC}, 373 {"ALH", SOF_DAI_INTEL_ALH}, 374 {"SAI", SOF_DAI_IMX_SAI}, 375 {"ESAI", SOF_DAI_IMX_ESAI}, 376 }; 377 378 static enum sof_ipc_dai_type find_dai(const char *name) 379 { 380 int i; 381 382 for (i = 0; i < ARRAY_SIZE(sof_dais); i++) { 383 if (strcmp(name, sof_dais[i].name) == 0) 384 return sof_dais[i].type; 385 } 386 387 return SOF_DAI_INTEL_NONE; 388 } 389 390 /* 391 * Supported Frame format types and lookup, add new ones to end of list. 392 */ 393 394 struct sof_frame_types { 395 const char *name; 396 enum sof_ipc_frame frame; 397 }; 398 399 static const struct sof_frame_types sof_frames[] = { 400 {"s16le", SOF_IPC_FRAME_S16_LE}, 401 {"s24le", SOF_IPC_FRAME_S24_4LE}, 402 {"s32le", SOF_IPC_FRAME_S32_LE}, 403 {"float", SOF_IPC_FRAME_FLOAT}, 404 }; 405 406 static enum sof_ipc_frame find_format(const char *name) 407 { 408 int i; 409 410 for (i = 0; i < ARRAY_SIZE(sof_frames); i++) { 411 if (strcmp(name, sof_frames[i].name) == 0) 412 return sof_frames[i].frame; 413 } 414 415 /* use s32le if nothing is specified */ 416 return SOF_IPC_FRAME_S32_LE; 417 } 418 419 struct sof_process_types { 420 const char *name; 421 enum sof_ipc_process_type type; 422 enum sof_comp_type comp_type; 423 }; 424 425 static const struct sof_process_types sof_process[] = { 426 {"EQFIR", SOF_PROCESS_EQFIR, SOF_COMP_EQ_FIR}, 427 {"EQIIR", SOF_PROCESS_EQIIR, SOF_COMP_EQ_IIR}, 428 {"KEYWORD_DETECT", SOF_PROCESS_KEYWORD_DETECT, SOF_COMP_KEYWORD_DETECT}, 429 {"KPB", SOF_PROCESS_KPB, SOF_COMP_KPB}, 430 {"CHAN_SELECTOR", SOF_PROCESS_CHAN_SELECTOR, SOF_COMP_SELECTOR}, 431 {"MUX", SOF_PROCESS_MUX, SOF_COMP_MUX}, 432 {"DEMUX", SOF_PROCESS_DEMUX, SOF_COMP_DEMUX}, 433 }; 434 435 static enum sof_ipc_process_type find_process(const char *name) 436 { 437 int i; 438 439 for (i = 0; i < ARRAY_SIZE(sof_process); i++) { 440 if (strcmp(name, sof_process[i].name) == 0) 441 return sof_process[i].type; 442 } 443 444 return SOF_PROCESS_NONE; 445 } 446 447 static enum sof_comp_type find_process_comp_type(enum sof_ipc_process_type type) 448 { 449 int i; 450 451 for (i = 0; i < ARRAY_SIZE(sof_process); i++) { 452 if (sof_process[i].type == type) 453 return sof_process[i].comp_type; 454 } 455 456 return SOF_COMP_NONE; 457 } 458 459 /* 460 * Topology Token Parsing. 461 * New tokens should be added to headers and parsing tables below. 462 */ 463 464 struct sof_topology_token { 465 u32 token; 466 u32 type; 467 int (*get_token)(void *elem, void *object, u32 offset, u32 size); 468 u32 offset; 469 u32 size; 470 }; 471 472 static int get_token_u32(void *elem, void *object, u32 offset, u32 size) 473 { 474 struct snd_soc_tplg_vendor_value_elem *velem = elem; 475 u32 *val = (u32 *)((u8 *)object + offset); 476 477 *val = le32_to_cpu(velem->value); 478 return 0; 479 } 480 481 static int get_token_u16(void *elem, void *object, u32 offset, u32 size) 482 { 483 struct snd_soc_tplg_vendor_value_elem *velem = elem; 484 u16 *val = (u16 *)((u8 *)object + offset); 485 486 *val = (u16)le32_to_cpu(velem->value); 487 return 0; 488 } 489 490 static int get_token_comp_format(void *elem, void *object, u32 offset, u32 size) 491 { 492 struct snd_soc_tplg_vendor_string_elem *velem = elem; 493 u32 *val = (u32 *)((u8 *)object + offset); 494 495 *val = find_format(velem->string); 496 return 0; 497 } 498 499 static int get_token_dai_type(void *elem, void *object, u32 offset, u32 size) 500 { 501 struct snd_soc_tplg_vendor_string_elem *velem = elem; 502 u32 *val = (u32 *)((u8 *)object + offset); 503 504 *val = find_dai(velem->string); 505 return 0; 506 } 507 508 static int get_token_process_type(void *elem, void *object, u32 offset, 509 u32 size) 510 { 511 struct snd_soc_tplg_vendor_string_elem *velem = elem; 512 u32 *val = (u32 *)((u8 *)object + offset); 513 514 *val = find_process(velem->string); 515 return 0; 516 } 517 518 /* Buffers */ 519 static const struct sof_topology_token buffer_tokens[] = { 520 {SOF_TKN_BUF_SIZE, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, 521 offsetof(struct sof_ipc_buffer, size), 0}, 522 {SOF_TKN_BUF_CAPS, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, 523 offsetof(struct sof_ipc_buffer, caps), 0}, 524 }; 525 526 /* DAI */ 527 static const struct sof_topology_token dai_tokens[] = { 528 {SOF_TKN_DAI_TYPE, SND_SOC_TPLG_TUPLE_TYPE_STRING, get_token_dai_type, 529 offsetof(struct sof_ipc_comp_dai, type), 0}, 530 {SOF_TKN_DAI_INDEX, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, 531 offsetof(struct sof_ipc_comp_dai, dai_index), 0}, 532 {SOF_TKN_DAI_DIRECTION, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, 533 offsetof(struct sof_ipc_comp_dai, direction), 0}, 534 }; 535 536 /* BE DAI link */ 537 static const struct sof_topology_token dai_link_tokens[] = { 538 {SOF_TKN_DAI_TYPE, SND_SOC_TPLG_TUPLE_TYPE_STRING, get_token_dai_type, 539 offsetof(struct sof_ipc_dai_config, type), 0}, 540 {SOF_TKN_DAI_INDEX, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, 541 offsetof(struct sof_ipc_dai_config, dai_index), 0}, 542 }; 543 544 /* scheduling */ 545 static const struct sof_topology_token sched_tokens[] = { 546 {SOF_TKN_SCHED_PERIOD, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, 547 offsetof(struct sof_ipc_pipe_new, period), 0}, 548 {SOF_TKN_SCHED_PRIORITY, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, 549 offsetof(struct sof_ipc_pipe_new, priority), 0}, 550 {SOF_TKN_SCHED_MIPS, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, 551 offsetof(struct sof_ipc_pipe_new, period_mips), 0}, 552 {SOF_TKN_SCHED_CORE, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, 553 offsetof(struct sof_ipc_pipe_new, core), 0}, 554 {SOF_TKN_SCHED_FRAMES, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, 555 offsetof(struct sof_ipc_pipe_new, frames_per_sched), 0}, 556 {SOF_TKN_SCHED_TIME_DOMAIN, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, 557 offsetof(struct sof_ipc_pipe_new, time_domain), 0}, 558 }; 559 560 /* volume */ 561 static const struct sof_topology_token volume_tokens[] = { 562 {SOF_TKN_VOLUME_RAMP_STEP_TYPE, SND_SOC_TPLG_TUPLE_TYPE_WORD, 563 get_token_u32, offsetof(struct sof_ipc_comp_volume, ramp), 0}, 564 {SOF_TKN_VOLUME_RAMP_STEP_MS, 565 SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, 566 offsetof(struct sof_ipc_comp_volume, initial_ramp), 0}, 567 }; 568 569 /* SRC */ 570 static const struct sof_topology_token src_tokens[] = { 571 {SOF_TKN_SRC_RATE_IN, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, 572 offsetof(struct sof_ipc_comp_src, source_rate), 0}, 573 {SOF_TKN_SRC_RATE_OUT, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, 574 offsetof(struct sof_ipc_comp_src, sink_rate), 0}, 575 }; 576 577 /* ASRC */ 578 static const struct sof_topology_token asrc_tokens[] = { 579 {SOF_TKN_ASRC_RATE_IN, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, 580 offsetof(struct sof_ipc_comp_asrc, source_rate), 0}, 581 {SOF_TKN_ASRC_RATE_OUT, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, 582 offsetof(struct sof_ipc_comp_asrc, sink_rate), 0}, 583 {SOF_TKN_ASRC_ASYNCHRONOUS_MODE, SND_SOC_TPLG_TUPLE_TYPE_WORD, 584 get_token_u32, 585 offsetof(struct sof_ipc_comp_asrc, asynchronous_mode), 0}, 586 {SOF_TKN_ASRC_OPERATION_MODE, SND_SOC_TPLG_TUPLE_TYPE_WORD, 587 get_token_u32, 588 offsetof(struct sof_ipc_comp_asrc, operation_mode), 0}, 589 }; 590 591 /* Tone */ 592 static const struct sof_topology_token tone_tokens[] = { 593 }; 594 595 /* EFFECT */ 596 static const struct sof_topology_token process_tokens[] = { 597 {SOF_TKN_PROCESS_TYPE, SND_SOC_TPLG_TUPLE_TYPE_STRING, 598 get_token_process_type, 599 offsetof(struct sof_ipc_comp_process, type), 0}, 600 }; 601 602 /* PCM */ 603 static const struct sof_topology_token pcm_tokens[] = { 604 {SOF_TKN_PCM_DMAC_CONFIG, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, 605 offsetof(struct sof_ipc_comp_host, dmac_config), 0}, 606 }; 607 608 /* PCM */ 609 static const struct sof_topology_token stream_tokens[] = { 610 {SOF_TKN_STREAM_PLAYBACK_COMPATIBLE_D0I3, 611 SND_SOC_TPLG_TUPLE_TYPE_BOOL, get_token_u16, 612 offsetof(struct snd_sof_pcm, stream[0].d0i3_compatible), 0}, 613 {SOF_TKN_STREAM_CAPTURE_COMPATIBLE_D0I3, 614 SND_SOC_TPLG_TUPLE_TYPE_BOOL, get_token_u16, 615 offsetof(struct snd_sof_pcm, stream[1].d0i3_compatible), 0}, 616 }; 617 618 /* Generic components */ 619 static const struct sof_topology_token comp_tokens[] = { 620 {SOF_TKN_COMP_PERIOD_SINK_COUNT, 621 SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, 622 offsetof(struct sof_ipc_comp_config, periods_sink), 0}, 623 {SOF_TKN_COMP_PERIOD_SOURCE_COUNT, 624 SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, 625 offsetof(struct sof_ipc_comp_config, periods_source), 0}, 626 {SOF_TKN_COMP_FORMAT, 627 SND_SOC_TPLG_TUPLE_TYPE_STRING, get_token_comp_format, 628 offsetof(struct sof_ipc_comp_config, frame_fmt), 0}, 629 }; 630 631 /* SSP */ 632 static const struct sof_topology_token ssp_tokens[] = { 633 {SOF_TKN_INTEL_SSP_CLKS_CONTROL, 634 SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, 635 offsetof(struct sof_ipc_dai_ssp_params, clks_control), 0}, 636 {SOF_TKN_INTEL_SSP_MCLK_ID, 637 SND_SOC_TPLG_TUPLE_TYPE_SHORT, get_token_u16, 638 offsetof(struct sof_ipc_dai_ssp_params, mclk_id), 0}, 639 {SOF_TKN_INTEL_SSP_SAMPLE_BITS, SND_SOC_TPLG_TUPLE_TYPE_WORD, 640 get_token_u32, 641 offsetof(struct sof_ipc_dai_ssp_params, sample_valid_bits), 0}, 642 {SOF_TKN_INTEL_SSP_FRAME_PULSE_WIDTH, SND_SOC_TPLG_TUPLE_TYPE_SHORT, 643 get_token_u16, 644 offsetof(struct sof_ipc_dai_ssp_params, frame_pulse_width), 0}, 645 {SOF_TKN_INTEL_SSP_QUIRKS, SND_SOC_TPLG_TUPLE_TYPE_WORD, 646 get_token_u32, 647 offsetof(struct sof_ipc_dai_ssp_params, quirks), 0}, 648 {SOF_TKN_INTEL_SSP_TDM_PADDING_PER_SLOT, SND_SOC_TPLG_TUPLE_TYPE_BOOL, 649 get_token_u16, 650 offsetof(struct sof_ipc_dai_ssp_params, 651 tdm_per_slot_padding_flag), 0}, 652 {SOF_TKN_INTEL_SSP_BCLK_DELAY, SND_SOC_TPLG_TUPLE_TYPE_WORD, 653 get_token_u32, 654 offsetof(struct sof_ipc_dai_ssp_params, bclk_delay), 0}, 655 656 }; 657 658 /* DMIC */ 659 static const struct sof_topology_token dmic_tokens[] = { 660 {SOF_TKN_INTEL_DMIC_DRIVER_VERSION, 661 SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, 662 offsetof(struct sof_ipc_dai_dmic_params, driver_ipc_version), 663 0}, 664 {SOF_TKN_INTEL_DMIC_CLK_MIN, 665 SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, 666 offsetof(struct sof_ipc_dai_dmic_params, pdmclk_min), 0}, 667 {SOF_TKN_INTEL_DMIC_CLK_MAX, 668 SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, 669 offsetof(struct sof_ipc_dai_dmic_params, pdmclk_max), 0}, 670 {SOF_TKN_INTEL_DMIC_SAMPLE_RATE, 671 SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, 672 offsetof(struct sof_ipc_dai_dmic_params, fifo_fs), 0}, 673 {SOF_TKN_INTEL_DMIC_DUTY_MIN, 674 SND_SOC_TPLG_TUPLE_TYPE_SHORT, get_token_u16, 675 offsetof(struct sof_ipc_dai_dmic_params, duty_min), 0}, 676 {SOF_TKN_INTEL_DMIC_DUTY_MAX, 677 SND_SOC_TPLG_TUPLE_TYPE_SHORT, get_token_u16, 678 offsetof(struct sof_ipc_dai_dmic_params, duty_max), 0}, 679 {SOF_TKN_INTEL_DMIC_NUM_PDM_ACTIVE, 680 SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, 681 offsetof(struct sof_ipc_dai_dmic_params, 682 num_pdm_active), 0}, 683 {SOF_TKN_INTEL_DMIC_FIFO_WORD_LENGTH, 684 SND_SOC_TPLG_TUPLE_TYPE_SHORT, get_token_u16, 685 offsetof(struct sof_ipc_dai_dmic_params, fifo_bits), 0}, 686 {SOF_TKN_INTEL_DMIC_UNMUTE_RAMP_TIME_MS, 687 SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, 688 offsetof(struct sof_ipc_dai_dmic_params, unmute_ramp_time), 0}, 689 690 }; 691 692 /* ESAI */ 693 static const struct sof_topology_token esai_tokens[] = { 694 {SOF_TKN_IMX_ESAI_MCLK_ID, 695 SND_SOC_TPLG_TUPLE_TYPE_SHORT, get_token_u16, 696 offsetof(struct sof_ipc_dai_esai_params, mclk_id), 0}, 697 }; 698 699 /* SAI */ 700 static const struct sof_topology_token sai_tokens[] = { 701 {SOF_TKN_IMX_SAI_MCLK_ID, 702 SND_SOC_TPLG_TUPLE_TYPE_SHORT, get_token_u16, 703 offsetof(struct sof_ipc_dai_sai_params, mclk_id), 0}, 704 }; 705 706 /* 707 * DMIC PDM Tokens 708 * SOF_TKN_INTEL_DMIC_PDM_CTRL_ID should be the first token 709 * as it increments the index while parsing the array of pdm tokens 710 * and determines the correct offset 711 */ 712 static const struct sof_topology_token dmic_pdm_tokens[] = { 713 {SOF_TKN_INTEL_DMIC_PDM_CTRL_ID, 714 SND_SOC_TPLG_TUPLE_TYPE_SHORT, get_token_u16, 715 offsetof(struct sof_ipc_dai_dmic_pdm_ctrl, id), 716 0}, 717 {SOF_TKN_INTEL_DMIC_PDM_MIC_A_Enable, 718 SND_SOC_TPLG_TUPLE_TYPE_SHORT, get_token_u16, 719 offsetof(struct sof_ipc_dai_dmic_pdm_ctrl, enable_mic_a), 720 0}, 721 {SOF_TKN_INTEL_DMIC_PDM_MIC_B_Enable, 722 SND_SOC_TPLG_TUPLE_TYPE_SHORT, get_token_u16, 723 offsetof(struct sof_ipc_dai_dmic_pdm_ctrl, enable_mic_b), 724 0}, 725 {SOF_TKN_INTEL_DMIC_PDM_POLARITY_A, 726 SND_SOC_TPLG_TUPLE_TYPE_SHORT, get_token_u16, 727 offsetof(struct sof_ipc_dai_dmic_pdm_ctrl, polarity_mic_a), 728 0}, 729 {SOF_TKN_INTEL_DMIC_PDM_POLARITY_B, 730 SND_SOC_TPLG_TUPLE_TYPE_SHORT, get_token_u16, 731 offsetof(struct sof_ipc_dai_dmic_pdm_ctrl, polarity_mic_b), 732 0}, 733 {SOF_TKN_INTEL_DMIC_PDM_CLK_EDGE, 734 SND_SOC_TPLG_TUPLE_TYPE_SHORT, get_token_u16, 735 offsetof(struct sof_ipc_dai_dmic_pdm_ctrl, clk_edge), 736 0}, 737 {SOF_TKN_INTEL_DMIC_PDM_SKEW, 738 SND_SOC_TPLG_TUPLE_TYPE_SHORT, get_token_u16, 739 offsetof(struct sof_ipc_dai_dmic_pdm_ctrl, skew), 740 0}, 741 }; 742 743 /* HDA */ 744 static const struct sof_topology_token hda_tokens[] = { 745 }; 746 747 /* Leds */ 748 static const struct sof_topology_token led_tokens[] = { 749 {SOF_TKN_MUTE_LED_USE, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, 750 offsetof(struct snd_sof_led_control, use_led), 0}, 751 {SOF_TKN_MUTE_LED_DIRECTION, SND_SOC_TPLG_TUPLE_TYPE_WORD, 752 get_token_u32, offsetof(struct snd_sof_led_control, direction), 0}, 753 }; 754 755 static void sof_parse_uuid_tokens(struct snd_soc_component *scomp, 756 void *object, 757 const struct sof_topology_token *tokens, 758 int count, 759 struct snd_soc_tplg_vendor_array *array) 760 { 761 struct snd_soc_tplg_vendor_uuid_elem *elem; 762 int i, j; 763 764 /* parse element by element */ 765 for (i = 0; i < le32_to_cpu(array->num_elems); i++) { 766 elem = &array->uuid[i]; 767 768 /* search for token */ 769 for (j = 0; j < count; j++) { 770 /* match token type */ 771 if (tokens[j].type != SND_SOC_TPLG_TUPLE_TYPE_UUID) 772 continue; 773 774 /* match token id */ 775 if (tokens[j].token != le32_to_cpu(elem->token)) 776 continue; 777 778 /* matched - now load token */ 779 tokens[j].get_token(elem, object, tokens[j].offset, 780 tokens[j].size); 781 } 782 } 783 } 784 785 static void sof_parse_string_tokens(struct snd_soc_component *scomp, 786 void *object, 787 const struct sof_topology_token *tokens, 788 int count, 789 struct snd_soc_tplg_vendor_array *array) 790 { 791 struct snd_soc_tplg_vendor_string_elem *elem; 792 int i, j; 793 794 /* parse element by element */ 795 for (i = 0; i < le32_to_cpu(array->num_elems); i++) { 796 elem = &array->string[i]; 797 798 /* search for token */ 799 for (j = 0; j < count; j++) { 800 /* match token type */ 801 if (tokens[j].type != SND_SOC_TPLG_TUPLE_TYPE_STRING) 802 continue; 803 804 /* match token id */ 805 if (tokens[j].token != le32_to_cpu(elem->token)) 806 continue; 807 808 /* matched - now load token */ 809 tokens[j].get_token(elem, object, tokens[j].offset, 810 tokens[j].size); 811 } 812 } 813 } 814 815 static void sof_parse_word_tokens(struct snd_soc_component *scomp, 816 void *object, 817 const struct sof_topology_token *tokens, 818 int count, 819 struct snd_soc_tplg_vendor_array *array) 820 { 821 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); 822 struct snd_soc_tplg_vendor_value_elem *elem; 823 size_t size = sizeof(struct sof_ipc_dai_dmic_pdm_ctrl); 824 int i, j; 825 u32 offset; 826 u32 *index = NULL; 827 828 /* parse element by element */ 829 for (i = 0; i < le32_to_cpu(array->num_elems); i++) { 830 elem = &array->value[i]; 831 832 /* search for token */ 833 for (j = 0; j < count; j++) { 834 /* match token type */ 835 if (!(tokens[j].type == SND_SOC_TPLG_TUPLE_TYPE_WORD || 836 tokens[j].type == SND_SOC_TPLG_TUPLE_TYPE_SHORT || 837 tokens[j].type == SND_SOC_TPLG_TUPLE_TYPE_BYTE || 838 tokens[j].type == SND_SOC_TPLG_TUPLE_TYPE_BOOL)) 839 continue; 840 841 /* match token id */ 842 if (tokens[j].token != le32_to_cpu(elem->token)) 843 continue; 844 845 /* pdm config array index */ 846 if (sdev->private) 847 index = sdev->private; 848 849 /* matched - determine offset */ 850 switch (tokens[j].token) { 851 case SOF_TKN_INTEL_DMIC_PDM_CTRL_ID: 852 853 /* inc number of pdm array index */ 854 if (index) 855 (*index)++; 856 /* fallthrough */ 857 case SOF_TKN_INTEL_DMIC_PDM_MIC_A_Enable: 858 case SOF_TKN_INTEL_DMIC_PDM_MIC_B_Enable: 859 case SOF_TKN_INTEL_DMIC_PDM_POLARITY_A: 860 case SOF_TKN_INTEL_DMIC_PDM_POLARITY_B: 861 case SOF_TKN_INTEL_DMIC_PDM_CLK_EDGE: 862 case SOF_TKN_INTEL_DMIC_PDM_SKEW: 863 864 /* check if array index is valid */ 865 if (!index || *index == 0) { 866 dev_err(scomp->dev, 867 "error: invalid array offset\n"); 868 continue; 869 } else { 870 /* offset within the pdm config array */ 871 offset = size * (*index - 1); 872 } 873 break; 874 default: 875 offset = 0; 876 break; 877 } 878 879 /* load token */ 880 tokens[j].get_token(elem, object, 881 offset + tokens[j].offset, 882 tokens[j].size); 883 } 884 } 885 } 886 887 static int sof_parse_tokens(struct snd_soc_component *scomp, 888 void *object, 889 const struct sof_topology_token *tokens, 890 int count, 891 struct snd_soc_tplg_vendor_array *array, 892 int priv_size) 893 { 894 int asize; 895 896 while (priv_size > 0) { 897 asize = le32_to_cpu(array->size); 898 899 /* validate asize */ 900 if (asize < 0) { /* FIXME: A zero-size array makes no sense */ 901 dev_err(scomp->dev, "error: invalid array size 0x%x\n", 902 asize); 903 return -EINVAL; 904 } 905 906 /* make sure there is enough data before parsing */ 907 priv_size -= asize; 908 if (priv_size < 0) { 909 dev_err(scomp->dev, "error: invalid array size 0x%x\n", 910 asize); 911 return -EINVAL; 912 } 913 914 /* call correct parser depending on type */ 915 switch (le32_to_cpu(array->type)) { 916 case SND_SOC_TPLG_TUPLE_TYPE_UUID: 917 sof_parse_uuid_tokens(scomp, object, tokens, count, 918 array); 919 break; 920 case SND_SOC_TPLG_TUPLE_TYPE_STRING: 921 sof_parse_string_tokens(scomp, object, tokens, count, 922 array); 923 break; 924 case SND_SOC_TPLG_TUPLE_TYPE_BOOL: 925 case SND_SOC_TPLG_TUPLE_TYPE_BYTE: 926 case SND_SOC_TPLG_TUPLE_TYPE_WORD: 927 case SND_SOC_TPLG_TUPLE_TYPE_SHORT: 928 sof_parse_word_tokens(scomp, object, tokens, count, 929 array); 930 break; 931 default: 932 dev_err(scomp->dev, "error: unknown token type %d\n", 933 array->type); 934 return -EINVAL; 935 } 936 937 /* next array */ 938 array = (struct snd_soc_tplg_vendor_array *)((u8 *)array 939 + asize); 940 } 941 return 0; 942 } 943 944 static void sof_dbg_comp_config(struct snd_soc_component *scomp, 945 struct sof_ipc_comp_config *config) 946 { 947 dev_dbg(scomp->dev, " config: periods snk %d src %d fmt %d\n", 948 config->periods_sink, config->periods_source, 949 config->frame_fmt); 950 } 951 952 /* 953 * Standard Kcontrols. 954 */ 955 956 static int sof_control_load_volume(struct snd_soc_component *scomp, 957 struct snd_sof_control *scontrol, 958 struct snd_kcontrol_new *kc, 959 struct snd_soc_tplg_ctl_hdr *hdr) 960 { 961 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); 962 struct snd_soc_tplg_mixer_control *mc = 963 container_of(hdr, struct snd_soc_tplg_mixer_control, hdr); 964 struct sof_ipc_ctrl_data *cdata; 965 int tlv[TLV_ITEMS]; 966 unsigned int i; 967 int ret = 0; 968 969 /* validate topology data */ 970 if (le32_to_cpu(mc->num_channels) > SND_SOC_TPLG_MAX_CHAN) { 971 ret = -EINVAL; 972 goto out; 973 } 974 975 /* init the volume get/put data */ 976 scontrol->size = struct_size(scontrol->control_data, chanv, 977 le32_to_cpu(mc->num_channels)); 978 scontrol->control_data = kzalloc(scontrol->size, GFP_KERNEL); 979 if (!scontrol->control_data) { 980 ret = -ENOMEM; 981 goto out; 982 } 983 984 scontrol->comp_id = sdev->next_comp_id; 985 scontrol->min_volume_step = le32_to_cpu(mc->min); 986 scontrol->max_volume_step = le32_to_cpu(mc->max); 987 scontrol->num_channels = le32_to_cpu(mc->num_channels); 988 989 /* set cmd for mixer control */ 990 if (le32_to_cpu(mc->max) == 1) { 991 scontrol->cmd = SOF_CTRL_CMD_SWITCH; 992 goto skip; 993 } 994 995 scontrol->cmd = SOF_CTRL_CMD_VOLUME; 996 997 /* extract tlv data */ 998 if (get_tlv_data(kc->tlv.p, tlv) < 0) { 999 dev_err(scomp->dev, "error: invalid TLV data\n"); 1000 ret = -EINVAL; 1001 goto out_free; 1002 } 1003 1004 /* set up volume table */ 1005 ret = set_up_volume_table(scontrol, tlv, le32_to_cpu(mc->max) + 1); 1006 if (ret < 0) { 1007 dev_err(scomp->dev, "error: setting up volume table\n"); 1008 goto out_free; 1009 } 1010 1011 /* set default volume values to 0dB in control */ 1012 cdata = scontrol->control_data; 1013 for (i = 0; i < scontrol->num_channels; i++) { 1014 cdata->chanv[i].channel = i; 1015 cdata->chanv[i].value = VOL_ZERO_DB; 1016 } 1017 1018 skip: 1019 /* set up possible led control from mixer private data */ 1020 ret = sof_parse_tokens(scomp, &scontrol->led_ctl, led_tokens, 1021 ARRAY_SIZE(led_tokens), mc->priv.array, 1022 le32_to_cpu(mc->priv.size)); 1023 if (ret != 0) { 1024 dev_err(scomp->dev, "error: parse led tokens failed %d\n", 1025 le32_to_cpu(mc->priv.size)); 1026 goto out_free_table; 1027 } 1028 1029 dev_dbg(scomp->dev, "tplg: load kcontrol index %d chans %d\n", 1030 scontrol->comp_id, scontrol->num_channels); 1031 1032 return ret; 1033 1034 out_free_table: 1035 if (le32_to_cpu(mc->max) > 1) 1036 kfree(scontrol->volume_table); 1037 out_free: 1038 kfree(scontrol->control_data); 1039 out: 1040 return ret; 1041 } 1042 1043 static int sof_control_load_enum(struct snd_soc_component *scomp, 1044 struct snd_sof_control *scontrol, 1045 struct snd_kcontrol_new *kc, 1046 struct snd_soc_tplg_ctl_hdr *hdr) 1047 { 1048 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); 1049 struct snd_soc_tplg_enum_control *ec = 1050 container_of(hdr, struct snd_soc_tplg_enum_control, hdr); 1051 1052 /* validate topology data */ 1053 if (le32_to_cpu(ec->num_channels) > SND_SOC_TPLG_MAX_CHAN) 1054 return -EINVAL; 1055 1056 /* init the enum get/put data */ 1057 scontrol->size = struct_size(scontrol->control_data, chanv, 1058 le32_to_cpu(ec->num_channels)); 1059 scontrol->control_data = kzalloc(scontrol->size, GFP_KERNEL); 1060 if (!scontrol->control_data) 1061 return -ENOMEM; 1062 1063 scontrol->comp_id = sdev->next_comp_id; 1064 scontrol->num_channels = le32_to_cpu(ec->num_channels); 1065 1066 scontrol->cmd = SOF_CTRL_CMD_ENUM; 1067 1068 dev_dbg(scomp->dev, "tplg: load kcontrol index %d chans %d comp_id %d\n", 1069 scontrol->comp_id, scontrol->num_channels, scontrol->comp_id); 1070 1071 return 0; 1072 } 1073 1074 static int sof_control_load_bytes(struct snd_soc_component *scomp, 1075 struct snd_sof_control *scontrol, 1076 struct snd_kcontrol_new *kc, 1077 struct snd_soc_tplg_ctl_hdr *hdr) 1078 { 1079 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); 1080 struct sof_ipc_ctrl_data *cdata; 1081 struct snd_soc_tplg_bytes_control *control = 1082 container_of(hdr, struct snd_soc_tplg_bytes_control, hdr); 1083 struct soc_bytes_ext *sbe = (struct soc_bytes_ext *)kc->private_value; 1084 int max_size = sbe->max; 1085 int ret = 0; 1086 1087 /* init the get/put bytes data */ 1088 scontrol->size = sizeof(struct sof_ipc_ctrl_data) + 1089 le32_to_cpu(control->priv.size); 1090 1091 if (scontrol->size > max_size) { 1092 dev_err(scomp->dev, "err: bytes data size %d exceeds max %d.\n", 1093 scontrol->size, max_size); 1094 ret = -EINVAL; 1095 goto out; 1096 } 1097 1098 scontrol->control_data = kzalloc(max_size, GFP_KERNEL); 1099 cdata = scontrol->control_data; 1100 if (!scontrol->control_data) { 1101 ret = -ENOMEM; 1102 goto out; 1103 } 1104 1105 scontrol->comp_id = sdev->next_comp_id; 1106 scontrol->cmd = SOF_CTRL_CMD_BINARY; 1107 1108 dev_dbg(scomp->dev, "tplg: load kcontrol index %d chans %d\n", 1109 scontrol->comp_id, scontrol->num_channels); 1110 1111 if (le32_to_cpu(control->priv.size) > 0) { 1112 memcpy(cdata->data, control->priv.data, 1113 le32_to_cpu(control->priv.size)); 1114 1115 if (cdata->data->magic != SOF_ABI_MAGIC) { 1116 dev_err(scomp->dev, "error: Wrong ABI magic 0x%08x.\n", 1117 cdata->data->magic); 1118 ret = -EINVAL; 1119 goto out_free; 1120 } 1121 if (SOF_ABI_VERSION_INCOMPATIBLE(SOF_ABI_VERSION, 1122 cdata->data->abi)) { 1123 dev_err(scomp->dev, 1124 "error: Incompatible ABI version 0x%08x.\n", 1125 cdata->data->abi); 1126 ret = -EINVAL; 1127 goto out_free; 1128 } 1129 if (cdata->data->size + sizeof(const struct sof_abi_hdr) != 1130 le32_to_cpu(control->priv.size)) { 1131 dev_err(scomp->dev, 1132 "error: Conflict in bytes vs. priv size.\n"); 1133 ret = -EINVAL; 1134 goto out_free; 1135 } 1136 } 1137 1138 return ret; 1139 1140 out_free: 1141 kfree(scontrol->control_data); 1142 out: 1143 return ret; 1144 } 1145 1146 /* external kcontrol init - used for any driver specific init */ 1147 static int sof_control_load(struct snd_soc_component *scomp, int index, 1148 struct snd_kcontrol_new *kc, 1149 struct snd_soc_tplg_ctl_hdr *hdr) 1150 { 1151 struct soc_mixer_control *sm; 1152 struct soc_bytes_ext *sbe; 1153 struct soc_enum *se; 1154 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); 1155 struct snd_soc_dobj *dobj; 1156 struct snd_sof_control *scontrol; 1157 int ret = -EINVAL; 1158 1159 dev_dbg(scomp->dev, "tplg: load control type %d name : %s\n", 1160 hdr->type, hdr->name); 1161 1162 scontrol = kzalloc(sizeof(*scontrol), GFP_KERNEL); 1163 if (!scontrol) 1164 return -ENOMEM; 1165 1166 scontrol->scomp = scomp; 1167 1168 switch (le32_to_cpu(hdr->ops.info)) { 1169 case SND_SOC_TPLG_CTL_VOLSW: 1170 case SND_SOC_TPLG_CTL_VOLSW_SX: 1171 case SND_SOC_TPLG_CTL_VOLSW_XR_SX: 1172 sm = (struct soc_mixer_control *)kc->private_value; 1173 dobj = &sm->dobj; 1174 ret = sof_control_load_volume(scomp, scontrol, kc, hdr); 1175 break; 1176 case SND_SOC_TPLG_CTL_BYTES: 1177 sbe = (struct soc_bytes_ext *)kc->private_value; 1178 dobj = &sbe->dobj; 1179 ret = sof_control_load_bytes(scomp, scontrol, kc, hdr); 1180 break; 1181 case SND_SOC_TPLG_CTL_ENUM: 1182 case SND_SOC_TPLG_CTL_ENUM_VALUE: 1183 se = (struct soc_enum *)kc->private_value; 1184 dobj = &se->dobj; 1185 ret = sof_control_load_enum(scomp, scontrol, kc, hdr); 1186 break; 1187 case SND_SOC_TPLG_CTL_RANGE: 1188 case SND_SOC_TPLG_CTL_STROBE: 1189 case SND_SOC_TPLG_DAPM_CTL_VOLSW: 1190 case SND_SOC_TPLG_DAPM_CTL_ENUM_DOUBLE: 1191 case SND_SOC_TPLG_DAPM_CTL_ENUM_VIRT: 1192 case SND_SOC_TPLG_DAPM_CTL_ENUM_VALUE: 1193 case SND_SOC_TPLG_DAPM_CTL_PIN: 1194 default: 1195 dev_warn(scomp->dev, "control type not supported %d:%d:%d\n", 1196 hdr->ops.get, hdr->ops.put, hdr->ops.info); 1197 kfree(scontrol); 1198 return 0; 1199 } 1200 1201 if (ret < 0) { 1202 kfree(scontrol); 1203 return ret; 1204 } 1205 1206 dobj->private = scontrol; 1207 list_add(&scontrol->list, &sdev->kcontrol_list); 1208 return ret; 1209 } 1210 1211 static int sof_control_unload(struct snd_soc_component *scomp, 1212 struct snd_soc_dobj *dobj) 1213 { 1214 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); 1215 struct sof_ipc_free fcomp; 1216 struct snd_sof_control *scontrol = dobj->private; 1217 1218 dev_dbg(scomp->dev, "tplg: unload control name : %s\n", scomp->name); 1219 1220 fcomp.hdr.cmd = SOF_IPC_GLB_TPLG_MSG | SOF_IPC_TPLG_COMP_FREE; 1221 fcomp.hdr.size = sizeof(fcomp); 1222 fcomp.id = scontrol->comp_id; 1223 1224 kfree(scontrol->control_data); 1225 list_del(&scontrol->list); 1226 kfree(scontrol); 1227 /* send IPC to the DSP */ 1228 return sof_ipc_tx_message(sdev->ipc, 1229 fcomp.hdr.cmd, &fcomp, sizeof(fcomp), 1230 NULL, 0); 1231 } 1232 1233 /* 1234 * DAI Topology 1235 */ 1236 1237 static int sof_connect_dai_widget(struct snd_soc_component *scomp, 1238 struct snd_soc_dapm_widget *w, 1239 struct snd_soc_tplg_dapm_widget *tw, 1240 struct snd_sof_dai *dai) 1241 { 1242 struct snd_soc_card *card = scomp->card; 1243 struct snd_soc_pcm_runtime *rtd; 1244 struct snd_soc_dai *cpu_dai; 1245 int i; 1246 1247 list_for_each_entry(rtd, &card->rtd_list, list) { 1248 dev_vdbg(scomp->dev, "tplg: check widget: %s stream: %s dai stream: %s\n", 1249 w->name, w->sname, rtd->dai_link->stream_name); 1250 1251 if (!w->sname || !rtd->dai_link->stream_name) 1252 continue; 1253 1254 /* does stream match DAI link ? */ 1255 if (strcmp(w->sname, rtd->dai_link->stream_name)) 1256 continue; 1257 1258 switch (w->id) { 1259 case snd_soc_dapm_dai_out: 1260 for_each_rtd_cpu_dais(rtd, i, cpu_dai) 1261 cpu_dai->capture_widget = w; 1262 dai->name = rtd->dai_link->name; 1263 dev_dbg(scomp->dev, "tplg: connected widget %s -> DAI link %s\n", 1264 w->name, rtd->dai_link->name); 1265 break; 1266 case snd_soc_dapm_dai_in: 1267 for_each_rtd_cpu_dais(rtd, i, cpu_dai) 1268 cpu_dai->playback_widget = w; 1269 dai->name = rtd->dai_link->name; 1270 dev_dbg(scomp->dev, "tplg: connected widget %s -> DAI link %s\n", 1271 w->name, rtd->dai_link->name); 1272 break; 1273 default: 1274 break; 1275 } 1276 } 1277 1278 /* check we have a connection */ 1279 if (!dai->name) { 1280 dev_err(scomp->dev, "error: can't connect DAI %s stream %s\n", 1281 w->name, w->sname); 1282 return -EINVAL; 1283 } 1284 1285 return 0; 1286 } 1287 1288 static int sof_widget_load_dai(struct snd_soc_component *scomp, int index, 1289 struct snd_sof_widget *swidget, 1290 struct snd_soc_tplg_dapm_widget *tw, 1291 struct sof_ipc_comp_reply *r, 1292 struct snd_sof_dai *dai) 1293 { 1294 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); 1295 struct snd_soc_tplg_private *private = &tw->priv; 1296 struct sof_ipc_comp_dai comp_dai; 1297 int ret; 1298 1299 /* configure dai IPC message */ 1300 memset(&comp_dai, 0, sizeof(comp_dai)); 1301 comp_dai.comp.hdr.size = sizeof(comp_dai); 1302 comp_dai.comp.hdr.cmd = SOF_IPC_GLB_TPLG_MSG | SOF_IPC_TPLG_COMP_NEW; 1303 comp_dai.comp.id = swidget->comp_id; 1304 comp_dai.comp.type = SOF_COMP_DAI; 1305 comp_dai.comp.pipeline_id = index; 1306 comp_dai.config.hdr.size = sizeof(comp_dai.config); 1307 1308 ret = sof_parse_tokens(scomp, &comp_dai, dai_tokens, 1309 ARRAY_SIZE(dai_tokens), private->array, 1310 le32_to_cpu(private->size)); 1311 if (ret != 0) { 1312 dev_err(scomp->dev, "error: parse dai tokens failed %d\n", 1313 le32_to_cpu(private->size)); 1314 return ret; 1315 } 1316 1317 ret = sof_parse_tokens(scomp, &comp_dai.config, comp_tokens, 1318 ARRAY_SIZE(comp_tokens), private->array, 1319 le32_to_cpu(private->size)); 1320 if (ret != 0) { 1321 dev_err(scomp->dev, "error: parse dai.cfg tokens failed %d\n", 1322 private->size); 1323 return ret; 1324 } 1325 1326 dev_dbg(scomp->dev, "dai %s: type %d index %d\n", 1327 swidget->widget->name, comp_dai.type, comp_dai.dai_index); 1328 sof_dbg_comp_config(scomp, &comp_dai.config); 1329 1330 ret = sof_ipc_tx_message(sdev->ipc, comp_dai.comp.hdr.cmd, 1331 &comp_dai, sizeof(comp_dai), r, sizeof(*r)); 1332 1333 if (ret == 0 && dai) { 1334 dai->scomp = scomp; 1335 memcpy(&dai->comp_dai, &comp_dai, sizeof(comp_dai)); 1336 } 1337 1338 return ret; 1339 } 1340 1341 /* 1342 * Buffer topology 1343 */ 1344 1345 static int sof_widget_load_buffer(struct snd_soc_component *scomp, int index, 1346 struct snd_sof_widget *swidget, 1347 struct snd_soc_tplg_dapm_widget *tw, 1348 struct sof_ipc_comp_reply *r) 1349 { 1350 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); 1351 struct snd_soc_tplg_private *private = &tw->priv; 1352 struct sof_ipc_buffer *buffer; 1353 int ret; 1354 1355 buffer = kzalloc(sizeof(*buffer), GFP_KERNEL); 1356 if (!buffer) 1357 return -ENOMEM; 1358 1359 /* configure dai IPC message */ 1360 buffer->comp.hdr.size = sizeof(*buffer); 1361 buffer->comp.hdr.cmd = SOF_IPC_GLB_TPLG_MSG | SOF_IPC_TPLG_BUFFER_NEW; 1362 buffer->comp.id = swidget->comp_id; 1363 buffer->comp.type = SOF_COMP_BUFFER; 1364 buffer->comp.pipeline_id = index; 1365 1366 ret = sof_parse_tokens(scomp, buffer, buffer_tokens, 1367 ARRAY_SIZE(buffer_tokens), private->array, 1368 le32_to_cpu(private->size)); 1369 if (ret != 0) { 1370 dev_err(scomp->dev, "error: parse buffer tokens failed %d\n", 1371 private->size); 1372 kfree(buffer); 1373 return ret; 1374 } 1375 1376 dev_dbg(scomp->dev, "buffer %s: size %d caps 0x%x\n", 1377 swidget->widget->name, buffer->size, buffer->caps); 1378 1379 swidget->private = buffer; 1380 1381 ret = sof_ipc_tx_message(sdev->ipc, buffer->comp.hdr.cmd, buffer, 1382 sizeof(*buffer), r, sizeof(*r)); 1383 if (ret < 0) { 1384 dev_err(scomp->dev, "error: buffer %s load failed\n", 1385 swidget->widget->name); 1386 kfree(buffer); 1387 } 1388 1389 return ret; 1390 } 1391 1392 /* bind PCM ID to host component ID */ 1393 static int spcm_bind(struct snd_soc_component *scomp, struct snd_sof_pcm *spcm, 1394 int dir) 1395 { 1396 struct snd_sof_widget *host_widget; 1397 1398 host_widget = snd_sof_find_swidget_sname(scomp, 1399 spcm->pcm.caps[dir].name, 1400 dir); 1401 if (!host_widget) { 1402 dev_err(scomp->dev, "can't find host comp to bind pcm\n"); 1403 return -EINVAL; 1404 } 1405 1406 spcm->stream[dir].comp_id = host_widget->comp_id; 1407 1408 return 0; 1409 } 1410 1411 /* 1412 * PCM Topology 1413 */ 1414 1415 static int sof_widget_load_pcm(struct snd_soc_component *scomp, int index, 1416 struct snd_sof_widget *swidget, 1417 enum sof_ipc_stream_direction dir, 1418 struct snd_soc_tplg_dapm_widget *tw, 1419 struct sof_ipc_comp_reply *r) 1420 { 1421 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); 1422 struct snd_soc_tplg_private *private = &tw->priv; 1423 struct sof_ipc_comp_host *host; 1424 int ret; 1425 1426 host = kzalloc(sizeof(*host), GFP_KERNEL); 1427 if (!host) 1428 return -ENOMEM; 1429 1430 /* configure host comp IPC message */ 1431 host->comp.hdr.size = sizeof(*host); 1432 host->comp.hdr.cmd = SOF_IPC_GLB_TPLG_MSG | SOF_IPC_TPLG_COMP_NEW; 1433 host->comp.id = swidget->comp_id; 1434 host->comp.type = SOF_COMP_HOST; 1435 host->comp.pipeline_id = index; 1436 host->direction = dir; 1437 host->config.hdr.size = sizeof(host->config); 1438 1439 ret = sof_parse_tokens(scomp, host, pcm_tokens, 1440 ARRAY_SIZE(pcm_tokens), private->array, 1441 le32_to_cpu(private->size)); 1442 if (ret != 0) { 1443 dev_err(scomp->dev, "error: parse host tokens failed %d\n", 1444 private->size); 1445 goto err; 1446 } 1447 1448 ret = sof_parse_tokens(scomp, &host->config, comp_tokens, 1449 ARRAY_SIZE(comp_tokens), private->array, 1450 le32_to_cpu(private->size)); 1451 if (ret != 0) { 1452 dev_err(scomp->dev, "error: parse host.cfg tokens failed %d\n", 1453 le32_to_cpu(private->size)); 1454 goto err; 1455 } 1456 1457 dev_dbg(scomp->dev, "loaded host %s\n", swidget->widget->name); 1458 sof_dbg_comp_config(scomp, &host->config); 1459 1460 swidget->private = host; 1461 1462 ret = sof_ipc_tx_message(sdev->ipc, host->comp.hdr.cmd, host, 1463 sizeof(*host), r, sizeof(*r)); 1464 if (ret >= 0) 1465 return ret; 1466 err: 1467 kfree(host); 1468 return ret; 1469 } 1470 1471 /* 1472 * Pipeline Topology 1473 */ 1474 int sof_load_pipeline_ipc(struct device *dev, 1475 struct sof_ipc_pipe_new *pipeline, 1476 struct sof_ipc_comp_reply *r) 1477 { 1478 struct snd_sof_dev *sdev = dev_get_drvdata(dev); 1479 struct sof_ipc_pm_core_config pm_core_config; 1480 int ret; 1481 1482 ret = sof_ipc_tx_message(sdev->ipc, pipeline->hdr.cmd, pipeline, 1483 sizeof(*pipeline), r, sizeof(*r)); 1484 if (ret < 0) { 1485 dev_err(dev, "error: load pipeline ipc failure\n"); 1486 return ret; 1487 } 1488 1489 /* power up the core that this pipeline is scheduled on */ 1490 ret = snd_sof_dsp_core_power_up(sdev, 1 << pipeline->core); 1491 if (ret < 0) { 1492 dev_err(dev, "error: powering up pipeline schedule core %d\n", 1493 pipeline->core); 1494 return ret; 1495 } 1496 1497 /* update enabled cores mask */ 1498 sdev->enabled_cores_mask |= 1 << pipeline->core; 1499 1500 /* 1501 * Now notify DSP that the core that this pipeline is scheduled on 1502 * has been powered up 1503 */ 1504 memset(&pm_core_config, 0, sizeof(pm_core_config)); 1505 pm_core_config.enable_mask = sdev->enabled_cores_mask; 1506 1507 /* configure CORE_ENABLE ipc message */ 1508 pm_core_config.hdr.size = sizeof(pm_core_config); 1509 pm_core_config.hdr.cmd = SOF_IPC_GLB_PM_MSG | SOF_IPC_PM_CORE_ENABLE; 1510 1511 /* send ipc */ 1512 ret = sof_ipc_tx_message(sdev->ipc, pm_core_config.hdr.cmd, 1513 &pm_core_config, sizeof(pm_core_config), 1514 &pm_core_config, sizeof(pm_core_config)); 1515 if (ret < 0) 1516 dev_err(dev, "error: core enable ipc failure\n"); 1517 1518 return ret; 1519 } 1520 1521 static int sof_widget_load_pipeline(struct snd_soc_component *scomp, 1522 int index, struct snd_sof_widget *swidget, 1523 struct snd_soc_tplg_dapm_widget *tw, 1524 struct sof_ipc_comp_reply *r) 1525 { 1526 struct snd_soc_tplg_private *private = &tw->priv; 1527 struct sof_ipc_pipe_new *pipeline; 1528 struct snd_sof_widget *comp_swidget; 1529 int ret; 1530 1531 pipeline = kzalloc(sizeof(*pipeline), GFP_KERNEL); 1532 if (!pipeline) 1533 return -ENOMEM; 1534 1535 /* configure dai IPC message */ 1536 pipeline->hdr.size = sizeof(*pipeline); 1537 pipeline->hdr.cmd = SOF_IPC_GLB_TPLG_MSG | SOF_IPC_TPLG_PIPE_NEW; 1538 pipeline->pipeline_id = index; 1539 pipeline->comp_id = swidget->comp_id; 1540 1541 /* component at start of pipeline is our stream id */ 1542 comp_swidget = snd_sof_find_swidget(scomp, tw->sname); 1543 if (!comp_swidget) { 1544 dev_err(scomp->dev, "error: widget %s refers to non existent widget %s\n", 1545 tw->name, tw->sname); 1546 ret = -EINVAL; 1547 goto err; 1548 } 1549 1550 pipeline->sched_id = comp_swidget->comp_id; 1551 1552 dev_dbg(scomp->dev, "tplg: pipeline id %d comp %d scheduling comp id %d\n", 1553 pipeline->pipeline_id, pipeline->comp_id, pipeline->sched_id); 1554 1555 ret = sof_parse_tokens(scomp, pipeline, sched_tokens, 1556 ARRAY_SIZE(sched_tokens), private->array, 1557 le32_to_cpu(private->size)); 1558 if (ret != 0) { 1559 dev_err(scomp->dev, "error: parse pipeline tokens failed %d\n", 1560 private->size); 1561 goto err; 1562 } 1563 1564 dev_dbg(scomp->dev, "pipeline %s: period %d pri %d mips %d core %d frames %d\n", 1565 swidget->widget->name, pipeline->period, pipeline->priority, 1566 pipeline->period_mips, pipeline->core, pipeline->frames_per_sched); 1567 1568 swidget->private = pipeline; 1569 1570 /* send ipc's to create pipeline comp and power up schedule core */ 1571 ret = sof_load_pipeline_ipc(scomp->dev, pipeline, r); 1572 if (ret >= 0) 1573 return ret; 1574 err: 1575 kfree(pipeline); 1576 return ret; 1577 } 1578 1579 /* 1580 * Mixer topology 1581 */ 1582 1583 static int sof_widget_load_mixer(struct snd_soc_component *scomp, int index, 1584 struct snd_sof_widget *swidget, 1585 struct snd_soc_tplg_dapm_widget *tw, 1586 struct sof_ipc_comp_reply *r) 1587 { 1588 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); 1589 struct snd_soc_tplg_private *private = &tw->priv; 1590 struct sof_ipc_comp_mixer *mixer; 1591 int ret; 1592 1593 mixer = kzalloc(sizeof(*mixer), GFP_KERNEL); 1594 if (!mixer) 1595 return -ENOMEM; 1596 1597 /* configure mixer IPC message */ 1598 mixer->comp.hdr.size = sizeof(*mixer); 1599 mixer->comp.hdr.cmd = SOF_IPC_GLB_TPLG_MSG | SOF_IPC_TPLG_COMP_NEW; 1600 mixer->comp.id = swidget->comp_id; 1601 mixer->comp.type = SOF_COMP_MIXER; 1602 mixer->comp.pipeline_id = index; 1603 mixer->config.hdr.size = sizeof(mixer->config); 1604 1605 ret = sof_parse_tokens(scomp, &mixer->config, comp_tokens, 1606 ARRAY_SIZE(comp_tokens), private->array, 1607 le32_to_cpu(private->size)); 1608 if (ret != 0) { 1609 dev_err(scomp->dev, "error: parse mixer.cfg tokens failed %d\n", 1610 private->size); 1611 kfree(mixer); 1612 return ret; 1613 } 1614 1615 sof_dbg_comp_config(scomp, &mixer->config); 1616 1617 swidget->private = mixer; 1618 1619 ret = sof_ipc_tx_message(sdev->ipc, mixer->comp.hdr.cmd, mixer, 1620 sizeof(*mixer), r, sizeof(*r)); 1621 if (ret < 0) 1622 kfree(mixer); 1623 1624 return ret; 1625 } 1626 1627 /* 1628 * Mux topology 1629 */ 1630 static int sof_widget_load_mux(struct snd_soc_component *scomp, int index, 1631 struct snd_sof_widget *swidget, 1632 struct snd_soc_tplg_dapm_widget *tw, 1633 struct sof_ipc_comp_reply *r) 1634 { 1635 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); 1636 struct snd_soc_tplg_private *private = &tw->priv; 1637 struct sof_ipc_comp_mux *mux; 1638 int ret; 1639 1640 mux = kzalloc(sizeof(*mux), GFP_KERNEL); 1641 if (!mux) 1642 return -ENOMEM; 1643 1644 /* configure mux IPC message */ 1645 mux->comp.hdr.size = sizeof(*mux); 1646 mux->comp.hdr.cmd = SOF_IPC_GLB_TPLG_MSG | SOF_IPC_TPLG_COMP_NEW; 1647 mux->comp.id = swidget->comp_id; 1648 mux->comp.type = SOF_COMP_MUX; 1649 mux->comp.pipeline_id = index; 1650 mux->config.hdr.size = sizeof(mux->config); 1651 1652 ret = sof_parse_tokens(scomp, &mux->config, comp_tokens, 1653 ARRAY_SIZE(comp_tokens), private->array, 1654 le32_to_cpu(private->size)); 1655 if (ret != 0) { 1656 dev_err(scomp->dev, "error: parse mux.cfg tokens failed %d\n", 1657 private->size); 1658 kfree(mux); 1659 return ret; 1660 } 1661 1662 sof_dbg_comp_config(scomp, &mux->config); 1663 1664 swidget->private = mux; 1665 1666 ret = sof_ipc_tx_message(sdev->ipc, mux->comp.hdr.cmd, mux, 1667 sizeof(*mux), r, sizeof(*r)); 1668 if (ret < 0) 1669 kfree(mux); 1670 1671 return ret; 1672 } 1673 1674 /* 1675 * PGA Topology 1676 */ 1677 1678 static int sof_widget_load_pga(struct snd_soc_component *scomp, int index, 1679 struct snd_sof_widget *swidget, 1680 struct snd_soc_tplg_dapm_widget *tw, 1681 struct sof_ipc_comp_reply *r) 1682 { 1683 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); 1684 struct snd_soc_tplg_private *private = &tw->priv; 1685 struct sof_ipc_comp_volume *volume; 1686 struct snd_sof_control *scontrol; 1687 int min_step; 1688 int max_step; 1689 int ret; 1690 1691 volume = kzalloc(sizeof(*volume), GFP_KERNEL); 1692 if (!volume) 1693 return -ENOMEM; 1694 1695 if (!le32_to_cpu(tw->num_kcontrols)) { 1696 dev_err(scomp->dev, "error: invalid kcontrol count %d for volume\n", 1697 tw->num_kcontrols); 1698 ret = -EINVAL; 1699 goto err; 1700 } 1701 1702 /* configure volume IPC message */ 1703 volume->comp.hdr.size = sizeof(*volume); 1704 volume->comp.hdr.cmd = SOF_IPC_GLB_TPLG_MSG | SOF_IPC_TPLG_COMP_NEW; 1705 volume->comp.id = swidget->comp_id; 1706 volume->comp.type = SOF_COMP_VOLUME; 1707 volume->comp.pipeline_id = index; 1708 volume->config.hdr.size = sizeof(volume->config); 1709 1710 ret = sof_parse_tokens(scomp, volume, volume_tokens, 1711 ARRAY_SIZE(volume_tokens), private->array, 1712 le32_to_cpu(private->size)); 1713 if (ret != 0) { 1714 dev_err(scomp->dev, "error: parse volume tokens failed %d\n", 1715 private->size); 1716 goto err; 1717 } 1718 ret = sof_parse_tokens(scomp, &volume->config, comp_tokens, 1719 ARRAY_SIZE(comp_tokens), private->array, 1720 le32_to_cpu(private->size)); 1721 if (ret != 0) { 1722 dev_err(scomp->dev, "error: parse volume.cfg tokens failed %d\n", 1723 le32_to_cpu(private->size)); 1724 goto err; 1725 } 1726 1727 sof_dbg_comp_config(scomp, &volume->config); 1728 1729 swidget->private = volume; 1730 1731 list_for_each_entry(scontrol, &sdev->kcontrol_list, list) { 1732 if (scontrol->comp_id == swidget->comp_id && 1733 scontrol->volume_table) { 1734 min_step = scontrol->min_volume_step; 1735 max_step = scontrol->max_volume_step; 1736 volume->min_value = scontrol->volume_table[min_step]; 1737 volume->max_value = scontrol->volume_table[max_step]; 1738 volume->channels = scontrol->num_channels; 1739 break; 1740 } 1741 } 1742 1743 ret = sof_ipc_tx_message(sdev->ipc, volume->comp.hdr.cmd, volume, 1744 sizeof(*volume), r, sizeof(*r)); 1745 if (ret >= 0) 1746 return ret; 1747 err: 1748 kfree(volume); 1749 return ret; 1750 } 1751 1752 /* 1753 * SRC Topology 1754 */ 1755 1756 static int sof_widget_load_src(struct snd_soc_component *scomp, int index, 1757 struct snd_sof_widget *swidget, 1758 struct snd_soc_tplg_dapm_widget *tw, 1759 struct sof_ipc_comp_reply *r) 1760 { 1761 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); 1762 struct snd_soc_tplg_private *private = &tw->priv; 1763 struct sof_ipc_comp_src *src; 1764 int ret; 1765 1766 src = kzalloc(sizeof(*src), GFP_KERNEL); 1767 if (!src) 1768 return -ENOMEM; 1769 1770 /* configure src IPC message */ 1771 src->comp.hdr.size = sizeof(*src); 1772 src->comp.hdr.cmd = SOF_IPC_GLB_TPLG_MSG | SOF_IPC_TPLG_COMP_NEW; 1773 src->comp.id = swidget->comp_id; 1774 src->comp.type = SOF_COMP_SRC; 1775 src->comp.pipeline_id = index; 1776 src->config.hdr.size = sizeof(src->config); 1777 1778 ret = sof_parse_tokens(scomp, src, src_tokens, 1779 ARRAY_SIZE(src_tokens), private->array, 1780 le32_to_cpu(private->size)); 1781 if (ret != 0) { 1782 dev_err(scomp->dev, "error: parse src tokens failed %d\n", 1783 private->size); 1784 goto err; 1785 } 1786 1787 ret = sof_parse_tokens(scomp, &src->config, comp_tokens, 1788 ARRAY_SIZE(comp_tokens), private->array, 1789 le32_to_cpu(private->size)); 1790 if (ret != 0) { 1791 dev_err(scomp->dev, "error: parse src.cfg tokens failed %d\n", 1792 le32_to_cpu(private->size)); 1793 goto err; 1794 } 1795 1796 dev_dbg(scomp->dev, "src %s: source rate %d sink rate %d\n", 1797 swidget->widget->name, src->source_rate, src->sink_rate); 1798 sof_dbg_comp_config(scomp, &src->config); 1799 1800 swidget->private = src; 1801 1802 ret = sof_ipc_tx_message(sdev->ipc, src->comp.hdr.cmd, src, 1803 sizeof(*src), r, sizeof(*r)); 1804 if (ret >= 0) 1805 return ret; 1806 err: 1807 kfree(src); 1808 return ret; 1809 } 1810 1811 /* 1812 * ASRC Topology 1813 */ 1814 1815 static int sof_widget_load_asrc(struct snd_soc_component *scomp, int index, 1816 struct snd_sof_widget *swidget, 1817 struct snd_soc_tplg_dapm_widget *tw, 1818 struct sof_ipc_comp_reply *r) 1819 { 1820 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); 1821 struct snd_soc_tplg_private *private = &tw->priv; 1822 struct sof_ipc_comp_asrc *asrc; 1823 int ret; 1824 1825 asrc = kzalloc(sizeof(*asrc), GFP_KERNEL); 1826 if (!asrc) 1827 return -ENOMEM; 1828 1829 /* configure ASRC IPC message */ 1830 asrc->comp.hdr.size = sizeof(*asrc); 1831 asrc->comp.hdr.cmd = SOF_IPC_GLB_TPLG_MSG | SOF_IPC_TPLG_COMP_NEW; 1832 asrc->comp.id = swidget->comp_id; 1833 asrc->comp.type = SOF_COMP_ASRC; 1834 asrc->comp.pipeline_id = index; 1835 asrc->config.hdr.size = sizeof(asrc->config); 1836 1837 ret = sof_parse_tokens(scomp, asrc, asrc_tokens, 1838 ARRAY_SIZE(asrc_tokens), private->array, 1839 le32_to_cpu(private->size)); 1840 if (ret != 0) { 1841 dev_err(scomp->dev, "error: parse asrc tokens failed %d\n", 1842 private->size); 1843 goto err; 1844 } 1845 1846 ret = sof_parse_tokens(scomp, &asrc->config, comp_tokens, 1847 ARRAY_SIZE(comp_tokens), private->array, 1848 le32_to_cpu(private->size)); 1849 if (ret != 0) { 1850 dev_err(scomp->dev, "error: parse asrc.cfg tokens failed %d\n", 1851 le32_to_cpu(private->size)); 1852 goto err; 1853 } 1854 1855 dev_dbg(scomp->dev, "asrc %s: source rate %d sink rate %d " 1856 "asynch %d operation %d\n", 1857 swidget->widget->name, asrc->source_rate, asrc->sink_rate, 1858 asrc->asynchronous_mode, asrc->operation_mode); 1859 sof_dbg_comp_config(scomp, &asrc->config); 1860 1861 swidget->private = asrc; 1862 1863 ret = sof_ipc_tx_message(sdev->ipc, asrc->comp.hdr.cmd, asrc, 1864 sizeof(*asrc), r, sizeof(*r)); 1865 if (ret >= 0) 1866 return ret; 1867 err: 1868 kfree(asrc); 1869 return ret; 1870 } 1871 1872 /* 1873 * Signal Generator Topology 1874 */ 1875 1876 static int sof_widget_load_siggen(struct snd_soc_component *scomp, int index, 1877 struct snd_sof_widget *swidget, 1878 struct snd_soc_tplg_dapm_widget *tw, 1879 struct sof_ipc_comp_reply *r) 1880 { 1881 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); 1882 struct snd_soc_tplg_private *private = &tw->priv; 1883 struct sof_ipc_comp_tone *tone; 1884 int ret; 1885 1886 tone = kzalloc(sizeof(*tone), GFP_KERNEL); 1887 if (!tone) 1888 return -ENOMEM; 1889 1890 /* configure siggen IPC message */ 1891 tone->comp.hdr.size = sizeof(*tone); 1892 tone->comp.hdr.cmd = SOF_IPC_GLB_TPLG_MSG | SOF_IPC_TPLG_COMP_NEW; 1893 tone->comp.id = swidget->comp_id; 1894 tone->comp.type = SOF_COMP_TONE; 1895 tone->comp.pipeline_id = index; 1896 tone->config.hdr.size = sizeof(tone->config); 1897 1898 ret = sof_parse_tokens(scomp, tone, tone_tokens, 1899 ARRAY_SIZE(tone_tokens), private->array, 1900 le32_to_cpu(private->size)); 1901 if (ret != 0) { 1902 dev_err(scomp->dev, "error: parse tone tokens failed %d\n", 1903 le32_to_cpu(private->size)); 1904 goto err; 1905 } 1906 1907 ret = sof_parse_tokens(scomp, &tone->config, comp_tokens, 1908 ARRAY_SIZE(comp_tokens), private->array, 1909 le32_to_cpu(private->size)); 1910 if (ret != 0) { 1911 dev_err(scomp->dev, "error: parse tone.cfg tokens failed %d\n", 1912 le32_to_cpu(private->size)); 1913 goto err; 1914 } 1915 1916 dev_dbg(scomp->dev, "tone %s: frequency %d amplitude %d\n", 1917 swidget->widget->name, tone->frequency, tone->amplitude); 1918 sof_dbg_comp_config(scomp, &tone->config); 1919 1920 swidget->private = tone; 1921 1922 ret = sof_ipc_tx_message(sdev->ipc, tone->comp.hdr.cmd, tone, 1923 sizeof(*tone), r, sizeof(*r)); 1924 if (ret >= 0) 1925 return ret; 1926 err: 1927 kfree(tone); 1928 return ret; 1929 } 1930 1931 static int sof_get_control_data(struct snd_soc_component *scomp, 1932 struct snd_soc_dapm_widget *widget, 1933 struct sof_widget_data *wdata, 1934 size_t *size) 1935 { 1936 const struct snd_kcontrol_new *kc; 1937 struct soc_mixer_control *sm; 1938 struct soc_bytes_ext *sbe; 1939 struct soc_enum *se; 1940 int i; 1941 1942 *size = 0; 1943 1944 for (i = 0; i < widget->num_kcontrols; i++) { 1945 kc = &widget->kcontrol_news[i]; 1946 1947 switch (widget->dobj.widget.kcontrol_type) { 1948 case SND_SOC_TPLG_TYPE_MIXER: 1949 sm = (struct soc_mixer_control *)kc->private_value; 1950 wdata[i].control = sm->dobj.private; 1951 break; 1952 case SND_SOC_TPLG_TYPE_BYTES: 1953 sbe = (struct soc_bytes_ext *)kc->private_value; 1954 wdata[i].control = sbe->dobj.private; 1955 break; 1956 case SND_SOC_TPLG_TYPE_ENUM: 1957 se = (struct soc_enum *)kc->private_value; 1958 wdata[i].control = se->dobj.private; 1959 break; 1960 default: 1961 dev_err(scomp->dev, "error: unknown kcontrol type %d in widget %s\n", 1962 widget->dobj.widget.kcontrol_type, 1963 widget->name); 1964 return -EINVAL; 1965 } 1966 1967 if (!wdata[i].control) { 1968 dev_err(scomp->dev, "error: no scontrol for widget %s\n", 1969 widget->name); 1970 return -EINVAL; 1971 } 1972 1973 wdata[i].pdata = wdata[i].control->control_data->data; 1974 if (!wdata[i].pdata) 1975 return -EINVAL; 1976 1977 /* make sure data is valid - data can be updated at runtime */ 1978 if (wdata[i].pdata->magic != SOF_ABI_MAGIC) 1979 return -EINVAL; 1980 1981 *size += wdata[i].pdata->size; 1982 1983 /* get data type */ 1984 switch (wdata[i].control->cmd) { 1985 case SOF_CTRL_CMD_VOLUME: 1986 case SOF_CTRL_CMD_ENUM: 1987 case SOF_CTRL_CMD_SWITCH: 1988 wdata[i].ipc_cmd = SOF_IPC_COMP_SET_VALUE; 1989 wdata[i].ctrl_type = SOF_CTRL_TYPE_VALUE_CHAN_SET; 1990 break; 1991 case SOF_CTRL_CMD_BINARY: 1992 wdata[i].ipc_cmd = SOF_IPC_COMP_SET_DATA; 1993 wdata[i].ctrl_type = SOF_CTRL_TYPE_DATA_SET; 1994 break; 1995 default: 1996 break; 1997 } 1998 } 1999 2000 return 0; 2001 } 2002 2003 static int sof_process_load(struct snd_soc_component *scomp, int index, 2004 struct snd_sof_widget *swidget, 2005 struct snd_soc_tplg_dapm_widget *tw, 2006 struct sof_ipc_comp_reply *r, 2007 int type) 2008 { 2009 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); 2010 struct snd_soc_dapm_widget *widget = swidget->widget; 2011 struct snd_soc_tplg_private *private = &tw->priv; 2012 struct sof_ipc_comp_process *process = NULL; 2013 struct sof_widget_data *wdata = NULL; 2014 size_t ipc_data_size = 0; 2015 size_t ipc_size; 2016 int offset = 0; 2017 int ret = 0; 2018 int i; 2019 2020 if (type == SOF_COMP_NONE) { 2021 dev_err(scomp->dev, "error: invalid process comp type %d\n", 2022 type); 2023 return -EINVAL; 2024 } 2025 2026 /* allocate struct for widget control data sizes and types */ 2027 if (widget->num_kcontrols) { 2028 wdata = kcalloc(widget->num_kcontrols, 2029 sizeof(*wdata), 2030 GFP_KERNEL); 2031 2032 if (!wdata) 2033 return -ENOMEM; 2034 2035 /* get possible component controls and get size of all pdata */ 2036 ret = sof_get_control_data(scomp, widget, wdata, 2037 &ipc_data_size); 2038 2039 if (ret < 0) 2040 goto out; 2041 } 2042 2043 ipc_size = sizeof(struct sof_ipc_comp_process) + 2044 le32_to_cpu(private->size) + 2045 ipc_data_size; 2046 2047 /* we are exceeding max ipc size, config needs to be sent separately */ 2048 if (ipc_size > SOF_IPC_MSG_MAX_SIZE) { 2049 ipc_size -= ipc_data_size; 2050 ipc_data_size = 0; 2051 } 2052 2053 process = kzalloc(ipc_size, GFP_KERNEL); 2054 if (!process) { 2055 ret = -ENOMEM; 2056 goto out; 2057 } 2058 2059 /* configure iir IPC message */ 2060 process->comp.hdr.size = ipc_size; 2061 process->comp.hdr.cmd = SOF_IPC_GLB_TPLG_MSG | SOF_IPC_TPLG_COMP_NEW; 2062 process->comp.id = swidget->comp_id; 2063 process->comp.type = type; 2064 process->comp.pipeline_id = index; 2065 process->config.hdr.size = sizeof(process->config); 2066 2067 ret = sof_parse_tokens(scomp, &process->config, comp_tokens, 2068 ARRAY_SIZE(comp_tokens), private->array, 2069 le32_to_cpu(private->size)); 2070 if (ret != 0) { 2071 dev_err(scomp->dev, "error: parse process.cfg tokens failed %d\n", 2072 le32_to_cpu(private->size)); 2073 goto err; 2074 } 2075 2076 sof_dbg_comp_config(scomp, &process->config); 2077 2078 /* 2079 * found private data in control, so copy it. 2080 * get possible component controls - get size of all pdata, 2081 * then memcpy with headers 2082 */ 2083 if (ipc_data_size) { 2084 for (i = 0; i < widget->num_kcontrols; i++) { 2085 memcpy(&process->data + offset, 2086 wdata[i].pdata->data, 2087 wdata[i].pdata->size); 2088 offset += wdata[i].pdata->size; 2089 } 2090 } 2091 2092 process->size = ipc_data_size; 2093 swidget->private = process; 2094 2095 ret = sof_ipc_tx_message(sdev->ipc, process->comp.hdr.cmd, process, 2096 ipc_size, r, sizeof(*r)); 2097 2098 if (ret < 0) { 2099 dev_err(scomp->dev, "error: create process failed\n"); 2100 goto err; 2101 } 2102 2103 /* we sent the data in single message so return */ 2104 if (ipc_data_size) 2105 goto out; 2106 2107 /* send control data with large message supported method */ 2108 for (i = 0; i < widget->num_kcontrols; i++) { 2109 wdata[i].control->readback_offset = 0; 2110 ret = snd_sof_ipc_set_get_comp_data(wdata[i].control, 2111 wdata[i].ipc_cmd, 2112 wdata[i].ctrl_type, 2113 wdata[i].control->cmd, 2114 true); 2115 if (ret != 0) { 2116 dev_err(scomp->dev, "error: send control failed\n"); 2117 break; 2118 } 2119 } 2120 2121 err: 2122 if (ret < 0) 2123 kfree(process); 2124 out: 2125 kfree(wdata); 2126 return ret; 2127 } 2128 2129 /* 2130 * Processing Component Topology - can be "effect", "codec", or general 2131 * "processing". 2132 */ 2133 2134 static int sof_widget_load_process(struct snd_soc_component *scomp, int index, 2135 struct snd_sof_widget *swidget, 2136 struct snd_soc_tplg_dapm_widget *tw, 2137 struct sof_ipc_comp_reply *r) 2138 { 2139 struct snd_soc_tplg_private *private = &tw->priv; 2140 struct sof_ipc_comp_process config; 2141 int ret; 2142 2143 /* check we have some tokens - we need at least process type */ 2144 if (le32_to_cpu(private->size) == 0) { 2145 dev_err(scomp->dev, "error: process tokens not found\n"); 2146 return -EINVAL; 2147 } 2148 2149 memset(&config, 0, sizeof(config)); 2150 2151 /* get the process token */ 2152 ret = sof_parse_tokens(scomp, &config, process_tokens, 2153 ARRAY_SIZE(process_tokens), private->array, 2154 le32_to_cpu(private->size)); 2155 if (ret != 0) { 2156 dev_err(scomp->dev, "error: parse process tokens failed %d\n", 2157 le32_to_cpu(private->size)); 2158 return ret; 2159 } 2160 2161 /* now load process specific data and send IPC */ 2162 ret = sof_process_load(scomp, index, swidget, tw, r, 2163 find_process_comp_type(config.type)); 2164 if (ret < 0) { 2165 dev_err(scomp->dev, "error: process loading failed\n"); 2166 return ret; 2167 } 2168 2169 return 0; 2170 } 2171 2172 static int sof_widget_bind_event(struct snd_soc_component *scomp, 2173 struct snd_sof_widget *swidget, 2174 u16 event_type) 2175 { 2176 struct sof_ipc_comp *ipc_comp; 2177 2178 /* validate widget event type */ 2179 switch (event_type) { 2180 case SOF_KEYWORD_DETECT_DAPM_EVENT: 2181 /* only KEYWORD_DETECT comps should handle this */ 2182 if (swidget->id != snd_soc_dapm_effect) 2183 break; 2184 2185 ipc_comp = swidget->private; 2186 if (ipc_comp && ipc_comp->type != SOF_COMP_KEYWORD_DETECT) 2187 break; 2188 2189 /* bind event to keyword detect comp */ 2190 return snd_soc_tplg_widget_bind_event(swidget->widget, 2191 sof_kwd_events, 2192 ARRAY_SIZE(sof_kwd_events), 2193 event_type); 2194 default: 2195 break; 2196 } 2197 2198 dev_err(scomp->dev, 2199 "error: invalid event type %d for widget %s\n", 2200 event_type, swidget->widget->name); 2201 return -EINVAL; 2202 } 2203 2204 /* external widget init - used for any driver specific init */ 2205 static int sof_widget_ready(struct snd_soc_component *scomp, int index, 2206 struct snd_soc_dapm_widget *w, 2207 struct snd_soc_tplg_dapm_widget *tw) 2208 { 2209 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); 2210 struct snd_sof_widget *swidget; 2211 struct snd_sof_dai *dai; 2212 struct sof_ipc_comp_reply reply; 2213 struct snd_sof_control *scontrol; 2214 int ret = 0; 2215 2216 swidget = kzalloc(sizeof(*swidget), GFP_KERNEL); 2217 if (!swidget) 2218 return -ENOMEM; 2219 2220 swidget->scomp = scomp; 2221 swidget->widget = w; 2222 swidget->comp_id = sdev->next_comp_id++; 2223 swidget->complete = 0; 2224 swidget->id = w->id; 2225 swidget->pipeline_id = index; 2226 swidget->private = NULL; 2227 memset(&reply, 0, sizeof(reply)); 2228 2229 dev_dbg(scomp->dev, "tplg: ready widget id %d pipe %d type %d name : %s stream %s\n", 2230 swidget->comp_id, index, swidget->id, tw->name, 2231 strnlen(tw->sname, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) > 0 2232 ? tw->sname : "none"); 2233 2234 /* handle any special case widgets */ 2235 switch (w->id) { 2236 case snd_soc_dapm_dai_in: 2237 case snd_soc_dapm_dai_out: 2238 dai = kzalloc(sizeof(*dai), GFP_KERNEL); 2239 if (!dai) { 2240 kfree(swidget); 2241 return -ENOMEM; 2242 } 2243 2244 ret = sof_widget_load_dai(scomp, index, swidget, tw, &reply, 2245 dai); 2246 if (ret == 0) { 2247 sof_connect_dai_widget(scomp, w, tw, dai); 2248 list_add(&dai->list, &sdev->dai_list); 2249 swidget->private = dai; 2250 } else { 2251 kfree(dai); 2252 } 2253 break; 2254 case snd_soc_dapm_mixer: 2255 ret = sof_widget_load_mixer(scomp, index, swidget, tw, &reply); 2256 break; 2257 case snd_soc_dapm_pga: 2258 ret = sof_widget_load_pga(scomp, index, swidget, tw, &reply); 2259 /* Find scontrol for this pga and set readback offset*/ 2260 list_for_each_entry(scontrol, &sdev->kcontrol_list, list) { 2261 if (scontrol->comp_id == swidget->comp_id) { 2262 scontrol->readback_offset = reply.offset; 2263 break; 2264 } 2265 } 2266 break; 2267 case snd_soc_dapm_buffer: 2268 ret = sof_widget_load_buffer(scomp, index, swidget, tw, &reply); 2269 break; 2270 case snd_soc_dapm_scheduler: 2271 ret = sof_widget_load_pipeline(scomp, index, swidget, tw, 2272 &reply); 2273 break; 2274 case snd_soc_dapm_aif_out: 2275 ret = sof_widget_load_pcm(scomp, index, swidget, 2276 SOF_IPC_STREAM_CAPTURE, tw, &reply); 2277 break; 2278 case snd_soc_dapm_aif_in: 2279 ret = sof_widget_load_pcm(scomp, index, swidget, 2280 SOF_IPC_STREAM_PLAYBACK, tw, &reply); 2281 break; 2282 case snd_soc_dapm_src: 2283 ret = sof_widget_load_src(scomp, index, swidget, tw, &reply); 2284 break; 2285 case snd_soc_dapm_asrc: 2286 ret = sof_widget_load_asrc(scomp, index, swidget, tw, &reply); 2287 break; 2288 case snd_soc_dapm_siggen: 2289 ret = sof_widget_load_siggen(scomp, index, swidget, tw, &reply); 2290 break; 2291 case snd_soc_dapm_effect: 2292 ret = sof_widget_load_process(scomp, index, swidget, tw, 2293 &reply); 2294 break; 2295 case snd_soc_dapm_mux: 2296 case snd_soc_dapm_demux: 2297 ret = sof_widget_load_mux(scomp, index, swidget, tw, &reply); 2298 break; 2299 case snd_soc_dapm_switch: 2300 case snd_soc_dapm_dai_link: 2301 case snd_soc_dapm_kcontrol: 2302 default: 2303 dev_warn(scomp->dev, "warning: widget type %d name %s not handled\n", 2304 swidget->id, tw->name); 2305 break; 2306 } 2307 2308 /* check IPC reply */ 2309 if (ret < 0 || reply.rhdr.error < 0) { 2310 dev_err(scomp->dev, 2311 "error: DSP failed to add widget id %d type %d name : %s stream %s reply %d\n", 2312 tw->shift, swidget->id, tw->name, 2313 strnlen(tw->sname, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) > 0 2314 ? tw->sname : "none", reply.rhdr.error); 2315 kfree(swidget); 2316 return ret; 2317 } 2318 2319 /* bind widget to external event */ 2320 if (tw->event_type) { 2321 ret = sof_widget_bind_event(scomp, swidget, 2322 le16_to_cpu(tw->event_type)); 2323 if (ret) { 2324 dev_err(scomp->dev, "error: widget event binding failed\n"); 2325 kfree(swidget->private); 2326 kfree(swidget); 2327 return ret; 2328 } 2329 } 2330 2331 w->dobj.private = swidget; 2332 list_add(&swidget->list, &sdev->widget_list); 2333 return ret; 2334 } 2335 2336 static int sof_route_unload(struct snd_soc_component *scomp, 2337 struct snd_soc_dobj *dobj) 2338 { 2339 struct snd_sof_route *sroute; 2340 2341 sroute = dobj->private; 2342 if (!sroute) 2343 return 0; 2344 2345 /* free sroute and its private data */ 2346 kfree(sroute->private); 2347 list_del(&sroute->list); 2348 kfree(sroute); 2349 2350 return 0; 2351 } 2352 2353 static int sof_widget_unload(struct snd_soc_component *scomp, 2354 struct snd_soc_dobj *dobj) 2355 { 2356 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); 2357 const struct snd_kcontrol_new *kc; 2358 struct snd_soc_dapm_widget *widget; 2359 struct sof_ipc_pipe_new *pipeline; 2360 struct snd_sof_control *scontrol; 2361 struct snd_sof_widget *swidget; 2362 struct soc_mixer_control *sm; 2363 struct soc_bytes_ext *sbe; 2364 struct snd_sof_dai *dai; 2365 struct soc_enum *se; 2366 int ret = 0; 2367 int i; 2368 2369 swidget = dobj->private; 2370 if (!swidget) 2371 return 0; 2372 2373 widget = swidget->widget; 2374 2375 switch (swidget->id) { 2376 case snd_soc_dapm_dai_in: 2377 case snd_soc_dapm_dai_out: 2378 dai = swidget->private; 2379 2380 if (dai) { 2381 /* free dai config */ 2382 kfree(dai->dai_config); 2383 list_del(&dai->list); 2384 } 2385 break; 2386 case snd_soc_dapm_scheduler: 2387 2388 /* power down the pipeline schedule core */ 2389 pipeline = swidget->private; 2390 ret = snd_sof_dsp_core_power_down(sdev, 1 << pipeline->core); 2391 if (ret < 0) 2392 dev_err(scomp->dev, "error: powering down pipeline schedule core %d\n", 2393 pipeline->core); 2394 2395 /* update enabled cores mask */ 2396 sdev->enabled_cores_mask &= ~(1 << pipeline->core); 2397 2398 break; 2399 default: 2400 break; 2401 } 2402 for (i = 0; i < widget->num_kcontrols; i++) { 2403 kc = &widget->kcontrol_news[i]; 2404 switch (dobj->widget.kcontrol_type) { 2405 case SND_SOC_TPLG_TYPE_MIXER: 2406 sm = (struct soc_mixer_control *)kc->private_value; 2407 scontrol = sm->dobj.private; 2408 if (sm->max > 1) 2409 kfree(scontrol->volume_table); 2410 break; 2411 case SND_SOC_TPLG_TYPE_ENUM: 2412 se = (struct soc_enum *)kc->private_value; 2413 scontrol = se->dobj.private; 2414 break; 2415 case SND_SOC_TPLG_TYPE_BYTES: 2416 sbe = (struct soc_bytes_ext *)kc->private_value; 2417 scontrol = sbe->dobj.private; 2418 break; 2419 default: 2420 dev_warn(scomp->dev, "unsupported kcontrol_type\n"); 2421 goto out; 2422 } 2423 kfree(scontrol->control_data); 2424 list_del(&scontrol->list); 2425 kfree(scontrol); 2426 } 2427 2428 out: 2429 /* free private value */ 2430 kfree(swidget->private); 2431 2432 /* remove and free swidget object */ 2433 list_del(&swidget->list); 2434 kfree(swidget); 2435 2436 return ret; 2437 } 2438 2439 /* 2440 * DAI HW configuration. 2441 */ 2442 2443 /* FE DAI - used for any driver specific init */ 2444 static int sof_dai_load(struct snd_soc_component *scomp, int index, 2445 struct snd_soc_dai_driver *dai_drv, 2446 struct snd_soc_tplg_pcm *pcm, struct snd_soc_dai *dai) 2447 { 2448 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); 2449 struct snd_soc_tplg_stream_caps *caps; 2450 struct snd_soc_tplg_private *private = &pcm->priv; 2451 struct snd_sof_pcm *spcm; 2452 int stream; 2453 int ret = 0; 2454 2455 /* nothing to do for BEs atm */ 2456 if (!pcm) 2457 return 0; 2458 2459 spcm = kzalloc(sizeof(*spcm), GFP_KERNEL); 2460 if (!spcm) 2461 return -ENOMEM; 2462 2463 spcm->scomp = scomp; 2464 2465 for_each_pcm_streams(stream) { 2466 spcm->stream[stream].comp_id = COMP_ID_UNASSIGNED; 2467 INIT_WORK(&spcm->stream[stream].period_elapsed_work, 2468 snd_sof_pcm_period_elapsed_work); 2469 } 2470 2471 spcm->pcm = *pcm; 2472 dev_dbg(scomp->dev, "tplg: load pcm %s\n", pcm->dai_name); 2473 2474 dai_drv->dobj.private = spcm; 2475 list_add(&spcm->list, &sdev->pcm_list); 2476 2477 ret = sof_parse_tokens(scomp, spcm, stream_tokens, 2478 ARRAY_SIZE(stream_tokens), private->array, 2479 le32_to_cpu(private->size)); 2480 if (ret) { 2481 dev_err(scomp->dev, "error: parse stream tokens failed %d\n", 2482 le32_to_cpu(private->size)); 2483 return ret; 2484 } 2485 2486 /* do we need to allocate playback PCM DMA pages */ 2487 if (!spcm->pcm.playback) 2488 goto capture; 2489 2490 stream = SNDRV_PCM_STREAM_PLAYBACK; 2491 2492 dev_vdbg(scomp->dev, "tplg: pcm %s stream tokens: playback d0i3:%d\n", 2493 spcm->pcm.pcm_name, spcm->stream[stream].d0i3_compatible); 2494 2495 caps = &spcm->pcm.caps[stream]; 2496 2497 /* allocate playback page table buffer */ 2498 ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, sdev->dev, 2499 PAGE_SIZE, &spcm->stream[stream].page_table); 2500 if (ret < 0) { 2501 dev_err(scomp->dev, "error: can't alloc page table for %s %d\n", 2502 caps->name, ret); 2503 2504 return ret; 2505 } 2506 2507 /* bind pcm to host comp */ 2508 ret = spcm_bind(scomp, spcm, stream); 2509 if (ret) { 2510 dev_err(scomp->dev, 2511 "error: can't bind pcm to host\n"); 2512 goto free_playback_tables; 2513 } 2514 2515 capture: 2516 stream = SNDRV_PCM_STREAM_CAPTURE; 2517 2518 /* do we need to allocate capture PCM DMA pages */ 2519 if (!spcm->pcm.capture) 2520 return ret; 2521 2522 dev_vdbg(scomp->dev, "tplg: pcm %s stream tokens: capture d0i3:%d\n", 2523 spcm->pcm.pcm_name, spcm->stream[stream].d0i3_compatible); 2524 2525 caps = &spcm->pcm.caps[stream]; 2526 2527 /* allocate capture page table buffer */ 2528 ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, sdev->dev, 2529 PAGE_SIZE, &spcm->stream[stream].page_table); 2530 if (ret < 0) { 2531 dev_err(scomp->dev, "error: can't alloc page table for %s %d\n", 2532 caps->name, ret); 2533 goto free_playback_tables; 2534 } 2535 2536 /* bind pcm to host comp */ 2537 ret = spcm_bind(scomp, spcm, stream); 2538 if (ret) { 2539 dev_err(scomp->dev, 2540 "error: can't bind pcm to host\n"); 2541 snd_dma_free_pages(&spcm->stream[stream].page_table); 2542 goto free_playback_tables; 2543 } 2544 2545 return ret; 2546 2547 free_playback_tables: 2548 if (spcm->pcm.playback) 2549 snd_dma_free_pages(&spcm->stream[SNDRV_PCM_STREAM_PLAYBACK].page_table); 2550 2551 return ret; 2552 } 2553 2554 static int sof_dai_unload(struct snd_soc_component *scomp, 2555 struct snd_soc_dobj *dobj) 2556 { 2557 struct snd_sof_pcm *spcm = dobj->private; 2558 2559 /* free PCM DMA pages */ 2560 if (spcm->pcm.playback) 2561 snd_dma_free_pages(&spcm->stream[SNDRV_PCM_STREAM_PLAYBACK].page_table); 2562 2563 if (spcm->pcm.capture) 2564 snd_dma_free_pages(&spcm->stream[SNDRV_PCM_STREAM_CAPTURE].page_table); 2565 2566 /* remove from list and free spcm */ 2567 list_del(&spcm->list); 2568 kfree(spcm); 2569 2570 return 0; 2571 } 2572 2573 static void sof_dai_set_format(struct snd_soc_tplg_hw_config *hw_config, 2574 struct sof_ipc_dai_config *config) 2575 { 2576 /* clock directions wrt codec */ 2577 if (hw_config->bclk_master == SND_SOC_TPLG_BCLK_CM) { 2578 /* codec is bclk master */ 2579 if (hw_config->fsync_master == SND_SOC_TPLG_FSYNC_CM) 2580 config->format |= SOF_DAI_FMT_CBM_CFM; 2581 else 2582 config->format |= SOF_DAI_FMT_CBM_CFS; 2583 } else { 2584 /* codec is bclk slave */ 2585 if (hw_config->fsync_master == SND_SOC_TPLG_FSYNC_CM) 2586 config->format |= SOF_DAI_FMT_CBS_CFM; 2587 else 2588 config->format |= SOF_DAI_FMT_CBS_CFS; 2589 } 2590 2591 /* inverted clocks ? */ 2592 if (hw_config->invert_bclk) { 2593 if (hw_config->invert_fsync) 2594 config->format |= SOF_DAI_FMT_IB_IF; 2595 else 2596 config->format |= SOF_DAI_FMT_IB_NF; 2597 } else { 2598 if (hw_config->invert_fsync) 2599 config->format |= SOF_DAI_FMT_NB_IF; 2600 else 2601 config->format |= SOF_DAI_FMT_NB_NF; 2602 } 2603 } 2604 2605 /* set config for all DAI's with name matching the link name */ 2606 static int sof_set_dai_config(struct snd_sof_dev *sdev, u32 size, 2607 struct snd_soc_dai_link *link, 2608 struct sof_ipc_dai_config *config) 2609 { 2610 struct snd_sof_dai *dai; 2611 int found = 0; 2612 2613 list_for_each_entry(dai, &sdev->dai_list, list) { 2614 if (!dai->name) 2615 continue; 2616 2617 if (strcmp(link->name, dai->name) == 0) { 2618 dai->dai_config = kmemdup(config, size, GFP_KERNEL); 2619 if (!dai->dai_config) 2620 return -ENOMEM; 2621 2622 /* set cpu_dai_name */ 2623 dai->cpu_dai_name = link->cpus->dai_name; 2624 2625 found = 1; 2626 } 2627 } 2628 2629 /* 2630 * machine driver may define a dai link with playback and capture 2631 * dai enabled, but the dai link in topology would support both, one 2632 * or none of them. Here print a warning message to notify user 2633 */ 2634 if (!found) { 2635 dev_warn(sdev->dev, "warning: failed to find dai for dai link %s", 2636 link->name); 2637 } 2638 2639 return 0; 2640 } 2641 2642 static int sof_link_ssp_load(struct snd_soc_component *scomp, int index, 2643 struct snd_soc_dai_link *link, 2644 struct snd_soc_tplg_link_config *cfg, 2645 struct snd_soc_tplg_hw_config *hw_config, 2646 struct sof_ipc_dai_config *config) 2647 { 2648 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); 2649 struct snd_soc_tplg_private *private = &cfg->priv; 2650 struct sof_ipc_reply reply; 2651 u32 size = sizeof(*config); 2652 int ret; 2653 2654 /* handle master/slave and inverted clocks */ 2655 sof_dai_set_format(hw_config, config); 2656 2657 /* init IPC */ 2658 memset(&config->ssp, 0, sizeof(struct sof_ipc_dai_ssp_params)); 2659 config->hdr.size = size; 2660 2661 ret = sof_parse_tokens(scomp, &config->ssp, ssp_tokens, 2662 ARRAY_SIZE(ssp_tokens), private->array, 2663 le32_to_cpu(private->size)); 2664 if (ret != 0) { 2665 dev_err(scomp->dev, "error: parse ssp tokens failed %d\n", 2666 le32_to_cpu(private->size)); 2667 return ret; 2668 } 2669 2670 config->ssp.mclk_rate = le32_to_cpu(hw_config->mclk_rate); 2671 config->ssp.bclk_rate = le32_to_cpu(hw_config->bclk_rate); 2672 config->ssp.fsync_rate = le32_to_cpu(hw_config->fsync_rate); 2673 config->ssp.tdm_slots = le32_to_cpu(hw_config->tdm_slots); 2674 config->ssp.tdm_slot_width = le32_to_cpu(hw_config->tdm_slot_width); 2675 config->ssp.mclk_direction = hw_config->mclk_direction; 2676 config->ssp.rx_slots = le32_to_cpu(hw_config->rx_slots); 2677 config->ssp.tx_slots = le32_to_cpu(hw_config->tx_slots); 2678 2679 dev_dbg(scomp->dev, "tplg: config SSP%d fmt 0x%x mclk %d bclk %d fclk %d width (%d)%d slots %d mclk id %d quirks %d\n", 2680 config->dai_index, config->format, 2681 config->ssp.mclk_rate, config->ssp.bclk_rate, 2682 config->ssp.fsync_rate, config->ssp.sample_valid_bits, 2683 config->ssp.tdm_slot_width, config->ssp.tdm_slots, 2684 config->ssp.mclk_id, config->ssp.quirks); 2685 2686 /* validate SSP fsync rate and channel count */ 2687 if (config->ssp.fsync_rate < 8000 || config->ssp.fsync_rate > 192000) { 2688 dev_err(scomp->dev, "error: invalid fsync rate for SSP%d\n", 2689 config->dai_index); 2690 return -EINVAL; 2691 } 2692 2693 if (config->ssp.tdm_slots < 1 || config->ssp.tdm_slots > 8) { 2694 dev_err(scomp->dev, "error: invalid channel count for SSP%d\n", 2695 config->dai_index); 2696 return -EINVAL; 2697 } 2698 2699 /* send message to DSP */ 2700 ret = sof_ipc_tx_message(sdev->ipc, 2701 config->hdr.cmd, config, size, &reply, 2702 sizeof(reply)); 2703 2704 if (ret < 0) { 2705 dev_err(scomp->dev, "error: failed to set DAI config for SSP%d\n", 2706 config->dai_index); 2707 return ret; 2708 } 2709 2710 /* set config for all DAI's with name matching the link name */ 2711 ret = sof_set_dai_config(sdev, size, link, config); 2712 if (ret < 0) 2713 dev_err(scomp->dev, "error: failed to save DAI config for SSP%d\n", 2714 config->dai_index); 2715 2716 return ret; 2717 } 2718 2719 static int sof_link_sai_load(struct snd_soc_component *scomp, int index, 2720 struct snd_soc_dai_link *link, 2721 struct snd_soc_tplg_link_config *cfg, 2722 struct snd_soc_tplg_hw_config *hw_config, 2723 struct sof_ipc_dai_config *config) 2724 { 2725 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); 2726 struct snd_soc_tplg_private *private = &cfg->priv; 2727 struct sof_ipc_reply reply; 2728 u32 size = sizeof(*config); 2729 int ret; 2730 2731 /* handle master/slave and inverted clocks */ 2732 sof_dai_set_format(hw_config, config); 2733 2734 /* init IPC */ 2735 memset(&config->sai, 0, sizeof(struct sof_ipc_dai_sai_params)); 2736 config->hdr.size = size; 2737 2738 ret = sof_parse_tokens(scomp, &config->sai, sai_tokens, 2739 ARRAY_SIZE(sai_tokens), private->array, 2740 le32_to_cpu(private->size)); 2741 if (ret != 0) { 2742 dev_err(scomp->dev, "error: parse sai tokens failed %d\n", 2743 le32_to_cpu(private->size)); 2744 return ret; 2745 } 2746 2747 config->sai.mclk_rate = le32_to_cpu(hw_config->mclk_rate); 2748 config->sai.mclk_direction = hw_config->mclk_direction; 2749 2750 config->sai.tdm_slots = le32_to_cpu(hw_config->tdm_slots); 2751 config->sai.tdm_slot_width = le32_to_cpu(hw_config->tdm_slot_width); 2752 config->sai.rx_slots = le32_to_cpu(hw_config->rx_slots); 2753 config->sai.tx_slots = le32_to_cpu(hw_config->tx_slots); 2754 2755 dev_info(scomp->dev, 2756 "tplg: config SAI%d fmt 0x%x mclk %d width %d slots %d mclk id %d\n", 2757 config->dai_index, config->format, 2758 config->sai.mclk_rate, config->sai.tdm_slot_width, 2759 config->sai.tdm_slots, config->sai.mclk_id); 2760 2761 if (config->sai.tdm_slots < 1 || config->sai.tdm_slots > 8) { 2762 dev_err(scomp->dev, "error: invalid channel count for SAI%d\n", 2763 config->dai_index); 2764 return -EINVAL; 2765 } 2766 2767 /* send message to DSP */ 2768 ret = sof_ipc_tx_message(sdev->ipc, 2769 config->hdr.cmd, config, size, &reply, 2770 sizeof(reply)); 2771 2772 if (ret < 0) { 2773 dev_err(scomp->dev, "error: failed to set DAI config for SAI%d\n", 2774 config->dai_index); 2775 return ret; 2776 } 2777 2778 /* set config for all DAI's with name matching the link name */ 2779 ret = sof_set_dai_config(sdev, size, link, config); 2780 if (ret < 0) 2781 dev_err(scomp->dev, "error: failed to save DAI config for SAI%d\n", 2782 config->dai_index); 2783 2784 return ret; 2785 } 2786 2787 static int sof_link_esai_load(struct snd_soc_component *scomp, int index, 2788 struct snd_soc_dai_link *link, 2789 struct snd_soc_tplg_link_config *cfg, 2790 struct snd_soc_tplg_hw_config *hw_config, 2791 struct sof_ipc_dai_config *config) 2792 { 2793 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); 2794 struct snd_soc_tplg_private *private = &cfg->priv; 2795 struct sof_ipc_reply reply; 2796 u32 size = sizeof(*config); 2797 int ret; 2798 2799 /* handle master/slave and inverted clocks */ 2800 sof_dai_set_format(hw_config, config); 2801 2802 /* init IPC */ 2803 memset(&config->esai, 0, sizeof(struct sof_ipc_dai_esai_params)); 2804 config->hdr.size = size; 2805 2806 ret = sof_parse_tokens(scomp, &config->esai, esai_tokens, 2807 ARRAY_SIZE(esai_tokens), private->array, 2808 le32_to_cpu(private->size)); 2809 if (ret != 0) { 2810 dev_err(scomp->dev, "error: parse esai tokens failed %d\n", 2811 le32_to_cpu(private->size)); 2812 return ret; 2813 } 2814 2815 config->esai.mclk_rate = le32_to_cpu(hw_config->mclk_rate); 2816 config->esai.bclk_rate = le32_to_cpu(hw_config->bclk_rate); 2817 config->esai.fsync_rate = le32_to_cpu(hw_config->fsync_rate); 2818 config->esai.mclk_direction = hw_config->mclk_direction; 2819 config->esai.tdm_slots = le32_to_cpu(hw_config->tdm_slots); 2820 config->esai.tdm_slot_width = le32_to_cpu(hw_config->tdm_slot_width); 2821 config->esai.rx_slots = le32_to_cpu(hw_config->rx_slots); 2822 config->esai.tx_slots = le32_to_cpu(hw_config->tx_slots); 2823 2824 dev_info(scomp->dev, 2825 "tplg: config ESAI%d fmt 0x%x mclk %d width %d slots %d mclk id %d\n", 2826 config->dai_index, config->format, 2827 config->esai.mclk_rate, config->esai.tdm_slot_width, 2828 config->esai.tdm_slots, config->esai.mclk_id); 2829 2830 if (config->esai.tdm_slots < 1 || config->esai.tdm_slots > 8) { 2831 dev_err(scomp->dev, "error: invalid channel count for ESAI%d\n", 2832 config->dai_index); 2833 return -EINVAL; 2834 } 2835 2836 /* send message to DSP */ 2837 ret = sof_ipc_tx_message(sdev->ipc, 2838 config->hdr.cmd, config, size, &reply, 2839 sizeof(reply)); 2840 if (ret < 0) { 2841 dev_err(scomp->dev, "error: failed to set DAI config for ESAI%d\n", 2842 config->dai_index); 2843 return ret; 2844 } 2845 2846 /* set config for all DAI's with name matching the link name */ 2847 ret = sof_set_dai_config(sdev, size, link, config); 2848 if (ret < 0) 2849 dev_err(scomp->dev, "error: failed to save DAI config for ESAI%d\n", 2850 config->dai_index); 2851 2852 return ret; 2853 } 2854 2855 static int sof_link_dmic_load(struct snd_soc_component *scomp, int index, 2856 struct snd_soc_dai_link *link, 2857 struct snd_soc_tplg_link_config *cfg, 2858 struct snd_soc_tplg_hw_config *hw_config, 2859 struct sof_ipc_dai_config *config) 2860 { 2861 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); 2862 struct snd_soc_tplg_private *private = &cfg->priv; 2863 struct sof_ipc_dai_config *ipc_config; 2864 struct sof_ipc_reply reply; 2865 struct sof_ipc_fw_ready *ready = &sdev->fw_ready; 2866 struct sof_ipc_fw_version *v = &ready->version; 2867 u32 size; 2868 int ret, j; 2869 2870 /* 2871 * config is only used for the common params in dmic_params structure 2872 * that does not include the PDM controller config array 2873 * Set the common params to 0. 2874 */ 2875 memset(&config->dmic, 0, sizeof(struct sof_ipc_dai_dmic_params)); 2876 2877 /* get DMIC tokens */ 2878 ret = sof_parse_tokens(scomp, &config->dmic, dmic_tokens, 2879 ARRAY_SIZE(dmic_tokens), private->array, 2880 le32_to_cpu(private->size)); 2881 if (ret != 0) { 2882 dev_err(scomp->dev, "error: parse dmic tokens failed %d\n", 2883 le32_to_cpu(private->size)); 2884 return ret; 2885 } 2886 2887 /* 2888 * allocate memory for dmic dai config accounting for the 2889 * variable number of active pdm controllers 2890 * This will be the ipc payload for setting dai config 2891 */ 2892 size = sizeof(*config) + sizeof(struct sof_ipc_dai_dmic_pdm_ctrl) * 2893 config->dmic.num_pdm_active; 2894 2895 ipc_config = kzalloc(size, GFP_KERNEL); 2896 if (!ipc_config) 2897 return -ENOMEM; 2898 2899 /* copy the common dai config and dmic params */ 2900 memcpy(ipc_config, config, sizeof(*config)); 2901 2902 /* 2903 * alloc memory for private member 2904 * Used to track the pdm config array index currently being parsed 2905 */ 2906 sdev->private = kzalloc(sizeof(u32), GFP_KERNEL); 2907 if (!sdev->private) { 2908 kfree(ipc_config); 2909 return -ENOMEM; 2910 } 2911 2912 /* get DMIC PDM tokens */ 2913 ret = sof_parse_tokens(scomp, &ipc_config->dmic.pdm[0], dmic_pdm_tokens, 2914 ARRAY_SIZE(dmic_pdm_tokens), private->array, 2915 le32_to_cpu(private->size)); 2916 if (ret != 0) { 2917 dev_err(scomp->dev, "error: parse dmic pdm tokens failed %d\n", 2918 le32_to_cpu(private->size)); 2919 goto err; 2920 } 2921 2922 /* set IPC header size */ 2923 ipc_config->hdr.size = size; 2924 2925 /* debug messages */ 2926 dev_dbg(scomp->dev, "tplg: config DMIC%d driver version %d\n", 2927 ipc_config->dai_index, ipc_config->dmic.driver_ipc_version); 2928 dev_dbg(scomp->dev, "pdmclk_min %d pdm_clkmax %d duty_min %hd\n", 2929 ipc_config->dmic.pdmclk_min, ipc_config->dmic.pdmclk_max, 2930 ipc_config->dmic.duty_min); 2931 dev_dbg(scomp->dev, "duty_max %hd fifo_fs %d num_pdms active %d\n", 2932 ipc_config->dmic.duty_max, ipc_config->dmic.fifo_fs, 2933 ipc_config->dmic.num_pdm_active); 2934 dev_dbg(scomp->dev, "fifo word length %hd\n", 2935 ipc_config->dmic.fifo_bits); 2936 2937 for (j = 0; j < ipc_config->dmic.num_pdm_active; j++) { 2938 dev_dbg(scomp->dev, "pdm %hd mic a %hd mic b %hd\n", 2939 ipc_config->dmic.pdm[j].id, 2940 ipc_config->dmic.pdm[j].enable_mic_a, 2941 ipc_config->dmic.pdm[j].enable_mic_b); 2942 dev_dbg(scomp->dev, "pdm %hd polarity a %hd polarity b %hd\n", 2943 ipc_config->dmic.pdm[j].id, 2944 ipc_config->dmic.pdm[j].polarity_mic_a, 2945 ipc_config->dmic.pdm[j].polarity_mic_b); 2946 dev_dbg(scomp->dev, "pdm %hd clk_edge %hd skew %hd\n", 2947 ipc_config->dmic.pdm[j].id, 2948 ipc_config->dmic.pdm[j].clk_edge, 2949 ipc_config->dmic.pdm[j].skew); 2950 } 2951 2952 if (SOF_ABI_VER(v->major, v->minor, v->micro) < SOF_ABI_VER(3, 0, 1)) { 2953 /* this takes care of backwards compatible handling of fifo_bits_b */ 2954 ipc_config->dmic.reserved_2 = ipc_config->dmic.fifo_bits; 2955 } 2956 2957 /* send message to DSP */ 2958 ret = sof_ipc_tx_message(sdev->ipc, 2959 ipc_config->hdr.cmd, ipc_config, size, &reply, 2960 sizeof(reply)); 2961 2962 if (ret < 0) { 2963 dev_err(scomp->dev, 2964 "error: failed to set DAI config for DMIC%d\n", 2965 config->dai_index); 2966 goto err; 2967 } 2968 2969 /* set config for all DAI's with name matching the link name */ 2970 ret = sof_set_dai_config(sdev, size, link, ipc_config); 2971 if (ret < 0) 2972 dev_err(scomp->dev, "error: failed to save DAI config for DMIC%d\n", 2973 config->dai_index); 2974 2975 err: 2976 kfree(sdev->private); 2977 kfree(ipc_config); 2978 2979 return ret; 2980 } 2981 2982 /* 2983 * for hda link, playback and capture are supported by different dai 2984 * in FW. Here get the dai_index, set dma channel of each dai 2985 * and send config to FW. In FW, each dai sets config by dai_index 2986 */ 2987 static int sof_link_hda_process(struct snd_sof_dev *sdev, 2988 struct snd_soc_dai_link *link, 2989 struct sof_ipc_dai_config *config) 2990 { 2991 struct sof_ipc_reply reply; 2992 u32 size = sizeof(*config); 2993 struct snd_sof_dai *sof_dai; 2994 int found = 0; 2995 int ret; 2996 2997 list_for_each_entry(sof_dai, &sdev->dai_list, list) { 2998 if (!sof_dai->name) 2999 continue; 3000 3001 if (strcmp(link->name, sof_dai->name) == 0) { 3002 config->dai_index = sof_dai->comp_dai.dai_index; 3003 found = 1; 3004 3005 config->hda.link_dma_ch = DMA_CHAN_INVALID; 3006 3007 /* save config in dai component */ 3008 sof_dai->dai_config = kmemdup(config, size, GFP_KERNEL); 3009 if (!sof_dai->dai_config) 3010 return -ENOMEM; 3011 3012 sof_dai->cpu_dai_name = link->cpus->dai_name; 3013 3014 /* send message to DSP */ 3015 ret = sof_ipc_tx_message(sdev->ipc, 3016 config->hdr.cmd, config, size, 3017 &reply, sizeof(reply)); 3018 3019 if (ret < 0) { 3020 dev_err(sdev->dev, "error: failed to set DAI config for direction:%d of HDA dai %d\n", 3021 sof_dai->comp_dai.direction, 3022 config->dai_index); 3023 3024 return ret; 3025 } 3026 } 3027 } 3028 3029 /* 3030 * machine driver may define a dai link with playback and capture 3031 * dai enabled, but the dai link in topology would support both, one 3032 * or none of them. Here print a warning message to notify user 3033 */ 3034 if (!found) { 3035 dev_warn(sdev->dev, "warning: failed to find dai for dai link %s", 3036 link->name); 3037 } 3038 3039 return 0; 3040 } 3041 3042 static int sof_link_hda_load(struct snd_soc_component *scomp, int index, 3043 struct snd_soc_dai_link *link, 3044 struct snd_soc_tplg_link_config *cfg, 3045 struct snd_soc_tplg_hw_config *hw_config, 3046 struct sof_ipc_dai_config *config) 3047 { 3048 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); 3049 struct snd_soc_tplg_private *private = &cfg->priv; 3050 struct snd_soc_dai *dai; 3051 u32 size = sizeof(*config); 3052 int ret; 3053 3054 /* init IPC */ 3055 memset(&config->hda, 0, sizeof(struct sof_ipc_dai_hda_params)); 3056 config->hdr.size = size; 3057 3058 /* get any bespoke DAI tokens */ 3059 ret = sof_parse_tokens(scomp, config, hda_tokens, 3060 ARRAY_SIZE(hda_tokens), private->array, 3061 le32_to_cpu(private->size)); 3062 if (ret != 0) { 3063 dev_err(scomp->dev, "error: parse hda tokens failed %d\n", 3064 le32_to_cpu(private->size)); 3065 return ret; 3066 } 3067 3068 dai = snd_soc_find_dai(link->cpus); 3069 if (!dai) { 3070 dev_err(scomp->dev, "error: failed to find dai %s in %s", 3071 link->cpus->dai_name, __func__); 3072 return -EINVAL; 3073 } 3074 3075 ret = sof_link_hda_process(sdev, link, config); 3076 if (ret < 0) 3077 dev_err(scomp->dev, "error: failed to process hda dai link %s", 3078 link->name); 3079 3080 return ret; 3081 } 3082 3083 static int sof_link_alh_load(struct snd_soc_component *scomp, int index, 3084 struct snd_soc_dai_link *link, 3085 struct snd_soc_tplg_link_config *cfg, 3086 struct snd_soc_tplg_hw_config *hw_config, 3087 struct sof_ipc_dai_config *config) 3088 { 3089 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); 3090 struct sof_ipc_reply reply; 3091 u32 size = sizeof(*config); 3092 int ret; 3093 3094 /* init IPC */ 3095 config->hdr.size = size; 3096 3097 /* send message to DSP */ 3098 ret = sof_ipc_tx_message(sdev->ipc, 3099 config->hdr.cmd, config, size, &reply, 3100 sizeof(reply)); 3101 3102 if (ret < 0) { 3103 dev_err(scomp->dev, "error: failed to set DAI config for ALH %d\n", 3104 config->dai_index); 3105 return ret; 3106 } 3107 3108 /* set config for all DAI's with name matching the link name */ 3109 ret = sof_set_dai_config(sdev, size, link, config); 3110 if (ret < 0) 3111 dev_err(scomp->dev, "error: failed to save DAI config for ALH %d\n", 3112 config->dai_index); 3113 3114 return ret; 3115 } 3116 3117 /* DAI link - used for any driver specific init */ 3118 static int sof_link_load(struct snd_soc_component *scomp, int index, 3119 struct snd_soc_dai_link *link, 3120 struct snd_soc_tplg_link_config *cfg) 3121 { 3122 struct snd_soc_tplg_private *private = &cfg->priv; 3123 struct sof_ipc_dai_config config; 3124 struct snd_soc_tplg_hw_config *hw_config; 3125 int num_hw_configs; 3126 int ret; 3127 int i = 0; 3128 3129 if (!link->platforms) { 3130 dev_err(scomp->dev, "error: no platforms\n"); 3131 return -EINVAL; 3132 } 3133 link->platforms->name = dev_name(scomp->dev); 3134 3135 /* 3136 * Set nonatomic property for FE dai links as their trigger action 3137 * involves IPC's. 3138 */ 3139 if (!link->no_pcm) { 3140 link->nonatomic = true; 3141 3142 /* set trigger order */ 3143 link->trigger[0] = SND_SOC_DPCM_TRIGGER_POST; 3144 link->trigger[1] = SND_SOC_DPCM_TRIGGER_POST; 3145 3146 /* nothing more to do for FE dai links */ 3147 return 0; 3148 } 3149 3150 /* check we have some tokens - we need at least DAI type */ 3151 if (le32_to_cpu(private->size) == 0) { 3152 dev_err(scomp->dev, "error: expected tokens for DAI, none found\n"); 3153 return -EINVAL; 3154 } 3155 3156 /* Send BE DAI link configurations to DSP */ 3157 memset(&config, 0, sizeof(config)); 3158 3159 /* get any common DAI tokens */ 3160 ret = sof_parse_tokens(scomp, &config, dai_link_tokens, 3161 ARRAY_SIZE(dai_link_tokens), private->array, 3162 le32_to_cpu(private->size)); 3163 if (ret != 0) { 3164 dev_err(scomp->dev, "error: parse link tokens failed %d\n", 3165 le32_to_cpu(private->size)); 3166 return ret; 3167 } 3168 3169 /* 3170 * DAI links are expected to have at least 1 hw_config. 3171 * But some older topologies might have no hw_config for HDA dai links. 3172 */ 3173 num_hw_configs = le32_to_cpu(cfg->num_hw_configs); 3174 if (!num_hw_configs) { 3175 if (config.type != SOF_DAI_INTEL_HDA) { 3176 dev_err(scomp->dev, "error: unexpected DAI config count %d!\n", 3177 le32_to_cpu(cfg->num_hw_configs)); 3178 return -EINVAL; 3179 } 3180 } else { 3181 dev_dbg(scomp->dev, "tplg: %d hw_configs found, default id: %d!\n", 3182 cfg->num_hw_configs, le32_to_cpu(cfg->default_hw_config_id)); 3183 3184 for (i = 0; i < num_hw_configs; i++) { 3185 if (cfg->hw_config[i].id == cfg->default_hw_config_id) 3186 break; 3187 } 3188 3189 if (i == num_hw_configs) { 3190 dev_err(scomp->dev, "error: default hw_config id: %d not found!\n", 3191 le32_to_cpu(cfg->default_hw_config_id)); 3192 return -EINVAL; 3193 } 3194 } 3195 3196 /* configure dai IPC message */ 3197 hw_config = &cfg->hw_config[i]; 3198 3199 config.hdr.cmd = SOF_IPC_GLB_DAI_MSG | SOF_IPC_DAI_CONFIG; 3200 config.format = le32_to_cpu(hw_config->fmt); 3201 3202 /* now load DAI specific data and send IPC - type comes from token */ 3203 switch (config.type) { 3204 case SOF_DAI_INTEL_SSP: 3205 ret = sof_link_ssp_load(scomp, index, link, cfg, hw_config, 3206 &config); 3207 break; 3208 case SOF_DAI_INTEL_DMIC: 3209 ret = sof_link_dmic_load(scomp, index, link, cfg, hw_config, 3210 &config); 3211 break; 3212 case SOF_DAI_INTEL_HDA: 3213 ret = sof_link_hda_load(scomp, index, link, cfg, hw_config, 3214 &config); 3215 break; 3216 case SOF_DAI_INTEL_ALH: 3217 ret = sof_link_alh_load(scomp, index, link, cfg, hw_config, 3218 &config); 3219 break; 3220 case SOF_DAI_IMX_SAI: 3221 ret = sof_link_sai_load(scomp, index, link, cfg, hw_config, 3222 &config); 3223 break; 3224 case SOF_DAI_IMX_ESAI: 3225 ret = sof_link_esai_load(scomp, index, link, cfg, hw_config, 3226 &config); 3227 break; 3228 default: 3229 dev_err(scomp->dev, "error: invalid DAI type %d\n", 3230 config.type); 3231 ret = -EINVAL; 3232 break; 3233 } 3234 if (ret < 0) 3235 return ret; 3236 3237 return 0; 3238 } 3239 3240 static int sof_link_hda_unload(struct snd_sof_dev *sdev, 3241 struct snd_soc_dai_link *link) 3242 { 3243 struct snd_soc_dai *dai; 3244 int ret = 0; 3245 3246 dai = snd_soc_find_dai(link->cpus); 3247 if (!dai) { 3248 dev_err(sdev->dev, "error: failed to find dai %s in %s", 3249 link->cpus->dai_name, __func__); 3250 return -EINVAL; 3251 } 3252 3253 return ret; 3254 } 3255 3256 static int sof_link_unload(struct snd_soc_component *scomp, 3257 struct snd_soc_dobj *dobj) 3258 { 3259 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); 3260 struct snd_soc_dai_link *link = 3261 container_of(dobj, struct snd_soc_dai_link, dobj); 3262 3263 struct snd_sof_dai *sof_dai; 3264 int ret = 0; 3265 3266 /* only BE link is loaded by sof */ 3267 if (!link->no_pcm) 3268 return 0; 3269 3270 list_for_each_entry(sof_dai, &sdev->dai_list, list) { 3271 if (!sof_dai->name) 3272 continue; 3273 3274 if (strcmp(link->name, sof_dai->name) == 0) 3275 goto found; 3276 } 3277 3278 dev_err(scomp->dev, "error: failed to find dai %s in %s", 3279 link->name, __func__); 3280 return -EINVAL; 3281 found: 3282 3283 switch (sof_dai->dai_config->type) { 3284 case SOF_DAI_INTEL_SSP: 3285 case SOF_DAI_INTEL_DMIC: 3286 case SOF_DAI_INTEL_ALH: 3287 case SOF_DAI_IMX_SAI: 3288 case SOF_DAI_IMX_ESAI: 3289 /* no resource needs to be released for all cases above */ 3290 break; 3291 case SOF_DAI_INTEL_HDA: 3292 ret = sof_link_hda_unload(sdev, link); 3293 break; 3294 default: 3295 dev_err(scomp->dev, "error: invalid DAI type %d\n", 3296 sof_dai->dai_config->type); 3297 ret = -EINVAL; 3298 break; 3299 } 3300 3301 return ret; 3302 } 3303 3304 /* DAI link - used for any driver specific init */ 3305 static int sof_route_load(struct snd_soc_component *scomp, int index, 3306 struct snd_soc_dapm_route *route) 3307 { 3308 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); 3309 struct sof_ipc_pipe_comp_connect *connect; 3310 struct snd_sof_widget *source_swidget, *sink_swidget; 3311 struct snd_soc_dobj *dobj = &route->dobj; 3312 struct snd_sof_route *sroute; 3313 struct sof_ipc_reply reply; 3314 int ret = 0; 3315 3316 /* allocate memory for sroute and connect */ 3317 sroute = kzalloc(sizeof(*sroute), GFP_KERNEL); 3318 if (!sroute) 3319 return -ENOMEM; 3320 3321 sroute->scomp = scomp; 3322 3323 connect = kzalloc(sizeof(*connect), GFP_KERNEL); 3324 if (!connect) { 3325 kfree(sroute); 3326 return -ENOMEM; 3327 } 3328 3329 connect->hdr.size = sizeof(*connect); 3330 connect->hdr.cmd = SOF_IPC_GLB_TPLG_MSG | SOF_IPC_TPLG_COMP_CONNECT; 3331 3332 dev_dbg(scomp->dev, "sink %s control %s source %s\n", 3333 route->sink, route->control ? route->control : "none", 3334 route->source); 3335 3336 /* source component */ 3337 source_swidget = snd_sof_find_swidget(scomp, (char *)route->source); 3338 if (!source_swidget) { 3339 dev_err(scomp->dev, "error: source %s not found\n", 3340 route->source); 3341 ret = -EINVAL; 3342 goto err; 3343 } 3344 3345 /* 3346 * Virtual widgets of type output/out_drv may be added in topology 3347 * for compatibility. These are not handled by the FW. 3348 * So, don't send routes whose source/sink widget is of such types 3349 * to the DSP. 3350 */ 3351 if (source_swidget->id == snd_soc_dapm_out_drv || 3352 source_swidget->id == snd_soc_dapm_output) 3353 goto err; 3354 3355 connect->source_id = source_swidget->comp_id; 3356 3357 /* sink component */ 3358 sink_swidget = snd_sof_find_swidget(scomp, (char *)route->sink); 3359 if (!sink_swidget) { 3360 dev_err(scomp->dev, "error: sink %s not found\n", 3361 route->sink); 3362 ret = -EINVAL; 3363 goto err; 3364 } 3365 3366 /* 3367 * Don't send routes whose sink widget is of type 3368 * output or out_drv to the DSP 3369 */ 3370 if (sink_swidget->id == snd_soc_dapm_out_drv || 3371 sink_swidget->id == snd_soc_dapm_output) 3372 goto err; 3373 3374 connect->sink_id = sink_swidget->comp_id; 3375 3376 /* 3377 * For virtual routes, both sink and source are not 3378 * buffer. Since only buffer linked to component is supported by 3379 * FW, others are reported as error, add check in route function, 3380 * do not send it to FW when both source and sink are not buffer 3381 */ 3382 if (source_swidget->id != snd_soc_dapm_buffer && 3383 sink_swidget->id != snd_soc_dapm_buffer) { 3384 dev_dbg(scomp->dev, "warning: neither Linked source component %s nor sink component %s is of buffer type, ignoring link\n", 3385 route->source, route->sink); 3386 ret = 0; 3387 goto err; 3388 } else { 3389 ret = sof_ipc_tx_message(sdev->ipc, 3390 connect->hdr.cmd, 3391 connect, sizeof(*connect), 3392 &reply, sizeof(reply)); 3393 3394 /* check IPC return value */ 3395 if (ret < 0) { 3396 dev_err(scomp->dev, "error: failed to add route sink %s control %s source %s\n", 3397 route->sink, 3398 route->control ? route->control : "none", 3399 route->source); 3400 goto err; 3401 } 3402 3403 /* check IPC reply */ 3404 if (reply.error < 0) { 3405 dev_err(scomp->dev, "error: DSP failed to add route sink %s control %s source %s result %d\n", 3406 route->sink, 3407 route->control ? route->control : "none", 3408 route->source, reply.error); 3409 ret = reply.error; 3410 goto err; 3411 } 3412 3413 sroute->route = route; 3414 dobj->private = sroute; 3415 sroute->private = connect; 3416 3417 /* add route to route list */ 3418 list_add(&sroute->list, &sdev->route_list); 3419 3420 return ret; 3421 } 3422 3423 err: 3424 kfree(connect); 3425 kfree(sroute); 3426 return ret; 3427 } 3428 3429 /* Function to set the initial value of SOF kcontrols. 3430 * The value will be stored in scontrol->control_data 3431 */ 3432 static int snd_sof_cache_kcontrol_val(struct snd_soc_component *scomp) 3433 { 3434 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); 3435 struct snd_sof_control *scontrol = NULL; 3436 int ipc_cmd, ctrl_type; 3437 int ret = 0; 3438 3439 list_for_each_entry(scontrol, &sdev->kcontrol_list, list) { 3440 3441 /* notify DSP of kcontrol values */ 3442 switch (scontrol->cmd) { 3443 case SOF_CTRL_CMD_VOLUME: 3444 case SOF_CTRL_CMD_ENUM: 3445 case SOF_CTRL_CMD_SWITCH: 3446 ipc_cmd = SOF_IPC_COMP_GET_VALUE; 3447 ctrl_type = SOF_CTRL_TYPE_VALUE_CHAN_GET; 3448 break; 3449 case SOF_CTRL_CMD_BINARY: 3450 ipc_cmd = SOF_IPC_COMP_GET_DATA; 3451 ctrl_type = SOF_CTRL_TYPE_DATA_GET; 3452 break; 3453 default: 3454 dev_err(scomp->dev, 3455 "error: Invalid scontrol->cmd: %d\n", 3456 scontrol->cmd); 3457 return -EINVAL; 3458 } 3459 ret = snd_sof_ipc_set_get_comp_data(scontrol, 3460 ipc_cmd, ctrl_type, 3461 scontrol->cmd, 3462 false); 3463 if (ret < 0) { 3464 dev_warn(scomp->dev, 3465 "error: kcontrol value get for widget: %d\n", 3466 scontrol->comp_id); 3467 } 3468 } 3469 3470 return ret; 3471 } 3472 3473 int snd_sof_complete_pipeline(struct device *dev, 3474 struct snd_sof_widget *swidget) 3475 { 3476 struct snd_sof_dev *sdev = dev_get_drvdata(dev); 3477 struct sof_ipc_pipe_ready ready; 3478 struct sof_ipc_reply reply; 3479 int ret; 3480 3481 dev_dbg(dev, "tplg: complete pipeline %s id %d\n", 3482 swidget->widget->name, swidget->comp_id); 3483 3484 memset(&ready, 0, sizeof(ready)); 3485 ready.hdr.size = sizeof(ready); 3486 ready.hdr.cmd = SOF_IPC_GLB_TPLG_MSG | SOF_IPC_TPLG_PIPE_COMPLETE; 3487 ready.comp_id = swidget->comp_id; 3488 3489 ret = sof_ipc_tx_message(sdev->ipc, 3490 ready.hdr.cmd, &ready, sizeof(ready), &reply, 3491 sizeof(reply)); 3492 if (ret < 0) 3493 return ret; 3494 return 1; 3495 } 3496 3497 /* completion - called at completion of firmware loading */ 3498 static void sof_complete(struct snd_soc_component *scomp) 3499 { 3500 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); 3501 struct snd_sof_widget *swidget; 3502 3503 /* some widget types require completion notificattion */ 3504 list_for_each_entry(swidget, &sdev->widget_list, list) { 3505 if (swidget->complete) 3506 continue; 3507 3508 switch (swidget->id) { 3509 case snd_soc_dapm_scheduler: 3510 swidget->complete = 3511 snd_sof_complete_pipeline(scomp->dev, swidget); 3512 break; 3513 default: 3514 break; 3515 } 3516 } 3517 /* 3518 * cache initial values of SOF kcontrols by reading DSP value over 3519 * IPC. It may be overwritten by alsa-mixer after booting up 3520 */ 3521 snd_sof_cache_kcontrol_val(scomp); 3522 } 3523 3524 /* manifest - optional to inform component of manifest */ 3525 static int sof_manifest(struct snd_soc_component *scomp, int index, 3526 struct snd_soc_tplg_manifest *man) 3527 { 3528 u32 size; 3529 u32 abi_version; 3530 3531 size = le32_to_cpu(man->priv.size); 3532 3533 /* backward compatible with tplg without ABI info */ 3534 if (!size) { 3535 dev_dbg(scomp->dev, "No topology ABI info\n"); 3536 return 0; 3537 } 3538 3539 if (size != SOF_TPLG_ABI_SIZE) { 3540 dev_err(scomp->dev, "error: invalid topology ABI size\n"); 3541 return -EINVAL; 3542 } 3543 3544 dev_info(scomp->dev, 3545 "Topology: ABI %d:%d:%d Kernel ABI %d:%d:%d\n", 3546 man->priv.data[0], man->priv.data[1], 3547 man->priv.data[2], SOF_ABI_MAJOR, SOF_ABI_MINOR, 3548 SOF_ABI_PATCH); 3549 3550 abi_version = SOF_ABI_VER(man->priv.data[0], 3551 man->priv.data[1], 3552 man->priv.data[2]); 3553 3554 if (SOF_ABI_VERSION_INCOMPATIBLE(SOF_ABI_VERSION, abi_version)) { 3555 dev_err(scomp->dev, "error: incompatible topology ABI version\n"); 3556 return -EINVAL; 3557 } 3558 3559 if (abi_version > SOF_ABI_VERSION) { 3560 if (!IS_ENABLED(CONFIG_SND_SOC_SOF_STRICT_ABI_CHECKS)) { 3561 dev_warn(scomp->dev, "warn: topology ABI is more recent than kernel\n"); 3562 } else { 3563 dev_err(scomp->dev, "error: topology ABI is more recent than kernel\n"); 3564 return -EINVAL; 3565 } 3566 } 3567 3568 return 0; 3569 } 3570 3571 /* vendor specific kcontrol handlers available for binding */ 3572 static const struct snd_soc_tplg_kcontrol_ops sof_io_ops[] = { 3573 {SOF_TPLG_KCTL_VOL_ID, snd_sof_volume_get, snd_sof_volume_put}, 3574 {SOF_TPLG_KCTL_BYTES_ID, snd_sof_bytes_get, snd_sof_bytes_put}, 3575 {SOF_TPLG_KCTL_ENUM_ID, snd_sof_enum_get, snd_sof_enum_put}, 3576 {SOF_TPLG_KCTL_SWITCH_ID, snd_sof_switch_get, snd_sof_switch_put}, 3577 }; 3578 3579 /* vendor specific bytes ext handlers available for binding */ 3580 static const struct snd_soc_tplg_bytes_ext_ops sof_bytes_ext_ops[] = { 3581 {SOF_TPLG_KCTL_BYTES_ID, snd_sof_bytes_ext_get, snd_sof_bytes_ext_put}, 3582 }; 3583 3584 static struct snd_soc_tplg_ops sof_tplg_ops = { 3585 /* external kcontrol init - used for any driver specific init */ 3586 .control_load = sof_control_load, 3587 .control_unload = sof_control_unload, 3588 3589 /* external kcontrol init - used for any driver specific init */ 3590 .dapm_route_load = sof_route_load, 3591 .dapm_route_unload = sof_route_unload, 3592 3593 /* external widget init - used for any driver specific init */ 3594 /* .widget_load is not currently used */ 3595 .widget_ready = sof_widget_ready, 3596 .widget_unload = sof_widget_unload, 3597 3598 /* FE DAI - used for any driver specific init */ 3599 .dai_load = sof_dai_load, 3600 .dai_unload = sof_dai_unload, 3601 3602 /* DAI link - used for any driver specific init */ 3603 .link_load = sof_link_load, 3604 .link_unload = sof_link_unload, 3605 3606 /* completion - called at completion of firmware loading */ 3607 .complete = sof_complete, 3608 3609 /* manifest - optional to inform component of manifest */ 3610 .manifest = sof_manifest, 3611 3612 /* vendor specific kcontrol handlers available for binding */ 3613 .io_ops = sof_io_ops, 3614 .io_ops_count = ARRAY_SIZE(sof_io_ops), 3615 3616 /* vendor specific bytes ext handlers available for binding */ 3617 .bytes_ext_ops = sof_bytes_ext_ops, 3618 .bytes_ext_ops_count = ARRAY_SIZE(sof_bytes_ext_ops), 3619 }; 3620 3621 int snd_sof_load_topology(struct snd_soc_component *scomp, const char *file) 3622 { 3623 const struct firmware *fw; 3624 int ret; 3625 3626 dev_dbg(scomp->dev, "loading topology:%s\n", file); 3627 3628 ret = request_firmware(&fw, file, scomp->dev); 3629 if (ret < 0) { 3630 dev_err(scomp->dev, "error: tplg request firmware %s failed err: %d\n", 3631 file, ret); 3632 return ret; 3633 } 3634 3635 ret = snd_soc_tplg_component_load(scomp, 3636 &sof_tplg_ops, fw, 3637 SND_SOC_TPLG_INDEX_ALL); 3638 if (ret < 0) { 3639 dev_err(scomp->dev, "error: tplg component load failed %d\n", 3640 ret); 3641 ret = -EINVAL; 3642 } 3643 3644 release_firmware(fw); 3645 return ret; 3646 } 3647 EXPORT_SYMBOL(snd_sof_load_topology); 3648