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