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