blob: dbe6a19b84f56d2437fba7fd404ee3d1f66dd1aa [file] [log] [blame]
Jeeja KPe4e2d2f2015-10-07 11:31:52 +01001/*
2 * skl-topology.c - Implements Platform component ALSA controls/widget
3 * handlers.
4 *
5 * Copyright (C) 2014-2015 Intel Corp
6 * Author: Jeeja KP <jeeja.kp@intel.com>
7 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as version 2, as
11 * published by the Free Software Foundation.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 */
18
19#include <linux/slab.h>
20#include <linux/types.h>
21#include <linux/firmware.h>
22#include <sound/soc.h>
23#include <sound/soc-topology.h>
Shreyas NC6277e832016-08-12 12:29:51 +053024#include <uapi/sound/snd_sst_tokens.h>
Jeeja KPe4e2d2f2015-10-07 11:31:52 +010025#include "skl-sst-dsp.h"
26#include "skl-sst-ipc.h"
27#include "skl-topology.h"
28#include "skl.h"
29#include "skl-tplg-interface.h"
Dharageswari R6c5768b2015-12-03 23:29:50 +053030#include "../common/sst-dsp.h"
31#include "../common/sst-dsp-priv.h"
Jeeja KPe4e2d2f2015-10-07 11:31:52 +010032
Jeeja KPf7590d42015-10-07 11:31:53 +010033#define SKL_CH_FIXUP_MASK (1 << 0)
34#define SKL_RATE_FIXUP_MASK (1 << 1)
35#define SKL_FMT_FIXUP_MASK (1 << 2)
Shreyas NC6277e832016-08-12 12:29:51 +053036#define SKL_IN_DIR_BIT_MASK BIT(0)
37#define SKL_PIN_COUNT_MASK GENMASK(7, 4)
Jeeja KPf7590d42015-10-07 11:31:53 +010038
Dharageswari R7a1b7492017-05-31 10:30:25 +053039static const int mic_mono_list[] = {
400, 1, 2, 3,
41};
42static const int mic_stereo_list[][SKL_CH_STEREO] = {
43{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3},
44};
45static const int mic_trio_list[][SKL_CH_TRIO] = {
46{0, 1, 2}, {0, 1, 3}, {0, 2, 3}, {1, 2, 3},
47};
48static const int mic_quatro_list[][SKL_CH_QUATRO] = {
49{0, 1, 2, 3},
50};
51
Ramesh Babuf6fa56e2017-08-23 19:33:53 +053052#define CHECK_HW_PARAMS(ch, freq, bps, prm_ch, prm_freq, prm_bps) \
53 ((ch == prm_ch) && (bps == prm_bps) && (freq == prm_freq))
54
Vinod Koula83e3b42016-11-03 17:07:20 +053055void skl_tplg_d0i3_get(struct skl *skl, enum d0i3_capability caps)
56{
57 struct skl_d0i3_data *d0i3 = &skl->skl_sst->d0i3;
58
59 switch (caps) {
60 case SKL_D0I3_NONE:
61 d0i3->non_d0i3++;
62 break;
63
64 case SKL_D0I3_STREAMING:
65 d0i3->streaming++;
66 break;
67
68 case SKL_D0I3_NON_STREAMING:
69 d0i3->non_streaming++;
70 break;
71 }
72}
73
74void skl_tplg_d0i3_put(struct skl *skl, enum d0i3_capability caps)
75{
76 struct skl_d0i3_data *d0i3 = &skl->skl_sst->d0i3;
77
78 switch (caps) {
79 case SKL_D0I3_NONE:
80 d0i3->non_d0i3--;
81 break;
82
83 case SKL_D0I3_STREAMING:
84 d0i3->streaming--;
85 break;
86
87 case SKL_D0I3_NON_STREAMING:
88 d0i3->non_streaming--;
89 break;
90 }
91}
92
Jeeja KPe4e2d2f2015-10-07 11:31:52 +010093/*
94 * SKL DSP driver modelling uses only few DAPM widgets so for rest we will
95 * ignore. This helpers checks if the SKL driver handles this widget type
96 */
Guneshwor Singhcb1f9042018-01-27 09:50:21 +053097static int is_skl_dsp_widget_type(struct snd_soc_dapm_widget *w,
98 struct device *dev)
Jeeja KPe4e2d2f2015-10-07 11:31:52 +010099{
Guneshwor Singhcb1f9042018-01-27 09:50:21 +0530100 if (w->dapm->dev != dev)
101 return false;
102
Jeeja KPe4e2d2f2015-10-07 11:31:52 +0100103 switch (w->id) {
104 case snd_soc_dapm_dai_link:
105 case snd_soc_dapm_dai_in:
106 case snd_soc_dapm_aif_in:
107 case snd_soc_dapm_aif_out:
108 case snd_soc_dapm_dai_out:
109 case snd_soc_dapm_switch:
110 return false;
111 default:
112 return true;
113 }
114}
115
116/*
117 * Each pipelines needs memory to be allocated. Check if we have free memory
Dharageswari.R9ba8ffe2016-02-03 17:59:47 +0530118 * from available pool.
Jeeja KPe4e2d2f2015-10-07 11:31:52 +0100119 */
Dharageswari.R9ba8ffe2016-02-03 17:59:47 +0530120static bool skl_is_pipe_mem_avail(struct skl *skl,
Jeeja KPe4e2d2f2015-10-07 11:31:52 +0100121 struct skl_module_cfg *mconfig)
122{
123 struct skl_sst *ctx = skl->skl_sst;
124
125 if (skl->resource.mem + mconfig->pipe->memory_pages >
126 skl->resource.max_mem) {
127 dev_err(ctx->dev,
128 "%s: module_id %d instance %d\n", __func__,
129 mconfig->id.module_id,
130 mconfig->id.instance_id);
131 dev_err(ctx->dev,
132 "exceeds ppl memory available %d mem %d\n",
133 skl->resource.max_mem, skl->resource.mem);
134 return false;
Dharageswari.R9ba8ffe2016-02-03 17:59:47 +0530135 } else {
136 return true;
Jeeja KPe4e2d2f2015-10-07 11:31:52 +0100137 }
Dharageswari.R9ba8ffe2016-02-03 17:59:47 +0530138}
Jeeja KPe4e2d2f2015-10-07 11:31:52 +0100139
Dharageswari.R9ba8ffe2016-02-03 17:59:47 +0530140/*
141 * Add the mem to the mem pool. This is freed when pipe is deleted.
142 * Note: DSP does actual memory management we only keep track for complete
143 * pool
144 */
145static void skl_tplg_alloc_pipe_mem(struct skl *skl,
146 struct skl_module_cfg *mconfig)
147{
Jeeja KPe4e2d2f2015-10-07 11:31:52 +0100148 skl->resource.mem += mconfig->pipe->memory_pages;
Jeeja KPe4e2d2f2015-10-07 11:31:52 +0100149}
150
151/*
152 * Pipeline needs needs DSP CPU resources for computation, this is
153 * quantified in MCPS (Million Clocks Per Second) required for module/pipe
154 *
155 * Each pipelines needs mcps to be allocated. Check if we have mcps for this
Dharageswari.R9ba8ffe2016-02-03 17:59:47 +0530156 * pipe.
Jeeja KPe4e2d2f2015-10-07 11:31:52 +0100157 */
Dharageswari.R9ba8ffe2016-02-03 17:59:47 +0530158
159static bool skl_is_pipe_mcps_avail(struct skl *skl,
Jeeja KPe4e2d2f2015-10-07 11:31:52 +0100160 struct skl_module_cfg *mconfig)
161{
162 struct skl_sst *ctx = skl->skl_sst;
Ramesh Babuf6fa56e2017-08-23 19:33:53 +0530163 u8 res_idx = mconfig->res_idx;
164 struct skl_module_res *res = &mconfig->module->resources[res_idx];
Jeeja KPe4e2d2f2015-10-07 11:31:52 +0100165
Ramesh Babuf6fa56e2017-08-23 19:33:53 +0530166 if (skl->resource.mcps + res->cps > skl->resource.max_mcps) {
Jeeja KPe4e2d2f2015-10-07 11:31:52 +0100167 dev_err(ctx->dev,
168 "%s: module_id %d instance %d\n", __func__,
169 mconfig->id.module_id, mconfig->id.instance_id);
170 dev_err(ctx->dev,
Guneshwor Singh7ca42f52016-02-03 17:59:46 +0530171 "exceeds ppl mcps available %d > mem %d\n",
Jeeja KPe4e2d2f2015-10-07 11:31:52 +0100172 skl->resource.max_mcps, skl->resource.mcps);
173 return false;
Dharageswari.R9ba8ffe2016-02-03 17:59:47 +0530174 } else {
175 return true;
Jeeja KPe4e2d2f2015-10-07 11:31:52 +0100176 }
Dharageswari.R9ba8ffe2016-02-03 17:59:47 +0530177}
Jeeja KPe4e2d2f2015-10-07 11:31:52 +0100178
Dharageswari.R9ba8ffe2016-02-03 17:59:47 +0530179static void skl_tplg_alloc_pipe_mcps(struct skl *skl,
180 struct skl_module_cfg *mconfig)
181{
Ramesh Babuf6fa56e2017-08-23 19:33:53 +0530182 u8 res_idx = mconfig->res_idx;
183 struct skl_module_res *res = &mconfig->module->resources[res_idx];
184
185 skl->resource.mcps += res->cps;
Jeeja KPe4e2d2f2015-10-07 11:31:52 +0100186}
187
188/*
189 * Free the mcps when tearing down
190 */
191static void
192skl_tplg_free_pipe_mcps(struct skl *skl, struct skl_module_cfg *mconfig)
193{
Ramesh Babuf6fa56e2017-08-23 19:33:53 +0530194 u8 res_idx = mconfig->res_idx;
195 struct skl_module_res *res = &mconfig->module->resources[res_idx];
196
Ramesh Babuf6fa56e2017-08-23 19:33:53 +0530197 skl->resource.mcps -= res->cps;
Jeeja KPe4e2d2f2015-10-07 11:31:52 +0100198}
199
200/*
201 * Free the memory when tearing down
202 */
203static void
204skl_tplg_free_pipe_mem(struct skl *skl, struct skl_module_cfg *mconfig)
205{
206 skl->resource.mem -= mconfig->pipe->memory_pages;
207}
208
Jeeja KPf7590d42015-10-07 11:31:53 +0100209
210static void skl_dump_mconfig(struct skl_sst *ctx,
211 struct skl_module_cfg *mcfg)
212{
Ramesh Babuf6fa56e2017-08-23 19:33:53 +0530213 struct skl_module_iface *iface = &mcfg->module->formats[0];
214
Jeeja KPf7590d42015-10-07 11:31:53 +0100215 dev_dbg(ctx->dev, "Dumping config\n");
216 dev_dbg(ctx->dev, "Input Format:\n");
Ramesh Babuf6fa56e2017-08-23 19:33:53 +0530217 dev_dbg(ctx->dev, "channels = %d\n", iface->inputs[0].fmt.channels);
218 dev_dbg(ctx->dev, "s_freq = %d\n", iface->inputs[0].fmt.s_freq);
219 dev_dbg(ctx->dev, "ch_cfg = %d\n", iface->inputs[0].fmt.ch_cfg);
220 dev_dbg(ctx->dev, "valid bit depth = %d\n",
221 iface->inputs[0].fmt.valid_bit_depth);
Jeeja KPf7590d42015-10-07 11:31:53 +0100222 dev_dbg(ctx->dev, "Output Format:\n");
Ramesh Babuf6fa56e2017-08-23 19:33:53 +0530223 dev_dbg(ctx->dev, "channels = %d\n", iface->outputs[0].fmt.channels);
224 dev_dbg(ctx->dev, "s_freq = %d\n", iface->outputs[0].fmt.s_freq);
225 dev_dbg(ctx->dev, "valid bit depth = %d\n",
226 iface->outputs[0].fmt.valid_bit_depth);
227 dev_dbg(ctx->dev, "ch_cfg = %d\n", iface->outputs[0].fmt.ch_cfg);
Jeeja KPf7590d42015-10-07 11:31:53 +0100228}
229
Subhransu S. Prustyea5a1372016-04-14 10:07:36 +0530230static void skl_tplg_update_chmap(struct skl_module_fmt *fmt, int chs)
231{
232 int slot_map = 0xFFFFFFFF;
233 int start_slot = 0;
234 int i;
235
236 for (i = 0; i < chs; i++) {
237 /*
238 * For 2 channels with starting slot as 0, slot map will
239 * look like 0xFFFFFF10.
240 */
241 slot_map &= (~(0xF << (4 * i)) | (start_slot << (4 * i)));
242 start_slot++;
243 }
244 fmt->ch_map = slot_map;
245}
246
Jeeja KPf7590d42015-10-07 11:31:53 +0100247static void skl_tplg_update_params(struct skl_module_fmt *fmt,
248 struct skl_pipe_params *params, int fixup)
249{
250 if (fixup & SKL_RATE_FIXUP_MASK)
251 fmt->s_freq = params->s_freq;
Subhransu S. Prustyea5a1372016-04-14 10:07:36 +0530252 if (fixup & SKL_CH_FIXUP_MASK) {
Jeeja KPf7590d42015-10-07 11:31:53 +0100253 fmt->channels = params->ch;
Subhransu S. Prustyea5a1372016-04-14 10:07:36 +0530254 skl_tplg_update_chmap(fmt, fmt->channels);
255 }
Jeeja KP98256f82015-11-23 22:26:25 +0530256 if (fixup & SKL_FMT_FIXUP_MASK) {
257 fmt->valid_bit_depth = skl_get_bit_depth(params->s_fmt);
258
259 /*
260 * 16 bit is 16 bit container whereas 24 bit is in 32 bit
261 * container so update bit depth accordingly
262 */
263 switch (fmt->valid_bit_depth) {
264 case SKL_DEPTH_16BIT:
265 fmt->bit_depth = fmt->valid_bit_depth;
266 break;
267
268 default:
269 fmt->bit_depth = SKL_DEPTH_32BIT;
270 break;
271 }
272 }
273
Jeeja KPf7590d42015-10-07 11:31:53 +0100274}
275
276/*
277 * A pipeline may have modules which impact the pcm parameters, like SRC,
278 * channel converter, format converter.
279 * We need to calculate the output params by applying the 'fixup'
280 * Topology will tell driver which type of fixup is to be applied by
281 * supplying the fixup mask, so based on that we calculate the output
282 *
283 * Now In FE the pcm hw_params is source/target format. Same is applicable
284 * for BE with its hw_params invoked.
285 * here based on FE, BE pipeline and direction we calculate the input and
286 * outfix and then apply that for a module
287 */
288static void skl_tplg_update_params_fixup(struct skl_module_cfg *m_cfg,
289 struct skl_pipe_params *params, bool is_fe)
290{
291 int in_fixup, out_fixup;
292 struct skl_module_fmt *in_fmt, *out_fmt;
293
Hardik T Shah4cd98992015-10-27 09:22:55 +0900294 /* Fixups will be applied to pin 0 only */
Ramesh Babuf6fa56e2017-08-23 19:33:53 +0530295 in_fmt = &m_cfg->module->formats[0].inputs[0].fmt;
296 out_fmt = &m_cfg->module->formats[0].outputs[0].fmt;
Jeeja KPf7590d42015-10-07 11:31:53 +0100297
298 if (params->stream == SNDRV_PCM_STREAM_PLAYBACK) {
299 if (is_fe) {
300 in_fixup = m_cfg->params_fixup;
301 out_fixup = (~m_cfg->converter) &
302 m_cfg->params_fixup;
303 } else {
304 out_fixup = m_cfg->params_fixup;
305 in_fixup = (~m_cfg->converter) &
306 m_cfg->params_fixup;
307 }
308 } else {
309 if (is_fe) {
310 out_fixup = m_cfg->params_fixup;
311 in_fixup = (~m_cfg->converter) &
312 m_cfg->params_fixup;
313 } else {
314 in_fixup = m_cfg->params_fixup;
315 out_fixup = (~m_cfg->converter) &
316 m_cfg->params_fixup;
317 }
318 }
319
320 skl_tplg_update_params(in_fmt, params, in_fixup);
321 skl_tplg_update_params(out_fmt, params, out_fixup);
322}
323
324/*
325 * A module needs input and output buffers, which are dependent upon pcm
326 * params, so once we have calculate params, we need buffer calculation as
327 * well.
328 */
329static void skl_tplg_update_buffer_size(struct skl_sst *ctx,
330 struct skl_module_cfg *mcfg)
331{
332 int multiplier = 1;
Hardik T Shah4cd98992015-10-27 09:22:55 +0900333 struct skl_module_fmt *in_fmt, *out_fmt;
Ramesh Babuf6fa56e2017-08-23 19:33:53 +0530334 struct skl_module_res *res;
Hardik T Shah4cd98992015-10-27 09:22:55 +0900335
336 /* Since fixups is applied to pin 0 only, ibs, obs needs
337 * change for pin 0 only
338 */
Ramesh Babuf6fa56e2017-08-23 19:33:53 +0530339 res = &mcfg->module->resources[0];
340 in_fmt = &mcfg->module->formats[0].inputs[0].fmt;
341 out_fmt = &mcfg->module->formats[0].outputs[0].fmt;
Jeeja KPf7590d42015-10-07 11:31:53 +0100342
343 if (mcfg->m_type == SKL_MODULE_TYPE_SRCINT)
344 multiplier = 5;
Jeeja KPf7590d42015-10-07 11:31:53 +0100345
Ramesh Babuf6fa56e2017-08-23 19:33:53 +0530346 res->ibs = DIV_ROUND_UP(in_fmt->s_freq, 1000) *
Takashi Sakamoto998d6fb2017-03-08 17:47:02 +0900347 in_fmt->channels * (in_fmt->bit_depth >> 3) *
Subhransu S. Prustyf0c8e1d2016-04-12 10:31:23 +0530348 multiplier;
349
Ramesh Babuf6fa56e2017-08-23 19:33:53 +0530350 res->obs = DIV_ROUND_UP(out_fmt->s_freq, 1000) *
Takashi Sakamoto998d6fb2017-03-08 17:47:02 +0900351 out_fmt->channels * (out_fmt->bit_depth >> 3) *
Subhransu S. Prustyf0c8e1d2016-04-12 10:31:23 +0530352 multiplier;
Jeeja KPf7590d42015-10-07 11:31:53 +0100353}
354
Senthilnathan Veppurdb2f5862017-02-09 16:44:01 +0530355static u8 skl_tplg_be_dev_type(int dev_type)
356{
357 int ret;
358
359 switch (dev_type) {
360 case SKL_DEVICE_BT:
361 ret = NHLT_DEVICE_BT;
362 break;
363
364 case SKL_DEVICE_DMIC:
365 ret = NHLT_DEVICE_DMIC;
366 break;
367
368 case SKL_DEVICE_I2S:
369 ret = NHLT_DEVICE_I2S;
370 break;
371
372 default:
373 ret = NHLT_DEVICE_INVALID;
374 break;
375 }
376
377 return ret;
378}
379
Jeeja KP2d1419a2016-02-05 12:19:10 +0530380static int skl_tplg_update_be_blob(struct snd_soc_dapm_widget *w,
381 struct skl_sst *ctx)
382{
383 struct skl_module_cfg *m_cfg = w->priv;
384 int link_type, dir;
385 u32 ch, s_freq, s_fmt;
386 struct nhlt_specific_cfg *cfg;
387 struct skl *skl = get_skl_ctx(ctx->dev);
Senthilnathan Veppurdb2f5862017-02-09 16:44:01 +0530388 u8 dev_type = skl_tplg_be_dev_type(m_cfg->dev_type);
Ramesh Babuf6fa56e2017-08-23 19:33:53 +0530389 int fmt_idx = m_cfg->fmt_idx;
390 struct skl_module_iface *m_iface = &m_cfg->module->formats[fmt_idx];
Jeeja KP2d1419a2016-02-05 12:19:10 +0530391
392 /* check if we already have blob */
393 if (m_cfg->formats_config.caps_size > 0)
394 return 0;
395
Jeeja KPc7c6c732016-03-01 07:59:10 +0530396 dev_dbg(ctx->dev, "Applying default cfg blob\n");
Jeeja KP2d1419a2016-02-05 12:19:10 +0530397 switch (m_cfg->dev_type) {
398 case SKL_DEVICE_DMIC:
399 link_type = NHLT_LINK_DMIC;
Jeeja KPc7c6c732016-03-01 07:59:10 +0530400 dir = SNDRV_PCM_STREAM_CAPTURE;
Ramesh Babuf6fa56e2017-08-23 19:33:53 +0530401 s_freq = m_iface->inputs[0].fmt.s_freq;
402 s_fmt = m_iface->inputs[0].fmt.bit_depth;
403 ch = m_iface->inputs[0].fmt.channels;
Jeeja KP2d1419a2016-02-05 12:19:10 +0530404 break;
405
406 case SKL_DEVICE_I2S:
407 link_type = NHLT_LINK_SSP;
408 if (m_cfg->hw_conn_type == SKL_CONN_SOURCE) {
Jeeja KPc7c6c732016-03-01 07:59:10 +0530409 dir = SNDRV_PCM_STREAM_PLAYBACK;
Ramesh Babuf6fa56e2017-08-23 19:33:53 +0530410 s_freq = m_iface->outputs[0].fmt.s_freq;
411 s_fmt = m_iface->outputs[0].fmt.bit_depth;
412 ch = m_iface->outputs[0].fmt.channels;
Jeeja KPc7c6c732016-03-01 07:59:10 +0530413 } else {
414 dir = SNDRV_PCM_STREAM_CAPTURE;
Ramesh Babuf6fa56e2017-08-23 19:33:53 +0530415 s_freq = m_iface->inputs[0].fmt.s_freq;
416 s_fmt = m_iface->inputs[0].fmt.bit_depth;
417 ch = m_iface->inputs[0].fmt.channels;
Jeeja KP2d1419a2016-02-05 12:19:10 +0530418 }
419 break;
420
421 default:
422 return -EINVAL;
423 }
424
425 /* update the blob based on virtual bus_id and default params */
426 cfg = skl_get_ep_blob(skl, m_cfg->vbus_id, link_type,
Senthilnathan Veppurdb2f5862017-02-09 16:44:01 +0530427 s_fmt, ch, s_freq, dir, dev_type);
Jeeja KP2d1419a2016-02-05 12:19:10 +0530428 if (cfg) {
429 m_cfg->formats_config.caps_size = cfg->size;
430 m_cfg->formats_config.caps = (u32 *) &cfg->caps;
431 } else {
432 dev_err(ctx->dev, "Blob NULL for id %x type %d dirn %d\n",
433 m_cfg->vbus_id, link_type, dir);
434 dev_err(ctx->dev, "PCM: ch %d, freq %d, fmt %d\n",
435 ch, s_freq, s_fmt);
436 return -EIO;
437 }
438
439 return 0;
440}
441
Jeeja KPf7590d42015-10-07 11:31:53 +0100442static void skl_tplg_update_module_params(struct snd_soc_dapm_widget *w,
443 struct skl_sst *ctx)
444{
445 struct skl_module_cfg *m_cfg = w->priv;
446 struct skl_pipe_params *params = m_cfg->pipe->p_params;
447 int p_conn_type = m_cfg->pipe->conn_type;
448 bool is_fe;
449
450 if (!m_cfg->params_fixup)
451 return;
452
453 dev_dbg(ctx->dev, "Mconfig for widget=%s BEFORE updation\n",
454 w->name);
455
456 skl_dump_mconfig(ctx, m_cfg);
457
458 if (p_conn_type == SKL_PIPE_CONN_TYPE_FE)
459 is_fe = true;
460 else
461 is_fe = false;
462
463 skl_tplg_update_params_fixup(m_cfg, params, is_fe);
464 skl_tplg_update_buffer_size(ctx, m_cfg);
465
466 dev_dbg(ctx->dev, "Mconfig for widget=%s AFTER updation\n",
467 w->name);
468
469 skl_dump_mconfig(ctx, m_cfg);
470}
471
Jeeja KPe4e2d2f2015-10-07 11:31:52 +0100472/*
Jeeja KPabb74002015-11-28 15:01:49 +0530473 * some modules can have multiple params set from user control and
474 * need to be set after module is initialized. If set_param flag is
475 * set module params will be done after module is initialised.
476 */
477static int skl_tplg_set_module_params(struct snd_soc_dapm_widget *w,
478 struct skl_sst *ctx)
479{
480 int i, ret;
481 struct skl_module_cfg *mconfig = w->priv;
482 const struct snd_kcontrol_new *k;
483 struct soc_bytes_ext *sb;
484 struct skl_algo_data *bc;
485 struct skl_specific_cfg *sp_cfg;
486
487 if (mconfig->formats_config.caps_size > 0 &&
Jeeja KP4ced1822015-12-03 23:29:53 +0530488 mconfig->formats_config.set_params == SKL_PARAM_SET) {
Jeeja KPabb74002015-11-28 15:01:49 +0530489 sp_cfg = &mconfig->formats_config;
490 ret = skl_set_module_params(ctx, sp_cfg->caps,
491 sp_cfg->caps_size,
492 sp_cfg->param_id, mconfig);
493 if (ret < 0)
494 return ret;
495 }
496
497 for (i = 0; i < w->num_kcontrols; i++) {
498 k = &w->kcontrol_news[i];
499 if (k->access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK) {
500 sb = (void *) k->private_value;
501 bc = (struct skl_algo_data *)sb->dobj.private;
502
Jeeja KP4ced1822015-12-03 23:29:53 +0530503 if (bc->set_params == SKL_PARAM_SET) {
Jeeja KPabb74002015-11-28 15:01:49 +0530504 ret = skl_set_module_params(ctx,
Dharageswari R0d682102016-07-08 18:15:03 +0530505 (u32 *)bc->params, bc->size,
Jeeja KPabb74002015-11-28 15:01:49 +0530506 bc->param_id, mconfig);
507 if (ret < 0)
508 return ret;
509 }
510 }
511 }
512
513 return 0;
514}
515
516/*
517 * some module param can set from user control and this is required as
518 * when module is initailzed. if module param is required in init it is
519 * identifed by set_param flag. if set_param flag is not set, then this
520 * parameter needs to set as part of module init.
521 */
522static int skl_tplg_set_module_init_data(struct snd_soc_dapm_widget *w)
523{
524 const struct snd_kcontrol_new *k;
525 struct soc_bytes_ext *sb;
526 struct skl_algo_data *bc;
527 struct skl_module_cfg *mconfig = w->priv;
528 int i;
529
530 for (i = 0; i < w->num_kcontrols; i++) {
531 k = &w->kcontrol_news[i];
532 if (k->access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK) {
533 sb = (struct soc_bytes_ext *)k->private_value;
534 bc = (struct skl_algo_data *)sb->dobj.private;
535
Jeeja KP4ced1822015-12-03 23:29:53 +0530536 if (bc->set_params != SKL_PARAM_INIT)
Jeeja KPabb74002015-11-28 15:01:49 +0530537 continue;
538
Takashi Sakamotod1a6fe42017-02-24 11:48:41 +0900539 mconfig->formats_config.caps = (u32 *)bc->params;
Dharageswari R0d682102016-07-08 18:15:03 +0530540 mconfig->formats_config.caps_size = bc->size;
Jeeja KPabb74002015-11-28 15:01:49 +0530541
542 break;
543 }
544 }
545
546 return 0;
547}
548
Jeeja KPbb704a732016-12-08 13:41:14 +0530549static int skl_tplg_module_prepare(struct skl_sst *ctx, struct skl_pipe *pipe,
550 struct snd_soc_dapm_widget *w, struct skl_module_cfg *mcfg)
551{
552 switch (mcfg->dev_type) {
553 case SKL_DEVICE_HDAHOST:
554 return skl_pcm_host_dma_prepare(ctx->dev, pipe->p_params);
555
556 case SKL_DEVICE_HDALINK:
557 return skl_pcm_link_dma_prepare(ctx->dev, pipe->p_params);
558 }
559
560 return 0;
561}
562
Jeeja KPabb74002015-11-28 15:01:49 +0530563/*
Jeeja KPe4e2d2f2015-10-07 11:31:52 +0100564 * Inside a pipe instance, we can have various modules. These modules need
565 * to instantiated in DSP by invoking INIT_MODULE IPC, which is achieved by
566 * skl_init_module() routine, so invoke that for all modules in a pipeline
567 */
568static int
569skl_tplg_init_pipe_modules(struct skl *skl, struct skl_pipe *pipe)
570{
571 struct skl_pipe_module *w_module;
572 struct snd_soc_dapm_widget *w;
573 struct skl_module_cfg *mconfig;
574 struct skl_sst *ctx = skl->skl_sst;
Ramesh Babuf6fa56e2017-08-23 19:33:53 +0530575 u8 cfg_idx;
Jeeja KPe4e2d2f2015-10-07 11:31:52 +0100576 int ret = 0;
577
578 list_for_each_entry(w_module, &pipe->w_list, node) {
Jeeja KPb26199e2017-03-24 23:10:31 +0530579 uuid_le *uuid_mod;
Jeeja KPe4e2d2f2015-10-07 11:31:52 +0100580 w = w_module->w;
581 mconfig = w->priv;
582
Vinod Koulb7c50552016-07-26 18:06:40 +0530583 /* check if module ids are populated */
584 if (mconfig->id.module_id < 0) {
Vinod Koula657ae72016-08-10 09:40:50 +0530585 dev_err(skl->skl_sst->dev,
586 "module %pUL id not populated\n",
587 (uuid_le *)mconfig->guid);
588 return -EIO;
Vinod Koulb7c50552016-07-26 18:06:40 +0530589 }
590
Ramesh Babuf6fa56e2017-08-23 19:33:53 +0530591 cfg_idx = mconfig->pipe->cur_config_idx;
592 mconfig->fmt_idx = mconfig->mod_cfg[cfg_idx].fmt_idx;
593 mconfig->res_idx = mconfig->mod_cfg[cfg_idx].res_idx;
594
Jeeja KPe4e2d2f2015-10-07 11:31:52 +0100595 /* check resource available */
Dharageswari.R9ba8ffe2016-02-03 17:59:47 +0530596 if (!skl_is_pipe_mcps_avail(skl, mconfig))
Jeeja KPe4e2d2f2015-10-07 11:31:52 +0100597 return -ENOMEM;
598
Ramesh Babuf6fa56e2017-08-23 19:33:53 +0530599 if (mconfig->module->loadable && ctx->dsp->fw_ops.load_mod) {
Dharageswari R6c5768b2015-12-03 23:29:50 +0530600 ret = ctx->dsp->fw_ops.load_mod(ctx->dsp,
601 mconfig->id.module_id, mconfig->guid);
602 if (ret < 0)
603 return ret;
Jeeja KPd6436782016-03-28 22:11:30 +0530604
605 mconfig->m_state = SKL_MODULE_LOADED;
Dharageswari R6c5768b2015-12-03 23:29:50 +0530606 }
607
Jeeja KPbb704a732016-12-08 13:41:14 +0530608 /* prepare the DMA if the module is gateway cpr */
609 ret = skl_tplg_module_prepare(ctx, pipe, w, mconfig);
610 if (ret < 0)
611 return ret;
612
Jeeja KP2d1419a2016-02-05 12:19:10 +0530613 /* update blob if blob is null for be with default value */
614 skl_tplg_update_be_blob(w, ctx);
615
Jeeja KPf7590d42015-10-07 11:31:53 +0100616 /*
617 * apply fix/conversion to module params based on
618 * FE/BE params
619 */
620 skl_tplg_update_module_params(w, ctx);
Jeeja KPb26199e2017-03-24 23:10:31 +0530621 uuid_mod = (uuid_le *)mconfig->guid;
622 mconfig->id.pvt_id = skl_get_pvt_id(ctx, uuid_mod,
623 mconfig->id.instance_id);
Dharageswari Ref2a3522016-09-22 14:00:38 +0530624 if (mconfig->id.pvt_id < 0)
625 return ret;
Jeeja KPabb74002015-11-28 15:01:49 +0530626 skl_tplg_set_module_init_data(w);
Pardha Saradhi K4147a6e2017-08-02 21:51:14 +0530627
628 ret = skl_dsp_get_core(ctx->dsp, mconfig->core_id);
629 if (ret < 0) {
630 dev_err(ctx->dev, "Failed to wake up core %d ret=%d\n",
631 mconfig->core_id, ret);
632 return ret;
633 }
634
Jeeja KP9939a9c2015-11-28 15:01:47 +0530635 ret = skl_init_module(ctx, mconfig);
Dharageswari Ref2a3522016-09-22 14:00:38 +0530636 if (ret < 0) {
Jeeja KPb26199e2017-03-24 23:10:31 +0530637 skl_put_pvt_id(ctx, uuid_mod, &mconfig->id.pvt_id);
Pardha Saradhi K4147a6e2017-08-02 21:51:14 +0530638 goto err;
Dharageswari Ref2a3522016-09-22 14:00:38 +0530639 }
Dharageswari R260eb732016-06-03 18:29:38 +0530640 skl_tplg_alloc_pipe_mcps(skl, mconfig);
Jeeja KPabb74002015-11-28 15:01:49 +0530641 ret = skl_tplg_set_module_params(w, ctx);
Jeeja KPe4e2d2f2015-10-07 11:31:52 +0100642 if (ret < 0)
Pardha Saradhi K4147a6e2017-08-02 21:51:14 +0530643 goto err;
Jeeja KPe4e2d2f2015-10-07 11:31:52 +0100644 }
645
646 return 0;
Pardha Saradhi K4147a6e2017-08-02 21:51:14 +0530647err:
648 skl_dsp_put_core(ctx->dsp, mconfig->core_id);
649 return ret;
Jeeja KPe4e2d2f2015-10-07 11:31:52 +0100650}
Vinod Kould93f8e52015-10-07 11:31:54 +0100651
Dharageswari R6c5768b2015-12-03 23:29:50 +0530652static int skl_tplg_unload_pipe_modules(struct skl_sst *ctx,
653 struct skl_pipe *pipe)
654{
Pardha Saradhi K4147a6e2017-08-02 21:51:14 +0530655 int ret = 0;
Dharageswari R6c5768b2015-12-03 23:29:50 +0530656 struct skl_pipe_module *w_module = NULL;
657 struct skl_module_cfg *mconfig = NULL;
658
659 list_for_each_entry(w_module, &pipe->w_list, node) {
Jeeja KPb26199e2017-03-24 23:10:31 +0530660 uuid_le *uuid_mod;
Dharageswari R6c5768b2015-12-03 23:29:50 +0530661 mconfig = w_module->w->priv;
Jeeja KPb26199e2017-03-24 23:10:31 +0530662 uuid_mod = (uuid_le *)mconfig->guid;
Dharageswari R6c5768b2015-12-03 23:29:50 +0530663
Ramesh Babuf6fa56e2017-08-23 19:33:53 +0530664 if (mconfig->module->loadable && ctx->dsp->fw_ops.unload_mod &&
Dharageswari Rb0fab9c2016-08-24 18:03:16 +0530665 mconfig->m_state > SKL_MODULE_UNINIT) {
666 ret = ctx->dsp->fw_ops.unload_mod(ctx->dsp,
Dharageswari R6c5768b2015-12-03 23:29:50 +0530667 mconfig->id.module_id);
Dharageswari Rb0fab9c2016-08-24 18:03:16 +0530668 if (ret < 0)
669 return -EIO;
670 }
Jeeja KPb26199e2017-03-24 23:10:31 +0530671 skl_put_pvt_id(ctx, uuid_mod, &mconfig->id.pvt_id);
Pardha Saradhi K4147a6e2017-08-02 21:51:14 +0530672
673 ret = skl_dsp_put_core(ctx->dsp, mconfig->core_id);
674 if (ret < 0) {
675 /* don't return; continue with other modules */
676 dev_err(ctx->dev, "Failed to sleep core %d ret=%d\n",
677 mconfig->core_id, ret);
678 }
Dharageswari R6c5768b2015-12-03 23:29:50 +0530679 }
680
681 /* no modules to unload in this path, so return */
Pardha Saradhi K4147a6e2017-08-02 21:51:14 +0530682 return ret;
Dharageswari R6c5768b2015-12-03 23:29:50 +0530683}
684
Vinod Kould93f8e52015-10-07 11:31:54 +0100685/*
Ramesh Babuf6fa56e2017-08-23 19:33:53 +0530686 * Here, we select pipe format based on the pipe type and pipe
687 * direction to determine the current config index for the pipeline.
688 * The config index is then used to select proper module resources.
689 * Intermediate pipes currently have a fixed format hence we select the
690 * 0th configuratation by default for such pipes.
691 */
692static int
693skl_tplg_get_pipe_config(struct skl *skl, struct skl_module_cfg *mconfig)
694{
695 struct skl_sst *ctx = skl->skl_sst;
696 struct skl_pipe *pipe = mconfig->pipe;
697 struct skl_pipe_params *params = pipe->p_params;
698 struct skl_path_config *pconfig = &pipe->configs[0];
699 struct skl_pipe_fmt *fmt = NULL;
700 bool in_fmt = false;
701 int i;
702
703 if (pipe->nr_cfgs == 0) {
704 pipe->cur_config_idx = 0;
705 return 0;
706 }
707
708 if (pipe->conn_type == SKL_PIPE_CONN_TYPE_NONE) {
709 dev_dbg(ctx->dev, "No conn_type detected, take 0th config\n");
710 pipe->cur_config_idx = 0;
711 pipe->memory_pages = pconfig->mem_pages;
712
713 return 0;
714 }
715
716 if ((pipe->conn_type == SKL_PIPE_CONN_TYPE_FE &&
717 pipe->direction == SNDRV_PCM_STREAM_PLAYBACK) ||
718 (pipe->conn_type == SKL_PIPE_CONN_TYPE_BE &&
719 pipe->direction == SNDRV_PCM_STREAM_CAPTURE))
720 in_fmt = true;
721
722 for (i = 0; i < pipe->nr_cfgs; i++) {
723 pconfig = &pipe->configs[i];
724 if (in_fmt)
725 fmt = &pconfig->in_fmt;
726 else
727 fmt = &pconfig->out_fmt;
728
729 if (CHECK_HW_PARAMS(params->ch, params->s_freq, params->s_fmt,
730 fmt->channels, fmt->freq, fmt->bps)) {
731 pipe->cur_config_idx = i;
732 pipe->memory_pages = pconfig->mem_pages;
733 dev_dbg(ctx->dev, "Using pipe config: %d\n", i);
734
735 return 0;
736 }
737 }
738
739 dev_err(ctx->dev, "Invalid pipe config: %d %d %d for pipe: %d\n",
740 params->ch, params->s_freq, params->s_fmt, pipe->ppl_id);
741 return -EINVAL;
742}
743
744/*
Vinod Kould93f8e52015-10-07 11:31:54 +0100745 * Mixer module represents a pipeline. So in the Pre-PMU event of mixer we
746 * need create the pipeline. So we do following:
747 * - check the resources
748 * - Create the pipeline
749 * - Initialize the modules in pipeline
750 * - finally bind all modules together
751 */
752static int skl_tplg_mixer_dapm_pre_pmu_event(struct snd_soc_dapm_widget *w,
753 struct skl *skl)
754{
755 int ret;
756 struct skl_module_cfg *mconfig = w->priv;
757 struct skl_pipe_module *w_module;
758 struct skl_pipe *s_pipe = mconfig->pipe;
Jeeja KPb8c722d2017-03-24 23:10:34 +0530759 struct skl_module_cfg *src_module = NULL, *dst_module, *module;
Vinod Kould93f8e52015-10-07 11:31:54 +0100760 struct skl_sst *ctx = skl->skl_sst;
Jeeja KPb8c722d2017-03-24 23:10:34 +0530761 struct skl_module_deferred_bind *modules;
Vinod Kould93f8e52015-10-07 11:31:54 +0100762
Ramesh Babuf6fa56e2017-08-23 19:33:53 +0530763 ret = skl_tplg_get_pipe_config(skl, mconfig);
764 if (ret < 0)
765 return ret;
766
Vinod Kould93f8e52015-10-07 11:31:54 +0100767 /* check resource available */
Dharageswari.R9ba8ffe2016-02-03 17:59:47 +0530768 if (!skl_is_pipe_mcps_avail(skl, mconfig))
Vinod Kould93f8e52015-10-07 11:31:54 +0100769 return -EBUSY;
770
Dharageswari.R9ba8ffe2016-02-03 17:59:47 +0530771 if (!skl_is_pipe_mem_avail(skl, mconfig))
Vinod Kould93f8e52015-10-07 11:31:54 +0100772 return -ENOMEM;
773
774 /*
775 * Create a list of modules for pipe.
776 * This list contains modules from source to sink
777 */
778 ret = skl_create_pipeline(ctx, mconfig->pipe);
779 if (ret < 0)
780 return ret;
781
Dharageswari R260eb732016-06-03 18:29:38 +0530782 skl_tplg_alloc_pipe_mem(skl, mconfig);
783 skl_tplg_alloc_pipe_mcps(skl, mconfig);
Vinod Kould93f8e52015-10-07 11:31:54 +0100784
785 /* Init all pipe modules from source to sink */
786 ret = skl_tplg_init_pipe_modules(skl, s_pipe);
787 if (ret < 0)
788 return ret;
789
790 /* Bind modules from source to sink */
791 list_for_each_entry(w_module, &s_pipe->w_list, node) {
792 dst_module = w_module->w->priv;
793
794 if (src_module == NULL) {
795 src_module = dst_module;
796 continue;
797 }
798
799 ret = skl_bind_modules(ctx, src_module, dst_module);
800 if (ret < 0)
801 return ret;
802
803 src_module = dst_module;
804 }
805
Jeeja KPb8c722d2017-03-24 23:10:34 +0530806 /*
807 * When the destination module is initialized, check for these modules
808 * in deferred bind list. If found, bind them.
809 */
810 list_for_each_entry(w_module, &s_pipe->w_list, node) {
811 if (list_empty(&skl->bind_list))
812 break;
813
814 list_for_each_entry(modules, &skl->bind_list, node) {
815 module = w_module->w->priv;
816 if (modules->dst == module)
817 skl_bind_modules(ctx, modules->src,
818 modules->dst);
819 }
820 }
821
Vinod Kould93f8e52015-10-07 11:31:54 +0100822 return 0;
823}
824
Dharageswari Rbf3e5ef2017-03-13 22:11:32 +0530825static int skl_fill_sink_instance_id(struct skl_sst *ctx, u32 *params,
826 int size, struct skl_module_cfg *mcfg)
Dharageswari R5e8f0ee2016-09-22 14:00:40 +0530827{
Dharageswari R5e8f0ee2016-09-22 14:00:40 +0530828 int i, pvt_id;
829
Dharageswari Rbf3e5ef2017-03-13 22:11:32 +0530830 if (mcfg->m_type == SKL_MODULE_TYPE_KPB) {
831 struct skl_kpb_params *kpb_params =
832 (struct skl_kpb_params *)params;
833 struct skl_mod_inst_map *inst = kpb_params->map;
Dharageswari R5e8f0ee2016-09-22 14:00:40 +0530834
Dharageswari Rbf3e5ef2017-03-13 22:11:32 +0530835 for (i = 0; i < kpb_params->num_modules; i++) {
836 pvt_id = skl_get_pvt_instance_id_map(ctx, inst->mod_id,
837 inst->inst_id);
838 if (pvt_id < 0)
839 return -EINVAL;
840
841 inst->inst_id = pvt_id;
842 inst++;
843 }
Dharageswari R5e8f0ee2016-09-22 14:00:40 +0530844 }
Dharageswari Rbf3e5ef2017-03-13 22:11:32 +0530845
Dharageswari R5e8f0ee2016-09-22 14:00:40 +0530846 return 0;
847}
Jeeja KPcc6a4042016-02-05 12:19:08 +0530848/*
849 * Some modules require params to be set after the module is bound to
850 * all pins connected.
851 *
852 * The module provider initializes set_param flag for such modules and we
853 * send params after binding
854 */
855static int skl_tplg_set_module_bind_params(struct snd_soc_dapm_widget *w,
856 struct skl_module_cfg *mcfg, struct skl_sst *ctx)
857{
858 int i, ret;
859 struct skl_module_cfg *mconfig = w->priv;
860 const struct snd_kcontrol_new *k;
861 struct soc_bytes_ext *sb;
862 struct skl_algo_data *bc;
863 struct skl_specific_cfg *sp_cfg;
Dharageswari Rbf3e5ef2017-03-13 22:11:32 +0530864 u32 *params;
Jeeja KPcc6a4042016-02-05 12:19:08 +0530865
866 /*
867 * check all out/in pins are in bind state.
868 * if so set the module param
869 */
Ramesh Babuf6fa56e2017-08-23 19:33:53 +0530870 for (i = 0; i < mcfg->module->max_output_pins; i++) {
Jeeja KPcc6a4042016-02-05 12:19:08 +0530871 if (mcfg->m_out_pin[i].pin_state != SKL_PIN_BIND_DONE)
872 return 0;
873 }
874
Ramesh Babuf6fa56e2017-08-23 19:33:53 +0530875 for (i = 0; i < mcfg->module->max_input_pins; i++) {
Jeeja KPcc6a4042016-02-05 12:19:08 +0530876 if (mcfg->m_in_pin[i].pin_state != SKL_PIN_BIND_DONE)
877 return 0;
878 }
879
880 if (mconfig->formats_config.caps_size > 0 &&
881 mconfig->formats_config.set_params == SKL_PARAM_BIND) {
882 sp_cfg = &mconfig->formats_config;
883 ret = skl_set_module_params(ctx, sp_cfg->caps,
884 sp_cfg->caps_size,
885 sp_cfg->param_id, mconfig);
886 if (ret < 0)
887 return ret;
888 }
889
890 for (i = 0; i < w->num_kcontrols; i++) {
891 k = &w->kcontrol_news[i];
892 if (k->access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK) {
893 sb = (void *) k->private_value;
894 bc = (struct skl_algo_data *)sb->dobj.private;
895
896 if (bc->set_params == SKL_PARAM_BIND) {
Dharageswari Rbf3e5ef2017-03-13 22:11:32 +0530897 params = kzalloc(bc->max, GFP_KERNEL);
898 if (!params)
899 return -ENOMEM;
900
901 memcpy(params, bc->params, bc->max);
902 skl_fill_sink_instance_id(ctx, params, bc->max,
903 mconfig);
904
905 ret = skl_set_module_params(ctx, params,
906 bc->max, bc->param_id, mconfig);
907 kfree(params);
908
Jeeja KPcc6a4042016-02-05 12:19:08 +0530909 if (ret < 0)
910 return ret;
911 }
912 }
913 }
914
915 return 0;
916}
917
Jeeja KPb8c722d2017-03-24 23:10:34 +0530918
919static int skl_tplg_module_add_deferred_bind(struct skl *skl,
920 struct skl_module_cfg *src, struct skl_module_cfg *dst)
921{
922 struct skl_module_deferred_bind *m_list, *modules;
923 int i;
924
925 /* only supported for module with static pin connection */
Ramesh Babuf6fa56e2017-08-23 19:33:53 +0530926 for (i = 0; i < dst->module->max_input_pins; i++) {
Jeeja KPb8c722d2017-03-24 23:10:34 +0530927 struct skl_module_pin *pin = &dst->m_in_pin[i];
928
929 if (pin->is_dynamic)
930 continue;
931
932 if ((pin->id.module_id == src->id.module_id) &&
933 (pin->id.instance_id == src->id.instance_id)) {
934
935 if (!list_empty(&skl->bind_list)) {
936 list_for_each_entry(modules, &skl->bind_list, node) {
937 if (modules->src == src && modules->dst == dst)
938 return 0;
939 }
940 }
941
942 m_list = kzalloc(sizeof(*m_list), GFP_KERNEL);
943 if (!m_list)
944 return -ENOMEM;
945
946 m_list->src = src;
947 m_list->dst = dst;
948
949 list_add(&m_list->node, &skl->bind_list);
950 }
951 }
952
953 return 0;
954}
955
Jeeja KP8724ff12015-10-27 09:22:52 +0900956static int skl_tplg_bind_sinks(struct snd_soc_dapm_widget *w,
957 struct skl *skl,
Jeeja KP6bd4cf82016-02-03 17:59:51 +0530958 struct snd_soc_dapm_widget *src_w,
Jeeja KP8724ff12015-10-27 09:22:52 +0900959 struct skl_module_cfg *src_mconfig)
Vinod Kould93f8e52015-10-07 11:31:54 +0100960{
961 struct snd_soc_dapm_path *p;
Jeeja KP0ed95d72015-11-13 19:22:11 +0530962 struct snd_soc_dapm_widget *sink = NULL, *next_sink = NULL;
Jeeja KP8724ff12015-10-27 09:22:52 +0900963 struct skl_module_cfg *sink_mconfig;
Vinod Kould93f8e52015-10-07 11:31:54 +0100964 struct skl_sst *ctx = skl->skl_sst;
Jeeja KP8724ff12015-10-27 09:22:52 +0900965 int ret;
Vinod Kould93f8e52015-10-07 11:31:54 +0100966
Jeeja KP8724ff12015-10-27 09:22:52 +0900967 snd_soc_dapm_widget_for_each_sink_path(w, p) {
Vinod Kould93f8e52015-10-07 11:31:54 +0100968 if (!p->connect)
969 continue;
970
971 dev_dbg(ctx->dev, "%s: src widget=%s\n", __func__, w->name);
972 dev_dbg(ctx->dev, "%s: sink widget=%s\n", __func__, p->sink->name);
973
Jeeja KP0ed95d72015-11-13 19:22:11 +0530974 next_sink = p->sink;
Jeeja KP6bd4cf82016-02-03 17:59:51 +0530975
Guneshwor Singhcb1f9042018-01-27 09:50:21 +0530976 if (!is_skl_dsp_widget_type(p->sink, ctx->dev))
Jeeja KP6bd4cf82016-02-03 17:59:51 +0530977 return skl_tplg_bind_sinks(p->sink, skl, src_w, src_mconfig);
978
Vinod Kould93f8e52015-10-07 11:31:54 +0100979 /*
980 * here we will check widgets in sink pipelines, so that
981 * can be any widgets type and we are only interested if
982 * they are ones used for SKL so check that first
983 */
984 if ((p->sink->priv != NULL) &&
Guneshwor Singhcb1f9042018-01-27 09:50:21 +0530985 is_skl_dsp_widget_type(p->sink, ctx->dev)) {
Vinod Kould93f8e52015-10-07 11:31:54 +0100986
987 sink = p->sink;
Vinod Kould93f8e52015-10-07 11:31:54 +0100988 sink_mconfig = sink->priv;
989
Jeeja KPb8c722d2017-03-24 23:10:34 +0530990 /*
991 * Modules other than PGA leaf can be connected
992 * directly or via switch to a module in another
993 * pipeline. EX: reference path
994 * when the path is enabled, the dst module that needs
995 * to be bound may not be initialized. if the module is
996 * not initialized, add these modules in the deferred
997 * bind list and when the dst module is initialised,
998 * bind this module to the dst_module in deferred list.
999 */
1000 if (((src_mconfig->m_state == SKL_MODULE_INIT_DONE)
1001 && (sink_mconfig->m_state == SKL_MODULE_UNINIT))) {
1002
1003 ret = skl_tplg_module_add_deferred_bind(skl,
1004 src_mconfig, sink_mconfig);
1005
1006 if (ret < 0)
1007 return ret;
1008
1009 }
1010
1011
Jeeja KPcc6a4042016-02-05 12:19:08 +05301012 if (src_mconfig->m_state == SKL_MODULE_UNINIT ||
1013 sink_mconfig->m_state == SKL_MODULE_UNINIT)
1014 continue;
1015
Vinod Kould93f8e52015-10-07 11:31:54 +01001016 /* Bind source to sink, mixin is always source */
1017 ret = skl_bind_modules(ctx, src_mconfig, sink_mconfig);
1018 if (ret)
1019 return ret;
1020
Jeeja KPcc6a4042016-02-05 12:19:08 +05301021 /* set module params after bind */
1022 skl_tplg_set_module_bind_params(src_w, src_mconfig, ctx);
1023 skl_tplg_set_module_bind_params(sink, sink_mconfig, ctx);
1024
Vinod Kould93f8e52015-10-07 11:31:54 +01001025 /* Start sinks pipe first */
1026 if (sink_mconfig->pipe->state != SKL_PIPE_STARTED) {
Jeeja KPd1730c32015-10-27 09:22:53 +09001027 if (sink_mconfig->pipe->conn_type !=
1028 SKL_PIPE_CONN_TYPE_FE)
1029 ret = skl_run_pipe(ctx,
1030 sink_mconfig->pipe);
Vinod Kould93f8e52015-10-07 11:31:54 +01001031 if (ret)
1032 return ret;
1033 }
Vinod Kould93f8e52015-10-07 11:31:54 +01001034 }
1035 }
1036
guneshwor.o.singh@intel.com10a54392017-07-28 16:12:16 +05301037 if (!sink && next_sink)
Jeeja KP6bd4cf82016-02-03 17:59:51 +05301038 return skl_tplg_bind_sinks(next_sink, skl, src_w, src_mconfig);
Jeeja KP8724ff12015-10-27 09:22:52 +09001039
1040 return 0;
1041}
1042
Vinod Kould93f8e52015-10-07 11:31:54 +01001043/*
1044 * A PGA represents a module in a pipeline. So in the Pre-PMU event of PGA
1045 * we need to do following:
1046 * - Bind to sink pipeline
1047 * Since the sink pipes can be running and we don't get mixer event on
1048 * connect for already running mixer, we need to find the sink pipes
1049 * here and bind to them. This way dynamic connect works.
1050 * - Start sink pipeline, if not running
1051 * - Then run current pipe
1052 */
1053static int skl_tplg_pga_dapm_pre_pmu_event(struct snd_soc_dapm_widget *w,
Jeeja KP8724ff12015-10-27 09:22:52 +09001054 struct skl *skl)
Vinod Kould93f8e52015-10-07 11:31:54 +01001055{
Jeeja KP8724ff12015-10-27 09:22:52 +09001056 struct skl_module_cfg *src_mconfig;
Vinod Kould93f8e52015-10-07 11:31:54 +01001057 struct skl_sst *ctx = skl->skl_sst;
1058 int ret = 0;
1059
Jeeja KP8724ff12015-10-27 09:22:52 +09001060 src_mconfig = w->priv;
Vinod Kould93f8e52015-10-07 11:31:54 +01001061
1062 /*
1063 * find which sink it is connected to, bind with the sink,
1064 * if sink is not started, start sink pipe first, then start
1065 * this pipe
1066 */
Jeeja KP6bd4cf82016-02-03 17:59:51 +05301067 ret = skl_tplg_bind_sinks(w, skl, w, src_mconfig);
Vinod Kould93f8e52015-10-07 11:31:54 +01001068 if (ret)
1069 return ret;
1070
Vinod Kould93f8e52015-10-07 11:31:54 +01001071 /* Start source pipe last after starting all sinks */
Jeeja KPd1730c32015-10-27 09:22:53 +09001072 if (src_mconfig->pipe->conn_type != SKL_PIPE_CONN_TYPE_FE)
1073 return skl_run_pipe(ctx, src_mconfig->pipe);
Vinod Kould93f8e52015-10-07 11:31:54 +01001074
1075 return 0;
1076}
1077
Jeeja KP8724ff12015-10-27 09:22:52 +09001078static struct snd_soc_dapm_widget *skl_get_src_dsp_widget(
1079 struct snd_soc_dapm_widget *w, struct skl *skl)
1080{
1081 struct snd_soc_dapm_path *p;
1082 struct snd_soc_dapm_widget *src_w = NULL;
1083 struct skl_sst *ctx = skl->skl_sst;
1084
1085 snd_soc_dapm_widget_for_each_source_path(w, p) {
1086 src_w = p->source;
1087 if (!p->connect)
1088 continue;
1089
1090 dev_dbg(ctx->dev, "sink widget=%s\n", w->name);
1091 dev_dbg(ctx->dev, "src widget=%s\n", p->source->name);
1092
1093 /*
1094 * here we will check widgets in sink pipelines, so that can
1095 * be any widgets type and we are only interested if they are
1096 * ones used for SKL so check that first
1097 */
1098 if ((p->source->priv != NULL) &&
Guneshwor Singhcb1f9042018-01-27 09:50:21 +05301099 is_skl_dsp_widget_type(p->source, ctx->dev)) {
Jeeja KP8724ff12015-10-27 09:22:52 +09001100 return p->source;
1101 }
1102 }
1103
1104 if (src_w != NULL)
1105 return skl_get_src_dsp_widget(src_w, skl);
1106
1107 return NULL;
1108}
1109
Vinod Kould93f8e52015-10-07 11:31:54 +01001110/*
1111 * in the Post-PMU event of mixer we need to do following:
1112 * - Check if this pipe is running
1113 * - if not, then
1114 * - bind this pipeline to its source pipeline
1115 * if source pipe is already running, this means it is a dynamic
1116 * connection and we need to bind only to that pipe
1117 * - start this pipeline
1118 */
1119static int skl_tplg_mixer_dapm_post_pmu_event(struct snd_soc_dapm_widget *w,
1120 struct skl *skl)
1121{
1122 int ret = 0;
Vinod Kould93f8e52015-10-07 11:31:54 +01001123 struct snd_soc_dapm_widget *source, *sink;
1124 struct skl_module_cfg *src_mconfig, *sink_mconfig;
1125 struct skl_sst *ctx = skl->skl_sst;
1126 int src_pipe_started = 0;
1127
1128 sink = w;
1129 sink_mconfig = sink->priv;
1130
1131 /*
1132 * If source pipe is already started, that means source is driving
1133 * one more sink before this sink got connected, Since source is
1134 * started, bind this sink to source and start this pipe.
1135 */
Jeeja KP8724ff12015-10-27 09:22:52 +09001136 source = skl_get_src_dsp_widget(w, skl);
1137 if (source != NULL) {
1138 src_mconfig = source->priv;
1139 sink_mconfig = sink->priv;
1140 src_pipe_started = 1;
Vinod Kould93f8e52015-10-07 11:31:54 +01001141
1142 /*
Jeeja KP8724ff12015-10-27 09:22:52 +09001143 * check pipe state, then no need to bind or start the
1144 * pipe
Vinod Kould93f8e52015-10-07 11:31:54 +01001145 */
Jeeja KP8724ff12015-10-27 09:22:52 +09001146 if (src_mconfig->pipe->state != SKL_PIPE_STARTED)
1147 src_pipe_started = 0;
Vinod Kould93f8e52015-10-07 11:31:54 +01001148 }
1149
1150 if (src_pipe_started) {
1151 ret = skl_bind_modules(ctx, src_mconfig, sink_mconfig);
1152 if (ret)
1153 return ret;
1154
Jeeja KPcc6a4042016-02-05 12:19:08 +05301155 /* set module params after bind */
1156 skl_tplg_set_module_bind_params(source, src_mconfig, ctx);
1157 skl_tplg_set_module_bind_params(sink, sink_mconfig, ctx);
1158
Jeeja KPd1730c32015-10-27 09:22:53 +09001159 if (sink_mconfig->pipe->conn_type != SKL_PIPE_CONN_TYPE_FE)
1160 ret = skl_run_pipe(ctx, sink_mconfig->pipe);
Vinod Kould93f8e52015-10-07 11:31:54 +01001161 }
1162
1163 return ret;
1164}
1165
1166/*
1167 * in the Pre-PMD event of mixer we need to do following:
1168 * - Stop the pipe
1169 * - find the source connections and remove that from dapm_path_list
1170 * - unbind with source pipelines if still connected
1171 */
1172static int skl_tplg_mixer_dapm_pre_pmd_event(struct snd_soc_dapm_widget *w,
1173 struct skl *skl)
1174{
Vinod Kould93f8e52015-10-07 11:31:54 +01001175 struct skl_module_cfg *src_mconfig, *sink_mconfig;
Jeeja KPce1b5552015-10-27 09:22:51 +09001176 int ret = 0, i;
Vinod Kould93f8e52015-10-07 11:31:54 +01001177 struct skl_sst *ctx = skl->skl_sst;
1178
Jeeja KPce1b5552015-10-27 09:22:51 +09001179 sink_mconfig = w->priv;
Vinod Kould93f8e52015-10-07 11:31:54 +01001180
1181 /* Stop the pipe */
1182 ret = skl_stop_pipe(ctx, sink_mconfig->pipe);
1183 if (ret)
1184 return ret;
1185
Ramesh Babuf6fa56e2017-08-23 19:33:53 +05301186 for (i = 0; i < sink_mconfig->module->max_input_pins; i++) {
Jeeja KPce1b5552015-10-27 09:22:51 +09001187 if (sink_mconfig->m_in_pin[i].pin_state == SKL_PIN_BIND_DONE) {
1188 src_mconfig = sink_mconfig->m_in_pin[i].tgt_mcfg;
1189 if (!src_mconfig)
1190 continue;
Vinod Kould93f8e52015-10-07 11:31:54 +01001191
Jeeja KPce1b5552015-10-27 09:22:51 +09001192 ret = skl_unbind_modules(ctx,
1193 src_mconfig, sink_mconfig);
Vinod Kould93f8e52015-10-07 11:31:54 +01001194 }
1195 }
1196
Vinod Kould93f8e52015-10-07 11:31:54 +01001197 return ret;
1198}
1199
1200/*
1201 * in the Post-PMD event of mixer we need to do following:
1202 * - Free the mcps used
1203 * - Free the mem used
1204 * - Unbind the modules within the pipeline
1205 * - Delete the pipeline (modules are not required to be explicitly
1206 * deleted, pipeline delete is enough here
1207 */
1208static int skl_tplg_mixer_dapm_post_pmd_event(struct snd_soc_dapm_widget *w,
1209 struct skl *skl)
1210{
1211 struct skl_module_cfg *mconfig = w->priv;
1212 struct skl_pipe_module *w_module;
1213 struct skl_module_cfg *src_module = NULL, *dst_module;
1214 struct skl_sst *ctx = skl->skl_sst;
1215 struct skl_pipe *s_pipe = mconfig->pipe;
Dan Carpenter550b3492017-04-14 22:11:20 +03001216 struct skl_module_deferred_bind *modules, *tmp;
Vinod Kould93f8e52015-10-07 11:31:54 +01001217
Dharageswari R260eb732016-06-03 18:29:38 +05301218 if (s_pipe->state == SKL_PIPE_INVALID)
1219 return -EINVAL;
1220
Vinod Kould93f8e52015-10-07 11:31:54 +01001221 skl_tplg_free_pipe_mcps(skl, mconfig);
Vinod Koul65976872015-11-23 22:26:29 +05301222 skl_tplg_free_pipe_mem(skl, mconfig);
Vinod Kould93f8e52015-10-07 11:31:54 +01001223
1224 list_for_each_entry(w_module, &s_pipe->w_list, node) {
Jeeja KPb8c722d2017-03-24 23:10:34 +05301225 if (list_empty(&skl->bind_list))
1226 break;
1227
1228 src_module = w_module->w->priv;
1229
Dan Carpenter550b3492017-04-14 22:11:20 +03001230 list_for_each_entry_safe(modules, tmp, &skl->bind_list, node) {
Jeeja KPb8c722d2017-03-24 23:10:34 +05301231 /*
1232 * When the destination module is deleted, Unbind the
1233 * modules from deferred bind list.
1234 */
1235 if (modules->dst == src_module) {
1236 skl_unbind_modules(ctx, modules->src,
1237 modules->dst);
1238 }
1239
1240 /*
1241 * When the source module is deleted, remove this entry
1242 * from the deferred bind list.
1243 */
1244 if (modules->src == src_module) {
1245 list_del(&modules->node);
1246 modules->src = NULL;
1247 modules->dst = NULL;
1248 kfree(modules);
1249 }
1250 }
1251 }
1252
1253 list_for_each_entry(w_module, &s_pipe->w_list, node) {
Vinod Kould93f8e52015-10-07 11:31:54 +01001254 dst_module = w_module->w->priv;
1255
Dharageswari R260eb732016-06-03 18:29:38 +05301256 if (mconfig->m_state >= SKL_MODULE_INIT_DONE)
1257 skl_tplg_free_pipe_mcps(skl, dst_module);
Vinod Kould93f8e52015-10-07 11:31:54 +01001258 if (src_module == NULL) {
1259 src_module = dst_module;
1260 continue;
1261 }
1262
Guneshwor Singh7ca42f52016-02-03 17:59:46 +05301263 skl_unbind_modules(ctx, src_module, dst_module);
Vinod Kould93f8e52015-10-07 11:31:54 +01001264 src_module = dst_module;
1265 }
1266
Vinod Koul547cafa2016-12-08 23:01:24 +05301267 skl_delete_pipe(ctx, mconfig->pipe);
Vinod Kould93f8e52015-10-07 11:31:54 +01001268
Jeeja KP473a4d52017-03-24 23:10:33 +05301269 list_for_each_entry(w_module, &s_pipe->w_list, node) {
1270 src_module = w_module->w->priv;
1271 src_module->m_state = SKL_MODULE_UNINIT;
1272 }
1273
Dharageswari R6c5768b2015-12-03 23:29:50 +05301274 return skl_tplg_unload_pipe_modules(ctx, s_pipe);
Vinod Kould93f8e52015-10-07 11:31:54 +01001275}
1276
1277/*
1278 * in the Post-PMD event of PGA we need to do following:
1279 * - Free the mcps used
1280 * - Stop the pipeline
1281 * - In source pipe is connected, unbind with source pipelines
1282 */
1283static int skl_tplg_pga_dapm_post_pmd_event(struct snd_soc_dapm_widget *w,
1284 struct skl *skl)
1285{
Vinod Kould93f8e52015-10-07 11:31:54 +01001286 struct skl_module_cfg *src_mconfig, *sink_mconfig;
Jeeja KPce1b5552015-10-27 09:22:51 +09001287 int ret = 0, i;
Vinod Kould93f8e52015-10-07 11:31:54 +01001288 struct skl_sst *ctx = skl->skl_sst;
1289
Jeeja KPce1b5552015-10-27 09:22:51 +09001290 src_mconfig = w->priv;
Vinod Kould93f8e52015-10-07 11:31:54 +01001291
Vinod Kould93f8e52015-10-07 11:31:54 +01001292 /* Stop the pipe since this is a mixin module */
1293 ret = skl_stop_pipe(ctx, src_mconfig->pipe);
1294 if (ret)
1295 return ret;
1296
Ramesh Babuf6fa56e2017-08-23 19:33:53 +05301297 for (i = 0; i < src_mconfig->module->max_output_pins; i++) {
Jeeja KPce1b5552015-10-27 09:22:51 +09001298 if (src_mconfig->m_out_pin[i].pin_state == SKL_PIN_BIND_DONE) {
1299 sink_mconfig = src_mconfig->m_out_pin[i].tgt_mcfg;
1300 if (!sink_mconfig)
1301 continue;
1302 /*
1303 * This is a connecter and if path is found that means
1304 * unbind between source and sink has not happened yet
1305 */
Jeeja KPce1b5552015-10-27 09:22:51 +09001306 ret = skl_unbind_modules(ctx, src_mconfig,
1307 sink_mconfig);
Vinod Kould93f8e52015-10-07 11:31:54 +01001308 }
1309 }
1310
Vinod Kould93f8e52015-10-07 11:31:54 +01001311 return ret;
1312}
1313
1314/*
Vinod Kould93f8e52015-10-07 11:31:54 +01001315 * In modelling, we assume there will be ONLY one mixer in a pipeline. If a
1316 * second one is required that is created as another pipe entity.
1317 * The mixer is responsible for pipe management and represent a pipeline
1318 * instance
1319 */
1320static int skl_tplg_mixer_event(struct snd_soc_dapm_widget *w,
1321 struct snd_kcontrol *k, int event)
1322{
1323 struct snd_soc_dapm_context *dapm = w->dapm;
1324 struct skl *skl = get_skl_ctx(dapm->dev);
1325
1326 switch (event) {
1327 case SND_SOC_DAPM_PRE_PMU:
1328 return skl_tplg_mixer_dapm_pre_pmu_event(w, skl);
1329
1330 case SND_SOC_DAPM_POST_PMU:
1331 return skl_tplg_mixer_dapm_post_pmu_event(w, skl);
1332
1333 case SND_SOC_DAPM_PRE_PMD:
1334 return skl_tplg_mixer_dapm_pre_pmd_event(w, skl);
1335
1336 case SND_SOC_DAPM_POST_PMD:
1337 return skl_tplg_mixer_dapm_post_pmd_event(w, skl);
1338 }
1339
1340 return 0;
1341}
1342
1343/*
1344 * In modelling, we assumed rest of the modules in pipeline are PGA. But we
1345 * are interested in last PGA (leaf PGA) in a pipeline to disconnect with
1346 * the sink when it is running (two FE to one BE or one FE to two BE)
1347 * scenarios
1348 */
1349static int skl_tplg_pga_event(struct snd_soc_dapm_widget *w,
1350 struct snd_kcontrol *k, int event)
1351
1352{
1353 struct snd_soc_dapm_context *dapm = w->dapm;
1354 struct skl *skl = get_skl_ctx(dapm->dev);
1355
1356 switch (event) {
1357 case SND_SOC_DAPM_PRE_PMU:
1358 return skl_tplg_pga_dapm_pre_pmu_event(w, skl);
1359
1360 case SND_SOC_DAPM_POST_PMD:
1361 return skl_tplg_pga_dapm_post_pmd_event(w, skl);
1362 }
1363
1364 return 0;
1365}
Vinod Koulcfb0a872015-10-07 11:31:55 +01001366
Jeeja KP140adfb2015-11-28 15:01:50 +05301367static int skl_tplg_tlv_control_get(struct snd_kcontrol *kcontrol,
1368 unsigned int __user *data, unsigned int size)
1369{
1370 struct soc_bytes_ext *sb =
1371 (struct soc_bytes_ext *)kcontrol->private_value;
1372 struct skl_algo_data *bc = (struct skl_algo_data *)sb->dobj.private;
Omair M Abdullah7d9f2912015-12-03 23:29:56 +05301373 struct snd_soc_dapm_widget *w = snd_soc_dapm_kcontrol_widget(kcontrol);
1374 struct skl_module_cfg *mconfig = w->priv;
1375 struct skl *skl = get_skl_ctx(w->dapm->dev);
1376
1377 if (w->power)
1378 skl_get_module_params(skl->skl_sst, (u32 *)bc->params,
Dharageswari R0d682102016-07-08 18:15:03 +05301379 bc->size, bc->param_id, mconfig);
Jeeja KP140adfb2015-11-28 15:01:50 +05301380
Vinod Koul41556f62016-02-03 17:59:44 +05301381 /* decrement size for TLV header */
1382 size -= 2 * sizeof(u32);
1383
1384 /* check size as we don't want to send kernel data */
1385 if (size > bc->max)
1386 size = bc->max;
1387
Jeeja KP140adfb2015-11-28 15:01:50 +05301388 if (bc->params) {
1389 if (copy_to_user(data, &bc->param_id, sizeof(u32)))
1390 return -EFAULT;
Dan Carpentere8bc3c92015-12-08 08:53:22 +03001391 if (copy_to_user(data + 1, &size, sizeof(u32)))
Jeeja KP140adfb2015-11-28 15:01:50 +05301392 return -EFAULT;
Dan Carpentere8bc3c92015-12-08 08:53:22 +03001393 if (copy_to_user(data + 2, bc->params, size))
Jeeja KP140adfb2015-11-28 15:01:50 +05301394 return -EFAULT;
1395 }
1396
1397 return 0;
1398}
1399
1400#define SKL_PARAM_VENDOR_ID 0xff
1401
1402static int skl_tplg_tlv_control_set(struct snd_kcontrol *kcontrol,
1403 const unsigned int __user *data, unsigned int size)
1404{
1405 struct snd_soc_dapm_widget *w = snd_soc_dapm_kcontrol_widget(kcontrol);
1406 struct skl_module_cfg *mconfig = w->priv;
1407 struct soc_bytes_ext *sb =
1408 (struct soc_bytes_ext *)kcontrol->private_value;
1409 struct skl_algo_data *ac = (struct skl_algo_data *)sb->dobj.private;
1410 struct skl *skl = get_skl_ctx(w->dapm->dev);
1411
1412 if (ac->params) {
Dharageswari R0d682102016-07-08 18:15:03 +05301413 if (size > ac->max)
1414 return -EINVAL;
1415
1416 ac->size = size;
Jeeja KP140adfb2015-11-28 15:01:50 +05301417 /*
1418 * if the param_is is of type Vendor, firmware expects actual
1419 * parameter id and size from the control.
1420 */
1421 if (ac->param_id == SKL_PARAM_VENDOR_ID) {
1422 if (copy_from_user(ac->params, data, size))
1423 return -EFAULT;
1424 } else {
1425 if (copy_from_user(ac->params,
Alan65b4bcb2016-02-19 11:42:32 +05301426 data + 2, size))
Jeeja KP140adfb2015-11-28 15:01:50 +05301427 return -EFAULT;
1428 }
1429
1430 if (w->power)
1431 return skl_set_module_params(skl->skl_sst,
Dharageswari R0d682102016-07-08 18:15:03 +05301432 (u32 *)ac->params, ac->size,
Jeeja KP140adfb2015-11-28 15:01:50 +05301433 ac->param_id, mconfig);
1434 }
1435
1436 return 0;
1437}
1438
Dharageswari R7a1b7492017-05-31 10:30:25 +05301439static int skl_tplg_mic_control_get(struct snd_kcontrol *kcontrol,
1440 struct snd_ctl_elem_value *ucontrol)
1441{
1442 struct snd_soc_dapm_widget *w = snd_soc_dapm_kcontrol_widget(kcontrol);
1443 struct skl_module_cfg *mconfig = w->priv;
1444 struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value;
1445 u32 ch_type = *((u32 *)ec->dobj.private);
1446
1447 if (mconfig->dmic_ch_type == ch_type)
1448 ucontrol->value.enumerated.item[0] =
1449 mconfig->dmic_ch_combo_index;
1450 else
1451 ucontrol->value.enumerated.item[0] = 0;
1452
1453 return 0;
1454}
1455
1456static int skl_fill_mic_sel_params(struct skl_module_cfg *mconfig,
1457 struct skl_mic_sel_config *mic_cfg, struct device *dev)
1458{
1459 struct skl_specific_cfg *sp_cfg = &mconfig->formats_config;
1460
1461 sp_cfg->caps_size = sizeof(struct skl_mic_sel_config);
1462 sp_cfg->set_params = SKL_PARAM_SET;
1463 sp_cfg->param_id = 0x00;
1464 if (!sp_cfg->caps) {
1465 sp_cfg->caps = devm_kzalloc(dev, sp_cfg->caps_size, GFP_KERNEL);
1466 if (!sp_cfg->caps)
1467 return -ENOMEM;
1468 }
1469
1470 mic_cfg->mic_switch = SKL_MIC_SEL_SWITCH;
1471 mic_cfg->flags = 0;
1472 memcpy(sp_cfg->caps, mic_cfg, sp_cfg->caps_size);
1473
1474 return 0;
1475}
1476
1477static int skl_tplg_mic_control_set(struct snd_kcontrol *kcontrol,
1478 struct snd_ctl_elem_value *ucontrol)
1479{
1480 struct snd_soc_dapm_widget *w = snd_soc_dapm_kcontrol_widget(kcontrol);
1481 struct skl_module_cfg *mconfig = w->priv;
1482 struct skl_mic_sel_config mic_cfg = {0};
1483 struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value;
1484 u32 ch_type = *((u32 *)ec->dobj.private);
1485 const int *list;
1486 u8 in_ch, out_ch, index;
1487
1488 mconfig->dmic_ch_type = ch_type;
1489 mconfig->dmic_ch_combo_index = ucontrol->value.enumerated.item[0];
1490
1491 /* enum control index 0 is INVALID, so no channels to be set */
1492 if (mconfig->dmic_ch_combo_index == 0)
1493 return 0;
1494
1495 /* No valid channel selection map for index 0, so offset by 1 */
1496 index = mconfig->dmic_ch_combo_index - 1;
1497
1498 switch (ch_type) {
1499 case SKL_CH_MONO:
1500 if (mconfig->dmic_ch_combo_index > ARRAY_SIZE(mic_mono_list))
1501 return -EINVAL;
1502
1503 list = &mic_mono_list[index];
1504 break;
1505
1506 case SKL_CH_STEREO:
1507 if (mconfig->dmic_ch_combo_index > ARRAY_SIZE(mic_stereo_list))
1508 return -EINVAL;
1509
1510 list = mic_stereo_list[index];
1511 break;
1512
1513 case SKL_CH_TRIO:
1514 if (mconfig->dmic_ch_combo_index > ARRAY_SIZE(mic_trio_list))
1515 return -EINVAL;
1516
1517 list = mic_trio_list[index];
1518 break;
1519
1520 case SKL_CH_QUATRO:
1521 if (mconfig->dmic_ch_combo_index > ARRAY_SIZE(mic_quatro_list))
1522 return -EINVAL;
1523
1524 list = mic_quatro_list[index];
1525 break;
1526
1527 default:
1528 dev_err(w->dapm->dev,
1529 "Invalid channel %d for mic_select module\n",
1530 ch_type);
1531 return -EINVAL;
1532
1533 }
1534
1535 /* channel type enum map to number of chanels for that type */
1536 for (out_ch = 0; out_ch < ch_type; out_ch++) {
1537 in_ch = list[out_ch];
1538 mic_cfg.blob[out_ch][in_ch] = SKL_DEFAULT_MIC_SEL_GAIN;
1539 }
1540
1541 return skl_fill_mic_sel_params(mconfig, &mic_cfg, w->dapm->dev);
1542}
1543
Vinod Koulcfb0a872015-10-07 11:31:55 +01001544/*
Jeeja KP8871dcb2016-06-03 18:29:42 +05301545 * Fill the dma id for host and link. In case of passthrough
1546 * pipeline, this will both host and link in the same
1547 * pipeline, so need to copy the link and host based on dev_type
1548 */
1549static void skl_tplg_fill_dma_id(struct skl_module_cfg *mcfg,
1550 struct skl_pipe_params *params)
1551{
1552 struct skl_pipe *pipe = mcfg->pipe;
1553
1554 if (pipe->passthru) {
1555 switch (mcfg->dev_type) {
1556 case SKL_DEVICE_HDALINK:
1557 pipe->p_params->link_dma_id = params->link_dma_id;
Jeeja KP12c3be02016-12-08 13:41:12 +05301558 pipe->p_params->link_index = params->link_index;
Jeeja KP7f975a32017-03-24 23:10:25 +05301559 pipe->p_params->link_bps = params->link_bps;
Jeeja KP8871dcb2016-06-03 18:29:42 +05301560 break;
1561
1562 case SKL_DEVICE_HDAHOST:
1563 pipe->p_params->host_dma_id = params->host_dma_id;
Jeeja KP7f975a32017-03-24 23:10:25 +05301564 pipe->p_params->host_bps = params->host_bps;
Jeeja KP8871dcb2016-06-03 18:29:42 +05301565 break;
1566
1567 default:
1568 break;
1569 }
1570 pipe->p_params->s_fmt = params->s_fmt;
1571 pipe->p_params->ch = params->ch;
1572 pipe->p_params->s_freq = params->s_freq;
1573 pipe->p_params->stream = params->stream;
Jeeja KP12c3be02016-12-08 13:41:12 +05301574 pipe->p_params->format = params->format;
Jeeja KP8871dcb2016-06-03 18:29:42 +05301575
1576 } else {
1577 memcpy(pipe->p_params, params, sizeof(*params));
1578 }
1579}
1580
1581/*
Vinod Koulcfb0a872015-10-07 11:31:55 +01001582 * The FE params are passed by hw_params of the DAI.
1583 * On hw_params, the params are stored in Gateway module of the FE and we
1584 * need to calculate the format in DSP module configuration, that
1585 * conversion is done here
1586 */
1587int skl_tplg_update_pipe_params(struct device *dev,
1588 struct skl_module_cfg *mconfig,
1589 struct skl_pipe_params *params)
1590{
Ramesh Babuf6fa56e2017-08-23 19:33:53 +05301591 struct skl_module_res *res = &mconfig->module->resources[0];
1592 struct skl *skl = get_skl_ctx(dev);
Vinod Koulcfb0a872015-10-07 11:31:55 +01001593 struct skl_module_fmt *format = NULL;
Ramesh Babuf6fa56e2017-08-23 19:33:53 +05301594 u8 cfg_idx = mconfig->pipe->cur_config_idx;
Vinod Koulcfb0a872015-10-07 11:31:55 +01001595
Jeeja KP8871dcb2016-06-03 18:29:42 +05301596 skl_tplg_fill_dma_id(mconfig, params);
Ramesh Babuf6fa56e2017-08-23 19:33:53 +05301597 mconfig->fmt_idx = mconfig->mod_cfg[cfg_idx].fmt_idx;
1598 mconfig->res_idx = mconfig->mod_cfg[cfg_idx].res_idx;
1599
1600 if (skl->nr_modules)
1601 return 0;
Vinod Koulcfb0a872015-10-07 11:31:55 +01001602
1603 if (params->stream == SNDRV_PCM_STREAM_PLAYBACK)
Ramesh Babuf6fa56e2017-08-23 19:33:53 +05301604 format = &mconfig->module->formats[0].inputs[0].fmt;
Vinod Koulcfb0a872015-10-07 11:31:55 +01001605 else
Ramesh Babuf6fa56e2017-08-23 19:33:53 +05301606 format = &mconfig->module->formats[0].outputs[0].fmt;
Vinod Koulcfb0a872015-10-07 11:31:55 +01001607
1608 /* set the hw_params */
1609 format->s_freq = params->s_freq;
1610 format->channels = params->ch;
1611 format->valid_bit_depth = skl_get_bit_depth(params->s_fmt);
1612
1613 /*
1614 * 16 bit is 16 bit container whereas 24 bit is in 32 bit
1615 * container so update bit depth accordingly
1616 */
1617 switch (format->valid_bit_depth) {
1618 case SKL_DEPTH_16BIT:
1619 format->bit_depth = format->valid_bit_depth;
1620 break;
1621
1622 case SKL_DEPTH_24BIT:
Jeeja KP6654f392015-10-27 09:22:46 +09001623 case SKL_DEPTH_32BIT:
Vinod Koulcfb0a872015-10-07 11:31:55 +01001624 format->bit_depth = SKL_DEPTH_32BIT;
1625 break;
1626
1627 default:
1628 dev_err(dev, "Invalid bit depth %x for pipe\n",
1629 format->valid_bit_depth);
1630 return -EINVAL;
1631 }
1632
1633 if (params->stream == SNDRV_PCM_STREAM_PLAYBACK) {
Ramesh Babuf6fa56e2017-08-23 19:33:53 +05301634 res->ibs = (format->s_freq / 1000) *
Vinod Koulcfb0a872015-10-07 11:31:55 +01001635 (format->channels) *
1636 (format->bit_depth >> 3);
1637 } else {
Ramesh Babuf6fa56e2017-08-23 19:33:53 +05301638 res->obs = (format->s_freq / 1000) *
Vinod Koulcfb0a872015-10-07 11:31:55 +01001639 (format->channels) *
1640 (format->bit_depth >> 3);
1641 }
1642
1643 return 0;
1644}
1645
1646/*
1647 * Query the module config for the FE DAI
1648 * This is used to find the hw_params set for that DAI and apply to FE
1649 * pipeline
1650 */
1651struct skl_module_cfg *
1652skl_tplg_fe_get_cpr_module(struct snd_soc_dai *dai, int stream)
1653{
1654 struct snd_soc_dapm_widget *w;
1655 struct snd_soc_dapm_path *p = NULL;
1656
1657 if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
1658 w = dai->playback_widget;
Subhransu S. Prustyf0900eb2015-10-22 23:22:36 +05301659 snd_soc_dapm_widget_for_each_sink_path(w, p) {
Vinod Koulcfb0a872015-10-07 11:31:55 +01001660 if (p->connect && p->sink->power &&
Guneshwor Singhcb1f9042018-01-27 09:50:21 +05301661 !is_skl_dsp_widget_type(p->sink, dai->dev))
Vinod Koulcfb0a872015-10-07 11:31:55 +01001662 continue;
1663
1664 if (p->sink->priv) {
1665 dev_dbg(dai->dev, "set params for %s\n",
1666 p->sink->name);
1667 return p->sink->priv;
1668 }
1669 }
1670 } else {
1671 w = dai->capture_widget;
Subhransu S. Prustyf0900eb2015-10-22 23:22:36 +05301672 snd_soc_dapm_widget_for_each_source_path(w, p) {
Vinod Koulcfb0a872015-10-07 11:31:55 +01001673 if (p->connect && p->source->power &&
Guneshwor Singhcb1f9042018-01-27 09:50:21 +05301674 !is_skl_dsp_widget_type(p->source, dai->dev))
Vinod Koulcfb0a872015-10-07 11:31:55 +01001675 continue;
1676
1677 if (p->source->priv) {
1678 dev_dbg(dai->dev, "set params for %s\n",
1679 p->source->name);
1680 return p->source->priv;
1681 }
1682 }
1683 }
1684
1685 return NULL;
1686}
1687
Dharageswari.R718a42b2016-02-05 12:19:06 +05301688static struct skl_module_cfg *skl_get_mconfig_pb_cpr(
1689 struct snd_soc_dai *dai, struct snd_soc_dapm_widget *w)
1690{
1691 struct snd_soc_dapm_path *p;
1692 struct skl_module_cfg *mconfig = NULL;
1693
1694 snd_soc_dapm_widget_for_each_source_path(w, p) {
1695 if (w->endpoints[SND_SOC_DAPM_DIR_OUT] > 0) {
1696 if (p->connect &&
1697 (p->sink->id == snd_soc_dapm_aif_out) &&
1698 p->source->priv) {
1699 mconfig = p->source->priv;
1700 return mconfig;
1701 }
1702 mconfig = skl_get_mconfig_pb_cpr(dai, p->source);
1703 if (mconfig)
1704 return mconfig;
1705 }
1706 }
1707 return mconfig;
1708}
1709
1710static struct skl_module_cfg *skl_get_mconfig_cap_cpr(
1711 struct snd_soc_dai *dai, struct snd_soc_dapm_widget *w)
1712{
1713 struct snd_soc_dapm_path *p;
1714 struct skl_module_cfg *mconfig = NULL;
1715
1716 snd_soc_dapm_widget_for_each_sink_path(w, p) {
1717 if (w->endpoints[SND_SOC_DAPM_DIR_IN] > 0) {
1718 if (p->connect &&
1719 (p->source->id == snd_soc_dapm_aif_in) &&
1720 p->sink->priv) {
1721 mconfig = p->sink->priv;
1722 return mconfig;
1723 }
1724 mconfig = skl_get_mconfig_cap_cpr(dai, p->sink);
1725 if (mconfig)
1726 return mconfig;
1727 }
1728 }
1729 return mconfig;
1730}
1731
1732struct skl_module_cfg *
1733skl_tplg_be_get_cpr_module(struct snd_soc_dai *dai, int stream)
1734{
1735 struct snd_soc_dapm_widget *w;
1736 struct skl_module_cfg *mconfig;
1737
1738 if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
1739 w = dai->playback_widget;
1740 mconfig = skl_get_mconfig_pb_cpr(dai, w);
1741 } else {
1742 w = dai->capture_widget;
1743 mconfig = skl_get_mconfig_cap_cpr(dai, w);
1744 }
1745 return mconfig;
1746}
1747
Vinod Koulcfb0a872015-10-07 11:31:55 +01001748static u8 skl_tplg_be_link_type(int dev_type)
1749{
1750 int ret;
1751
1752 switch (dev_type) {
1753 case SKL_DEVICE_BT:
1754 ret = NHLT_LINK_SSP;
1755 break;
1756
1757 case SKL_DEVICE_DMIC:
1758 ret = NHLT_LINK_DMIC;
1759 break;
1760
1761 case SKL_DEVICE_I2S:
1762 ret = NHLT_LINK_SSP;
1763 break;
1764
1765 case SKL_DEVICE_HDALINK:
1766 ret = NHLT_LINK_HDA;
1767 break;
1768
1769 default:
1770 ret = NHLT_LINK_INVALID;
1771 break;
1772 }
1773
1774 return ret;
1775}
1776
1777/*
1778 * Fill the BE gateway parameters
1779 * The BE gateway expects a blob of parameters which are kept in the ACPI
1780 * NHLT blob, so query the blob for interface type (i2s/pdm) and instance.
1781 * The port can have multiple settings so pick based on the PCM
1782 * parameters
1783 */
1784static int skl_tplg_be_fill_pipe_params(struct snd_soc_dai *dai,
1785 struct skl_module_cfg *mconfig,
1786 struct skl_pipe_params *params)
1787{
Vinod Koulcfb0a872015-10-07 11:31:55 +01001788 struct nhlt_specific_cfg *cfg;
1789 struct skl *skl = get_skl_ctx(dai->dev);
1790 int link_type = skl_tplg_be_link_type(mconfig->dev_type);
Senthilnathan Veppurdb2f5862017-02-09 16:44:01 +05301791 u8 dev_type = skl_tplg_be_dev_type(mconfig->dev_type);
Vinod Koulcfb0a872015-10-07 11:31:55 +01001792
Jeeja KP8871dcb2016-06-03 18:29:42 +05301793 skl_tplg_fill_dma_id(mconfig, params);
Vinod Koulcfb0a872015-10-07 11:31:55 +01001794
Jeeja KPb30c2752015-10-27 09:22:48 +09001795 if (link_type == NHLT_LINK_HDA)
1796 return 0;
1797
Vinod Koulcfb0a872015-10-07 11:31:55 +01001798 /* update the blob based on virtual bus_id*/
1799 cfg = skl_get_ep_blob(skl, mconfig->vbus_id, link_type,
1800 params->s_fmt, params->ch,
Senthilnathan Veppurdb2f5862017-02-09 16:44:01 +05301801 params->s_freq, params->stream,
1802 dev_type);
Vinod Koulcfb0a872015-10-07 11:31:55 +01001803 if (cfg) {
1804 mconfig->formats_config.caps_size = cfg->size;
Jeeja KPbc032812015-10-22 23:22:35 +05301805 mconfig->formats_config.caps = (u32 *) &cfg->caps;
Vinod Koulcfb0a872015-10-07 11:31:55 +01001806 } else {
1807 dev_err(dai->dev, "Blob NULL for id %x type %d dirn %d\n",
1808 mconfig->vbus_id, link_type,
1809 params->stream);
1810 dev_err(dai->dev, "PCM: ch %d, freq %d, fmt %d\n",
1811 params->ch, params->s_freq, params->s_fmt);
1812 return -EINVAL;
1813 }
1814
1815 return 0;
1816}
1817
1818static int skl_tplg_be_set_src_pipe_params(struct snd_soc_dai *dai,
1819 struct snd_soc_dapm_widget *w,
1820 struct skl_pipe_params *params)
1821{
1822 struct snd_soc_dapm_path *p;
Subhransu S. Prusty4d8adccb2015-10-22 23:22:37 +05301823 int ret = -EIO;
Vinod Koulcfb0a872015-10-07 11:31:55 +01001824
Subhransu S. Prustyf0900eb2015-10-22 23:22:36 +05301825 snd_soc_dapm_widget_for_each_source_path(w, p) {
Guneshwor Singhcb1f9042018-01-27 09:50:21 +05301826 if (p->connect && is_skl_dsp_widget_type(p->source, dai->dev) &&
Vinod Koulcfb0a872015-10-07 11:31:55 +01001827 p->source->priv) {
1828
Jeeja KP9a03cb42015-10-27 09:22:54 +09001829 ret = skl_tplg_be_fill_pipe_params(dai,
1830 p->source->priv, params);
1831 if (ret < 0)
1832 return ret;
Vinod Koulcfb0a872015-10-07 11:31:55 +01001833 } else {
Jeeja KP9a03cb42015-10-27 09:22:54 +09001834 ret = skl_tplg_be_set_src_pipe_params(dai,
1835 p->source, params);
Subhransu S. Prusty4d8adccb2015-10-22 23:22:37 +05301836 if (ret < 0)
1837 return ret;
Vinod Koulcfb0a872015-10-07 11:31:55 +01001838 }
1839 }
1840
Subhransu S. Prusty4d8adccb2015-10-22 23:22:37 +05301841 return ret;
Vinod Koulcfb0a872015-10-07 11:31:55 +01001842}
1843
1844static int skl_tplg_be_set_sink_pipe_params(struct snd_soc_dai *dai,
1845 struct snd_soc_dapm_widget *w, struct skl_pipe_params *params)
1846{
1847 struct snd_soc_dapm_path *p = NULL;
Subhransu S. Prusty4d8adccb2015-10-22 23:22:37 +05301848 int ret = -EIO;
Vinod Koulcfb0a872015-10-07 11:31:55 +01001849
Subhransu S. Prustyf0900eb2015-10-22 23:22:36 +05301850 snd_soc_dapm_widget_for_each_sink_path(w, p) {
Guneshwor Singhcb1f9042018-01-27 09:50:21 +05301851 if (p->connect && is_skl_dsp_widget_type(p->sink, dai->dev) &&
Vinod Koulcfb0a872015-10-07 11:31:55 +01001852 p->sink->priv) {
1853
Jeeja KP9a03cb42015-10-27 09:22:54 +09001854 ret = skl_tplg_be_fill_pipe_params(dai,
1855 p->sink->priv, params);
1856 if (ret < 0)
1857 return ret;
Vinod Koulcfb0a872015-10-07 11:31:55 +01001858 } else {
Subhransu S. Prusty4d8adccb2015-10-22 23:22:37 +05301859 ret = skl_tplg_be_set_sink_pipe_params(
Vinod Koulcfb0a872015-10-07 11:31:55 +01001860 dai, p->sink, params);
Subhransu S. Prusty4d8adccb2015-10-22 23:22:37 +05301861 if (ret < 0)
1862 return ret;
Vinod Koulcfb0a872015-10-07 11:31:55 +01001863 }
1864 }
1865
Subhransu S. Prusty4d8adccb2015-10-22 23:22:37 +05301866 return ret;
Vinod Koulcfb0a872015-10-07 11:31:55 +01001867}
1868
1869/*
1870 * BE hw_params can be a source parameters (capture) or sink parameters
1871 * (playback). Based on sink and source we need to either find the source
1872 * list or the sink list and set the pipeline parameters
1873 */
1874int skl_tplg_be_update_params(struct snd_soc_dai *dai,
1875 struct skl_pipe_params *params)
1876{
1877 struct snd_soc_dapm_widget *w;
1878
1879 if (params->stream == SNDRV_PCM_STREAM_PLAYBACK) {
1880 w = dai->playback_widget;
1881
1882 return skl_tplg_be_set_src_pipe_params(dai, w, params);
1883
1884 } else {
1885 w = dai->capture_widget;
1886
1887 return skl_tplg_be_set_sink_pipe_params(dai, w, params);
1888 }
1889
1890 return 0;
1891}
Vinod Koul3af36702015-10-07 11:31:56 +01001892
1893static const struct snd_soc_tplg_widget_events skl_tplg_widget_ops[] = {
1894 {SKL_MIXER_EVENT, skl_tplg_mixer_event},
Vinod Koul9a1e3502017-03-24 23:10:29 +05301895 {SKL_VMIXER_EVENT, skl_tplg_mixer_event},
Vinod Koul3af36702015-10-07 11:31:56 +01001896 {SKL_PGA_EVENT, skl_tplg_pga_event},
1897};
1898
Jeeja KP140adfb2015-11-28 15:01:50 +05301899static const struct snd_soc_tplg_bytes_ext_ops skl_tlv_ops[] = {
1900 {SKL_CONTROL_TYPE_BYTE_TLV, skl_tplg_tlv_control_get,
1901 skl_tplg_tlv_control_set},
1902};
1903
Dharageswari R7a1b7492017-05-31 10:30:25 +05301904static const struct snd_soc_tplg_kcontrol_ops skl_tplg_kcontrol_ops[] = {
1905 {
1906 .id = SKL_CONTROL_TYPE_MIC_SELECT,
1907 .get = skl_tplg_mic_control_get,
1908 .put = skl_tplg_mic_control_set,
1909 },
1910};
1911
Ramesh Babuf6fa56e2017-08-23 19:33:53 +05301912static int skl_tplg_fill_pipe_cfg(struct device *dev,
1913 struct skl_pipe *pipe, u32 tkn,
1914 u32 tkn_val, int conf_idx, int dir)
1915{
1916 struct skl_pipe_fmt *fmt;
1917 struct skl_path_config *config;
1918
1919 switch (dir) {
1920 case SKL_DIR_IN:
1921 fmt = &pipe->configs[conf_idx].in_fmt;
1922 break;
1923
1924 case SKL_DIR_OUT:
1925 fmt = &pipe->configs[conf_idx].out_fmt;
1926 break;
1927
1928 default:
1929 dev_err(dev, "Invalid direction: %d\n", dir);
1930 return -EINVAL;
1931 }
1932
1933 config = &pipe->configs[conf_idx];
1934
1935 switch (tkn) {
1936 case SKL_TKN_U32_CFG_FREQ:
1937 fmt->freq = tkn_val;
1938 break;
1939
1940 case SKL_TKN_U8_CFG_CHAN:
1941 fmt->channels = tkn_val;
1942 break;
1943
1944 case SKL_TKN_U8_CFG_BPS:
1945 fmt->bps = tkn_val;
1946 break;
1947
1948 case SKL_TKN_U32_PATH_MEM_PGS:
1949 config->mem_pages = tkn_val;
1950 break;
1951
1952 default:
1953 dev_err(dev, "Invalid token config: %d\n", tkn);
1954 return -EINVAL;
1955 }
1956
1957 return 0;
1958}
1959
Shreyas NC6277e832016-08-12 12:29:51 +05301960static int skl_tplg_fill_pipe_tkn(struct device *dev,
1961 struct skl_pipe *pipe, u32 tkn,
1962 u32 tkn_val)
Vinod Koul3af36702015-10-07 11:31:56 +01001963{
Vinod Koul3af36702015-10-07 11:31:56 +01001964
Shreyas NC6277e832016-08-12 12:29:51 +05301965 switch (tkn) {
1966 case SKL_TKN_U32_PIPE_CONN_TYPE:
1967 pipe->conn_type = tkn_val;
1968 break;
1969
1970 case SKL_TKN_U32_PIPE_PRIORITY:
1971 pipe->pipe_priority = tkn_val;
1972 break;
1973
1974 case SKL_TKN_U32_PIPE_MEM_PGS:
1975 pipe->memory_pages = tkn_val;
1976 break;
1977
Vinod Koul8a0cb232016-11-03 17:07:18 +05301978 case SKL_TKN_U32_PMODE:
1979 pipe->lp_mode = tkn_val;
1980 break;
1981
Ramesh Babuf6fa56e2017-08-23 19:33:53 +05301982 case SKL_TKN_U32_PIPE_DIRECTION:
1983 pipe->direction = tkn_val;
1984 break;
1985
1986 case SKL_TKN_U32_NUM_CONFIGS:
1987 pipe->nr_cfgs = tkn_val;
1988 break;
1989
Shreyas NC6277e832016-08-12 12:29:51 +05301990 default:
1991 dev_err(dev, "Token not handled %d\n", tkn);
1992 return -EINVAL;
Vinod Koul3af36702015-10-07 11:31:56 +01001993 }
Shreyas NC6277e832016-08-12 12:29:51 +05301994
1995 return 0;
Vinod Koul3af36702015-10-07 11:31:56 +01001996}
1997
1998/*
Shreyas NC6277e832016-08-12 12:29:51 +05301999 * Add pipeline by parsing the relevant tokens
2000 * Return an existing pipe if the pipe already exists.
Vinod Koul3af36702015-10-07 11:31:56 +01002001 */
Shreyas NC6277e832016-08-12 12:29:51 +05302002static int skl_tplg_add_pipe(struct device *dev,
2003 struct skl_module_cfg *mconfig, struct skl *skl,
2004 struct snd_soc_tplg_vendor_value_elem *tkn_elem)
Vinod Koul3af36702015-10-07 11:31:56 +01002005{
2006 struct skl_pipeline *ppl;
2007 struct skl_pipe *pipe;
2008 struct skl_pipe_params *params;
2009
2010 list_for_each_entry(ppl, &skl->ppl_list, node) {
Shreyas NC6277e832016-08-12 12:29:51 +05302011 if (ppl->pipe->ppl_id == tkn_elem->value) {
2012 mconfig->pipe = ppl->pipe;
Guneshwor Singh081dc8a2017-04-27 12:21:22 +05302013 return -EEXIST;
Shreyas NC6277e832016-08-12 12:29:51 +05302014 }
Vinod Koul3af36702015-10-07 11:31:56 +01002015 }
2016
2017 ppl = devm_kzalloc(dev, sizeof(*ppl), GFP_KERNEL);
2018 if (!ppl)
Shreyas NC6277e832016-08-12 12:29:51 +05302019 return -ENOMEM;
Vinod Koul3af36702015-10-07 11:31:56 +01002020
2021 pipe = devm_kzalloc(dev, sizeof(*pipe), GFP_KERNEL);
2022 if (!pipe)
Shreyas NC6277e832016-08-12 12:29:51 +05302023 return -ENOMEM;
Vinod Koul3af36702015-10-07 11:31:56 +01002024
2025 params = devm_kzalloc(dev, sizeof(*params), GFP_KERNEL);
2026 if (!params)
Shreyas NC6277e832016-08-12 12:29:51 +05302027 return -ENOMEM;
Vinod Koul3af36702015-10-07 11:31:56 +01002028
Vinod Koul3af36702015-10-07 11:31:56 +01002029 pipe->p_params = params;
Shreyas NC6277e832016-08-12 12:29:51 +05302030 pipe->ppl_id = tkn_elem->value;
Vinod Koul3af36702015-10-07 11:31:56 +01002031 INIT_LIST_HEAD(&pipe->w_list);
2032
2033 ppl->pipe = pipe;
2034 list_add(&ppl->node, &skl->ppl_list);
2035
Shreyas NC6277e832016-08-12 12:29:51 +05302036 mconfig->pipe = pipe;
2037 mconfig->pipe->state = SKL_PIPE_INVALID;
2038
2039 return 0;
Vinod Koul3af36702015-10-07 11:31:56 +01002040}
2041
Sriram Periyasamy22ebd662017-11-07 16:16:22 +05302042static int skl_tplg_get_uuid(struct device *dev, u8 *guid,
2043 struct snd_soc_tplg_vendor_uuid_elem *uuid_tkn)
Shreyas NC6277e832016-08-12 12:29:51 +05302044{
Sriram Periyasamy22ebd662017-11-07 16:16:22 +05302045 if (uuid_tkn->token == SKL_TKN_UUID) {
2046 memcpy(guid, &uuid_tkn->uuid, 16);
2047 return 0;
2048 }
2049
2050 dev_err(dev, "Not an UUID token %d\n", uuid_tkn->token);
2051
2052 return -EINVAL;
2053}
2054
2055static int skl_tplg_fill_pin(struct device *dev,
2056 struct snd_soc_tplg_vendor_value_elem *tkn_elem,
2057 struct skl_module_pin *m_pin,
2058 int pin_index)
2059{
Sriram Periyasamyd9561472017-11-07 16:16:23 +05302060 int ret;
2061
Sriram Periyasamy22ebd662017-11-07 16:16:22 +05302062 switch (tkn_elem->token) {
Shreyas NC6277e832016-08-12 12:29:51 +05302063 case SKL_TKN_U32_PIN_MOD_ID:
Sriram Periyasamy22ebd662017-11-07 16:16:22 +05302064 m_pin[pin_index].id.module_id = tkn_elem->value;
Shreyas NC6277e832016-08-12 12:29:51 +05302065 break;
2066
2067 case SKL_TKN_U32_PIN_INST_ID:
Sriram Periyasamy22ebd662017-11-07 16:16:22 +05302068 m_pin[pin_index].id.instance_id = tkn_elem->value;
Shreyas NC6277e832016-08-12 12:29:51 +05302069 break;
2070
Sriram Periyasamyd9561472017-11-07 16:16:23 +05302071 case SKL_TKN_UUID:
2072 ret = skl_tplg_get_uuid(dev, m_pin[pin_index].id.mod_uuid.b,
2073 (struct snd_soc_tplg_vendor_uuid_elem *)tkn_elem);
2074 if (ret < 0)
2075 return ret;
2076
Shreyas NC6277e832016-08-12 12:29:51 +05302077 break;
2078
2079 default:
Sriram Periyasamy22ebd662017-11-07 16:16:22 +05302080 dev_err(dev, "%d Not a pin token\n", tkn_elem->token);
Shreyas NC6277e832016-08-12 12:29:51 +05302081 return -EINVAL;
2082 }
2083
2084 return 0;
2085}
2086
2087/*
2088 * Parse for pin config specific tokens to fill up the
2089 * module private data
2090 */
2091static int skl_tplg_fill_pins_info(struct device *dev,
2092 struct skl_module_cfg *mconfig,
2093 struct snd_soc_tplg_vendor_value_elem *tkn_elem,
2094 int dir, int pin_count)
2095{
2096 int ret;
2097 struct skl_module_pin *m_pin;
2098
2099 switch (dir) {
2100 case SKL_DIR_IN:
2101 m_pin = mconfig->m_in_pin;
2102 break;
2103
2104 case SKL_DIR_OUT:
2105 m_pin = mconfig->m_out_pin;
2106 break;
2107
2108 default:
Colin Ian Kingecd286a2016-09-16 18:51:21 +01002109 dev_err(dev, "Invalid direction value\n");
Shreyas NC6277e832016-08-12 12:29:51 +05302110 return -EINVAL;
2111 }
2112
Sriram Periyasamy22ebd662017-11-07 16:16:22 +05302113 ret = skl_tplg_fill_pin(dev, tkn_elem, m_pin, pin_count);
Shreyas NC6277e832016-08-12 12:29:51 +05302114 if (ret < 0)
2115 return ret;
2116
2117 m_pin[pin_count].in_use = false;
2118 m_pin[pin_count].pin_state = SKL_PIN_UNBIND;
2119
2120 return 0;
2121}
2122
2123/*
2124 * Fill up input/output module config format based
2125 * on the direction
2126 */
2127static int skl_tplg_fill_fmt(struct device *dev,
Shreyas NCca312fd2017-08-23 19:33:50 +05302128 struct skl_module_fmt *dst_fmt,
2129 u32 tkn, u32 value)
Shreyas NC6277e832016-08-12 12:29:51 +05302130{
Shreyas NC6277e832016-08-12 12:29:51 +05302131 switch (tkn) {
2132 case SKL_TKN_U32_FMT_CH:
2133 dst_fmt->channels = value;
2134 break;
2135
2136 case SKL_TKN_U32_FMT_FREQ:
2137 dst_fmt->s_freq = value;
2138 break;
2139
2140 case SKL_TKN_U32_FMT_BIT_DEPTH:
2141 dst_fmt->bit_depth = value;
2142 break;
2143
2144 case SKL_TKN_U32_FMT_SAMPLE_SIZE:
2145 dst_fmt->valid_bit_depth = value;
2146 break;
2147
2148 case SKL_TKN_U32_FMT_CH_CONFIG:
2149 dst_fmt->ch_cfg = value;
2150 break;
2151
2152 case SKL_TKN_U32_FMT_INTERLEAVE:
2153 dst_fmt->interleaving_style = value;
2154 break;
2155
2156 case SKL_TKN_U32_FMT_SAMPLE_TYPE:
2157 dst_fmt->sample_type = value;
2158 break;
2159
2160 case SKL_TKN_U32_FMT_CH_MAP:
2161 dst_fmt->ch_map = value;
2162 break;
2163
2164 default:
Colin Ian Kingecd286a2016-09-16 18:51:21 +01002165 dev_err(dev, "Invalid token %d\n", tkn);
Shreyas NC6277e832016-08-12 12:29:51 +05302166 return -EINVAL;
2167 }
2168
2169 return 0;
2170}
2171
Shreyas NCca312fd2017-08-23 19:33:50 +05302172static int skl_tplg_widget_fill_fmt(struct device *dev,
Ramesh Babuf6fa56e2017-08-23 19:33:53 +05302173 struct skl_module_iface *fmt,
Shreyas NCca312fd2017-08-23 19:33:50 +05302174 u32 tkn, u32 val, u32 dir, int fmt_idx)
2175{
2176 struct skl_module_fmt *dst_fmt;
2177
Ramesh Babuf6fa56e2017-08-23 19:33:53 +05302178 if (!fmt)
2179 return -EINVAL;
2180
Shreyas NCca312fd2017-08-23 19:33:50 +05302181 switch (dir) {
2182 case SKL_DIR_IN:
Ramesh Babuf6fa56e2017-08-23 19:33:53 +05302183 dst_fmt = &fmt->inputs[fmt_idx].fmt;
Shreyas NCca312fd2017-08-23 19:33:50 +05302184 break;
2185
2186 case SKL_DIR_OUT:
Ramesh Babuf6fa56e2017-08-23 19:33:53 +05302187 dst_fmt = &fmt->outputs[fmt_idx].fmt;
Shreyas NCca312fd2017-08-23 19:33:50 +05302188 break;
2189
2190 default:
2191 dev_err(dev, "Invalid direction: %d\n", dir);
2192 return -EINVAL;
2193 }
2194
2195 return skl_tplg_fill_fmt(dev, dst_fmt, tkn, val);
2196}
2197
Shreyas NC6277e832016-08-12 12:29:51 +05302198static void skl_tplg_fill_pin_dynamic_val(
2199 struct skl_module_pin *mpin, u32 pin_count, u32 value)
Hardik T Shah4cd98992015-10-27 09:22:55 +09002200{
2201 int i;
2202
Shreyas NC6277e832016-08-12 12:29:51 +05302203 for (i = 0; i < pin_count; i++)
2204 mpin[i].is_dynamic = value;
2205}
2206
2207/*
Shreyas NCdb6ed552017-08-23 19:33:52 +05302208 * Resource table in the manifest has pin specific resources
2209 * like pin and pin buffer size
2210 */
2211static int skl_tplg_manifest_pin_res_tkn(struct device *dev,
2212 struct snd_soc_tplg_vendor_value_elem *tkn_elem,
2213 struct skl_module_res *res, int pin_idx, int dir)
2214{
2215 struct skl_module_pin_resources *m_pin;
2216
2217 switch (dir) {
2218 case SKL_DIR_IN:
2219 m_pin = &res->input[pin_idx];
2220 break;
2221
2222 case SKL_DIR_OUT:
2223 m_pin = &res->output[pin_idx];
2224 break;
2225
2226 default:
2227 dev_err(dev, "Invalid pin direction: %d\n", dir);
2228 return -EINVAL;
2229 }
2230
2231 switch (tkn_elem->token) {
2232 case SKL_TKN_MM_U32_RES_PIN_ID:
2233 m_pin->pin_index = tkn_elem->value;
2234 break;
2235
2236 case SKL_TKN_MM_U32_PIN_BUF:
2237 m_pin->buf_size = tkn_elem->value;
2238 break;
2239
2240 default:
2241 dev_err(dev, "Invalid token: %d\n", tkn_elem->token);
2242 return -EINVAL;
2243 }
2244
2245 return 0;
2246}
2247
2248/*
2249 * Fill module specific resources from the manifest's resource
2250 * table like CPS, DMA size, mem_pages.
2251 */
2252static int skl_tplg_fill_res_tkn(struct device *dev,
2253 struct snd_soc_tplg_vendor_value_elem *tkn_elem,
2254 struct skl_module_res *res,
2255 int pin_idx, int dir)
2256{
2257 int ret, tkn_count = 0;
2258
2259 if (!res)
2260 return -EINVAL;
2261
2262 switch (tkn_elem->token) {
2263 case SKL_TKN_MM_U32_CPS:
2264 res->cps = tkn_elem->value;
2265 break;
2266
2267 case SKL_TKN_MM_U32_DMA_SIZE:
2268 res->dma_buffer_size = tkn_elem->value;
2269 break;
2270
2271 case SKL_TKN_MM_U32_CPC:
2272 res->cpc = tkn_elem->value;
2273 break;
2274
2275 case SKL_TKN_U32_MEM_PAGES:
2276 res->is_pages = tkn_elem->value;
2277 break;
2278
2279 case SKL_TKN_U32_OBS:
2280 res->obs = tkn_elem->value;
2281 break;
2282
2283 case SKL_TKN_U32_IBS:
2284 res->ibs = tkn_elem->value;
2285 break;
2286
Ramesh Babuf6fa56e2017-08-23 19:33:53 +05302287 case SKL_TKN_U32_MAX_MCPS:
2288 res->cps = tkn_elem->value;
2289 break;
2290
Shreyas NCdb6ed552017-08-23 19:33:52 +05302291 case SKL_TKN_MM_U32_RES_PIN_ID:
2292 case SKL_TKN_MM_U32_PIN_BUF:
2293 ret = skl_tplg_manifest_pin_res_tkn(dev, tkn_elem, res,
2294 pin_idx, dir);
2295 if (ret < 0)
2296 return ret;
2297 break;
2298
2299 default:
2300 dev_err(dev, "Not a res type token: %d", tkn_elem->token);
2301 return -EINVAL;
2302
2303 }
2304 tkn_count++;
2305
2306 return tkn_count;
2307}
2308
2309/*
Shreyas NC6277e832016-08-12 12:29:51 +05302310 * Parse tokens to fill up the module private data
2311 */
2312static int skl_tplg_get_token(struct device *dev,
2313 struct snd_soc_tplg_vendor_value_elem *tkn_elem,
2314 struct skl *skl, struct skl_module_cfg *mconfig)
2315{
2316 int tkn_count = 0;
2317 int ret;
2318 static int is_pipe_exists;
Ramesh Babuf6fa56e2017-08-23 19:33:53 +05302319 static int pin_index, dir, conf_idx;
2320 struct skl_module_iface *iface = NULL;
2321 struct skl_module_res *res = NULL;
2322 int res_idx = mconfig->res_idx;
2323 int fmt_idx = mconfig->fmt_idx;
2324
2325 /*
2326 * If the manifest structure contains no modules, fill all
2327 * the module data to 0th index.
2328 * res_idx and fmt_idx are default set to 0.
2329 */
2330 if (skl->nr_modules == 0) {
2331 res = &mconfig->module->resources[res_idx];
2332 iface = &mconfig->module->formats[fmt_idx];
2333 }
Shreyas NC6277e832016-08-12 12:29:51 +05302334
2335 if (tkn_elem->token > SKL_TKN_MAX)
2336 return -EINVAL;
2337
2338 switch (tkn_elem->token) {
2339 case SKL_TKN_U8_IN_QUEUE_COUNT:
Ramesh Babuf6fa56e2017-08-23 19:33:53 +05302340 mconfig->module->max_input_pins = tkn_elem->value;
Shreyas NC6277e832016-08-12 12:29:51 +05302341 break;
2342
2343 case SKL_TKN_U8_OUT_QUEUE_COUNT:
Ramesh Babuf6fa56e2017-08-23 19:33:53 +05302344 mconfig->module->max_output_pins = tkn_elem->value;
Shreyas NC6277e832016-08-12 12:29:51 +05302345 break;
2346
2347 case SKL_TKN_U8_DYN_IN_PIN:
2348 if (!mconfig->m_in_pin)
Ramesh Babuf6fa56e2017-08-23 19:33:53 +05302349 mconfig->m_in_pin = devm_kzalloc(dev, MAX_IN_QUEUE *
2350 sizeof(*mconfig->m_in_pin), GFP_KERNEL);
2351 if (!mconfig->m_in_pin)
Shreyas NC6277e832016-08-12 12:29:51 +05302352 return -ENOMEM;
2353
Ramesh Babuf6fa56e2017-08-23 19:33:53 +05302354 skl_tplg_fill_pin_dynamic_val(mconfig->m_in_pin, MAX_IN_QUEUE,
2355 tkn_elem->value);
Shreyas NC6277e832016-08-12 12:29:51 +05302356 break;
2357
2358 case SKL_TKN_U8_DYN_OUT_PIN:
2359 if (!mconfig->m_out_pin)
Ramesh Babuf6fa56e2017-08-23 19:33:53 +05302360 mconfig->m_out_pin = devm_kzalloc(dev, MAX_IN_QUEUE *
2361 sizeof(*mconfig->m_in_pin), GFP_KERNEL);
2362 if (!mconfig->m_out_pin)
Shreyas NC6277e832016-08-12 12:29:51 +05302363 return -ENOMEM;
2364
Ramesh Babuf6fa56e2017-08-23 19:33:53 +05302365 skl_tplg_fill_pin_dynamic_val(mconfig->m_out_pin, MAX_OUT_QUEUE,
2366 tkn_elem->value);
Shreyas NC6277e832016-08-12 12:29:51 +05302367 break;
2368
2369 case SKL_TKN_U8_TIME_SLOT:
2370 mconfig->time_slot = tkn_elem->value;
2371 break;
2372
2373 case SKL_TKN_U8_CORE_ID:
2374 mconfig->core_id = tkn_elem->value;
2375
2376 case SKL_TKN_U8_MOD_TYPE:
2377 mconfig->m_type = tkn_elem->value;
2378 break;
2379
2380 case SKL_TKN_U8_DEV_TYPE:
2381 mconfig->dev_type = tkn_elem->value;
2382 break;
2383
2384 case SKL_TKN_U8_HW_CONN_TYPE:
2385 mconfig->hw_conn_type = tkn_elem->value;
2386 break;
2387
2388 case SKL_TKN_U16_MOD_INST_ID:
2389 mconfig->id.instance_id =
2390 tkn_elem->value;
2391 break;
2392
2393 case SKL_TKN_U32_MEM_PAGES:
Shreyas NC6277e832016-08-12 12:29:51 +05302394 case SKL_TKN_U32_MAX_MCPS:
Shreyas NC6277e832016-08-12 12:29:51 +05302395 case SKL_TKN_U32_OBS:
Shreyas NC6277e832016-08-12 12:29:51 +05302396 case SKL_TKN_U32_IBS:
Colin Ian King2b79b152017-09-20 14:01:25 +01002397 ret = skl_tplg_fill_res_tkn(dev, tkn_elem, res, pin_index, dir);
Ramesh Babuf6fa56e2017-08-23 19:33:53 +05302398 if (ret < 0)
2399 return ret;
2400
Shreyas NC6277e832016-08-12 12:29:51 +05302401 break;
2402
2403 case SKL_TKN_U32_VBUS_ID:
2404 mconfig->vbus_id = tkn_elem->value;
2405 break;
2406
2407 case SKL_TKN_U32_PARAMS_FIXUP:
2408 mconfig->params_fixup = tkn_elem->value;
2409 break;
2410
2411 case SKL_TKN_U32_CONVERTER:
2412 mconfig->converter = tkn_elem->value;
2413 break;
2414
Subhransu S. Prustyc0116be2017-05-04 14:09:11 +05302415 case SKL_TKN_U32_D0I3_CAPS:
Vinod Koul6bd9dcf2016-11-03 17:07:19 +05302416 mconfig->d0i3_caps = tkn_elem->value;
2417 break;
2418
Shreyas NC6277e832016-08-12 12:29:51 +05302419 case SKL_TKN_U32_PIPE_ID:
2420 ret = skl_tplg_add_pipe(dev,
2421 mconfig, skl, tkn_elem);
2422
Guneshwor Singh081dc8a2017-04-27 12:21:22 +05302423 if (ret < 0) {
2424 if (ret == -EEXIST) {
2425 is_pipe_exists = 1;
2426 break;
2427 }
Shreyas NC6277e832016-08-12 12:29:51 +05302428 return is_pipe_exists;
Guneshwor Singh081dc8a2017-04-27 12:21:22 +05302429 }
Shreyas NC6277e832016-08-12 12:29:51 +05302430
2431 break;
2432
Ramesh Babuf6fa56e2017-08-23 19:33:53 +05302433 case SKL_TKN_U32_PIPE_CONFIG_ID:
2434 conf_idx = tkn_elem->value;
2435 break;
2436
Shreyas NC6277e832016-08-12 12:29:51 +05302437 case SKL_TKN_U32_PIPE_CONN_TYPE:
2438 case SKL_TKN_U32_PIPE_PRIORITY:
2439 case SKL_TKN_U32_PIPE_MEM_PGS:
Vinod Koul8a0cb232016-11-03 17:07:18 +05302440 case SKL_TKN_U32_PMODE:
Ramesh Babuf6fa56e2017-08-23 19:33:53 +05302441 case SKL_TKN_U32_PIPE_DIRECTION:
2442 case SKL_TKN_U32_NUM_CONFIGS:
Shreyas NC6277e832016-08-12 12:29:51 +05302443 if (is_pipe_exists) {
2444 ret = skl_tplg_fill_pipe_tkn(dev, mconfig->pipe,
2445 tkn_elem->token, tkn_elem->value);
2446 if (ret < 0)
2447 return ret;
2448 }
2449
2450 break;
2451
Ramesh Babuf6fa56e2017-08-23 19:33:53 +05302452 case SKL_TKN_U32_PATH_MEM_PGS:
2453 case SKL_TKN_U32_CFG_FREQ:
2454 case SKL_TKN_U8_CFG_CHAN:
2455 case SKL_TKN_U8_CFG_BPS:
2456 if (mconfig->pipe->nr_cfgs) {
2457 ret = skl_tplg_fill_pipe_cfg(dev, mconfig->pipe,
2458 tkn_elem->token, tkn_elem->value,
2459 conf_idx, dir);
2460 if (ret < 0)
2461 return ret;
2462 }
2463 break;
2464
2465 case SKL_TKN_CFG_MOD_RES_ID:
2466 mconfig->mod_cfg[conf_idx].res_idx = tkn_elem->value;
2467 break;
2468
2469 case SKL_TKN_CFG_MOD_FMT_ID:
2470 mconfig->mod_cfg[conf_idx].fmt_idx = tkn_elem->value;
2471 break;
2472
Shreyas NC6277e832016-08-12 12:29:51 +05302473 /*
2474 * SKL_TKN_U32_DIR_PIN_COUNT token has the value for both
2475 * direction and the pin count. The first four bits represent
2476 * direction and next four the pin count.
2477 */
2478 case SKL_TKN_U32_DIR_PIN_COUNT:
2479 dir = tkn_elem->value & SKL_IN_DIR_BIT_MASK;
2480 pin_index = (tkn_elem->value &
2481 SKL_PIN_COUNT_MASK) >> 4;
2482
2483 break;
2484
2485 case SKL_TKN_U32_FMT_CH:
2486 case SKL_TKN_U32_FMT_FREQ:
2487 case SKL_TKN_U32_FMT_BIT_DEPTH:
2488 case SKL_TKN_U32_FMT_SAMPLE_SIZE:
2489 case SKL_TKN_U32_FMT_CH_CONFIG:
2490 case SKL_TKN_U32_FMT_INTERLEAVE:
2491 case SKL_TKN_U32_FMT_SAMPLE_TYPE:
2492 case SKL_TKN_U32_FMT_CH_MAP:
Ramesh Babuf6fa56e2017-08-23 19:33:53 +05302493 ret = skl_tplg_widget_fill_fmt(dev, iface, tkn_elem->token,
Shreyas NC6277e832016-08-12 12:29:51 +05302494 tkn_elem->value, dir, pin_index);
2495
2496 if (ret < 0)
2497 return ret;
2498
2499 break;
2500
2501 case SKL_TKN_U32_PIN_MOD_ID:
2502 case SKL_TKN_U32_PIN_INST_ID:
Sriram Periyasamyd9561472017-11-07 16:16:23 +05302503 case SKL_TKN_UUID:
Shreyas NC6277e832016-08-12 12:29:51 +05302504 ret = skl_tplg_fill_pins_info(dev,
2505 mconfig, tkn_elem, dir,
2506 pin_index);
2507 if (ret < 0)
2508 return ret;
2509
2510 break;
2511
2512 case SKL_TKN_U32_CAPS_SIZE:
2513 mconfig->formats_config.caps_size =
2514 tkn_elem->value;
2515
2516 break;
2517
Shreyas NC133e6e52017-05-15 19:44:31 +05302518 case SKL_TKN_U32_CAPS_SET_PARAMS:
2519 mconfig->formats_config.set_params =
2520 tkn_elem->value;
2521 break;
2522
2523 case SKL_TKN_U32_CAPS_PARAMS_ID:
2524 mconfig->formats_config.param_id =
2525 tkn_elem->value;
2526 break;
2527
Shreyas NC6277e832016-08-12 12:29:51 +05302528 case SKL_TKN_U32_PROC_DOMAIN:
2529 mconfig->domain =
2530 tkn_elem->value;
2531
2532 break;
2533
Ramesh Babu939df3a2017-06-19 11:59:19 +05302534 case SKL_TKN_U32_DMA_BUF_SIZE:
2535 mconfig->dma_buffer_size = tkn_elem->value;
2536 break;
2537
Shreyas NC6277e832016-08-12 12:29:51 +05302538 case SKL_TKN_U8_IN_PIN_TYPE:
2539 case SKL_TKN_U8_OUT_PIN_TYPE:
2540 case SKL_TKN_U8_CONN_TYPE:
2541 break;
2542
2543 default:
2544 dev_err(dev, "Token %d not handled\n",
2545 tkn_elem->token);
2546 return -EINVAL;
Hardik T Shah4cd98992015-10-27 09:22:55 +09002547 }
Shreyas NC6277e832016-08-12 12:29:51 +05302548
2549 tkn_count++;
2550
2551 return tkn_count;
2552}
2553
2554/*
2555 * Parse the vendor array for specific tokens to construct
2556 * module private data
2557 */
2558static int skl_tplg_get_tokens(struct device *dev,
2559 char *pvt_data, struct skl *skl,
2560 struct skl_module_cfg *mconfig, int block_size)
2561{
2562 struct snd_soc_tplg_vendor_array *array;
2563 struct snd_soc_tplg_vendor_value_elem *tkn_elem;
2564 int tkn_count = 0, ret;
2565 int off = 0, tuple_size = 0;
Sriram Periyasamyd9561472017-11-07 16:16:23 +05302566 bool is_module_guid = true;
Shreyas NC6277e832016-08-12 12:29:51 +05302567
2568 if (block_size <= 0)
2569 return -EINVAL;
2570
2571 while (tuple_size < block_size) {
2572 array = (struct snd_soc_tplg_vendor_array *)(pvt_data + off);
2573
2574 off += array->size;
2575
2576 switch (array->type) {
2577 case SND_SOC_TPLG_TUPLE_TYPE_STRING:
Colin Ian Kingecd286a2016-09-16 18:51:21 +01002578 dev_warn(dev, "no string tokens expected for skl tplg\n");
Shreyas NC6277e832016-08-12 12:29:51 +05302579 continue;
2580
2581 case SND_SOC_TPLG_TUPLE_TYPE_UUID:
Sriram Periyasamyd9561472017-11-07 16:16:23 +05302582 if (is_module_guid) {
2583 ret = skl_tplg_get_uuid(dev, mconfig->guid,
2584 array->uuid);
2585 is_module_guid = false;
2586 } else {
2587 ret = skl_tplg_get_token(dev, array->value, skl,
2588 mconfig);
2589 }
2590
Shreyas NC6277e832016-08-12 12:29:51 +05302591 if (ret < 0)
2592 return ret;
2593
2594 tuple_size += sizeof(*array->uuid);
2595
2596 continue;
2597
2598 default:
2599 tkn_elem = array->value;
2600 tkn_count = 0;
2601 break;
2602 }
2603
2604 while (tkn_count <= (array->num_elems - 1)) {
2605 ret = skl_tplg_get_token(dev, tkn_elem,
2606 skl, mconfig);
2607
2608 if (ret < 0)
2609 return ret;
2610
2611 tkn_count = tkn_count + ret;
2612 tkn_elem++;
2613 }
2614
2615 tuple_size += tkn_count * sizeof(*tkn_elem);
2616 }
2617
Shreyas NC133e6e52017-05-15 19:44:31 +05302618 return off;
Shreyas NC6277e832016-08-12 12:29:51 +05302619}
2620
2621/*
2622 * Every data block is preceded by a descriptor to read the number
2623 * of data blocks, they type of the block and it's size
2624 */
2625static int skl_tplg_get_desc_blocks(struct device *dev,
2626 struct snd_soc_tplg_vendor_array *array)
2627{
2628 struct snd_soc_tplg_vendor_value_elem *tkn_elem;
2629
2630 tkn_elem = array->value;
2631
2632 switch (tkn_elem->token) {
2633 case SKL_TKN_U8_NUM_BLOCKS:
2634 case SKL_TKN_U8_BLOCK_TYPE:
2635 case SKL_TKN_U16_BLOCK_SIZE:
2636 return tkn_elem->value;
2637
2638 default:
Colin Ian Kingecd286a2016-09-16 18:51:21 +01002639 dev_err(dev, "Invalid descriptor token %d\n", tkn_elem->token);
Shreyas NC6277e832016-08-12 12:29:51 +05302640 break;
2641 }
2642
2643 return -EINVAL;
2644}
2645
2646/*
2647 * Parse the private data for the token and corresponding value.
2648 * The private data can have multiple data blocks. So, a data block
2649 * is preceded by a descriptor for number of blocks and a descriptor
2650 * for the type and size of the suceeding data block.
2651 */
2652static int skl_tplg_get_pvt_data(struct snd_soc_tplg_dapm_widget *tplg_w,
2653 struct skl *skl, struct device *dev,
2654 struct skl_module_cfg *mconfig)
2655{
2656 struct snd_soc_tplg_vendor_array *array;
2657 int num_blocks, block_size = 0, block_type, off = 0;
2658 char *data;
2659 int ret;
2660
2661 /* Read the NUM_DATA_BLOCKS descriptor */
2662 array = (struct snd_soc_tplg_vendor_array *)tplg_w->priv.data;
2663 ret = skl_tplg_get_desc_blocks(dev, array);
2664 if (ret < 0)
2665 return ret;
2666 num_blocks = ret;
2667
2668 off += array->size;
Shreyas NC6277e832016-08-12 12:29:51 +05302669 /* Read the BLOCK_TYPE and BLOCK_SIZE descriptor */
2670 while (num_blocks > 0) {
Shreyas NC133e6e52017-05-15 19:44:31 +05302671 array = (struct snd_soc_tplg_vendor_array *)
2672 (tplg_w->priv.data + off);
2673
Shreyas NC6277e832016-08-12 12:29:51 +05302674 ret = skl_tplg_get_desc_blocks(dev, array);
2675
2676 if (ret < 0)
2677 return ret;
2678 block_type = ret;
2679 off += array->size;
2680
2681 array = (struct snd_soc_tplg_vendor_array *)
2682 (tplg_w->priv.data + off);
2683
2684 ret = skl_tplg_get_desc_blocks(dev, array);
2685
2686 if (ret < 0)
2687 return ret;
2688 block_size = ret;
2689 off += array->size;
2690
2691 array = (struct snd_soc_tplg_vendor_array *)
2692 (tplg_w->priv.data + off);
2693
2694 data = (tplg_w->priv.data + off);
2695
2696 if (block_type == SKL_TYPE_TUPLE) {
2697 ret = skl_tplg_get_tokens(dev, data,
2698 skl, mconfig, block_size);
2699
2700 if (ret < 0)
2701 return ret;
2702
2703 --num_blocks;
2704 } else {
2705 if (mconfig->formats_config.caps_size > 0)
2706 memcpy(mconfig->formats_config.caps, data,
2707 mconfig->formats_config.caps_size);
2708 --num_blocks;
Shreyas NC133e6e52017-05-15 19:44:31 +05302709 ret = mconfig->formats_config.caps_size;
Shreyas NC6277e832016-08-12 12:29:51 +05302710 }
Shreyas NC133e6e52017-05-15 19:44:31 +05302711 off += ret;
Shreyas NC6277e832016-08-12 12:29:51 +05302712 }
2713
2714 return 0;
Hardik T Shah4cd98992015-10-27 09:22:55 +09002715}
2716
Dharageswari Rfe3f4442016-06-03 18:29:39 +05302717static void skl_clear_pin_config(struct snd_soc_platform *platform,
2718 struct snd_soc_dapm_widget *w)
2719{
2720 int i;
2721 struct skl_module_cfg *mconfig;
2722 struct skl_pipe *pipe;
2723
2724 if (!strncmp(w->dapm->component->name, platform->component.name,
2725 strlen(platform->component.name))) {
2726 mconfig = w->priv;
2727 pipe = mconfig->pipe;
Ramesh Babuf6fa56e2017-08-23 19:33:53 +05302728 for (i = 0; i < mconfig->module->max_input_pins; i++) {
Dharageswari Rfe3f4442016-06-03 18:29:39 +05302729 mconfig->m_in_pin[i].in_use = false;
2730 mconfig->m_in_pin[i].pin_state = SKL_PIN_UNBIND;
2731 }
Ramesh Babuf6fa56e2017-08-23 19:33:53 +05302732 for (i = 0; i < mconfig->module->max_output_pins; i++) {
Dharageswari Rfe3f4442016-06-03 18:29:39 +05302733 mconfig->m_out_pin[i].in_use = false;
2734 mconfig->m_out_pin[i].pin_state = SKL_PIN_UNBIND;
2735 }
2736 pipe->state = SKL_PIPE_INVALID;
2737 mconfig->m_state = SKL_MODULE_UNINIT;
2738 }
2739}
2740
2741void skl_cleanup_resources(struct skl *skl)
2742{
2743 struct skl_sst *ctx = skl->skl_sst;
2744 struct snd_soc_platform *soc_platform = skl->platform;
2745 struct snd_soc_dapm_widget *w;
2746 struct snd_soc_card *card;
2747
2748 if (soc_platform == NULL)
2749 return;
2750
2751 card = soc_platform->component.card;
2752 if (!card || !card->instantiated)
2753 return;
2754
2755 skl->resource.mem = 0;
2756 skl->resource.mcps = 0;
2757
2758 list_for_each_entry(w, &card->widgets, list) {
Guneshwor Singhcb1f9042018-01-27 09:50:21 +05302759 if (is_skl_dsp_widget_type(w, ctx->dev) && w->priv != NULL)
Dharageswari Rfe3f4442016-06-03 18:29:39 +05302760 skl_clear_pin_config(soc_platform, w);
2761 }
2762
2763 skl_clear_module_cnt(ctx->dsp);
2764}
2765
Vinod Koul3af36702015-10-07 11:31:56 +01002766/*
2767 * Topology core widget load callback
2768 *
2769 * This is used to save the private data for each widget which gives
2770 * information to the driver about module and pipeline parameters which DSP
2771 * FW expects like ids, resource values, formats etc
2772 */
2773static int skl_tplg_widget_load(struct snd_soc_component *cmpnt,
Jeeja KPb663a8c2015-10-07 11:31:57 +01002774 struct snd_soc_dapm_widget *w,
2775 struct snd_soc_tplg_dapm_widget *tplg_w)
Vinod Koul3af36702015-10-07 11:31:56 +01002776{
2777 int ret;
2778 struct hdac_ext_bus *ebus = snd_soc_component_get_drvdata(cmpnt);
2779 struct skl *skl = ebus_to_skl(ebus);
2780 struct hdac_bus *bus = ebus_to_hbus(ebus);
2781 struct skl_module_cfg *mconfig;
Vinod Koul3af36702015-10-07 11:31:56 +01002782
2783 if (!tplg_w->priv.size)
2784 goto bind_event;
2785
2786 mconfig = devm_kzalloc(bus->dev, sizeof(*mconfig), GFP_KERNEL);
2787
2788 if (!mconfig)
2789 return -ENOMEM;
2790
Ramesh Babuf6fa56e2017-08-23 19:33:53 +05302791 if (skl->nr_modules == 0) {
2792 mconfig->module = devm_kzalloc(bus->dev,
2793 sizeof(*mconfig->module), GFP_KERNEL);
2794 if (!mconfig->module)
2795 return -ENOMEM;
2796 }
2797
Vinod Koul3af36702015-10-07 11:31:56 +01002798 w->priv = mconfig;
Shreyas NC09305da2016-04-21 11:45:22 +05302799
Vinod Koulb7c50552016-07-26 18:06:40 +05302800 /*
2801 * module binary can be loaded later, so set it to query when
2802 * module is load for a use case
2803 */
2804 mconfig->id.module_id = -1;
Hardik T Shah4cd98992015-10-27 09:22:55 +09002805
Shreyas NC6277e832016-08-12 12:29:51 +05302806 /* Parse private data for tuples */
2807 ret = skl_tplg_get_pvt_data(tplg_w, skl, bus->dev, mconfig);
2808 if (ret < 0)
2809 return ret;
Vinod Kould14700a2017-06-30 09:06:06 +05302810
2811 skl_debug_init_module(skl->debugfs, w, mconfig);
2812
Vinod Koul3af36702015-10-07 11:31:56 +01002813bind_event:
2814 if (tplg_w->event_type == 0) {
Vinod Koul3373f712015-10-07 16:39:38 +01002815 dev_dbg(bus->dev, "ASoC: No event handler required\n");
Vinod Koul3af36702015-10-07 11:31:56 +01002816 return 0;
2817 }
2818
2819 ret = snd_soc_tplg_widget_bind_event(w, skl_tplg_widget_ops,
Jeeja KPb663a8c2015-10-07 11:31:57 +01002820 ARRAY_SIZE(skl_tplg_widget_ops),
2821 tplg_w->event_type);
Vinod Koul3af36702015-10-07 11:31:56 +01002822
2823 if (ret) {
2824 dev_err(bus->dev, "%s: No matching event handlers found for %d\n",
2825 __func__, tplg_w->event_type);
2826 return -EINVAL;
2827 }
2828
2829 return 0;
2830}
2831
Jeeja KP140adfb2015-11-28 15:01:50 +05302832static int skl_init_algo_data(struct device *dev, struct soc_bytes_ext *be,
2833 struct snd_soc_tplg_bytes_control *bc)
2834{
2835 struct skl_algo_data *ac;
2836 struct skl_dfw_algo_data *dfw_ac =
2837 (struct skl_dfw_algo_data *)bc->priv.data;
2838
2839 ac = devm_kzalloc(dev, sizeof(*ac), GFP_KERNEL);
2840 if (!ac)
2841 return -ENOMEM;
2842
2843 /* Fill private data */
2844 ac->max = dfw_ac->max;
2845 ac->param_id = dfw_ac->param_id;
2846 ac->set_params = dfw_ac->set_params;
Dharageswari R0d682102016-07-08 18:15:03 +05302847 ac->size = dfw_ac->max;
Jeeja KP140adfb2015-11-28 15:01:50 +05302848
2849 if (ac->max) {
2850 ac->params = (char *) devm_kzalloc(dev, ac->max, GFP_KERNEL);
2851 if (!ac->params)
2852 return -ENOMEM;
2853
Alan Coxedd7ea22016-02-22 09:37:27 +05302854 memcpy(ac->params, dfw_ac->params, ac->max);
Jeeja KP140adfb2015-11-28 15:01:50 +05302855 }
2856
2857 be->dobj.private = ac;
2858 return 0;
2859}
2860
Dharageswari R7a1b7492017-05-31 10:30:25 +05302861static int skl_init_enum_data(struct device *dev, struct soc_enum *se,
2862 struct snd_soc_tplg_enum_control *ec)
2863{
2864
2865 void *data;
2866
2867 if (ec->priv.size) {
2868 data = devm_kzalloc(dev, sizeof(ec->priv.size), GFP_KERNEL);
2869 if (!data)
2870 return -ENOMEM;
2871 memcpy(data, ec->priv.data, ec->priv.size);
2872 se->dobj.private = data;
2873 }
2874
2875 return 0;
2876
2877}
2878
Jeeja KP140adfb2015-11-28 15:01:50 +05302879static int skl_tplg_control_load(struct snd_soc_component *cmpnt,
2880 struct snd_kcontrol_new *kctl,
2881 struct snd_soc_tplg_ctl_hdr *hdr)
2882{
2883 struct soc_bytes_ext *sb;
2884 struct snd_soc_tplg_bytes_control *tplg_bc;
Dharageswari R7a1b7492017-05-31 10:30:25 +05302885 struct snd_soc_tplg_enum_control *tplg_ec;
Jeeja KP140adfb2015-11-28 15:01:50 +05302886 struct hdac_ext_bus *ebus = snd_soc_component_get_drvdata(cmpnt);
2887 struct hdac_bus *bus = ebus_to_hbus(ebus);
Dharageswari R7a1b7492017-05-31 10:30:25 +05302888 struct soc_enum *se;
Jeeja KP140adfb2015-11-28 15:01:50 +05302889
2890 switch (hdr->ops.info) {
2891 case SND_SOC_TPLG_CTL_BYTES:
2892 tplg_bc = container_of(hdr,
2893 struct snd_soc_tplg_bytes_control, hdr);
2894 if (kctl->access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK) {
2895 sb = (struct soc_bytes_ext *)kctl->private_value;
2896 if (tplg_bc->priv.size)
2897 return skl_init_algo_data(
2898 bus->dev, sb, tplg_bc);
2899 }
2900 break;
2901
Dharageswari R7a1b7492017-05-31 10:30:25 +05302902 case SND_SOC_TPLG_CTL_ENUM:
2903 tplg_ec = container_of(hdr,
2904 struct snd_soc_tplg_enum_control, hdr);
2905 if (kctl->access & SNDRV_CTL_ELEM_ACCESS_READWRITE) {
2906 se = (struct soc_enum *)kctl->private_value;
2907 if (tplg_ec->priv.size)
2908 return skl_init_enum_data(bus->dev, se,
2909 tplg_ec);
2910 }
2911 break;
2912
Jeeja KP140adfb2015-11-28 15:01:50 +05302913 default:
Naveen Manohar43629342017-12-08 09:30:18 +05302914 dev_dbg(bus->dev, "Control load not supported %d:%d:%d\n",
Jeeja KP140adfb2015-11-28 15:01:50 +05302915 hdr->ops.get, hdr->ops.put, hdr->ops.info);
2916 break;
2917 }
2918
2919 return 0;
2920}
2921
Shreyas NC541070c2016-08-23 09:31:03 +05302922static int skl_tplg_fill_str_mfest_tkn(struct device *dev,
2923 struct snd_soc_tplg_vendor_string_elem *str_elem,
Jeeja KPeee0e162017-01-02 09:50:04 +05302924 struct skl *skl)
Shreyas NC541070c2016-08-23 09:31:03 +05302925{
2926 int tkn_count = 0;
2927 static int ref_count;
2928
2929 switch (str_elem->token) {
2930 case SKL_TKN_STR_LIB_NAME:
Jeeja KPeee0e162017-01-02 09:50:04 +05302931 if (ref_count > skl->skl_sst->lib_count - 1) {
Shreyas NC541070c2016-08-23 09:31:03 +05302932 ref_count = 0;
2933 return -EINVAL;
2934 }
2935
Jeeja KPeee0e162017-01-02 09:50:04 +05302936 strncpy(skl->skl_sst->lib_info[ref_count].name,
2937 str_elem->string,
2938 ARRAY_SIZE(skl->skl_sst->lib_info[ref_count].name));
Shreyas NC541070c2016-08-23 09:31:03 +05302939 ref_count++;
Shreyas NC541070c2016-08-23 09:31:03 +05302940 break;
2941
2942 default:
Colin Ian Kingecd286a2016-09-16 18:51:21 +01002943 dev_err(dev, "Not a string token %d\n", str_elem->token);
Shreyas NC541070c2016-08-23 09:31:03 +05302944 break;
2945 }
Shreyas NCdb6ed552017-08-23 19:33:52 +05302946 tkn_count++;
Shreyas NC541070c2016-08-23 09:31:03 +05302947
2948 return tkn_count;
2949}
2950
2951static int skl_tplg_get_str_tkn(struct device *dev,
2952 struct snd_soc_tplg_vendor_array *array,
Jeeja KPeee0e162017-01-02 09:50:04 +05302953 struct skl *skl)
Shreyas NC541070c2016-08-23 09:31:03 +05302954{
2955 int tkn_count = 0, ret;
2956 struct snd_soc_tplg_vendor_string_elem *str_elem;
2957
2958 str_elem = (struct snd_soc_tplg_vendor_string_elem *)array->value;
2959 while (tkn_count < array->num_elems) {
Jeeja KPeee0e162017-01-02 09:50:04 +05302960 ret = skl_tplg_fill_str_mfest_tkn(dev, str_elem, skl);
Shreyas NC541070c2016-08-23 09:31:03 +05302961 str_elem++;
2962
2963 if (ret < 0)
2964 return ret;
2965
2966 tkn_count = tkn_count + ret;
2967 }
2968
2969 return tkn_count;
2970}
2971
Shreyas NCdb6ed552017-08-23 19:33:52 +05302972static int skl_tplg_manifest_fill_fmt(struct device *dev,
2973 struct skl_module_iface *fmt,
2974 struct snd_soc_tplg_vendor_value_elem *tkn_elem,
2975 u32 dir, int fmt_idx)
2976{
2977 struct skl_module_pin_fmt *dst_fmt;
2978 struct skl_module_fmt *mod_fmt;
2979 int ret;
2980
2981 if (!fmt)
2982 return -EINVAL;
2983
2984 switch (dir) {
2985 case SKL_DIR_IN:
2986 dst_fmt = &fmt->inputs[fmt_idx];
2987 break;
2988
2989 case SKL_DIR_OUT:
2990 dst_fmt = &fmt->outputs[fmt_idx];
2991 break;
2992
2993 default:
2994 dev_err(dev, "Invalid direction: %d\n", dir);
2995 return -EINVAL;
2996 }
2997
2998 mod_fmt = &dst_fmt->fmt;
2999
3000 switch (tkn_elem->token) {
3001 case SKL_TKN_MM_U32_INTF_PIN_ID:
3002 dst_fmt->id = tkn_elem->value;
3003 break;
3004
3005 default:
3006 ret = skl_tplg_fill_fmt(dev, mod_fmt, tkn_elem->token,
3007 tkn_elem->value);
3008 if (ret < 0)
3009 return ret;
3010 break;
3011 }
3012
3013 return 0;
3014}
3015
3016static int skl_tplg_fill_mod_info(struct device *dev,
3017 struct snd_soc_tplg_vendor_value_elem *tkn_elem,
3018 struct skl_module *mod)
3019{
3020
3021 if (!mod)
3022 return -EINVAL;
3023
3024 switch (tkn_elem->token) {
3025 case SKL_TKN_U8_IN_PIN_TYPE:
3026 mod->input_pin_type = tkn_elem->value;
3027 break;
3028
3029 case SKL_TKN_U8_OUT_PIN_TYPE:
3030 mod->output_pin_type = tkn_elem->value;
3031 break;
3032
3033 case SKL_TKN_U8_IN_QUEUE_COUNT:
3034 mod->max_input_pins = tkn_elem->value;
3035 break;
3036
3037 case SKL_TKN_U8_OUT_QUEUE_COUNT:
3038 mod->max_output_pins = tkn_elem->value;
3039 break;
3040
3041 case SKL_TKN_MM_U8_NUM_RES:
3042 mod->nr_resources = tkn_elem->value;
3043 break;
3044
3045 case SKL_TKN_MM_U8_NUM_INTF:
3046 mod->nr_interfaces = tkn_elem->value;
3047 break;
3048
3049 default:
3050 dev_err(dev, "Invalid mod info token %d", tkn_elem->token);
3051 return -EINVAL;
3052 }
3053
3054 return 0;
3055}
3056
3057
Shreyas NC541070c2016-08-23 09:31:03 +05303058static int skl_tplg_get_int_tkn(struct device *dev,
3059 struct snd_soc_tplg_vendor_value_elem *tkn_elem,
Jeeja KPeee0e162017-01-02 09:50:04 +05303060 struct skl *skl)
Shreyas NC541070c2016-08-23 09:31:03 +05303061{
Pradeep Tewani43762352017-12-06 16:34:02 +05303062 int tkn_count = 0, ret, size;
Shreyas NCdb6ed552017-08-23 19:33:52 +05303063 static int mod_idx, res_val_idx, intf_val_idx, dir, pin_idx;
3064 struct skl_module_res *res = NULL;
3065 struct skl_module_iface *fmt = NULL;
3066 struct skl_module *mod = NULL;
Pradeep Tewani43762352017-12-06 16:34:02 +05303067 static struct skl_astate_param *astate_table;
3068 static int astate_cfg_idx, count;
Shreyas NCdb6ed552017-08-23 19:33:52 +05303069 int i;
3070
3071 if (skl->modules) {
3072 mod = skl->modules[mod_idx];
3073 res = &mod->resources[res_val_idx];
3074 fmt = &mod->formats[intf_val_idx];
3075 }
Shreyas NC541070c2016-08-23 09:31:03 +05303076
3077 switch (tkn_elem->token) {
3078 case SKL_TKN_U32_LIB_COUNT:
Jeeja KPeee0e162017-01-02 09:50:04 +05303079 skl->skl_sst->lib_count = tkn_elem->value;
Shreyas NCdb6ed552017-08-23 19:33:52 +05303080 break;
3081
3082 case SKL_TKN_U8_NUM_MOD:
3083 skl->nr_modules = tkn_elem->value;
3084 skl->modules = devm_kcalloc(dev, skl->nr_modules,
3085 sizeof(*skl->modules), GFP_KERNEL);
3086 if (!skl->modules)
3087 return -ENOMEM;
3088
3089 for (i = 0; i < skl->nr_modules; i++) {
3090 skl->modules[i] = devm_kzalloc(dev,
3091 sizeof(struct skl_module), GFP_KERNEL);
3092 if (!skl->modules[i])
3093 return -ENOMEM;
3094 }
3095 break;
3096
3097 case SKL_TKN_MM_U8_MOD_IDX:
3098 mod_idx = tkn_elem->value;
3099 break;
3100
Pradeep Tewani43762352017-12-06 16:34:02 +05303101 case SKL_TKN_U32_ASTATE_COUNT:
3102 if (astate_table != NULL) {
3103 dev_err(dev, "More than one entry for A-State count");
3104 return -EINVAL;
3105 }
3106
3107 if (tkn_elem->value > SKL_MAX_ASTATE_CFG) {
3108 dev_err(dev, "Invalid A-State count %d\n",
3109 tkn_elem->value);
3110 return -EINVAL;
3111 }
3112
3113 size = tkn_elem->value * sizeof(struct skl_astate_param) +
3114 sizeof(count);
3115 skl->cfg.astate_cfg = devm_kzalloc(dev, size, GFP_KERNEL);
3116 if (!skl->cfg.astate_cfg)
3117 return -ENOMEM;
3118
3119 astate_table = skl->cfg.astate_cfg->astate_table;
3120 count = skl->cfg.astate_cfg->count = tkn_elem->value;
3121 break;
3122
3123 case SKL_TKN_U32_ASTATE_IDX:
3124 if (tkn_elem->value >= count) {
3125 dev_err(dev, "Invalid A-State index %d\n",
3126 tkn_elem->value);
3127 return -EINVAL;
3128 }
3129
3130 astate_cfg_idx = tkn_elem->value;
3131 break;
3132
3133 case SKL_TKN_U32_ASTATE_KCPS:
3134 astate_table[astate_cfg_idx].kcps = tkn_elem->value;
3135 break;
3136
3137 case SKL_TKN_U32_ASTATE_CLK_SRC:
3138 astate_table[astate_cfg_idx].clk_src = tkn_elem->value;
3139 break;
3140
Shreyas NCdb6ed552017-08-23 19:33:52 +05303141 case SKL_TKN_U8_IN_PIN_TYPE:
3142 case SKL_TKN_U8_OUT_PIN_TYPE:
3143 case SKL_TKN_U8_IN_QUEUE_COUNT:
3144 case SKL_TKN_U8_OUT_QUEUE_COUNT:
3145 case SKL_TKN_MM_U8_NUM_RES:
3146 case SKL_TKN_MM_U8_NUM_INTF:
3147 ret = skl_tplg_fill_mod_info(dev, tkn_elem, mod);
3148 if (ret < 0)
3149 return ret;
3150 break;
3151
3152 case SKL_TKN_U32_DIR_PIN_COUNT:
3153 dir = tkn_elem->value & SKL_IN_DIR_BIT_MASK;
3154 pin_idx = (tkn_elem->value & SKL_PIN_COUNT_MASK) >> 4;
3155 break;
3156
3157 case SKL_TKN_MM_U32_RES_ID:
3158 if (!res)
3159 return -EINVAL;
3160
3161 res->id = tkn_elem->value;
3162 res_val_idx = tkn_elem->value;
3163 break;
3164
3165 case SKL_TKN_MM_U32_FMT_ID:
3166 if (!fmt)
3167 return -EINVAL;
3168
3169 fmt->fmt_idx = tkn_elem->value;
3170 intf_val_idx = tkn_elem->value;
3171 break;
3172
3173 case SKL_TKN_MM_U32_CPS:
3174 case SKL_TKN_MM_U32_DMA_SIZE:
3175 case SKL_TKN_MM_U32_CPC:
3176 case SKL_TKN_U32_MEM_PAGES:
3177 case SKL_TKN_U32_OBS:
3178 case SKL_TKN_U32_IBS:
3179 case SKL_TKN_MM_U32_RES_PIN_ID:
3180 case SKL_TKN_MM_U32_PIN_BUF:
3181 ret = skl_tplg_fill_res_tkn(dev, tkn_elem, res, pin_idx, dir);
3182 if (ret < 0)
3183 return ret;
3184
3185 break;
3186
3187 case SKL_TKN_MM_U32_NUM_IN_FMT:
3188 if (!fmt)
3189 return -EINVAL;
3190
3191 res->nr_input_pins = tkn_elem->value;
3192 break;
3193
3194 case SKL_TKN_MM_U32_NUM_OUT_FMT:
3195 if (!fmt)
3196 return -EINVAL;
3197
3198 res->nr_output_pins = tkn_elem->value;
3199 break;
3200
3201 case SKL_TKN_U32_FMT_CH:
3202 case SKL_TKN_U32_FMT_FREQ:
3203 case SKL_TKN_U32_FMT_BIT_DEPTH:
3204 case SKL_TKN_U32_FMT_SAMPLE_SIZE:
3205 case SKL_TKN_U32_FMT_CH_CONFIG:
3206 case SKL_TKN_U32_FMT_INTERLEAVE:
3207 case SKL_TKN_U32_FMT_SAMPLE_TYPE:
3208 case SKL_TKN_U32_FMT_CH_MAP:
3209 case SKL_TKN_MM_U32_INTF_PIN_ID:
3210 ret = skl_tplg_manifest_fill_fmt(dev, fmt, tkn_elem,
3211 dir, pin_idx);
3212 if (ret < 0)
3213 return ret;
Shreyas NC541070c2016-08-23 09:31:03 +05303214 break;
3215
3216 default:
Colin Ian Kingecd286a2016-09-16 18:51:21 +01003217 dev_err(dev, "Not a manifest token %d\n", tkn_elem->token);
Shreyas NC541070c2016-08-23 09:31:03 +05303218 return -EINVAL;
3219 }
Shreyas NCdb6ed552017-08-23 19:33:52 +05303220 tkn_count++;
Shreyas NC541070c2016-08-23 09:31:03 +05303221
3222 return tkn_count;
3223}
3224
Shreyas NCdb6ed552017-08-23 19:33:52 +05303225static int skl_tplg_get_manifest_uuid(struct device *dev,
3226 struct skl *skl,
3227 struct snd_soc_tplg_vendor_uuid_elem *uuid_tkn)
3228{
3229 static int ref_count;
3230 struct skl_module *mod;
3231
3232 if (uuid_tkn->token == SKL_TKN_UUID) {
3233 mod = skl->modules[ref_count];
3234 memcpy(&mod->uuid, &uuid_tkn->uuid, sizeof(uuid_tkn->uuid));
3235 ref_count++;
3236 } else {
3237 dev_err(dev, "Not an UUID token tkn %d\n", uuid_tkn->token);
3238 return -EINVAL;
3239 }
3240
3241 return 0;
3242}
3243
Shreyas NC541070c2016-08-23 09:31:03 +05303244/*
3245 * Fill the manifest structure by parsing the tokens based on the
3246 * type.
3247 */
3248static int skl_tplg_get_manifest_tkn(struct device *dev,
Jeeja KPeee0e162017-01-02 09:50:04 +05303249 char *pvt_data, struct skl *skl,
Shreyas NC541070c2016-08-23 09:31:03 +05303250 int block_size)
3251{
3252 int tkn_count = 0, ret;
3253 int off = 0, tuple_size = 0;
3254 struct snd_soc_tplg_vendor_array *array;
3255 struct snd_soc_tplg_vendor_value_elem *tkn_elem;
3256
3257 if (block_size <= 0)
3258 return -EINVAL;
3259
3260 while (tuple_size < block_size) {
3261 array = (struct snd_soc_tplg_vendor_array *)(pvt_data + off);
3262 off += array->size;
3263 switch (array->type) {
3264 case SND_SOC_TPLG_TUPLE_TYPE_STRING:
Jeeja KPeee0e162017-01-02 09:50:04 +05303265 ret = skl_tplg_get_str_tkn(dev, array, skl);
Shreyas NC541070c2016-08-23 09:31:03 +05303266
3267 if (ret < 0)
3268 return ret;
Shreyas NC0a716772017-05-15 19:44:30 +05303269 tkn_count = ret;
Shreyas NC541070c2016-08-23 09:31:03 +05303270
3271 tuple_size += tkn_count *
3272 sizeof(struct snd_soc_tplg_vendor_string_elem);
3273 continue;
3274
3275 case SND_SOC_TPLG_TUPLE_TYPE_UUID:
Shreyas NCdb6ed552017-08-23 19:33:52 +05303276 ret = skl_tplg_get_manifest_uuid(dev, skl, array->uuid);
3277 if (ret < 0)
3278 return ret;
3279
3280 tuple_size += sizeof(*array->uuid);
Shreyas NC541070c2016-08-23 09:31:03 +05303281 continue;
3282
3283 default:
3284 tkn_elem = array->value;
3285 tkn_count = 0;
3286 break;
3287 }
3288
3289 while (tkn_count <= array->num_elems - 1) {
3290 ret = skl_tplg_get_int_tkn(dev,
Jeeja KPeee0e162017-01-02 09:50:04 +05303291 tkn_elem, skl);
Shreyas NC541070c2016-08-23 09:31:03 +05303292 if (ret < 0)
3293 return ret;
3294
3295 tkn_count = tkn_count + ret;
3296 tkn_elem++;
Shreyas NC541070c2016-08-23 09:31:03 +05303297 }
Shreyas NC9fc129f2017-08-23 19:33:48 +05303298 tuple_size += (tkn_count * sizeof(*tkn_elem));
Shreyas NC541070c2016-08-23 09:31:03 +05303299 tkn_count = 0;
3300 }
3301
Shreyas NC9fc129f2017-08-23 19:33:48 +05303302 return off;
Shreyas NC541070c2016-08-23 09:31:03 +05303303}
3304
3305/*
3306 * Parse manifest private data for tokens. The private data block is
3307 * preceded by descriptors for type and size of data block.
3308 */
3309static int skl_tplg_get_manifest_data(struct snd_soc_tplg_manifest *manifest,
Jeeja KPeee0e162017-01-02 09:50:04 +05303310 struct device *dev, struct skl *skl)
Shreyas NC541070c2016-08-23 09:31:03 +05303311{
3312 struct snd_soc_tplg_vendor_array *array;
3313 int num_blocks, block_size = 0, block_type, off = 0;
3314 char *data;
3315 int ret;
3316
3317 /* Read the NUM_DATA_BLOCKS descriptor */
3318 array = (struct snd_soc_tplg_vendor_array *)manifest->priv.data;
3319 ret = skl_tplg_get_desc_blocks(dev, array);
3320 if (ret < 0)
3321 return ret;
3322 num_blocks = ret;
3323
3324 off += array->size;
Shreyas NC541070c2016-08-23 09:31:03 +05303325 /* Read the BLOCK_TYPE and BLOCK_SIZE descriptor */
3326 while (num_blocks > 0) {
Shreyas NC9fc129f2017-08-23 19:33:48 +05303327 array = (struct snd_soc_tplg_vendor_array *)
3328 (manifest->priv.data + off);
Shreyas NC541070c2016-08-23 09:31:03 +05303329 ret = skl_tplg_get_desc_blocks(dev, array);
3330
3331 if (ret < 0)
3332 return ret;
3333 block_type = ret;
3334 off += array->size;
3335
3336 array = (struct snd_soc_tplg_vendor_array *)
3337 (manifest->priv.data + off);
3338
3339 ret = skl_tplg_get_desc_blocks(dev, array);
3340
3341 if (ret < 0)
3342 return ret;
3343 block_size = ret;
3344 off += array->size;
3345
3346 array = (struct snd_soc_tplg_vendor_array *)
3347 (manifest->priv.data + off);
3348
3349 data = (manifest->priv.data + off);
3350
3351 if (block_type == SKL_TYPE_TUPLE) {
Jeeja KPeee0e162017-01-02 09:50:04 +05303352 ret = skl_tplg_get_manifest_tkn(dev, data, skl,
Shreyas NC541070c2016-08-23 09:31:03 +05303353 block_size);
3354
3355 if (ret < 0)
3356 return ret;
3357
3358 --num_blocks;
3359 } else {
3360 return -EINVAL;
3361 }
Shreyas NC9fc129f2017-08-23 19:33:48 +05303362 off += ret;
Shreyas NC541070c2016-08-23 09:31:03 +05303363 }
3364
3365 return 0;
3366}
3367
Kranthi G15ecaba92016-07-26 18:06:43 +05303368static int skl_manifest_load(struct snd_soc_component *cmpnt,
3369 struct snd_soc_tplg_manifest *manifest)
3370{
Kranthi G15ecaba92016-07-26 18:06:43 +05303371 struct hdac_ext_bus *ebus = snd_soc_component_get_drvdata(cmpnt);
3372 struct hdac_bus *bus = ebus_to_hbus(ebus);
3373 struct skl *skl = ebus_to_skl(ebus);
Kranthi G15ecaba92016-07-26 18:06:43 +05303374
Vinod Koulc15ad602016-08-24 18:03:13 +05303375 /* proceed only if we have private data defined */
3376 if (manifest->priv.size == 0)
3377 return 0;
3378
Jeeja KPeee0e162017-01-02 09:50:04 +05303379 skl_tplg_get_manifest_data(manifest, bus->dev, skl);
Shreyas NC541070c2016-08-23 09:31:03 +05303380
Jeeja KPeee0e162017-01-02 09:50:04 +05303381 if (skl->skl_sst->lib_count > SKL_MAX_LIB) {
Kranthi G15ecaba92016-07-26 18:06:43 +05303382 dev_err(bus->dev, "Exceeding max Library count. Got:%d\n",
Jeeja KPeee0e162017-01-02 09:50:04 +05303383 skl->skl_sst->lib_count);
3384 return -EINVAL;
Kranthi G15ecaba92016-07-26 18:06:43 +05303385 }
3386
Jeeja KPeee0e162017-01-02 09:50:04 +05303387 return 0;
Kranthi G15ecaba92016-07-26 18:06:43 +05303388}
3389
Vinod Koul3af36702015-10-07 11:31:56 +01003390static struct snd_soc_tplg_ops skl_tplg_ops = {
3391 .widget_load = skl_tplg_widget_load,
Jeeja KP140adfb2015-11-28 15:01:50 +05303392 .control_load = skl_tplg_control_load,
3393 .bytes_ext_ops = skl_tlv_ops,
3394 .bytes_ext_ops_count = ARRAY_SIZE(skl_tlv_ops),
Dharageswari R7a1b7492017-05-31 10:30:25 +05303395 .io_ops = skl_tplg_kcontrol_ops,
3396 .io_ops_count = ARRAY_SIZE(skl_tplg_kcontrol_ops),
Kranthi G15ecaba92016-07-26 18:06:43 +05303397 .manifest = skl_manifest_load,
Guneshwor Singh606e21f2017-10-09 11:20:31 +05303398 .dai_load = skl_dai_load,
Vinod Koul3af36702015-10-07 11:31:56 +01003399};
3400
Jeeja KP287af4f2016-06-03 18:29:40 +05303401/*
3402 * A pipe can have multiple modules, each of them will be a DAPM widget as
3403 * well. While managing a pipeline we need to get the list of all the
3404 * widgets in a pipelines, so this helper - skl_tplg_create_pipe_widget_list()
3405 * helps to get the SKL type widgets in that pipeline
3406 */
3407static int skl_tplg_create_pipe_widget_list(struct snd_soc_platform *platform)
3408{
3409 struct snd_soc_dapm_widget *w;
3410 struct skl_module_cfg *mcfg = NULL;
3411 struct skl_pipe_module *p_module = NULL;
3412 struct skl_pipe *pipe;
3413
3414 list_for_each_entry(w, &platform->component.card->widgets, list) {
Guneshwor Singhcb1f9042018-01-27 09:50:21 +05303415 if (is_skl_dsp_widget_type(w, platform->dev) && w->priv) {
Jeeja KP287af4f2016-06-03 18:29:40 +05303416 mcfg = w->priv;
3417 pipe = mcfg->pipe;
3418
3419 p_module = devm_kzalloc(platform->dev,
3420 sizeof(*p_module), GFP_KERNEL);
3421 if (!p_module)
3422 return -ENOMEM;
3423
3424 p_module->w = w;
3425 list_add_tail(&p_module->node, &pipe->w_list);
3426 }
3427 }
3428
3429 return 0;
3430}
3431
Jeeja KPf0aa94f2016-06-03 18:29:41 +05303432static void skl_tplg_set_pipe_type(struct skl *skl, struct skl_pipe *pipe)
3433{
3434 struct skl_pipe_module *w_module;
3435 struct snd_soc_dapm_widget *w;
3436 struct skl_module_cfg *mconfig;
3437 bool host_found = false, link_found = false;
3438
3439 list_for_each_entry(w_module, &pipe->w_list, node) {
3440 w = w_module->w;
3441 mconfig = w->priv;
3442
3443 if (mconfig->dev_type == SKL_DEVICE_HDAHOST)
3444 host_found = true;
3445 else if (mconfig->dev_type != SKL_DEVICE_NONE)
3446 link_found = true;
3447 }
3448
3449 if (host_found && link_found)
3450 pipe->passthru = true;
3451 else
3452 pipe->passthru = false;
3453}
3454
Vinod Koul3af36702015-10-07 11:31:56 +01003455/* This will be read from topology manifest, currently defined here */
3456#define SKL_MAX_MCPS 30000000
3457#define SKL_FW_MAX_MEM 1000000
3458
3459/*
3460 * SKL topology init routine
3461 */
3462int skl_tplg_init(struct snd_soc_platform *platform, struct hdac_ext_bus *ebus)
3463{
3464 int ret;
3465 const struct firmware *fw;
3466 struct hdac_bus *bus = ebus_to_hbus(ebus);
3467 struct skl *skl = ebus_to_skl(ebus);
Jeeja KPf0aa94f2016-06-03 18:29:41 +05303468 struct skl_pipeline *ppl;
Vinod Koul3af36702015-10-07 11:31:56 +01003469
Vinod Koul4b235c42016-02-19 11:42:34 +05303470 ret = request_firmware(&fw, skl->tplg_name, bus->dev);
Vinod Koul3af36702015-10-07 11:31:56 +01003471 if (ret < 0) {
Chintan Patel19de7172017-10-12 09:44:37 -07003472 dev_info(bus->dev, "tplg fw %s load failed with %d, falling back to dfw_sst.bin",
Vinod Koul4b235c42016-02-19 11:42:34 +05303473 skl->tplg_name, ret);
3474 ret = request_firmware(&fw, "dfw_sst.bin", bus->dev);
3475 if (ret < 0) {
3476 dev_err(bus->dev, "Fallback tplg fw %s load failed with %d\n",
3477 "dfw_sst.bin", ret);
3478 return ret;
3479 }
Vinod Koul3af36702015-10-07 11:31:56 +01003480 }
3481
3482 /*
3483 * The complete tplg for SKL is loaded as index 0, we don't use
3484 * any other index
3485 */
Jeeja KPb663a8c2015-10-07 11:31:57 +01003486 ret = snd_soc_tplg_component_load(&platform->component,
3487 &skl_tplg_ops, fw, 0);
Vinod Koul3af36702015-10-07 11:31:56 +01003488 if (ret < 0) {
3489 dev_err(bus->dev, "tplg component load failed%d\n", ret);
Sudip Mukherjeec14a82c2016-01-21 17:27:59 +05303490 release_firmware(fw);
Vinod Koul3af36702015-10-07 11:31:56 +01003491 return -EINVAL;
3492 }
3493
3494 skl->resource.max_mcps = SKL_MAX_MCPS;
3495 skl->resource.max_mem = SKL_FW_MAX_MEM;
3496
Vinod Kould8018362016-01-05 17:16:04 +05303497 skl->tplg = fw;
Jeeja KP287af4f2016-06-03 18:29:40 +05303498 ret = skl_tplg_create_pipe_widget_list(platform);
3499 if (ret < 0)
3500 return ret;
Vinod Kould8018362016-01-05 17:16:04 +05303501
Jeeja KPf0aa94f2016-06-03 18:29:41 +05303502 list_for_each_entry(ppl, &skl->ppl_list, node)
3503 skl_tplg_set_pipe_type(skl, ppl->pipe);
Vinod Koul3af36702015-10-07 11:31:56 +01003504
3505 return 0;
Jeeja KPe4e2d2f2015-10-07 11:31:52 +01003506}