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