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