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->dma_buffer.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        substream->runtime->dma_area = substream->dma_buffer.area;
 237        str_params.sparams = param;
 238        str_params.aparams = alloc_params;
 239        str_params.codec = SST_CODEC_TYPE_PCM;
 240
 241        /* fill the device type and stream id to pass to SST driver */
 242        ret_val = sst_fill_stream_params(substream, ctx, &str_params, false);
 243        if (ret_val < 0)
 244                return ret_val;
 245
 246        stream->stream_info.str_id = str_params.stream_id;
 247
 248        ret_val = stream->ops->open(sst->dev, &str_params);
 249        if (ret_val <= 0)
 250                return ret_val;
 251
 252
 253        return ret_val;
 254}
 255
 256static void sst_period_elapsed(void *arg)
 257{
 258        struct snd_pcm_substream *substream = arg;
 259        struct sst_runtime_stream *stream;
 260        int status;
 261
 262        if (!substream || !substream->runtime)
 263                return;
 264        stream = substream->runtime->private_data;
 265        if (!stream)
 266                return;
 267        status = sst_get_stream_status(stream);
 268        if (status != SST_PLATFORM_RUNNING)
 269                return;
 270        snd_pcm_period_elapsed(substream);
 271}
 272
 273static int sst_platform_init_stream(struct snd_pcm_substream *substream)
 274{
 275        struct sst_runtime_stream *stream =
 276                        substream->runtime->private_data;
 277        struct snd_soc_pcm_runtime *rtd = substream->private_data;
 278        int ret_val;
 279
 280        dev_dbg(rtd->dev, "setting buffer ptr param\n");
 281        sst_set_stream_status(stream, SST_PLATFORM_INIT);
 282        stream->stream_info.period_elapsed = sst_period_elapsed;
 283        stream->stream_info.arg = substream;
 284        stream->stream_info.buffer_ptr = 0;
 285        stream->stream_info.sfreq = substream->runtime->rate;
 286        ret_val = stream->ops->stream_init(sst->dev, &stream->stream_info);
 287        if (ret_val)
 288                dev_err(rtd->dev, "control_set ret error %d\n", ret_val);
 289        return ret_val;
 290
 291}
 292
 293static int power_up_sst(struct sst_runtime_stream *stream)
 294{
 295        return stream->ops->power(sst->dev, true);
 296}
 297
 298static void power_down_sst(struct sst_runtime_stream *stream)
 299{
 300        stream->ops->power(sst->dev, false);
 301}
 302
 303static int sst_media_open(struct snd_pcm_substream *substream,
 304                struct snd_soc_dai *dai)
 305{
 306        int ret_val = 0;
 307        struct snd_pcm_runtime *runtime = substream->runtime;
 308        struct sst_runtime_stream *stream;
 309
 310        stream = kzalloc(sizeof(*stream), GFP_KERNEL);
 311        if (!stream)
 312                return -ENOMEM;
 313        spin_lock_init(&stream->status_lock);
 314
 315        /* get the sst ops */
 316        mutex_lock(&sst_lock);
 317        if (!sst ||
 318            !try_module_get(sst->dev->driver->owner)) {
 319                dev_err(dai->dev, "no device available to run\n");
 320                ret_val = -ENODEV;
 321                goto out_ops;
 322        }
 323        stream->ops = sst->ops;
 324        mutex_unlock(&sst_lock);
 325
 326        stream->stream_info.str_id = 0;
 327
 328        stream->stream_info.arg = substream;
 329        /* allocate memory for SST API set */
 330        runtime->private_data = stream;
 331
 332        ret_val = power_up_sst(stream);
 333        if (ret_val < 0)
 334                return ret_val;
 335
 336        /* Make sure, that the period size is always even */
 337        snd_pcm_hw_constraint_step(substream->runtime, 0,
 338                           SNDRV_PCM_HW_PARAM_PERIODS, 2);
 339
 340        return snd_pcm_hw_constraint_integer(runtime,
 341                         SNDRV_PCM_HW_PARAM_PERIODS);
 342out_ops:
 343        kfree(stream);
 344        mutex_unlock(&sst_lock);
 345        return ret_val;
 346}
 347
 348static void sst_media_close(struct snd_pcm_substream *substream,
 349                struct snd_soc_dai *dai)
 350{
 351        struct sst_runtime_stream *stream;
 352        int str_id;
 353
 354        stream = substream->runtime->private_data;
 355        power_down_sst(stream);
 356
 357        str_id = stream->stream_info.str_id;
 358        if (str_id)
 359                stream->ops->close(sst->dev, str_id);
 360        module_put(sst->dev->driver->owner);
 361        kfree(stream);
 362}
 363
 364static int sst_media_prepare(struct snd_pcm_substream *substream,
 365                struct snd_soc_dai *dai)
 366{
 367        struct sst_runtime_stream *stream;
 368        int ret_val = 0, str_id;
 369
 370        stream = substream->runtime->private_data;
 371        str_id = stream->stream_info.str_id;
 372        if (stream->stream_info.str_id) {
 373                ret_val = stream->ops->stream_drop(sst->dev, str_id);
 374                return ret_val;
 375        }
 376
 377        ret_val = sst_platform_alloc_stream(substream, dai);
 378        if (ret_val <= 0)
 379                return ret_val;
 380        snprintf(substream->pcm->id, sizeof(substream->pcm->id),
 381                        "%d", stream->stream_info.str_id);
 382
 383        ret_val = sst_platform_init_stream(substream);
 384        if (ret_val)
 385                return ret_val;
 386        substream->runtime->hw.info = SNDRV_PCM_INFO_BLOCK_TRANSFER;
 387        return ret_val;
 388}
 389
 390static int sst_media_hw_params(struct snd_pcm_substream *substream,
 391                                struct snd_pcm_hw_params *params,
 392                                struct snd_soc_dai *dai)
 393{
 394        int ret;
 395
 396        ret =
 397                snd_pcm_lib_malloc_pages(substream,
 398                                params_buffer_bytes(params));
 399        if (ret)
 400                return ret;
 401        memset(substream->runtime->dma_area, 0, params_buffer_bytes(params));
 402        return 0;
 403}
 404
 405static int sst_media_hw_free(struct snd_pcm_substream *substream,
 406                struct snd_soc_dai *dai)
 407{
 408        return snd_pcm_lib_free_pages(substream);
 409}
 410
 411static int sst_enable_ssp(struct snd_pcm_substream *substream,
 412                        struct snd_soc_dai *dai)
 413{
 414        int ret = 0;
 415
 416        if (!dai->active) {
 417                ret = sst_handle_vb_timer(dai, true);
 418                sst_fill_ssp_defaults(dai);
 419        }
 420        return ret;
 421}
 422
 423static int sst_be_hw_params(struct snd_pcm_substream *substream,
 424                                struct snd_pcm_hw_params *params,
 425                                struct snd_soc_dai *dai)
 426{
 427        int ret = 0;
 428
 429        if (dai->active == 1)
 430                ret = send_ssp_cmd(dai, dai->name, 1);
 431        return ret;
 432}
 433
 434static int sst_set_format(struct snd_soc_dai *dai, unsigned int fmt)
 435{
 436        int ret = 0;
 437
 438        if (!dai->active)
 439                return 0;
 440
 441        ret = sst_fill_ssp_config(dai, fmt);
 442        if (ret < 0)
 443                dev_err(dai->dev, "sst_set_format failed..\n");
 444
 445        return ret;
 446}
 447
 448static int sst_platform_set_ssp_slot(struct snd_soc_dai *dai,
 449                        unsigned int tx_mask, unsigned int rx_mask,
 450                        int slots, int slot_width) {
 451        int ret = 0;
 452
 453        if (!dai->active)
 454                return ret;
 455
 456        ret = sst_fill_ssp_slot(dai, tx_mask, rx_mask, slots, slot_width);
 457        if (ret < 0)
 458                dev_err(dai->dev, "sst_fill_ssp_slot failed..%d\n", ret);
 459
 460        return ret;
 461}
 462
 463static void sst_disable_ssp(struct snd_pcm_substream *substream,
 464                        struct snd_soc_dai *dai)
 465{
 466        if (!dai->active) {
 467                send_ssp_cmd(dai, dai->name, 0);
 468                sst_handle_vb_timer(dai, false);
 469        }
 470}
 471
 472static const struct snd_soc_dai_ops sst_media_dai_ops = {
 473        .startup = sst_media_open,
 474        .shutdown = sst_media_close,
 475        .prepare = sst_media_prepare,
 476        .hw_params = sst_media_hw_params,
 477        .hw_free = sst_media_hw_free,
 478        .mute_stream = sst_media_digital_mute,
 479};
 480
 481static const struct snd_soc_dai_ops sst_compr_dai_ops = {
 482        .mute_stream = sst_media_digital_mute,
 483};
 484
 485static const struct snd_soc_dai_ops sst_be_dai_ops = {
 486        .startup = sst_enable_ssp,
 487        .hw_params = sst_be_hw_params,
 488        .set_fmt = sst_set_format,
 489        .set_tdm_slot = sst_platform_set_ssp_slot,
 490        .shutdown = sst_disable_ssp,
 491};
 492
 493static struct snd_soc_dai_driver sst_platform_dai[] = {
 494{
 495        .name = "media-cpu-dai",
 496        .ops = &sst_media_dai_ops,
 497        .playback = {
 498                .stream_name = "Headset Playback",
 499                .channels_min = SST_STEREO,
 500                .channels_max = SST_STEREO,
 501                .rates = SNDRV_PCM_RATE_44100|SNDRV_PCM_RATE_48000,
 502                .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE,
 503        },
 504        .capture = {
 505                .stream_name = "Headset Capture",
 506                .channels_min = 1,
 507                .channels_max = 2,
 508                .rates = SNDRV_PCM_RATE_44100|SNDRV_PCM_RATE_48000,
 509                .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE,
 510        },
 511},
 512{
 513        .name = "deepbuffer-cpu-dai",
 514        .ops = &sst_media_dai_ops,
 515        .playback = {
 516                .stream_name = "Deepbuffer Playback",
 517                .channels_min = SST_STEREO,
 518                .channels_max = SST_STEREO,
 519                .rates = SNDRV_PCM_RATE_44100|SNDRV_PCM_RATE_48000,
 520                .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE,
 521        },
 522},
 523{
 524        .name = "compress-cpu-dai",
 525        .compress_new = snd_soc_new_compress,
 526        .ops = &sst_compr_dai_ops,
 527        .playback = {
 528                .stream_name = "Compress Playback",
 529                .channels_min = 1,
 530        },
 531},
 532/* BE CPU  Dais */
 533{
 534        .name = "ssp0-port",
 535        .ops = &sst_be_dai_ops,
 536        .playback = {
 537                .stream_name = "ssp0 Tx",
 538                .channels_min = SST_STEREO,
 539                .channels_max = SST_STEREO,
 540                .rates = SNDRV_PCM_RATE_48000,
 541                .formats = SNDRV_PCM_FMTBIT_S16_LE,
 542        },
 543        .capture = {
 544                .stream_name = "ssp0 Rx",
 545                .channels_min = SST_STEREO,
 546                .channels_max = SST_STEREO,
 547                .rates = SNDRV_PCM_RATE_48000,
 548                .formats = SNDRV_PCM_FMTBIT_S16_LE,
 549        },
 550},
 551{
 552        .name = "ssp1-port",
 553        .ops = &sst_be_dai_ops,
 554        .playback = {
 555                .stream_name = "ssp1 Tx",
 556                .channels_min = SST_STEREO,
 557                .channels_max = SST_STEREO,
 558                .rates = SNDRV_PCM_RATE_8000|SNDRV_PCM_RATE_16000|SNDRV_PCM_RATE_48000,
 559                .formats = SNDRV_PCM_FMTBIT_S16_LE,
 560        },
 561        .capture = {
 562                .stream_name = "ssp1 Rx",
 563                .channels_min = SST_STEREO,
 564                .channels_max = SST_STEREO,
 565                .rates = SNDRV_PCM_RATE_8000|SNDRV_PCM_RATE_16000|SNDRV_PCM_RATE_48000,
 566                .formats = SNDRV_PCM_FMTBIT_S16_LE,
 567        },
 568},
 569{
 570        .name = "ssp2-port",
 571        .ops = &sst_be_dai_ops,
 572        .playback = {
 573                .stream_name = "ssp2 Tx",
 574                .channels_min = SST_STEREO,
 575                .channels_max = SST_STEREO,
 576                .rates = SNDRV_PCM_RATE_48000,
 577                .formats = SNDRV_PCM_FMTBIT_S16_LE,
 578        },
 579        .capture = {
 580                .stream_name = "ssp2 Rx",
 581                .channels_min = SST_STEREO,
 582                .channels_max = SST_STEREO,
 583                .rates = SNDRV_PCM_RATE_48000,
 584                .formats = SNDRV_PCM_FMTBIT_S16_LE,
 585        },
 586},
 587};
 588
 589static int sst_platform_open(struct snd_pcm_substream *substream)
 590{
 591        struct snd_pcm_runtime *runtime;
 592
 593        if (substream->pcm->internal)
 594                return 0;
 595
 596        runtime = substream->runtime;
 597        runtime->hw = sst_platform_pcm_hw;
 598        return 0;
 599}
 600
 601static int sst_platform_pcm_trigger(struct snd_pcm_substream *substream,
 602                                        int cmd)
 603{
 604        int ret_val = 0, str_id;
 605        struct sst_runtime_stream *stream;
 606        int status;
 607        struct snd_soc_pcm_runtime *rtd = substream->private_data;
 608
 609        dev_dbg(rtd->dev, "sst_platform_pcm_trigger called\n");
 610        if (substream->pcm->internal)
 611                return 0;
 612        stream = substream->runtime->private_data;
 613        str_id = stream->stream_info.str_id;
 614        switch (cmd) {
 615        case SNDRV_PCM_TRIGGER_START:
 616                dev_dbg(rtd->dev, "sst: Trigger Start\n");
 617                status = SST_PLATFORM_RUNNING;
 618                stream->stream_info.arg = substream;
 619                ret_val = stream->ops->stream_start(sst->dev, str_id);
 620                break;
 621        case SNDRV_PCM_TRIGGER_STOP:
 622                dev_dbg(rtd->dev, "sst: in stop\n");
 623                status = SST_PLATFORM_DROPPED;
 624                ret_val = stream->ops->stream_drop(sst->dev, str_id);
 625                break;
 626        case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
 627        case SNDRV_PCM_TRIGGER_SUSPEND:
 628                dev_dbg(rtd->dev, "sst: in pause\n");
 629                status = SST_PLATFORM_PAUSED;
 630                ret_val = stream->ops->stream_pause(sst->dev, str_id);
 631                break;
 632        case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
 633        case SNDRV_PCM_TRIGGER_RESUME:
 634                dev_dbg(rtd->dev, "sst: in pause release\n");
 635                status = SST_PLATFORM_RUNNING;
 636                ret_val = stream->ops->stream_pause_release(sst->dev, str_id);
 637                break;
 638        default:
 639                return -EINVAL;
 640        }
 641
 642        if (!ret_val)
 643                sst_set_stream_status(stream, status);
 644
 645        return ret_val;
 646}
 647
 648
 649static snd_pcm_uframes_t sst_platform_pcm_pointer
 650                        (struct snd_pcm_substream *substream)
 651{
 652        struct sst_runtime_stream *stream;
 653        int ret_val, status;
 654        struct pcm_stream_info *str_info;
 655        struct snd_soc_pcm_runtime *rtd = substream->private_data;
 656
 657        stream = substream->runtime->private_data;
 658        status = sst_get_stream_status(stream);
 659        if (status == SST_PLATFORM_INIT)
 660                return 0;
 661        str_info = &stream->stream_info;
 662        ret_val = stream->ops->stream_read_tstamp(sst->dev, str_info);
 663        if (ret_val) {
 664                dev_err(rtd->dev, "sst: error code = %d\n", ret_val);
 665                return ret_val;
 666        }
 667        substream->runtime->delay = str_info->pcm_delay;
 668        return str_info->buffer_ptr;
 669}
 670
 671static const struct snd_pcm_ops sst_platform_ops = {
 672        .open = sst_platform_open,
 673        .ioctl = snd_pcm_lib_ioctl,
 674        .trigger = sst_platform_pcm_trigger,
 675        .pointer = sst_platform_pcm_pointer,
 676};
 677
 678static int sst_pcm_new(struct snd_soc_pcm_runtime *rtd)
 679{
 680        struct snd_soc_dai *dai = rtd->cpu_dai;
 681        struct snd_pcm *pcm = rtd->pcm;
 682
 683        if (dai->driver->playback.channels_min ||
 684                        dai->driver->capture.channels_min) {
 685                snd_pcm_lib_preallocate_pages_for_all(pcm,
 686                        SNDRV_DMA_TYPE_CONTINUOUS,
 687                        snd_dma_continuous_data(GFP_DMA),
 688                        SST_MIN_BUFFER, SST_MAX_BUFFER);
 689        }
 690        return 0;
 691}
 692
 693static int sst_soc_probe(struct snd_soc_component *component)
 694{
 695        struct sst_data *drv = dev_get_drvdata(component->dev);
 696
 697        drv->soc_card = component->card;
 698        return sst_dsp_init_v2_dpcm(component);
 699}
 700
 701static void sst_soc_remove(struct snd_soc_component *component)
 702{
 703        struct sst_data *drv = dev_get_drvdata(component->dev);
 704
 705        drv->soc_card = NULL;
 706}
 707
 708static const struct snd_soc_component_driver sst_soc_platform_drv  = {
 709        .name           = DRV_NAME,
 710        .probe          = sst_soc_probe,
 711        .remove         = sst_soc_remove,
 712        .ops            = &sst_platform_ops,
 713        .compr_ops      = &sst_platform_compr_ops,
 714        .pcm_new        = sst_pcm_new,
 715};
 716
 717static int sst_platform_probe(struct platform_device *pdev)
 718{
 719        struct sst_data *drv;
 720        int ret;
 721        struct sst_platform_data *pdata;
 722
 723        drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_KERNEL);
 724        if (drv == NULL) {
 725                return -ENOMEM;
 726        }
 727
 728        pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
 729        if (pdata == NULL) {
 730                return -ENOMEM;
 731        }
 732
 733        pdata->pdev_strm_map = dpcm_strm_map;
 734        pdata->strm_map_size = ARRAY_SIZE(dpcm_strm_map);
 735        drv->pdata = pdata;
 736        drv->pdev = pdev;
 737        mutex_init(&drv->lock);
 738        dev_set_drvdata(&pdev->dev, drv);
 739
 740        ret = devm_snd_soc_register_component(&pdev->dev, &sst_soc_platform_drv,
 741                                sst_platform_dai, ARRAY_SIZE(sst_platform_dai));
 742        if (ret)
 743                dev_err(&pdev->dev, "registering cpu dais failed\n");
 744
 745        return ret;
 746}
 747
 748static int sst_platform_remove(struct platform_device *pdev)
 749{
 750        dev_dbg(&pdev->dev, "sst_platform_remove success\n");
 751        return 0;
 752}
 753
 754#ifdef CONFIG_PM_SLEEP
 755
 756static int sst_soc_prepare(struct device *dev)
 757{
 758        struct sst_data *drv = dev_get_drvdata(dev);
 759        struct snd_soc_pcm_runtime *rtd;
 760
 761        if (!drv->soc_card)
 762                return 0;
 763
 764        /* suspend all pcms first */
 765        snd_soc_suspend(drv->soc_card->dev);
 766        snd_soc_poweroff(drv->soc_card->dev);
 767
 768        /* set the SSPs to idle */
 769        for_each_card_rtds(drv->soc_card, rtd) {
 770                struct snd_soc_dai *dai = rtd->cpu_dai;
 771
 772                if (dai->active) {
 773                        send_ssp_cmd(dai, dai->name, 0);
 774                        sst_handle_vb_timer(dai, false);
 775                }
 776        }
 777
 778        return 0;
 779}
 780
 781static void sst_soc_complete(struct device *dev)
 782{
 783        struct sst_data *drv = dev_get_drvdata(dev);
 784        struct snd_soc_pcm_runtime *rtd;
 785
 786        if (!drv->soc_card)
 787                return;
 788
 789        /* restart SSPs */
 790        for_each_card_rtds(drv->soc_card, rtd) {
 791                struct snd_soc_dai *dai = rtd->cpu_dai;
 792
 793                if (dai->active) {
 794                        sst_handle_vb_timer(dai, true);
 795                        send_ssp_cmd(dai, dai->name, 1);
 796                }
 797        }
 798        snd_soc_resume(drv->soc_card->dev);
 799}
 800
 801#else
 802
 803#define sst_soc_prepare NULL
 804#define sst_soc_complete NULL
 805
 806#endif
 807
 808
 809static const struct dev_pm_ops sst_platform_pm = {
 810        .prepare        = sst_soc_prepare,
 811        .complete       = sst_soc_complete,
 812};
 813
 814static struct platform_driver sst_platform_driver = {
 815        .driver         = {
 816                .name           = "sst-mfld-platform",
 817                .pm             = &sst_platform_pm,
 818        },
 819        .probe          = sst_platform_probe,
 820        .remove         = sst_platform_remove,
 821};
 822
 823module_platform_driver(sst_platform_driver);
 824
 825MODULE_DESCRIPTION("ASoC Intel(R) MID Platform driver");
 826MODULE_AUTHOR("Vinod Koul <vinod.koul@intel.com>");
 827MODULE_AUTHOR("Harsha Priya <priya.harsha@intel.com>");
 828MODULE_LICENSE("GPL v2");
 829MODULE_ALIAS("platform:sst-atom-hifi2-platform");
 830MODULE_ALIAS("platform:sst-mfld-platform");
 831