1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * sst_mfld_platform.c - Intel MID Platform driver 4 * 5 * Copyright (C) 2010-2014 Intel Corp 6 * Author: Vinod Koul <vinod.koul@intel.com> 7 * Author: Harsha Priya <priya.harsha@intel.com> 8 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 9 * 10 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 11 */ 12 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 13 14 #include <linux/cleanup.h> 15 #include <linux/slab.h> 16 #include <linux/io.h> 17 #include <linux/module.h> 18 #include <sound/core.h> 19 #include <sound/pcm.h> 20 #include <sound/pcm_params.h> 21 #include <sound/soc.h> 22 #include <sound/compress_driver.h> 23 #include <asm/platform_sst_audio.h> 24 #include "sst-mfld-platform.h" 25 #include "sst-atom-controls.h" 26 27 struct sst_device *sst; 28 static DEFINE_MUTEX(sst_lock); 29 30 int sst_register_dsp(struct sst_device *dev) 31 { 32 if (WARN_ON(!dev)) 33 return -EINVAL; 34 if (!try_module_get(dev->dev->driver->owner)) 35 return -ENODEV; 36 guard(mutex)(&sst_lock); 37 if (sst) { 38 dev_err(dev->dev, "we already have a device %s\n", sst->name); 39 module_put(dev->dev->driver->owner); 40 mutex_unlock(&sst_lock); 41 return -EEXIST; 42 } 43 dev_dbg(dev->dev, "registering device %s\n", dev->name); 44 sst = dev; 45 46 return 0; 47 } 48 EXPORT_SYMBOL_GPL(sst_register_dsp); 49 50 int sst_unregister_dsp(struct sst_device *dev) 51 { 52 if (WARN_ON(!dev)) 53 return -EINVAL; 54 if (dev != sst) 55 return -EINVAL; 56 57 guard(mutex)(&sst_lock); 58 59 if (!sst) 60 return -EIO; 61 62 module_put(sst->dev->driver->owner); 63 dev_dbg(dev->dev, "unreg %s\n", sst->name); 64 sst = NULL; 65 66 return 0; 67 } 68 EXPORT_SYMBOL_GPL(sst_unregister_dsp); 69 70 static const struct snd_pcm_hardware sst_platform_pcm_hw = { 71 .info = (SNDRV_PCM_INFO_INTERLEAVED | 72 SNDRV_PCM_INFO_DOUBLE | 73 SNDRV_PCM_INFO_PAUSE | 74 SNDRV_PCM_INFO_RESUME | 75 SNDRV_PCM_INFO_MMAP| 76 SNDRV_PCM_INFO_MMAP_VALID | 77 SNDRV_PCM_INFO_BLOCK_TRANSFER | 78 SNDRV_PCM_INFO_SYNC_START), 79 .buffer_bytes_max = SST_MAX_BUFFER, 80 .period_bytes_min = SST_MIN_PERIOD_BYTES, 81 .period_bytes_max = SST_MAX_PERIOD_BYTES, 82 .periods_min = SST_MIN_PERIODS, 83 .periods_max = SST_MAX_PERIODS, 84 .fifo_size = SST_FIFO_SIZE, 85 }; 86 87 static struct sst_dev_stream_map dpcm_strm_map[] = { 88 {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, /* Reserved, not in use */ 89 {MERR_DPCM_AUDIO, 0, SNDRV_PCM_STREAM_PLAYBACK, PIPE_MEDIA1_IN, SST_TASK_ID_MEDIA, 0}, 90 {MERR_DPCM_COMPR, 0, SNDRV_PCM_STREAM_PLAYBACK, PIPE_MEDIA0_IN, SST_TASK_ID_MEDIA, 0}, 91 {MERR_DPCM_AUDIO, 0, SNDRV_PCM_STREAM_CAPTURE, PIPE_PCM1_OUT, SST_TASK_ID_MEDIA, 0}, 92 {MERR_DPCM_DEEP_BUFFER, 0, SNDRV_PCM_STREAM_PLAYBACK, PIPE_MEDIA3_IN, SST_TASK_ID_MEDIA, 0}, 93 }; 94 95 static int sst_media_digital_mute(struct snd_soc_dai *dai, int mute, int stream) 96 { 97 98 return sst_send_pipe_gains(dai, stream, mute); 99 } 100 101 /* helper functions */ 102 void sst_set_stream_status(struct sst_runtime_stream *stream, 103 int state) 104 { 105 guard(spinlock_irqsave)(&stream->status_lock); 106 stream->stream_status = state; 107 } 108 109 static inline int sst_get_stream_status(struct sst_runtime_stream *stream) 110 { 111 guard(spinlock_irqsave)(&stream->status_lock); 112 return stream->stream_status; 113 } 114 115 static void sst_fill_alloc_params(struct snd_pcm_substream *substream, 116 struct snd_sst_alloc_params_ext *alloc_param) 117 { 118 unsigned int channels; 119 snd_pcm_uframes_t period_size; 120 ssize_t periodbytes; 121 ssize_t buffer_bytes = snd_pcm_lib_buffer_bytes(substream); 122 u32 buffer_addr = substream->runtime->dma_addr; 123 124 channels = substream->runtime->channels; 125 period_size = substream->runtime->period_size; 126 periodbytes = samples_to_bytes(substream->runtime, period_size); 127 alloc_param->ring_buf_info[0].addr = buffer_addr; 128 alloc_param->ring_buf_info[0].size = buffer_bytes; 129 alloc_param->sg_count = 1; 130 alloc_param->reserved = 0; 131 alloc_param->frag_size = periodbytes * channels; 132 133 } 134 static void sst_fill_pcm_params(struct snd_pcm_substream *substream, 135 struct snd_sst_stream_params *param) 136 { 137 param->uc.pcm_params.num_chan = (u8) substream->runtime->channels; 138 param->uc.pcm_params.pcm_wd_sz = substream->runtime->sample_bits; 139 param->uc.pcm_params.sfreq = substream->runtime->rate; 140 141 /* PCM stream via ALSA interface */ 142 param->uc.pcm_params.use_offload_path = 0; 143 param->uc.pcm_params.reserved2 = 0; 144 memset(param->uc.pcm_params.channel_map, 0, sizeof(u8)); 145 146 } 147 148 static int sst_get_stream_mapping(int dev, int sdev, int dir, 149 struct sst_dev_stream_map *map, int size) 150 { 151 int i; 152 153 if (map == NULL) 154 return -EINVAL; 155 156 157 /* index 0 is not used in stream map */ 158 for (i = 1; i < size; i++) { 159 if ((map[i].dev_num == dev) && (map[i].direction == dir)) 160 return i; 161 } 162 return 0; 163 } 164 165 int sst_fill_stream_params(void *substream, 166 const struct sst_data *ctx, struct snd_sst_params *str_params, bool is_compress) 167 { 168 int map_size; 169 int index; 170 struct sst_dev_stream_map *map; 171 struct snd_pcm_substream *pstream = NULL; 172 struct snd_compr_stream *cstream = NULL; 173 174 map = ctx->pdata->pdev_strm_map; 175 map_size = ctx->pdata->strm_map_size; 176 177 if (is_compress) 178 cstream = (struct snd_compr_stream *)substream; 179 else 180 pstream = (struct snd_pcm_substream *)substream; 181 182 str_params->stream_type = SST_STREAM_TYPE_MUSIC; 183 184 /* For pcm streams */ 185 if (pstream) { 186 index = sst_get_stream_mapping(pstream->pcm->device, 187 pstream->number, pstream->stream, 188 map, map_size); 189 if (index <= 0) 190 return -EINVAL; 191 192 str_params->stream_id = index; 193 str_params->device_type = map[index].device_id; 194 str_params->task = map[index].task_id; 195 196 str_params->ops = (u8)pstream->stream; 197 } 198 199 if (cstream) { 200 index = sst_get_stream_mapping(cstream->device->device, 201 0, cstream->direction, 202 map, map_size); 203 if (index <= 0) 204 return -EINVAL; 205 str_params->stream_id = index; 206 str_params->device_type = map[index].device_id; 207 str_params->task = map[index].task_id; 208 209 str_params->ops = (u8)cstream->direction; 210 } 211 return 0; 212 } 213 214 static int sst_platform_alloc_stream(struct snd_pcm_substream *substream, 215 struct snd_soc_dai *dai) 216 { 217 struct sst_runtime_stream *stream = 218 substream->runtime->private_data; 219 struct snd_sst_stream_params param = {{{0,},},}; 220 struct snd_sst_params str_params = {0}; 221 struct snd_sst_alloc_params_ext alloc_params = {0}; 222 int ret_val = 0; 223 struct sst_data *ctx = snd_soc_dai_get_drvdata(dai); 224 225 /* set codec params and inform SST driver the same */ 226 sst_fill_pcm_params(substream, ¶m); 227 sst_fill_alloc_params(substream, &alloc_params); 228 str_params.sparams = param; 229 str_params.aparams = alloc_params; 230 str_params.codec = SST_CODEC_TYPE_PCM; 231 232 /* fill the device type and stream id to pass to SST driver */ 233 ret_val = sst_fill_stream_params(substream, ctx, &str_params, false); 234 if (ret_val < 0) 235 return ret_val; 236 237 stream->stream_info.str_id = str_params.stream_id; 238 239 return stream->ops->open(sst->dev, &str_params); 240 } 241 242 static void sst_period_elapsed(void *arg) 243 { 244 struct snd_pcm_substream *substream = arg; 245 struct sst_runtime_stream *stream; 246 int status; 247 248 if (!substream || !substream->runtime) 249 return; 250 stream = substream->runtime->private_data; 251 if (!stream) 252 return; 253 status = sst_get_stream_status(stream); 254 if (status != SST_PLATFORM_RUNNING) 255 return; 256 snd_pcm_period_elapsed(substream); 257 } 258 259 static int sst_platform_init_stream(struct snd_pcm_substream *substream) 260 { 261 struct sst_runtime_stream *stream = 262 substream->runtime->private_data; 263 struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); 264 int ret_val; 265 266 dev_dbg(rtd->dev, "setting buffer ptr param\n"); 267 sst_set_stream_status(stream, SST_PLATFORM_INIT); 268 stream->stream_info.period_elapsed = sst_period_elapsed; 269 stream->stream_info.arg = substream; 270 stream->stream_info.buffer_ptr = 0; 271 stream->stream_info.sfreq = substream->runtime->rate; 272 ret_val = stream->ops->stream_init(sst->dev, &stream->stream_info); 273 if (ret_val) 274 dev_err(rtd->dev, "control_set ret error %d\n", ret_val); 275 return ret_val; 276 277 } 278 279 static int power_up_sst(struct sst_runtime_stream *stream) 280 { 281 return stream->ops->power(sst->dev, true); 282 } 283 284 static void power_down_sst(struct sst_runtime_stream *stream) 285 { 286 stream->ops->power(sst->dev, false); 287 } 288 289 static int sst_media_open(struct snd_pcm_substream *substream, 290 struct snd_soc_dai *dai) 291 { 292 int ret_val = 0; 293 struct snd_pcm_runtime *runtime = substream->runtime; 294 struct sst_runtime_stream *stream __free(kfree) = NULL; 295 296 stream = kzalloc_obj(*stream); 297 if (!stream) 298 return -ENOMEM; 299 spin_lock_init(&stream->status_lock); 300 301 /* get the sst ops */ 302 scoped_guard(mutex, &sst_lock) { 303 if (!sst || 304 !try_module_get(sst->dev->driver->owner)) { 305 dev_err(dai->dev, "no device available to run\n"); 306 return -ENODEV; 307 } 308 stream->ops = sst->ops; 309 } 310 311 stream->stream_info.str_id = 0; 312 313 stream->stream_info.arg = substream; 314 /* allocate memory for SST API set */ 315 runtime->private_data = stream; 316 317 ret_val = power_up_sst(stream); 318 if (ret_val < 0) 319 return ret_val; 320 321 /* 322 * Make sure the period to be multiple of 1ms to align the 323 * design of firmware. Apply same rule to buffer size to make 324 * sure alsa could always find a value for period size 325 * regardless the buffer size given by user space. 326 */ 327 snd_pcm_hw_constraint_step(substream->runtime, 0, 328 SNDRV_PCM_HW_PARAM_PERIOD_SIZE, 48); 329 snd_pcm_hw_constraint_step(substream->runtime, 0, 330 SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 48); 331 332 /* Make sure, that the period size is always even */ 333 snd_pcm_hw_constraint_step(substream->runtime, 0, 334 SNDRV_PCM_HW_PARAM_PERIODS, 2); 335 336 ret_val = snd_pcm_hw_constraint_integer(runtime, 337 SNDRV_PCM_HW_PARAM_PERIODS); 338 339 if (ret_val < 0) 340 return ret_val; 341 342 stream = NULL; 343 344 return ret_val; 345 } 346 347 static void sst_media_close(struct snd_pcm_substream *substream, 348 struct snd_soc_dai *dai) 349 { 350 struct sst_runtime_stream *stream; 351 int str_id; 352 353 stream = substream->runtime->private_data; 354 power_down_sst(stream); 355 356 str_id = stream->stream_info.str_id; 357 if (str_id) 358 stream->ops->close(sst->dev, str_id); 359 module_put(sst->dev->driver->owner); 360 kfree(stream); 361 } 362 363 static int sst_media_prepare(struct snd_pcm_substream *substream, 364 struct snd_soc_dai *dai) 365 { 366 struct sst_runtime_stream *stream; 367 int ret_val, str_id; 368 369 stream = substream->runtime->private_data; 370 str_id = stream->stream_info.str_id; 371 if (stream->stream_info.str_id) { 372 ret_val = stream->ops->stream_drop(sst->dev, str_id); 373 return ret_val; 374 } 375 376 ret_val = sst_platform_alloc_stream(substream, dai); 377 if (ret_val <= 0) 378 return ret_val; 379 snprintf(substream->pcm->id, sizeof(substream->pcm->id), 380 "%d", stream->stream_info.str_id); 381 382 ret_val = sst_platform_init_stream(substream); 383 if (ret_val) 384 return ret_val; 385 substream->runtime->hw.info = SNDRV_PCM_INFO_BLOCK_TRANSFER; 386 return 0; 387 } 388 389 static int sst_enable_ssp(struct snd_pcm_substream *substream, 390 struct snd_soc_dai *dai) 391 { 392 int ret = 0; 393 394 if (!snd_soc_dai_active(dai)) { 395 ret = sst_handle_vb_timer(dai, true); 396 sst_fill_ssp_defaults(dai); 397 } 398 return ret; 399 } 400 401 static int sst_be_hw_params(struct snd_pcm_substream *substream, 402 struct snd_pcm_hw_params *params, 403 struct snd_soc_dai *dai) 404 { 405 int ret = 0; 406 407 if (snd_soc_dai_active(dai) == 1) 408 ret = send_ssp_cmd(dai, dai->name, 1); 409 return ret; 410 } 411 412 static int sst_set_format(struct snd_soc_dai *dai, unsigned int fmt) 413 { 414 int ret = 0; 415 416 if (!snd_soc_dai_active(dai)) 417 return 0; 418 419 ret = sst_fill_ssp_config(dai, fmt); 420 if (ret < 0) 421 dev_err(dai->dev, "sst_set_format failed..\n"); 422 423 return ret; 424 } 425 426 static int sst_platform_set_ssp_slot(struct snd_soc_dai *dai, 427 unsigned int tx_mask, unsigned int rx_mask, 428 int slots, int slot_width) { 429 int ret = 0; 430 431 if (!snd_soc_dai_active(dai)) 432 return ret; 433 434 ret = sst_fill_ssp_slot(dai, tx_mask, rx_mask, slots, slot_width); 435 if (ret < 0) 436 dev_err(dai->dev, "sst_fill_ssp_slot failed..%d\n", ret); 437 438 return ret; 439 } 440 441 static void sst_disable_ssp(struct snd_pcm_substream *substream, 442 struct snd_soc_dai *dai) 443 { 444 if (!snd_soc_dai_active(dai)) { 445 send_ssp_cmd(dai, dai->name, 0); 446 sst_handle_vb_timer(dai, false); 447 } 448 } 449 450 static const struct snd_soc_dai_ops sst_media_dai_ops = { 451 .startup = sst_media_open, 452 .shutdown = sst_media_close, 453 .prepare = sst_media_prepare, 454 .mute_stream = sst_media_digital_mute, 455 }; 456 457 static const struct snd_soc_dai_ops sst_compr_dai_ops = { 458 .compress_new = snd_soc_new_compress, 459 .mute_stream = sst_media_digital_mute, 460 }; 461 462 static const struct snd_soc_dai_ops sst_be_dai_ops = { 463 .startup = sst_enable_ssp, 464 .hw_params = sst_be_hw_params, 465 .set_fmt = sst_set_format, 466 .set_tdm_slot = sst_platform_set_ssp_slot, 467 .shutdown = sst_disable_ssp, 468 }; 469 470 static struct snd_soc_dai_driver sst_platform_dai[] = { 471 { 472 .name = "media-cpu-dai", 473 .ops = &sst_media_dai_ops, 474 .playback = { 475 .stream_name = "Headset Playback", 476 .channels_min = SST_STEREO, 477 .channels_max = SST_STEREO, 478 .rates = SNDRV_PCM_RATE_48000, 479 .formats = SNDRV_PCM_FMTBIT_S16_LE, 480 }, 481 .capture = { 482 .stream_name = "Headset Capture", 483 .channels_min = 1, 484 .channels_max = 2, 485 .rates = SNDRV_PCM_RATE_48000, 486 .formats = SNDRV_PCM_FMTBIT_S16_LE, 487 }, 488 }, 489 { 490 .name = "deepbuffer-cpu-dai", 491 .ops = &sst_media_dai_ops, 492 .playback = { 493 .stream_name = "Deepbuffer Playback", 494 .channels_min = SST_STEREO, 495 .channels_max = SST_STEREO, 496 .rates = SNDRV_PCM_RATE_48000, 497 .formats = SNDRV_PCM_FMTBIT_S16_LE, 498 }, 499 }, 500 { 501 .name = "compress-cpu-dai", 502 .ops = &sst_compr_dai_ops, 503 .playback = { 504 .stream_name = "Compress Playback", 505 .channels_min = 1, 506 }, 507 }, 508 /* BE CPU Dais */ 509 { 510 .name = "ssp0-port", 511 .ops = &sst_be_dai_ops, 512 .playback = { 513 .stream_name = "ssp0 Tx", 514 .channels_min = SST_STEREO, 515 .channels_max = SST_STEREO, 516 .rates = SNDRV_PCM_RATE_48000, 517 .formats = SNDRV_PCM_FMTBIT_S16_LE, 518 }, 519 .capture = { 520 .stream_name = "ssp0 Rx", 521 .channels_min = SST_STEREO, 522 .channels_max = SST_STEREO, 523 .rates = SNDRV_PCM_RATE_48000, 524 .formats = SNDRV_PCM_FMTBIT_S16_LE, 525 }, 526 }, 527 { 528 .name = "ssp1-port", 529 .ops = &sst_be_dai_ops, 530 .playback = { 531 .stream_name = "ssp1 Tx", 532 .channels_min = SST_STEREO, 533 .channels_max = SST_STEREO, 534 .rates = SNDRV_PCM_RATE_8000|SNDRV_PCM_RATE_16000|SNDRV_PCM_RATE_48000, 535 .formats = SNDRV_PCM_FMTBIT_S16_LE, 536 }, 537 .capture = { 538 .stream_name = "ssp1 Rx", 539 .channels_min = SST_STEREO, 540 .channels_max = SST_STEREO, 541 .rates = SNDRV_PCM_RATE_8000|SNDRV_PCM_RATE_16000|SNDRV_PCM_RATE_48000, 542 .formats = SNDRV_PCM_FMTBIT_S16_LE, 543 }, 544 }, 545 { 546 .name = "ssp2-port", 547 .ops = &sst_be_dai_ops, 548 .playback = { 549 .stream_name = "ssp2 Tx", 550 .channels_min = SST_STEREO, 551 .channels_max = SST_STEREO, 552 .rates = SNDRV_PCM_RATE_48000, 553 .formats = SNDRV_PCM_FMTBIT_S16_LE, 554 }, 555 .capture = { 556 .stream_name = "ssp2 Rx", 557 .channels_min = SST_STEREO, 558 .channels_max = SST_STEREO, 559 .rates = SNDRV_PCM_RATE_48000, 560 .formats = SNDRV_PCM_FMTBIT_S16_LE, 561 }, 562 }, 563 }; 564 565 static int sst_soc_open(struct snd_soc_component *component, 566 struct snd_pcm_substream *substream) 567 { 568 struct snd_pcm_runtime *runtime; 569 570 if (substream->pcm->internal) 571 return 0; 572 573 runtime = substream->runtime; 574 runtime->hw = sst_platform_pcm_hw; 575 return 0; 576 } 577 578 static int sst_soc_trigger(struct snd_soc_component *component, 579 struct snd_pcm_substream *substream, int cmd) 580 { 581 int ret_val = 0, str_id; 582 struct sst_runtime_stream *stream; 583 int status; 584 struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); 585 586 dev_dbg(rtd->dev, "%s called\n", __func__); 587 if (substream->pcm->internal) 588 return 0; 589 stream = substream->runtime->private_data; 590 str_id = stream->stream_info.str_id; 591 switch (cmd) { 592 case SNDRV_PCM_TRIGGER_START: 593 dev_dbg(rtd->dev, "sst: Trigger Start\n"); 594 status = SST_PLATFORM_RUNNING; 595 stream->stream_info.arg = substream; 596 ret_val = stream->ops->stream_start(sst->dev, str_id); 597 break; 598 case SNDRV_PCM_TRIGGER_STOP: 599 dev_dbg(rtd->dev, "sst: in stop\n"); 600 status = SST_PLATFORM_DROPPED; 601 ret_val = stream->ops->stream_drop(sst->dev, str_id); 602 break; 603 case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 604 case SNDRV_PCM_TRIGGER_SUSPEND: 605 dev_dbg(rtd->dev, "sst: in pause\n"); 606 status = SST_PLATFORM_PAUSED; 607 ret_val = stream->ops->stream_pause(sst->dev, str_id); 608 break; 609 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 610 case SNDRV_PCM_TRIGGER_RESUME: 611 dev_dbg(rtd->dev, "sst: in pause release\n"); 612 status = SST_PLATFORM_RUNNING; 613 ret_val = stream->ops->stream_pause_release(sst->dev, str_id); 614 break; 615 default: 616 return -EINVAL; 617 } 618 619 if (!ret_val) 620 sst_set_stream_status(stream, status); 621 622 return ret_val; 623 } 624 625 626 static snd_pcm_uframes_t sst_soc_pointer(struct snd_soc_component *component, 627 struct snd_pcm_substream *substream) 628 { 629 struct sst_runtime_stream *stream; 630 int ret_val, status; 631 struct pcm_stream_info *str_info; 632 struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); 633 634 stream = substream->runtime->private_data; 635 status = sst_get_stream_status(stream); 636 if (status == SST_PLATFORM_INIT) 637 return 0; 638 str_info = &stream->stream_info; 639 ret_val = stream->ops->stream_read_tstamp(sst->dev, str_info); 640 if (ret_val) { 641 dev_err(rtd->dev, "sst: error code = %d\n", ret_val); 642 return ret_val; 643 } 644 return str_info->buffer_ptr; 645 } 646 647 static snd_pcm_sframes_t sst_soc_delay(struct snd_soc_component *component, 648 struct snd_pcm_substream *substream) 649 { 650 struct sst_runtime_stream *stream = substream->runtime->private_data; 651 struct pcm_stream_info *str_info = &stream->stream_info; 652 653 if (sst_get_stream_status(stream) == SST_PLATFORM_INIT) 654 return 0; 655 656 return str_info->pcm_delay; 657 } 658 659 static int sst_soc_pcm_new(struct snd_soc_component *component, 660 struct snd_soc_pcm_runtime *rtd) 661 { 662 struct snd_soc_dai *dai = snd_soc_rtd_to_cpu(rtd, 0); 663 struct snd_pcm *pcm = rtd->pcm; 664 665 if (dai->driver->playback.channels_min || 666 dai->driver->capture.channels_min) { 667 snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV, 668 pcm->card->dev, 669 SST_MIN_BUFFER, SST_MAX_BUFFER); 670 } 671 return 0; 672 } 673 674 static int sst_soc_probe(struct snd_soc_component *component) 675 { 676 struct sst_data *drv = dev_get_drvdata(component->dev); 677 678 drv->soc_card = component->card; 679 return sst_dsp_init_v2_dpcm(component); 680 } 681 682 static void sst_soc_remove(struct snd_soc_component *component) 683 { 684 struct sst_data *drv = dev_get_drvdata(component->dev); 685 686 drv->soc_card = NULL; 687 } 688 689 static const struct snd_soc_component_driver sst_soc_platform_drv = { 690 .name = DRV_NAME, 691 .probe = sst_soc_probe, 692 .remove = sst_soc_remove, 693 .open = sst_soc_open, 694 .trigger = sst_soc_trigger, 695 .pointer = sst_soc_pointer, 696 .delay = sst_soc_delay, 697 .compress_ops = &sst_platform_compress_ops, 698 .pcm_new = sst_soc_pcm_new, 699 }; 700 701 static int sst_platform_probe(struct platform_device *pdev) 702 { 703 struct sst_data *drv; 704 int ret; 705 struct sst_platform_data *pdata; 706 707 drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_KERNEL); 708 if (drv == NULL) { 709 return -ENOMEM; 710 } 711 712 pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); 713 if (pdata == NULL) { 714 return -ENOMEM; 715 } 716 717 pdata->pdev_strm_map = dpcm_strm_map; 718 pdata->strm_map_size = ARRAY_SIZE(dpcm_strm_map); 719 drv->pdata = pdata; 720 drv->pdev = pdev; 721 mutex_init(&drv->lock); 722 dev_set_drvdata(&pdev->dev, drv); 723 724 ret = devm_snd_soc_register_component(&pdev->dev, &sst_soc_platform_drv, 725 sst_platform_dai, ARRAY_SIZE(sst_platform_dai)); 726 if (ret) 727 dev_err(&pdev->dev, "registering cpu dais failed\n"); 728 729 return ret; 730 } 731 732 static void sst_platform_remove(struct platform_device *pdev) 733 { 734 dev_dbg(&pdev->dev, "sst_platform_remove success\n"); 735 } 736 737 #ifdef CONFIG_PM_SLEEP 738 739 static int sst_soc_prepare(struct device *dev) 740 { 741 struct sst_data *drv = dev_get_drvdata(dev); 742 struct snd_soc_pcm_runtime *rtd; 743 744 if (!drv->soc_card) 745 return 0; 746 747 /* suspend all pcms first */ 748 snd_soc_suspend(drv->soc_card->dev); 749 snd_soc_poweroff(drv->soc_card->dev); 750 751 /* set the SSPs to idle */ 752 for_each_card_rtds(drv->soc_card, rtd) { 753 struct snd_soc_dai *dai = snd_soc_rtd_to_cpu(rtd, 0); 754 755 if (snd_soc_dai_active(dai)) { 756 send_ssp_cmd(dai, dai->name, 0); 757 sst_handle_vb_timer(dai, false); 758 } 759 } 760 761 return 0; 762 } 763 764 static void sst_soc_complete(struct device *dev) 765 { 766 struct sst_data *drv = dev_get_drvdata(dev); 767 struct snd_soc_pcm_runtime *rtd; 768 769 if (!drv->soc_card) 770 return; 771 772 /* restart SSPs */ 773 for_each_card_rtds(drv->soc_card, rtd) { 774 struct snd_soc_dai *dai = snd_soc_rtd_to_cpu(rtd, 0); 775 776 if (snd_soc_dai_active(dai)) { 777 sst_handle_vb_timer(dai, true); 778 send_ssp_cmd(dai, dai->name, 1); 779 } 780 } 781 snd_soc_resume(drv->soc_card->dev); 782 } 783 784 #else 785 786 #define sst_soc_prepare NULL 787 #define sst_soc_complete NULL 788 789 #endif 790 791 792 static const struct dev_pm_ops sst_platform_pm = { 793 .prepare = sst_soc_prepare, 794 .complete = sst_soc_complete, 795 }; 796 797 static struct platform_driver sst_platform_driver = { 798 .driver = { 799 .name = "sst-mfld-platform", 800 .pm = &sst_platform_pm, 801 }, 802 .probe = sst_platform_probe, 803 .remove = sst_platform_remove, 804 }; 805 806 module_platform_driver(sst_platform_driver); 807 808 MODULE_DESCRIPTION("ASoC Intel(R) MID Platform driver"); 809 MODULE_AUTHOR("Vinod Koul <vinod.koul@intel.com>"); 810 MODULE_AUTHOR("Harsha Priya <priya.harsha@intel.com>"); 811 MODULE_LICENSE("GPL v2"); 812 MODULE_ALIAS("platform:sst-atom-hifi2-platform"); 813 MODULE_ALIAS("platform:sst-mfld-platform"); 814