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