1 // SPDX-License-Identifier: BSD-3-Clause
2 //
3 // Copyright(c) 2018 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 
8 #include <sof/audio/component.h>
9 #include <sof/drivers/ssp.h>
10 #include <sof/lib/alloc.h>
11 #include <sof/lib/dai.h>
12 #include <sof/lib/dma.h>
13 #include <sof/lib/shim.h>
14 #include <sof/spinlock.h>
15 #include <sof/trace/trace.h>
16 #include <ipc/dai.h>
17 #include <ipc/dai-intel.h>
18 #include <ipc/stream.h>
19 #include <ipc/topology.h>
20 #include <user/trace.h>
21 #include <errno.h>
22 #include <stdbool.h>
23 #include <stdint.h>
24 
25 /* save SSP context prior to entering D3 */
ssp_context_store(struct dai * dai)26 static int ssp_context_store(struct dai *dai)
27 {
28 	struct ssp_pdata *ssp = dai_get_drvdata(dai);
29 
30 	ssp->sscr0 = ssp_read(dai, SSCR0);
31 	ssp->sscr1 = ssp_read(dai, SSCR1);
32 
33 	/* FIXME: need to store sscr2,3,4,5 */
34 	ssp->psp = ssp_read(dai, SSPSP);
35 
36 	return 0;
37 }
38 
39 /* restore SSP context after leaving D3 */
ssp_context_restore(struct dai * dai)40 static int ssp_context_restore(struct dai *dai)
41 {
42 	struct ssp_pdata *ssp = dai_get_drvdata(dai);
43 
44 	ssp_write(dai, SSCR0, ssp->sscr0);
45 	ssp_write(dai, SSCR1, ssp->sscr1);
46 	/* FIXME: need to restore sscr2,3,4,5 */
47 	ssp_write(dai, SSPSP, ssp->psp);
48 
49 	return 0;
50 }
51 
52 /* Digital Audio interface formatting */
ssp_set_config(struct dai * dai,struct ipc_config_dai * common_config,void * spec_config)53 static int ssp_set_config(struct dai *dai, struct ipc_config_dai *common_config,
54 			  void *spec_config)
55 {
56 	struct sof_ipc_dai_config *config = spec_config;
57 	struct ssp_pdata *ssp = dai_get_drvdata(dai);
58 	uint32_t sscr0;
59 	uint32_t sscr1;
60 	uint32_t sscr2;
61 	uint32_t sspsp;
62 	uint32_t sspsp2;
63 	uint32_t mdiv;
64 	uint32_t bdiv;
65 	uint32_t data_size;
66 	uint32_t start_delay;
67 	uint32_t frame_end_padding;
68 	uint32_t slot_end_padding;
69 	uint32_t frame_len = 0;
70 	uint32_t bdiv_min;
71 	uint32_t format;
72 	bool inverted_frame = false;
73 	int ret = 0;
74 
75 	spin_lock(&dai->lock);
76 
77 	/* is playback/capture already running */
78 	if (ssp->state[DAI_DIR_PLAYBACK] == COMP_STATE_ACTIVE ||
79 	    ssp->state[DAI_DIR_CAPTURE] == COMP_STATE_ACTIVE) {
80 		dai_info(dai, "ssp_set_config(): playback/capture active. Ignore config");
81 		goto out;
82 	}
83 
84 	dai_info(dai, "ssp_set_config()");
85 
86 	/* disable clock */
87 	shim_update_bits(SHIM_CLKCTL, SHIM_CLKCTL_EN_SSP(dai->index), 0);
88 
89 	/* enable MCLK */
90 	shim_update_bits(SHIM_CLKCTL, SHIM_CLKCTL_SMOS(0x3),
91 			 SHIM_CLKCTL_SMOS(0x3));
92 
93 	/* reset SSP settings */
94 	/* sscr0 dynamic settings are DSS, EDSS, SCR, FRDC, ECS */
95 	sscr0 = SSCR0_MOD | SSCR0_PSP;
96 
97 	/* sscr1 dynamic settings are TFT, RFT, SFRMDIR, SCLKDIR, SCFR */
98 	sscr1 = SSCR1_TTE | SSCR1_TTELP;
99 
100 	/* enable Transmit underrun mode 1 */
101 	sscr2 = SSCR2_TURM1;
102 
103 	/* sspsp dynamic settings are SCMODE, SFRMP, DMYSTRT, SFRMWDTH */
104 	sspsp = 0x0;
105 
106 	/* sspsp2 no dynamic setting */
107 	sspsp2 = 0x0;
108 
109 	ssp->config = *config;
110 	ssp->params = config->ssp;
111 
112 	switch (config->format & SOF_DAI_FMT_CLOCK_PROVIDER_MASK) {
113 	case SOF_DAI_FMT_CBP_CFP:
114 		sscr1 |= SSCR1_SCLKDIR | SSCR1_SFRMDIR;
115 #ifdef ENABLE_SSRCR1_SCFR
116 		sscr1 |= SSCR1_SCFR;
117 #endif
118 		break;
119 	case SOF_DAI_FMT_CBC_CFC:
120 		break;
121 	case SOF_DAI_FMT_CBP_CFC:
122 		sscr1 |= SSCR1_SCLKDIR;
123 #ifdef ENABLE_SSRCR1_SCFR
124 		sscr1 |= SSCR1_SCFR;
125 #endif
126 		break;
127 	case SOF_DAI_FMT_CBC_CFP:
128 		sscr1 |= SSCR1_SFRMDIR;
129 		break;
130 	default:
131 		dai_err(dai, "ssp_set_config(): format & PROVIDER_MASK EINVAL");
132 		ret = -EINVAL;
133 		goto out;
134 	}
135 
136 	/* clock signal polarity */
137 	switch (config->format & SOF_DAI_FMT_INV_MASK) {
138 	case SOF_DAI_FMT_NB_NF:
139 		break;
140 	case SOF_DAI_FMT_NB_IF:
141 		inverted_frame = true; /* handled later with format */
142 		break;
143 	case SOF_DAI_FMT_IB_IF:
144 		sspsp |= SSPSP_SCMODE(2);
145 		inverted_frame = true; /* handled later with format */
146 		break;
147 	case SOF_DAI_FMT_IB_NF:
148 		sspsp |= SSPSP_SCMODE(2);
149 		break;
150 	default:
151 		dai_err(dai, "ssp_set_config(): format & INV_MASK EINVAL");
152 		ret = -EINVAL;
153 		goto out;
154 	}
155 
156 	/* Additional hardware settings */
157 
158 	/* Receiver Time-out Interrupt Disabled/Enabled */
159 	sscr1 |= (ssp->params.quirks & SOF_DAI_INTEL_SSP_QUIRK_TINTE) ?
160 		SSCR1_TINTE : 0;
161 
162 	/* Peripheral Trailing Byte Interrupts Disable/Enable */
163 	sscr1 |= (ssp->params.quirks & SOF_DAI_INTEL_SSP_QUIRK_PINTE) ?
164 		SSCR1_PINTE : 0;
165 
166 	/* Enable/disable internal loopback. Output of transmit serial
167 	 * shifter connected to input of receive serial shifter, internally.
168 	 */
169 	sscr1 |= (ssp->params.quirks & SOF_DAI_INTEL_SSP_QUIRK_LBM) ?
170 		SSCR1_LBM : 0;
171 
172 	/* Transmit data are driven at the same/opposite clock edge specified
173 	 * in SSPSP.SCMODE[1:0]
174 	 */
175 	sscr2 |= (ssp->params.quirks & SOF_DAI_INTEL_SSP_QUIRK_SMTATF) ?
176 		SSCR2_SMTATF : 0;
177 
178 	/* Receive data are sampled at the same/opposite clock edge specified
179 	 * in SSPSP.SCMODE[1:0]
180 	 */
181 	sscr2 |= (ssp->params.quirks & SOF_DAI_INTEL_SSP_QUIRK_MMRATF) ?
182 		SSCR2_MMRATF : 0;
183 
184 	/* Enable/disable the fix for PSP consumer mode TXD wait for frame
185 	 * de-assertion before starting the second channel
186 	 */
187 	sscr2 |= (ssp->params.quirks & SOF_DAI_INTEL_SSP_QUIRK_PSPSTWFDFD) ?
188 		SSCR2_PSPSTWFDFD : 0;
189 
190 	/* Enable/disable the fix for PSP provider mode FSRT with dummy stop &
191 	 * frame end padding capability
192 	 */
193 	sscr2 |= (ssp->params.quirks & SOF_DAI_INTEL_SSP_QUIRK_PSPSRWFDFD) ?
194 		SSCR2_PSPSRWFDFD : 0;
195 
196 	/* BCLK is generated from MCLK - must be divisable */
197 	if (config->ssp.mclk_rate % config->ssp.bclk_rate) {
198 		dai_err(dai, "ssp_set_config(): MCLK is not divisable");
199 		ret = -EINVAL;
200 		goto out;
201 	}
202 
203 	/* divisor must be within SCR range */
204 	mdiv = (config->ssp.mclk_rate / config->ssp.bclk_rate) - 1;
205 	if (mdiv > (SSCR0_SCR_MASK >> 8)) {
206 		dai_err(dai, "ssp_set_config(): divisor is not within SCR range");
207 		ret = -EINVAL;
208 		goto out;
209 	}
210 
211 	/* set the SCR divisor */
212 	sscr0 |= SSCR0_SCR(mdiv);
213 
214 	/* calc frame width based on BCLK and rate - must be divisable */
215 	if (config->ssp.bclk_rate % config->ssp.fsync_rate) {
216 		dai_err(dai, "ssp_set_config(): BLCK is not divisable");
217 		ret = -EINVAL;
218 		goto out;
219 	}
220 
221 	/* must be enouch BCLKs for data */
222 	bdiv = config->ssp.bclk_rate / config->ssp.fsync_rate;
223 	if (bdiv < config->ssp.tdm_slot_width *
224 	    config->ssp.tdm_slots) {
225 		dai_err(dai, "ssp_set_config(): not enough BCLKs");
226 		ret = -EINVAL;
227 		goto out;
228 	}
229 
230 	/* tdm_slot_width must be <= 38 for SSP */
231 	if (config->ssp.tdm_slot_width > 38) {
232 		dai_err(dai, "ssp_set_config(): tdm_slot_width > 38");
233 		ret = -EINVAL;
234 		goto out;
235 	}
236 
237 	bdiv_min = config->ssp.tdm_slots * config->ssp.sample_valid_bits;
238 	if (bdiv < bdiv_min) {
239 		dai_err(dai, "ssp_set_config(): bdiv < bdiv_min");
240 		ret = -EINVAL;
241 		goto out;
242 	}
243 
244 	frame_end_padding = bdiv - bdiv_min;
245 	if (frame_end_padding > SSPSP2_FEP_MASK) {
246 		dai_err(dai, "ssp_set_config(): frame_end_padding > SSPSP2_FEP_MASK");
247 		ret = -EINVAL;
248 		goto out;
249 	}
250 
251 	/* format */
252 	format = config->format & SOF_DAI_FMT_FORMAT_MASK;
253 	switch (format) {
254 	case SOF_DAI_FMT_I2S:
255 	case SOF_DAI_FMT_LEFT_J:
256 
257 		if (format == SOF_DAI_FMT_I2S) {
258 			start_delay = 1;
259 
260 		/*
261 		 * handle frame polarity, I2S default is falling/active low,
262 		 * non-inverted(inverted_frame=0) -- active low(SFRMP=0),
263 		 * inverted(inverted_frame=1) -- rising/active high(SFRMP=1),
264 		 * so, we should set SFRMP to inverted_frame.
265 		 */
266 			sspsp |= SSPSP_SFRMP(inverted_frame);
267 			sspsp |= SSPSP_FSRT;
268 
269 		} else {
270 			start_delay = 0;
271 
272 		/*
273 		 * handle frame polarity, LEFT_J default is rising/active high,
274 		 * non-inverted(inverted_frame=0) -- active high(SFRMP=1),
275 		 * inverted(inverted_frame=1) -- falling/active low(SFRMP=0),
276 		 * so, we should set SFRMP to !inverted_frame.
277 		 */
278 			sspsp |= SSPSP_SFRMP(!inverted_frame);
279 		}
280 
281 		sscr0 |= SSCR0_FRDC(config->ssp.tdm_slots);
282 
283 		if (bdiv % 2) {
284 			dai_err(dai, "ssp_set_config(): bdiv is not divisible by 2");
285 			ret = -EINVAL;
286 			goto out;
287 		}
288 
289 		/* set asserted frame length to half frame length */
290 		frame_len = bdiv / 2;
291 
292 		/*
293 		 *  for I2S/LEFT_J, the padding has to happen at the end
294 		 * of each slot
295 		 */
296 		if (frame_end_padding % 2) {
297 			dai_err(dai, "ssp_set_config(): frame_end_padding is not divisible by 2");
298 			ret = -EINVAL;
299 			goto out;
300 		}
301 
302 		slot_end_padding = frame_end_padding / 2;
303 
304 		if (slot_end_padding > 15) {
305 			/* can't handle padding over 15 bits */
306 			dai_err(dai, "ssp_set_config(): slot_end_padding over 15 bits");
307 			ret = -EINVAL;
308 			goto out;
309 		}
310 
311 		sspsp |= SSPSP_DMYSTOP(slot_end_padding);
312 		slot_end_padding >>= SSPSP_DMYSTOP_BITS;
313 		sspsp |= SSPSP_EDMYSTOP(slot_end_padding);
314 
315 		break;
316 	case SOF_DAI_FMT_DSP_A:
317 
318 		start_delay = 1;
319 
320 		sscr0 |= SSCR0_FRDC(config->ssp.tdm_slots);
321 
322 		/* set asserted frame length */
323 		frame_len = 1;
324 
325 		/* handle frame polarity, DSP_A default is rising/active high */
326 		sspsp |= SSPSP_SFRMP(!inverted_frame);
327 		sspsp2 |= (frame_end_padding & SSPSP2_FEP_MASK);
328 
329 		break;
330 	case SOF_DAI_FMT_DSP_B:
331 
332 		start_delay = 0;
333 
334 		sscr0 |= SSCR0_FRDC(config->ssp.tdm_slots);
335 
336 		/* set asserted frame length */
337 		frame_len = 1;
338 
339 		/* handle frame polarity, DSP_B default is rising/active high */
340 		sspsp |= SSPSP_SFRMP(!inverted_frame);
341 		sspsp2 |= (frame_end_padding & SSPSP2_FEP_MASK);
342 
343 		break;
344 	default:
345 		dai_err(dai, "ssp_set_config(): invalid format");
346 		ret = -EINVAL;
347 		goto out;
348 	}
349 
350 	if (start_delay)
351 		sspsp |= SSPSP_FSRT;
352 
353 	sspsp |= SSPSP_SFRMWDTH(frame_len);
354 
355 	data_size = config->ssp.sample_valid_bits;
356 
357 	if (data_size > 16)
358 		sscr0 |= (SSCR0_EDSS | SSCR0_DSIZE(data_size - 16));
359 	else
360 		sscr0 |= SSCR0_DSIZE(data_size);
361 
362 	sscr1 |= SSCR1_TFT(0x8) | SSCR1_RFT(0x8);
363 
364 	ssp_write(dai, SSCR0, sscr0);
365 	ssp_write(dai, SSCR1, sscr1);
366 	ssp_write(dai, SSCR2, sscr2);
367 	ssp_write(dai, SSPSP, sspsp);
368 	ssp_write(dai, SSTSA, SSTSA_SSTSA(config->ssp.tx_slots));
369 	ssp_write(dai, SSRSA, SSRSA_SSRSA(config->ssp.rx_slots));
370 	ssp_write(dai, SSPSP2, sspsp2);
371 
372 	ssp->state[DAI_DIR_PLAYBACK] = COMP_STATE_PREPARE;
373 	ssp->state[DAI_DIR_CAPTURE] = COMP_STATE_PREPARE;
374 
375 	/* enable clock */
376 	shim_update_bits(SHIM_CLKCTL, SHIM_CLKCTL_EN_SSP(dai->index),
377 			 SHIM_CLKCTL_EN_SSP(dai->index));
378 
379 	/* enable free running clock */
380 	ssp_update_bits(dai, SSCR0, SSCR0_SSE, SSCR0_SSE);
381 	ssp_update_bits(dai, SSCR0, SSCR0_SSE, 0);
382 
383 	dai_info(dai, "ssp_set_config(), done");
384 
385 out:
386 	spin_unlock(&dai->lock);
387 
388 	return ret;
389 }
390 
391 /* get SSP hw params */
ssp_get_hw_params(struct dai * dai,struct sof_ipc_stream_params * params,int dir)392 static int ssp_get_hw_params(struct dai *dai,
393 			     struct sof_ipc_stream_params  *params, int dir)
394 {
395 	struct ssp_pdata *ssp = dai_get_drvdata(dai);
396 
397 	params->rate = ssp->params.fsync_rate;
398 	params->buffer_fmt = 0;
399 
400 	if (dir == SOF_IPC_STREAM_PLAYBACK)
401 		params->channels = popcount(ssp->params.tx_slots);
402 	else
403 		params->channels = popcount(ssp->params.rx_slots);
404 
405 	switch (ssp->params.sample_valid_bits) {
406 	case 16:
407 		params->frame_fmt = SOF_IPC_FRAME_S16_LE;
408 		break;
409 	case 24:
410 		params->frame_fmt = SOF_IPC_FRAME_S24_4LE;
411 		break;
412 	case 32:
413 		params->frame_fmt = SOF_IPC_FRAME_S32_LE;
414 		break;
415 	default:
416 		dai_err(dai, "ssp_get_hw_params(): not supported format");
417 		return -EINVAL;
418 	}
419 
420 	return 0;
421 }
422 
423 /* start the SSP for either playback or capture */
ssp_start(struct dai * dai,int direction)424 static void ssp_start(struct dai *dai, int direction)
425 {
426 	struct ssp_pdata *ssp = dai_get_drvdata(dai);
427 
428 	spin_lock(&dai->lock);
429 
430 	dai_info(dai, "ssp_start()");
431 
432 	/* enable DMA */
433 	if (direction == DAI_DIR_PLAYBACK) {
434 		ssp_update_bits(dai, SSCR1, SSCR1_TSRE | SSCR1_EBCEI,
435 				SSCR1_TSRE | SSCR1_EBCEI);
436 		ssp_update_bits(dai, SSCR0, SSCR0_SSE, SSCR0_SSE);
437 		ssp_update_bits(dai, SSCR0, SSCR0_TIM, 0);
438 		ssp_update_bits(dai, SSTSA, SSTSA_TSEN, SSTSA_TSEN);
439 	} else {
440 		ssp_update_bits(dai, SSCR1, SSCR1_RSRE | SSCR1_EBCEI,
441 				SSCR1_RSRE | SSCR1_EBCEI);
442 		ssp_update_bits(dai, SSCR0, SSCR0_SSE, SSCR0_SSE);
443 		ssp_update_bits(dai, SSCR0, SSCR0_RIM, 0);
444 		ssp_update_bits(dai, SSRSA, SSRSA_RSEN, SSRSA_RSEN);
445 	}
446 
447 	/* enable port */
448 	ssp->state[direction] = COMP_STATE_ACTIVE;
449 
450 	spin_unlock(&dai->lock);
451 }
452 
453 /* stop the SSP for either playback or capture */
ssp_stop(struct dai * dai,int direction)454 static void ssp_stop(struct dai *dai, int direction)
455 {
456 	struct ssp_pdata *ssp = dai_get_drvdata(dai);
457 
458 	spin_lock(&dai->lock);
459 
460 	/* stop Rx if neeed */
461 	if (direction == DAI_DIR_CAPTURE &&
462 	    ssp->state[SOF_IPC_STREAM_CAPTURE] != COMP_STATE_PREPARE) {
463 		ssp_update_bits(dai, SSCR1, SSCR1_RSRE, 0);
464 		ssp_update_bits(dai, SSCR0, SSCR0_RIM, SSCR0_RIM);
465 		ssp_update_bits(dai, SSRSA, SSRSA_RSEN, 0);
466 		ssp->state[SOF_IPC_STREAM_CAPTURE] = COMP_STATE_PREPARE;
467 		dai_info(dai, "ssp_stop(), RX stop");
468 	}
469 
470 	/* stop Tx if needed */
471 	if (direction == DAI_DIR_PLAYBACK &&
472 	    ssp->state[SOF_IPC_STREAM_PLAYBACK] != COMP_STATE_PREPARE) {
473 		ssp_update_bits(dai, SSCR1, SSCR1_TSRE, 0);
474 		ssp_update_bits(dai, SSCR0, SSCR0_TIM, SSCR0_TIM);
475 		ssp_update_bits(dai, SSTSA, SSTSA_TSEN, 0);
476 		ssp->state[SOF_IPC_STREAM_PLAYBACK] = COMP_STATE_PREPARE;
477 		dai_info(dai, "ssp_stop(), TX stop");
478 	}
479 
480 	/* disable SSP port if no users */
481 	if (ssp->state[SOF_IPC_STREAM_CAPTURE] == COMP_STATE_PREPARE &&
482 	    ssp->state[SOF_IPC_STREAM_PLAYBACK] == COMP_STATE_PREPARE) {
483 		ssp_update_bits(dai, SSCR0, SSCR0_SSE, 0);
484 		dai_info(dai, "ssp_stop(), SSP port disabled");
485 	}
486 
487 	spin_unlock(&dai->lock);
488 }
489 
ssp_pause(struct dai * dai,int direction)490 static void ssp_pause(struct dai *dai, int direction)
491 {
492 	struct ssp_pdata *ssp = dai_get_drvdata(dai);
493 
494 	if (direction == SOF_IPC_STREAM_CAPTURE)
495 		dai_info(dai, "ssp_pause(), RX");
496 	else
497 		dai_info(dai, "ssp_pause(), TX");
498 
499 	ssp->state[direction] = COMP_STATE_PAUSED;
500 }
501 
ssp_trigger(struct dai * dai,int cmd,int direction)502 static int ssp_trigger(struct dai *dai, int cmd, int direction)
503 {
504 	struct ssp_pdata *ssp = dai_get_drvdata(dai);
505 
506 	dai_info(dai, "ssp_trigger()");
507 
508 	switch (cmd) {
509 	case COMP_TRIGGER_START:
510 		if (ssp->state[direction] == COMP_STATE_PREPARE ||
511 		    ssp->state[direction] == COMP_STATE_PAUSED)
512 			ssp_start(dai, direction);
513 		break;
514 	case COMP_TRIGGER_RELEASE:
515 		if (ssp->state[direction] == COMP_STATE_PAUSED ||
516 		    ssp->state[direction] == COMP_STATE_PREPARE)
517 			ssp_start(dai, direction);
518 		break;
519 	case COMP_TRIGGER_STOP:
520 		ssp_stop(dai, direction);
521 		break;
522 	case COMP_TRIGGER_PAUSE:
523 		ssp_pause(dai, direction);
524 		break;
525 	case COMP_TRIGGER_RESUME:
526 		ssp_context_restore(dai);
527 		break;
528 	case COMP_TRIGGER_SUSPEND:
529 		ssp_context_store(dai);
530 		break;
531 	default:
532 		break;
533 	}
534 
535 	return 0;
536 }
537 
ssp_probe(struct dai * dai)538 static int ssp_probe(struct dai *dai)
539 {
540 	struct ssp_pdata *ssp;
541 
542 	/* allocate private data */
543 	ssp = rzalloc(SOF_MEM_ZONE_SYS_SHARED, 0, SOF_MEM_CAPS_RAM, sizeof(*ssp));
544 	dai_set_drvdata(dai, ssp);
545 
546 	ssp->state[DAI_DIR_PLAYBACK] = COMP_STATE_READY;
547 	ssp->state[DAI_DIR_CAPTURE] = COMP_STATE_READY;
548 
549 	return 0;
550 }
551 
ssp_get_handshake(struct dai * dai,int direction,int stream_id)552 static int ssp_get_handshake(struct dai *dai, int direction, int stream_id)
553 {
554 	return dai->plat_data.fifo[direction].handshake;
555 }
556 
ssp_get_fifo(struct dai * dai,int direction,int stream_id)557 static int ssp_get_fifo(struct dai *dai, int direction, int stream_id)
558 {
559 	return dai->plat_data.fifo[direction].offset;
560 }
561 
562 const struct dai_driver ssp_driver = {
563 	.type = SOF_DAI_INTEL_SSP,
564 	.dma_caps = DMA_CAP_GP_LP | DMA_CAP_GP_HP,
565 	.dma_dev = DMA_DEV_SSP,
566 	.ops = {
567 		.trigger		= ssp_trigger,
568 		.set_config		= ssp_set_config,
569 		.pm_context_store	= ssp_context_store,
570 		.pm_context_restore	= ssp_context_restore,
571 		.get_hw_params		= ssp_get_hw_params,
572 		.get_handshake		= ssp_get_handshake,
573 		.get_fifo		= ssp_get_fifo,
574 		.probe			= ssp_probe,
575 	},
576 };
577