xref: /linux/sound/soc/intel/atom/sst-mfld-platform-pcm.c (revision e5c91aac491def6ab3f90c4cc246e3fcb0f8f058)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  *  sst_mfld_platform.c - Intel MID Platform driver
4  *
5  *  Copyright (C) 2010-2014 Intel Corp
6  *  Author: Vinod Koul <vinod.koul@intel.com>
7  *  Author: Harsha Priya <priya.harsha@intel.com>
8  *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
9  *
10  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
11  */
12 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
13 
14 #include <linux/cleanup.h>
15 #include <linux/slab.h>
16 #include <linux/io.h>
17 #include <linux/module.h>
18 #include <sound/core.h>
19 #include <sound/pcm.h>
20 #include <sound/pcm_params.h>
21 #include <sound/soc.h>
22 #include <sound/compress_driver.h>
23 #include <asm/platform_sst_audio.h>
24 #include "sst-mfld-platform.h"
25 #include "sst-atom-controls.h"
26 
27 struct sst_device *sst;
28 static DEFINE_MUTEX(sst_lock);
29 
30 int sst_register_dsp(struct sst_device *dev)
31 {
32 	if (WARN_ON(!dev))
33 		return -EINVAL;
34 	if (!try_module_get(dev->dev->driver->owner))
35 		return -ENODEV;
36 	guard(mutex)(&sst_lock);
37 	if (sst) {
38 		dev_err(dev->dev, "we already have a device %s\n", sst->name);
39 		module_put(dev->dev->driver->owner);
40 		mutex_unlock(&sst_lock);
41 		return -EEXIST;
42 	}
43 	dev_dbg(dev->dev, "registering device %s\n", dev->name);
44 	sst = dev;
45 
46 	return 0;
47 }
48 EXPORT_SYMBOL_GPL(sst_register_dsp);
49 
50 int sst_unregister_dsp(struct sst_device *dev)
51 {
52 	if (WARN_ON(!dev))
53 		return -EINVAL;
54 	if (dev != sst)
55 		return -EINVAL;
56 
57 	guard(mutex)(&sst_lock);
58 
59 	if (!sst)
60 		return -EIO;
61 
62 	module_put(sst->dev->driver->owner);
63 	dev_dbg(dev->dev, "unreg %s\n", sst->name);
64 	sst = NULL;
65 
66 	return 0;
67 }
68 EXPORT_SYMBOL_GPL(sst_unregister_dsp);
69 
70 static const struct snd_pcm_hardware sst_platform_pcm_hw = {
71 	.info =	(SNDRV_PCM_INFO_INTERLEAVED |
72 			SNDRV_PCM_INFO_DOUBLE |
73 			SNDRV_PCM_INFO_PAUSE |
74 			SNDRV_PCM_INFO_RESUME |
75 			SNDRV_PCM_INFO_MMAP|
76 			SNDRV_PCM_INFO_MMAP_VALID |
77 			SNDRV_PCM_INFO_BLOCK_TRANSFER |
78 			SNDRV_PCM_INFO_SYNC_START),
79 	.buffer_bytes_max = SST_MAX_BUFFER,
80 	.period_bytes_min = SST_MIN_PERIOD_BYTES,
81 	.period_bytes_max = SST_MAX_PERIOD_BYTES,
82 	.periods_min = SST_MIN_PERIODS,
83 	.periods_max = SST_MAX_PERIODS,
84 	.fifo_size = SST_FIFO_SIZE,
85 };
86 
87 static struct sst_dev_stream_map dpcm_strm_map[] = {
88 	{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, /* Reserved, not in use */
89 	{MERR_DPCM_AUDIO, 0, SNDRV_PCM_STREAM_PLAYBACK, PIPE_MEDIA1_IN, SST_TASK_ID_MEDIA, 0},
90 	{MERR_DPCM_COMPR, 0, SNDRV_PCM_STREAM_PLAYBACK, PIPE_MEDIA0_IN, SST_TASK_ID_MEDIA, 0},
91 	{MERR_DPCM_AUDIO, 0, SNDRV_PCM_STREAM_CAPTURE, PIPE_PCM1_OUT, SST_TASK_ID_MEDIA, 0},
92 	{MERR_DPCM_DEEP_BUFFER, 0, SNDRV_PCM_STREAM_PLAYBACK, PIPE_MEDIA3_IN, SST_TASK_ID_MEDIA, 0},
93 };
94 
95 static int sst_media_digital_mute(struct snd_soc_dai *dai, int mute, int stream)
96 {
97 
98 	return sst_send_pipe_gains(dai, stream, mute);
99 }
100 
101 /* helper functions */
102 void sst_set_stream_status(struct sst_runtime_stream *stream,
103 					int state)
104 {
105 	guard(spinlock_irqsave)(&stream->status_lock);
106 	stream->stream_status = state;
107 }
108 
109 static inline int sst_get_stream_status(struct sst_runtime_stream *stream)
110 {
111 	guard(spinlock_irqsave)(&stream->status_lock);
112 	return stream->stream_status;
113 }
114 
115 static void sst_fill_alloc_params(struct snd_pcm_substream *substream,
116 				struct snd_sst_alloc_params_ext *alloc_param)
117 {
118 	unsigned int channels;
119 	snd_pcm_uframes_t period_size;
120 	ssize_t periodbytes;
121 	ssize_t buffer_bytes = snd_pcm_lib_buffer_bytes(substream);
122 	u32 buffer_addr = substream->runtime->dma_addr;
123 
124 	channels = substream->runtime->channels;
125 	period_size = substream->runtime->period_size;
126 	periodbytes = samples_to_bytes(substream->runtime, period_size);
127 	alloc_param->ring_buf_info[0].addr = buffer_addr;
128 	alloc_param->ring_buf_info[0].size = buffer_bytes;
129 	alloc_param->sg_count = 1;
130 	alloc_param->reserved = 0;
131 	alloc_param->frag_size = periodbytes * channels;
132 
133 }
134 static void sst_fill_pcm_params(struct snd_pcm_substream *substream,
135 				struct snd_sst_stream_params *param)
136 {
137 	param->uc.pcm_params.num_chan = (u8) substream->runtime->channels;
138 	param->uc.pcm_params.pcm_wd_sz = substream->runtime->sample_bits;
139 	param->uc.pcm_params.sfreq = substream->runtime->rate;
140 
141 	/* PCM stream via ALSA interface */
142 	param->uc.pcm_params.use_offload_path = 0;
143 	param->uc.pcm_params.reserved2 = 0;
144 	memset(param->uc.pcm_params.channel_map, 0, sizeof(u8));
145 
146 }
147 
148 static int sst_get_stream_mapping(int dev, int sdev, int dir,
149 	struct sst_dev_stream_map *map, int size)
150 {
151 	int i;
152 
153 	if (map == NULL)
154 		return -EINVAL;
155 
156 
157 	/* index 0 is not used in stream map */
158 	for (i = 1; i < size; i++) {
159 		if ((map[i].dev_num == dev) && (map[i].direction == dir))
160 			return i;
161 	}
162 	return 0;
163 }
164 
165 int sst_fill_stream_params(void *substream,
166 	const struct sst_data *ctx, struct snd_sst_params *str_params, bool is_compress)
167 {
168 	int map_size;
169 	int index;
170 	struct sst_dev_stream_map *map;
171 	struct snd_pcm_substream *pstream = NULL;
172 	struct snd_compr_stream *cstream = NULL;
173 
174 	map = ctx->pdata->pdev_strm_map;
175 	map_size = ctx->pdata->strm_map_size;
176 
177 	if (is_compress)
178 		cstream = (struct snd_compr_stream *)substream;
179 	else
180 		pstream = (struct snd_pcm_substream *)substream;
181 
182 	str_params->stream_type = SST_STREAM_TYPE_MUSIC;
183 
184 	/* For pcm streams */
185 	if (pstream) {
186 		index = sst_get_stream_mapping(pstream->pcm->device,
187 					  pstream->number, pstream->stream,
188 					  map, map_size);
189 		if (index <= 0)
190 			return -EINVAL;
191 
192 		str_params->stream_id = index;
193 		str_params->device_type = map[index].device_id;
194 		str_params->task = map[index].task_id;
195 
196 		str_params->ops = (u8)pstream->stream;
197 	}
198 
199 	if (cstream) {
200 		index = sst_get_stream_mapping(cstream->device->device,
201 					       0, cstream->direction,
202 					       map, map_size);
203 		if (index <= 0)
204 			return -EINVAL;
205 		str_params->stream_id = index;
206 		str_params->device_type = map[index].device_id;
207 		str_params->task = map[index].task_id;
208 
209 		str_params->ops = (u8)cstream->direction;
210 	}
211 	return 0;
212 }
213 
214 static int sst_platform_alloc_stream(struct snd_pcm_substream *substream,
215 		struct snd_soc_dai *dai)
216 {
217 	struct sst_runtime_stream *stream =
218 			substream->runtime->private_data;
219 	struct snd_sst_stream_params param = {{{0,},},};
220 	struct snd_sst_params str_params = {0};
221 	struct snd_sst_alloc_params_ext alloc_params = {0};
222 	int ret_val = 0;
223 	struct sst_data *ctx = snd_soc_dai_get_drvdata(dai);
224 
225 	/* set codec params and inform SST driver the same */
226 	sst_fill_pcm_params(substream, &param);
227 	sst_fill_alloc_params(substream, &alloc_params);
228 	str_params.sparams = param;
229 	str_params.aparams = alloc_params;
230 	str_params.codec = SST_CODEC_TYPE_PCM;
231 
232 	/* fill the device type and stream id to pass to SST driver */
233 	ret_val = sst_fill_stream_params(substream, ctx, &str_params, false);
234 	if (ret_val < 0)
235 		return ret_val;
236 
237 	stream->stream_info.str_id = str_params.stream_id;
238 
239 	return stream->ops->open(sst->dev, &str_params);
240 }
241 
242 static void sst_period_elapsed(void *arg)
243 {
244 	struct snd_pcm_substream *substream = arg;
245 	struct sst_runtime_stream *stream;
246 	int status;
247 
248 	if (!substream || !substream->runtime)
249 		return;
250 	stream = substream->runtime->private_data;
251 	if (!stream)
252 		return;
253 	status = sst_get_stream_status(stream);
254 	if (status != SST_PLATFORM_RUNNING)
255 		return;
256 	snd_pcm_period_elapsed(substream);
257 }
258 
259 static int sst_platform_init_stream(struct snd_pcm_substream *substream)
260 {
261 	struct sst_runtime_stream *stream =
262 			substream->runtime->private_data;
263 	struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
264 	int ret_val;
265 
266 	dev_dbg(rtd->dev, "setting buffer ptr param\n");
267 	sst_set_stream_status(stream, SST_PLATFORM_INIT);
268 	stream->stream_info.period_elapsed = sst_period_elapsed;
269 	stream->stream_info.arg = substream;
270 	stream->stream_info.buffer_ptr = 0;
271 	stream->stream_info.sfreq = substream->runtime->rate;
272 	ret_val = stream->ops->stream_init(sst->dev, &stream->stream_info);
273 	if (ret_val)
274 		dev_err(rtd->dev, "control_set ret error %d\n", ret_val);
275 	return ret_val;
276 
277 }
278 
279 static int power_up_sst(struct sst_runtime_stream *stream)
280 {
281 	return stream->ops->power(sst->dev, true);
282 }
283 
284 static void power_down_sst(struct sst_runtime_stream *stream)
285 {
286 	stream->ops->power(sst->dev, false);
287 }
288 
289 static int sst_media_open(struct snd_pcm_substream *substream,
290 		struct snd_soc_dai *dai)
291 {
292 	int ret_val = 0;
293 	struct snd_pcm_runtime *runtime = substream->runtime;
294 	struct sst_runtime_stream *stream __free(kfree) = NULL;
295 
296 	stream = kzalloc_obj(*stream);
297 	if (!stream)
298 		return -ENOMEM;
299 	spin_lock_init(&stream->status_lock);
300 
301 	/* get the sst ops */
302 	scoped_guard(mutex, &sst_lock) {
303 		if (!sst ||
304 		    !try_module_get(sst->dev->driver->owner)) {
305 			dev_err(dai->dev, "no device available to run\n");
306 			return -ENODEV;
307 		}
308 		stream->ops = sst->ops;
309 	}
310 
311 	stream->stream_info.str_id = 0;
312 
313 	stream->stream_info.arg = substream;
314 	/* allocate memory for SST API set */
315 	runtime->private_data = stream;
316 
317 	ret_val = power_up_sst(stream);
318 	if (ret_val < 0)
319 		return ret_val;
320 
321 	/*
322 	 * Make sure the period to be multiple of 1ms to align the
323 	 * design of firmware. Apply same rule to buffer size to make
324 	 * sure alsa could always find a value for period size
325 	 * regardless the buffer size given by user space.
326 	 */
327 	snd_pcm_hw_constraint_step(substream->runtime, 0,
328 			   SNDRV_PCM_HW_PARAM_PERIOD_SIZE, 48);
329 	snd_pcm_hw_constraint_step(substream->runtime, 0,
330 			   SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 48);
331 
332 	/* Make sure, that the period size is always even */
333 	snd_pcm_hw_constraint_step(substream->runtime, 0,
334 			   SNDRV_PCM_HW_PARAM_PERIODS, 2);
335 
336 	ret_val = snd_pcm_hw_constraint_integer(runtime,
337 						SNDRV_PCM_HW_PARAM_PERIODS);
338 
339 	if (ret_val < 0)
340 		return ret_val;
341 
342 	stream = NULL;
343 
344 	return ret_val;
345 }
346 
347 static void sst_media_close(struct snd_pcm_substream *substream,
348 		struct snd_soc_dai *dai)
349 {
350 	struct sst_runtime_stream *stream;
351 	int str_id;
352 
353 	stream = substream->runtime->private_data;
354 	power_down_sst(stream);
355 
356 	str_id = stream->stream_info.str_id;
357 	if (str_id)
358 		stream->ops->close(sst->dev, str_id);
359 	module_put(sst->dev->driver->owner);
360 	kfree(stream);
361 }
362 
363 static int sst_media_prepare(struct snd_pcm_substream *substream,
364 		struct snd_soc_dai *dai)
365 {
366 	struct sst_runtime_stream *stream;
367 	int ret_val, str_id;
368 
369 	stream = substream->runtime->private_data;
370 	str_id = stream->stream_info.str_id;
371 	if (stream->stream_info.str_id) {
372 		ret_val = stream->ops->stream_drop(sst->dev, str_id);
373 		return ret_val;
374 	}
375 
376 	ret_val = sst_platform_alloc_stream(substream, dai);
377 	if (ret_val <= 0)
378 		return ret_val;
379 	snprintf(substream->pcm->id, sizeof(substream->pcm->id),
380 			"%d", stream->stream_info.str_id);
381 
382 	ret_val = sst_platform_init_stream(substream);
383 	if (ret_val)
384 		return ret_val;
385 	substream->runtime->hw.info = SNDRV_PCM_INFO_BLOCK_TRANSFER;
386 	return 0;
387 }
388 
389 static int sst_enable_ssp(struct snd_pcm_substream *substream,
390 			struct snd_soc_dai *dai)
391 {
392 	int ret = 0;
393 
394 	if (!snd_soc_dai_active(dai)) {
395 		ret = sst_handle_vb_timer(dai, true);
396 		sst_fill_ssp_defaults(dai);
397 	}
398 	return ret;
399 }
400 
401 static int sst_be_hw_params(struct snd_pcm_substream *substream,
402 				struct snd_pcm_hw_params *params,
403 				struct snd_soc_dai *dai)
404 {
405 	int ret = 0;
406 
407 	if (snd_soc_dai_active(dai) == 1)
408 		ret = send_ssp_cmd(dai, dai->name, 1);
409 	return ret;
410 }
411 
412 static int sst_set_format(struct snd_soc_dai *dai, unsigned int fmt)
413 {
414 	int ret = 0;
415 
416 	if (!snd_soc_dai_active(dai))
417 		return 0;
418 
419 	ret = sst_fill_ssp_config(dai, fmt);
420 	if (ret < 0)
421 		dev_err(dai->dev, "sst_set_format failed..\n");
422 
423 	return ret;
424 }
425 
426 static int sst_platform_set_ssp_slot(struct snd_soc_dai *dai,
427 			unsigned int tx_mask, unsigned int rx_mask,
428 			int slots, int slot_width) {
429 	int ret = 0;
430 
431 	if (!snd_soc_dai_active(dai))
432 		return ret;
433 
434 	ret = sst_fill_ssp_slot(dai, tx_mask, rx_mask, slots, slot_width);
435 	if (ret < 0)
436 		dev_err(dai->dev, "sst_fill_ssp_slot failed..%d\n", ret);
437 
438 	return ret;
439 }
440 
441 static void sst_disable_ssp(struct snd_pcm_substream *substream,
442 			struct snd_soc_dai *dai)
443 {
444 	if (!snd_soc_dai_active(dai)) {
445 		send_ssp_cmd(dai, dai->name, 0);
446 		sst_handle_vb_timer(dai, false);
447 	}
448 }
449 
450 static const struct snd_soc_dai_ops sst_media_dai_ops = {
451 	.startup = sst_media_open,
452 	.shutdown = sst_media_close,
453 	.prepare = sst_media_prepare,
454 	.mute_stream = sst_media_digital_mute,
455 };
456 
457 static const struct snd_soc_dai_ops sst_compr_dai_ops = {
458 	.compress_new = snd_soc_new_compress,
459 	.mute_stream = sst_media_digital_mute,
460 };
461 
462 static const struct snd_soc_dai_ops sst_be_dai_ops = {
463 	.startup = sst_enable_ssp,
464 	.hw_params = sst_be_hw_params,
465 	.set_fmt = sst_set_format,
466 	.set_tdm_slot = sst_platform_set_ssp_slot,
467 	.shutdown = sst_disable_ssp,
468 };
469 
470 static struct snd_soc_dai_driver sst_platform_dai[] = {
471 {
472 	.name = "media-cpu-dai",
473 	.ops = &sst_media_dai_ops,
474 	.playback = {
475 		.stream_name = "Headset Playback",
476 		.channels_min = SST_STEREO,
477 		.channels_max = SST_STEREO,
478 		.rates = SNDRV_PCM_RATE_48000,
479 		.formats = SNDRV_PCM_FMTBIT_S16_LE,
480 	},
481 	.capture = {
482 		.stream_name = "Headset Capture",
483 		.channels_min = 1,
484 		.channels_max = 2,
485 		.rates = SNDRV_PCM_RATE_48000,
486 		.formats = SNDRV_PCM_FMTBIT_S16_LE,
487 	},
488 },
489 {
490 	.name = "deepbuffer-cpu-dai",
491 	.ops = &sst_media_dai_ops,
492 	.playback = {
493 		.stream_name = "Deepbuffer Playback",
494 		.channels_min = SST_STEREO,
495 		.channels_max = SST_STEREO,
496 		.rates = SNDRV_PCM_RATE_48000,
497 		.formats = SNDRV_PCM_FMTBIT_S16_LE,
498 	},
499 },
500 {
501 	.name = "compress-cpu-dai",
502 	.ops = &sst_compr_dai_ops,
503 	.playback = {
504 		.stream_name = "Compress Playback",
505 		.channels_min = 1,
506 	},
507 },
508 /* BE CPU  Dais */
509 {
510 	.name = "ssp0-port",
511 	.ops = &sst_be_dai_ops,
512 	.playback = {
513 		.stream_name = "ssp0 Tx",
514 		.channels_min = SST_STEREO,
515 		.channels_max = SST_STEREO,
516 		.rates = SNDRV_PCM_RATE_48000,
517 		.formats = SNDRV_PCM_FMTBIT_S16_LE,
518 	},
519 	.capture = {
520 		.stream_name = "ssp0 Rx",
521 		.channels_min = SST_STEREO,
522 		.channels_max = SST_STEREO,
523 		.rates = SNDRV_PCM_RATE_48000,
524 		.formats = SNDRV_PCM_FMTBIT_S16_LE,
525 	},
526 },
527 {
528 	.name = "ssp1-port",
529 	.ops = &sst_be_dai_ops,
530 	.playback = {
531 		.stream_name = "ssp1 Tx",
532 		.channels_min = SST_STEREO,
533 		.channels_max = SST_STEREO,
534 		.rates = SNDRV_PCM_RATE_8000|SNDRV_PCM_RATE_16000|SNDRV_PCM_RATE_48000,
535 		.formats = SNDRV_PCM_FMTBIT_S16_LE,
536 	},
537 	.capture = {
538 		.stream_name = "ssp1 Rx",
539 		.channels_min = SST_STEREO,
540 		.channels_max = SST_STEREO,
541 		.rates = SNDRV_PCM_RATE_8000|SNDRV_PCM_RATE_16000|SNDRV_PCM_RATE_48000,
542 		.formats = SNDRV_PCM_FMTBIT_S16_LE,
543 	},
544 },
545 {
546 	.name = "ssp2-port",
547 	.ops = &sst_be_dai_ops,
548 	.playback = {
549 		.stream_name = "ssp2 Tx",
550 		.channels_min = SST_STEREO,
551 		.channels_max = SST_STEREO,
552 		.rates = SNDRV_PCM_RATE_48000,
553 		.formats = SNDRV_PCM_FMTBIT_S16_LE,
554 	},
555 	.capture = {
556 		.stream_name = "ssp2 Rx",
557 		.channels_min = SST_STEREO,
558 		.channels_max = SST_STEREO,
559 		.rates = SNDRV_PCM_RATE_48000,
560 		.formats = SNDRV_PCM_FMTBIT_S16_LE,
561 	},
562 },
563 };
564 
565 static int sst_soc_open(struct snd_soc_component *component,
566 			struct snd_pcm_substream *substream)
567 {
568 	struct snd_pcm_runtime *runtime;
569 
570 	if (substream->pcm->internal)
571 		return 0;
572 
573 	runtime = substream->runtime;
574 	runtime->hw = sst_platform_pcm_hw;
575 	return 0;
576 }
577 
578 static int sst_soc_trigger(struct snd_soc_component *component,
579 			   struct snd_pcm_substream *substream, int cmd)
580 {
581 	int ret_val = 0, str_id;
582 	struct sst_runtime_stream *stream;
583 	int status;
584 	struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
585 
586 	dev_dbg(rtd->dev, "%s called\n", __func__);
587 	if (substream->pcm->internal)
588 		return 0;
589 	stream = substream->runtime->private_data;
590 	str_id = stream->stream_info.str_id;
591 	switch (cmd) {
592 	case SNDRV_PCM_TRIGGER_START:
593 		dev_dbg(rtd->dev, "sst: Trigger Start\n");
594 		status = SST_PLATFORM_RUNNING;
595 		stream->stream_info.arg = substream;
596 		ret_val = stream->ops->stream_start(sst->dev, str_id);
597 		break;
598 	case SNDRV_PCM_TRIGGER_STOP:
599 		dev_dbg(rtd->dev, "sst: in stop\n");
600 		status = SST_PLATFORM_DROPPED;
601 		ret_val = stream->ops->stream_drop(sst->dev, str_id);
602 		break;
603 	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
604 	case SNDRV_PCM_TRIGGER_SUSPEND:
605 		dev_dbg(rtd->dev, "sst: in pause\n");
606 		status = SST_PLATFORM_PAUSED;
607 		ret_val = stream->ops->stream_pause(sst->dev, str_id);
608 		break;
609 	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
610 	case SNDRV_PCM_TRIGGER_RESUME:
611 		dev_dbg(rtd->dev, "sst: in pause release\n");
612 		status = SST_PLATFORM_RUNNING;
613 		ret_val = stream->ops->stream_pause_release(sst->dev, str_id);
614 		break;
615 	default:
616 		return -EINVAL;
617 	}
618 
619 	if (!ret_val)
620 		sst_set_stream_status(stream, status);
621 
622 	return ret_val;
623 }
624 
625 
626 static snd_pcm_uframes_t sst_soc_pointer(struct snd_soc_component *component,
627 					 struct snd_pcm_substream *substream)
628 {
629 	struct sst_runtime_stream *stream;
630 	int ret_val, status;
631 	struct pcm_stream_info *str_info;
632 	struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
633 
634 	stream = substream->runtime->private_data;
635 	status = sst_get_stream_status(stream);
636 	if (status == SST_PLATFORM_INIT)
637 		return 0;
638 	str_info = &stream->stream_info;
639 	ret_val = stream->ops->stream_read_tstamp(sst->dev, str_info);
640 	if (ret_val) {
641 		dev_err(rtd->dev, "sst: error code = %d\n", ret_val);
642 		return ret_val;
643 	}
644 	return str_info->buffer_ptr;
645 }
646 
647 static snd_pcm_sframes_t sst_soc_delay(struct snd_soc_component *component,
648 				       struct snd_pcm_substream *substream)
649 {
650 	struct sst_runtime_stream *stream = substream->runtime->private_data;
651 	struct pcm_stream_info *str_info = &stream->stream_info;
652 
653 	if (sst_get_stream_status(stream) == SST_PLATFORM_INIT)
654 		return 0;
655 
656 	return str_info->pcm_delay;
657 }
658 
659 static int sst_soc_pcm_new(struct snd_soc_component *component,
660 			   struct snd_soc_pcm_runtime *rtd)
661 {
662 	struct snd_soc_dai *dai = snd_soc_rtd_to_cpu(rtd, 0);
663 	struct snd_pcm *pcm = rtd->pcm;
664 
665 	if (dai->driver->playback.channels_min ||
666 			dai->driver->capture.channels_min) {
667 		snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV,
668 					       pcm->card->dev,
669 					       SST_MIN_BUFFER, SST_MAX_BUFFER);
670 	}
671 	return 0;
672 }
673 
674 static int sst_soc_probe(struct snd_soc_component *component)
675 {
676 	struct sst_data *drv = dev_get_drvdata(component->dev);
677 
678 	drv->soc_card = component->card;
679 	return sst_dsp_init_v2_dpcm(component);
680 }
681 
682 static void sst_soc_remove(struct snd_soc_component *component)
683 {
684 	struct sst_data *drv = dev_get_drvdata(component->dev);
685 
686 	drv->soc_card = NULL;
687 }
688 
689 static const struct snd_soc_component_driver sst_soc_platform_drv  = {
690 	.name		= DRV_NAME,
691 	.probe		= sst_soc_probe,
692 	.remove		= sst_soc_remove,
693 	.open		= sst_soc_open,
694 	.trigger	= sst_soc_trigger,
695 	.pointer	= sst_soc_pointer,
696 	.delay		= sst_soc_delay,
697 	.compress_ops	= &sst_platform_compress_ops,
698 	.pcm_new	= sst_soc_pcm_new,
699 };
700 
701 static int sst_platform_probe(struct platform_device *pdev)
702 {
703 	struct sst_data *drv;
704 	int ret;
705 	struct sst_platform_data *pdata;
706 
707 	drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_KERNEL);
708 	if (drv == NULL) {
709 		return -ENOMEM;
710 	}
711 
712 	pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
713 	if (pdata == NULL) {
714 		return -ENOMEM;
715 	}
716 
717 	pdata->pdev_strm_map = dpcm_strm_map;
718 	pdata->strm_map_size = ARRAY_SIZE(dpcm_strm_map);
719 	drv->pdata = pdata;
720 	drv->pdev = pdev;
721 	mutex_init(&drv->lock);
722 	dev_set_drvdata(&pdev->dev, drv);
723 
724 	ret = devm_snd_soc_register_component(&pdev->dev, &sst_soc_platform_drv,
725 				sst_platform_dai, ARRAY_SIZE(sst_platform_dai));
726 	if (ret)
727 		dev_err(&pdev->dev, "registering cpu dais failed\n");
728 
729 	return ret;
730 }
731 
732 static void sst_platform_remove(struct platform_device *pdev)
733 {
734 	dev_dbg(&pdev->dev, "sst_platform_remove success\n");
735 }
736 
737 #ifdef CONFIG_PM_SLEEP
738 
739 static int sst_soc_prepare(struct device *dev)
740 {
741 	struct sst_data *drv = dev_get_drvdata(dev);
742 	struct snd_soc_pcm_runtime *rtd;
743 
744 	if (!drv->soc_card)
745 		return 0;
746 
747 	/* suspend all pcms first */
748 	snd_soc_suspend(drv->soc_card->dev);
749 	snd_soc_poweroff(drv->soc_card->dev);
750 
751 	/* set the SSPs to idle */
752 	for_each_card_rtds(drv->soc_card, rtd) {
753 		struct snd_soc_dai *dai = snd_soc_rtd_to_cpu(rtd, 0);
754 
755 		if (snd_soc_dai_active(dai)) {
756 			send_ssp_cmd(dai, dai->name, 0);
757 			sst_handle_vb_timer(dai, false);
758 		}
759 	}
760 
761 	return 0;
762 }
763 
764 static void sst_soc_complete(struct device *dev)
765 {
766 	struct sst_data *drv = dev_get_drvdata(dev);
767 	struct snd_soc_pcm_runtime *rtd;
768 
769 	if (!drv->soc_card)
770 		return;
771 
772 	/* restart SSPs */
773 	for_each_card_rtds(drv->soc_card, rtd) {
774 		struct snd_soc_dai *dai = snd_soc_rtd_to_cpu(rtd, 0);
775 
776 		if (snd_soc_dai_active(dai)) {
777 			sst_handle_vb_timer(dai, true);
778 			send_ssp_cmd(dai, dai->name, 1);
779 		}
780 	}
781 	snd_soc_resume(drv->soc_card->dev);
782 }
783 
784 #else
785 
786 #define sst_soc_prepare NULL
787 #define sst_soc_complete NULL
788 
789 #endif
790 
791 
792 static const struct dev_pm_ops sst_platform_pm = {
793 	.prepare	= sst_soc_prepare,
794 	.complete	= sst_soc_complete,
795 };
796 
797 static struct platform_driver sst_platform_driver = {
798 	.driver		= {
799 		.name		= "sst-mfld-platform",
800 		.pm             = &sst_platform_pm,
801 	},
802 	.probe		= sst_platform_probe,
803 	.remove		= sst_platform_remove,
804 };
805 
806 module_platform_driver(sst_platform_driver);
807 
808 MODULE_DESCRIPTION("ASoC Intel(R) MID Platform driver");
809 MODULE_AUTHOR("Vinod Koul <vinod.koul@intel.com>");
810 MODULE_AUTHOR("Harsha Priya <priya.harsha@intel.com>");
811 MODULE_LICENSE("GPL v2");
812 MODULE_ALIAS("platform:sst-atom-hifi2-platform");
813 MODULE_ALIAS("platform:sst-mfld-platform");
814