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