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