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