linux/sound/core/compress_offload.c
<<
>>
Prefs
   1/*
   2 *  compress_core.c - compress offload core
   3 *
   4 *  Copyright (C) 2011 Intel Corporation
   5 *  Authors:    Vinod Koul <vinod.koul@linux.intel.com>
   6 *              Pierre-Louis Bossart <pierre-louis.bossart@linux.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 *  You should have received a copy of the GNU General Public License along
  19 *  with this program; if not, write to the Free Software Foundation, Inc.,
  20 *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  21 *
  22 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  23 *
  24 */
  25#define FORMAT(fmt) "%s: %d: " fmt, __func__, __LINE__
  26#define pr_fmt(fmt) KBUILD_MODNAME ": " FORMAT(fmt)
  27
  28#include <linux/file.h>
  29#include <linux/fs.h>
  30#include <linux/list.h>
  31#include <linux/math64.h>
  32#include <linux/mm.h>
  33#include <linux/mutex.h>
  34#include <linux/poll.h>
  35#include <linux/slab.h>
  36#include <linux/sched.h>
  37#include <linux/types.h>
  38#include <linux/uio.h>
  39#include <linux/uaccess.h>
  40#include <linux/module.h>
  41#include <linux/compat.h>
  42#include <sound/core.h>
  43#include <sound/initval.h>
  44#include <sound/info.h>
  45#include <sound/compress_params.h>
  46#include <sound/compress_offload.h>
  47#include <sound/compress_driver.h>
  48
  49/* struct snd_compr_codec_caps overflows the ioctl bit size for some
  50 * architectures, so we need to disable the relevant ioctls.
  51 */
  52#if _IOC_SIZEBITS < 14
  53#define COMPR_CODEC_CAPS_OVERFLOW
  54#endif
  55
  56/* TODO:
  57 * - add substream support for multiple devices in case of
  58 *      SND_DYNAMIC_MINORS is not used
  59 * - Multiple node representation
  60 *      driver should be able to register multiple nodes
  61 */
  62
  63static DEFINE_MUTEX(device_mutex);
  64
  65struct snd_compr_file {
  66        unsigned long caps;
  67        struct snd_compr_stream stream;
  68};
  69
  70/*
  71 * a note on stream states used:
  72 * we use following states in the compressed core
  73 * SNDRV_PCM_STATE_OPEN: When stream has been opened.
  74 * SNDRV_PCM_STATE_SETUP: When stream has been initialized. This is done by
  75 *      calling SNDRV_COMPRESS_SET_PARAMS. Running streams will come to this
  76 *      state at stop by calling SNDRV_COMPRESS_STOP, or at end of drain.
  77 * SNDRV_PCM_STATE_PREPARED: When a stream has been written to (for
  78 *      playback only). User after setting up stream writes the data buffer
  79 *      before starting the stream.
  80 * SNDRV_PCM_STATE_RUNNING: When stream has been started and is
  81 *      decoding/encoding and rendering/capturing data.
  82 * SNDRV_PCM_STATE_DRAINING: When stream is draining current data. This is done
  83 *      by calling SNDRV_COMPRESS_DRAIN.
  84 * SNDRV_PCM_STATE_PAUSED: When stream is paused. This is done by calling
  85 *      SNDRV_COMPRESS_PAUSE. It can be stopped or resumed by calling
  86 *      SNDRV_COMPRESS_STOP or SNDRV_COMPRESS_RESUME respectively.
  87 */
  88static int snd_compr_open(struct inode *inode, struct file *f)
  89{
  90        struct snd_compr *compr;
  91        struct snd_compr_file *data;
  92        struct snd_compr_runtime *runtime;
  93        enum snd_compr_direction dirn;
  94        int maj = imajor(inode);
  95        int ret;
  96
  97        if ((f->f_flags & O_ACCMODE) == O_WRONLY)
  98                dirn = SND_COMPRESS_PLAYBACK;
  99        else if ((f->f_flags & O_ACCMODE) == O_RDONLY)
 100                dirn = SND_COMPRESS_CAPTURE;
 101        else
 102                return -EINVAL;
 103
 104        if (maj == snd_major)
 105                compr = snd_lookup_minor_data(iminor(inode),
 106                                        SNDRV_DEVICE_TYPE_COMPRESS);
 107        else
 108                return -EBADFD;
 109
 110        if (compr == NULL) {
 111                pr_err("no device data!!!\n");
 112                return -ENODEV;
 113        }
 114
 115        if (dirn != compr->direction) {
 116                pr_err("this device doesn't support this direction\n");
 117                snd_card_unref(compr->card);
 118                return -EINVAL;
 119        }
 120
 121        data = kzalloc(sizeof(*data), GFP_KERNEL);
 122        if (!data) {
 123                snd_card_unref(compr->card);
 124                return -ENOMEM;
 125        }
 126        data->stream.ops = compr->ops;
 127        data->stream.direction = dirn;
 128        data->stream.private_data = compr->private_data;
 129        data->stream.device = compr;
 130        runtime = kzalloc(sizeof(*runtime), GFP_KERNEL);
 131        if (!runtime) {
 132                kfree(data);
 133                snd_card_unref(compr->card);
 134                return -ENOMEM;
 135        }
 136        runtime->state = SNDRV_PCM_STATE_OPEN;
 137        init_waitqueue_head(&runtime->sleep);
 138        data->stream.runtime = runtime;
 139        f->private_data = (void *)data;
 140        mutex_lock(&compr->lock);
 141        ret = compr->ops->open(&data->stream);
 142        mutex_unlock(&compr->lock);
 143        if (ret) {
 144                kfree(runtime);
 145                kfree(data);
 146        }
 147        snd_card_unref(compr->card);
 148        return ret;
 149}
 150
 151static int snd_compr_free(struct inode *inode, struct file *f)
 152{
 153        struct snd_compr_file *data = f->private_data;
 154        struct snd_compr_runtime *runtime = data->stream.runtime;
 155
 156        switch (runtime->state) {
 157        case SNDRV_PCM_STATE_RUNNING:
 158        case SNDRV_PCM_STATE_DRAINING:
 159        case SNDRV_PCM_STATE_PAUSED:
 160                data->stream.ops->trigger(&data->stream, SNDRV_PCM_TRIGGER_STOP);
 161                break;
 162        default:
 163                break;
 164        }
 165
 166        data->stream.ops->free(&data->stream);
 167        kfree(data->stream.runtime->buffer);
 168        kfree(data->stream.runtime);
 169        kfree(data);
 170        return 0;
 171}
 172
 173static int snd_compr_update_tstamp(struct snd_compr_stream *stream,
 174                struct snd_compr_tstamp *tstamp)
 175{
 176        if (!stream->ops->pointer)
 177                return -ENOTSUPP;
 178        stream->ops->pointer(stream, tstamp);
 179        pr_debug("dsp consumed till %d total %d bytes\n",
 180                tstamp->byte_offset, tstamp->copied_total);
 181        if (stream->direction == SND_COMPRESS_PLAYBACK)
 182                stream->runtime->total_bytes_transferred = tstamp->copied_total;
 183        else
 184                stream->runtime->total_bytes_available = tstamp->copied_total;
 185        return 0;
 186}
 187
 188static size_t snd_compr_calc_avail(struct snd_compr_stream *stream,
 189                struct snd_compr_avail *avail)
 190{
 191        memset(avail, 0, sizeof(*avail));
 192        snd_compr_update_tstamp(stream, &avail->tstamp);
 193        /* Still need to return avail even if tstamp can't be filled in */
 194
 195        if (stream->runtime->total_bytes_available == 0 &&
 196                        stream->runtime->state == SNDRV_PCM_STATE_SETUP &&
 197                        stream->direction == SND_COMPRESS_PLAYBACK) {
 198                pr_debug("detected init and someone forgot to do a write\n");
 199                return stream->runtime->buffer_size;
 200        }
 201        pr_debug("app wrote %lld, DSP consumed %lld\n",
 202                        stream->runtime->total_bytes_available,
 203                        stream->runtime->total_bytes_transferred);
 204        if (stream->runtime->total_bytes_available ==
 205                                stream->runtime->total_bytes_transferred) {
 206                if (stream->direction == SND_COMPRESS_PLAYBACK) {
 207                        pr_debug("both pointers are same, returning full avail\n");
 208                        return stream->runtime->buffer_size;
 209                } else {
 210                        pr_debug("both pointers are same, returning no avail\n");
 211                        return 0;
 212                }
 213        }
 214
 215        avail->avail = stream->runtime->total_bytes_available -
 216                        stream->runtime->total_bytes_transferred;
 217        if (stream->direction == SND_COMPRESS_PLAYBACK)
 218                avail->avail = stream->runtime->buffer_size - avail->avail;
 219
 220        pr_debug("ret avail as %lld\n", avail->avail);
 221        return avail->avail;
 222}
 223
 224static inline size_t snd_compr_get_avail(struct snd_compr_stream *stream)
 225{
 226        struct snd_compr_avail avail;
 227
 228        return snd_compr_calc_avail(stream, &avail);
 229}
 230
 231static int
 232snd_compr_ioctl_avail(struct snd_compr_stream *stream, unsigned long arg)
 233{
 234        struct snd_compr_avail ioctl_avail;
 235        size_t avail;
 236
 237        avail = snd_compr_calc_avail(stream, &ioctl_avail);
 238        ioctl_avail.avail = avail;
 239
 240        if (copy_to_user((__u64 __user *)arg,
 241                                &ioctl_avail, sizeof(ioctl_avail)))
 242                return -EFAULT;
 243        return 0;
 244}
 245
 246static int snd_compr_write_data(struct snd_compr_stream *stream,
 247               const char __user *buf, size_t count)
 248{
 249        void *dstn;
 250        size_t copy;
 251        struct snd_compr_runtime *runtime = stream->runtime;
 252        /* 64-bit Modulus */
 253        u64 app_pointer = div64_u64(runtime->total_bytes_available,
 254                                    runtime->buffer_size);
 255        app_pointer = runtime->total_bytes_available -
 256                      (app_pointer * runtime->buffer_size);
 257
 258        dstn = runtime->buffer + app_pointer;
 259        pr_debug("copying %ld at %lld\n",
 260                        (unsigned long)count, app_pointer);
 261        if (count < runtime->buffer_size - app_pointer) {
 262                if (copy_from_user(dstn, buf, count))
 263                        return -EFAULT;
 264        } else {
 265                copy = runtime->buffer_size - app_pointer;
 266                if (copy_from_user(dstn, buf, copy))
 267                        return -EFAULT;
 268                if (copy_from_user(runtime->buffer, buf + copy, count - copy))
 269                        return -EFAULT;
 270        }
 271        /* if DSP cares, let it know data has been written */
 272        if (stream->ops->ack)
 273                stream->ops->ack(stream, count);
 274        return count;
 275}
 276
 277static ssize_t snd_compr_write(struct file *f, const char __user *buf,
 278                size_t count, loff_t *offset)
 279{
 280        struct snd_compr_file *data = f->private_data;
 281        struct snd_compr_stream *stream;
 282        size_t avail;
 283        int retval;
 284
 285        if (snd_BUG_ON(!data))
 286                return -EFAULT;
 287
 288        stream = &data->stream;
 289        mutex_lock(&stream->device->lock);
 290        /* write is allowed when stream is running or has been steup */
 291        if (stream->runtime->state != SNDRV_PCM_STATE_SETUP &&
 292            stream->runtime->state != SNDRV_PCM_STATE_PREPARED &&
 293                        stream->runtime->state != SNDRV_PCM_STATE_RUNNING) {
 294                mutex_unlock(&stream->device->lock);
 295                return -EBADFD;
 296        }
 297
 298        avail = snd_compr_get_avail(stream);
 299        pr_debug("avail returned %ld\n", (unsigned long)avail);
 300        /* calculate how much we can write to buffer */
 301        if (avail > count)
 302                avail = count;
 303
 304        if (stream->ops->copy) {
 305                char __user* cbuf = (char __user*)buf;
 306                retval = stream->ops->copy(stream, cbuf, avail);
 307        } else {
 308                retval = snd_compr_write_data(stream, buf, avail);
 309        }
 310        if (retval > 0)
 311                stream->runtime->total_bytes_available += retval;
 312
 313        /* while initiating the stream, write should be called before START
 314         * call, so in setup move state */
 315        if (stream->runtime->state == SNDRV_PCM_STATE_SETUP) {
 316                stream->runtime->state = SNDRV_PCM_STATE_PREPARED;
 317                pr_debug("stream prepared, Houston we are good to go\n");
 318        }
 319
 320        mutex_unlock(&stream->device->lock);
 321        return retval;
 322}
 323
 324
 325static ssize_t snd_compr_read(struct file *f, char __user *buf,
 326                size_t count, loff_t *offset)
 327{
 328        struct snd_compr_file *data = f->private_data;
 329        struct snd_compr_stream *stream;
 330        size_t avail;
 331        int retval;
 332
 333        if (snd_BUG_ON(!data))
 334                return -EFAULT;
 335
 336        stream = &data->stream;
 337        mutex_lock(&stream->device->lock);
 338
 339        /* read is allowed when stream is running, paused, draining and setup
 340         * (yes setup is state which we transition to after stop, so if user
 341         * wants to read data after stop we allow that)
 342         */
 343        switch (stream->runtime->state) {
 344        case SNDRV_PCM_STATE_OPEN:
 345        case SNDRV_PCM_STATE_PREPARED:
 346        case SNDRV_PCM_STATE_XRUN:
 347        case SNDRV_PCM_STATE_SUSPENDED:
 348        case SNDRV_PCM_STATE_DISCONNECTED:
 349                retval = -EBADFD;
 350                goto out;
 351        }
 352
 353        avail = snd_compr_get_avail(stream);
 354        pr_debug("avail returned %ld\n", (unsigned long)avail);
 355        /* calculate how much we can read from buffer */
 356        if (avail > count)
 357                avail = count;
 358
 359        if (stream->ops->copy) {
 360                retval = stream->ops->copy(stream, buf, avail);
 361        } else {
 362                retval = -ENXIO;
 363                goto out;
 364        }
 365        if (retval > 0)
 366                stream->runtime->total_bytes_transferred += retval;
 367
 368out:
 369        mutex_unlock(&stream->device->lock);
 370        return retval;
 371}
 372
 373static int snd_compr_mmap(struct file *f, struct vm_area_struct *vma)
 374{
 375        return -ENXIO;
 376}
 377
 378static inline int snd_compr_get_poll(struct snd_compr_stream *stream)
 379{
 380        if (stream->direction == SND_COMPRESS_PLAYBACK)
 381                return POLLOUT | POLLWRNORM;
 382        else
 383                return POLLIN | POLLRDNORM;
 384}
 385
 386static unsigned int snd_compr_poll(struct file *f, poll_table *wait)
 387{
 388        struct snd_compr_file *data = f->private_data;
 389        struct snd_compr_stream *stream;
 390        size_t avail;
 391        int retval = 0;
 392
 393        if (snd_BUG_ON(!data))
 394                return -EFAULT;
 395        stream = &data->stream;
 396        if (snd_BUG_ON(!stream))
 397                return -EFAULT;
 398
 399        mutex_lock(&stream->device->lock);
 400        if (stream->runtime->state == SNDRV_PCM_STATE_OPEN) {
 401                retval = -EBADFD;
 402                goto out;
 403        }
 404        poll_wait(f, &stream->runtime->sleep, wait);
 405
 406        avail = snd_compr_get_avail(stream);
 407        pr_debug("avail is %ld\n", (unsigned long)avail);
 408        /* check if we have at least one fragment to fill */
 409        switch (stream->runtime->state) {
 410        case SNDRV_PCM_STATE_DRAINING:
 411                /* stream has been woken up after drain is complete
 412                 * draining done so set stream state to stopped
 413                 */
 414                retval = snd_compr_get_poll(stream);
 415                stream->runtime->state = SNDRV_PCM_STATE_SETUP;
 416                break;
 417        case SNDRV_PCM_STATE_RUNNING:
 418        case SNDRV_PCM_STATE_PREPARED:
 419        case SNDRV_PCM_STATE_PAUSED:
 420                if (avail >= stream->runtime->fragment_size)
 421                        retval = snd_compr_get_poll(stream);
 422                break;
 423        default:
 424                if (stream->direction == SND_COMPRESS_PLAYBACK)
 425                        retval = POLLOUT | POLLWRNORM | POLLERR;
 426                else
 427                        retval = POLLIN | POLLRDNORM | POLLERR;
 428                break;
 429        }
 430out:
 431        mutex_unlock(&stream->device->lock);
 432        return retval;
 433}
 434
 435static int
 436snd_compr_get_caps(struct snd_compr_stream *stream, unsigned long arg)
 437{
 438        int retval;
 439        struct snd_compr_caps caps;
 440
 441        if (!stream->ops->get_caps)
 442                return -ENXIO;
 443
 444        memset(&caps, 0, sizeof(caps));
 445        retval = stream->ops->get_caps(stream, &caps);
 446        if (retval)
 447                goto out;
 448        if (copy_to_user((void __user *)arg, &caps, sizeof(caps)))
 449                retval = -EFAULT;
 450out:
 451        return retval;
 452}
 453
 454#ifndef COMPR_CODEC_CAPS_OVERFLOW
 455static int
 456snd_compr_get_codec_caps(struct snd_compr_stream *stream, unsigned long arg)
 457{
 458        int retval;
 459        struct snd_compr_codec_caps *caps;
 460
 461        if (!stream->ops->get_codec_caps)
 462                return -ENXIO;
 463
 464        caps = kzalloc(sizeof(*caps), GFP_KERNEL);
 465        if (!caps)
 466                return -ENOMEM;
 467
 468        retval = stream->ops->get_codec_caps(stream, caps);
 469        if (retval)
 470                goto out;
 471        if (copy_to_user((void __user *)arg, caps, sizeof(*caps)))
 472                retval = -EFAULT;
 473
 474out:
 475        kfree(caps);
 476        return retval;
 477}
 478#endif /* !COMPR_CODEC_CAPS_OVERFLOW */
 479
 480/* revisit this with snd_pcm_preallocate_xxx */
 481static int snd_compr_allocate_buffer(struct snd_compr_stream *stream,
 482                struct snd_compr_params *params)
 483{
 484        unsigned int buffer_size;
 485        void *buffer;
 486
 487        buffer_size = params->buffer.fragment_size * params->buffer.fragments;
 488        if (stream->ops->copy) {
 489                buffer = NULL;
 490                /* if copy is defined the driver will be required to copy
 491                 * the data from core
 492                 */
 493        } else {
 494                buffer = kmalloc(buffer_size, GFP_KERNEL);
 495                if (!buffer)
 496                        return -ENOMEM;
 497        }
 498        stream->runtime->fragment_size = params->buffer.fragment_size;
 499        stream->runtime->fragments = params->buffer.fragments;
 500        stream->runtime->buffer = buffer;
 501        stream->runtime->buffer_size = buffer_size;
 502        return 0;
 503}
 504
 505static int snd_compress_check_input(struct snd_compr_params *params)
 506{
 507        /* first let's check the buffer parameter's */
 508        if (params->buffer.fragment_size == 0 ||
 509            params->buffer.fragments > INT_MAX / params->buffer.fragment_size)
 510                return -EINVAL;
 511
 512        /* now codec parameters */
 513        if (params->codec.id == 0 || params->codec.id > SND_AUDIOCODEC_MAX)
 514                return -EINVAL;
 515
 516        if (params->codec.ch_in == 0 || params->codec.ch_out == 0)
 517                return -EINVAL;
 518
 519        return 0;
 520}
 521
 522static int
 523snd_compr_set_params(struct snd_compr_stream *stream, unsigned long arg)
 524{
 525        struct snd_compr_params *params;
 526        int retval;
 527
 528        if (stream->runtime->state == SNDRV_PCM_STATE_OPEN) {
 529                /*
 530                 * we should allow parameter change only when stream has been
 531                 * opened not in other cases
 532                 */
 533                params = kmalloc(sizeof(*params), GFP_KERNEL);
 534                if (!params)
 535                        return -ENOMEM;
 536                if (copy_from_user(params, (void __user *)arg, sizeof(*params))) {
 537                        retval = -EFAULT;
 538                        goto out;
 539                }
 540
 541                retval = snd_compress_check_input(params);
 542                if (retval)
 543                        goto out;
 544
 545                retval = snd_compr_allocate_buffer(stream, params);
 546                if (retval) {
 547                        retval = -ENOMEM;
 548                        goto out;
 549                }
 550
 551                retval = stream->ops->set_params(stream, params);
 552                if (retval)
 553                        goto out;
 554
 555                stream->metadata_set = false;
 556                stream->next_track = false;
 557
 558                if (stream->direction == SND_COMPRESS_PLAYBACK)
 559                        stream->runtime->state = SNDRV_PCM_STATE_SETUP;
 560                else
 561                        stream->runtime->state = SNDRV_PCM_STATE_PREPARED;
 562        } else {
 563                return -EPERM;
 564        }
 565out:
 566        kfree(params);
 567        return retval;
 568}
 569
 570static int
 571snd_compr_get_params(struct snd_compr_stream *stream, unsigned long arg)
 572{
 573        struct snd_codec *params;
 574        int retval;
 575
 576        if (!stream->ops->get_params)
 577                return -EBADFD;
 578
 579        params = kzalloc(sizeof(*params), GFP_KERNEL);
 580        if (!params)
 581                return -ENOMEM;
 582        retval = stream->ops->get_params(stream, params);
 583        if (retval)
 584                goto out;
 585        if (copy_to_user((char __user *)arg, params, sizeof(*params)))
 586                retval = -EFAULT;
 587
 588out:
 589        kfree(params);
 590        return retval;
 591}
 592
 593static int
 594snd_compr_get_metadata(struct snd_compr_stream *stream, unsigned long arg)
 595{
 596        struct snd_compr_metadata metadata;
 597        int retval;
 598
 599        if (!stream->ops->get_metadata)
 600                return -ENXIO;
 601
 602        if (copy_from_user(&metadata, (void __user *)arg, sizeof(metadata)))
 603                return -EFAULT;
 604
 605        retval = stream->ops->get_metadata(stream, &metadata);
 606        if (retval != 0)
 607                return retval;
 608
 609        if (copy_to_user((void __user *)arg, &metadata, sizeof(metadata)))
 610                return -EFAULT;
 611
 612        return 0;
 613}
 614
 615static int
 616snd_compr_set_metadata(struct snd_compr_stream *stream, unsigned long arg)
 617{
 618        struct snd_compr_metadata metadata;
 619        int retval;
 620
 621        if (!stream->ops->set_metadata)
 622                return -ENXIO;
 623        /*
 624        * we should allow parameter change only when stream has been
 625        * opened not in other cases
 626        */
 627        if (copy_from_user(&metadata, (void __user *)arg, sizeof(metadata)))
 628                return -EFAULT;
 629
 630        retval = stream->ops->set_metadata(stream, &metadata);
 631        stream->metadata_set = true;
 632
 633        return retval;
 634}
 635
 636static inline int
 637snd_compr_tstamp(struct snd_compr_stream *stream, unsigned long arg)
 638{
 639        struct snd_compr_tstamp tstamp = {0};
 640        int ret;
 641
 642        ret = snd_compr_update_tstamp(stream, &tstamp);
 643        if (ret == 0)
 644                ret = copy_to_user((struct snd_compr_tstamp __user *)arg,
 645                        &tstamp, sizeof(tstamp)) ? -EFAULT : 0;
 646        return ret;
 647}
 648
 649static int snd_compr_pause(struct snd_compr_stream *stream)
 650{
 651        int retval;
 652
 653        if (stream->runtime->state != SNDRV_PCM_STATE_RUNNING)
 654                return -EPERM;
 655        retval = stream->ops->trigger(stream, SNDRV_PCM_TRIGGER_PAUSE_PUSH);
 656        if (!retval)
 657                stream->runtime->state = SNDRV_PCM_STATE_PAUSED;
 658        return retval;
 659}
 660
 661static int snd_compr_resume(struct snd_compr_stream *stream)
 662{
 663        int retval;
 664
 665        if (stream->runtime->state != SNDRV_PCM_STATE_PAUSED)
 666                return -EPERM;
 667        retval = stream->ops->trigger(stream, SNDRV_PCM_TRIGGER_PAUSE_RELEASE);
 668        if (!retval)
 669                stream->runtime->state = SNDRV_PCM_STATE_RUNNING;
 670        return retval;
 671}
 672
 673static int snd_compr_start(struct snd_compr_stream *stream)
 674{
 675        int retval;
 676
 677        if (stream->runtime->state != SNDRV_PCM_STATE_PREPARED)
 678                return -EPERM;
 679        retval = stream->ops->trigger(stream, SNDRV_PCM_TRIGGER_START);
 680        if (!retval)
 681                stream->runtime->state = SNDRV_PCM_STATE_RUNNING;
 682        return retval;
 683}
 684
 685static int snd_compr_stop(struct snd_compr_stream *stream)
 686{
 687        int retval;
 688
 689        if (stream->runtime->state == SNDRV_PCM_STATE_PREPARED ||
 690                        stream->runtime->state == SNDRV_PCM_STATE_SETUP)
 691                return -EPERM;
 692        retval = stream->ops->trigger(stream, SNDRV_PCM_TRIGGER_STOP);
 693        if (!retval) {
 694                snd_compr_drain_notify(stream);
 695                stream->runtime->total_bytes_available = 0;
 696                stream->runtime->total_bytes_transferred = 0;
 697        }
 698        return retval;
 699}
 700
 701static int snd_compress_wait_for_drain(struct snd_compr_stream *stream)
 702{
 703        int ret;
 704
 705        /*
 706         * We are called with lock held. So drop the lock while we wait for
 707         * drain complete notification from the driver
 708         *
 709         * It is expected that driver will notify the drain completion and then
 710         * stream will be moved to SETUP state, even if draining resulted in an
 711         * error. We can trigger next track after this.
 712         */
 713        stream->runtime->state = SNDRV_PCM_STATE_DRAINING;
 714        mutex_unlock(&stream->device->lock);
 715
 716        /* we wait for drain to complete here, drain can return when
 717         * interruption occurred, wait returned error or success.
 718         * For the first two cases we don't do anything different here and
 719         * return after waking up
 720         */
 721
 722        ret = wait_event_interruptible(stream->runtime->sleep,
 723                        (stream->runtime->state != SNDRV_PCM_STATE_DRAINING));
 724        if (ret == -ERESTARTSYS)
 725                pr_debug("wait aborted by a signal");
 726        else if (ret)
 727                pr_debug("wait for drain failed with %d\n", ret);
 728
 729
 730        wake_up(&stream->runtime->sleep);
 731        mutex_lock(&stream->device->lock);
 732
 733        return ret;
 734}
 735
 736static int snd_compr_drain(struct snd_compr_stream *stream)
 737{
 738        int retval;
 739
 740        if (stream->runtime->state == SNDRV_PCM_STATE_PREPARED ||
 741                        stream->runtime->state == SNDRV_PCM_STATE_SETUP)
 742                return -EPERM;
 743
 744        retval = stream->ops->trigger(stream, SND_COMPR_TRIGGER_DRAIN);
 745        if (retval) {
 746                pr_debug("SND_COMPR_TRIGGER_DRAIN failed %d\n", retval);
 747                wake_up(&stream->runtime->sleep);
 748                return retval;
 749        }
 750
 751        return snd_compress_wait_for_drain(stream);
 752}
 753
 754static int snd_compr_next_track(struct snd_compr_stream *stream)
 755{
 756        int retval;
 757
 758        /* only a running stream can transition to next track */
 759        if (stream->runtime->state != SNDRV_PCM_STATE_RUNNING)
 760                return -EPERM;
 761
 762        /* you can signal next track if this is intended to be a gapless stream
 763         * and current track metadata is set
 764         */
 765        if (stream->metadata_set == false)
 766                return -EPERM;
 767
 768        retval = stream->ops->trigger(stream, SND_COMPR_TRIGGER_NEXT_TRACK);
 769        if (retval != 0)
 770                return retval;
 771        stream->metadata_set = false;
 772        stream->next_track = true;
 773        return 0;
 774}
 775
 776static int snd_compr_partial_drain(struct snd_compr_stream *stream)
 777{
 778        int retval;
 779        if (stream->runtime->state == SNDRV_PCM_STATE_PREPARED ||
 780                        stream->runtime->state == SNDRV_PCM_STATE_SETUP)
 781                return -EPERM;
 782        /* stream can be drained only when next track has been signalled */
 783        if (stream->next_track == false)
 784                return -EPERM;
 785
 786        retval = stream->ops->trigger(stream, SND_COMPR_TRIGGER_PARTIAL_DRAIN);
 787        if (retval) {
 788                pr_debug("Partial drain returned failure\n");
 789                wake_up(&stream->runtime->sleep);
 790                return retval;
 791        }
 792
 793        stream->next_track = false;
 794        return snd_compress_wait_for_drain(stream);
 795}
 796
 797static long snd_compr_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
 798{
 799        struct snd_compr_file *data = f->private_data;
 800        struct snd_compr_stream *stream;
 801        int retval = -ENOTTY;
 802
 803        if (snd_BUG_ON(!data))
 804                return -EFAULT;
 805        stream = &data->stream;
 806        if (snd_BUG_ON(!stream))
 807                return -EFAULT;
 808        mutex_lock(&stream->device->lock);
 809        switch (_IOC_NR(cmd)) {
 810        case _IOC_NR(SNDRV_COMPRESS_IOCTL_VERSION):
 811                retval = put_user(SNDRV_COMPRESS_VERSION,
 812                                (int __user *)arg) ? -EFAULT : 0;
 813                break;
 814        case _IOC_NR(SNDRV_COMPRESS_GET_CAPS):
 815                retval = snd_compr_get_caps(stream, arg);
 816                break;
 817#ifndef COMPR_CODEC_CAPS_OVERFLOW
 818        case _IOC_NR(SNDRV_COMPRESS_GET_CODEC_CAPS):
 819                retval = snd_compr_get_codec_caps(stream, arg);
 820                break;
 821#endif
 822        case _IOC_NR(SNDRV_COMPRESS_SET_PARAMS):
 823                retval = snd_compr_set_params(stream, arg);
 824                break;
 825        case _IOC_NR(SNDRV_COMPRESS_GET_PARAMS):
 826                retval = snd_compr_get_params(stream, arg);
 827                break;
 828        case _IOC_NR(SNDRV_COMPRESS_SET_METADATA):
 829                retval = snd_compr_set_metadata(stream, arg);
 830                break;
 831        case _IOC_NR(SNDRV_COMPRESS_GET_METADATA):
 832                retval = snd_compr_get_metadata(stream, arg);
 833                break;
 834        case _IOC_NR(SNDRV_COMPRESS_TSTAMP):
 835                retval = snd_compr_tstamp(stream, arg);
 836                break;
 837        case _IOC_NR(SNDRV_COMPRESS_AVAIL):
 838                retval = snd_compr_ioctl_avail(stream, arg);
 839                break;
 840        case _IOC_NR(SNDRV_COMPRESS_PAUSE):
 841                retval = snd_compr_pause(stream);
 842                break;
 843        case _IOC_NR(SNDRV_COMPRESS_RESUME):
 844                retval = snd_compr_resume(stream);
 845                break;
 846        case _IOC_NR(SNDRV_COMPRESS_START):
 847                retval = snd_compr_start(stream);
 848                break;
 849        case _IOC_NR(SNDRV_COMPRESS_STOP):
 850                retval = snd_compr_stop(stream);
 851                break;
 852        case _IOC_NR(SNDRV_COMPRESS_DRAIN):
 853                retval = snd_compr_drain(stream);
 854                break;
 855        case _IOC_NR(SNDRV_COMPRESS_PARTIAL_DRAIN):
 856                retval = snd_compr_partial_drain(stream);
 857                break;
 858        case _IOC_NR(SNDRV_COMPRESS_NEXT_TRACK):
 859                retval = snd_compr_next_track(stream);
 860                break;
 861
 862        }
 863        mutex_unlock(&stream->device->lock);
 864        return retval;
 865}
 866
 867/* support of 32bit userspace on 64bit platforms */
 868#ifdef CONFIG_COMPAT
 869static long snd_compr_ioctl_compat(struct file *file, unsigned int cmd,
 870                                                unsigned long arg)
 871{
 872        return snd_compr_ioctl(file, cmd, (unsigned long)compat_ptr(arg));
 873}
 874#endif
 875
 876static const struct file_operations snd_compr_file_ops = {
 877                .owner =        THIS_MODULE,
 878                .open =         snd_compr_open,
 879                .release =      snd_compr_free,
 880                .write =        snd_compr_write,
 881                .read =         snd_compr_read,
 882                .unlocked_ioctl = snd_compr_ioctl,
 883#ifdef CONFIG_COMPAT
 884                .compat_ioctl = snd_compr_ioctl_compat,
 885#endif
 886                .mmap =         snd_compr_mmap,
 887                .poll =         snd_compr_poll,
 888};
 889
 890static int snd_compress_dev_register(struct snd_device *device)
 891{
 892        int ret = -EINVAL;
 893        char str[16];
 894        struct snd_compr *compr;
 895
 896        if (snd_BUG_ON(!device || !device->device_data))
 897                return -EBADFD;
 898        compr = device->device_data;
 899
 900        pr_debug("reg %s for device %s, direction %d\n", str, compr->name,
 901                        compr->direction);
 902        /* register compressed device */
 903        ret = snd_register_device(SNDRV_DEVICE_TYPE_COMPRESS,
 904                                  compr->card, compr->device,
 905                                  &snd_compr_file_ops, compr, &compr->dev);
 906        if (ret < 0) {
 907                pr_err("snd_register_device failed\n %d", ret);
 908                return ret;
 909        }
 910        return ret;
 911
 912}
 913
 914static int snd_compress_dev_disconnect(struct snd_device *device)
 915{
 916        struct snd_compr *compr;
 917
 918        compr = device->device_data;
 919        snd_unregister_device(&compr->dev);
 920        return 0;
 921}
 922
 923#ifdef CONFIG_SND_VERBOSE_PROCFS
 924static void snd_compress_proc_info_read(struct snd_info_entry *entry,
 925                                        struct snd_info_buffer *buffer)
 926{
 927        struct snd_compr *compr = (struct snd_compr *)entry->private_data;
 928
 929        snd_iprintf(buffer, "card: %d\n", compr->card->number);
 930        snd_iprintf(buffer, "device: %d\n", compr->device);
 931        snd_iprintf(buffer, "stream: %s\n",
 932                        compr->direction == SND_COMPRESS_PLAYBACK
 933                                ? "PLAYBACK" : "CAPTURE");
 934        snd_iprintf(buffer, "id: %s\n", compr->id);
 935}
 936
 937static int snd_compress_proc_init(struct snd_compr *compr)
 938{
 939        struct snd_info_entry *entry;
 940        char name[16];
 941
 942        sprintf(name, "compr%i", compr->device);
 943        entry = snd_info_create_card_entry(compr->card, name,
 944                                           compr->card->proc_root);
 945        if (!entry)
 946                return -ENOMEM;
 947        entry->mode = S_IFDIR | S_IRUGO | S_IXUGO;
 948        if (snd_info_register(entry) < 0) {
 949                snd_info_free_entry(entry);
 950                return -ENOMEM;
 951        }
 952        compr->proc_root = entry;
 953
 954        entry = snd_info_create_card_entry(compr->card, "info",
 955                                           compr->proc_root);
 956        if (entry) {
 957                snd_info_set_text_ops(entry, compr,
 958                                      snd_compress_proc_info_read);
 959                if (snd_info_register(entry) < 0) {
 960                        snd_info_free_entry(entry);
 961                        entry = NULL;
 962                }
 963        }
 964        compr->proc_info_entry = entry;
 965
 966        return 0;
 967}
 968
 969static void snd_compress_proc_done(struct snd_compr *compr)
 970{
 971        snd_info_free_entry(compr->proc_info_entry);
 972        compr->proc_info_entry = NULL;
 973        snd_info_free_entry(compr->proc_root);
 974        compr->proc_root = NULL;
 975}
 976
 977static inline void snd_compress_set_id(struct snd_compr *compr, const char *id)
 978{
 979        strlcpy(compr->id, id, sizeof(compr->id));
 980}
 981#else
 982static inline int snd_compress_proc_init(struct snd_compr *compr)
 983{
 984        return 0;
 985}
 986
 987static inline void snd_compress_proc_done(struct snd_compr *compr)
 988{
 989}
 990
 991static inline void snd_compress_set_id(struct snd_compr *compr, const char *id)
 992{
 993}
 994#endif
 995
 996static int snd_compress_dev_free(struct snd_device *device)
 997{
 998        struct snd_compr *compr;
 999
1000        compr = device->device_data;
1001        snd_compress_proc_done(compr);
1002        put_device(&compr->dev);
1003        return 0;
1004}
1005
1006/*
1007 * snd_compress_new: create new compress device
1008 * @card: sound card pointer
1009 * @device: device number
1010 * @dirn: device direction, should be of type enum snd_compr_direction
1011 * @compr: compress device pointer
1012 */
1013int snd_compress_new(struct snd_card *card, int device,
1014                        int dirn, const char *id, struct snd_compr *compr)
1015{
1016        static struct snd_device_ops ops = {
1017                .dev_free = snd_compress_dev_free,
1018                .dev_register = snd_compress_dev_register,
1019                .dev_disconnect = snd_compress_dev_disconnect,
1020        };
1021        int ret;
1022
1023        compr->card = card;
1024        compr->device = device;
1025        compr->direction = dirn;
1026
1027        snd_compress_set_id(compr, id);
1028
1029        snd_device_initialize(&compr->dev, card);
1030        dev_set_name(&compr->dev, "comprC%iD%i", card->number, device);
1031
1032        ret = snd_device_new(card, SNDRV_DEV_COMPRESS, compr, &ops);
1033        if (ret == 0)
1034                snd_compress_proc_init(compr);
1035
1036        return ret;
1037}
1038EXPORT_SYMBOL_GPL(snd_compress_new);
1039
1040static int snd_compress_add_device(struct snd_compr *device)
1041{
1042        int ret;
1043
1044        if (!device->card)
1045                return -EINVAL;
1046
1047        /* register the card */
1048        ret = snd_card_register(device->card);
1049        if (ret)
1050                goto out;
1051        return 0;
1052
1053out:
1054        pr_err("failed with %d\n", ret);
1055        return ret;
1056
1057}
1058
1059static int snd_compress_remove_device(struct snd_compr *device)
1060{
1061        return snd_card_free(device->card);
1062}
1063
1064/**
1065 * snd_compress_register - register compressed device
1066 *
1067 * @device: compressed device to register
1068 */
1069int snd_compress_register(struct snd_compr *device)
1070{
1071        int retval;
1072
1073        if (device->name == NULL || device->ops == NULL)
1074                return -EINVAL;
1075
1076        pr_debug("Registering compressed device %s\n", device->name);
1077        if (snd_BUG_ON(!device->ops->open))
1078                return -EINVAL;
1079        if (snd_BUG_ON(!device->ops->free))
1080                return -EINVAL;
1081        if (snd_BUG_ON(!device->ops->set_params))
1082                return -EINVAL;
1083        if (snd_BUG_ON(!device->ops->trigger))
1084                return -EINVAL;
1085
1086        mutex_init(&device->lock);
1087
1088        /* register a compressed card */
1089        mutex_lock(&device_mutex);
1090        retval = snd_compress_add_device(device);
1091        mutex_unlock(&device_mutex);
1092        return retval;
1093}
1094EXPORT_SYMBOL_GPL(snd_compress_register);
1095
1096int snd_compress_deregister(struct snd_compr *device)
1097{
1098        pr_debug("Removing compressed device %s\n", device->name);
1099        mutex_lock(&device_mutex);
1100        snd_compress_remove_device(device);
1101        mutex_unlock(&device_mutex);
1102        return 0;
1103}
1104EXPORT_SYMBOL_GPL(snd_compress_deregister);
1105
1106static int __init snd_compress_init(void)
1107{
1108        return 0;
1109}
1110
1111static void __exit snd_compress_exit(void)
1112{
1113}
1114
1115module_init(snd_compress_init);
1116module_exit(snd_compress_exit);
1117
1118MODULE_DESCRIPTION("ALSA Compressed offload framework");
1119MODULE_AUTHOR("Vinod Koul <vinod.koul@linux.intel.com>");
1120MODULE_LICENSE("GPL v2");
1121