linux/sound/soc/intel/sst-mfld-platform-pcm.c
<<
>>
Prefs
   1/*
   2 *  sst_mfld_platform.c - Intel MID Platform driver
   3 *
   4 *  Copyright (C) 2010-2014 Intel Corp
   5 *  Author: Vinod Koul <vinod.koul@intel.com>
   6 *  Author: Harsha Priya <priya.harsha@intel.com>
   7 *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   8 *
   9 *  This program is free software; you can redistribute it and/or modify
  10 *  it under the terms of the GNU General Public License as published by
  11 *  the Free Software Foundation; version 2 of the License.
  12 *
  13 *  This program is distributed in the hope that it will be useful, but
  14 *  WITHOUT ANY WARRANTY; without even the implied warranty of
  15 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16 *  General Public License for more details.
  17 *
  18 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  19 */
  20#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  21
  22#include <linux/slab.h>
  23#include <linux/io.h>
  24#include <linux/module.h>
  25#include <sound/core.h>
  26#include <sound/pcm.h>
  27#include <sound/pcm_params.h>
  28#include <sound/soc.h>
  29#include <sound/compress_driver.h>
  30#include <asm/platform_sst_audio.h>
  31#include "sst-mfld-platform.h"
  32#include "sst-atom-controls.h"
  33
  34struct sst_device *sst;
  35static DEFINE_MUTEX(sst_lock);
  36extern struct snd_compr_ops sst_platform_compr_ops;
  37
  38int sst_register_dsp(struct sst_device *dev)
  39{
  40        if (WARN_ON(!dev))
  41                return -EINVAL;
  42        if (!try_module_get(dev->dev->driver->owner))
  43                return -ENODEV;
  44        mutex_lock(&sst_lock);
  45        if (sst) {
  46                pr_err("we already have a device %s\n", sst->name);
  47                module_put(dev->dev->driver->owner);
  48                mutex_unlock(&sst_lock);
  49                return -EEXIST;
  50        }
  51        pr_debug("registering device %s\n", dev->name);
  52        sst = dev;
  53        mutex_unlock(&sst_lock);
  54        return 0;
  55}
  56EXPORT_SYMBOL_GPL(sst_register_dsp);
  57
  58int sst_unregister_dsp(struct sst_device *dev)
  59{
  60        if (WARN_ON(!dev))
  61                return -EINVAL;
  62        if (dev != sst)
  63                return -EINVAL;
  64
  65        mutex_lock(&sst_lock);
  66
  67        if (!sst) {
  68                mutex_unlock(&sst_lock);
  69                return -EIO;
  70        }
  71
  72        module_put(sst->dev->driver->owner);
  73        pr_debug("unreg %s\n", sst->name);
  74        sst = NULL;
  75        mutex_unlock(&sst_lock);
  76        return 0;
  77}
  78EXPORT_SYMBOL_GPL(sst_unregister_dsp);
  79
  80static struct snd_pcm_hardware sst_platform_pcm_hw = {
  81        .info = (SNDRV_PCM_INFO_INTERLEAVED |
  82                        SNDRV_PCM_INFO_DOUBLE |
  83                        SNDRV_PCM_INFO_PAUSE |
  84                        SNDRV_PCM_INFO_RESUME |
  85                        SNDRV_PCM_INFO_MMAP|
  86                        SNDRV_PCM_INFO_MMAP_VALID |
  87                        SNDRV_PCM_INFO_BLOCK_TRANSFER |
  88                        SNDRV_PCM_INFO_SYNC_START),
  89        .buffer_bytes_max = SST_MAX_BUFFER,
  90        .period_bytes_min = SST_MIN_PERIOD_BYTES,
  91        .period_bytes_max = SST_MAX_PERIOD_BYTES,
  92        .periods_min = SST_MIN_PERIODS,
  93        .periods_max = SST_MAX_PERIODS,
  94        .fifo_size = SST_FIFO_SIZE,
  95};
  96
  97static struct sst_dev_stream_map dpcm_strm_map[] = {
  98        {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, /* Reserved, not in use */
  99        {MERR_DPCM_AUDIO, 0, SNDRV_PCM_STREAM_PLAYBACK, PIPE_MEDIA1_IN, SST_TASK_ID_MEDIA, 0},
 100        {MERR_DPCM_COMPR, 0, SNDRV_PCM_STREAM_PLAYBACK, PIPE_MEDIA0_IN, SST_TASK_ID_MEDIA, 0},
 101        {MERR_DPCM_AUDIO, 0, SNDRV_PCM_STREAM_CAPTURE, PIPE_PCM1_OUT, SST_TASK_ID_MEDIA, 0},
 102};
 103
 104/* MFLD - MSIC */
 105static struct snd_soc_dai_driver sst_platform_dai[] = {
 106{
 107        .name = "Headset-cpu-dai",
 108        .id = 0,
 109        .playback = {
 110                .channels_min = SST_STEREO,
 111                .channels_max = SST_STEREO,
 112                .rates = SNDRV_PCM_RATE_48000,
 113                .formats = SNDRV_PCM_FMTBIT_S24_LE,
 114        },
 115        .capture = {
 116                .channels_min = 1,
 117                .channels_max = 5,
 118                .rates = SNDRV_PCM_RATE_48000,
 119                .formats = SNDRV_PCM_FMTBIT_S24_LE,
 120        },
 121},
 122{
 123        .name = "Compress-cpu-dai",
 124        .compress_dai = 1,
 125        .playback = {
 126                .channels_min = SST_STEREO,
 127                .channels_max = SST_STEREO,
 128                .rates = SNDRV_PCM_RATE_44100|SNDRV_PCM_RATE_48000,
 129                .formats = SNDRV_PCM_FMTBIT_S16_LE,
 130        },
 131},
 132};
 133
 134/* helper functions */
 135void sst_set_stream_status(struct sst_runtime_stream *stream,
 136                                        int state)
 137{
 138        unsigned long flags;
 139        spin_lock_irqsave(&stream->status_lock, flags);
 140        stream->stream_status = state;
 141        spin_unlock_irqrestore(&stream->status_lock, flags);
 142}
 143
 144static inline int sst_get_stream_status(struct sst_runtime_stream *stream)
 145{
 146        int state;
 147        unsigned long flags;
 148
 149        spin_lock_irqsave(&stream->status_lock, flags);
 150        state = stream->stream_status;
 151        spin_unlock_irqrestore(&stream->status_lock, flags);
 152        return state;
 153}
 154
 155static void sst_fill_alloc_params(struct snd_pcm_substream *substream,
 156                                struct snd_sst_alloc_params_ext *alloc_param)
 157{
 158        unsigned int channels;
 159        snd_pcm_uframes_t period_size;
 160        ssize_t periodbytes;
 161        ssize_t buffer_bytes = snd_pcm_lib_buffer_bytes(substream);
 162        u32 buffer_addr = virt_to_phys(substream->dma_buffer.area);
 163
 164        channels = substream->runtime->channels;
 165        period_size = substream->runtime->period_size;
 166        periodbytes = samples_to_bytes(substream->runtime, period_size);
 167        alloc_param->ring_buf_info[0].addr = buffer_addr;
 168        alloc_param->ring_buf_info[0].size = buffer_bytes;
 169        alloc_param->sg_count = 1;
 170        alloc_param->reserved = 0;
 171        alloc_param->frag_size = periodbytes * channels;
 172
 173}
 174static void sst_fill_pcm_params(struct snd_pcm_substream *substream,
 175                                struct snd_sst_stream_params *param)
 176{
 177        param->uc.pcm_params.num_chan = (u8) substream->runtime->channels;
 178        param->uc.pcm_params.pcm_wd_sz = substream->runtime->sample_bits;
 179        param->uc.pcm_params.sfreq = substream->runtime->rate;
 180
 181        /* PCM stream via ALSA interface */
 182        param->uc.pcm_params.use_offload_path = 0;
 183        param->uc.pcm_params.reserved2 = 0;
 184        memset(param->uc.pcm_params.channel_map, 0, sizeof(u8));
 185
 186}
 187
 188static int sst_get_stream_mapping(int dev, int sdev, int dir,
 189        struct sst_dev_stream_map *map, int size)
 190{
 191        int i;
 192
 193        if (map == NULL)
 194                return -EINVAL;
 195
 196
 197        /* index 0 is not used in stream map */
 198        for (i = 1; i < size; i++) {
 199                if ((map[i].dev_num == dev) && (map[i].direction == dir))
 200                        return i;
 201        }
 202        return 0;
 203}
 204
 205int sst_fill_stream_params(void *substream,
 206        const struct sst_data *ctx, struct snd_sst_params *str_params, bool is_compress)
 207{
 208        int map_size;
 209        int index;
 210        struct sst_dev_stream_map *map;
 211        struct snd_pcm_substream *pstream = NULL;
 212        struct snd_compr_stream *cstream = NULL;
 213
 214        map = ctx->pdata->pdev_strm_map;
 215        map_size = ctx->pdata->strm_map_size;
 216
 217        if (is_compress == true)
 218                cstream = (struct snd_compr_stream *)substream;
 219        else
 220                pstream = (struct snd_pcm_substream *)substream;
 221
 222        str_params->stream_type = SST_STREAM_TYPE_MUSIC;
 223
 224        /* For pcm streams */
 225        if (pstream) {
 226                index = sst_get_stream_mapping(pstream->pcm->device,
 227                                          pstream->number, pstream->stream,
 228                                          map, map_size);
 229                if (index <= 0)
 230                        return -EINVAL;
 231
 232                str_params->stream_id = index;
 233                str_params->device_type = map[index].device_id;
 234                str_params->task = map[index].task_id;
 235
 236                str_params->ops = (u8)pstream->stream;
 237        }
 238
 239        if (cstream) {
 240                index = sst_get_stream_mapping(cstream->device->device,
 241                                               0, cstream->direction,
 242                                               map, map_size);
 243                if (index <= 0)
 244                        return -EINVAL;
 245                str_params->stream_id = index;
 246                str_params->device_type = map[index].device_id;
 247                str_params->task = map[index].task_id;
 248
 249                str_params->ops = (u8)cstream->direction;
 250        }
 251        return 0;
 252}
 253
 254static int sst_platform_alloc_stream(struct snd_pcm_substream *substream,
 255                struct snd_soc_platform *platform)
 256{
 257        struct sst_runtime_stream *stream =
 258                        substream->runtime->private_data;
 259        struct snd_sst_stream_params param = {{{0,},},};
 260        struct snd_sst_params str_params = {0};
 261        struct snd_sst_alloc_params_ext alloc_params = {0};
 262        int ret_val = 0;
 263        struct sst_data *ctx = snd_soc_platform_get_drvdata(platform);
 264
 265        /* set codec params and inform SST driver the same */
 266        sst_fill_pcm_params(substream, &param);
 267        sst_fill_alloc_params(substream, &alloc_params);
 268        substream->runtime->dma_area = substream->dma_buffer.area;
 269        str_params.sparams = param;
 270        str_params.aparams = alloc_params;
 271        str_params.codec = SST_CODEC_TYPE_PCM;
 272
 273        /* fill the device type and stream id to pass to SST driver */
 274        ret_val = sst_fill_stream_params(substream, ctx, &str_params, false);
 275        if (ret_val < 0)
 276                return ret_val;
 277
 278        stream->stream_info.str_id = str_params.stream_id;
 279
 280        ret_val = stream->ops->open(&str_params);
 281        if (ret_val <= 0)
 282                return ret_val;
 283
 284
 285        return ret_val;
 286}
 287
 288static void sst_period_elapsed(void *arg)
 289{
 290        struct snd_pcm_substream *substream = arg;
 291        struct sst_runtime_stream *stream;
 292        int status;
 293
 294        if (!substream || !substream->runtime)
 295                return;
 296        stream = substream->runtime->private_data;
 297        if (!stream)
 298                return;
 299        status = sst_get_stream_status(stream);
 300        if (status != SST_PLATFORM_RUNNING)
 301                return;
 302        snd_pcm_period_elapsed(substream);
 303}
 304
 305static int sst_platform_init_stream(struct snd_pcm_substream *substream)
 306{
 307        struct sst_runtime_stream *stream =
 308                        substream->runtime->private_data;
 309        int ret_val;
 310
 311        pr_debug("setting buffer ptr param\n");
 312        sst_set_stream_status(stream, SST_PLATFORM_INIT);
 313        stream->stream_info.period_elapsed = sst_period_elapsed;
 314        stream->stream_info.arg = substream;
 315        stream->stream_info.buffer_ptr = 0;
 316        stream->stream_info.sfreq = substream->runtime->rate;
 317        ret_val = stream->ops->device_control(
 318                        SST_SND_STREAM_INIT, &stream->stream_info);
 319        if (ret_val)
 320                pr_err("control_set ret error %d\n", ret_val);
 321        return ret_val;
 322
 323}
 324/* end -- helper functions */
 325
 326static int sst_media_open(struct snd_pcm_substream *substream,
 327                struct snd_soc_dai *dai)
 328{
 329        int ret_val = 0;
 330        struct snd_pcm_runtime *runtime = substream->runtime;
 331        struct sst_runtime_stream *stream;
 332
 333        stream = kzalloc(sizeof(*stream), GFP_KERNEL);
 334        if (!stream)
 335                return -ENOMEM;
 336        spin_lock_init(&stream->status_lock);
 337
 338        /* get the sst ops */
 339        mutex_lock(&sst_lock);
 340        if (!sst ||
 341            !try_module_get(sst->dev->driver->owner)) {
 342                pr_err("no device available to run\n");
 343                ret_val = -ENODEV;
 344                goto out_ops;
 345        }
 346        stream->ops = sst->ops;
 347        mutex_unlock(&sst_lock);
 348
 349        stream->stream_info.str_id = 0;
 350
 351        stream->stream_info.arg = substream;
 352        /* allocate memory for SST API set */
 353        runtime->private_data = stream;
 354
 355        /* Make sure, that the period size is always even */
 356        snd_pcm_hw_constraint_step(substream->runtime, 0,
 357                           SNDRV_PCM_HW_PARAM_PERIODS, 2);
 358
 359        return snd_pcm_hw_constraint_integer(runtime,
 360                         SNDRV_PCM_HW_PARAM_PERIODS);
 361out_ops:
 362        kfree(stream);
 363        mutex_unlock(&sst_lock);
 364        return ret_val;
 365}
 366
 367static void sst_media_close(struct snd_pcm_substream *substream,
 368                struct snd_soc_dai *dai)
 369{
 370        struct sst_runtime_stream *stream;
 371        int ret_val = 0, str_id;
 372
 373        stream = substream->runtime->private_data;
 374        str_id = stream->stream_info.str_id;
 375        if (str_id)
 376                ret_val = stream->ops->close(str_id);
 377        module_put(sst->dev->driver->owner);
 378        kfree(stream);
 379}
 380
 381static inline unsigned int get_current_pipe_id(struct snd_soc_platform *platform,
 382                                               struct snd_pcm_substream *substream)
 383{
 384        struct sst_data *sst = snd_soc_platform_get_drvdata(platform);
 385        struct sst_dev_stream_map *map = sst->pdata->pdev_strm_map;
 386        struct sst_runtime_stream *stream =
 387                        substream->runtime->private_data;
 388        u32 str_id = stream->stream_info.str_id;
 389        unsigned int pipe_id;
 390        pipe_id = map[str_id].device_id;
 391
 392        pr_debug("%s: got pipe_id = %#x for str_id = %d\n",
 393                 __func__, pipe_id, str_id);
 394        return pipe_id;
 395}
 396
 397static int sst_media_prepare(struct snd_pcm_substream *substream,
 398                struct snd_soc_dai *dai)
 399{
 400        struct sst_runtime_stream *stream;
 401        int ret_val = 0, str_id;
 402
 403        stream = substream->runtime->private_data;
 404        str_id = stream->stream_info.str_id;
 405        if (stream->stream_info.str_id) {
 406                ret_val = stream->ops->device_control(
 407                                SST_SND_DROP, &str_id);
 408                return ret_val;
 409        }
 410
 411        ret_val = sst_platform_alloc_stream(substream, dai->platform);
 412        if (ret_val <= 0)
 413                return ret_val;
 414        snprintf(substream->pcm->id, sizeof(substream->pcm->id),
 415                        "%d", stream->stream_info.str_id);
 416
 417        ret_val = sst_platform_init_stream(substream);
 418        if (ret_val)
 419                return ret_val;
 420        substream->runtime->hw.info = SNDRV_PCM_INFO_BLOCK_TRANSFER;
 421        return ret_val;
 422}
 423
 424static int sst_media_hw_params(struct snd_pcm_substream *substream,
 425                                struct snd_pcm_hw_params *params,
 426                                struct snd_soc_dai *dai)
 427{
 428        snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params));
 429        memset(substream->runtime->dma_area, 0, params_buffer_bytes(params));
 430        return 0;
 431}
 432
 433static int sst_media_hw_free(struct snd_pcm_substream *substream,
 434                struct snd_soc_dai *dai)
 435{
 436        return snd_pcm_lib_free_pages(substream);
 437}
 438
 439static struct snd_soc_dai_ops sst_media_dai_ops = {
 440        .startup = sst_media_open,
 441        .shutdown = sst_media_close,
 442        .prepare = sst_media_prepare,
 443        .hw_params = sst_media_hw_params,
 444        .hw_free = sst_media_hw_free,
 445};
 446
 447static int sst_platform_open(struct snd_pcm_substream *substream)
 448{
 449        struct snd_pcm_runtime *runtime;
 450
 451        if (substream->pcm->internal)
 452                return 0;
 453
 454        runtime = substream->runtime;
 455        runtime->hw = sst_platform_pcm_hw;
 456        return 0;
 457}
 458
 459static int sst_platform_pcm_trigger(struct snd_pcm_substream *substream,
 460                                        int cmd)
 461{
 462        int ret_val = 0, str_id;
 463        struct sst_runtime_stream *stream;
 464        int str_cmd, status;
 465
 466        pr_debug("sst_platform_pcm_trigger called\n");
 467        stream = substream->runtime->private_data;
 468        str_id = stream->stream_info.str_id;
 469        switch (cmd) {
 470        case SNDRV_PCM_TRIGGER_START:
 471                pr_debug("sst: Trigger Start\n");
 472                str_cmd = SST_SND_START;
 473                status = SST_PLATFORM_RUNNING;
 474                stream->stream_info.arg = substream;
 475                break;
 476        case SNDRV_PCM_TRIGGER_STOP:
 477                pr_debug("sst: in stop\n");
 478                str_cmd = SST_SND_DROP;
 479                status = SST_PLATFORM_DROPPED;
 480                break;
 481        case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
 482                pr_debug("sst: in pause\n");
 483                str_cmd = SST_SND_PAUSE;
 484                status = SST_PLATFORM_PAUSED;
 485                break;
 486        case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
 487                pr_debug("sst: in pause release\n");
 488                str_cmd = SST_SND_RESUME;
 489                status = SST_PLATFORM_RUNNING;
 490                break;
 491        default:
 492                return -EINVAL;
 493        }
 494        ret_val = stream->ops->device_control(str_cmd, &str_id);
 495        if (!ret_val)
 496                sst_set_stream_status(stream, status);
 497
 498        return ret_val;
 499}
 500
 501
 502static snd_pcm_uframes_t sst_platform_pcm_pointer
 503                        (struct snd_pcm_substream *substream)
 504{
 505        struct sst_runtime_stream *stream;
 506        int ret_val, status;
 507        struct pcm_stream_info *str_info;
 508
 509        stream = substream->runtime->private_data;
 510        status = sst_get_stream_status(stream);
 511        if (status == SST_PLATFORM_INIT)
 512                return 0;
 513        str_info = &stream->stream_info;
 514        ret_val = stream->ops->device_control(
 515                                SST_SND_BUFFER_POINTER, str_info);
 516        if (ret_val) {
 517                pr_err("sst: error code = %d\n", ret_val);
 518                return ret_val;
 519        }
 520        substream->runtime->delay = str_info->pcm_delay;
 521        return str_info->buffer_ptr;
 522}
 523
 524static struct snd_pcm_ops sst_platform_ops = {
 525        .open = sst_platform_open,
 526        .ioctl = snd_pcm_lib_ioctl,
 527        .trigger = sst_platform_pcm_trigger,
 528        .pointer = sst_platform_pcm_pointer,
 529};
 530
 531static void sst_pcm_free(struct snd_pcm *pcm)
 532{
 533        pr_debug("sst_pcm_free called\n");
 534        snd_pcm_lib_preallocate_free_for_all(pcm);
 535}
 536
 537static int sst_pcm_new(struct snd_soc_pcm_runtime *rtd)
 538{
 539        struct snd_soc_dai *dai = rtd->cpu_dai;
 540        struct snd_pcm *pcm = rtd->pcm;
 541        int retval = 0;
 542
 543        if (dai->driver->playback.channels_min ||
 544                        dai->driver->capture.channels_min) {
 545                retval =  snd_pcm_lib_preallocate_pages_for_all(pcm,
 546                        SNDRV_DMA_TYPE_CONTINUOUS,
 547                        snd_dma_continuous_data(GFP_DMA),
 548                        SST_MIN_BUFFER, SST_MAX_BUFFER);
 549                if (retval) {
 550                        pr_err("dma buffer allocationf fail\n");
 551                        return retval;
 552                }
 553        }
 554        return retval;
 555}
 556
 557static struct snd_soc_platform_driver sst_soc_platform_drv = {
 558        .ops            = &sst_platform_ops,
 559        .compr_ops      = &sst_platform_compr_ops,
 560        .pcm_new        = sst_pcm_new,
 561        .pcm_free       = sst_pcm_free,
 562};
 563
 564static const struct snd_soc_component_driver sst_component = {
 565        .name           = "sst",
 566};
 567
 568
 569static int sst_platform_probe(struct platform_device *pdev)
 570{
 571        struct sst_data *drv;
 572        int ret;
 573        struct sst_platform_data *pdata;
 574
 575        drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_KERNEL);
 576        if (drv == NULL) {
 577                pr_err("kzalloc failed\n");
 578                return -ENOMEM;
 579        }
 580
 581        pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
 582        if (pdata == NULL) {
 583                pr_err("kzalloc failed for pdata\n");
 584                return -ENOMEM;
 585        }
 586
 587        pdata->pdev_strm_map = dpcm_strm_map;
 588        pdata->strm_map_size = ARRAY_SIZE(dpcm_strm_map);
 589        drv->pdata = pdata;
 590        mutex_init(&drv->lock);
 591        dev_set_drvdata(&pdev->dev, drv);
 592
 593        ret = snd_soc_register_platform(&pdev->dev, &sst_soc_platform_drv);
 594        if (ret) {
 595                pr_err("registering soc platform failed\n");
 596                return ret;
 597        }
 598
 599        ret = snd_soc_register_component(&pdev->dev, &sst_component,
 600                                sst_platform_dai, ARRAY_SIZE(sst_platform_dai));
 601        if (ret) {
 602                pr_err("registering cpu dais failed\n");
 603                snd_soc_unregister_platform(&pdev->dev);
 604        }
 605        return ret;
 606}
 607
 608static int sst_platform_remove(struct platform_device *pdev)
 609{
 610
 611        snd_soc_unregister_component(&pdev->dev);
 612        snd_soc_unregister_platform(&pdev->dev);
 613        pr_debug("sst_platform_remove success\n");
 614        return 0;
 615}
 616
 617static struct platform_driver sst_platform_driver = {
 618        .driver         = {
 619                .name           = "sst-mfld-platform",
 620                .owner          = THIS_MODULE,
 621        },
 622        .probe          = sst_platform_probe,
 623        .remove         = sst_platform_remove,
 624};
 625
 626module_platform_driver(sst_platform_driver);
 627
 628MODULE_DESCRIPTION("ASoC Intel(R) MID Platform driver");
 629MODULE_AUTHOR("Vinod Koul <vinod.koul@intel.com>");
 630MODULE_AUTHOR("Harsha Priya <priya.harsha@intel.com>");
 631MODULE_LICENSE("GPL v2");
 632MODULE_ALIAS("platform:sst-mfld-platform");
 633