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