1 // SPDX-License-Identifier: BSD-3-Clause
2 //
3 // Copyright(c) 2016 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 
9 #include <sof/audio/component.h>
10 #include <sof/common.h>
11 #include <sof/drivers/mn.h>
12 #include <sof/drivers/timestamp.h>
13 #include <sof/drivers/ssp.h>
14 #include <rtos/alloc.h>
15 #include <rtos/clk.h>
16 #include <sof/lib/dai.h>
17 #include <sof/lib/dma.h>
18 #include <sof/lib/memory.h>
19 #include <sof/lib/pm_runtime.h>
20 #include <sof/lib/uuid.h>
21 #include <rtos/wait.h>
22 #include <sof/platform.h>
23 #include <rtos/spinlock.h>
24 #include <sof/trace/trace.h>
25 #include <ipc/dai.h>
26 #include <ipc/dai-intel.h>
27 #include <ipc/stream.h>
28 #include <ipc/topology.h>
29 #include <ipc4/ssp.h>
30 #include <user/trace.h>
31 
32 #include <errno.h>
33 #include <stdbool.h>
34 #include <stdint.h>
35 
36 LOG_MODULE_REGISTER(ssp_dai, CONFIG_SOF_LOG_LEVEL);
37 
38 /* 31458125-95c4-4085-8f3f-497434cb2daf */
39 DECLARE_SOF_UUID("ssp-dai", ssp_uuid, 0x31458125, 0x95c4, 0x4085,
40 		 0x8f, 0x3f, 0x49, 0x74, 0x34, 0xcb, 0x2d, 0xaf);
41 
42 DECLARE_TR_CTX(ssp_tr, SOF_UUID(ssp_uuid), LOG_LEVEL_INFO);
43 
44 /* empty SSP transmit FIFO */
ssp_empty_tx_fifo(struct dai * dai)45 static void ssp_empty_tx_fifo(struct dai *dai)
46 {
47 	int ret;
48 	uint32_t sssr;
49 
50 	/*
51 	 * SSSR_TNF is cleared when TX FIFO is empty or full,
52 	 * so wait for set TNF then for TFL zero - order matter.
53 	 */
54 	ret = poll_for_register_delay(dai_base(dai) + SSSR, SSSR_TNF, SSSR_TNF,
55 				      SSP_MAX_SEND_TIME_PER_SAMPLE);
56 	ret |= poll_for_register_delay(dai_base(dai) + SSCR3, SSCR3_TFL_MASK, 0,
57 				       SSP_MAX_SEND_TIME_PER_SAMPLE *
58 				       (SSP_FIFO_DEPTH - 1) / 2);
59 
60 	if (ret)
61 		dai_warn(dai, "ssp_empty_tx_fifo() warning: timeout");
62 
63 	sssr = ssp_read(dai, SSSR);
64 
65 	/* clear interrupt */
66 	if (sssr & SSSR_TUR)
67 		ssp_write(dai, SSSR, sssr);
68 }
69 
70 /* empty SSP receive FIFO */
ssp_empty_rx_fifo(struct dai * dai)71 static void ssp_empty_rx_fifo(struct dai *dai)
72 {
73 	struct ssp_pdata *ssp = dai_get_drvdata(dai);
74 	uint64_t sample_ticks = clock_ticks_per_sample(PLATFORM_DEFAULT_CLOCK,
75 						       ssp->params.fsync_rate);
76 	uint32_t retry = SSP_RX_FLUSH_RETRY_MAX;
77 	uint32_t entries;
78 	uint32_t i;
79 
80 	/*
81 	 * To make sure all the RX FIFO entries are read out for the flushing,
82 	 * we need to wait a minimal SSP port delay after entries are all read,
83 	 * and then re-check to see if there is any subsequent entries written
84 	 * to the FIFO. This will help to make sure there is no sample mismatched
85 	 * issue for the next run with the SSP RX.
86 	 */
87 	while ((ssp_read(dai, SSSR) & SSSR_RNE) && retry--) {
88 		entries = SSCR3_RFL_VAL(ssp_read(dai, SSCR3));
89 		dai_dbg(dai, "ssp_empty_rx_fifo(), before flushing, entries %d", entries);
90 		for (i = 0; i < entries + 1; i++)
91 			/* read to try empty fifo */
92 			ssp_read(dai, SSDR);
93 
94 		/* wait to get valid fifo status and re-check */
95 		wait_delay(sample_ticks);
96 		entries = SSCR3_RFL_VAL(ssp_read(dai, SSCR3));
97 		dai_dbg(dai, "ssp_empty_rx_fifo(), after flushing, entries %d", entries);
98 	}
99 
100 	/* clear interrupt */
101 	ssp_update_bits(dai, SSSR, SSSR_ROR, SSSR_ROR);
102 }
103 
ssp_mclk_prepare_enable(struct dai * dai)104 static int ssp_mclk_prepare_enable(struct dai *dai)
105 {
106 	struct ssp_pdata *ssp = dai_get_drvdata(dai);
107 	struct sof_ipc_dai_config *config = &ssp->config;
108 	int ret;
109 
110 	if (ssp->clk_active & SSP_CLK_MCLK_ACTIVE)
111 		return 0;
112 
113 	/* MCLK config */
114 	ret = mn_set_mclk(config->ssp.mclk_id, config->ssp.mclk_rate);
115 	if (ret < 0)
116 		dai_err(dai, "ssp_mclk_prepare_enable(): invalid mclk_rate = %d for mclk_id = %d",
117 			config->ssp.mclk_rate, config->ssp.mclk_id);
118 	else
119 		ssp->clk_active |= SSP_CLK_MCLK_ACTIVE;
120 
121 	return ret;
122 }
123 
ssp_mclk_disable_unprepare(struct dai * dai)124 static void ssp_mclk_disable_unprepare(struct dai *dai)
125 {
126 	struct ssp_pdata *ssp = dai_get_drvdata(dai);
127 
128 	if (!(ssp->clk_active & SSP_CLK_MCLK_ACTIVE))
129 		return;
130 
131 	mn_release_mclk(ssp->config.ssp.mclk_id);
132 
133 	ssp->clk_active &= ~SSP_CLK_MCLK_ACTIVE;
134 }
135 
ssp_bclk_prepare_enable(struct dai * dai)136 static int ssp_bclk_prepare_enable(struct dai *dai)
137 {
138 	struct ssp_pdata *ssp = dai_get_drvdata(dai);
139 	struct sof_ipc_dai_config *config = &ssp->config;
140 	uint32_t sscr0;
141 	uint32_t mdiv;
142 	bool need_ecs = false;
143 	int ret = 0;
144 
145 	if (ssp->clk_active & SSP_CLK_BCLK_ACTIVE)
146 		return 0;
147 
148 	sscr0 = ssp_read(dai, SSCR0);
149 
150 #if CONFIG_INTEL_MN
151 	/* BCLK config */
152 	ret = mn_set_bclk(config->dai_index, config->ssp.bclk_rate,
153 			  &mdiv, &need_ecs);
154 	if (ret < 0) {
155 		dai_err(dai, "ssp_bclk_prepare_enable(): invalid bclk_rate = %d for dai_index = %d",
156 			config->ssp.bclk_rate, config->dai_index);
157 		goto out;
158 	}
159 #else
160 	if (ssp_freq[SSP_DEFAULT_IDX].freq % config->ssp.bclk_rate != 0) {
161 		dai_err(dai, "ssp_bclk_prepare_enable(): invalid bclk_rate = %d for dai_index = %d",
162 			config->ssp.bclk_rate, config->dai_index);
163 		ret = -EINVAL;
164 		goto out;
165 	}
166 
167 	mdiv = ssp_freq[SSP_DEFAULT_IDX].freq / config->ssp.bclk_rate;
168 #endif
169 
170 	if (need_ecs)
171 		sscr0 |= SSCR0_ECS;
172 
173 	/* clock divisor is SCR + 1 */
174 	mdiv -= 1;
175 
176 	/* divisor must be within SCR range */
177 	if (mdiv > (SSCR0_SCR_MASK >> 8)) {
178 		dai_err(dai, "ssp_bclk_prepare_enable(): divisor %d is not within SCR range",
179 			mdiv);
180 		ret = -EINVAL;
181 		goto out;
182 	}
183 
184 	/* set the SCR divisor */
185 	sscr0 &= ~SSCR0_SCR_MASK;
186 	sscr0 |= SSCR0_SCR(mdiv);
187 
188 	ssp_write(dai, SSCR0, sscr0);
189 
190 	dai_info(dai, "ssp_bclk_prepare_enable(): sscr0 = 0x%08x", sscr0);
191 out:
192 	if (!ret)
193 		ssp->clk_active |= SSP_CLK_BCLK_ACTIVE;
194 
195 	return ret;
196 }
197 
ssp_bclk_disable_unprepare(struct dai * dai)198 static void ssp_bclk_disable_unprepare(struct dai *dai)
199 {
200 	struct ssp_pdata *ssp = dai_get_drvdata(dai);
201 
202 	if (!(ssp->clk_active & SSP_CLK_BCLK_ACTIVE))
203 		return;
204 #if CONFIG_INTEL_MN
205 	mn_release_bclk(dai->index);
206 #endif
207 	ssp->clk_active &= ~SSP_CLK_BCLK_ACTIVE;
208 }
209 
210 /* Digital Audio interface formatting */
ssp_set_config_tplg(struct dai * dai,struct ipc_config_dai * common_config,const void * spec_config)211 static int ssp_set_config_tplg(struct dai *dai, struct ipc_config_dai *common_config,
212 			       const void *spec_config)
213 {
214 	struct ssp_pdata *ssp = dai_get_drvdata(dai);
215 	const struct sof_ipc_dai_config *config = spec_config;
216 	uint32_t sscr0;
217 	uint32_t sscr1;
218 	uint32_t sscr2;
219 	uint32_t sscr3;
220 	uint32_t sspsp;
221 	uint32_t sspsp2;
222 	uint32_t sstsa;
223 	uint32_t ssrsa;
224 	uint32_t ssto;
225 	uint32_t ssioc;
226 	uint32_t bdiv;
227 	uint32_t data_size;
228 	uint32_t frame_end_padding;
229 	uint32_t slot_end_padding;
230 	uint32_t frame_len = 0;
231 	uint32_t bdiv_min;
232 	uint32_t tft;
233 	uint32_t rft;
234 	uint32_t active_tx_slots = 2;
235 	uint32_t active_rx_slots = 2;
236 	uint32_t sample_width = 2;
237 	k_spinlock_key_t key;
238 
239 	bool inverted_bclk = false;
240 	bool inverted_frame = false;
241 	bool cfs = false;
242 	bool start_delay = false;
243 
244 	int ret = 0;
245 
246 	key = k_spin_lock(&dai->lock);
247 
248 	/* ignore config if SSP is already configured */
249 	if (ssp->state[DAI_DIR_PLAYBACK] > COMP_STATE_READY ||
250 	    ssp->state[DAI_DIR_CAPTURE] > COMP_STATE_READY) {
251 		if (!memcmp(&ssp->params, &config->ssp, sizeof(ssp->params))) {
252 			dai_info(dai, "ssp_set_config(): Already configured. Ignore config");
253 			goto clk;
254 		}
255 
256 		if (ssp->clk_active & (SSP_CLK_MCLK_ACTIVE | SSP_CLK_BCLK_ACTIVE)) {
257 			dai_warn(dai, "ssp_set_config(): SSP active, cannot change config");
258 			goto clk;
259 		}
260 
261 		/* safe to proceed and change HW config */
262 	}
263 
264 	dai_info(dai, "ssp_set_config(), config->format = 0x%4x",
265 		 common_config->format);
266 
267 	/* reset SSP settings */
268 	/* sscr0 dynamic settings are DSS, EDSS, SCR, FRDC, ECS */
269 	/*
270 	 * FIXME: MOD, ACS, NCS are not set,
271 	 * no support for network mode for now
272 	 */
273 	sscr0 = SSCR0_PSP | SSCR0_RIM | SSCR0_TIM;
274 
275 	/* sscr1 dynamic settings are SFRMDIR, SCLKDIR, SCFR, RSRE, TSRE */
276 	sscr1 = SSCR1_TTE | SSCR1_TTELP | SSCR1_TRAIL;
277 
278 	/* sscr2 dynamic setting is LJDFD */
279 	sscr2 = SSCR2_SDFD | SSCR2_TURM1;
280 
281 	/* sscr3 dynamic settings are TFT, RFT */
282 	sscr3 = 0;
283 
284 	/* sspsp dynamic settings are SCMODE, SFRMP, DMYSTRT, SFRMWDTH */
285 	sspsp = 0;
286 
287 	ssp->config = *config;
288 	ssp->params = config->ssp;
289 
290 	/* sspsp2 no dynamic setting */
291 	sspsp2 = 0x0;
292 
293 	/* ssioc dynamic setting is SFCR */
294 	ssioc = SSIOC_SCOE;
295 
296 	/* ssto no dynamic setting */
297 	ssto = 0x0;
298 
299 	/* sstsa dynamic setting is TTSA, default 2 slots */
300 	sstsa = SSTSA_SSTSA(config->ssp.tx_slots);
301 
302 	/* ssrsa dynamic setting is RTSA, default 2 slots */
303 	ssrsa = SSRSA_SSRSA(config->ssp.rx_slots);
304 
305 	switch (config->format & SOF_DAI_FMT_CLOCK_PROVIDER_MASK) {
306 	case SOF_DAI_FMT_CBP_CFP:
307 		sscr1 |= SSCR1_SCLKDIR | SSCR1_SFRMDIR;
308 		break;
309 	case SOF_DAI_FMT_CBC_CFC:
310 		sscr1 |= SSCR1_SCFR;
311 		cfs = true;
312 		break;
313 	case SOF_DAI_FMT_CBP_CFC:
314 		sscr1 |= SSCR1_SCLKDIR;
315 		/* FIXME: this mode has not been tested */
316 
317 		cfs = true;
318 		break;
319 	case SOF_DAI_FMT_CBC_CFP:
320 		sscr1 |= SSCR1_SCFR | SSCR1_SFRMDIR;
321 		/* FIXME: this mode has not been tested */
322 		break;
323 	default:
324 		dai_err(dai, "ssp_set_config(): format & PROVIDER_MASK EINVAL");
325 		ret = -EINVAL;
326 		goto out;
327 	}
328 
329 	/* clock signal polarity */
330 	switch (config->format & SOF_DAI_FMT_INV_MASK) {
331 	case SOF_DAI_FMT_NB_NF:
332 		break;
333 	case SOF_DAI_FMT_NB_IF:
334 		inverted_frame = true; /* handled later with format */
335 		break;
336 	case SOF_DAI_FMT_IB_IF:
337 		inverted_bclk = true; /* handled later with bclk idle */
338 		inverted_frame = true; /* handled later with format */
339 		break;
340 	case SOF_DAI_FMT_IB_NF:
341 		inverted_bclk = true; /* handled later with bclk idle */
342 		break;
343 	default:
344 		dai_err(dai, "ssp_set_config(): format & INV_MASK EINVAL");
345 		ret = -EINVAL;
346 		goto out;
347 	}
348 
349 	/* supporting bclk idle state */
350 	if (ssp->params.clks_control &
351 		SOF_DAI_INTEL_SSP_CLKCTRL_BCLK_IDLE_HIGH) {
352 		/* bclk idle state high */
353 		sspsp |= SSPSP_SCMODE((inverted_bclk ^ 0x3) & 0x3);
354 	} else {
355 		/* bclk idle state low */
356 		sspsp |= SSPSP_SCMODE(inverted_bclk);
357 	}
358 
359 	sscr0 |= SSCR0_MOD | SSCR0_ACS;
360 
361 	/* Additional hardware settings */
362 
363 	/* Receiver Time-out Interrupt Disabled/Enabled */
364 	sscr1 |= (ssp->params.quirks & SOF_DAI_INTEL_SSP_QUIRK_TINTE) ?
365 		SSCR1_TINTE : 0;
366 
367 	/* Peripheral Trailing Byte Interrupts Disable/Enable */
368 	sscr1 |= (ssp->params.quirks & SOF_DAI_INTEL_SSP_QUIRK_PINTE) ?
369 		SSCR1_PINTE : 0;
370 
371 	/* Enable/disable internal loopback. Output of transmit serial
372 	 * shifter connected to input of receive serial shifter, internally.
373 	 */
374 	sscr1 |= (ssp->params.quirks & SOF_DAI_INTEL_SSP_QUIRK_LBM) ?
375 		SSCR1_LBM : 0;
376 
377 	/* Transmit data are driven at the same/opposite clock edge specified
378 	 * in SSPSP.SCMODE[1:0]
379 	 */
380 	sscr2 |= (ssp->params.quirks & SOF_DAI_INTEL_SSP_QUIRK_SMTATF) ?
381 		SSCR2_SMTATF : 0;
382 
383 	/* Receive data are sampled at the same/opposite clock edge specified
384 	 * in SSPSP.SCMODE[1:0]
385 	 */
386 	sscr2 |= (ssp->params.quirks & SOF_DAI_INTEL_SSP_QUIRK_MMRATF) ?
387 		SSCR2_MMRATF : 0;
388 
389 	/* Enable/disable the fix for PSP consumer mode TXD wait for frame
390 	 * de-assertion before starting the second channel
391 	 */
392 	sscr2 |= (ssp->params.quirks & SOF_DAI_INTEL_SSP_QUIRK_PSPSTWFDFD) ?
393 		SSCR2_PSPSTWFDFD : 0;
394 
395 	/* Enable/disable the fix for PSP provider mode FSRT with dummy stop &
396 	 * frame end padding capability
397 	 */
398 	sscr2 |= (ssp->params.quirks & SOF_DAI_INTEL_SSP_QUIRK_PSPSRWFDFD) ?
399 		SSCR2_PSPSRWFDFD : 0;
400 
401 	if (!config->ssp.mclk_rate ||
402 	    config->ssp.mclk_rate > ssp_freq[MAX_SSP_FREQ_INDEX].freq) {
403 		dai_err(dai, "ssp_set_config(): invalid MCLK = %d Hz (valid < %d)",
404 			config->ssp.mclk_rate,
405 			ssp_freq[MAX_SSP_FREQ_INDEX].freq);
406 		ret = -EINVAL;
407 		goto out;
408 	}
409 
410 	if (!config->ssp.bclk_rate ||
411 	    config->ssp.bclk_rate > config->ssp.mclk_rate) {
412 		dai_err(dai, "ssp_set_config(): BCLK %d Hz = 0 or > MCLK %d Hz",
413 			config->ssp.bclk_rate, config->ssp.mclk_rate);
414 		ret = -EINVAL;
415 		goto out;
416 	}
417 
418 	/* calc frame width based on BCLK and rate - must be divisable */
419 	if (config->ssp.bclk_rate % config->ssp.fsync_rate) {
420 		dai_err(dai, "ssp_set_config(): BCLK %d is not divisable by rate %d",
421 			config->ssp.bclk_rate, config->ssp.fsync_rate);
422 		ret = -EINVAL;
423 		goto out;
424 	}
425 
426 	/* must be enough BCLKs for data */
427 	bdiv = config->ssp.bclk_rate / config->ssp.fsync_rate;
428 	if (bdiv < config->ssp.tdm_slot_width * config->ssp.tdm_slots) {
429 		dai_err(dai, "ssp_set_config(): not enough BCLKs need %d",
430 			config->ssp.tdm_slot_width *
431 			config->ssp.tdm_slots);
432 		ret = -EINVAL;
433 		goto out;
434 	}
435 
436 	/* tdm_slot_width must be <= 38 for SSP */
437 	if (config->ssp.tdm_slot_width > 38) {
438 		dai_err(dai, "ssp_set_config(): tdm_slot_width %d > 38",
439 			config->ssp.tdm_slot_width);
440 		ret = -EINVAL;
441 		goto out;
442 	}
443 
444 	bdiv_min = config->ssp.tdm_slots *
445 		   (config->ssp.tdm_per_slot_padding_flag ?
446 		    config->ssp.tdm_slot_width : config->ssp.sample_valid_bits);
447 	if (bdiv < bdiv_min) {
448 		dai_err(dai, "ssp_set_config(): bdiv(%d) < bdiv_min(%d)",
449 			bdiv, bdiv_min);
450 		ret = -EINVAL;
451 		goto out;
452 	}
453 
454 	frame_end_padding = bdiv - bdiv_min;
455 	if (frame_end_padding > SSPSP2_FEP_MASK) {
456 		dai_err(dai, "ssp_set_config(): frame_end_padding too big: %u",
457 			frame_end_padding);
458 		ret = -EINVAL;
459 		goto out;
460 	}
461 
462 	/* format */
463 	switch (config->format & SOF_DAI_FMT_FORMAT_MASK) {
464 	case SOF_DAI_FMT_I2S:
465 
466 		start_delay = true;
467 
468 		sscr0 |= SSCR0_FRDC(config->ssp.tdm_slots);
469 
470 		if (bdiv % 2) {
471 			dai_err(dai, "ssp_set_config(): bdiv %d is not divisible by 2",
472 				bdiv);
473 			ret = -EINVAL;
474 			goto out;
475 		}
476 
477 		/* set asserted frame length to half frame length */
478 		frame_len = bdiv / 2;
479 
480 		/*
481 		 * handle frame polarity, I2S default is falling/active low,
482 		 * non-inverted(inverted_frame=0) -- active low(SFRMP=0),
483 		 * inverted(inverted_frame=1) -- rising/active high(SFRMP=1),
484 		 * so, we should set SFRMP to inverted_frame.
485 		 */
486 		sspsp |= SSPSP_SFRMP(inverted_frame);
487 
488 		/*
489 		 *  for I2S/LEFT_J, the padding has to happen at the end
490 		 * of each slot
491 		 */
492 		if (frame_end_padding % 2) {
493 			dai_err(dai, "ssp_set_config(): frame_end_padding %d is not divisible by 2",
494 				frame_end_padding);
495 			ret = -EINVAL;
496 			goto out;
497 		}
498 
499 		slot_end_padding = frame_end_padding / 2;
500 
501 		if (slot_end_padding > SOF_DAI_INTEL_SSP_SLOT_PADDING_MAX) {
502 			/* too big padding */
503 			dai_err(dai, "ssp_set_config(): slot_end_padding > %d",
504 				SOF_DAI_INTEL_SSP_SLOT_PADDING_MAX);
505 			ret = -EINVAL;
506 			goto out;
507 		}
508 
509 		sspsp |= SSPSP_DMYSTOP(slot_end_padding);
510 		slot_end_padding >>= SSPSP_DMYSTOP_BITS;
511 		sspsp |= SSPSP_EDMYSTOP(slot_end_padding);
512 
513 		break;
514 
515 	case SOF_DAI_FMT_LEFT_J:
516 
517 		/* default start_delay value is set to false */
518 
519 		sscr0 |= SSCR0_FRDC(config->ssp.tdm_slots);
520 
521 		/* LJDFD enable */
522 		sscr2 &= ~SSCR2_LJDFD;
523 
524 		if (bdiv % 2) {
525 			dai_err(dai, "ssp_set_config(): bdiv %d is not divisible by 2",
526 				bdiv);
527 			ret = -EINVAL;
528 			goto out;
529 		}
530 
531 		/* set asserted frame length to half frame length */
532 		frame_len = bdiv / 2;
533 
534 		/*
535 		 * handle frame polarity, LEFT_J default is rising/active high,
536 		 * non-inverted(inverted_frame=0) -- active high(SFRMP=1),
537 		 * inverted(inverted_frame=1) -- falling/active low(SFRMP=0),
538 		 * so, we should set SFRMP to !inverted_frame.
539 		 */
540 		sspsp |= SSPSP_SFRMP(!inverted_frame);
541 
542 		/*
543 		 *  for I2S/LEFT_J, the padding has to happen at the end
544 		 * of each slot
545 		 */
546 		if (frame_end_padding % 2) {
547 			dai_err(dai, "ssp_set_config(): frame_end_padding %d is not divisible by 2",
548 				frame_end_padding);
549 			ret = -EINVAL;
550 			goto out;
551 		}
552 
553 		slot_end_padding = frame_end_padding / 2;
554 
555 		if (slot_end_padding > 15) {
556 			/* can't handle padding over 15 bits */
557 			dai_err(dai, "ssp_set_config(): slot_end_padding %d > 15 bits",
558 				slot_end_padding);
559 			ret = -EINVAL;
560 			goto out;
561 		}
562 
563 		sspsp |= SSPSP_DMYSTOP(slot_end_padding);
564 		slot_end_padding >>= SSPSP_DMYSTOP_BITS;
565 		sspsp |= SSPSP_EDMYSTOP(slot_end_padding);
566 
567 		break;
568 	case SOF_DAI_FMT_DSP_A:
569 
570 		start_delay = true;
571 
572 		/* fallthrough */
573 
574 	case SOF_DAI_FMT_DSP_B:
575 
576 		/* default start_delay value is set to false */
577 
578 		sscr0 |= SSCR0_MOD | SSCR0_FRDC(config->ssp.tdm_slots);
579 
580 		/* set asserted frame length */
581 		frame_len = 1; /* default */
582 
583 		if (cfs && ssp->params.frame_pulse_width > 0 &&
584 		    ssp->params.frame_pulse_width <=
585 		    SOF_DAI_INTEL_SSP_FRAME_PULSE_WIDTH_MAX) {
586 			frame_len = ssp->params.frame_pulse_width;
587 		}
588 
589 		/* frame_pulse_width must less or equal 38 */
590 		if (ssp->params.frame_pulse_width >
591 			SOF_DAI_INTEL_SSP_FRAME_PULSE_WIDTH_MAX) {
592 			dai_err(dai, "ssp_set_config(): frame_pulse_width > %d",
593 				SOF_DAI_INTEL_SSP_FRAME_PULSE_WIDTH_MAX);
594 			ret = -EINVAL;
595 			goto out;
596 		}
597 		/*
598 		 * handle frame polarity, DSP_B default is rising/active high,
599 		 * non-inverted(inverted_frame=0) -- active high(SFRMP=1),
600 		 * inverted(inverted_frame=1) -- falling/active low(SFRMP=0),
601 		 * so, we should set SFRMP to !inverted_frame.
602 		 */
603 		sspsp |= SSPSP_SFRMP(!inverted_frame);
604 
605 		active_tx_slots = popcount(config->ssp.tx_slots);
606 		active_rx_slots = popcount(config->ssp.rx_slots);
607 
608 		/*
609 		 * handle TDM mode, TDM mode has padding at the end of
610 		 * each slot. The amount of padding is equal to result of
611 		 * subtracting slot width and valid bits per slot.
612 		 */
613 		if (ssp->params.tdm_per_slot_padding_flag) {
614 			frame_end_padding = bdiv - config->ssp.tdm_slots *
615 				config->ssp.tdm_slot_width;
616 
617 			slot_end_padding = config->ssp.tdm_slot_width -
618 				config->ssp.sample_valid_bits;
619 
620 			if (slot_end_padding >
621 				SOF_DAI_INTEL_SSP_SLOT_PADDING_MAX) {
622 				dai_err(dai, "ssp_set_config(): slot_end_padding > %d",
623 					SOF_DAI_INTEL_SSP_SLOT_PADDING_MAX);
624 				ret = -EINVAL;
625 				goto out;
626 			}
627 
628 			sspsp |= SSPSP_DMYSTOP(slot_end_padding);
629 			slot_end_padding >>= SSPSP_DMYSTOP_BITS;
630 			sspsp |= SSPSP_EDMYSTOP(slot_end_padding);
631 		}
632 
633 		sspsp2 |= (frame_end_padding & SSPSP2_FEP_MASK);
634 
635 		break;
636 	default:
637 		dai_err(dai, "ssp_set_config(): invalid format 0x%04x",
638 			config->format);
639 		ret = -EINVAL;
640 		goto out;
641 	}
642 
643 	if (start_delay)
644 		sspsp |= SSPSP_FSRT;
645 
646 	sspsp |= SSPSP_SFRMWDTH(frame_len);
647 
648 	data_size = config->ssp.sample_valid_bits;
649 
650 	if (data_size > 16)
651 		sscr0 |= (SSCR0_EDSS | SSCR0_DSIZE(data_size - 16));
652 	else
653 		sscr0 |= SSCR0_DSIZE(data_size);
654 
655 	/* setting TFT and RFT */
656 	switch (config->ssp.sample_valid_bits) {
657 	case 16:
658 			/* use 2 bytes for each slot */
659 			sample_width = 2;
660 			break;
661 	case 24:
662 	case 32:
663 			/* use 4 bytes for each slot */
664 			sample_width = 4;
665 			break;
666 	default:
667 			dai_err(dai, "ssp_set_config(): sample_valid_bits %d",
668 				config->ssp.sample_valid_bits);
669 			ret = -EINVAL;
670 			goto out;
671 	}
672 
673 	tft = MIN(SSP_FIFO_DEPTH - SSP_FIFO_WATERMARK,
674 		  sample_width * active_tx_slots);
675 	rft = MIN(SSP_FIFO_DEPTH - SSP_FIFO_WATERMARK,
676 		  sample_width * active_rx_slots);
677 
678 	sscr3 |= SSCR3_TX(tft) | SSCR3_RX(rft);
679 
680 	ssp_write(dai, SSCR0, sscr0);
681 	ssp_write(dai, SSCR1, sscr1);
682 	ssp_write(dai, SSCR2, sscr2);
683 	ssp_write(dai, SSCR3, sscr3);
684 	ssp_write(dai, SSPSP, sspsp);
685 	ssp_write(dai, SSPSP2, sspsp2);
686 	ssp_write(dai, SSIOC, ssioc);
687 	ssp_write(dai, SSTO, ssto);
688 	ssp_write(dai, SSTSA, sstsa);
689 	ssp_write(dai, SSRSA, ssrsa);
690 
691 	dai_info(dai, "ssp_set_config(), sscr0 = 0x%08x, sscr1 = 0x%08x, ssto = 0x%08x, sspsp = 0x%0x",
692 		 sscr0, sscr1, ssto, sspsp);
693 	dai_info(dai, "ssp_set_config(), sscr2 = 0x%08x, sspsp2 = 0x%08x, sscr3 = 0x%08x, ssioc = 0x%08x",
694 		 sscr2, sspsp2, sscr3, ssioc);
695 	dai_info(dai, "ssp_set_config(), ssrsa = 0x%08x, sstsa = 0x%08x",
696 		 ssrsa, sstsa);
697 
698 	ssp->state[DAI_DIR_PLAYBACK] = COMP_STATE_PREPARE;
699 	ssp->state[DAI_DIR_CAPTURE] = COMP_STATE_PREPARE;
700 
701 clk:
702 	/* MCLK always-on: turn on mclk and never turn it off */
703 	if (ssp->params.clks_control & SOF_DAI_INTEL_SSP_CLKCTRL_MCLK_AON) {
704 		ret = ssp_mclk_prepare_enable(dai);
705 		if (ret < 0)
706 			goto out;
707 
708 		ssp->clk_active |= SSP_CLK_MCLK_AON_REQ;
709 
710 		dai_info(dai, "ssp_set_config(): enable MCLK for SSP%d", dai->index);
711 	}
712 
713 	switch (config->flags & SOF_DAI_CONFIG_FLAGS_CMD_MASK) {
714 	case SOF_DAI_CONFIG_FLAGS_HW_PARAMS:
715 		if (ssp->params.clks_control & SOF_DAI_INTEL_SSP_CLKCTRL_MCLK_ES) {
716 			ret = ssp_mclk_prepare_enable(dai);
717 			if (ret < 0)
718 				goto out;
719 
720 			ssp->clk_active |= SSP_CLK_MCLK_ES_REQ;
721 
722 			dai_info(dai, "ssp_set_config(): hw_params stage: enabled MCLK clocks for SSP%d...",
723 				 dai->index);
724 		}
725 
726 		if (ssp->params.clks_control & SOF_DAI_INTEL_SSP_CLKCTRL_BCLK_ES) {
727 			bool enable_sse = false;
728 
729 			if (!(ssp->clk_active & SSP_CLK_BCLK_ACTIVE))
730 				enable_sse = true;
731 
732 			ret = ssp_bclk_prepare_enable(dai);
733 			if (ret < 0)
734 				goto out;
735 
736 			ssp->clk_active |= SSP_CLK_BCLK_ES_REQ;
737 
738 			if (enable_sse) {
739 
740 				/* enable TRSE/RSRE before SSE */
741 				ssp_update_bits(dai, SSCR1,
742 						SSCR1_TSRE | SSCR1_RSRE,
743 						SSCR1_TSRE | SSCR1_RSRE);
744 
745 				/* enable port */
746 				ssp_update_bits(dai, SSCR0, SSCR0_SSE, SSCR0_SSE);
747 
748 				dai_info(dai, "ssp_set_config(): SSE set for SSP%d", dai->index);
749 			}
750 
751 			dai_info(dai, "ssp_set_config(): hw_params stage: enabled BCLK clocks for SSP%d...",
752 				 dai->index);
753 		}
754 		break;
755 	case SOF_DAI_CONFIG_FLAGS_HW_FREE:
756 		/* disable SSP port if no users */
757 		if (ssp->state[SOF_IPC_STREAM_CAPTURE] != COMP_STATE_PREPARE ||
758 		    ssp->state[SOF_IPC_STREAM_PLAYBACK] != COMP_STATE_PREPARE) {
759 			dai_info(dai, "ssp_set_config(): hw_free stage: ignore since SSP%d still in use",
760 				 dai->index);
761 			break;
762 		}
763 
764 		if (ssp->params.clks_control & SOF_DAI_INTEL_SSP_CLKCTRL_BCLK_ES) {
765 			dai_info(dai, "ssp_set_config(): hw_free stage: releasing BCLK clocks for SSP%d...",
766 				 dai->index);
767 			if (ssp->clk_active & SSP_CLK_BCLK_ACTIVE) {
768 				/* clear TRSE/RSRE before SSE */
769 				ssp_update_bits(dai, SSCR1,
770 						SSCR1_TSRE | SSCR1_RSRE,
771 						0);
772 
773 				ssp_update_bits(dai, SSCR0, SSCR0_SSE, 0);
774 				dai_info(dai, "ssp_set_config(): SSE clear for SSP%d", dai->index);
775 			}
776 			ssp_bclk_disable_unprepare(dai);
777 			ssp->clk_active &= ~SSP_CLK_BCLK_ES_REQ;
778 		}
779 		if (ssp->params.clks_control & SOF_DAI_INTEL_SSP_CLKCTRL_MCLK_ES) {
780 			dai_info(dai, "ssp_set_config: hw_free stage: releasing MCLK clocks for SSP%d...",
781 				 dai->index);
782 			ssp_mclk_disable_unprepare(dai);
783 			ssp->clk_active &= ~SSP_CLK_MCLK_ES_REQ;
784 		}
785 		break;
786 	default:
787 		break;
788 	}
789 out:
790 
791 	k_spin_unlock(&dai->lock, key);
792 
793 	return ret;
794 }
795 
ssp_set_config_blob(struct dai * dai,struct ipc_config_dai * common_config,const void * spec_config)796 static int ssp_set_config_blob(struct dai *dai, struct ipc_config_dai *common_config,
797 			       const void *spec_config)
798 {
799 	const struct ipc4_ssp_configuration_blob *blob = spec_config;
800 	struct ssp_pdata *ssp = dai_get_drvdata(dai);
801 	uint32_t ssc0, sstsa, ssrsa;
802 
803 	/* set config only once for playback or capture */
804 	if (dai->sref > 1)
805 		return 0;
806 
807 	ssc0 = blob->i2s_driver_config.i2s_config.ssc0;
808 	sstsa = blob->i2s_driver_config.i2s_config.sstsa;
809 	ssrsa = blob->i2s_driver_config.i2s_config.ssrsa;
810 
811 	ssp_write(dai, SSCR0, ssc0);
812 	ssp_write(dai, SSCR1, blob->i2s_driver_config.i2s_config.ssc1);
813 	ssp_write(dai, SSCR2, blob->i2s_driver_config.i2s_config.ssc2);
814 	ssp_write(dai, SSCR3, blob->i2s_driver_config.i2s_config.ssc3);
815 	ssp_write(dai, SSPSP, blob->i2s_driver_config.i2s_config.sspsp);
816 	ssp_write(dai, SSPSP2, blob->i2s_driver_config.i2s_config.sspsp2);
817 	ssp_write(dai, SSIOC, blob->i2s_driver_config.i2s_config.ssioc);
818 	ssp_write(dai, SSTO, blob->i2s_driver_config.i2s_config.sscto);
819 	ssp_write(dai, SSTSA, sstsa);
820 	ssp_write(dai, SSRSA, ssrsa);
821 
822 	dai_info(dai, "ssp_set_config(), sscr0 = 0x%08x, sscr1 = 0x%08x, ssto = 0x%08x, sspsp = 0x%0x",
823 		 ssc0, blob->i2s_driver_config.i2s_config.ssc1,
824 		 blob->i2s_driver_config.i2s_config.sscto,
825 		 blob->i2s_driver_config.i2s_config.sspsp);
826 	dai_info(dai, "ssp_set_config(), sscr2 = 0x%08x, sspsp2 = 0x%08x, sscr3 = 0x%08x",
827 		 blob->i2s_driver_config.i2s_config.ssc2, blob->i2s_driver_config.i2s_config.sspsp2,
828 		 blob->i2s_driver_config.i2s_config.ssc3);
829 	dai_err(dai, "ssp_set_config(), ssioc = 0x%08x, ssrsa = 0x%08x, sstsa = 0x%08x",
830 		blob->i2s_driver_config.i2s_config.ssioc, ssrsa, sstsa);
831 
832 	ssp->config.ssp.sample_valid_bits = SSCR0_DSIZE_GET(ssc0);
833 	if (ssc0 & SSCR0_EDSS)
834 		ssp->config.ssp.sample_valid_bits += 16;
835 
836 	ssp->config.ssp.tdm_slots = SSCR0_FRDC_GET(ssc0);
837 	ssp->config.ssp.tx_slots = SSTSA_GET(sstsa);
838 	ssp->config.ssp.rx_slots = SSRSA_GET(ssrsa);
839 	ssp->config.ssp.fsync_rate = common_config->sampling_frequency;
840 	ssp->params = ssp->config.ssp;
841 
842 	ssp->state[DAI_DIR_PLAYBACK] = COMP_STATE_PREPARE;
843 	ssp->state[DAI_DIR_CAPTURE] = COMP_STATE_PREPARE;
844 
845 	/* ssp blob is set by pcm_hw_params for ipc4 stream, so enable
846 	 * mclk and bclk at this time.
847 	 */
848 	mn_set_mclk_blob(blob->i2s_driver_config.mclk_config.mdivc,
849 			 blob->i2s_driver_config.mclk_config.mdivr);
850 	ssp->clk_active |= SSP_CLK_MCLK_ES_REQ;
851 
852 	/* enable TRSE/RSRE before SSE */
853 	ssp_update_bits(dai, SSCR1, SSCR1_TSRE | SSCR1_RSRE, SSCR1_TSRE | SSCR1_RSRE);
854 
855 	/* enable port */
856 	ssp_update_bits(dai, SSCR0, SSCR0_SSE, SSCR0_SSE);
857 	ssp->clk_active |= SSP_CLK_BCLK_ES_REQ;
858 
859 	return 0;
860 }
861 
ssp_set_config(struct dai * dai,struct ipc_config_dai * common_config,const void * spec_config)862 static int ssp_set_config(struct dai *dai, struct ipc_config_dai *common_config,
863 			  const void *spec_config)
864 {
865 	if (!common_config->is_config_blob)
866 		return ssp_set_config_tplg(dai, common_config, spec_config);
867 	else
868 		return ssp_set_config_blob(dai, common_config, spec_config);
869 }
870 
871 /*
872  * Portion of the SSP configuration should be applied just before the
873  * SSP dai is activated, for either power saving or params runtime
874  * configurable flexibility.
875  */
ssp_pre_start(struct dai * dai)876 static int ssp_pre_start(struct dai *dai)
877 {
878 	struct ssp_pdata *ssp = dai_get_drvdata(dai);
879 	int ret = 0;
880 
881 	dai_info(dai, "ssp_pre_start()");
882 
883 	/*
884 	 * We will test if mclk/bclk is configured in
885 	 * ssp_mclk/bclk_prepare_enable/disable functions
886 	 */
887 	if (!(ssp->clk_active & SSP_CLK_MCLK_ES_REQ) &&
888 	    !(ssp->clk_active & SSP_CLK_MCLK_AON_REQ)) {
889 		/* MCLK config */
890 		ret = ssp_mclk_prepare_enable(dai);
891 		if (ret < 0)
892 			return ret;
893 	}
894 
895 	if (!(ssp->clk_active & SSP_CLK_BCLK_ES_REQ))
896 		ret = ssp_bclk_prepare_enable(dai);
897 
898 	return ret;
899 }
900 
901 /*
902  * For power saving, we should do kinds of power release when the SSP
903  * dai is changed to inactive, though the runtime param configuration
904  * don't have to be reset.
905  */
ssp_post_stop(struct dai * dai)906 static void ssp_post_stop(struct dai *dai)
907 {
908 	struct ssp_pdata *ssp = dai_get_drvdata(dai);
909 
910 	/* release clocks if SSP is inactive */
911 	if (ssp->state[SOF_IPC_STREAM_PLAYBACK] != COMP_STATE_ACTIVE &&
912 	    ssp->state[SOF_IPC_STREAM_CAPTURE] != COMP_STATE_ACTIVE) {
913 		if (!(ssp->clk_active & SSP_CLK_BCLK_ES_REQ)) {
914 			dai_info(dai, "ssp_post_stop releasing BCLK clocks for SSP%d...",
915 				 dai->index);
916 			ssp_bclk_disable_unprepare(dai);
917 		}
918 		if (!(ssp->clk_active & SSP_CLK_MCLK_ES_REQ) &&
919 		    !(ssp->clk_active & SSP_CLK_MCLK_AON_REQ)) {
920 			dai_info(dai, "ssp_post_stop releasing MCLK clocks for SSP%d...",
921 				 dai->index);
922 			ssp_mclk_disable_unprepare(dai);
923 		}
924 	}
925 }
926 
927 /* get SSP hw params */
ssp_get_hw_params(struct dai * dai,struct sof_ipc_stream_params * params,int dir)928 static int ssp_get_hw_params(struct dai *dai,
929 			     struct sof_ipc_stream_params  *params, int dir)
930 {
931 	struct ssp_pdata *ssp = dai_get_drvdata(dai);
932 
933 	params->rate = ssp->params.fsync_rate;
934 	params->buffer_fmt = 0;
935 
936 	if (dir == SOF_IPC_STREAM_PLAYBACK)
937 		params->channels = popcount(ssp->params.tx_slots);
938 	else
939 		params->channels = popcount(ssp->params.rx_slots);
940 
941 	switch (ssp->params.sample_valid_bits) {
942 	case 16:
943 		params->frame_fmt = SOF_IPC_FRAME_S16_LE;
944 		break;
945 	case 24:
946 		params->frame_fmt = SOF_IPC_FRAME_S24_4LE;
947 		break;
948 	case 32:
949 		params->frame_fmt = SOF_IPC_FRAME_S32_LE;
950 		break;
951 	default:
952 		dai_err(dai, "ssp_get_hw_params(): not supported format");
953 		return -EINVAL;
954 	}
955 
956 	return 0;
957 }
958 
ssp_early_start(struct dai * dai,int direction)959 static void ssp_early_start(struct dai *dai, int direction)
960 {
961 	struct ssp_pdata *ssp = dai_get_drvdata(dai);
962 	k_spinlock_key_t key;
963 
964 	key = k_spin_lock(&dai->lock);
965 
966 	/* request mclk/bclk */
967 	ssp_pre_start(dai);
968 
969 	if (!(ssp->clk_active & SSP_CLK_BCLK_ES_REQ)) {
970 		/* enable TRSE/RSRE before SSE */
971 		ssp_update_bits(dai, SSCR1,
972 				SSCR1_TSRE | SSCR1_RSRE,
973 				SSCR1_TSRE | SSCR1_RSRE);
974 
975 		/* enable port */
976 		ssp_update_bits(dai, SSCR0, SSCR0_SSE, SSCR0_SSE);
977 		dai_info(dai, "ssp_early_start(): SSE set for SSP%d", dai->index);
978 	}
979 
980 
981 	k_spin_unlock(&dai->lock, key);
982 }
983 
984 /* start the SSP for either playback or capture */
ssp_start(struct dai * dai,int direction)985 static void ssp_start(struct dai *dai, int direction)
986 {
987 	struct ssp_pdata *ssp = dai_get_drvdata(dai);
988 	k_spinlock_key_t key;
989 
990 	key = k_spin_lock(&dai->lock);
991 
992 	dai_info(dai, "ssp_start()");
993 
994 	/* enable DMA */
995 	if (direction == DAI_DIR_PLAYBACK)
996 		ssp_update_bits(dai, SSTSA, SSTSA_TXEN, SSTSA_TXEN);
997 	else
998 		ssp_update_bits(dai, SSRSA, SSRSA_RXEN, SSRSA_RXEN);
999 
1000 	ssp->state[direction] = COMP_STATE_ACTIVE;
1001 
1002 	/*
1003 	 * Wait to get valid fifo status in clock consumer mode. TODO it's
1004 	 * uncertain which SSP clock consumer modes need the delay atm, but
1005 	 * these can be added here when confirmed.
1006 	 */
1007 	switch (ssp->config.format & SOF_DAI_FMT_CLOCK_PROVIDER_MASK) {
1008 	case SOF_DAI_FMT_CBC_CFC:
1009 		break;
1010 	default:
1011 		/* delay for all SSP consumed clocks atm - see above */
1012 		wait_delay(PLATFORM_SSP_DELAY);
1013 		break;
1014 	}
1015 
1016 	k_spin_unlock(&dai->lock, key);
1017 }
1018 
1019 /* stop the SSP for either playback or capture */
ssp_stop(struct dai * dai,int direction)1020 static void ssp_stop(struct dai *dai, int direction)
1021 {
1022 	struct ssp_pdata *ssp = dai_get_drvdata(dai);
1023 	k_spinlock_key_t key;
1024 
1025 	key = k_spin_lock(&dai->lock);
1026 
1027 	/*
1028 	 * Wait to get valid fifo status in clock consumer mode. TODO it's
1029 	 * uncertain which SSP clock consumer modes need the delay atm, but
1030 	 * these can be added here when confirmed.
1031 	 */
1032 	switch (ssp->config.format & SOF_DAI_FMT_CLOCK_PROVIDER_MASK) {
1033 	case SOF_DAI_FMT_CBC_CFC:
1034 		break;
1035 	default:
1036 		/* delay for all SSP consumed clocks atm - see above */
1037 		wait_delay(PLATFORM_SSP_DELAY);
1038 		break;
1039 	}
1040 
1041 	/* stop Rx if neeed */
1042 	if (direction == DAI_DIR_CAPTURE &&
1043 	    ssp->state[SOF_IPC_STREAM_CAPTURE] != COMP_STATE_PREPARE) {
1044 		ssp_update_bits(dai, SSRSA, SSRSA_RXEN, 0);
1045 		ssp_empty_rx_fifo(dai);
1046 		ssp->state[SOF_IPC_STREAM_CAPTURE] = COMP_STATE_PREPARE;
1047 		dai_info(dai, "ssp_stop(), RX stop");
1048 	}
1049 
1050 	/* stop Tx if needed */
1051 	if (direction == DAI_DIR_PLAYBACK &&
1052 	    ssp->state[SOF_IPC_STREAM_PLAYBACK] != COMP_STATE_PREPARE) {
1053 		ssp_empty_tx_fifo(dai);
1054 		ssp_update_bits(dai, SSTSA, SSTSA_TXEN, 0);
1055 		ssp->state[SOF_IPC_STREAM_PLAYBACK] = COMP_STATE_PREPARE;
1056 		dai_info(dai, "ssp_stop(), TX stop");
1057 	}
1058 
1059 	/* disable SSP port if no users */
1060 	if (ssp->state[SOF_IPC_STREAM_CAPTURE] == COMP_STATE_PREPARE &&
1061 	    ssp->state[SOF_IPC_STREAM_PLAYBACK] == COMP_STATE_PREPARE) {
1062 		if (!(ssp->clk_active & SSP_CLK_BCLK_ES_REQ)) {
1063 			/* clear TRSE/RSRE before SSE */
1064 			ssp_update_bits(dai, SSCR1,
1065 					SSCR1_TSRE | SSCR1_RSRE,
1066 					0);
1067 
1068 			ssp_update_bits(dai, SSCR0, SSCR0_SSE, 0);
1069 			dai_info(dai, "ssp_stop(): SSE clear SSP%d", dai->index);
1070 		}
1071 	}
1072 
1073 	ssp_post_stop(dai);
1074 
1075 	k_spin_unlock(&dai->lock, key);
1076 }
1077 
ssp_pause(struct dai * dai,int direction)1078 static void ssp_pause(struct dai *dai, int direction)
1079 {
1080 	struct ssp_pdata *ssp = dai_get_drvdata(dai);
1081 
1082 	if (direction == SOF_IPC_STREAM_CAPTURE)
1083 		dai_info(dai, "ssp_pause(), RX");
1084 	else
1085 		dai_info(dai, "ssp_pause(), TX");
1086 
1087 	ssp->state[direction] = COMP_STATE_PAUSED;
1088 }
1089 
ssp_trigger(struct dai * dai,int cmd,int direction)1090 static int ssp_trigger(struct dai *dai, int cmd, int direction)
1091 {
1092 	struct ssp_pdata *ssp = dai_get_drvdata(dai);
1093 
1094 	dai_info(dai, "ssp_trigger() cmd %d", cmd);
1095 
1096 	switch (cmd) {
1097 	case COMP_TRIGGER_START:
1098 	case COMP_TRIGGER_RELEASE:
1099 		if (ssp->state[direction] == COMP_STATE_PAUSED ||
1100 		    ssp->state[direction] == COMP_STATE_PREPARE)
1101 			ssp_start(dai, direction);
1102 		break;
1103 	case COMP_TRIGGER_STOP:
1104 		ssp_stop(dai, direction);
1105 		break;
1106 	case COMP_TRIGGER_PAUSE:
1107 		ssp_pause(dai, direction);
1108 		break;
1109 	case COMP_TRIGGER_PRE_START:
1110 	case COMP_TRIGGER_PRE_RELEASE:
1111 		ssp_early_start(dai, direction);
1112 		break;
1113 	}
1114 
1115 	return 0;
1116 }
1117 
ssp_probe(struct dai * dai)1118 static int ssp_probe(struct dai *dai)
1119 {
1120 	struct ssp_pdata *ssp;
1121 
1122 	if (dai_get_drvdata(dai))
1123 		return -EEXIST; /* already created */
1124 
1125 	/* allocate private data */
1126 	ssp = rzalloc(SOF_MEM_ZONE_RUNTIME_SHARED, 0, SOF_MEM_CAPS_RAM, sizeof(*ssp));
1127 	if (!ssp) {
1128 		dai_err(dai, "ssp_probe(): alloc failed");
1129 		return -ENOMEM;
1130 	}
1131 	dai_set_drvdata(dai, ssp);
1132 
1133 	ssp->state[DAI_DIR_PLAYBACK] = COMP_STATE_READY;
1134 	ssp->state[DAI_DIR_CAPTURE] = COMP_STATE_READY;
1135 
1136 #if CONFIG_INTEL_MN
1137 	/* Reset M/N, power-gating functions need it */
1138 	mn_reset_bclk_divider(dai->index);
1139 #endif
1140 
1141 	/* Enable SSP power */
1142 	pm_runtime_get_sync(SSP_POW, dai->index);
1143 
1144 	/* Disable dynamic clock gating before touching any register */
1145 	pm_runtime_get_sync(SSP_CLK, dai->index);
1146 
1147 	ssp_empty_rx_fifo(dai);
1148 
1149 	return 0;
1150 }
1151 
ssp_remove(struct dai * dai)1152 static int ssp_remove(struct dai *dai)
1153 {
1154 	pm_runtime_put_sync(SSP_CLK, dai->index);
1155 
1156 	ssp_mclk_disable_unprepare(dai);
1157 	ssp_bclk_disable_unprepare(dai);
1158 
1159 	/* Disable SSP power */
1160 	pm_runtime_put_sync(SSP_POW, dai->index);
1161 
1162 	rfree(dai_get_drvdata(dai));
1163 	dai_set_drvdata(dai, NULL);
1164 
1165 	return 0;
1166 }
1167 
ssp_get_handshake(struct dai * dai,int direction,int stream_id)1168 static int ssp_get_handshake(struct dai *dai, int direction, int stream_id)
1169 {
1170 	return dai->plat_data.fifo[direction].handshake;
1171 }
1172 
ssp_get_fifo(struct dai * dai,int direction,int stream_id)1173 static int ssp_get_fifo(struct dai *dai, int direction, int stream_id)
1174 {
1175 	return dai->plat_data.fifo[direction].offset;
1176 }
1177 
ssp_get_init_delay_ms(struct dai * dai)1178 static uint32_t ssp_get_init_delay_ms(struct dai *dai)
1179 {
1180 	struct ssp_pdata *ssp = dai_get_drvdata(dai);
1181 
1182 	if (ssp->clk_active & SSP_CLK_BCLK_ACTIVE)
1183 		return 0;
1184 
1185 	/* drive BCLK early for guaranteed time,
1186 	 * before first FSYNC, it is required by some codecs
1187 	 */
1188 	return ssp->params.bclk_delay;
1189 }
1190 
1191 const struct dai_driver ssp_driver = {
1192 	.type = SOF_DAI_INTEL_SSP,
1193 	.uid = SOF_UUID(ssp_uuid),
1194 	.tctx = &ssp_tr,
1195 	.dma_caps = DMA_CAP_GP_LP | DMA_CAP_GP_HP,
1196 	.dma_dev = DMA_DEV_SSP,
1197 	.ops = {
1198 		.trigger		= ssp_trigger,
1199 		.set_config		= ssp_set_config,
1200 		.get_hw_params		= ssp_get_hw_params,
1201 		.get_handshake		= ssp_get_handshake,
1202 		.get_fifo		= ssp_get_fifo,
1203 		.get_init_delay_ms	= ssp_get_init_delay_ms,
1204 		.probe			= ssp_probe,
1205 		.remove			= ssp_remove,
1206 	},
1207 	.ts_ops = {
1208 		.ts_config		= timestamp_ssp_config,
1209 		.ts_start		= timestamp_ssp_start,
1210 		.ts_get			= timestamp_ssp_get,
1211 		.ts_stop		= timestamp_ssp_stop,
1212 	},
1213 };
1214