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