root/sound/soc/intel/atom/sst/sst_drv_interface.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. free_stream_context
  2. sst_get_stream_allocated
  3. sst_get_sfreq
  4. sst_get_num_channel
  5. sst_get_stream
  6. sst_power_control
  7. sst_open_pcm_stream
  8. sst_cdev_open
  9. sst_cdev_close
  10. sst_cdev_ack
  11. sst_cdev_set_metadata
  12. sst_cdev_stream_pause
  13. sst_cdev_stream_pause_release
  14. sst_cdev_stream_start
  15. sst_cdev_stream_drop
  16. sst_cdev_stream_drain
  17. sst_cdev_stream_partial_drain
  18. sst_cdev_tstamp
  19. sst_cdev_caps
  20. sst_cdev_codec_caps
  21. sst_cdev_fragment_elapsed
  22. sst_close_pcm_stream
  23. sst_calc_tstamp
  24. sst_read_timestamp
  25. sst_stream_start
  26. sst_stream_drop
  27. sst_stream_pause
  28. sst_stream_resume
  29. sst_stream_init
  30. sst_send_byte_stream
  31. sst_register
  32. sst_unregister

   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 }

/* [<][>][^][v][top][bottom][index][help] */