1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  *  sst_drv_interface.c - Intel SST Driver for audio engine
4  *
5  *  Copyright (C) 2008-14 Intel Corp
6  *  Authors:	Vinod Koul <vinod.koul@intel.com>
7  *		Harsha Priya <priya.harsha@intel.com>
8  *		Dharageswari R <dharageswari.r@intel.com)
9  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
10  *
11  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
12  */
13 #include <linux/delay.h>
14 #include <linux/pci.h>
15 #include <linux/fs.h>
16 #include <linux/firmware.h>
17 #include <linux/pm_runtime.h>
18 #include <linux/pm_qos.h>
19 #include <linux/math64.h>
20 #include <sound/core.h>
21 #include <sound/pcm.h>
22 #include <sound/soc.h>
23 #include <sound/compress_driver.h>
24 #include <asm/platform_sst_audio.h>
25 #include "../sst-mfld-platform.h"
26 #include "sst.h"
27 #include "../../common/sst-dsp.h"
28 
29 
30 
31 #define NUM_CODEC 2
32 #define MIN_FRAGMENT 2
33 #define MAX_FRAGMENT 4
34 #define MIN_FRAGMENT_SIZE (50 * 1024)
35 #define MAX_FRAGMENT_SIZE (1024 * 1024)
36 #define SST_GET_BYTES_PER_SAMPLE(pcm_wd_sz)  (((pcm_wd_sz + 15) >> 4) << 1)
37 #ifdef CONFIG_PM
38 #define GET_USAGE_COUNT(dev) (atomic_read(&dev->power.usage_count))
39 #else
40 #define GET_USAGE_COUNT(dev) 1
41 #endif
42 
43 int free_stream_context(struct intel_sst_drv *ctx, unsigned int str_id)
44 {
45 	struct stream_info *stream;
46 	int ret = 0;
47 
48 	stream = get_stream_info(ctx, str_id);
49 	if (stream) {
50 		/* str_id is valid, so stream is alloacted */
51 		ret = sst_free_stream(ctx, str_id);
52 		if (ret)
53 			sst_clean_stream(&ctx->streams[str_id]);
54 		return ret;
55 	} else {
56 		dev_err(ctx->dev, "we tried to free stream context %d which was freed!!!\n", str_id);
57 	}
58 	return ret;
59 }
60 
61 int sst_get_stream_allocated(struct intel_sst_drv *ctx,
62 	struct snd_sst_params *str_param,
63 	struct snd_sst_lib_download **lib_dnld)
64 {
65 	int retval;
66 
67 	retval = ctx->ops->alloc_stream(ctx, str_param);
68 	if (retval > 0)
69 		dev_dbg(ctx->dev, "Stream allocated %d\n", retval);
70 	return retval;
71 
72 }
73 
74 /*
75  * sst_get_sfreq - this function returns the frequency of the stream
76  *
77  * @str_param : stream params
78  */
79 int sst_get_sfreq(struct snd_sst_params *str_param)
80 {
81 	switch (str_param->codec) {
82 	case SST_CODEC_TYPE_PCM:
83 		return str_param->sparams.uc.pcm_params.sfreq;
84 	case SST_CODEC_TYPE_AAC:
85 		return str_param->sparams.uc.aac_params.externalsr;
86 	case SST_CODEC_TYPE_MP3:
87 		return 0;
88 	default:
89 		return -EINVAL;
90 	}
91 }
92 
93 /*
94  * sst_get_num_channel - get number of channels for the stream
95  *
96  * @str_param : stream params
97  */
98 int sst_get_num_channel(struct snd_sst_params *str_param)
99 {
100 	switch (str_param->codec) {
101 	case SST_CODEC_TYPE_PCM:
102 		return str_param->sparams.uc.pcm_params.num_chan;
103 	case SST_CODEC_TYPE_MP3:
104 		return str_param->sparams.uc.mp3_params.num_chan;
105 	case SST_CODEC_TYPE_AAC:
106 		return str_param->sparams.uc.aac_params.num_chan;
107 	default:
108 		return -EINVAL;
109 	}
110 }
111 
112 /*
113  * sst_get_stream - this function prepares for stream allocation
114  *
115  * @str_param : stream param
116  */
117 int sst_get_stream(struct intel_sst_drv *ctx,
118 			struct snd_sst_params *str_param)
119 {
120 	int retval;
121 	struct stream_info *str_info;
122 
123 	/* stream is not allocated, we are allocating */
124 	retval = ctx->ops->alloc_stream(ctx, str_param);
125 	if (retval <= 0) {
126 		return -EIO;
127 	}
128 	/* store sampling freq */
129 	str_info = &ctx->streams[retval];
130 	str_info->sfreq = sst_get_sfreq(str_param);
131 
132 	return retval;
133 }
134 
135 static int sst_power_control(struct device *dev, bool state)
136 {
137 	struct intel_sst_drv *ctx = dev_get_drvdata(dev);
138 	int ret = 0;
139 	int usage_count = 0;
140 
141 	if (state) {
142 		ret = pm_runtime_get_sync(dev);
143 		usage_count = GET_USAGE_COUNT(dev);
144 		dev_dbg(ctx->dev, "Enable: pm usage count: %d\n", usage_count);
145 		if (ret < 0) {
146 			pm_runtime_put_sync(dev);
147 			dev_err(ctx->dev, "Runtime get failed with err: %d\n", ret);
148 			return ret;
149 		}
150 		if ((ctx->sst_state == SST_RESET) && (usage_count == 1)) {
151 			ret = sst_load_fw(ctx);
152 			if (ret) {
153 				dev_err(dev, "FW download fail %d\n", ret);
154 				sst_set_fw_state_locked(ctx, SST_RESET);
155 				ret = sst_pm_runtime_put(ctx);
156 			}
157 		}
158 	} else {
159 		usage_count = GET_USAGE_COUNT(dev);
160 		dev_dbg(ctx->dev, "Disable: pm usage count: %d\n", usage_count);
161 		return sst_pm_runtime_put(ctx);
162 	}
163 	return ret;
164 }
165 
166 /*
167  * sst_open_pcm_stream - Open PCM interface
168  *
169  * @str_param: parameters of pcm stream
170  *
171  * This function is called by MID sound card driver to open
172  * a new pcm interface
173  */
174 static int sst_open_pcm_stream(struct device *dev,
175 		struct snd_sst_params *str_param)
176 {
177 	int retval;
178 	struct intel_sst_drv *ctx = dev_get_drvdata(dev);
179 
180 	if (!str_param)
181 		return -EINVAL;
182 
183 	retval = sst_get_stream(ctx, str_param);
184 	if (retval > 0)
185 		ctx->stream_cnt++;
186 	else
187 		dev_err(ctx->dev, "sst_get_stream returned err %d\n", retval);
188 
189 	return retval;
190 }
191 
192 static int sst_cdev_open(struct device *dev,
193 		struct snd_sst_params *str_params, struct sst_compress_cb *cb)
194 {
195 	int str_id, retval;
196 	struct stream_info *stream;
197 	struct intel_sst_drv *ctx = dev_get_drvdata(dev);
198 
199 	retval = pm_runtime_get_sync(ctx->dev);
200 	if (retval < 0) {
201 		pm_runtime_put_sync(ctx->dev);
202 		return retval;
203 	}
204 
205 	str_id = sst_get_stream(ctx, str_params);
206 	if (str_id > 0) {
207 		dev_dbg(dev, "stream allocated in sst_cdev_open %d\n", str_id);
208 		stream = &ctx->streams[str_id];
209 		stream->compr_cb = cb->compr_cb;
210 		stream->compr_cb_param = cb->param;
211 		stream->drain_notify = cb->drain_notify;
212 		stream->drain_cb_param = cb->drain_cb_param;
213 	} else {
214 		dev_err(dev, "stream encountered error during alloc %d\n", str_id);
215 		str_id = -EINVAL;
216 		sst_pm_runtime_put(ctx);
217 	}
218 	return str_id;
219 }
220 
221 static int sst_cdev_close(struct device *dev, unsigned int str_id)
222 {
223 	int retval;
224 	struct stream_info *stream;
225 	struct intel_sst_drv *ctx = dev_get_drvdata(dev);
226 
227 	stream = get_stream_info(ctx, str_id);
228 	if (!stream) {
229 		dev_err(dev, "stream info is NULL for str %d!!!\n", str_id);
230 		return -EINVAL;
231 	}
232 
233 	retval = sst_free_stream(ctx, str_id);
234 	stream->compr_cb_param = NULL;
235 	stream->compr_cb = NULL;
236 
237 	if (retval)
238 		dev_err(dev, "free stream returned err %d\n", retval);
239 
240 	dev_dbg(dev, "End\n");
241 	return retval;
242 }
243 
244 static int sst_cdev_ack(struct device *dev, unsigned int str_id,
245 		unsigned long bytes)
246 {
247 	struct stream_info *stream;
248 	struct snd_sst_tstamp fw_tstamp = {0,};
249 	int offset;
250 	void __iomem *addr;
251 	struct intel_sst_drv *ctx = dev_get_drvdata(dev);
252 
253 	stream = get_stream_info(ctx, str_id);
254 	if (!stream)
255 		return -EINVAL;
256 
257 	/* update bytes sent */
258 	stream->cumm_bytes += bytes;
259 	dev_dbg(dev, "bytes copied %d inc by %ld\n", stream->cumm_bytes, bytes);
260 
261 	addr =  ((void __iomem *)(ctx->mailbox + ctx->tstamp)) +
262 		(str_id * sizeof(fw_tstamp));
263 
264 	memcpy_fromio(&fw_tstamp, addr, sizeof(fw_tstamp));
265 
266 	fw_tstamp.bytes_copied = stream->cumm_bytes;
267 	dev_dbg(dev, "bytes sent to fw %llu inc by %ld\n",
268 			fw_tstamp.bytes_copied, bytes);
269 
270 	offset =  offsetof(struct snd_sst_tstamp, bytes_copied);
271 	sst_shim_write(addr, offset, fw_tstamp.bytes_copied);
272 	return 0;
273 }
274 
275 static int sst_cdev_set_metadata(struct device *dev,
276 		unsigned int str_id, struct snd_compr_metadata *metadata)
277 {
278 	int retval = 0;
279 	struct stream_info *str_info;
280 	struct intel_sst_drv *ctx = dev_get_drvdata(dev);
281 
282 	dev_dbg(dev, "set metadata for stream %d\n", str_id);
283 
284 	str_info = get_stream_info(ctx, str_id);
285 	if (!str_info)
286 		return -EINVAL;
287 
288 	dev_dbg(dev, "pipe id = %d\n", str_info->pipe_id);
289 	retval = sst_prepare_and_post_msg(ctx, str_info->task_id, IPC_CMD,
290 			IPC_IA_SET_STREAM_PARAMS_MRFLD, str_info->pipe_id,
291 			sizeof(*metadata), metadata, NULL,
292 			true, true, true, false);
293 
294 	return retval;
295 }
296 
297 static int sst_cdev_stream_pause(struct device *dev, unsigned int str_id)
298 {
299 	struct intel_sst_drv *ctx = dev_get_drvdata(dev);
300 
301 	return sst_pause_stream(ctx, str_id);
302 }
303 
304 static int sst_cdev_stream_pause_release(struct device *dev,
305 		unsigned int str_id)
306 {
307 	struct intel_sst_drv *ctx = dev_get_drvdata(dev);
308 
309 	return sst_resume_stream(ctx, str_id);
310 }
311 
312 static int sst_cdev_stream_start(struct device *dev, unsigned int str_id)
313 {
314 	struct stream_info *str_info;
315 	struct intel_sst_drv *ctx = dev_get_drvdata(dev);
316 
317 	str_info = get_stream_info(ctx, str_id);
318 	if (!str_info)
319 		return -EINVAL;
320 	str_info->prev = str_info->status;
321 	str_info->status = STREAM_RUNNING;
322 	return sst_start_stream(ctx, str_id);
323 }
324 
325 static int sst_cdev_stream_drop(struct device *dev, unsigned int str_id)
326 {
327 	struct intel_sst_drv *ctx = dev_get_drvdata(dev);
328 
329 	return sst_drop_stream(ctx, str_id);
330 }
331 
332 static int sst_cdev_stream_drain(struct device *dev, unsigned int str_id)
333 {
334 	struct intel_sst_drv *ctx = dev_get_drvdata(dev);
335 
336 	return sst_drain_stream(ctx, str_id, false);
337 }
338 
339 static int sst_cdev_stream_partial_drain(struct device *dev,
340 		unsigned int str_id)
341 {
342 	struct intel_sst_drv *ctx = dev_get_drvdata(dev);
343 
344 	return sst_drain_stream(ctx, str_id, true);
345 }
346 
347 static int sst_cdev_tstamp(struct device *dev, unsigned int str_id,
348 		struct snd_compr_tstamp *tstamp)
349 {
350 	struct snd_sst_tstamp fw_tstamp = {0,};
351 	struct stream_info *stream;
352 	struct intel_sst_drv *ctx = dev_get_drvdata(dev);
353 	void __iomem *addr;
354 
355 	addr = (void __iomem *)(ctx->mailbox + ctx->tstamp) +
356 		(str_id * sizeof(fw_tstamp));
357 
358 	memcpy_fromio(&fw_tstamp, addr, sizeof(fw_tstamp));
359 
360 	stream = get_stream_info(ctx, str_id);
361 	if (!stream)
362 		return -EINVAL;
363 	dev_dbg(dev, "rb_counter %llu in bytes\n", fw_tstamp.ring_buffer_counter);
364 
365 	tstamp->copied_total = fw_tstamp.ring_buffer_counter;
366 	tstamp->pcm_frames = fw_tstamp.frames_decoded;
367 	tstamp->pcm_io_frames = div_u64(fw_tstamp.hardware_counter,
368 			(u64)stream->num_ch * SST_GET_BYTES_PER_SAMPLE(24));
369 	tstamp->sampling_rate = fw_tstamp.sampling_frequency;
370 
371 	dev_dbg(dev, "PCM  = %u\n", tstamp->pcm_io_frames);
372 	dev_dbg(dev, "Ptr Query on strid = %d  copied_total %d, decodec %d\n",
373 		str_id, tstamp->copied_total, tstamp->pcm_frames);
374 	dev_dbg(dev, "rendered %d\n", tstamp->pcm_io_frames);
375 
376 	return 0;
377 }
378 
379 static int sst_cdev_caps(struct snd_compr_caps *caps)
380 {
381 	caps->num_codecs = NUM_CODEC;
382 	caps->min_fragment_size = MIN_FRAGMENT_SIZE;  /* 50KB */
383 	caps->max_fragment_size = MAX_FRAGMENT_SIZE;  /* 1024KB */
384 	caps->min_fragments = MIN_FRAGMENT;
385 	caps->max_fragments = MAX_FRAGMENT;
386 	caps->codecs[0] = SND_AUDIOCODEC_MP3;
387 	caps->codecs[1] = SND_AUDIOCODEC_AAC;
388 	return 0;
389 }
390 
391 static const struct snd_compr_codec_caps caps_mp3 = {
392 	.num_descriptors = 1,
393 	.descriptor[0].max_ch = 2,
394 	.descriptor[0].sample_rates[0] = 48000,
395 	.descriptor[0].sample_rates[1] = 44100,
396 	.descriptor[0].sample_rates[2] = 32000,
397 	.descriptor[0].sample_rates[3] = 16000,
398 	.descriptor[0].sample_rates[4] = 8000,
399 	.descriptor[0].num_sample_rates = 5,
400 	.descriptor[0].bit_rate[0] = 320,
401 	.descriptor[0].bit_rate[1] = 192,
402 	.descriptor[0].num_bitrates = 2,
403 	.descriptor[0].profiles = 0,
404 	.descriptor[0].modes = SND_AUDIOCHANMODE_MP3_STEREO,
405 	.descriptor[0].formats = 0,
406 };
407 
408 static const struct snd_compr_codec_caps caps_aac = {
409 	.num_descriptors = 2,
410 	.descriptor[1].max_ch = 2,
411 	.descriptor[0].sample_rates[0] = 48000,
412 	.descriptor[0].sample_rates[1] = 44100,
413 	.descriptor[0].sample_rates[2] = 32000,
414 	.descriptor[0].sample_rates[3] = 16000,
415 	.descriptor[0].sample_rates[4] = 8000,
416 	.descriptor[0].num_sample_rates = 5,
417 	.descriptor[1].bit_rate[0] = 320,
418 	.descriptor[1].bit_rate[1] = 192,
419 	.descriptor[1].num_bitrates = 2,
420 	.descriptor[1].profiles = 0,
421 	.descriptor[1].modes = 0,
422 	.descriptor[1].formats =
423 			(SND_AUDIOSTREAMFORMAT_MP4ADTS |
424 				SND_AUDIOSTREAMFORMAT_RAW),
425 };
426 
427 static int sst_cdev_codec_caps(struct snd_compr_codec_caps *codec)
428 {
429 	if (codec->codec == SND_AUDIOCODEC_MP3)
430 		*codec = caps_mp3;
431 	else if (codec->codec == SND_AUDIOCODEC_AAC)
432 		*codec = caps_aac;
433 	else
434 		return -EINVAL;
435 
436 	return 0;
437 }
438 
439 void sst_cdev_fragment_elapsed(struct intel_sst_drv *ctx, int str_id)
440 {
441 	struct stream_info *stream;
442 
443 	dev_dbg(ctx->dev, "fragment elapsed from firmware for str_id %d\n",
444 			str_id);
445 	stream = &ctx->streams[str_id];
446 	if (stream->compr_cb)
447 		stream->compr_cb(stream->compr_cb_param);
448 }
449 
450 /*
451  * sst_close_pcm_stream - Close PCM interface
452  *
453  * @str_id: stream id to be closed
454  *
455  * This function is called by MID sound card driver to close
456  * an existing pcm interface
457  */
458 static int sst_close_pcm_stream(struct device *dev, unsigned int str_id)
459 {
460 	struct stream_info *stream;
461 	int retval = 0;
462 	struct intel_sst_drv *ctx = dev_get_drvdata(dev);
463 
464 	stream = get_stream_info(ctx, str_id);
465 	if (!stream) {
466 		dev_err(ctx->dev, "stream info is NULL for str %d!!!\n", str_id);
467 		return -EINVAL;
468 	}
469 
470 	retval = free_stream_context(ctx, str_id);
471 	stream->pcm_substream = NULL;
472 	stream->status = STREAM_UN_INIT;
473 	stream->period_elapsed = NULL;
474 	ctx->stream_cnt--;
475 
476 	if (retval)
477 		dev_err(ctx->dev, "free stream returned err %d\n", retval);
478 
479 	dev_dbg(ctx->dev, "Exit\n");
480 	return 0;
481 }
482 
483 static inline int sst_calc_tstamp(struct intel_sst_drv *ctx,
484 		struct pcm_stream_info *info,
485 		struct snd_pcm_substream *substream,
486 		struct snd_sst_tstamp *fw_tstamp)
487 {
488 	size_t delay_bytes, delay_frames;
489 	size_t buffer_sz;
490 	u32 pointer_bytes, pointer_samples;
491 
492 	dev_dbg(ctx->dev, "mrfld ring_buffer_counter %llu in bytes\n",
493 			fw_tstamp->ring_buffer_counter);
494 	dev_dbg(ctx->dev, "mrfld hardware_counter %llu in bytes\n",
495 			 fw_tstamp->hardware_counter);
496 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
497 		delay_bytes = (size_t) (fw_tstamp->ring_buffer_counter -
498 					fw_tstamp->hardware_counter);
499 	else
500 		delay_bytes = (size_t) (fw_tstamp->hardware_counter -
501 					fw_tstamp->ring_buffer_counter);
502 	delay_frames = bytes_to_frames(substream->runtime, delay_bytes);
503 	buffer_sz = snd_pcm_lib_buffer_bytes(substream);
504 	div_u64_rem(fw_tstamp->ring_buffer_counter, buffer_sz, &pointer_bytes);
505 	pointer_samples = bytes_to_samples(substream->runtime, pointer_bytes);
506 
507 	dev_dbg(ctx->dev, "pcm delay %zu in bytes\n", delay_bytes);
508 
509 	info->buffer_ptr = pointer_samples / substream->runtime->channels;
510 
511 	info->pcm_delay = delay_frames;
512 	dev_dbg(ctx->dev, "buffer ptr %llu pcm_delay rep: %llu\n",
513 			info->buffer_ptr, info->pcm_delay);
514 	return 0;
515 }
516 
517 static int sst_read_timestamp(struct device *dev, struct pcm_stream_info *info)
518 {
519 	struct stream_info *stream;
520 	struct snd_pcm_substream *substream;
521 	struct snd_sst_tstamp fw_tstamp;
522 	unsigned int str_id;
523 	struct intel_sst_drv *ctx = dev_get_drvdata(dev);
524 	void __iomem *addr;
525 
526 	str_id = info->str_id;
527 	stream = get_stream_info(ctx, str_id);
528 	if (!stream)
529 		return -EINVAL;
530 
531 	if (!stream->pcm_substream)
532 		return -EINVAL;
533 	substream = stream->pcm_substream;
534 
535 	addr = (void __iomem *)(ctx->mailbox + ctx->tstamp) +
536 		(str_id * sizeof(fw_tstamp));
537 
538 	memcpy_fromio(&fw_tstamp, addr, sizeof(fw_tstamp));
539 
540 	return sst_calc_tstamp(ctx, info, substream, &fw_tstamp);
541 }
542 
543 static int sst_stream_start(struct device *dev, int str_id)
544 {
545 	struct stream_info *str_info;
546 	struct intel_sst_drv *ctx = dev_get_drvdata(dev);
547 
548 	if (ctx->sst_state != SST_FW_RUNNING)
549 		return 0;
550 	str_info = get_stream_info(ctx, str_id);
551 	if (!str_info)
552 		return -EINVAL;
553 	str_info->prev = str_info->status;
554 	str_info->status = STREAM_RUNNING;
555 	sst_start_stream(ctx, str_id);
556 
557 	return 0;
558 }
559 
560 static int sst_stream_drop(struct device *dev, int str_id)
561 {
562 	struct stream_info *str_info;
563 	struct intel_sst_drv *ctx = dev_get_drvdata(dev);
564 
565 	if (ctx->sst_state != SST_FW_RUNNING)
566 		return 0;
567 
568 	str_info = get_stream_info(ctx, str_id);
569 	if (!str_info)
570 		return -EINVAL;
571 	str_info->prev = STREAM_UN_INIT;
572 	str_info->status = STREAM_INIT;
573 	return sst_drop_stream(ctx, str_id);
574 }
575 
576 static int sst_stream_pause(struct device *dev, int str_id)
577 {
578 	struct stream_info *str_info;
579 	struct intel_sst_drv *ctx = dev_get_drvdata(dev);
580 
581 	if (ctx->sst_state != SST_FW_RUNNING)
582 		return 0;
583 
584 	str_info = get_stream_info(ctx, str_id);
585 	if (!str_info)
586 		return -EINVAL;
587 
588 	return sst_pause_stream(ctx, str_id);
589 }
590 
591 static int sst_stream_resume(struct device *dev, int str_id)
592 {
593 	struct stream_info *str_info;
594 	struct intel_sst_drv *ctx = dev_get_drvdata(dev);
595 
596 	if (ctx->sst_state != SST_FW_RUNNING)
597 		return 0;
598 
599 	str_info = get_stream_info(ctx, str_id);
600 	if (!str_info)
601 		return -EINVAL;
602 	return sst_resume_stream(ctx, str_id);
603 }
604 
605 static int sst_stream_init(struct device *dev, struct pcm_stream_info *str_info)
606 {
607 	int str_id = 0;
608 	struct stream_info *stream;
609 	struct intel_sst_drv *ctx = dev_get_drvdata(dev);
610 
611 	str_id = str_info->str_id;
612 
613 	if (ctx->sst_state != SST_FW_RUNNING)
614 		return 0;
615 
616 	stream = get_stream_info(ctx, str_id);
617 	if (!stream)
618 		return -EINVAL;
619 
620 	dev_dbg(ctx->dev, "setting the period ptrs\n");
621 	stream->pcm_substream = str_info->arg;
622 	stream->period_elapsed = str_info->period_elapsed;
623 	stream->sfreq = str_info->sfreq;
624 	stream->prev = stream->status;
625 	stream->status = STREAM_INIT;
626 	dev_dbg(ctx->dev,
627 		"pcm_substream %p, period_elapsed %p, sfreq %d, status %d\n",
628 		stream->pcm_substream, stream->period_elapsed,
629 		stream->sfreq, stream->status);
630 
631 	return 0;
632 }
633 
634 /*
635  * sst_set_byte_stream - Set generic params
636  *
637  * @cmd: control cmd to be set
638  * @arg: command argument
639  *
640  * This function is called by MID sound card driver to configure
641  * SST runtime params.
642  */
643 static int sst_send_byte_stream(struct device *dev,
644 		struct snd_sst_bytes_v2 *bytes)
645 {
646 	int ret_val = 0;
647 	struct intel_sst_drv *ctx = dev_get_drvdata(dev);
648 
649 	if (NULL == bytes)
650 		return -EINVAL;
651 	ret_val = pm_runtime_get_sync(ctx->dev);
652 	if (ret_val < 0) {
653 		pm_runtime_put_sync(ctx->dev);
654 		return ret_val;
655 	}
656 
657 	ret_val = sst_send_byte_stream_mrfld(ctx, bytes);
658 	sst_pm_runtime_put(ctx);
659 
660 	return ret_val;
661 }
662 
663 static struct sst_ops pcm_ops = {
664 	.open = sst_open_pcm_stream,
665 	.stream_init = sst_stream_init,
666 	.stream_start = sst_stream_start,
667 	.stream_drop = sst_stream_drop,
668 	.stream_pause = sst_stream_pause,
669 	.stream_pause_release = sst_stream_resume,
670 	.stream_read_tstamp = sst_read_timestamp,
671 	.send_byte_stream = sst_send_byte_stream,
672 	.close = sst_close_pcm_stream,
673 	.power = sst_power_control,
674 };
675 
676 static struct compress_sst_ops compr_ops = {
677 	.open = sst_cdev_open,
678 	.close = sst_cdev_close,
679 	.stream_pause = sst_cdev_stream_pause,
680 	.stream_pause_release = sst_cdev_stream_pause_release,
681 	.stream_start = sst_cdev_stream_start,
682 	.stream_drop = sst_cdev_stream_drop,
683 	.stream_drain = sst_cdev_stream_drain,
684 	.stream_partial_drain = sst_cdev_stream_partial_drain,
685 	.tstamp = sst_cdev_tstamp,
686 	.ack = sst_cdev_ack,
687 	.get_caps = sst_cdev_caps,
688 	.get_codec_caps = sst_cdev_codec_caps,
689 	.set_metadata = sst_cdev_set_metadata,
690 	.power = sst_power_control,
691 };
692 
693 static struct sst_device sst_dsp_device = {
694 	.name = "Intel(R) SST LPE",
695 	.dev = NULL,
696 	.ops = &pcm_ops,
697 	.compr_ops = &compr_ops,
698 };
699 
700 /*
701  * sst_register - function to register DSP
702  *
703  * This functions registers DSP with the platform driver
704  */
705 int sst_register(struct device *dev)
706 {
707 	int ret_val;
708 
709 	sst_dsp_device.dev = dev;
710 	ret_val = sst_register_dsp(&sst_dsp_device);
711 	if (ret_val)
712 		dev_err(dev, "Unable to register DSP with platform driver\n");
713 
714 	return ret_val;
715 }
716 
717 int sst_unregister(struct device *dev)
718 {
719 	return sst_unregister_dsp(&sst_dsp_device);
720 }
721