0001
0002
0003
0004
0005
0006
0007
0008
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
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
0073
0074
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
0092
0093
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
0111
0112
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
0121 retval = ctx->ops->alloc_stream(ctx, str_param);
0122 if (retval <= 0) {
0123 return -EIO;
0124 }
0125
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
0164
0165
0166
0167
0168
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
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;
0377 caps->max_fragment_size = MAX_FRAGMENT_SIZE;
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
0446
0447
0448
0449
0450
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
0630
0631
0632
0633
0634
0635
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
0694
0695
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 }