Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  *  sst_drv_interface.c - Intel SST Driver for audio engine
0004  *
0005  *  Copyright (C) 2008-14 Intel Corp
0006  *  Authors:    Vinod Koul <vinod.koul@intel.com>
0007  *      Harsha Priya <priya.harsha@intel.com>
0008  *      Dharageswari R <dharageswari.r@intel.com)
0009  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
0010  *
0011  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
0012  */
0013 #include <linux/delay.h>
0014 #include <linux/pci.h>
0015 #include <linux/fs.h>
0016 #include <linux/firmware.h>
0017 #include <linux/pm_runtime.h>
0018 #include <linux/pm_qos.h>
0019 #include <linux/math64.h>
0020 #include <sound/core.h>
0021 #include <sound/pcm.h>
0022 #include <sound/soc.h>
0023 #include <sound/compress_driver.h>
0024 #include <asm/platform_sst_audio.h>
0025 #include "../sst-mfld-platform.h"
0026 #include "sst.h"
0027 
0028 #define NUM_CODEC 2
0029 #define MIN_FRAGMENT 2
0030 #define MAX_FRAGMENT 4
0031 #define MIN_FRAGMENT_SIZE (50 * 1024)
0032 #define MAX_FRAGMENT_SIZE (1024 * 1024)
0033 #define SST_GET_BYTES_PER_SAMPLE(pcm_wd_sz)  (((pcm_wd_sz + 15) >> 4) << 1)
0034 #ifdef CONFIG_PM
0035 #define GET_USAGE_COUNT(dev) (atomic_read(&dev->power.usage_count))
0036 #else
0037 #define GET_USAGE_COUNT(dev) 1
0038 #endif
0039 
0040 int free_stream_context(struct intel_sst_drv *ctx, unsigned int str_id)
0041 {
0042     struct stream_info *stream;
0043     int ret = 0;
0044 
0045     stream = get_stream_info(ctx, str_id);
0046     if (stream) {
0047         /* str_id is valid, so stream is alloacted */
0048         ret = sst_free_stream(ctx, str_id);
0049         if (ret)
0050             sst_clean_stream(&ctx->streams[str_id]);
0051         return ret;
0052     } else {
0053         dev_err(ctx->dev, "we tried to free stream context %d which was freed!!!\n", str_id);
0054     }
0055     return ret;
0056 }
0057 
0058 int sst_get_stream_allocated(struct intel_sst_drv *ctx,
0059     struct snd_sst_params *str_param,
0060     struct snd_sst_lib_download **lib_dnld)
0061 {
0062     int retval;
0063 
0064     retval = ctx->ops->alloc_stream(ctx, str_param);
0065     if (retval > 0)
0066         dev_dbg(ctx->dev, "Stream allocated %d\n", retval);
0067     return retval;
0068 
0069 }
0070 
0071 /*
0072  * sst_get_sfreq - this function returns the frequency of the stream
0073  *
0074  * @str_param : stream params
0075  */
0076 int sst_get_sfreq(struct snd_sst_params *str_param)
0077 {
0078     switch (str_param->codec) {
0079     case SST_CODEC_TYPE_PCM:
0080         return str_param->sparams.uc.pcm_params.sfreq;
0081     case SST_CODEC_TYPE_AAC:
0082         return str_param->sparams.uc.aac_params.externalsr;
0083     case SST_CODEC_TYPE_MP3:
0084         return 0;
0085     default:
0086         return -EINVAL;
0087     }
0088 }
0089 
0090 /*
0091  * sst_get_num_channel - get number of channels for the stream
0092  *
0093  * @str_param : stream params
0094  */
0095 int sst_get_num_channel(struct snd_sst_params *str_param)
0096 {
0097     switch (str_param->codec) {
0098     case SST_CODEC_TYPE_PCM:
0099         return str_param->sparams.uc.pcm_params.num_chan;
0100     case SST_CODEC_TYPE_MP3:
0101         return str_param->sparams.uc.mp3_params.num_chan;
0102     case SST_CODEC_TYPE_AAC:
0103         return str_param->sparams.uc.aac_params.num_chan;
0104     default:
0105         return -EINVAL;
0106     }
0107 }
0108 
0109 /*
0110  * sst_get_stream - this function prepares for stream allocation
0111  *
0112  * @str_param : stream param
0113  */
0114 int sst_get_stream(struct intel_sst_drv *ctx,
0115             struct snd_sst_params *str_param)
0116 {
0117     int retval;
0118     struct stream_info *str_info;
0119 
0120     /* stream is not allocated, we are allocating */
0121     retval = ctx->ops->alloc_stream(ctx, str_param);
0122     if (retval <= 0) {
0123         return -EIO;
0124     }
0125     /* store sampling freq */
0126     str_info = &ctx->streams[retval];
0127     str_info->sfreq = sst_get_sfreq(str_param);
0128 
0129     return retval;
0130 }
0131 
0132 static int sst_power_control(struct device *dev, bool state)
0133 {
0134     struct intel_sst_drv *ctx = dev_get_drvdata(dev);
0135     int ret = 0;
0136     int usage_count = 0;
0137 
0138     if (state) {
0139         ret = pm_runtime_resume_and_get(dev);
0140         usage_count = GET_USAGE_COUNT(dev);
0141         dev_dbg(ctx->dev, "Enable: pm usage count: %d\n", usage_count);
0142         if (ret < 0) {
0143             dev_err(ctx->dev, "Runtime get failed with err: %d\n", ret);
0144             return ret;
0145         }
0146         if ((ctx->sst_state == SST_RESET) && (usage_count == 1)) {
0147             ret = sst_load_fw(ctx);
0148             if (ret) {
0149                 dev_err(dev, "FW download fail %d\n", ret);
0150                 sst_set_fw_state_locked(ctx, SST_RESET);
0151                 ret = sst_pm_runtime_put(ctx);
0152             }
0153         }
0154     } else {
0155         usage_count = GET_USAGE_COUNT(dev);
0156         dev_dbg(ctx->dev, "Disable: pm usage count: %d\n", usage_count);
0157         return sst_pm_runtime_put(ctx);
0158     }
0159     return ret;
0160 }
0161 
0162 /*
0163  * sst_open_pcm_stream - Open PCM interface
0164  *
0165  * @str_param: parameters of pcm stream
0166  *
0167  * This function is called by MID sound card driver to open
0168  * a new pcm interface
0169  */
0170 static int sst_open_pcm_stream(struct device *dev,
0171         struct snd_sst_params *str_param)
0172 {
0173     int retval;
0174     struct intel_sst_drv *ctx = dev_get_drvdata(dev);
0175 
0176     if (!str_param)
0177         return -EINVAL;
0178 
0179     retval = sst_get_stream(ctx, str_param);
0180     if (retval > 0)
0181         ctx->stream_cnt++;
0182     else
0183         dev_err(ctx->dev, "sst_get_stream returned err %d\n", retval);
0184 
0185     return retval;
0186 }
0187 
0188 static int sst_cdev_open(struct device *dev,
0189         struct snd_sst_params *str_params, struct sst_compress_cb *cb)
0190 {
0191     int str_id, retval;
0192     struct stream_info *stream;
0193     struct intel_sst_drv *ctx = dev_get_drvdata(dev);
0194 
0195     retval = pm_runtime_resume_and_get(ctx->dev);
0196     if (retval < 0)
0197         return retval;
0198 
0199     str_id = sst_get_stream(ctx, str_params);
0200     if (str_id > 0) {
0201         dev_dbg(dev, "stream allocated in sst_cdev_open %d\n", str_id);
0202         stream = &ctx->streams[str_id];
0203         stream->compr_cb = cb->compr_cb;
0204         stream->compr_cb_param = cb->param;
0205         stream->drain_notify = cb->drain_notify;
0206         stream->drain_cb_param = cb->drain_cb_param;
0207     } else {
0208         dev_err(dev, "stream encountered error during alloc %d\n", str_id);
0209         str_id = -EINVAL;
0210         sst_pm_runtime_put(ctx);
0211     }
0212     return str_id;
0213 }
0214 
0215 static int sst_cdev_close(struct device *dev, unsigned int str_id)
0216 {
0217     int retval;
0218     struct stream_info *stream;
0219     struct intel_sst_drv *ctx = dev_get_drvdata(dev);
0220 
0221     stream = get_stream_info(ctx, str_id);
0222     if (!stream) {
0223         dev_err(dev, "stream info is NULL for str %d!!!\n", str_id);
0224         return -EINVAL;
0225     }
0226 
0227     retval = sst_free_stream(ctx, str_id);
0228     stream->compr_cb_param = NULL;
0229     stream->compr_cb = NULL;
0230 
0231     if (retval)
0232         dev_err(dev, "free stream returned err %d\n", retval);
0233 
0234     dev_dbg(dev, "End\n");
0235     return retval;
0236 }
0237 
0238 static int sst_cdev_ack(struct device *dev, unsigned int str_id,
0239         unsigned long bytes)
0240 {
0241     struct stream_info *stream;
0242     struct snd_sst_tstamp fw_tstamp = {0,};
0243     int offset;
0244     void __iomem *addr;
0245     struct intel_sst_drv *ctx = dev_get_drvdata(dev);
0246 
0247     stream = get_stream_info(ctx, str_id);
0248     if (!stream)
0249         return -EINVAL;
0250 
0251     /* update bytes sent */
0252     stream->cumm_bytes += bytes;
0253     dev_dbg(dev, "bytes copied %d inc by %ld\n", stream->cumm_bytes, bytes);
0254 
0255     addr =  ((void __iomem *)(ctx->mailbox + ctx->tstamp)) +
0256         (str_id * sizeof(fw_tstamp));
0257 
0258     memcpy_fromio(&fw_tstamp, addr, sizeof(fw_tstamp));
0259 
0260     fw_tstamp.bytes_copied = stream->cumm_bytes;
0261     dev_dbg(dev, "bytes sent to fw %llu inc by %ld\n",
0262             fw_tstamp.bytes_copied, bytes);
0263 
0264     offset =  offsetof(struct snd_sst_tstamp, bytes_copied);
0265     sst_shim_write(addr, offset, fw_tstamp.bytes_copied);
0266     return 0;
0267 }
0268 
0269 static int sst_cdev_set_metadata(struct device *dev,
0270         unsigned int str_id, struct snd_compr_metadata *metadata)
0271 {
0272     int retval = 0;
0273     struct stream_info *str_info;
0274     struct intel_sst_drv *ctx = dev_get_drvdata(dev);
0275 
0276     dev_dbg(dev, "set metadata for stream %d\n", str_id);
0277 
0278     str_info = get_stream_info(ctx, str_id);
0279     if (!str_info)
0280         return -EINVAL;
0281 
0282     dev_dbg(dev, "pipe id = %d\n", str_info->pipe_id);
0283     retval = sst_prepare_and_post_msg(ctx, str_info->task_id, IPC_CMD,
0284             IPC_IA_SET_STREAM_PARAMS_MRFLD, str_info->pipe_id,
0285             sizeof(*metadata), metadata, NULL,
0286             true, true, true, false);
0287 
0288     return retval;
0289 }
0290 
0291 static int sst_cdev_stream_pause(struct device *dev, unsigned int str_id)
0292 {
0293     struct intel_sst_drv *ctx = dev_get_drvdata(dev);
0294 
0295     return sst_pause_stream(ctx, str_id);
0296 }
0297 
0298 static int sst_cdev_stream_pause_release(struct device *dev,
0299         unsigned int str_id)
0300 {
0301     struct intel_sst_drv *ctx = dev_get_drvdata(dev);
0302 
0303     return sst_resume_stream(ctx, str_id);
0304 }
0305 
0306 static int sst_cdev_stream_start(struct device *dev, unsigned int str_id)
0307 {
0308     struct stream_info *str_info;
0309     struct intel_sst_drv *ctx = dev_get_drvdata(dev);
0310 
0311     str_info = get_stream_info(ctx, str_id);
0312     if (!str_info)
0313         return -EINVAL;
0314     str_info->prev = str_info->status;
0315     str_info->status = STREAM_RUNNING;
0316     return sst_start_stream(ctx, str_id);
0317 }
0318 
0319 static int sst_cdev_stream_drop(struct device *dev, unsigned int str_id)
0320 {
0321     struct intel_sst_drv *ctx = dev_get_drvdata(dev);
0322 
0323     return sst_drop_stream(ctx, str_id);
0324 }
0325 
0326 static int sst_cdev_stream_drain(struct device *dev, unsigned int str_id)
0327 {
0328     struct intel_sst_drv *ctx = dev_get_drvdata(dev);
0329 
0330     return sst_drain_stream(ctx, str_id, false);
0331 }
0332 
0333 static int sst_cdev_stream_partial_drain(struct device *dev,
0334         unsigned int str_id)
0335 {
0336     struct intel_sst_drv *ctx = dev_get_drvdata(dev);
0337 
0338     return sst_drain_stream(ctx, str_id, true);
0339 }
0340 
0341 static int sst_cdev_tstamp(struct device *dev, unsigned int str_id,
0342         struct snd_compr_tstamp *tstamp)
0343 {
0344     struct snd_sst_tstamp fw_tstamp = {0,};
0345     struct stream_info *stream;
0346     struct intel_sst_drv *ctx = dev_get_drvdata(dev);
0347     void __iomem *addr;
0348 
0349     addr = (void __iomem *)(ctx->mailbox + ctx->tstamp) +
0350         (str_id * sizeof(fw_tstamp));
0351 
0352     memcpy_fromio(&fw_tstamp, addr, sizeof(fw_tstamp));
0353 
0354     stream = get_stream_info(ctx, str_id);
0355     if (!stream)
0356         return -EINVAL;
0357     dev_dbg(dev, "rb_counter %llu in bytes\n", fw_tstamp.ring_buffer_counter);
0358 
0359     tstamp->copied_total = fw_tstamp.ring_buffer_counter;
0360     tstamp->pcm_frames = fw_tstamp.frames_decoded;
0361     tstamp->pcm_io_frames = div_u64(fw_tstamp.hardware_counter,
0362             (u64)stream->num_ch * SST_GET_BYTES_PER_SAMPLE(24));
0363     tstamp->sampling_rate = fw_tstamp.sampling_frequency;
0364 
0365     dev_dbg(dev, "PCM  = %u\n", tstamp->pcm_io_frames);
0366     dev_dbg(dev, "Ptr Query on strid = %d  copied_total %d, decodec %d\n",
0367         str_id, tstamp->copied_total, tstamp->pcm_frames);
0368     dev_dbg(dev, "rendered %d\n", tstamp->pcm_io_frames);
0369 
0370     return 0;
0371 }
0372 
0373 static int sst_cdev_caps(struct snd_compr_caps *caps)
0374 {
0375     caps->num_codecs = NUM_CODEC;
0376     caps->min_fragment_size = MIN_FRAGMENT_SIZE;  /* 50KB */
0377     caps->max_fragment_size = MAX_FRAGMENT_SIZE;  /* 1024KB */
0378     caps->min_fragments = MIN_FRAGMENT;
0379     caps->max_fragments = MAX_FRAGMENT;
0380     caps->codecs[0] = SND_AUDIOCODEC_MP3;
0381     caps->codecs[1] = SND_AUDIOCODEC_AAC;
0382     return 0;
0383 }
0384 
0385 static const struct snd_compr_codec_caps caps_mp3 = {
0386     .num_descriptors = 1,
0387     .descriptor[0].max_ch = 2,
0388     .descriptor[0].sample_rates[0] = 48000,
0389     .descriptor[0].sample_rates[1] = 44100,
0390     .descriptor[0].sample_rates[2] = 32000,
0391     .descriptor[0].sample_rates[3] = 16000,
0392     .descriptor[0].sample_rates[4] = 8000,
0393     .descriptor[0].num_sample_rates = 5,
0394     .descriptor[0].bit_rate[0] = 320,
0395     .descriptor[0].bit_rate[1] = 192,
0396     .descriptor[0].num_bitrates = 2,
0397     .descriptor[0].profiles = 0,
0398     .descriptor[0].modes = SND_AUDIOCHANMODE_MP3_STEREO,
0399     .descriptor[0].formats = 0,
0400 };
0401 
0402 static const struct snd_compr_codec_caps caps_aac = {
0403     .num_descriptors = 2,
0404     .descriptor[1].max_ch = 2,
0405     .descriptor[0].sample_rates[0] = 48000,
0406     .descriptor[0].sample_rates[1] = 44100,
0407     .descriptor[0].sample_rates[2] = 32000,
0408     .descriptor[0].sample_rates[3] = 16000,
0409     .descriptor[0].sample_rates[4] = 8000,
0410     .descriptor[0].num_sample_rates = 5,
0411     .descriptor[1].bit_rate[0] = 320,
0412     .descriptor[1].bit_rate[1] = 192,
0413     .descriptor[1].num_bitrates = 2,
0414     .descriptor[1].profiles = 0,
0415     .descriptor[1].modes = 0,
0416     .descriptor[1].formats =
0417             (SND_AUDIOSTREAMFORMAT_MP4ADTS |
0418                 SND_AUDIOSTREAMFORMAT_RAW),
0419 };
0420 
0421 static int sst_cdev_codec_caps(struct snd_compr_codec_caps *codec)
0422 {
0423     if (codec->codec == SND_AUDIOCODEC_MP3)
0424         *codec = caps_mp3;
0425     else if (codec->codec == SND_AUDIOCODEC_AAC)
0426         *codec = caps_aac;
0427     else
0428         return -EINVAL;
0429 
0430     return 0;
0431 }
0432 
0433 void sst_cdev_fragment_elapsed(struct intel_sst_drv *ctx, int str_id)
0434 {
0435     struct stream_info *stream;
0436 
0437     dev_dbg(ctx->dev, "fragment elapsed from firmware for str_id %d\n",
0438             str_id);
0439     stream = &ctx->streams[str_id];
0440     if (stream->compr_cb)
0441         stream->compr_cb(stream->compr_cb_param);
0442 }
0443 
0444 /*
0445  * sst_close_pcm_stream - Close PCM interface
0446  *
0447  * @str_id: stream id to be closed
0448  *
0449  * This function is called by MID sound card driver to close
0450  * an existing pcm interface
0451  */
0452 static int sst_close_pcm_stream(struct device *dev, unsigned int str_id)
0453 {
0454     struct stream_info *stream;
0455     int retval = 0;
0456     struct intel_sst_drv *ctx = dev_get_drvdata(dev);
0457 
0458     stream = get_stream_info(ctx, str_id);
0459     if (!stream) {
0460         dev_err(ctx->dev, "stream info is NULL for str %d!!!\n", str_id);
0461         return -EINVAL;
0462     }
0463 
0464     retval = free_stream_context(ctx, str_id);
0465     stream->pcm_substream = NULL;
0466     stream->status = STREAM_UN_INIT;
0467     stream->period_elapsed = NULL;
0468     ctx->stream_cnt--;
0469 
0470     if (retval)
0471         dev_err(ctx->dev, "free stream returned err %d\n", retval);
0472 
0473     dev_dbg(ctx->dev, "Exit\n");
0474     return 0;
0475 }
0476 
0477 static inline int sst_calc_tstamp(struct intel_sst_drv *ctx,
0478         struct pcm_stream_info *info,
0479         struct snd_pcm_substream *substream,
0480         struct snd_sst_tstamp *fw_tstamp)
0481 {
0482     size_t delay_bytes, delay_frames;
0483     size_t buffer_sz;
0484     u32 pointer_bytes, pointer_samples;
0485 
0486     dev_dbg(ctx->dev, "mrfld ring_buffer_counter %llu in bytes\n",
0487             fw_tstamp->ring_buffer_counter);
0488     dev_dbg(ctx->dev, "mrfld hardware_counter %llu in bytes\n",
0489              fw_tstamp->hardware_counter);
0490     if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
0491         delay_bytes = (size_t) (fw_tstamp->ring_buffer_counter -
0492                     fw_tstamp->hardware_counter);
0493     else
0494         delay_bytes = (size_t) (fw_tstamp->hardware_counter -
0495                     fw_tstamp->ring_buffer_counter);
0496     delay_frames = bytes_to_frames(substream->runtime, delay_bytes);
0497     buffer_sz = snd_pcm_lib_buffer_bytes(substream);
0498     div_u64_rem(fw_tstamp->ring_buffer_counter, buffer_sz, &pointer_bytes);
0499     pointer_samples = bytes_to_samples(substream->runtime, pointer_bytes);
0500 
0501     dev_dbg(ctx->dev, "pcm delay %zu in bytes\n", delay_bytes);
0502 
0503     info->buffer_ptr = pointer_samples / substream->runtime->channels;
0504 
0505     info->pcm_delay = delay_frames;
0506     dev_dbg(ctx->dev, "buffer ptr %llu pcm_delay rep: %llu\n",
0507             info->buffer_ptr, info->pcm_delay);
0508     return 0;
0509 }
0510 
0511 static int sst_read_timestamp(struct device *dev, struct pcm_stream_info *info)
0512 {
0513     struct stream_info *stream;
0514     struct snd_pcm_substream *substream;
0515     struct snd_sst_tstamp fw_tstamp;
0516     unsigned int str_id;
0517     struct intel_sst_drv *ctx = dev_get_drvdata(dev);
0518     void __iomem *addr;
0519 
0520     str_id = info->str_id;
0521     stream = get_stream_info(ctx, str_id);
0522     if (!stream)
0523         return -EINVAL;
0524 
0525     if (!stream->pcm_substream)
0526         return -EINVAL;
0527     substream = stream->pcm_substream;
0528 
0529     addr = (void __iomem *)(ctx->mailbox + ctx->tstamp) +
0530         (str_id * sizeof(fw_tstamp));
0531 
0532     memcpy_fromio(&fw_tstamp, addr, sizeof(fw_tstamp));
0533 
0534     return sst_calc_tstamp(ctx, info, substream, &fw_tstamp);
0535 }
0536 
0537 static int sst_stream_start(struct device *dev, int str_id)
0538 {
0539     struct stream_info *str_info;
0540     struct intel_sst_drv *ctx = dev_get_drvdata(dev);
0541 
0542     if (ctx->sst_state != SST_FW_RUNNING)
0543         return 0;
0544     str_info = get_stream_info(ctx, str_id);
0545     if (!str_info)
0546         return -EINVAL;
0547     str_info->prev = str_info->status;
0548     str_info->status = STREAM_RUNNING;
0549     sst_start_stream(ctx, str_id);
0550 
0551     return 0;
0552 }
0553 
0554 static int sst_stream_drop(struct device *dev, int str_id)
0555 {
0556     struct stream_info *str_info;
0557     struct intel_sst_drv *ctx = dev_get_drvdata(dev);
0558 
0559     if (ctx->sst_state != SST_FW_RUNNING)
0560         return 0;
0561 
0562     str_info = get_stream_info(ctx, str_id);
0563     if (!str_info)
0564         return -EINVAL;
0565     str_info->prev = STREAM_UN_INIT;
0566     str_info->status = STREAM_INIT;
0567     return sst_drop_stream(ctx, str_id);
0568 }
0569 
0570 static int sst_stream_pause(struct device *dev, int str_id)
0571 {
0572     struct stream_info *str_info;
0573     struct intel_sst_drv *ctx = dev_get_drvdata(dev);
0574 
0575     if (ctx->sst_state != SST_FW_RUNNING)
0576         return 0;
0577 
0578     str_info = get_stream_info(ctx, str_id);
0579     if (!str_info)
0580         return -EINVAL;
0581 
0582     return sst_pause_stream(ctx, str_id);
0583 }
0584 
0585 static int sst_stream_resume(struct device *dev, int str_id)
0586 {
0587     struct stream_info *str_info;
0588     struct intel_sst_drv *ctx = dev_get_drvdata(dev);
0589 
0590     if (ctx->sst_state != SST_FW_RUNNING)
0591         return 0;
0592 
0593     str_info = get_stream_info(ctx, str_id);
0594     if (!str_info)
0595         return -EINVAL;
0596     return sst_resume_stream(ctx, str_id);
0597 }
0598 
0599 static int sst_stream_init(struct device *dev, struct pcm_stream_info *str_info)
0600 {
0601     int str_id = 0;
0602     struct stream_info *stream;
0603     struct intel_sst_drv *ctx = dev_get_drvdata(dev);
0604 
0605     str_id = str_info->str_id;
0606 
0607     if (ctx->sst_state != SST_FW_RUNNING)
0608         return 0;
0609 
0610     stream = get_stream_info(ctx, str_id);
0611     if (!stream)
0612         return -EINVAL;
0613 
0614     dev_dbg(ctx->dev, "setting the period ptrs\n");
0615     stream->pcm_substream = str_info->arg;
0616     stream->period_elapsed = str_info->period_elapsed;
0617     stream->sfreq = str_info->sfreq;
0618     stream->prev = stream->status;
0619     stream->status = STREAM_INIT;
0620     dev_dbg(ctx->dev,
0621         "pcm_substream %p, period_elapsed %p, sfreq %d, status %d\n",
0622         stream->pcm_substream, stream->period_elapsed,
0623         stream->sfreq, stream->status);
0624 
0625     return 0;
0626 }
0627 
0628 /*
0629  * sst_set_byte_stream - Set generic params
0630  *
0631  * @cmd: control cmd to be set
0632  * @arg: command argument
0633  *
0634  * This function is called by MID sound card driver to configure
0635  * SST runtime params.
0636  */
0637 static int sst_send_byte_stream(struct device *dev,
0638         struct snd_sst_bytes_v2 *bytes)
0639 {
0640     int ret_val = 0;
0641     struct intel_sst_drv *ctx = dev_get_drvdata(dev);
0642 
0643     if (NULL == bytes)
0644         return -EINVAL;
0645     ret_val = pm_runtime_resume_and_get(ctx->dev);
0646     if (ret_val < 0)
0647         return ret_val;
0648 
0649     ret_val = sst_send_byte_stream_mrfld(ctx, bytes);
0650     sst_pm_runtime_put(ctx);
0651 
0652     return ret_val;
0653 }
0654 
0655 static struct sst_ops pcm_ops = {
0656     .open = sst_open_pcm_stream,
0657     .stream_init = sst_stream_init,
0658     .stream_start = sst_stream_start,
0659     .stream_drop = sst_stream_drop,
0660     .stream_pause = sst_stream_pause,
0661     .stream_pause_release = sst_stream_resume,
0662     .stream_read_tstamp = sst_read_timestamp,
0663     .send_byte_stream = sst_send_byte_stream,
0664     .close = sst_close_pcm_stream,
0665     .power = sst_power_control,
0666 };
0667 
0668 static struct compress_sst_ops compr_ops = {
0669     .open = sst_cdev_open,
0670     .close = sst_cdev_close,
0671     .stream_pause = sst_cdev_stream_pause,
0672     .stream_pause_release = sst_cdev_stream_pause_release,
0673     .stream_start = sst_cdev_stream_start,
0674     .stream_drop = sst_cdev_stream_drop,
0675     .stream_drain = sst_cdev_stream_drain,
0676     .stream_partial_drain = sst_cdev_stream_partial_drain,
0677     .tstamp = sst_cdev_tstamp,
0678     .ack = sst_cdev_ack,
0679     .get_caps = sst_cdev_caps,
0680     .get_codec_caps = sst_cdev_codec_caps,
0681     .set_metadata = sst_cdev_set_metadata,
0682     .power = sst_power_control,
0683 };
0684 
0685 static struct sst_device sst_dsp_device = {
0686     .name = "Intel(R) SST LPE",
0687     .dev = NULL,
0688     .ops = &pcm_ops,
0689     .compr_ops = &compr_ops,
0690 };
0691 
0692 /*
0693  * sst_register - function to register DSP
0694  *
0695  * This functions registers DSP with the platform driver
0696  */
0697 int sst_register(struct device *dev)
0698 {
0699     int ret_val;
0700 
0701     sst_dsp_device.dev = dev;
0702     ret_val = sst_register_dsp(&sst_dsp_device);
0703     if (ret_val)
0704         dev_err(dev, "Unable to register DSP with platform driver\n");
0705 
0706     return ret_val;
0707 }
0708 
0709 int sst_unregister(struct device *dev)
0710 {
0711     return sst_unregister_dsp(&sst_dsp_device);
0712 }