linux/drivers/staging/dream/qdsp5/audio_qcelp.c
<<
>>
Prefs
   1/* arch/arm/mach-msm/qdsp5/audio_qcelp.c
   2 *
   3 * qcelp 13k audio decoder device
   4 *
   5 * Copyright (c) 2008 QUALCOMM USA, INC.
   6 *
   7 * This code is based in part on audio_mp3.c, which is
   8 * Copyright (C) 2008 Google, Inc.
   9 * Copyright (C) 2008 HTC Corporation
  10 *
  11 * This software is licensed under the terms of the GNU General Public
  12 * License version 2, as published by the Free Software Foundation, and
  13 * may be copied, distributed, and modified under those terms.
  14 *
  15 * This program is distributed in the hope that it will be useful,
  16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  18 *
  19 * See the GNU General Public License for more details.
  20 * You should have received a copy of the GNU General Public License
  21 * along with this program; if not, you can find it at http://www.fsf.org.
  22 *
  23 */
  24
  25#include <linux/module.h>
  26#include <linux/fs.h>
  27#include <linux/miscdevice.h>
  28#include <linux/uaccess.h>
  29#include <linux/sched.h>
  30#include <linux/wait.h>
  31#include <linux/dma-mapping.h>
  32
  33#include <asm/ioctls.h>
  34#include <mach/msm_adsp.h>
  35#include <linux/msm_audio.h>
  36#include <mach/qdsp5/qdsp5audppcmdi.h>
  37#include <mach/qdsp5/qdsp5audppmsg.h>
  38#include <mach/qdsp5/qdsp5audplaycmdi.h>
  39#include <mach/qdsp5/qdsp5audplaymsg.h>
  40
  41#include "audmgr.h"
  42/* for queue ids - should be relative to module number*/
  43#include "adsp.h"
  44
  45#ifdef DEBUG
  46#define dprintk(format, arg...) \
  47printk(KERN_DEBUG format, ## arg)
  48#else
  49#define dprintk(format, arg...) do {} while (0)
  50#endif
  51
  52#define BUFSZ 1080 /* QCELP 13K Hold 600ms packet data = 36 * 30 */
  53#define BUF_COUNT 2
  54#define DMASZ (BUFSZ * BUF_COUNT)
  55
  56#define PCM_BUFSZ_MIN 1600 /* 100ms worth of data */
  57#define PCM_BUF_MAX_COUNT 5
  58
  59#define AUDDEC_DEC_QCELP 9
  60
  61#define ROUTING_MODE_FTRT       1
  62#define ROUTING_MODE_RT         2
  63/* Decoder status received from AUDPPTASK */
  64#define AUDPP_DEC_STATUS_SLEEP  0
  65#define AUDPP_DEC_STATUS_INIT   1
  66#define AUDPP_DEC_STATUS_CFG    2
  67#define AUDPP_DEC_STATUS_PLAY   3
  68
  69struct buffer {
  70        void *data;
  71        unsigned size;
  72        unsigned used;          /* Input usage actual DSP produced PCM size  */
  73        unsigned addr;
  74};
  75
  76struct audio {
  77        struct buffer out[BUF_COUNT];
  78
  79        spinlock_t dsp_lock;
  80
  81        uint8_t out_head;
  82        uint8_t out_tail;
  83        uint8_t out_needed;     /* number of buffers the dsp is waiting for */
  84
  85        struct mutex lock;
  86        struct mutex write_lock;
  87        wait_queue_head_t write_wait;
  88
  89        /* Host PCM section - START */
  90        struct buffer in[PCM_BUF_MAX_COUNT];
  91        struct mutex read_lock;
  92        wait_queue_head_t read_wait;    /* Wait queue for read */
  93        char *read_data;        /* pointer to reader buffer */
  94        dma_addr_t read_phys;   /* physical address of reader buffer */
  95        uint8_t read_next;      /* index to input buffers to be read next */
  96        uint8_t fill_next;      /* index to buffer that DSP should be filling */
  97        uint8_t pcm_buf_count;  /* number of pcm buffer allocated */
  98        /* Host PCM section - END */
  99
 100        struct msm_adsp_module *audplay;
 101
 102        struct audmgr audmgr;
 103
 104        /* data allocated for various buffers */
 105        char *data;
 106        dma_addr_t phys;
 107
 108        uint8_t opened:1;
 109        uint8_t enabled:1;
 110        uint8_t running:1;
 111        uint8_t stopped:1;      /* set when stopped, cleared on flush */
 112        uint8_t pcm_feedback:1; /* set when non-tunnel mode */
 113        uint8_t buf_refresh:1;
 114
 115        unsigned volume;
 116
 117        uint16_t dec_id;
 118};
 119
 120static struct audio the_qcelp_audio;
 121
 122static int auddec_dsp_config(struct audio *audio, int enable);
 123static void audpp_cmd_cfg_adec_params(struct audio *audio);
 124static void audpp_cmd_cfg_routing_mode(struct audio *audio);
 125static void audqcelp_send_data(struct audio *audio, unsigned needed);
 126static void audqcelp_config_hostpcm(struct audio *audio);
 127static void audqcelp_buffer_refresh(struct audio *audio);
 128static void audqcelp_dsp_event(void *private, unsigned id, uint16_t *msg);
 129
 130/* must be called with audio->lock held */
 131static int audqcelp_enable(struct audio *audio)
 132{
 133        struct audmgr_config cfg;
 134        int rc;
 135
 136        dprintk("audqcelp_enable()\n");
 137
 138        if (audio->enabled)
 139                return 0;
 140
 141        audio->out_tail = 0;
 142        audio->out_needed = 0;
 143
 144        cfg.tx_rate = RPC_AUD_DEF_SAMPLE_RATE_NONE;
 145        cfg.rx_rate = RPC_AUD_DEF_SAMPLE_RATE_48000;
 146        cfg.def_method = RPC_AUD_DEF_METHOD_PLAYBACK;
 147        cfg.codec = RPC_AUD_DEF_CODEC_13K;
 148        cfg.snd_method = RPC_SND_METHOD_MIDI;
 149
 150        rc = audmgr_enable(&audio->audmgr, &cfg);
 151        if (rc < 0)
 152                return rc;
 153
 154        if (msm_adsp_enable(audio->audplay)) {
 155                pr_err("audio: msm_adsp_enable(audplay) failed\n");
 156                audmgr_disable(&audio->audmgr);
 157                return -ENODEV;
 158        }
 159
 160        if (audpp_enable(audio->dec_id, audqcelp_dsp_event, audio)) {
 161                pr_err("audio: audpp_enable() failed\n");
 162                msm_adsp_disable(audio->audplay);
 163                audmgr_disable(&audio->audmgr);
 164                return -ENODEV;
 165        }
 166        audio->enabled = 1;
 167        return 0;
 168}
 169
 170/* must be called with audio->lock held */
 171static int audqcelp_disable(struct audio *audio)
 172{
 173        dprintk("audqcelp_disable()\n");
 174        if (audio->enabled) {
 175                audio->enabled = 0;
 176                auddec_dsp_config(audio, 0);
 177                wake_up(&audio->write_wait);
 178                wake_up(&audio->read_wait);
 179                msm_adsp_disable(audio->audplay);
 180                audpp_disable(audio->dec_id, audio);
 181                audmgr_disable(&audio->audmgr);
 182                audio->out_needed = 0;
 183        }
 184        return 0;
 185}
 186
 187/* ------------------- dsp --------------------- */
 188static void audqcelp_update_pcm_buf_entry(struct audio *audio,
 189        uint32_t *payload)
 190{
 191        uint8_t index;
 192        unsigned long flags;
 193
 194        spin_lock_irqsave(&audio->dsp_lock, flags);
 195        for (index = 0; index < payload[1]; index++) {
 196                if (audio->in[audio->fill_next].addr ==
 197                        payload[2 + index * 2]) {
 198                        dprintk("audqcelp_update_pcm_buf_entry: in[%d] ready\n",
 199                        audio->fill_next);
 200                        audio->in[audio->fill_next].used =
 201                        payload[3 + index * 2];
 202                        if ((++audio->fill_next) == audio->pcm_buf_count)
 203                                audio->fill_next = 0;
 204                } else {
 205                        pr_err(
 206                        "audqcelp_update_pcm_buf_entry: expected=%x ret=%x\n",
 207                        audio->in[audio->fill_next].addr,
 208                        payload[1 + index * 2]);
 209                        break;
 210                }
 211        }
 212        if (audio->in[audio->fill_next].used == 0) {
 213                audqcelp_buffer_refresh(audio);
 214        } else {
 215                dprintk("audqcelp_update_pcm_buf_entry: read cannot keep up\n");
 216                audio->buf_refresh = 1;
 217        }
 218
 219        spin_unlock_irqrestore(&audio->dsp_lock, flags);
 220        wake_up(&audio->read_wait);
 221}
 222
 223static void audplay_dsp_event(void *data, unsigned id, size_t len,
 224                              void (*getevent) (void *ptr, size_t len))
 225{
 226        struct audio *audio = data;
 227        uint32_t msg[28];
 228        getevent(msg, sizeof(msg));
 229
 230        dprintk("audplay_dsp_event: msg_id=%x\n", id);
 231
 232        switch (id) {
 233        case AUDPLAY_MSG_DEC_NEEDS_DATA:
 234                audqcelp_send_data(audio, 1);
 235                break;
 236
 237        case AUDPLAY_MSG_BUFFER_UPDATE:
 238                audqcelp_update_pcm_buf_entry(audio, msg);
 239                break;
 240
 241        default:
 242                pr_err("unexpected message from decoder \n");
 243        }
 244}
 245
 246static void audqcelp_dsp_event(void *private, unsigned id, uint16_t *msg)
 247{
 248        struct audio *audio = private;
 249
 250        switch (id) {
 251        case AUDPP_MSG_STATUS_MSG:{
 252                        unsigned status = msg[1];
 253
 254                        switch (status) {
 255                        case AUDPP_DEC_STATUS_SLEEP:
 256                                dprintk("decoder status: sleep \n");
 257                                break;
 258
 259                        case AUDPP_DEC_STATUS_INIT:
 260                                dprintk("decoder status: init \n");
 261                                audpp_cmd_cfg_routing_mode(audio);
 262                                break;
 263
 264                        case AUDPP_DEC_STATUS_CFG:
 265                                dprintk("decoder status: cfg \n");
 266                                break;
 267                        case AUDPP_DEC_STATUS_PLAY:
 268                                dprintk("decoder status: play \n");
 269                                if (audio->pcm_feedback) {
 270                                        audqcelp_config_hostpcm(audio);
 271                                        audqcelp_buffer_refresh(audio);
 272                                }
 273                                break;
 274                        default:
 275                                pr_err("unknown decoder status \n");
 276                        }
 277                        break;
 278                }
 279        case AUDPP_MSG_CFG_MSG:
 280                if (msg[0] == AUDPP_MSG_ENA_ENA) {
 281                        dprintk("audqcelp_dsp_event: CFG_MSG ENABLE\n");
 282                        auddec_dsp_config(audio, 1);
 283                        audio->out_needed = 0;
 284                        audio->running = 1;
 285                        audpp_set_volume_and_pan(audio->dec_id, audio->volume,
 286                                                 0);
 287                        audpp_avsync(audio->dec_id, 22050);
 288                } else if (msg[0] == AUDPP_MSG_ENA_DIS) {
 289                        dprintk("audqcelp_dsp_event: CFG_MSG DISABLE\n");
 290                        audpp_avsync(audio->dec_id, 0);
 291                        audio->running = 0;
 292                } else {
 293                        pr_err("audqcelp_dsp_event: CFG_MSG %d?\n", msg[0]);
 294                }
 295                break;
 296        case AUDPP_MSG_ROUTING_ACK:
 297                dprintk("audqcelp_dsp_event: ROUTING_ACK mode=%d\n", msg[1]);
 298                audpp_cmd_cfg_adec_params(audio);
 299                break;
 300        default:
 301                pr_err("audqcelp_dsp_event: UNKNOWN (%d)\n", id);
 302        }
 303
 304}
 305
 306struct msm_adsp_ops audplay_adsp_ops_qcelp = {
 307        .event = audplay_dsp_event,
 308};
 309
 310#define audplay_send_queue0(audio, cmd, len) \
 311        msm_adsp_write(audio->audplay, QDSP_uPAudPlay0BitStreamCtrlQueue, \
 312                       cmd, len)
 313
 314static int auddec_dsp_config(struct audio *audio, int enable)
 315{
 316        audpp_cmd_cfg_dec_type cmd;
 317
 318        memset(&cmd, 0, sizeof(cmd));
 319        cmd.cmd_id = AUDPP_CMD_CFG_DEC_TYPE;
 320        if (enable)
 321                cmd.dec0_cfg = AUDPP_CMD_UPDATDE_CFG_DEC |
 322                    AUDPP_CMD_ENA_DEC_V | AUDDEC_DEC_QCELP;
 323        else
 324                cmd.dec0_cfg = AUDPP_CMD_UPDATDE_CFG_DEC | AUDPP_CMD_DIS_DEC_V;
 325
 326        return audpp_send_queue1(&cmd, sizeof(cmd));
 327}
 328
 329static void audpp_cmd_cfg_adec_params(struct audio *audio)
 330{
 331        struct audpp_cmd_cfg_adec_params_v13k cmd;
 332
 333        memset(&cmd, 0, sizeof(cmd));
 334        cmd.common.cmd_id = AUDPP_CMD_CFG_ADEC_PARAMS;
 335        cmd.common.length = AUDPP_CMD_CFG_ADEC_PARAMS_V13K_LEN;
 336        cmd.common.dec_id = audio->dec_id;
 337        cmd.common.input_sampling_frequency = 8000;
 338        cmd.stereo_cfg = AUDPP_CMD_PCM_INTF_MONO_V;
 339
 340        audpp_send_queue2(&cmd, sizeof(cmd));
 341}
 342
 343static void audpp_cmd_cfg_routing_mode(struct audio *audio)
 344{
 345        struct audpp_cmd_routing_mode cmd;
 346        dprintk("audpp_cmd_cfg_routing_mode()\n");
 347        memset(&cmd, 0, sizeof(cmd));
 348        cmd.cmd_id = AUDPP_CMD_ROUTING_MODE;
 349        cmd.object_number = audio->dec_id;
 350        if (audio->pcm_feedback)
 351                cmd.routing_mode = ROUTING_MODE_FTRT;
 352        else
 353                cmd.routing_mode = ROUTING_MODE_RT;
 354        audpp_send_queue1(&cmd, sizeof(cmd));
 355}
 356
 357static int audplay_dsp_send_data_avail(struct audio *audio,
 358                                       unsigned idx, unsigned len)
 359{
 360        audplay_cmd_bitstream_data_avail cmd;
 361
 362        cmd.cmd_id = AUDPLAY_CMD_BITSTREAM_DATA_AVAIL;
 363        cmd.decoder_id = audio->dec_id;
 364        cmd.buf_ptr = audio->out[idx].addr;
 365        cmd.buf_size = len / 2;
 366        cmd.partition_number = 0;
 367        return audplay_send_queue0(audio, &cmd, sizeof(cmd));
 368}
 369
 370static void audqcelp_buffer_refresh(struct audio *audio)
 371{
 372        struct audplay_cmd_buffer_refresh refresh_cmd;
 373
 374        refresh_cmd.cmd_id = AUDPLAY_CMD_BUFFER_REFRESH;
 375        refresh_cmd.num_buffers = 1;
 376        refresh_cmd.buf0_address = audio->in[audio->fill_next].addr;
 377        refresh_cmd.buf0_length = audio->in[audio->fill_next].size;
 378        refresh_cmd.buf_read_count = 0;
 379        dprintk("audplay_buffer_fresh: buf0_addr=%x buf0_len=%d\n",
 380                refresh_cmd.buf0_address, refresh_cmd.buf0_length);
 381
 382        (void)audplay_send_queue0(audio, &refresh_cmd, sizeof(refresh_cmd));
 383}
 384
 385static void audqcelp_config_hostpcm(struct audio *audio)
 386{
 387        struct audplay_cmd_hpcm_buf_cfg cfg_cmd;
 388
 389        dprintk("audqcelp_config_hostpcm()\n");
 390        cfg_cmd.cmd_id = AUDPLAY_CMD_HPCM_BUF_CFG;
 391        cfg_cmd.max_buffers = audio->pcm_buf_count;
 392        cfg_cmd.byte_swap = 0;
 393        cfg_cmd.hostpcm_config = (0x8000) | (0x4000);
 394        cfg_cmd.feedback_frequency = 1;
 395        cfg_cmd.partition_number = 0;
 396
 397        (void)audplay_send_queue0(audio, &cfg_cmd, sizeof(cfg_cmd));
 398}
 399
 400static void audqcelp_send_data(struct audio *audio, unsigned needed)
 401{
 402        struct buffer *frame;
 403        unsigned long flags;
 404
 405        spin_lock_irqsave(&audio->dsp_lock, flags);
 406        if (!audio->running)
 407                goto done;
 408
 409        if (needed) {
 410                /* We were called from the callback because the DSP
 411                 * requested more data.  Note that the DSP does want
 412                 * more data, and if a buffer was in-flight, mark it
 413                 * as available (since the DSP must now be done with
 414                 * it).
 415                 */
 416                audio->out_needed = 1;
 417                frame = audio->out + audio->out_tail;
 418                if (frame->used == 0xffffffff) {
 419                        dprintk("frame %d free\n", audio->out_tail);
 420                        frame->used = 0;
 421                        audio->out_tail ^= 1;
 422                        wake_up(&audio->write_wait);
 423                }
 424        }
 425
 426        if (audio->out_needed) {
 427                /* If the DSP currently wants data and we have a
 428                 * buffer available, we will send it and reset
 429                 * the needed flag.  We'll mark the buffer as in-flight
 430                 * so that it won't be recycled until the next buffer
 431                 * is requested
 432                 */
 433
 434                frame = audio->out + audio->out_tail;
 435                if (frame->used) {
 436                        BUG_ON(frame->used == 0xffffffff);
 437                        dprintk("frame %d busy\n", audio->out_tail);
 438                        audplay_dsp_send_data_avail(audio, audio->out_tail,
 439                                                    frame->used);
 440                        frame->used = 0xffffffff;
 441                        audio->out_needed = 0;
 442                }
 443        }
 444 done:
 445        spin_unlock_irqrestore(&audio->dsp_lock, flags);
 446}
 447
 448/* ------------------- device --------------------- */
 449
 450static void audqcelp_flush(struct audio *audio)
 451{
 452        audio->out[0].used = 0;
 453        audio->out[1].used = 0;
 454        audio->out_head = 0;
 455        audio->out_tail = 0;
 456        audio->stopped = 0;
 457}
 458
 459static void audqcelp_flush_pcm_buf(struct audio *audio)
 460{
 461        uint8_t index;
 462
 463        for (index = 0; index < PCM_BUF_MAX_COUNT; index++)
 464                audio->in[index].used = 0;
 465
 466        audio->read_next = 0;
 467        audio->fill_next = 0;
 468}
 469
 470static long audqcelp_ioctl(struct file *file, unsigned int cmd,
 471                unsigned long arg)
 472{
 473        struct audio *audio = file->private_data;
 474        int rc = 0;
 475
 476        dprintk("audqcelp_ioctl() cmd = %d\n", cmd);
 477
 478        if (cmd == AUDIO_GET_STATS) {
 479                struct msm_audio_stats stats;
 480                stats.byte_count = audpp_avsync_byte_count(audio->dec_id);
 481                stats.sample_count = audpp_avsync_sample_count(audio->dec_id);
 482                if (copy_to_user((void *)arg, &stats, sizeof(stats)))
 483                        return -EFAULT;
 484                return 0;
 485        }
 486        if (cmd == AUDIO_SET_VOLUME) {
 487                unsigned long flags;
 488                spin_lock_irqsave(&audio->dsp_lock, flags);
 489                audio->volume = arg;
 490                if (audio->running)
 491                        audpp_set_volume_and_pan(audio->dec_id, arg, 0);
 492                spin_unlock_irqrestore(&audio->dsp_lock, flags);
 493                return 0;
 494        }
 495        mutex_lock(&audio->lock);
 496        switch (cmd) {
 497        case AUDIO_START:
 498                rc = audqcelp_enable(audio);
 499                break;
 500        case AUDIO_STOP:
 501                rc = audqcelp_disable(audio);
 502                audio->stopped = 1;
 503                break;
 504        case AUDIO_FLUSH:
 505                if (audio->stopped) {
 506                        /* Make sure we're stopped and we wake any threads
 507                         * that might be blocked holding the write_lock.
 508                         * While audio->stopped write threads will always
 509                         * exit immediately.
 510                         */
 511                        wake_up(&audio->write_wait);
 512                        mutex_lock(&audio->write_lock);
 513                        audqcelp_flush(audio);
 514                        mutex_unlock(&audio->write_lock);
 515                        wake_up(&audio->read_wait);
 516                        mutex_lock(&audio->read_lock);
 517                        audqcelp_flush_pcm_buf(audio);
 518                        mutex_unlock(&audio->read_lock);
 519                        break;
 520                }
 521                break;
 522        case AUDIO_SET_CONFIG:
 523                dprintk("AUDIO_SET_CONFIG not applicable \n");
 524                break;
 525        case AUDIO_GET_CONFIG:{
 526                        struct msm_audio_config config;
 527                        config.buffer_size = BUFSZ;
 528                        config.buffer_count = BUF_COUNT;
 529                        config.sample_rate = 8000;
 530                        config.channel_count = 1;
 531                        config.unused[0] = 0;
 532                        config.unused[1] = 0;
 533                        config.unused[2] = 0;
 534                        config.unused[3] = 0;
 535                        if (copy_to_user((void *)arg, &config,
 536                                         sizeof(config)))
 537                                rc = -EFAULT;
 538                        else
 539                                rc = 0;
 540
 541                        break;
 542                }
 543        case AUDIO_GET_PCM_CONFIG:{
 544                        struct msm_audio_pcm_config config;
 545
 546                        config.pcm_feedback = 0;
 547                        config.buffer_count = PCM_BUF_MAX_COUNT;
 548                        config.buffer_size = PCM_BUFSZ_MIN;
 549                        if (copy_to_user((void *)arg, &config,
 550                                sizeof(config)))
 551                                rc = -EFAULT;
 552                        else
 553                                rc = 0;
 554                        break;
 555                }
 556        case AUDIO_SET_PCM_CONFIG:{
 557                        struct msm_audio_pcm_config config;
 558
 559                        if (copy_from_user(&config, (void *)arg,
 560                                sizeof(config))) {
 561                                rc = -EFAULT;
 562                                break;
 563                        }
 564                        if ((config.buffer_count > PCM_BUF_MAX_COUNT) ||
 565                                (config.buffer_count == 1))
 566                                config.buffer_count = PCM_BUF_MAX_COUNT;
 567
 568                        if (config.buffer_size < PCM_BUFSZ_MIN)
 569                                config.buffer_size = PCM_BUFSZ_MIN;
 570
 571                        /* Check if pcm feedback is required */
 572                        if ((config.pcm_feedback) && (!audio->read_data)) {
 573                                dprintk(
 574                                "audqcelp_ioctl: allocate PCM buf %d\n",
 575                                config.buffer_count * config.buffer_size);
 576                                audio->read_data = dma_alloc_coherent(NULL,
 577                                config.buffer_size * config.buffer_count,
 578                                &audio->read_phys, GFP_KERNEL);
 579                                if (!audio->read_data) {
 580                                        pr_err(
 581                                        "audqcelp_ioctl: no mem for pcm buf\n"
 582                                        );
 583                                        rc = -ENOMEM;
 584                                } else {
 585                                        uint8_t index;
 586                                        uint32_t offset = 0;
 587
 588                                        audio->pcm_feedback = 1;
 589                                        audio->buf_refresh = 0;
 590                                        audio->pcm_buf_count =
 591                                                config.buffer_count;
 592                                        audio->read_next = 0;
 593                                        audio->fill_next = 0;
 594
 595                                        for (index = 0;
 596                                        index < config.buffer_count; index++) {
 597                                                audio->in[index].data =
 598                                                audio->read_data + offset;
 599                                                audio->in[index].addr =
 600                                                audio->read_phys + offset;
 601                                                audio->in[index].size =
 602                                                config.buffer_size;
 603                                                audio->in[index].used = 0;
 604                                                offset += config.buffer_size;
 605                                        }
 606                                        rc = 0;
 607                                }
 608                        } else {
 609                                rc = 0;
 610                        }
 611                        break;
 612                }
 613        case AUDIO_PAUSE:
 614                dprintk("%s: AUDIO_PAUSE %ld\n", __func__, arg);
 615                rc = audpp_pause(audio->dec_id, (int) arg);
 616                break;
 617        default:
 618                rc = -EINVAL;
 619        }
 620        mutex_unlock(&audio->lock);
 621        return rc;
 622}
 623
 624static ssize_t audqcelp_read(struct file *file, char __user *buf, size_t count,
 625                        loff_t *pos)
 626{
 627        struct audio *audio = file->private_data;
 628        const char __user *start = buf;
 629        int rc = 0;
 630
 631        if (!audio->pcm_feedback)
 632                return 0; /* PCM feedback is not enabled. Nothing to read */
 633
 634        mutex_lock(&audio->read_lock);
 635        dprintk("audqcelp_read() %d \n", count);
 636        while (count > 0) {
 637                rc = wait_event_interruptible(audio->read_wait,
 638                                (audio->in[audio->read_next].used > 0) ||
 639                                (audio->stopped));
 640                if (rc < 0)
 641                        break;
 642
 643                if (audio->stopped) {
 644                        rc = -EBUSY;
 645                        break;
 646                }
 647
 648                if (count < audio->in[audio->read_next].used) {
 649                        /* Read must happen in frame boundary. Since driver does
 650                        not know frame size, read count must be greater or equal
 651                        to size of PCM samples */
 652                        dprintk("audqcelp_read:read stop - partial frame\n");
 653                        break;
 654                } else {
 655                        dprintk("audqcelp_read: read from in[%d]\n",
 656                                audio->read_next);
 657                        if (copy_to_user(buf,
 658                                audio->in[audio->read_next].data,
 659                                audio->in[audio->read_next].used)) {
 660                                pr_err("audqcelp_read: invalid addr %x \n",
 661                                        (unsigned int)buf);
 662                                rc = -EFAULT;
 663                                break;
 664                        }
 665                        count -= audio->in[audio->read_next].used;
 666                        buf += audio->in[audio->read_next].used;
 667                        audio->in[audio->read_next].used = 0;
 668                        if ((++audio->read_next) == audio->pcm_buf_count)
 669                                audio->read_next = 0;
 670                }
 671        }
 672
 673        if (audio->buf_refresh) {
 674                audio->buf_refresh = 0;
 675                dprintk("audqcelp_read: kick start pcm feedback again\n");
 676                audqcelp_buffer_refresh(audio);
 677        }
 678
 679        mutex_unlock(&audio->read_lock);
 680
 681        if (buf > start)
 682                rc = buf - start;
 683
 684        dprintk("audqcelp_read: read %d bytes\n", rc);
 685        return rc;
 686}
 687
 688static ssize_t audqcelp_write(struct file *file, const char __user *buf,
 689                           size_t count, loff_t *pos)
 690{
 691        struct audio *audio = file->private_data;
 692        const char __user *start = buf;
 693        struct buffer *frame;
 694        size_t xfer;
 695        int rc = 0;
 696
 697        if (count & 1)
 698                return -EINVAL;
 699        dprintk("audqcelp_write() \n");
 700        mutex_lock(&audio->write_lock);
 701        while (count > 0) {
 702                frame = audio->out + audio->out_head;
 703                rc = wait_event_interruptible(audio->write_wait,
 704                                              (frame->used == 0)
 705                                              || (audio->stopped));
 706                dprintk("audqcelp_write() buffer available\n");
 707                if (rc < 0)
 708                        break;
 709                if (audio->stopped) {
 710                        rc = -EBUSY;
 711                        break;
 712                }
 713                xfer = (count > frame->size) ? frame->size : count;
 714                if (copy_from_user(frame->data, buf, xfer)) {
 715                        rc = -EFAULT;
 716                        break;
 717                }
 718
 719                frame->used = xfer;
 720                audio->out_head ^= 1;
 721                count -= xfer;
 722                buf += xfer;
 723
 724                audqcelp_send_data(audio, 0);
 725
 726        }
 727        mutex_unlock(&audio->write_lock);
 728        if (buf > start)
 729                return buf - start;
 730        return rc;
 731}
 732
 733static int audqcelp_release(struct inode *inode, struct file *file)
 734{
 735        struct audio *audio = file->private_data;
 736
 737        dprintk("audqcelp_release()\n");
 738
 739        mutex_lock(&audio->lock);
 740        audqcelp_disable(audio);
 741        audqcelp_flush(audio);
 742        audqcelp_flush_pcm_buf(audio);
 743        msm_adsp_put(audio->audplay);
 744        audio->audplay = NULL;
 745        audio->opened = 0;
 746        if (audio->data)
 747                dma_free_coherent(NULL, DMASZ, audio->data, audio->phys);
 748        audio->data = NULL;
 749        if (audio->read_data) {
 750                dma_free_coherent(NULL,
 751                                 audio->in[0].size * audio->pcm_buf_count,
 752                                 audio->read_data, audio->read_phys);
 753                audio->read_data = NULL;
 754        }
 755        audio->pcm_feedback = 0;
 756        mutex_unlock(&audio->lock);
 757        return 0;
 758}
 759
 760static int audqcelp_open(struct inode *inode, struct file *file)
 761{
 762        struct audio *audio = &the_qcelp_audio;
 763        int rc;
 764
 765        mutex_lock(&audio->lock);
 766
 767        if (audio->opened) {
 768                pr_err("audio: busy\n");
 769                rc = -EBUSY;
 770                goto done;
 771        }
 772
 773        audio->data = dma_alloc_coherent(NULL, DMASZ,
 774                                         &audio->phys, GFP_KERNEL);
 775        if (!audio->data) {
 776                pr_err("audio: could not allocate DMA buffers\n");
 777                rc = -ENOMEM;
 778                goto done;
 779        }
 780
 781        rc = audmgr_open(&audio->audmgr);
 782        if (rc)
 783                goto err;
 784
 785        rc = msm_adsp_get("AUDPLAY0TASK", &audio->audplay,
 786                &audplay_adsp_ops_qcelp, audio);
 787        if (rc) {
 788                pr_err("audio: failed to get audplay0 dsp module\n");
 789                audmgr_close(&audio->audmgr);
 790                goto err;
 791        }
 792
 793        audio->dec_id = 0;
 794
 795        audio->out[0].data = audio->data + 0;
 796        audio->out[0].addr = audio->phys + 0;
 797        audio->out[0].size = BUFSZ;
 798
 799        audio->out[1].data = audio->data + BUFSZ;
 800        audio->out[1].addr = audio->phys + BUFSZ;
 801        audio->out[1].size = BUFSZ;
 802
 803        audio->volume = 0x2000; /* Q13 1.0 */
 804
 805        audqcelp_flush(audio);
 806
 807        file->private_data = audio;
 808        audio->opened = 1;
 809        rc = 0;
 810done:
 811        mutex_unlock(&audio->lock);
 812        return rc;
 813err:
 814        dma_free_coherent(NULL, DMASZ, audio->data, audio->phys);
 815        mutex_unlock(&audio->lock);
 816        return rc;
 817}
 818
 819static struct file_operations audio_qcelp_fops = {
 820        .owner = THIS_MODULE,
 821        .open = audqcelp_open,
 822        .release = audqcelp_release,
 823        .read = audqcelp_read,
 824        .write = audqcelp_write,
 825        .unlocked_ioctl = audqcelp_ioctl,
 826};
 827
 828struct miscdevice audio_qcelp_misc = {
 829        .minor = MISC_DYNAMIC_MINOR,
 830        .name = "msm_qcelp",
 831        .fops = &audio_qcelp_fops,
 832};
 833
 834static int __init audqcelp_init(void)
 835{
 836        mutex_init(&the_qcelp_audio.lock);
 837        mutex_init(&the_qcelp_audio.write_lock);
 838        mutex_init(&the_qcelp_audio.read_lock);
 839        spin_lock_init(&the_qcelp_audio.dsp_lock);
 840        init_waitqueue_head(&the_qcelp_audio.write_wait);
 841        init_waitqueue_head(&the_qcelp_audio.read_wait);
 842        the_qcelp_audio.read_data = NULL;
 843        return misc_register(&audio_qcelp_misc);
 844}
 845
 846static void __exit audqcelp_exit(void)
 847{
 848        misc_deregister(&audio_qcelp_misc);
 849}
 850
 851module_init(audqcelp_init);
 852module_exit(audqcelp_exit);
 853
 854MODULE_DESCRIPTION("MSM QCELP 13K driver");
 855MODULE_LICENSE("GPL v2");
 856MODULE_AUTHOR("QUALCOMM");
 857