~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/sound/soc/intel/atom/sst/sst_drv_interface.c

Version: ~ [ linux-5.8 ] ~ [ linux-5.7.14 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.57 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.138 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.193 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.232 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.232 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.140 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.85 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  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 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp