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