1// SPDX-License-Identifier: BSD-3-Clause
2//
3// Copyright(c) 2021 Intel Corporation. All rights reserved.
4//
5// Author: Liam Girdwood <liam.r.girdwood@linux.intel.com>
6//         Keyon Jie <yang.jie@linux.intel.com>
7//         Rander Wang <rander.wang@linux.intel.com>
8//         Jaska Uimonen <jaska.uimonen@linux.intel.com>
9
10#include "aconfig.h"
11#include <stdint.h>
12#include <errno.h>
13#include <stdio.h>
14#include <stdlib.h>
15#include <string.h>
16#include <stdbool.h>
17#include <alsa/global.h>
18#include <alsa/input.h>
19#include <alsa/output.h>
20#include <alsa/conf.h>
21#include <alsa/error.h>
22#include "../intel-nhlt.h"
23#include "../../nhlt.h"
24#include "ssp-process.h"
25#include "ssp-intel.h"
26#include "ssp-internal.h"
27#include "ssp-debug.h"
28
29static int popcount(uint32_t value)
30{
31	int bits_set = 0;
32
33	while (value) {
34		bits_set += value & 1;
35		value >>= 1;
36	}
37
38	return bits_set;
39}
40
41static void ssp_calculate_intern_v15(struct intel_nhlt_params *nhlt, int hwi)
42{
43	struct intel_ssp_params *ssp = (struct intel_ssp_params *)nhlt->ssp_params;
44	int di = ssp->ssp_count;;
45	struct ssp_intel_config_data_1_5 *blob15 = &ssp->ssp_blob_1_5[di][hwi];
46	struct ssp_intel_config_data *blob = &ssp->ssp_blob[di][hwi];
47	int i;
48
49	blob15->gateway_attributes = ssp->ssp_blob[di][hwi].gateway_attributes;
50	blob15->version = SSP_BLOB_VER_1_5;
51
52	for (i = 0; i < 8; i++)
53		blob15->ts_group[i] = blob->ts_group[i];
54
55	blob15->ssc0 = blob->ssc0;
56	blob15->ssc1 = blob->ssc1;
57	blob15->sscto = blob->sscto;
58	blob15->sspsp = blob->sspsp;
59	blob15->sstsa = blob->sstsa;
60	blob15->ssrsa = blob->ssrsa;
61	blob15->ssc2 = blob->ssc2;
62	blob15->sspsp2 = blob->sspsp2;
63	blob15->ssc3 = blob->ssc3;
64	blob15->ssioc = blob->ssioc;
65
66	/* for now we use only 1 divider as in legacy */
67	blob15->mdivctlr = blob->mdivc;
68	ssp->ssp_prm[di].mdivr[hwi].count = 1;
69	blob15->mdivrcnt = ssp->ssp_prm[di].mdivr[hwi].count;
70	ssp->ssp_prm[di].mdivr[hwi].mdivrs[0] = blob->mdivr;
71
72	blob15->size = sizeof(struct ssp_intel_config_data_1_5) +
73		blob15->mdivrcnt * sizeof(uint32_t) +
74		ssp->ssp_blob_ext[di][hwi].size;
75}
76
77static int ssp_calculate_intern(struct intel_nhlt_params *nhlt, int hwi)
78{
79	struct intel_ssp_params *ssp = (struct intel_ssp_params *)nhlt->ssp_params;
80	uint32_t active_tx_slots = 2;
81	uint32_t active_rx_slots = 2;
82	uint32_t inverted_frame = 0;
83	uint32_t inverted_bclk = 0;
84	uint32_t frame_end_padding;
85	uint32_t total_sample_size;
86	uint32_t slot_end_padding;
87	bool start_delay = false;
88	uint32_t frame_len = 0;
89	uint32_t sample_width;
90	uint32_t end_padding;
91	uint32_t data_size;
92	uint32_t bdiv_min;
93	bool cfs = false;
94	uint32_t clk_div;
95	uint32_t bdiv;
96	uint32_t tft;
97	uint32_t rft;
98	int di;
99	unsigned int i, j;
100
101	if (!ssp)
102		return -EINVAL;
103
104	di = ssp->ssp_count;
105
106	/* should be eventually the lp_mode defined in pipeline */
107	ssp->ssp_blob[di][hwi].gateway_attributes = 0;
108
109	for (j = 0; j < SSP_TDM_MAX_SLOT_MAP_COUNT; j++) {
110		for (i = 0; i < ssp->ssp_prm[di].hw_cfg[hwi].tdm_slots; i++)
111			ssp->ssp_blob[di][hwi].ts_group[j] |= (i << (i * 4));
112		for (; i < SSP_TDM_MAX_SLOT_MAP_COUNT; i++)
113			ssp->ssp_blob[di][hwi].ts_group[j] |= (0xF << (i * 4));
114	}
115
116	/* reset SSP settings */
117	/* sscr0 dynamic settings are DSS, EDSS, SCR, FRDC, ECS */
118	ssp->ssp_blob[di][hwi].ssc0 = SSCR0_PSP | SSCR0_RIM | SSCR0_TIM;
119
120	/* sscr1 dynamic settings are SFRMDIR, SCLKDIR, SCFR */
121	ssp->ssp_blob[di][hwi].ssc1 = SSCR1_TTE | SSCR1_TTELP | SSCR1_TRAIL | SSCR1_RSRE |
122		SSCR1_TSRE;
123
124	/* sscr2 dynamic setting is LJDFD */
125	ssp->ssp_blob[di][hwi].ssc2 = SSCR2_SDFD | SSCR2_TURM1;
126
127	/* sscr3 dynamic settings are TFT, RFT */
128	ssp->ssp_blob[di][hwi].ssc3 = 0;
129
130	/* sspsp dynamic settings are SCMODE, SFRMP, DMYSTRT, SFRMWDTH */
131	ssp->ssp_blob[di][hwi].sspsp = 0;
132
133	/* sspsp2 no dynamic setting */
134	ssp->ssp_blob[di][hwi].sspsp2 = 0x0;
135
136	/* ssioc dynamic setting is SFCR */
137	ssp->ssp_blob[di][hwi].ssioc = SSIOC_SCOE;
138
139	/* ssto no dynamic setting */
140	ssp->ssp_blob[di][hwi].sscto = 0x0;
141
142	/* sstsa dynamic setting is TTSA, default 2 slots */
143	ssp->ssp_blob[di][hwi].sstsa = SSTSA_SSTSA(ssp->ssp_prm[di].hw_cfg[hwi].tx_slots);
144
145	/* ssrsa dynamic setting is RTSA, default 2 slots */
146	ssp->ssp_blob[di][hwi].ssrsa = SSRSA_SSRSA(ssp->ssp_prm[di].hw_cfg[hwi].rx_slots);
147
148	switch (ssp->ssp_prm[di].hw_cfg[hwi].format & SSP_FMT_CLOCK_PROVIDER_MASK) {
149	case SSP_FMT_CBP_CFP:
150		ssp->ssp_blob[di][hwi].ssc1 |= SSCR1_SCLKDIR | SSCR1_SFRMDIR;
151		break;
152	case SSP_FMT_CBC_CFC:
153		ssp->ssp_blob[di][hwi].ssc1 |= SSCR1_SCFR;
154		cfs = true;
155		break;
156	case SSP_FMT_CBP_CFC:
157		ssp->ssp_blob[di][hwi].ssc1 |= SSCR1_SCLKDIR;
158		/* FIXME: this mode has not been tested */
159
160		cfs = true;
161		break;
162	case SSP_FMT_CBC_CFP:
163		ssp->ssp_blob[di][hwi].ssc1 |= SSCR1_SCFR | SSCR1_SFRMDIR;
164		/* FIXME: this mode has not been tested */
165		break;
166	default:
167		fprintf(stderr, "ssp_calculate(): format & PROVIDER_MASK EINVAL\n");
168		return -EINVAL;
169	}
170
171	/* clock signal polarity */
172	switch (ssp->ssp_prm[di].hw_cfg[hwi].format & SSP_FMT_INV_MASK) {
173	case SSP_FMT_NB_NF:
174		break;
175	case SSP_FMT_NB_IF:
176		inverted_frame = 1; /* handled later with format */
177		break;
178	case SSP_FMT_IB_IF:
179		inverted_bclk = 1; /* handled later with bclk idle */
180		inverted_frame = 1; /* handled later with format */
181		break;
182	case SSP_FMT_IB_NF:
183		inverted_bclk = 1; /* handled later with bclk idle */
184		break;
185	default:
186		fprintf(stderr, "ssp_calculate: format & INV_MASK EINVAL\n");
187		return -EINVAL;
188	}
189
190	/* supporting bclk idle state */
191	if (ssp->ssp_prm[di].clks_control &
192		SSP_INTEL_CLKCTRL_BCLK_IDLE_HIGH) {
193		/* bclk idle state high */
194		ssp->ssp_blob[di][hwi].sspsp |= SSPSP_SCMODE((inverted_bclk ^ 0x3) & 0x3);
195	} else {
196		/* bclk idle state low */
197		ssp->ssp_blob[di][hwi].sspsp |= SSPSP_SCMODE(inverted_bclk);
198	}
199
200	ssp->ssp_blob[di][hwi].ssc0 |= SSCR0_MOD | SSCR0_ACS;
201
202	/* Additional hardware settings */
203
204	/* Receiver Time-out Interrupt Disabled/Enabled */
205	ssp->ssp_blob[di][hwi].ssc1 |= (ssp->ssp_prm[di].quirks & SSP_INTEL_QUIRK_TINTE) ?
206		SSCR1_TINTE : 0;
207
208	/* Peripheral Trailing Byte Interrupts Disable/Enable */
209	ssp->ssp_blob[di][hwi].ssc1 |= (ssp->ssp_prm[di].quirks & SSP_INTEL_QUIRK_PINTE) ?
210		SSCR1_PINTE : 0;
211
212	/* Enable/disable internal loopback. Output of transmit serial
213	 * shifter connected to input of receive serial shifter, internally.
214	 */
215	ssp->ssp_blob[di][hwi].ssc1 |= (ssp->ssp_prm[di].quirks & SSP_INTEL_QUIRK_LBM) ?
216		SSCR1_LBM : 0;
217
218	/* Transmit data are driven at the same/opposite clock edge specified
219	 * in SSPSP.SCMODE[1:0]
220	 */
221	ssp->ssp_blob[di][hwi].ssc2 |= (ssp->ssp_prm[di].quirks & SSP_INTEL_QUIRK_SMTATF) ?
222		SSCR2_SMTATF : 0;
223
224	/* Receive data are sampled at the same/opposite clock edge specified
225	 * in SSPSP.SCMODE[1:0]
226	 */
227	ssp->ssp_blob[di][hwi].ssc2 |= (ssp->ssp_prm[di].quirks & SSP_INTEL_QUIRK_MMRATF) ?
228		SSCR2_MMRATF : 0;
229
230	/* Enable/disable the fix for PSP consumer mode TXD wait for frame
231	 * de-assertion before starting the second channel
232	 */
233	ssp->ssp_blob[di][hwi].ssc2 |= (ssp->ssp_prm[di].quirks & SSP_INTEL_QUIRK_PSPSTWFDFD) ?
234		SSCR2_PSPSTWFDFD : 0;
235
236	/* Enable/disable the fix for PSP provider mode FSRT with dummy stop &
237	 * frame end padding capability
238	 */
239	ssp->ssp_blob[di][hwi].ssc2 |= (ssp->ssp_prm[di].quirks & SSP_INTEL_QUIRK_PSPSRWFDFD) ?
240		SSCR2_PSPSRWFDFD : 0;
241
242	if (!ssp->ssp_prm[di].hw_cfg[hwi].mclk_rate) {
243		fprintf(stderr, "ssp_calculate(): invalid MCLK = %u \n",
244			ssp->ssp_prm[di].hw_cfg[hwi].mclk_rate);
245		return -EINVAL;
246	}
247
248	if (!ssp->ssp_prm[di].hw_cfg[hwi].bclk_rate ||
249	    ssp->ssp_prm[di].hw_cfg[hwi].bclk_rate > ssp->ssp_prm[di].hw_cfg[hwi].mclk_rate) {
250		fprintf(stderr, "ssp_calculate(): BCLK %u Hz = 0 or > MCLK %u Hz\n",
251			ssp->ssp_prm[di].hw_cfg[hwi].bclk_rate,
252			ssp->ssp_prm[di].hw_cfg[hwi].mclk_rate);
253		return -EINVAL;
254	}
255
256	/* calc frame width based on BCLK and rate - must be divisible */
257	if (ssp->ssp_prm[di].hw_cfg[hwi].bclk_rate % ssp->ssp_prm[di].hw_cfg[hwi].fsync_rate) {
258		fprintf(stderr, "ssp_calculate(): BCLK %u is not divisible by rate %u\n",
259			ssp->ssp_prm[di].hw_cfg[hwi].bclk_rate,
260			ssp->ssp_prm[di].hw_cfg[hwi].fsync_rate);
261		return -EINVAL;
262	}
263
264	/* must be enough BCLKs for data */
265	bdiv = ssp->ssp_prm[di].hw_cfg[hwi].bclk_rate / ssp->ssp_prm[di].hw_cfg[hwi].fsync_rate;
266	if (bdiv < ssp->ssp_prm[di].hw_cfg[hwi].tdm_slot_width *
267	    ssp->ssp_prm[di].hw_cfg[hwi].tdm_slots) {
268		fprintf(stderr, "ssp_calculate(): not enough BCLKs need %u\n",
269			ssp->ssp_prm[di].hw_cfg[hwi].tdm_slot_width *
270			ssp->ssp_prm[di].hw_cfg[hwi].tdm_slots);
271		return -EINVAL;
272	}
273
274	/* tdm_slot_width must be <= 38 for SSP */
275	if (ssp->ssp_prm[di].hw_cfg[hwi].tdm_slot_width > 38) {
276		fprintf(stderr, "ssp_calculate(): tdm_slot_width %u > 38\n",
277			ssp->ssp_prm[di].hw_cfg[hwi].tdm_slot_width);
278		return -EINVAL;
279	}
280
281	bdiv_min = ssp->ssp_prm[di].hw_cfg[hwi].tdm_slots *
282		   (ssp->ssp_prm[di].tdm_per_slot_padding_flag ?
283		    ssp->ssp_prm[di].hw_cfg[hwi].tdm_slot_width :
284		    ssp->ssp_prm[di].sample_valid_bits);
285	if (bdiv < bdiv_min) {
286		fprintf(stderr, "ssp_calculate(): bdiv(%u) < bdiv_min(%u)\n",
287			bdiv, bdiv_min);
288		return -EINVAL;
289	}
290
291	frame_end_padding = bdiv - bdiv_min;
292	if (frame_end_padding > SSPSP2_FEP_MASK) {
293		fprintf(stderr, "ssp_calculate(): frame_end_padding too big: %u\n",
294			frame_end_padding);
295		return -EINVAL;
296	}
297
298	/* format */
299	switch (ssp->ssp_prm[di].hw_cfg[hwi].format & SSP_FMT_FORMAT_MASK) {
300	case SSP_FMT_I2S:
301
302		start_delay = true;
303
304		ssp->ssp_blob[di][hwi].ssc0 |= SSCR0_FRDC(ssp->ssp_prm[di].hw_cfg[hwi].tdm_slots);
305
306		if (bdiv % 2) {
307			fprintf(stderr, "ssp_calculate(): bdiv %u is not divisible by 2\n",
308				bdiv);
309			return -EINVAL;
310		}
311
312		/* set asserted frame length to half frame length */
313		frame_len = bdiv / 2;
314
315		/*
316		 * handle frame polarity, I2S default is falling/active low,
317		 * non-inverted(inverted_frame=0) -- active low(SFRMP=0),
318		 * inverted(inverted_frame=1) -- rising/active high(SFRMP=1),
319		 * so, we should set SFRMP to inverted_frame.
320		 */
321		ssp->ssp_blob[di][hwi].sspsp |= SSPSP_SFRMP(inverted_frame);
322
323		/*
324		 *  for I2S/LEFT_J, the padding has to happen at the end
325		 * of each slot
326		 */
327		if (frame_end_padding % 2) {
328			fprintf(stderr, "ssp_calculate():frame_end_padding %u not divisible by 2\n",
329				frame_end_padding);
330			return -EINVAL;
331		}
332
333		slot_end_padding = frame_end_padding / 2;
334
335		if (slot_end_padding > SSP_INTEL_SLOT_PADDING_MAX) {
336			/* too big padding */
337			fprintf(stderr, "ssp_calculate(): slot_end_padding > %d\n",
338				SSP_INTEL_SLOT_PADDING_MAX);
339			return -EINVAL;
340		}
341
342		ssp->ssp_blob[di][hwi].sspsp |= SSPSP_DMYSTOP(slot_end_padding);
343		slot_end_padding >>= SSPSP_DMYSTOP_BITS;
344		ssp->ssp_blob[di][hwi].sspsp |= SSPSP_EDMYSTOP(slot_end_padding);
345
346		break;
347
348	case SSP_FMT_LEFT_J:
349
350		/* default start_delay value is set to false */
351
352		ssp->ssp_blob[di][hwi].ssc0 |= SSCR0_FRDC(ssp->ssp_prm[di].hw_cfg[hwi].tdm_slots);
353
354		/* LJDFD enable */
355		ssp->ssp_blob[di][hwi].ssc2 &= ~SSCR2_LJDFD;
356
357		if (bdiv % 2) {
358			fprintf(stderr, "ssp_calculate(): bdiv %u is not divisible by 2\n",
359				bdiv);
360			return -EINVAL;
361		}
362
363		/* set asserted frame length to half frame length */
364		frame_len = bdiv / 2;
365
366		/*
367		 * handle frame polarity, LEFT_J default is rising/active high,
368		 * non-inverted(inverted_frame=0) -- active high(SFRMP=1),
369		 * inverted(inverted_frame=1) -- falling/active low(SFRMP=0),
370		 * so, we should set SFRMP to !inverted_frame.
371		 */
372		ssp->ssp_blob[di][hwi].sspsp |= SSPSP_SFRMP(!inverted_frame ? 1 : 0);
373
374		/*
375		 *  for I2S/LEFT_J, the padding has to happen at the end
376		 * of each slot
377		 */
378		if (frame_end_padding % 2) {
379			fprintf(stderr, "ssp_set_config(): frame padding %u not divisible by 2\n",
380				frame_end_padding);
381			return -EINVAL;
382		}
383
384		slot_end_padding = frame_end_padding / 2;
385
386		if (slot_end_padding > 15) {
387			/* can't handle padding over 15 bits */
388			fprintf(stderr, "ssp_set_config(): slot_end_padding %u > 15 bits\n",
389				slot_end_padding);
390			return -EINVAL;
391		}
392
393		ssp->ssp_blob[di][hwi].sspsp |= SSPSP_DMYSTOP(slot_end_padding);
394		slot_end_padding >>= SSPSP_DMYSTOP_BITS;
395		ssp->ssp_blob[di][hwi].sspsp |= SSPSP_EDMYSTOP(slot_end_padding);
396
397		break;
398	case SSP_FMT_DSP_A:
399
400		start_delay = true;
401
402		/* fallthrough */
403
404	case SSP_FMT_DSP_B:
405
406		/* default start_delay value is set to false */
407
408		ssp->ssp_blob[di][hwi].ssc0 |= SSCR0_MOD |
409			SSCR0_FRDC(ssp->ssp_prm[di].hw_cfg[hwi].tdm_slots);
410
411		/* set asserted frame length */
412		frame_len = 1; /* default */
413
414		if (cfs && ssp->ssp_prm[di].frame_pulse_width > 0 &&
415		    ssp->ssp_prm[di].frame_pulse_width <=
416		    SSP_INTEL_FRAME_PULSE_WIDTH_MAX) {
417			frame_len = ssp->ssp_prm[di].frame_pulse_width;
418		}
419
420		/* frame_pulse_width must less or equal 38 */
421		if (ssp->ssp_prm[di].frame_pulse_width >
422			SSP_INTEL_FRAME_PULSE_WIDTH_MAX) {
423			fprintf(stderr, "ssp_set_config(): frame_pulse_width > %d\n",
424				SSP_INTEL_FRAME_PULSE_WIDTH_MAX);
425			return -EINVAL;
426		}
427		/*
428		 * handle frame polarity, DSP_B default is rising/active high,
429		 * non-inverted(inverted_frame=0) -- active high(SFRMP=1),
430		 * inverted(inverted_frame=1) -- falling/active low(SFRMP=0),
431		 * so, we should set SFRMP to !inverted_frame.
432		 */
433		ssp->ssp_blob[di][hwi].sspsp |= SSPSP_SFRMP(!inverted_frame ? 1 : 0);
434
435		active_tx_slots = popcount(ssp->ssp_prm[di].hw_cfg[hwi].tx_slots);
436		active_rx_slots = popcount(ssp->ssp_prm[di].hw_cfg[hwi].rx_slots);
437
438		/*
439		 * handle TDM mode, TDM mode has padding at the end of
440		 * each slot. The amount of padding is equal to result of
441		 * subtracting slot width and valid bits per slot.
442		 */
443		if (ssp->ssp_prm[di].tdm_per_slot_padding_flag) {
444			frame_end_padding = bdiv - ssp->ssp_prm[di].hw_cfg[hwi].tdm_slots *
445				ssp->ssp_prm[di].hw_cfg[hwi].tdm_slot_width;
446
447			slot_end_padding = ssp->ssp_prm[di].hw_cfg[hwi].tdm_slot_width -
448				ssp->ssp_prm[di].sample_valid_bits;
449
450			if (slot_end_padding >
451				SSP_INTEL_SLOT_PADDING_MAX) {
452				fprintf(stderr, "ssp_set_config(): slot_end_padding > %d\n",
453					SSP_INTEL_SLOT_PADDING_MAX);
454				return -EINVAL;
455			}
456
457			ssp->ssp_blob[di][hwi].sspsp |= SSPSP_DMYSTOP(slot_end_padding);
458			slot_end_padding >>= SSPSP_DMYSTOP_BITS;
459			ssp->ssp_blob[di][hwi].sspsp |= SSPSP_EDMYSTOP(slot_end_padding);
460		}
461
462		ssp->ssp_blob[di][hwi].sspsp2 |= (frame_end_padding & SSPSP2_FEP_MASK);
463
464		break;
465	default:
466		fprintf(stderr, "ssp_set_config(): invalid format 0x%04x\n",
467			ssp->ssp_prm[di].hw_cfg[hwi].format);
468		return -EINVAL;
469	}
470
471	if (start_delay)
472		ssp->ssp_blob[di][hwi].sspsp |= SSPSP_FSRT;
473
474	ssp->ssp_blob[di][hwi].sspsp |= SSPSP_SFRMWDTH(frame_len);
475
476	data_size = ssp->ssp_prm[di].sample_valid_bits;
477
478	if (data_size > 16)
479		ssp->ssp_blob[di][hwi].ssc0 |= (SSCR0_EDSS | SSCR0_DSIZE(data_size - 16));
480	else
481		ssp->ssp_blob[di][hwi].ssc0 |= SSCR0_DSIZE(data_size);
482
483	end_padding = 0;
484	total_sample_size = ssp->ssp_prm[di].hw_cfg[hwi].tdm_slot_width *
485		ssp->ssp_prm[di].hw_cfg[hwi].tdm_slots;
486	while (ssp->ssp_prm[di].io_clk % ((total_sample_size + end_padding) *
487				      ssp->ssp_prm[di].hw_cfg[hwi].fsync_rate)) {
488		if (++end_padding >= 256)
489			break;
490	}
491
492	if (end_padding >= 256)
493		return -EINVAL;
494
495	/* calc scr divisor */
496	clk_div = ssp->ssp_prm[di].io_clk / ((total_sample_size + end_padding) *
497					 ssp->ssp_prm[di].hw_cfg[hwi].fsync_rate);
498	if (clk_div >= 4095)
499		return -EINVAL;
500
501	ssp->ssp_blob[di][hwi].ssc0 |= SSCR0_SCR(clk_div - 1);
502
503	/* setting TFT and RFT */
504	switch (ssp->ssp_prm[di].sample_valid_bits) {
505	case 16:
506		/* use 2 bytes for each slot */
507		sample_width = 2;
508		break;
509	case 24:
510	case 32:
511		/* use 4 bytes for each slot */
512		sample_width = 4;
513		break;
514	default:
515		fprintf(stderr, "ssp_set_config(): sample_valid_bits %u\n",
516			ssp->ssp_prm[di].sample_valid_bits);
517		return -EINVAL;
518	}
519
520	tft = MIN((uint32_t)(SSP_FIFO_DEPTH - SSP_FIFO_WATERMARK),
521		  sample_width * active_tx_slots);
522	rft = MIN((uint32_t)(SSP_FIFO_DEPTH - SSP_FIFO_WATERMARK),
523		  sample_width * active_rx_slots);
524
525	ssp->ssp_blob[di][hwi].ssc3 |= SSCR3_TX(tft) | SSCR3_RX(rft);
526
527	/* calc mn divisor */
528	if (ssp->ssp_prm[di].io_clk % ssp->ssp_prm[di].hw_cfg[hwi].mclk_rate) {
529		fprintf(stderr, "ssp_set_config(): io_clk not divisible with mclk\n");
530		return -EINVAL;
531	}
532
533	clk_div = ssp->ssp_prm[di].io_clk / ssp->ssp_prm[di].hw_cfg[hwi].mclk_rate;
534	if (clk_div > 1)
535		clk_div -= 2;
536	else
537		clk_div = 0xFFF; /* bypass clk divider */
538
539	ssp->ssp_blob[di][hwi].mdivr = clk_div;
540	/* clock will always go through the divider */
541	ssp->ssp_blob[di][hwi].ssc0 |= SSCR0_ECS;
542	/* enable divider for this clock id */
543	ssp->ssp_blob[di][hwi].mdivc |= BIT(ssp->ssp_prm[di].mclk_id);
544	/* set mclk source always for audio cardinal clock */
545	ssp->ssp_blob[di][hwi].mdivc |= MCDSS(SSP_CLOCK_AUDIO_CARDINAL);
546	/* set bclk source for audio cardinal clock */
547	ssp->ssp_blob[di][hwi].mdivc |= MNDSS(SSP_CLOCK_AUDIO_CARDINAL);
548
549	return 0;
550}
551
552static int ssp_calculate_intern_ext(struct intel_nhlt_params *nhlt, int hwi)
553{
554	size_t aux_size, mn_size, clk_size, tr_size, run_size, sync_size, node_size, ext_size,
555		link_size, size, total_size;
556	struct intel_ssp_params *ssp;
557	struct ssp_config_aux *aux;
558	struct ssp_intel_aux_tlv *tlv;
559	struct ssp_intel_mn_ctl *mn;
560	struct ssp_intel_clk_ctl *clk;
561	struct ssp_intel_tr_ctl *tr;
562	struct ssp_intel_run_ctl *run;
563	struct ssp_intel_sync_ctl *sync;
564	struct ssp_intel_node_ctl *node;
565	struct ssp_intel_ext_ctl *ext;
566	struct ssp_intel_link_ctl *link;
567	uint8_t *aux_blob;
568	uint32_t enabled;
569	unsigned int i;
570	int di;
571
572	aux_size = sizeof(struct ssp_intel_aux_tlv);
573	mn_size = sizeof(struct ssp_intel_mn_ctl);
574	clk_size = sizeof(struct ssp_intel_clk_ctl);
575	tr_size = sizeof(struct ssp_intel_tr_ctl);
576	run_size = sizeof(struct ssp_intel_run_ctl);
577	sync_size = sizeof(struct ssp_intel_sync_ctl);
578	node_size = sizeof(struct ssp_intel_node_ctl);
579	ext_size = sizeof(struct ssp_intel_ext_ctl);
580	link_size = sizeof(struct ssp_intel_link_ctl);
581
582	ssp = (struct intel_ssp_params *)nhlt->ssp_params;
583	di = ssp->ssp_count;
584	enabled = ssp->ssp_prm[di].aux_cfg[hwi].enabled;
585	aux = &(ssp->ssp_prm[di].aux_cfg[hwi]);
586	aux_blob = ssp->ssp_blob_ext[di][hwi].aux_blob;
587	total_size = 0;
588	size = 0;
589
590	if (enabled & BIT(SSP_MN_DIVIDER_CONTROLS)) {
591		tlv = (struct ssp_intel_aux_tlv *)aux_blob;
592		mn = (struct ssp_intel_mn_ctl *)(aux_blob + aux_size);
593		size = mn_size + aux_size;
594		tlv->type = SSP_MN_DIVIDER_CONTROLS;
595		tlv->size = mn_size;
596		mn->div_m = aux->mn.m_div;
597		mn->div_n = aux->mn.n_div;
598		aux_blob += size;
599		total_size += size;
600	}
601
602	if (enabled & BIT(SSP_DMA_CLK_CONTROLS)) {
603		tlv = (struct ssp_intel_aux_tlv *)aux_blob;
604		clk = (struct ssp_intel_clk_ctl *)(aux_blob + aux_size);
605		size = clk_size + aux_size;
606		tlv->type = SSP_DMA_CLK_CONTROLS;
607		tlv->size = clk_size;
608		clk->start |= SET_BITS(15, 0, aux->clk.clock_warm_up);
609		clk->start |= SET_BIT(16, aux->clk.mclk);
610		clk->start |= SET_BIT(17, aux->clk.warm_up_ovr);
611		clk->stop |= SET_BITS(15, 0, aux->clk.clock_stop_delay);
612		clk->stop |= SET_BIT(16, aux->clk.keep_running);
613		clk->stop |= SET_BIT(17, aux->clk.clock_stop_ovr);
614		aux_blob += size;
615		total_size += size;
616	}
617
618	if (enabled & BIT(SSP_DMA_TRANSMISSION_START)) {
619		tlv = (struct ssp_intel_aux_tlv *)aux_blob;
620		tr = (struct ssp_intel_tr_ctl *)(aux_blob + aux_size);
621		size = tr_size + aux_size;
622		tlv->type = SSP_DMA_TRANSMISSION_START;
623		tlv->size = tr_size;
624		tr->sampling_frequency = aux->tr_start.sampling_frequency;
625		tr->bit_depth = aux->tr_start.bit_depth;
626		tr->channel_map = aux->tr_start.channel_map;
627		tr->channel_config = aux->tr_start.channel_config;
628		tr->interleaving_style = aux->tr_start.interleaving_style;
629		tr->format |= SET_BITS(7, 0, aux->tr_start.number_of_channels);
630		tr->format |= SET_BITS(15, 8, aux->tr_start.valid_bit_depth);
631		tr->format |= SET_BITS(23, 16, aux->tr_start.sample_type);
632		aux_blob += size;
633		total_size += size;
634	}
635
636	if (enabled & BIT(SSP_DMA_TRANSMISSION_STOP)) {
637		tlv = (struct ssp_intel_aux_tlv *)aux_blob;
638		tr = (struct ssp_intel_tr_ctl *)(aux_blob + aux_size);
639		size = tr_size + aux_size;
640		tlv->type = SSP_DMA_TRANSMISSION_STOP;
641		tlv->size = tr_size;
642		tr->sampling_frequency = aux->tr_stop.sampling_frequency;
643		tr->bit_depth = aux->tr_stop.bit_depth;
644		tr->channel_map = aux->tr_stop.channel_map;
645		tr->channel_config = aux->tr_stop.channel_config;
646		tr->interleaving_style = aux->tr_stop.interleaving_style;
647		tr->format |= SET_BITS(7, 0, aux->tr_stop.number_of_channels);
648		tr->format |= SET_BITS(15, 8, aux->tr_stop.valid_bit_depth);
649		tr->format |= SET_BITS(23, 16, aux->tr_stop.sample_type);
650		aux_blob += size;
651		total_size += size;
652	}
653
654	if (enabled & BIT(SSP_DMA_ALWAYS_RUNNING_MODE)) {
655		tlv = (struct ssp_intel_aux_tlv *)aux_blob;
656		run = (struct ssp_intel_run_ctl *)(aux_blob + aux_size);
657		size = run_size + aux_size;
658		tlv->type = SSP_DMA_ALWAYS_RUNNING_MODE;
659		tlv->size = run_size;
660		run->enabled = aux->run.always_run;
661		aux_blob += size;
662		total_size += size;
663	}
664
665	if (enabled & BIT(SSP_DMA_SYNC_DATA)) {
666		tlv = (struct ssp_intel_aux_tlv *)aux_blob;
667		sync = (struct ssp_intel_sync_ctl *)(aux_blob + aux_size);
668		size = sync_size + aux_size;
669		tlv->type = SSP_DMA_SYNC_DATA;
670		tlv->size = sync_size;
671		sync->sync_denominator = aux->sync.sync_denominator;
672		sync->count = aux->sync.count;
673		aux_blob += size;
674		total_size += size;
675		for (i = 0; i < sync->count; i++) {
676			node = (struct ssp_intel_node_ctl *)(aux_blob);
677			size = node_size;
678			node->node_id = aux->sync.nodes[i].node_id;
679			node->sampling_rate = aux->sync.nodes[i].sampling_rate;
680			tlv->size += node_size;
681			aux_blob += size;
682			total_size += size;
683		}
684	}
685
686	if (enabled & BIT(SSP_DMA_CLK_CONTROLS_EXT)) {
687		tlv = (struct ssp_intel_aux_tlv *)aux_blob;
688		ext = (struct ssp_intel_ext_ctl *)(aux_blob + aux_size);
689		size = ext_size + aux_size;
690		tlv->type = SSP_DMA_CLK_CONTROLS_EXT;
691		tlv->size = ext_size;
692		ext->ext_data |= SET_BIT(0, aux->ext.mclk_policy_override);
693		ext->ext_data |= SET_BIT(1, aux->ext.mclk_always_running);
694		ext->ext_data |= SET_BIT(2, aux->ext.mclk_starts_on_gtw_init);
695		ext->ext_data |= SET_BIT(3, aux->ext.mclk_starts_on_run);
696		ext->ext_data |= SET_BIT(4, aux->ext.mclk_starts_on_pause);
697		ext->ext_data |= SET_BIT(5, aux->ext.mclk_stops_on_pause);
698		ext->ext_data |= SET_BIT(6, aux->ext.mclk_stops_on_reset);
699		ext->ext_data |= SET_BIT(8, aux->ext.bclk_policy_override);
700		ext->ext_data |= SET_BIT(9, aux->ext.bclk_always_running);
701		ext->ext_data |= SET_BIT(10, aux->ext.bclk_starts_on_gtw_init);
702		ext->ext_data |= SET_BIT(11, aux->ext.bclk_starts_on_run);
703		ext->ext_data |= SET_BIT(12, aux->ext.bclk_starts_on_pause);
704		ext->ext_data |= SET_BIT(13, aux->ext.bclk_stops_on_pause);
705		ext->ext_data |= SET_BIT(14, aux->ext.bclk_stops_on_reset);
706		ext->ext_data |= SET_BIT(16, aux->ext.sync_policy_override);
707		ext->ext_data |= SET_BIT(17, aux->ext.sync_always_running);
708		ext->ext_data |= SET_BIT(18, aux->ext.sync_starts_on_gtw_init);
709		ext->ext_data |= SET_BIT(19, aux->ext.sync_starts_on_run);
710		ext->ext_data |= SET_BIT(20, aux->ext.sync_starts_on_pause);
711		ext->ext_data |= SET_BIT(21, aux->ext.sync_stops_on_pause);
712		ext->ext_data |= SET_BIT(22, aux->ext.sync_stops_on_reset);
713		aux_blob += size;
714		total_size += size;
715	}
716
717	if (enabled & BIT(SSP_LINK_CLK_SOURCE)) {
718		tlv = (struct ssp_intel_aux_tlv *)aux_blob;
719		link = (struct ssp_intel_link_ctl *)(aux_blob + aux_size);
720		size = link_size + aux_size;
721		tlv->type = SSP_LINK_CLK_SOURCE;
722		tlv->size = link_size;
723		link->clock_source = aux->link.clock_source;
724		aux_blob += size;
725		total_size += size;
726	}
727
728	ssp->ssp_blob_ext[di][hwi].size = total_size;
729
730	return 0;
731}
732
733
734
735int ssp_calculate(struct intel_nhlt_params *nhlt)
736{
737	struct intel_ssp_params *ssp = (struct intel_ssp_params *)nhlt->ssp_params;
738	unsigned int i;
739
740	if (!ssp)
741		return -EINVAL;
742
743	/* calculate blob for every hw config */
744	for (i = 0; i < ssp->ssp_hw_config_count[ssp->ssp_count]; i++) {
745		if (ssp_calculate_intern(nhlt, i) < 0)
746			return -EINVAL;
747		if (ssp_calculate_intern_ext(nhlt, i) < 0)
748			return -EINVAL;
749		/* v15 blob is made from legacy blob, so it can't fail */
750		ssp_calculate_intern_v15(nhlt, i);
751	}
752
753	ssp_print_internal(ssp);
754	ssp_print_calculated(ssp);
755
756	ssp->ssp_count++;
757
758	return 0;
759}
760
761int ssp_get_dir(struct intel_nhlt_params *nhlt, int dai_index, uint8_t *dir)
762{
763	struct intel_ssp_params *ssp = (struct intel_ssp_params *)nhlt->ssp_params;
764
765	if (!ssp)
766		return -EINVAL;
767
768	*dir = ssp->ssp_prm[dai_index].direction;
769
770	return 0;
771}
772
773int ssp_get_params(struct intel_nhlt_params *nhlt, int dai_index, uint32_t *virtualbus_id,
774		   uint32_t *formats_count, uint32_t *device_type, uint32_t *direction)
775{
776	struct intel_ssp_params *ssp = (struct intel_ssp_params *)nhlt->ssp_params;
777
778	if (!ssp)
779		return -EINVAL;
780
781	*virtualbus_id = ssp->ssp_dai_index[dai_index];
782	*formats_count = ssp->ssp_hw_config_count[dai_index];
783	if (ssp->ssp_prm[dai_index].quirks & SSP_INTEL_QUIRK_BT_SIDEBAND)
784		*device_type = NHLT_DEVICE_TYPE_SSP_BT_SIDEBAND;
785	else
786		*device_type = 0;
787	if (ssp->ssp_prm[dai_index].quirks & SSP_INTEL_QUIRK_RENDER_FEEDBACK) {
788		if (*direction == NHLT_ENDPOINT_DIRECTION_RENDER)
789			*direction = NHLT_ENDPOINT_DIRECTION_RENDER_WITH_LOOPBACK;
790		else if (*direction == NHLT_ENDPOINT_DIRECTION_CAPTURE)
791			*direction = NHLT_ENDPOINT_DIRECTION_FEEDBACK_FOR_RENDER;
792	}
793
794	return 0;
795}
796
797int ssp_get_hw_params(struct intel_nhlt_params *nhlt, int dai_index, int hw_index,
798		      uint32_t *sample_rate, uint16_t *channel_count, uint32_t *bits_per_sample)
799{
800	struct intel_ssp_params *ssp = (struct intel_ssp_params *)nhlt->ssp_params;
801
802	if (!ssp)
803		return -EINVAL;
804
805	*channel_count = ssp->ssp_prm[dai_index].hw_cfg[hw_index].tdm_slots;
806	*sample_rate = ssp->ssp_prm[dai_index].hw_cfg[hw_index].fsync_rate;
807	*bits_per_sample = ssp->ssp_prm[dai_index].hw_cfg[hw_index].tdm_slot_width;
808
809	return 0;
810}
811
812/*
813 * Build ssp vendor blob from calculated parameters.
814 *
815 * Supposed to be called after all ssp DAIs are parsed from topology and the final nhlt blob is
816 * generated.
817 */
818int ssp_get_vendor_blob_size(struct intel_nhlt_params *nhlt, int dai_index,
819			     int hw_config_index, size_t *size)
820{
821	struct intel_ssp_params *ssp = (struct intel_ssp_params *)nhlt->ssp_params;
822
823	if (!ssp)
824		return -EINVAL;
825
826	/* set size for the blob */
827	if (ssp->ssp_prm[dai_index].version == SSP_BLOB_VER_1_5)
828		*size = ssp->ssp_blob_1_5[dai_index][hw_config_index].size;
829	else
830		/* legacy */
831		*size = sizeof(struct ssp_intel_config_data) +
832			ssp->ssp_blob_ext[dai_index][hw_config_index].size;
833
834	return 0;
835}
836
837int ssp_get_vendor_blob_count(struct intel_nhlt_params *nhlt)
838{
839	struct intel_ssp_params *ssp = (struct intel_ssp_params *)nhlt->ssp_params;
840
841	if (!ssp || !ssp->ssp_count)
842		return -EINVAL;
843
844	return ssp->ssp_count;
845}
846
847/* Get the size of dynamic vendor blob to reserve proper amount of memory */
848int ssp_get_vendor_blob(struct intel_nhlt_params *nhlt, uint8_t *vendor_blob,
849			int dai_index, int hw_config_index)
850{
851	struct intel_ssp_params *ssp = (struct intel_ssp_params *)nhlt->ssp_params;
852	uint32_t basic_len, clock_len;
853
854	if (!ssp)
855		return -EINVAL;
856
857	/* top level struct */
858	if (ssp->ssp_prm[dai_index].version == SSP_BLOB_VER_1_5) {
859		basic_len = sizeof(struct ssp_intel_config_data_1_5);
860		clock_len = sizeof(uint32_t) * ssp->ssp_prm[dai_index].mdivr[hw_config_index].count;
861		/* basic data */
862		memcpy(vendor_blob, &ssp->ssp_blob_1_5[dai_index][hw_config_index], basic_len);
863		/* clock data */
864		memcpy(vendor_blob + basic_len,
865		       &ssp->ssp_prm[dai_index].mdivr[hw_config_index].mdivrs[0], clock_len);
866		/* ext data */
867		memcpy(vendor_blob + basic_len + clock_len,
868		       ssp->ssp_blob_ext[dai_index][hw_config_index].aux_blob,
869		       ssp->ssp_blob_ext[dai_index][hw_config_index].size);
870	}
871	else {
872		basic_len = sizeof(struct ssp_intel_config_data);
873		/*basic data */
874		memcpy(vendor_blob, &ssp->ssp_blob[dai_index][hw_config_index], basic_len);
875		/* ext data */
876		memcpy(vendor_blob + basic_len,
877		       ssp->ssp_blob_ext[dai_index][hw_config_index].aux_blob,
878		       ssp->ssp_blob_ext[dai_index][hw_config_index].size);
879	}
880
881	return 0;
882}
883
884int ssp_set_params(struct intel_nhlt_params *nhlt, const char *dir, int dai_index, int io_clk,
885		   int bclk_delay, int sample_bits, int mclk_id, int clks_control,
886		   int frame_pulse_width, const char *tdm_padding_per_slot, const char *quirks,
887		   int version)
888{
889	struct intel_ssp_params *ssp = (struct intel_ssp_params *)nhlt->ssp_params;
890	char delim[] = ",";
891	char *buf, *token = NULL;
892
893	if (!ssp)
894		return -EINVAL;
895
896	if (dir) {
897		if (!strcmp(dir, "playback"))
898			ssp->ssp_prm[ssp->ssp_count].direction = NHLT_ENDPOINT_DIRECTION_RENDER;
899		else if (!strcmp(dir, "capture"))
900			ssp->ssp_prm[ssp->ssp_count].direction = NHLT_ENDPOINT_DIRECTION_CAPTURE;
901		else if (!strcmp(dir, "duplex"))
902			ssp->ssp_prm[ssp->ssp_count].direction =
903			  NHLT_ENDPOINT_DIRECTION_FEEDBACK_FOR_RENDER + 1;
904		else
905			return -EINVAL;
906	}
907	ssp->ssp_dai_index[ssp->ssp_count] = dai_index;
908	ssp->ssp_prm[ssp->ssp_count].io_clk = io_clk;
909	ssp->ssp_prm[ssp->ssp_count].bclk_delay = bclk_delay;
910	ssp->ssp_prm[ssp->ssp_count].sample_valid_bits = sample_bits;
911	ssp->ssp_prm[ssp->ssp_count].mclk_id = mclk_id;
912	ssp->ssp_prm[ssp->ssp_count].clks_control = clks_control;
913	ssp->ssp_prm[ssp->ssp_count].frame_pulse_width = frame_pulse_width;
914	/* let's compare the lower 16 bits as we don't send the signature from topology */
915	if (version == (SSP_BLOB_VER_1_5 & ((1 << 16) - 1)))
916		ssp->ssp_prm[ssp->ssp_count].version = SSP_BLOB_VER_1_5;
917	if (tdm_padding_per_slot && !strcmp(tdm_padding_per_slot, "true"))
918		ssp->ssp_prm[ssp->ssp_count].tdm_per_slot_padding_flag = 1;
919	else
920		ssp->ssp_prm[ssp->ssp_count].tdm_per_slot_padding_flag = 0;
921
922	ssp->ssp_prm[ssp->ssp_count].quirks = 0;
923
924	if (quirks) {
925		buf = strdup(quirks);
926		if (!buf)
927			return -ENOMEM;
928
929		token = strtok(buf, delim);
930
931		while (token) {
932			if (!strcmp(token, "lbm_mode"))
933				ssp->ssp_prm[ssp->ssp_count].quirks |= SSP_INTEL_QUIRK_LBM;
934			else if (!strcmp(token, "bt_sideband"))
935				ssp->ssp_prm[ssp->ssp_count].quirks |= SSP_INTEL_QUIRK_BT_SIDEBAND;
936			else if (!strcmp(token, "render_feedback")) {
937				if (!strcmp(dir, "duplex"))
938					ssp->ssp_prm[ssp->ssp_count].quirks |= SSP_INTEL_QUIRK_RENDER_FEEDBACK;
939			} else {
940				fprintf(stderr, "ssp_set_params(): unknown quirk %s\n", token);
941				free(buf);
942				return -EINVAL;
943			}
944
945			token = strtok(NULL, delim);
946		}
947
948		free(buf);
949	}
950
951	/* reset hw config count for this ssp instance */
952	ssp->ssp_hw_config_count[ssp->ssp_count] = 0;
953
954	return 0;
955}
956
957int ssp_hw_set_params(struct intel_nhlt_params *nhlt, const char *format,
958		      const char *mclk ATTRIBUTE_UNUSED,
959		      const char *bclk, const char *bclk_invert, const char *fsync,
960		      const char *fsync_invert, int mclk_freq, int bclk_freq, int fsync_freq,
961		      int tdm_slots, int tdm_slot_width, int tx_slots, int rx_slots)
962{
963	struct intel_ssp_params *ssp = (struct intel_ssp_params *)nhlt->ssp_params;
964	uint32_t hwi;
965
966	if (!ssp)
967		return -EINVAL;
968
969	/* check that the strings are defined ?*/
970
971	/* compose format out of clock related string variables */
972	hwi = ssp->ssp_hw_config_count[ssp->ssp_count];
973
974	if (!strcmp(format, "I2S")) {
975		ssp->ssp_prm[ssp->ssp_count].hw_cfg[hwi].format = SSP_FMT_I2S;
976	} else if (!strcmp(format, "RIGHT_J")) {
977		ssp->ssp_prm[ssp->ssp_count].hw_cfg[hwi].format = SSP_FMT_RIGHT_J;
978	} else if (!strcmp(format, "LEFT_J")) {
979		ssp->ssp_prm[ssp->ssp_count].hw_cfg[hwi].format = SSP_FMT_LEFT_J;
980	} else if (!strcmp(format, "DSP_A")) {
981		ssp->ssp_prm[ssp->ssp_count].hw_cfg[hwi].format = SSP_FMT_DSP_A;
982	} else if (!strcmp(format, "DSP_B")) {
983		ssp->ssp_prm[ssp->ssp_count].hw_cfg[hwi].format = SSP_FMT_DSP_B;
984	} else {
985		fprintf(stderr, "no valid format specified for ssp: %s\n", format);
986		return -EINVAL;
987	}
988
989	/* clock directions wrt codec */
990	if (bclk && !strcmp(bclk, "codec_provider")) {
991		/* codec is bclk provider */
992		if (fsync && !strcmp(fsync, "codec_provider"))
993			ssp->ssp_prm[ssp->ssp_count].hw_cfg[hwi].format |= SSP_FMT_CBP_CFP;
994		else
995			ssp->ssp_prm[ssp->ssp_count].hw_cfg[hwi].format |= SSP_FMT_CBP_CFC;
996	} else {
997		/* codec is bclk consumer */
998		if (fsync && !strcmp(fsync, "codec_provider"))
999			ssp->ssp_prm[ssp->ssp_count].hw_cfg[hwi].format |= SSP_FMT_CBC_CFP;
1000		else
1001			ssp->ssp_prm[ssp->ssp_count].hw_cfg[hwi].format |= SSP_FMT_CBC_CFC;
1002	}
1003
1004	/* inverted clocks ? */
1005	if (bclk_invert && !strcmp(bclk_invert, "true")) {
1006		if (fsync_invert && !strcmp(fsync_invert, "true"))
1007			ssp->ssp_prm[ssp->ssp_count].hw_cfg[hwi].format |= SSP_FMT_IB_IF;
1008		else
1009			ssp->ssp_prm[ssp->ssp_count].hw_cfg[hwi].format |= SSP_FMT_IB_NF;
1010	} else {
1011		if (fsync_invert && !strcmp(fsync_invert, "true"))
1012			ssp->ssp_prm[ssp->ssp_count].hw_cfg[hwi].format |= SSP_FMT_NB_IF;
1013		else
1014			ssp->ssp_prm[ssp->ssp_count].hw_cfg[hwi].format |= SSP_FMT_NB_NF;
1015	}
1016
1017	ssp->ssp_prm[ssp->ssp_count].hw_cfg[hwi].mclk_rate = mclk_freq;
1018	ssp->ssp_prm[ssp->ssp_count].hw_cfg[hwi].bclk_rate = bclk_freq;
1019	ssp->ssp_prm[ssp->ssp_count].hw_cfg[hwi].fsync_rate = fsync_freq;
1020	ssp->ssp_prm[ssp->ssp_count].hw_cfg[hwi].tdm_slots = tdm_slots;
1021	ssp->ssp_prm[ssp->ssp_count].hw_cfg[hwi].tdm_slot_width = tdm_slot_width;
1022	ssp->ssp_prm[ssp->ssp_count].hw_cfg[hwi].tx_slots = tx_slots;
1023	ssp->ssp_prm[ssp->ssp_count].hw_cfg[hwi].rx_slots = rx_slots;
1024
1025	ssp->ssp_hw_config_count[ssp->ssp_count]++;
1026
1027	return 0;
1028}
1029
1030int ssp_mn_set_params(struct intel_nhlt_params *nhlt, int m_div, int n_div)
1031{
1032	struct intel_ssp_params *ssp = (struct intel_ssp_params *)nhlt->ssp_params;
1033	int di = ssp->ssp_count;
1034	int hwi = ssp->ssp_hw_config_count[di];
1035
1036	if (di < 0 || hwi < 0)
1037		return -EINVAL;
1038
1039	ssp->ssp_prm[di].aux_cfg[hwi].enabled |= BIT(SSP_MN_DIVIDER_CONTROLS);
1040
1041	ssp->ssp_prm[di].aux_cfg[hwi].mn.m_div = m_div;
1042	ssp->ssp_prm[di].aux_cfg[hwi].mn.n_div = n_div;
1043
1044	return 0;
1045}
1046
1047int ssp_clk_set_params(struct intel_nhlt_params *nhlt, int clock_warm_up, int mclk, int warm_up_ovr,
1048		       int clock_stop_delay, int keep_running, int clock_stop_ovr)
1049{
1050	struct intel_ssp_params *ssp = (struct intel_ssp_params *)nhlt->ssp_params;
1051	int di = ssp->ssp_count;
1052	int hwi = ssp->ssp_hw_config_count[di];
1053
1054	if (di < 0 || hwi < 0)
1055		return -EINVAL;
1056
1057	ssp->ssp_prm[di].aux_cfg[hwi].enabled |= BIT(SSP_DMA_CLK_CONTROLS);
1058
1059	ssp->ssp_prm[di].aux_cfg[hwi].clk.clock_warm_up = clock_warm_up;
1060	ssp->ssp_prm[di].aux_cfg[hwi].clk.mclk = mclk;
1061	ssp->ssp_prm[di].aux_cfg[hwi].clk.warm_up_ovr = warm_up_ovr;
1062	ssp->ssp_prm[di].aux_cfg[hwi].clk.clock_stop_delay = clock_stop_delay;
1063	ssp->ssp_prm[di].aux_cfg[hwi].clk.keep_running = keep_running;
1064	ssp->ssp_prm[di].aux_cfg[hwi].clk.clock_stop_ovr = clock_stop_ovr;
1065
1066	return 0;
1067}
1068
1069int ssp_tr_start_set_params(struct intel_nhlt_params *nhlt, int sampling_frequency,
1070			    int bit_depth, int channel_map, int channel_config,
1071			    int interleaving_style, int number_of_channels,
1072			    int valid_bit_depth, int sample_type)
1073{
1074	struct intel_ssp_params *ssp;
1075	struct ssp_aux_config_tr *tr;
1076	int di, hwi;
1077
1078	ssp = (struct intel_ssp_params *)nhlt->ssp_params;
1079	di = ssp->ssp_count;
1080	hwi = ssp->ssp_hw_config_count[di];
1081	if (di < 0 || hwi < 0)
1082		return -EINVAL;
1083	tr = (struct ssp_aux_config_tr *)&(ssp->ssp_prm[di].aux_cfg[hwi].tr_start);
1084
1085	ssp->ssp_prm[di].aux_cfg[hwi].enabled |= BIT(SSP_DMA_TRANSMISSION_START);
1086
1087	tr->sampling_frequency = sampling_frequency;
1088	tr->bit_depth = bit_depth;
1089	tr->channel_map = channel_map;
1090	tr->channel_config = channel_config;
1091	tr->interleaving_style = interleaving_style;
1092	tr->number_of_channels = number_of_channels;
1093	tr->valid_bit_depth = valid_bit_depth;
1094	tr->sample_type = sample_type;
1095
1096	return 0;
1097}
1098
1099int ssp_tr_stop_set_params(struct intel_nhlt_params *nhlt, int sampling_frequency,
1100			    int bit_depth, int channel_map, int channel_config,
1101			    int interleaving_style, int number_of_channels,
1102			    int valid_bit_depth, int sample_type)
1103{
1104	struct intel_ssp_params *ssp;
1105	struct ssp_aux_config_tr *tr;
1106	int di, hwi;
1107
1108	ssp = (struct intel_ssp_params *)nhlt->ssp_params;
1109	di = ssp->ssp_count;
1110	hwi = ssp->ssp_hw_config_count[di];
1111	if (di < 0 || hwi < 0)
1112		return -EINVAL;
1113	tr = (struct ssp_aux_config_tr *)&(ssp->ssp_prm[di].aux_cfg[hwi].tr_stop);
1114
1115	ssp->ssp_prm[di].aux_cfg[hwi].enabled |= BIT(SSP_DMA_TRANSMISSION_STOP);
1116
1117	tr->sampling_frequency = sampling_frequency;
1118	tr->bit_depth = bit_depth;
1119	tr->channel_map = channel_map;
1120	tr->channel_config = channel_config;
1121	tr->interleaving_style = interleaving_style;
1122	tr->number_of_channels = number_of_channels;
1123	tr->valid_bit_depth = valid_bit_depth;
1124	tr->sample_type = sample_type;
1125
1126	return 0;
1127}
1128
1129int ssp_run_set_params(struct intel_nhlt_params *nhlt, int always_run)
1130{
1131	struct intel_ssp_params *ssp = (struct intel_ssp_params *)nhlt->ssp_params;
1132	int di = ssp->ssp_count;
1133	int hwi = ssp->ssp_hw_config_count[di];
1134
1135	if (di < 0 || hwi < 0)
1136		return -EINVAL;
1137
1138	ssp->ssp_prm[di].aux_cfg[hwi].enabled |= BIT(SSP_DMA_ALWAYS_RUNNING_MODE);
1139
1140	ssp->ssp_prm[di].aux_cfg[hwi].run.always_run = always_run;
1141
1142	return 0;
1143}
1144
1145int ssp_sync_set_params(struct intel_nhlt_params *nhlt, int sync_denominator)
1146{
1147	struct intel_ssp_params *ssp = (struct intel_ssp_params *)nhlt->ssp_params;
1148	int di = ssp->ssp_count;
1149	int hwi = ssp->ssp_hw_config_count[di];
1150
1151	if (di < 0 || hwi < 0)
1152		return -EINVAL;
1153
1154	ssp->ssp_prm[di].aux_cfg[hwi].enabled |= BIT(SSP_DMA_SYNC_DATA);
1155
1156	ssp->ssp_prm[di].aux_cfg[hwi].sync.sync_denominator = sync_denominator;
1157
1158	return 0;
1159}
1160
1161int ssp_node_set_params(struct intel_nhlt_params *nhlt, int node_id, int sampling_rate)
1162{
1163	struct intel_ssp_params *ssp = (struct intel_ssp_params *)nhlt->ssp_params;
1164	int di = ssp->ssp_count;
1165	int hwi = ssp->ssp_hw_config_count[di];
1166	int count;
1167
1168	if (di < 0 || hwi < 0)
1169		return -EINVAL;
1170
1171	count = ssp->ssp_prm[di].aux_cfg[hwi].sync.count;
1172	if (count > SSP_MAX_DAIS)
1173		return -EINVAL;
1174
1175	ssp->ssp_prm[di].aux_cfg[hwi].sync.nodes[count].node_id = node_id;
1176	ssp->ssp_prm[di].aux_cfg[hwi].sync.nodes[count].sampling_rate = sampling_rate;
1177
1178	ssp->ssp_prm[di].aux_cfg[hwi].sync.count++;
1179
1180	return 0;
1181}
1182
1183int ssp_ext_set_params(struct intel_nhlt_params *nhlt, int mclk_policy_override,
1184		       int mclk_always_running, int mclk_starts_on_gtw_init, int mclk_starts_on_run,
1185		       int mclk_starts_on_pause, int mclk_stops_on_pause, int mclk_stops_on_reset,
1186		       int bclk_policy_override, int bclk_always_running,
1187		       int bclk_starts_on_gtw_init, int bclk_starts_on_run,
1188		       int bclk_starts_on_pause, int bclk_stops_on_pause, int bclk_stops_on_reset,
1189		       int sync_policy_override, int sync_always_running,
1190		       int sync_starts_on_gtw_init, int sync_starts_on_run,
1191		       int sync_starts_on_pause, int sync_stops_on_pause, int sync_stops_on_reset)
1192{
1193	struct intel_ssp_params *ssp = (struct intel_ssp_params *)nhlt->ssp_params;
1194	int di = ssp->ssp_count;
1195	int hwi = ssp->ssp_hw_config_count[di];
1196
1197	if (di < 0 || hwi < 0)
1198		return -EINVAL;
1199
1200	ssp->ssp_prm[di].aux_cfg[hwi].enabled |= BIT(SSP_DMA_CLK_CONTROLS_EXT);
1201
1202	ssp->ssp_prm[di].aux_cfg[hwi].ext.mclk_policy_override = mclk_policy_override;
1203	ssp->ssp_prm[di].aux_cfg[hwi].ext.mclk_always_running = mclk_always_running;
1204	ssp->ssp_prm[di].aux_cfg[hwi].ext.mclk_starts_on_gtw_init  = mclk_starts_on_gtw_init;
1205	ssp->ssp_prm[di].aux_cfg[hwi].ext.mclk_starts_on_run = mclk_starts_on_run;
1206	ssp->ssp_prm[di].aux_cfg[hwi].ext.mclk_starts_on_pause = mclk_starts_on_pause;
1207	ssp->ssp_prm[di].aux_cfg[hwi].ext.mclk_stops_on_pause = mclk_stops_on_pause;
1208	ssp->ssp_prm[di].aux_cfg[hwi].ext.mclk_stops_on_reset = mclk_stops_on_reset;
1209	ssp->ssp_prm[di].aux_cfg[hwi].ext.bclk_policy_override = bclk_policy_override;
1210	ssp->ssp_prm[di].aux_cfg[hwi].ext.bclk_always_running = bclk_always_running;
1211	ssp->ssp_prm[di].aux_cfg[hwi].ext.bclk_starts_on_gtw_init = bclk_starts_on_gtw_init;
1212	ssp->ssp_prm[di].aux_cfg[hwi].ext.bclk_starts_on_run = bclk_starts_on_run;
1213	ssp->ssp_prm[di].aux_cfg[hwi].ext.bclk_starts_on_pause = bclk_starts_on_pause;
1214	ssp->ssp_prm[di].aux_cfg[hwi].ext.bclk_stops_on_pause = bclk_stops_on_pause;
1215	ssp->ssp_prm[di].aux_cfg[hwi].ext.bclk_stops_on_reset = bclk_stops_on_reset;
1216	ssp->ssp_prm[di].aux_cfg[hwi].ext.sync_policy_override = sync_policy_override;
1217	ssp->ssp_prm[di].aux_cfg[hwi].ext.sync_always_running = sync_always_running;
1218	ssp->ssp_prm[di].aux_cfg[hwi].ext.sync_starts_on_gtw_init = sync_starts_on_gtw_init;
1219	ssp->ssp_prm[di].aux_cfg[hwi].ext.sync_starts_on_run = sync_starts_on_run;
1220	ssp->ssp_prm[di].aux_cfg[hwi].ext.sync_starts_on_pause = sync_starts_on_pause;
1221	ssp->ssp_prm[di].aux_cfg[hwi].ext.sync_stops_on_pause = sync_stops_on_pause;
1222	ssp->ssp_prm[di].aux_cfg[hwi].ext.sync_stops_on_reset = sync_stops_on_reset;
1223
1224	return 0;
1225}
1226
1227int ssp_link_set_params(struct intel_nhlt_params *nhlt, int clock_source)
1228{
1229	struct intel_ssp_params *ssp = (struct intel_ssp_params *)nhlt->ssp_params;
1230	int di = ssp->ssp_count;
1231	int hwi = ssp->ssp_hw_config_count[di];
1232
1233	if (di < 0 || hwi < 0)
1234		return -EINVAL;
1235
1236	ssp->ssp_prm[di].aux_cfg[hwi].enabled |= BIT(SSP_LINK_CLK_SOURCE);
1237
1238	ssp->ssp_prm[di].aux_cfg[hwi].link.clock_source = clock_source;
1239
1240	return 0;
1241}
1242
1243/* init ssp parameters, should be called before parsing dais */
1244int ssp_init_params(struct intel_nhlt_params *nhlt)
1245{
1246	struct intel_ssp_params *ssp;
1247	int i, j;
1248
1249	ssp = calloc(1, sizeof(struct intel_ssp_params));
1250	if (!ssp)
1251		return -EINVAL;
1252
1253	nhlt->ssp_params = ssp;
1254	ssp->ssp_count = 0;
1255
1256	for (i = 0; i < SSP_MAX_DAIS; i++) {
1257		ssp->ssp_hw_config_count[i] = 0;
1258		for (j = 0; j < SSP_MAX_HW_CONFIG; j++)
1259			ssp->ssp_prm[i].aux_cfg[j].sync.count = 0;
1260	}
1261
1262	return 0;
1263}
1264