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