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