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
free_stream_context(struct intel_sst_drv * ctx,unsigned int str_id)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
sst_get_stream_allocated(struct intel_sst_drv * ctx,struct snd_sst_params * str_param,struct snd_sst_lib_download ** lib_dnld)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 */
sst_get_sfreq(struct snd_sst_params * str_param)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 */
sst_get_num_channel(struct snd_sst_params * str_param)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 */
sst_get_stream(struct intel_sst_drv * ctx,struct snd_sst_params * str_param)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
sst_power_control(struct device * dev,bool state)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 */
sst_open_pcm_stream(struct device * dev,struct snd_sst_params * str_param)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
sst_cdev_open(struct device * dev,struct snd_sst_params * str_params,struct sst_compress_cb * cb)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
sst_cdev_close(struct device * dev,unsigned int str_id)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
sst_cdev_ack(struct device * dev,unsigned int str_id,unsigned long bytes)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
sst_cdev_set_metadata(struct device * dev,unsigned int str_id,struct snd_compr_metadata * metadata)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
sst_cdev_stream_pause(struct device * dev,unsigned int str_id)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
sst_cdev_stream_pause_release(struct device * dev,unsigned int str_id)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
sst_cdev_stream_start(struct device * dev,unsigned int str_id)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
sst_cdev_stream_drop(struct device * dev,unsigned int str_id)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
sst_cdev_stream_drain(struct device * dev,unsigned int str_id)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
sst_cdev_stream_partial_drain(struct device * dev,unsigned int str_id)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
sst_cdev_tstamp(struct device * dev,unsigned int str_id,struct snd_compr_tstamp * tstamp)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
sst_cdev_caps(struct snd_compr_caps * caps)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
sst_cdev_codec_caps(struct snd_compr_codec_caps * codec)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
sst_cdev_fragment_elapsed(struct intel_sst_drv * ctx,int str_id)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 */
sst_close_pcm_stream(struct device * dev,unsigned int str_id)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
sst_calc_tstamp(struct intel_sst_drv * ctx,struct pcm_stream_info * info,struct snd_pcm_substream * substream,struct snd_sst_tstamp * fw_tstamp)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
sst_read_timestamp(struct device * dev,struct pcm_stream_info * info)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
sst_stream_start(struct device * dev,int str_id)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
sst_stream_drop(struct device * dev,int str_id)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
sst_stream_pause(struct device * dev,int str_id)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
sst_stream_resume(struct device * dev,int str_id)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
sst_stream_init(struct device * dev,struct pcm_stream_info * str_info)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 */
sst_send_byte_stream(struct device * dev,struct snd_sst_bytes_v2 * bytes)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 */
sst_register(struct device * dev)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
sst_unregister(struct device * dev)717 int sst_unregister(struct device *dev)
718 {
719 return sst_unregister_dsp(&sst_dsp_device);
720 }
721